breeze-client 2.2.2 → 3.0.0

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 (299) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +83 -63
  3. package/adapters/abstract-data-service-adapter.d.ts +120 -0
  4. package/adapters/abstract-data-service-adapter.js +395 -0
  5. package/adapters/abstract-data-service-adapter.js.map +1 -0
  6. package/adapters/adapter-ajax-fetch.d.ts +12 -0
  7. package/adapters/adapter-ajax-fetch.js +13 -0
  8. package/adapters/adapter-ajax-fetch.js.map +1 -0
  9. package/{adapter-ajax-post → adapters}/adapter-ajax-post.d.ts +40 -36
  10. package/{fesm2022/breeze-client-adapter-ajax-post.mjs → adapters/adapter-ajax-post.js} +80 -82
  11. package/adapters/adapter-ajax-post.js.map +1 -0
  12. package/{adapter-ajax-fetch → adapters}/adapter-core.d.ts +4 -4
  13. package/{fesm2022/breeze-client-adapter-uri-builder-json.mjs → adapters/adapter-core.js} +48 -91
  14. package/adapters/adapter-core.js.map +1 -0
  15. package/adapters/adapter-data-service-webapi.d.ts +9 -0
  16. package/{fesm2022/breeze-client-adapter-data-service-webapi.mjs → adapters/adapter-data-service-webapi.js} +105 -107
  17. package/adapters/adapter-data-service-webapi.js.map +1 -0
  18. package/adapters/adapter-model-library-backing-store.d.ts +32 -0
  19. package/adapters/adapter-model-library-backing-store.js +321 -0
  20. package/adapters/adapter-model-library-backing-store.js.map +1 -0
  21. package/adapters/adapter-uri-builder-json.d.ts +11 -0
  22. package/adapters/adapter-uri-builder-json.js +40 -0
  23. package/adapters/adapter-uri-builder-json.js.map +1 -0
  24. package/adapters/http.d.ts +52 -0
  25. package/adapters/http.js +202 -0
  26. package/adapters/http.js.map +1 -0
  27. package/angular/adapter-angular-httpclient.d.ts +21 -0
  28. package/angular/adapter-angular-httpclient.js +70 -0
  29. package/angular/adapter-angular-httpclient.js.map +1 -0
  30. package/breeze.d.ts +215 -0
  31. package/breeze.js +141 -0
  32. package/breeze.js.map +1 -0
  33. package/config/config.d.ts +212 -0
  34. package/config/config.js +392 -0
  35. package/config/config.js.map +1 -0
  36. package/config/configure.d.ts +66 -0
  37. package/config/configure.js +46 -0
  38. package/config/configure.js.map +1 -0
  39. package/config/default-adapters.d.ts +1 -0
  40. package/config/default-adapters.js +40 -0
  41. package/config/default-adapters.js.map +1 -0
  42. package/config/interface-registry.d.ts +191 -0
  43. package/config/interface-registry.js +5 -0
  44. package/config/interface-registry.js.map +1 -0
  45. package/{src → core}/assert-param.d.ts +52 -60
  46. package/core/assert-param.js +390 -0
  47. package/core/assert-param.js.map +1 -0
  48. package/core/core.d.ts +285 -0
  49. package/core/core.js +772 -0
  50. package/core/core.js.map +1 -0
  51. package/core/enum.d.ts +116 -0
  52. package/core/enum.js +167 -0
  53. package/core/enum.js.map +1 -0
  54. package/core/event.d.ts +169 -0
  55. package/core/event.js +338 -0
  56. package/core/event.js.map +1 -0
  57. package/entity/array.d.ts +3 -0
  58. package/entity/array.js +4 -0
  59. package/entity/array.js.map +1 -0
  60. package/entity/complex-array.d.ts +17 -0
  61. package/entity/complex-array.js +104 -0
  62. package/entity/complex-array.js.map +1 -0
  63. package/entity/default-property-interceptor.d.ts +1 -0
  64. package/entity/default-property-interceptor.js +496 -0
  65. package/entity/default-property-interceptor.js.map +1 -0
  66. package/{src → entity}/entity-action.d.ts +36 -42
  67. package/entity/entity-action.js +45 -0
  68. package/entity/entity-action.js.map +1 -0
  69. package/entity/entity-aspect.d.ts +457 -0
  70. package/entity/entity-aspect.js +1262 -0
  71. package/entity/entity-aspect.js.map +1 -0
  72. package/entity/entity-base.d.ts +55 -0
  73. package/entity/entity-base.js +41 -0
  74. package/entity/entity-base.js.map +1 -0
  75. package/entity/entity-group.d.ts +1 -0
  76. package/entity/entity-group.js +224 -0
  77. package/entity/entity-group.js.map +1 -0
  78. package/entity/entity-key.d.ts +95 -0
  79. package/entity/entity-key.js +189 -0
  80. package/entity/entity-key.js.map +1 -0
  81. package/{src → entity}/entity-state.d.ts +112 -84
  82. package/entity/entity-state.js +135 -0
  83. package/entity/entity-state.js.map +1 -0
  84. package/entity/key-generator.d.ts +57 -0
  85. package/entity/key-generator.js +155 -0
  86. package/entity/key-generator.js.map +1 -0
  87. package/entity/observable-array.d.ts +25 -0
  88. package/entity/observable-array.js +230 -0
  89. package/entity/observable-array.js.map +1 -0
  90. package/entity/primitive-array.d.ts +12 -0
  91. package/entity/primitive-array.js +71 -0
  92. package/entity/primitive-array.js.map +1 -0
  93. package/entity/relation-array.d.ts +24 -0
  94. package/entity/relation-array.js +176 -0
  95. package/entity/relation-array.js.map +1 -0
  96. package/entity/unattached-children-map.d.ts +1 -0
  97. package/entity/unattached-children-map.js +105 -0
  98. package/entity/unattached-children-map.js.map +1 -0
  99. package/generate-entity-classes.js +1176 -0
  100. package/manager/entity-manager.d.ts +801 -0
  101. package/manager/entity-manager.js +2395 -0
  102. package/manager/entity-manager.js.map +1 -0
  103. package/{src → manager}/save-options.d.ts +48 -42
  104. package/manager/save-options.js +51 -0
  105. package/manager/save-options.js.map +1 -0
  106. package/{src → metadata}/data-service.d.ts +229 -184
  107. package/metadata/data-service.js +246 -0
  108. package/metadata/data-service.js.map +1 -0
  109. package/metadata/data-type.d.ts +122 -0
  110. package/metadata/data-type.js +465 -0
  111. package/metadata/data-type.js.map +1 -0
  112. package/metadata/entity-metadata.d.ts +1193 -0
  113. package/metadata/entity-metadata.js +2502 -0
  114. package/metadata/entity-metadata.js.map +1 -0
  115. package/{src → metadata}/local-query-comparison-options.d.ts +65 -59
  116. package/metadata/local-query-comparison-options.js +69 -0
  117. package/metadata/local-query-comparison-options.js.map +1 -0
  118. package/{src → metadata}/naming-convention.d.ts +75 -72
  119. package/metadata/naming-convention.js +97 -0
  120. package/metadata/naming-convention.js.map +1 -0
  121. package/mixins/mixin-get-entity-graph.d.ts +63 -0
  122. package/{fesm2022/breeze-client-mixin-get-entity-graph.mjs → mixins/mixin-get-entity-graph.js} +331 -253
  123. package/mixins/mixin-get-entity-graph.js.map +1 -0
  124. package/mixins/mixin-save-queuing.d.ts +98 -0
  125. package/{fesm2022/breeze-client-mixin-save-queuing.mjs → mixins/mixin-save-queuing.js} +493 -365
  126. package/mixins/mixin-save-queuing.js.map +1 -0
  127. package/package.json +63 -94
  128. package/query/entity-query.d.ts +521 -0
  129. package/query/entity-query.js +1149 -0
  130. package/query/entity-query.js.map +1 -0
  131. package/{src → query}/mapping-context.d.ts +44 -46
  132. package/query/mapping-context.js +412 -0
  133. package/query/mapping-context.js.map +1 -0
  134. package/query/predicate.d.ts +394 -0
  135. package/query/predicate.js +1294 -0
  136. package/query/predicate.js.map +1 -0
  137. package/query/property-path.d.ts +252 -0
  138. package/query/property-path.js +2 -0
  139. package/query/property-path.js.map +1 -0
  140. package/{src → query}/query-options.d.ts +143 -119
  141. package/query/query-options.js +180 -0
  142. package/query/query-options.js.map +1 -0
  143. package/rxjs/breeze-rxjs.d.ts +72 -0
  144. package/rxjs/breeze-rxjs.js +117 -0
  145. package/rxjs/breeze-rxjs.js.map +1 -0
  146. package/validation/validate.d.ts +583 -0
  147. package/validation/validate.js +961 -0
  148. package/validation/validate.js.map +1 -0
  149. package/{src → validation}/validation-options.d.ts +67 -63
  150. package/validation/validation-options.js +70 -0
  151. package/validation/validation-options.js.map +1 -0
  152. package/adapter-ajax-angularjs/adapter-ajax-angularjs.d.ts +0 -17
  153. package/adapter-ajax-angularjs/adapter-core.d.ts +0 -4
  154. package/adapter-ajax-angularjs/index.d.ts +0 -5
  155. package/adapter-ajax-fetch/adapter-ajax-fetch.d.ts +0 -18
  156. package/adapter-ajax-fetch/index.d.ts +0 -5
  157. package/adapter-ajax-httpclient/adapter-ajax-httpclient.d.ts +0 -13
  158. package/adapter-ajax-httpclient/adapter-core.d.ts +0 -4
  159. package/adapter-ajax-httpclient/index.d.ts +0 -5
  160. package/adapter-ajax-jquery/adapter-ajax-jquery.d.ts +0 -15
  161. package/adapter-ajax-jquery/index.d.ts +0 -5
  162. package/adapter-ajax-post/index.d.ts +0 -5
  163. package/adapter-data-service-odata/adapter-core.d.ts +0 -4
  164. package/adapter-data-service-odata/adapter-data-service-odata.d.ts +0 -17
  165. package/adapter-data-service-odata/index.d.ts +0 -5
  166. package/adapter-data-service-webapi/adapter-data-service-webapi.d.ts +0 -15
  167. package/adapter-data-service-webapi/index.d.ts +0 -5
  168. package/adapter-model-library-backing-store/adapter-model-library-backing-store.d.ts +0 -10
  169. package/adapter-model-library-backing-store/index.d.ts +0 -5
  170. package/adapter-model-library-ko/adapter-model-library-ko.d.ts +0 -10
  171. package/adapter-model-library-ko/index.d.ts +0 -5
  172. package/adapter-uri-builder-json/adapter-core.d.ts +0 -4
  173. package/adapter-uri-builder-json/adapter-uri-builder-json.d.ts +0 -8
  174. package/adapter-uri-builder-json/index.d.ts +0 -5
  175. package/adapter-uri-builder-odata/adapter-core.d.ts +0 -4
  176. package/adapter-uri-builder-odata/adapter-uri-builder-odata.d.ts +0 -8
  177. package/adapter-uri-builder-odata/index.d.ts +0 -5
  178. package/esm2022/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +0 -135
  179. package/esm2022/adapter-ajax-angularjs/adapter-core.mjs +0 -49
  180. package/esm2022/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +0 -5
  181. package/esm2022/adapter-ajax-fetch/adapter-ajax-fetch.mjs +0 -135
  182. package/esm2022/adapter-ajax-fetch/adapter-core.mjs +0 -49
  183. package/esm2022/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +0 -5
  184. package/esm2022/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +0 -139
  185. package/esm2022/adapter-ajax-httpclient/adapter-core.mjs +0 -49
  186. package/esm2022/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +0 -5
  187. package/esm2022/adapter-ajax-jquery/adapter-ajax-jquery.mjs +0 -107
  188. package/esm2022/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +0 -5
  189. package/esm2022/adapter-ajax-post/adapter-ajax-post.mjs +0 -77
  190. package/esm2022/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +0 -5
  191. package/esm2022/adapter-data-service-odata/adapter-core.mjs +0 -49
  192. package/esm2022/adapter-data-service-odata/adapter-data-service-odata.mjs +0 -461
  193. package/esm2022/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +0 -5
  194. package/esm2022/adapter-data-service-webapi/adapter-data-service-webapi.mjs +0 -100
  195. package/esm2022/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +0 -5
  196. package/esm2022/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +0 -269
  197. package/esm2022/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +0 -5
  198. package/esm2022/adapter-model-library-ko/adapter-model-library-ko.mjs +0 -241
  199. package/esm2022/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +0 -5
  200. package/esm2022/adapter-uri-builder-json/adapter-core.mjs +0 -49
  201. package/esm2022/adapter-uri-builder-json/adapter-uri-builder-json.mjs +0 -37
  202. package/esm2022/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +0 -5
  203. package/esm2022/adapter-uri-builder-odata/adapter-core.mjs +0 -49
  204. package/esm2022/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +0 -191
  205. package/esm2022/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +0 -5
  206. package/esm2022/breeze-client.mjs +0 -5
  207. package/esm2022/index.mjs +0 -2
  208. package/esm2022/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +0 -5
  209. package/esm2022/mixin-get-entity-graph/mixin-get-entity-graph.mjs +0 -269
  210. package/esm2022/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +0 -5
  211. package/esm2022/mixin-save-queuing/mixin-save-queuing.mjs +0 -421
  212. package/esm2022/src/abstract-data-service-adapter.mjs +0 -325
  213. package/esm2022/src/array.mjs +0 -4
  214. package/esm2022/src/assert-param.mjs +0 -330
  215. package/esm2022/src/breeze.mjs +0 -85
  216. package/esm2022/src/complex-array.mjs +0 -117
  217. package/esm2022/src/config.mjs +0 -232
  218. package/esm2022/src/core.mjs +0 -712
  219. package/esm2022/src/csdl-metadata-parser.mjs +0 -385
  220. package/esm2022/src/data-service.mjs +0 -221
  221. package/esm2022/src/data-type.mjs +0 -510
  222. package/esm2022/src/default-property-interceptor.mjs +0 -460
  223. package/esm2022/src/entity-action.mjs +0 -45
  224. package/esm2022/src/entity-aspect.mjs +0 -897
  225. package/esm2022/src/entity-group.mjs +0 -192
  226. package/esm2022/src/entity-key.mjs +0 -125
  227. package/esm2022/src/entity-manager.mjs +0 -2163
  228. package/esm2022/src/entity-metadata.mjs +0 -2242
  229. package/esm2022/src/entity-query.mjs +0 -1024
  230. package/esm2022/src/entity-state.mjs +0 -107
  231. package/esm2022/src/enum.mjs +0 -143
  232. package/esm2022/src/event.mjs +0 -264
  233. package/esm2022/src/interface-registry.mjs +0 -39
  234. package/esm2022/src/key-generator.mjs +0 -110
  235. package/esm2022/src/local-query-comparison-options.mjs +0 -65
  236. package/esm2022/src/mapping-context.mjs +0 -411
  237. package/esm2022/src/naming-convention.mjs +0 -92
  238. package/esm2022/src/observable-array.mjs +0 -183
  239. package/esm2022/src/predicate.mjs +0 -1259
  240. package/esm2022/src/primitive-array.mjs +0 -85
  241. package/esm2022/src/query-options.mjs +0 -152
  242. package/esm2022/src/relation-array.mjs +0 -173
  243. package/esm2022/src/save-options.mjs +0 -41
  244. package/esm2022/src/unattached-children-map.mjs +0 -56
  245. package/esm2022/src/validate.mjs +0 -995
  246. package/esm2022/src/validation-options.mjs +0 -64
  247. package/fesm2022/breeze-client-adapter-ajax-angularjs.mjs +0 -190
  248. package/fesm2022/breeze-client-adapter-ajax-angularjs.mjs.map +0 -1
  249. package/fesm2022/breeze-client-adapter-ajax-fetch.mjs +0 -190
  250. package/fesm2022/breeze-client-adapter-ajax-fetch.mjs.map +0 -1
  251. package/fesm2022/breeze-client-adapter-ajax-httpclient.mjs +0 -194
  252. package/fesm2022/breeze-client-adapter-ajax-httpclient.mjs.map +0 -1
  253. package/fesm2022/breeze-client-adapter-ajax-jquery.mjs +0 -114
  254. package/fesm2022/breeze-client-adapter-ajax-jquery.mjs.map +0 -1
  255. package/fesm2022/breeze-client-adapter-ajax-post.mjs.map +0 -1
  256. package/fesm2022/breeze-client-adapter-data-service-odata.mjs +0 -516
  257. package/fesm2022/breeze-client-adapter-data-service-odata.mjs.map +0 -1
  258. package/fesm2022/breeze-client-adapter-data-service-webapi.mjs.map +0 -1
  259. package/fesm2022/breeze-client-adapter-model-library-backing-store.mjs +0 -276
  260. package/fesm2022/breeze-client-adapter-model-library-backing-store.mjs.map +0 -1
  261. package/fesm2022/breeze-client-adapter-model-library-ko.mjs +0 -248
  262. package/fesm2022/breeze-client-adapter-model-library-ko.mjs.map +0 -1
  263. package/fesm2022/breeze-client-adapter-uri-builder-json.mjs.map +0 -1
  264. package/fesm2022/breeze-client-adapter-uri-builder-odata.mjs +0 -246
  265. package/fesm2022/breeze-client-adapter-uri-builder-odata.mjs.map +0 -1
  266. package/fesm2022/breeze-client-mixin-get-entity-graph.mjs.map +0 -1
  267. package/fesm2022/breeze-client-mixin-save-queuing.mjs.map +0 -1
  268. package/fesm2022/breeze-client.mjs +0 -14144
  269. package/fesm2022/breeze-client.mjs.map +0 -1
  270. package/index.d.ts +0 -1
  271. package/mixin-get-entity-graph/index.d.ts +0 -5
  272. package/mixin-get-entity-graph/mixin-get-entity-graph.d.ts +0 -31
  273. package/mixin-save-queuing/index.d.ts +0 -5
  274. package/mixin-save-queuing/mixin-save-queuing.d.ts +0 -32
  275. package/src/abstract-data-service-adapter.d.ts +0 -84
  276. package/src/array.d.ts +0 -3
  277. package/src/breeze.d.ts +0 -139
  278. package/src/complex-array.d.ts +0 -13
  279. package/src/config.d.ts +0 -104
  280. package/src/core.d.ts +0 -164
  281. package/src/csdl-metadata-parser.d.ts +0 -7
  282. package/src/data-type.d.ts +0 -89
  283. package/src/default-property-interceptor.d.ts +0 -4
  284. package/src/entity-aspect.d.ts +0 -332
  285. package/src/entity-group.d.ts +0 -28
  286. package/src/entity-key.d.ts +0 -77
  287. package/src/entity-manager.d.ts +0 -680
  288. package/src/entity-metadata.d.ts +0 -988
  289. package/src/entity-query.d.ts +0 -444
  290. package/src/enum.d.ts +0 -100
  291. package/src/event.d.ts +0 -142
  292. package/src/interface-registry.d.ts +0 -150
  293. package/src/key-generator.d.ts +0 -12
  294. package/src/observable-array.d.ts +0 -52
  295. package/src/predicate.d.ts +0 -376
  296. package/src/primitive-array.d.ts +0 -7
  297. package/src/relation-array.d.ts +0 -18
  298. package/src/unattached-children-map.d.ts +0 -19
  299. package/src/validate.d.ts +0 -650
@@ -1,2163 +0,0 @@
1
- import { core } from './core';
2
- import { assertParam, assertConfig } from './assert-param';
3
- import { config } from './config';
4
- import { BreezeEvent } from './event';
5
- import { EntityAspect } from './entity-aspect';
6
- import { MetadataStore, EntityType, DataProperty, AutoGeneratedKeyType } from './entity-metadata';
7
- import { EntityKey } from './entity-key';
8
- import { EntityAction } from './entity-action';
9
- import { EntityState } from './entity-state';
10
- import { DataService } from './data-service';
11
- import { DataType } from './data-type';
12
- import { ValidationError } from './validate';
13
- import { ValidationOptions } from './validation-options';
14
- import { QueryOptions, MergeStrategy, FetchStrategy } from './query-options';
15
- import { SaveOptions } from './save-options';
16
- import { KeyGenerator } from './key-generator';
17
- import { EntityGroup } from './entity-group';
18
- import { MappingContext } from './mapping-context';
19
- import { EntityQuery } from './entity-query';
20
- import { UnattachedChildrenMap } from './unattached-children-map';
21
- /**
22
- Instances of the EntityManager contain and manage collections of entities, either retrieved from a backend datastore or created on the client.
23
- **/
24
- export class EntityManager {
25
- // events
26
- /**
27
- A [[BreezeEvent]] that fires whenever a change to any entity in this EntityManager occurs. __Read Only__
28
-
29
- @eventArgs -
30
- - entityAction - The [[EntityAction]] that occured.
31
- - entity - The entity that changed. If this is null, then all entities in the entityManager were affected.
32
- - args - Additional information about this event. This will differ based on the entityAction.
33
-
34
- > let em = new EntityManager( {serviceName: "breeze/NorthwindIBModel" });
35
- > em.entityChanged.subscribe(function(changeArgs) {
36
- > // This code will be executed any time any entity within the entityManager
37
- > // is added, modified, deleted or detached for any reason.
38
- > let action = changeArgs.entityAction;
39
- > let entity = changeArgs.entity;
40
- > // .. do something to this entity when it is changed.
41
- > });
42
- > });
43
- @event
44
- **/
45
- entityChanged;
46
- /**
47
- An [[BreezeEvent]] that fires whenever validationErrors change for any entity in this EntityManager. __Read Only__
48
- @eventArgs -
49
- - entity - The entity on which the validation errors have been added or removed.
50
- - added - An array containing any newly added [[ValidationError]]s
51
- - removed - An array containing any newly removed [[ValidationError]]s. This is those errors that have been 'fixed'
52
-
53
- > let em = new EntityManager( {serviceName: "breeze/NorthwindIBModel" });
54
- > em.validationErrorsChanged.subscribe(function(changeArgs) {
55
- > // This code will be executed any time any entity within the entityManager experiences a change to its validationErrors collection.
56
- > function (validationChangeArgs) {
57
- > let entity == validationChangeArgs.entity;
58
- > let errorsAdded = validationChangeArgs.added;
59
- > let errorsCleared = validationChangeArgs.removed;
60
- > // ... do something interesting with the order.
61
- > });
62
- > });
63
- > });
64
- @event
65
- **/
66
- validationErrorsChanged;
67
- /**
68
- A [[BreezeEvent]] that fires whenever an EntityManager transitions to or from having changes. __Read Only__
69
- @eventArgs -
70
- - entityManager - The EntityManager whose 'hasChanges' status has changed.
71
- - hasChanges - Whether or not this EntityManager has changes.
72
-
73
- > let em = new EntityManager( {serviceName: "breeze/NorthwindIBModel" });
74
- > em.hasChangesChanged.subscribe(function(args) {
75
- > let hasChangesChanged = args.hasChanges;
76
- > let entityManager = args.entityManager;
77
- > });
78
- > });
79
- @event
80
- **/
81
- hasChangesChanged;
82
- /** @hidden @internal */
83
- _pendingPubs; // TODO: refine later
84
- /** @hidden @internal */
85
- _hasChangesAction; // TODO refine later
86
- /** @hidden @internal */
87
- _hasChanges;
88
- /** @hidden @internal */
89
- _entityGroupMap;
90
- /** @hidden @internal */
91
- _unattachedChildrenMap;
92
- /** @hidden @internal */
93
- _inKeyFixup;
94
- helper = {
95
- unwrapInstance: unwrapInstance,
96
- unwrapOriginalValues: unwrapOriginalValues,
97
- unwrapChangedValues: unwrapChangedValues
98
- };
99
- /**
100
- EntityManager constructor.
101
-
102
- At its most basic an EntityManager can be constructed with just a service name
103
- > let entityManager = new EntityManager( "breeze/NorthwindIBModel");
104
-
105
- This is the same as calling it with the following configuration object
106
- > let entityManager = new EntityManager( {serviceName: "breeze/NorthwindIBModel" });
107
-
108
- Usually however, configuration objects will contain more than just the 'serviceName';
109
- > let metadataStore = new MetadataStore();
110
- > let entityManager = new EntityManager( {
111
- > serviceName: "breeze/NorthwindIBModel",
112
- > metadataStore: metadataStore
113
- > });
114
-
115
- or
116
- > return new QueryOptions({
117
- > mergeStrategy: obj,
118
- > fetchStrategy: this.fetchStrategy
119
- > });
120
- > let queryOptions = new QueryOptions({
121
- > mergeStrategy: MergeStrategy.OverwriteChanges,
122
- > fetchStrategy: FetchStrategy.FromServer
123
- > });
124
- > let validationOptions = new ValidationOptions({
125
- > validateOnAttach: true,
126
- > validateOnSave: true,
127
- > validateOnQuery: false
128
- > });
129
- > let entityManager = new EntityManager({
130
- > serviceName: "breeze/NorthwindIBModel",
131
- > queryOptions: queryOptions,
132
- > validationOptions: validationOptions
133
- > });
134
- @param emConfig - Configuration settings or a service name.
135
- **/
136
- constructor(emConfig) {
137
- if (arguments.length > 1) {
138
- throw new Error("The EntityManager ctor has a single optional argument that is either a 'serviceName' or a configuration object.");
139
- }
140
- let config;
141
- if (arguments.length === 0) {
142
- config = { serviceName: "" };
143
- }
144
- else if (typeof emConfig === 'string') {
145
- config = { serviceName: emConfig };
146
- }
147
- else {
148
- config = emConfig || {};
149
- }
150
- EntityManager._updateWithConfig(this, config, true);
151
- this.entityChanged = new BreezeEvent("entityChanged", this);
152
- this.validationErrorsChanged = new BreezeEvent("validationErrorsChanged", this);
153
- this.hasChangesChanged = new BreezeEvent("hasChangesChanged", this);
154
- this.clear();
155
- }
156
- /**
157
- General purpose property set method. Any of the properties in the [[EntityManagerConfig]]
158
- may be set.
159
- > // assume em1 is a previously created EntityManager
160
- > // where we want to change some of its settings.
161
- > em1.setProperties( {
162
- > serviceName: "breeze/foo"
163
- > });
164
- @param config - An object containing the selected properties and values to set.
165
- **/
166
- setProperties(config) {
167
- EntityManager._updateWithConfig(this, config, false);
168
- }
169
- /** @hidden @internal */
170
- static _updateWithConfig(em, config, isCtor) {
171
- let defaultQueryOptions = isCtor ? QueryOptions.defaultInstance : em.queryOptions;
172
- let defaultSaveOptions = isCtor ? SaveOptions.defaultInstance : em.saveOptions;
173
- let defaultValidationOptions = isCtor ? ValidationOptions.defaultInstance : em.validationOptions;
174
- let configParam = assertConfig(config)
175
- .whereParam("serviceName").isOptional().isString()
176
- .whereParam("dataService").isOptional().isInstanceOf(DataService)
177
- .whereParam("queryOptions").isInstanceOf(QueryOptions).isOptional().withDefault(defaultQueryOptions)
178
- .whereParam("saveOptions").isInstanceOf(SaveOptions).isOptional().withDefault(defaultSaveOptions)
179
- .whereParam("validationOptions").isInstanceOf(ValidationOptions).isOptional().withDefault(defaultValidationOptions)
180
- .whereParam("keyGeneratorCtor").isFunction().isOptional();
181
- if (isCtor) {
182
- configParam = configParam
183
- .whereParam("metadataStore").isInstanceOf(MetadataStore).isOptional().withDefault(new MetadataStore());
184
- }
185
- configParam.applyAll(em);
186
- // insure that entityManager's options versions are completely populated
187
- core.updateWithDefaults(em.queryOptions, defaultQueryOptions);
188
- core.updateWithDefaults(em.saveOptions, defaultSaveOptions);
189
- core.updateWithDefaults(em.validationOptions, defaultValidationOptions);
190
- if (config.serviceName) {
191
- em.dataService = new DataService({
192
- serviceName: em.serviceName
193
- });
194
- }
195
- em.serviceName = em.dataService && em.dataService.serviceName;
196
- em.keyGeneratorCtor = em.keyGeneratorCtor || KeyGenerator;
197
- if (isCtor || config.keyGeneratorCtor) {
198
- em.keyGenerator = new em.keyGeneratorCtor();
199
- }
200
- }
201
- /**
202
- Creates a new entity of a specified type and optionally initializes it. By default the new entity is created with an EntityState of Added
203
- but you can also optionally specify an EntityState. An EntityState of 'Detached' will insure that the entity is created but not yet added
204
- to the EntityManager.
205
- > // assume em1 is an EntityManager containing a number of preexisting entities.
206
- > // create and add an entity;
207
- > let emp1 = em1.createEntity("Employee");
208
- > // create and add an initialized entity;
209
- > let emp2 = em1.createEntity("Employee", { lastName: "Smith", firstName: "John" });
210
- > // create and attach (not add) an initialized entity
211
- > let emp3 = em1.createEntity("Employee", { id: 435, lastName: "Smith", firstName: "John" }, EntityState.Unchanged);
212
- > // create but don't attach an entity;
213
- > let emp4 = em1.createEntity("Employee", { id: 435, lastName: "Smith", firstName: "John" }, EntityState.Detached);
214
- @param typeName - The name of the EntityType for which an instance should be created.
215
- @param entityType - The EntityType of the type for which an instance should be created.
216
- @param initialValues - (default=null) Configuration object of the properties to set immediately after creation.
217
- @param entityState - (default = [[EntityState.Added]]) The EntityState of the entity after being created and added to this EntityManager.
218
- @param mergeStrategy - (default = [[MergeStrategy.Disallowed]]) - How to handle conflicts if an entity with the same key already exists within this EntityManager.
219
- @return {Entity} A new Entity of the specified type.
220
- */
221
- createEntity(entityType, initialValues, entityState, mergeStrategy) {
222
- assertParam(entityType, "entityType").isString().or().isInstanceOf(EntityType).check();
223
- assertParam(entityState, "entityState").isEnumOf(EntityState).isOptional().check();
224
- assertParam(mergeStrategy, "mergeStrategy").isEnumOf(MergeStrategy).isOptional().check();
225
- let et = (typeof entityType === "string") ? this.metadataStore._getStructuralType(entityType) : entityType;
226
- entityState = entityState || EntityState.Added;
227
- let entity = {};
228
- core.using(this, "isLoading", true, function () {
229
- entity = et.createEntity(initialValues);
230
- });
231
- if (entityState !== EntityState.Detached) {
232
- entity = this.attachEntity(entity, entityState, mergeStrategy);
233
- }
234
- return entity;
235
- }
236
- /**
237
- Creates a new EntityManager and imports a previously exported result into it.
238
- > // assume em1 is an EntityManager containing a number of preexisting entities.
239
- > let bundle = em1.exportEntities();
240
- > // can be stored via the web storage api
241
- > window.localStorage.setItem("myEntityManager", bundle);
242
- > // assume the code below occurs in a different session.
243
- > let bundleFromStorage = window.localStorage.getItem("myEntityManager");
244
- > // and imported
245
- > let em2 = EntityManager.importEntities(bundleFromStorage);
246
- > // em2 will now have a complete copy of what was in em1
247
- @param exportedString - The result of a previous 'exportEntities' call as a string
248
- @param exportedData - The result of a previous 'exportEntities' call as an Object.
249
- @param config - A configuration object.
250
- @param config.mergeStrategy - A [[MergeStrategy]] to use when
251
- merging into an existing EntityManager.
252
- @param config.metadataVersionFn - A function that takes two arguments (the current metadataVersion and the imported store's 'name')
253
- and may be used to perform version checking.
254
- @return A new EntityManager. Note that the return value of this method call is different from that
255
- provided by the same named method on an EntityManager instance. Use that method if you need additional information
256
- regarding the imported entities.
257
- **/
258
- static importEntities(exported, config) {
259
- let em = new EntityManager();
260
- em.importEntities(exported, config);
261
- return em;
262
- }
263
- // instance methods
264
- /**
265
- Calls [[EntityAspect.acceptChanges]] on every changed entity in this EntityManager.
266
- **/
267
- acceptChanges() {
268
- this.getChanges().map(function (entity) {
269
- return entity.entityAspect._checkOperation("acceptChanges");
270
- }).forEach(function (aspect) {
271
- aspect.acceptChanges();
272
- });
273
- }
274
- /**
275
- Exports selected entities, all entities of selected types, or an entire EntityManager cache.
276
-
277
- This method takes a snapshot of an EntityManager that can be stored offline or held in memory.
278
- Use the [[EntityManager.importEntities]] method to restore or merge the snapshot
279
- into another EntityManager at some later time.
280
- > // let em1 be an EntityManager containing a number of existing entities.
281
- > // export every entity in em1.
282
- > let bundle = em1.exportEntities();
283
- > // save to the browser's local storage
284
- > window.localStorage.setItem("myEntityManager", bundle);
285
- > // later retrieve the export
286
- > let bundleFromStorage = window.localStorage.getItem("myEntityManager");
287
- > // import the retrieved export bundle into another manager
288
- > let em2 = em1.createEmptyCopy();
289
- > em2.importEntities(bundleFromStorage);
290
- > // em2 now has a complete, faithful copy of the entities that were in em1
291
-
292
- You can also control exactly which entities are exported.
293
- > // get em1's unsaved changes (an array) and export them.
294
- > let changes = em1.getChanges();
295
- > let bundle = em1.exportEntities(changes);
296
- > // merge these entities into em2 which may contains some of the same entities.
297
- > // do NOT overwrite the entities in em2 if they themselves have unsaved changes.
298
- > em2.importEntities(bundle, { mergeStrategy: MergeStrategy.PreserveChanges} );
299
-
300
- Metadata are included in an export by default. You may want to exclude the metadata
301
- especially if you're exporting just a few entities for local storage.
302
- > let bundle = em1.exportEntities(arrayOfSelectedEntities, {includeMetadata: false});
303
- > window.localStorage.setItem("goodStuff", bundle);
304
-
305
- You may still express this option as a boolean value although this older syntax is deprecated.
306
- > // Exclude the metadata (deprecated syntax)
307
- > let bundle = em1.exportEntities(arrayOfSelectedEntities, false);
308
-
309
- You can export all entities of one or more specified EntityTypes.
310
- > // Export all Customer and Employee entities (and also exclude metadata)
311
- > let bundle = em1.exportEntities(['Customer', 'Employee'], {includeMetadata: false});
312
-
313
- All of the above examples return an export bundle as a string which is the default format.
314
- You can export the bundle as JSON if you prefer by setting the `asString` option to false.
315
- > // Export all Customer and Employee entities as JSON and exclude the metadata
316
- > let bundle = em1.exportEntities(['Customer', 'Employee'],
317
- > {asString: false, includeMetadata: false});
318
- > // store JSON bundle somewhere ... perhaps indexDb ... and later import as we do here.
319
- > em2.importEntities(bundle);
320
- @param entities - The entities to export or the EntityType(s) of the entities to export;
321
- all entities are exported if this parameter is omitted or null.
322
- @param exportConfig - Export configuration options or a boolean
323
- - asString - (boolean) - If true (default), return export bundle as a string.
324
- - includeMetadata - (boolean) - If true (default), include metadata in the export bundle.
325
- @return The export bundle either serialized as a string (default) or as a JSON object.
326
- The bundle contains the metadata (unless excluded) and the entity data grouped by type.
327
- The entity data include property values, change-state, and temporary key mappings (if any).
328
-
329
- The export bundle internals are deliberately undocumented. This Breeze-internal representation of entity data is
330
- suitable for export, storage, and import. The schema and contents of the bundle may change in future versions of Breeze.
331
- Manipulate it at your own risk with appropriate caution.
332
- **/
333
- exportEntities(entities, exportConfig) {
334
- assertParam(entities, "entities").isArray().isEntity()
335
- .or().isNonEmptyArray().isInstanceOf(EntityType)
336
- .or().isNonEmptyArray().isString()
337
- .or().isOptional().check();
338
- // assertParam(exportConfig, "exportConfig").isObject()
339
- // .or().isBoolean()
340
- // .or().isOptional().check();
341
- if (exportConfig == null) {
342
- exportConfig = { includeMetadata: true, asString: true };
343
- }
344
- else if (typeof exportConfig === 'boolean') { // deprecated
345
- exportConfig = { includeMetadata: exportConfig, asString: true };
346
- }
347
- assertConfig(exportConfig)
348
- .whereParam("asString").isBoolean().isOptional().withDefault(true)
349
- .whereParam("includeMetadata").isBoolean().isOptional().withDefault(true)
350
- .applyAll(exportConfig);
351
- let exportBundle = exportEntityGroups(this, entities);
352
- let json = core.extend({}, exportBundle, ["tempKeys", "entityGroupMap"]);
353
- if (exportConfig.includeMetadata) {
354
- json = core.extend(json, this, ["dataService", "saveOptions", "queryOptions", "validationOptions"]);
355
- json.metadataStore = this.metadataStore.exportMetadata();
356
- }
357
- else {
358
- json.metadataVersion = MetadataStore.metadataVersion;
359
- json.metadataStoreName = this.metadataStore.name;
360
- }
361
- let result = exportConfig.asString ? JSON.stringify(json, null, config.stringifyPad) : json;
362
- return result;
363
- }
364
- /**
365
- Imports a previously exported result into this EntityManager.
366
-
367
- This method can be used to make a complete copy of any previously created entityManager, even if created
368
- in a previous session and stored in localStorage. The static version of this method performs a
369
- very similar process.
370
- > // assume em1 is an EntityManager containing a number of existing entities.
371
- > let bundle = em1.exportEntities();
372
- > // bundle can be stored in window.localStorage or just held in memory.
373
- > let em2 = new EntityManager({
374
- > serviceName: em1.serviceName,
375
- > metadataStore: em1.metadataStore
376
- > });
377
- > em2.importEntities(bundle);
378
- > // em2 will now have a complete copy of what was in em1
379
-
380
- It can also be used to merge the contents of a previously created EntityManager with an
381
- existing EntityManager with control over how the two are merged.
382
- > let bundle = em1.exportEntities();
383
- > // assume em2 is another entityManager containing some of the same entities possibly with modifications.
384
- > em2.importEntities(bundle, { mergeStrategy: MergeStrategy.PreserveChanges} );
385
- > // em2 will now contain all of the entities from both em1 and em2. Any em2 entities with previously
386
- > // made modifications will not have been touched, but all other entities from em1 will have been imported.
387
- @param exportedString - The result of a previous 'export' call.
388
- @param importConfig - A configuration object.
389
- @param importConfig.mergeStrategy - A [[MergeStrategy]] to use when
390
- merging into an existing EntityManager.
391
- @param importConfig.metadataVersionFn - A function that takes two arguments (the current metadataVersion and the imported store's 'name')
392
- and may be used to perform version checking.
393
- @return result
394
- - result.entities {Array of Entities} The entities that were imported.
395
- - result.tempKeyMap {Object} Mapping from original EntityKey in the import bundle to its corresponding EntityKey in this EntityManager.
396
- **/
397
- importEntities(exported, importConfig) {
398
- importConfig = importConfig || {};
399
- assertConfig(importConfig)
400
- .whereParam("mergeStrategy").isEnumOf(MergeStrategy).isOptional().withDefault(this.queryOptions.mergeStrategy)
401
- .whereParam("metadataVersionFn").isFunction().isOptional()
402
- .whereParam("mergeAdds").isBoolean().isOptional()
403
- .applyAll(importConfig);
404
- let json = (typeof exported === "string") ? JSON.parse(exported) : exported;
405
- if (json.metadataStore) {
406
- this.metadataStore.importMetadata(json.metadataStore);
407
- // the || clause is for backwards compat with an earlier serialization format.
408
- this.dataService = (json.dataService && DataService.fromJSON(json.dataService)) || new DataService({ serviceName: json.serviceName });
409
- this.saveOptions = new SaveOptions(json.saveOptions);
410
- this.queryOptions = QueryOptions.fromJSON(json.queryOptions);
411
- this.validationOptions = new ValidationOptions(json.validationOptions);
412
- }
413
- else {
414
- importConfig.metadataVersionFn && importConfig.metadataVersionFn({
415
- metadataVersion: json.metadataVersion,
416
- metadataStoreName: json.metadataStoreName
417
- });
418
- }
419
- let tempKeyMap = {};
420
- json.tempKeys.forEach((k) => {
421
- let oldKey = EntityKey.fromJSON(k, this.metadataStore);
422
- // try to use oldKey if not already used in this keyGenerator.
423
- tempKeyMap[oldKey.toString()] = new EntityKey(oldKey.entityType, this.keyGenerator.generateTempKeyValue(oldKey.entityType, oldKey.values[0]));
424
- });
425
- let entitiesToLink = [];
426
- let impConfig = importConfig;
427
- impConfig.tempKeyMap = tempKeyMap;
428
- core.wrapExecution(() => {
429
- this._pendingPubs = [];
430
- }, (state) => {
431
- this._pendingPubs.forEach((fn) => fn());
432
- this._pendingPubs = undefined;
433
- this._hasChangesAction && this._hasChangesAction();
434
- }, () => {
435
- core.objectForEach(json.entityGroupMap, (entityTypeName, jsonGroup) => {
436
- let entityType = this.metadataStore._getStructuralType(entityTypeName, false);
437
- let targetEntityGroup = findOrCreateEntityGroup(this, entityType);
438
- let entities = importEntityGroup(targetEntityGroup, jsonGroup, impConfig);
439
- if (entities && entities.length) {
440
- entitiesToLink = entitiesToLink.concat(entities);
441
- }
442
- });
443
- entitiesToLink.forEach((entity) => {
444
- if (!entity.entityAspect.entityState.isDeleted()) {
445
- this._linkRelatedEntities(entity);
446
- }
447
- });
448
- });
449
- return {
450
- entities: entitiesToLink,
451
- tempKeyMapping: tempKeyMap
452
- };
453
- }
454
- /**
455
- Clears this EntityManager's cache but keeps all other settings. Note that this
456
- method is not as fast as creating a new EntityManager via 'new EntityManager'.
457
- This is because clear actually detaches all of the entities from the EntityManager.
458
- > // assume em1 is an EntityManager containing a number of existing entities.
459
- > em1.clear();
460
- > // em1 is will now contain no entities, but all other setting will be maintained.
461
- **/
462
- clear() {
463
- core.objectMap(this._entityGroupMap, function (key, entityGroup) {
464
- return entityGroup._checkOperation('clear');
465
- }).forEach((entityGroup) => {
466
- entityGroup._clear();
467
- });
468
- this._entityGroupMap = {};
469
- this._unattachedChildrenMap = new UnattachedChildrenMap();
470
- this.keyGenerator = new this.keyGeneratorCtor();
471
- this.entityChanged.publish({ entityAction: EntityAction.Clear });
472
- this._setHasChanges(false);
473
- }
474
- /**
475
- Creates an empty copy of this EntityManager but with the same DataService, MetadataStore, QueryOptions, SaveOptions, ValidationOptions, etc.
476
- > // assume em1 is an EntityManager containing a number of existing entities.
477
- > let em2 = em1.createEmptyCopy();
478
- > // em2 is a new EntityManager with all of em1's settings
479
- > // but no entities.
480
- @return A new EntityManager.
481
- **/
482
- createEmptyCopy() {
483
- let copy = new EntityManager(core.extend({}, this, ["dataService", "metadataStore", "queryOptions", "saveOptions", "validationOptions", "keyGeneratorCtor"]));
484
- return copy;
485
- }
486
- /**
487
- Attaches an entity to this EntityManager with an [[EntityState]] of 'Added'.
488
- > // assume em1 is an EntityManager containing a number of existing entities.
489
- > let custType = em1.metadataStore.getEntityType("Customer");
490
- > let cust1 = custType.createEntity();
491
- > em1.addEntity(cust1);
492
-
493
- Note that this is the same as using 'attachEntity' with an [[EntityState]] of 'Added'.
494
-
495
- > // assume em1 is an EntityManager containing a number of existing entities.
496
- > let custType = em1.metadataStore.getEntityType("Customer");
497
- > let cust1 = custType.createEntity();
498
- > em1.attachEntity(cust1, EntityState.Added);
499
- @param entity - The entity to add.
500
- @return The added entity.
501
- **/
502
- addEntity(entity) {
503
- return this.attachEntity(entity, EntityState.Added);
504
- }
505
- /**
506
- Attaches an entity to this EntityManager with a specified [[EntityState]].
507
- > // assume em1 is an EntityManager containing a number of existing entities.
508
- > let custType = em1.metadataStore.getEntityType("Customer");
509
- > let cust1 = custType.createEntity();
510
- > em1.attachEntity(cust1, EntityState.Added);
511
- @param entity - The entity to add.
512
- @param entityState - (default=EntityState.Unchanged) The EntityState of the newly attached entity. If omitted this defaults to EntityState.Unchanged.
513
- @param mergeStrategy - (default = MergeStrategy.Disallowed) How the specified entity should be merged into the EntityManager if this EntityManager already contains an entity with the same key.
514
- @return The attached entity.
515
- **/
516
- attachEntity(entity, entityState, mergeStrategy) {
517
- assertParam(entity, "entity").isRequired().check();
518
- this.metadataStore._checkEntityType(entity);
519
- let esSymbol = assertParam(entityState, "entityState").isEnumOf(EntityState).isOptional().check(EntityState.Unchanged);
520
- let msSymbol = assertParam(mergeStrategy, "mergeStrategy").isEnumOf(MergeStrategy).isOptional().check(MergeStrategy.Disallowed);
521
- if (entity.entityType.metadataStore !== this.metadataStore) {
522
- throw new Error("Cannot attach this entity because the EntityType (" + entity.entityType.name +
523
- ") and MetadataStore associated with this entity does not match this EntityManager's MetadataStore.");
524
- }
525
- let aspect = entity.entityAspect;
526
- if (aspect) {
527
- // to avoid reattaching an entity in progress
528
- if (aspect._inProcessEntity)
529
- return aspect._inProcessEntity;
530
- }
531
- else {
532
- // this occur's when attaching an entity created via new instead of via createEntity.
533
- aspect = new EntityAspect(entity);
534
- }
535
- let manager = aspect.entityManager;
536
- if (manager) {
537
- if (manager === this) {
538
- return entity;
539
- }
540
- else {
541
- throw new Error("This entity already belongs to another EntityManager");
542
- }
543
- }
544
- let attachedEntity = {};
545
- core.using(this, "isLoading", true, () => {
546
- if (esSymbol.isAdded()) {
547
- checkEntityKey(this, entity);
548
- }
549
- // attachedEntity === entity EXCEPT in the case of a merge.
550
- attachedEntity = this._attachEntityCore(entity, esSymbol, msSymbol);
551
- aspect._inProcessEntity = attachedEntity;
552
- try {
553
- // entity ( not attachedEntity) is deliberate here.
554
- attachRelatedEntities(this, entity, esSymbol, msSymbol);
555
- }
556
- finally {
557
- // insure that _inProcessEntity is cleared.
558
- aspect._inProcessEntity = undefined;
559
- }
560
- });
561
- if (this.validationOptions.validateOnAttach) {
562
- attachedEntity.entityAspect.validateEntity();
563
- }
564
- if (!esSymbol.isUnchanged()) {
565
- this._notifyStateChange(attachedEntity, true);
566
- }
567
- this.entityChanged.publish({ entityAction: EntityAction.Attach, entity: attachedEntity });
568
- return attachedEntity;
569
- }
570
- /**
571
- Detaches an entity from this EntityManager.
572
- > // assume em1 is an EntityManager containing a number of existing entities.
573
- > // assume cust1 is a customer Entity previously attached to em1
574
- > em1.detachEntity(cust1);
575
- > // em1 will now no longer contain cust1 and cust1 will have an
576
- > // entityAspect.entityState of EntityState.Detached
577
- @param entity - The entity to detach.
578
- @return Whether the entity could be detached. This will return false if the entity is already detached or was never attached.
579
- **/
580
- detachEntity(entity) {
581
- assertParam(entity, "entity").isEntity().check();
582
- let aspect = entity.entityAspect;
583
- if (!aspect) {
584
- // no aspect means in couldn't appear in any group
585
- return false;
586
- }
587
- if (aspect.entityManager !== this) {
588
- throw new Error("This entity does not belong to this EntityManager.");
589
- }
590
- return aspect.setDetached();
591
- }
592
- /**
593
- Fetches the metadata associated with the EntityManager's current 'serviceName'. This call
594
- occurs internally before the first query to any service if the metadata hasn't already been
595
- loaded. __Async__
596
-
597
- Usually you will not actually process the results of a fetchMetadata call directly, but will instead
598
- ask for the metadata from the EntityManager after the fetchMetadata call returns.
599
- > let em1 = new EntityManager( "breeze/NorthwindIBModel");
600
- > em1.fetchMetadata()
601
- > .then(function() {
602
- > let metadataStore = em1.metadataStore;
603
- > // do something with the metadata
604
- > }).catch(function(exception) {
605
- > // handle exception here
606
- > });
607
-
608
- @param callback - Function called on success.
609
- @param errorCallback - Function called on failure.
610
- @return {Promise}
611
- - schema {Object} The raw Schema object from metadata provider - Because this schema will differ depending on the metadata provider
612
- it is usually better to access metadata via the 'metadataStore' property of the EntityManager instead of using this 'raw' data.
613
- **/
614
- fetchMetadata(dataService, callback, errorCallback) {
615
- if (typeof (dataService) === "function") {
616
- // legacy support for when dataService was not an arg. i.e. first arg was callback
617
- errorCallback = callback;
618
- callback = dataService;
619
- dataService = undefined;
620
- }
621
- else {
622
- assertParam(dataService, "dataService").isInstanceOf(DataService).isOptional().check();
623
- assertParam(callback, "callback").isFunction().isOptional().check();
624
- assertParam(errorCallback, "errorCallback").isFunction().isOptional().check();
625
- }
626
- let promise = this.metadataStore.fetchMetadata(dataService || this.dataService);
627
- return promiseWithCallbacks(promise, callback, errorCallback);
628
- }
629
- /**
630
- Executes the specified query. __Async__
631
-
632
- > let em = new EntityManager(serviceName);
633
- > let query = new EntityQuery("Orders");
634
- > em.executeQuery(query).then( function(data) {
635
- > let orders = data.results;
636
- > ... query results processed here
637
- > }).catch( function(err) {
638
- > ... query failure processed here
639
- > });
640
-
641
- or with callbacks
642
- > let em = new EntityManager(serviceName);
643
- > let query = new EntityQuery("Orders");
644
- > em.executeQuery(query,
645
- > function(data) {
646
- > let orders = data.results;
647
- > ... query results processed here
648
- > },
649
- > function(err) {
650
- > ... query failure processed here
651
- > });
652
-
653
- Either way this method is the same as calling the The [[EntityQuery]] 'execute' method.
654
- > let em = new EntityManager(serviceName);
655
- > let query = new EntityQuery("Orders").using(em);
656
- > query.execute().then( function(data) {
657
- > let orders = data.results;
658
- > ... query results processed here
659
- > }).catch( function(err) {
660
- > ... query failure processed here
661
- > });
662
- @param query - The [[EntityQuery]] or OData query string to execute.
663
- @param callback - Function called on success.
664
- @param errorCallback - {Function} Function called on failure.
665
- @return Promise of
666
- - results - An array of entities
667
- - retrievedEntities - A array of all of the entities returned by the query. Differs from results (above) when .expand() is used.
668
- - query - The original [[EntityQuery]] or query string
669
- - entityManager - The EntityManager.
670
- - httpResponse - The [[IHttpResponse]] returned from the server.
671
- - inlineCount - Only available if 'inlineCount(true)' was applied to the query. Returns the count of
672
- items that would have been returned by the query before applying any skip or take operators, but after any filter/where predicates
673
- would have been applied.
674
- **/
675
- executeQuery(query, callback, errorCallback) {
676
- assertParam(query, "query").isInstanceOf(EntityQuery).or().isString().check();
677
- assertParam(callback, "callback").isFunction().isOptional().check();
678
- assertParam(errorCallback, "errorCallback").isFunction().isOptional().check();
679
- let promise;
680
- // 'resolve' methods create a new typed object with all of its properties fully resolved against a list of sources.
681
- // Thought about creating a 'normalized' query with these 'resolved' objects
682
- // but decided not to because the 'query' may not be an EntityQuery (it can be a string) and hence might not have a queryOptions or dataServices property on it.
683
- let queryOptions = QueryOptions.resolve([query.queryOptions, this.queryOptions, QueryOptions.defaultInstance]);
684
- let dataService = DataService.resolve([query.dataService, this.dataService]);
685
- if ((!dataService.hasServerMetadata) || this.metadataStore.hasMetadataFor(dataService.serviceName)) {
686
- promise = executeQueryCore(this, query, queryOptions, dataService);
687
- }
688
- else {
689
- promise = this.fetchMetadata(dataService).then(() => {
690
- return executeQueryCore(this, query, queryOptions, dataService);
691
- });
692
- }
693
- return promiseWithCallbacks(promise, callback, errorCallback);
694
- }
695
- /**
696
- Executes the specified query against this EntityManager's local cache.
697
-
698
- Because this method is executed immediately there is no need for a promise or a callback
699
- > let em = new EntityManager(serviceName);
700
- > let query = new EntityQuery("Orders");
701
- > let orders = em.executeQueryLocally(query);
702
-
703
- Note that this can also be accomplished using the 'executeQuery' method with
704
- a FetchStrategy of FromLocalCache and making use of the Promise or callback
705
- > let em = new EntityManager(serviceName);
706
- > let query = new EntityQuery("Orders").using(FetchStrategy.FromLocalCache);
707
- > em.executeQuery(query).then( function(data) {
708
- > let orders = data.results;
709
- > ... query results processed here
710
- > }).catch( function(err) {
711
- > ... query failure processed here
712
- > });
713
- @param query - The [[EntityQuery]] to execute.
714
- @return {Array of Entity} Array of entities from cache that satisfy the query
715
- **/
716
- executeQueryLocally(query) {
717
- return executeQueryLocallyCore(this, query).results;
718
- }
719
- /**
720
- Saves either a list of specified entities or all changed entities within this EntityManager. If there are no changes to any of the entities
721
- specified then there will be no server side call made but a valid 'empty' saveResult will still be returned. __Async__
722
-
723
- Often we will be saving all of the entities within an EntityManager that are either added, modified or deleted
724
- and we will let the 'saveChanges' call determine which entities these are.
725
- > // assume em1 is an EntityManager containing a number of preexisting entities.
726
- > // This could include added, modified and deleted entities.
727
- > em.saveChanges().then(function(saveResult) {
728
- > let savedEntities = saveResult.entities;
729
- > let keyMappings = saveResult.keyMappings;
730
- > }).catch(function (e) {
731
- > // e is any exception that was thrown.
732
- > });
733
-
734
- But we can also control exactly which entities to save and can specify specific SaveOptions
735
-
736
- > // assume entitiesToSave is an array of entities to save.
737
- > let saveOptions = new SaveOptions({ allowConcurrentSaves: true });
738
- > em.saveChanges(entitiesToSave, saveOptions).then(function(saveResult) {
739
- > let savedEntities = saveResult.entities;
740
- > let keyMappings = saveResult.keyMappings;
741
- > }).catch(function (e) {
742
- > // e is any exception that was thrown.
743
- > });
744
-
745
- Callback methods can also be used
746
- > em.saveChanges(entitiesToSave, null,
747
- > function(saveResult) {
748
- > let savedEntities = saveResult.entities;
749
- > let keyMappings = saveResult.keyMappings;
750
- > }, function (e) {
751
- > // e is any exception that was thrown.
752
- > }
753
- > );
754
-
755
- @param entities - The list of entities to save.
756
- Every entity in that list will be sent to the server, whether changed or unchanged,
757
- as long as it is attached to this EntityManager.
758
- If this parameter is omitted, null or empty (the usual case),
759
- every entity with pending changes in this EntityManager will be saved.
760
- @param saveOptions - [[SaveOptions]] for the save - will default to
761
- [[EntityManager.saveOptions]] if null.
762
- @param callback - Function called on success.
763
- @param errorCallback - Function called on failure.
764
- @return {Promise} Promise
765
- **/
766
- saveChanges(entities, saveOptions, callback, errorCallback) {
767
- assertParam(entities, "entities").isOptional().isArray().isEntity().check();
768
- assertParam(saveOptions, "saveOptions").isInstanceOf(SaveOptions).isOptional().check();
769
- assertParam(callback, "callback").isFunction().isOptional().check();
770
- assertParam(errorCallback, "errorCallback").isFunction().isOptional().check();
771
- saveOptions = saveOptions || this.saveOptions || SaveOptions.defaultInstance;
772
- let entitiesToSave = getEntitiesToSave(this, entities ? entities : undefined);
773
- if (entitiesToSave.length === 0) {
774
- let result = { entities: [], keyMappings: [] };
775
- if (callback)
776
- callback(result);
777
- return Promise.resolve(result);
778
- }
779
- if (!saveOptions.allowConcurrentSaves) {
780
- let anyPendingSaves = entitiesToSave.some(function (entity) {
781
- return entity.entityAspect.isBeingSaved;
782
- });
783
- if (anyPendingSaves) {
784
- let err = new Error("Concurrent saves not allowed - SaveOptions.allowConcurrentSaves is false");
785
- if (errorCallback)
786
- errorCallback(err);
787
- return Promise.reject(err);
788
- }
789
- }
790
- clearServerErrors(entitiesToSave);
791
- let valError = this.saveChangesValidateOnClient(entitiesToSave);
792
- if (valError) {
793
- if (errorCallback)
794
- errorCallback(valError);
795
- return Promise.reject(valError);
796
- }
797
- let dataService = DataService.resolve([saveOptions.dataService, this.dataService]);
798
- let saveContext = {
799
- entityManager: this,
800
- dataService: dataService,
801
- processSavedEntities: processSavedEntities,
802
- resourceName: saveOptions.resourceName || this.saveOptions.resourceName || "SaveChanges"
803
- };
804
- // TODO: need to check that if we are doing a partial save that all entities whose temp keys
805
- // are referenced are also in the partial save group
806
- let saveBundle = { entities: entitiesToSave, saveOptions: saveOptions };
807
- try { // Guard against exception thrown in dataservice adapter before it goes async
808
- updateConcurrencyProperties(entitiesToSave);
809
- return dataService.adapterInstance.saveChanges(saveContext, saveBundle)
810
- .then(saveSuccess).then((r) => r, saveFail);
811
- }
812
- catch (err) {
813
- // undo the marking by updateConcurrencyProperties
814
- markIsBeingSaved(entitiesToSave, false);
815
- if (errorCallback)
816
- errorCallback(err);
817
- return Promise.reject(err);
818
- }
819
- function saveSuccess(saveResult) {
820
- let em = saveContext.entityManager;
821
- markIsBeingSaved(entitiesToSave, false);
822
- let savedEntities = saveContext.processSavedEntities(saveResult);
823
- saveResult.entities = savedEntities;
824
- // update _hasChanges after save.
825
- em._setHasChanges();
826
- // can't do this anymore because other changes might have been made while saved entities in flight.
827
- // let hasChanges = (isFullSave && haveSameContents(entitiesToSave, savedEntities)) ? false : null;
828
- // em._setHasChanges(hasChanges);
829
- if (callback)
830
- callback(saveResult);
831
- return Promise.resolve(saveResult);
832
- }
833
- function processSavedEntities(saveResult) {
834
- let savedEntities = saveResult.entities;
835
- let deletedKeys = saveResult.deletedKeys || [];
836
- if (savedEntities.length === 0 && deletedKeys.length === 0) {
837
- return [];
838
- }
839
- let keyMappings = saveResult.keyMappings;
840
- let em = saveContext.entityManager;
841
- // must occur outside of isLoading block
842
- fixupKeys(em, keyMappings);
843
- core.using(em, "isLoading", true, () => {
844
- let mappingContext = new MappingContext({
845
- query: undefined,
846
- entityManager: em,
847
- mergeOptions: { mergeStrategy: MergeStrategy.OverwriteChanges },
848
- dataService: dataService
849
- });
850
- // The visitAndMerge operation has been optimized so that we do not actually perform a merge if the
851
- // the save operation did not actually return the entity - i.e. during OData and Mongo updates and deletes.
852
- savedEntities = mappingContext.visitAndMerge(savedEntities, { nodeType: "root" });
853
- });
854
- // detach any entities found in the em that appear in the deletedKeys list.
855
- deletedKeys.forEach(key => {
856
- let entityType = em.metadataStore._getStructuralType(key.entityTypeName);
857
- let ekey = new EntityKey(entityType, key.keyValues);
858
- let entity = em.getEntityByKey(ekey);
859
- if (entity) {
860
- entity.entityAspect.setDetached();
861
- }
862
- });
863
- return savedEntities;
864
- }
865
- function saveFail(serverError) {
866
- markIsBeingSaved(entitiesToSave, false);
867
- let clientError = processServerErrors(saveContext, serverError);
868
- if (errorCallback)
869
- errorCallback(clientError);
870
- return Promise.reject(clientError);
871
- }
872
- }
873
- /**
874
- Run the "saveChanges" pre-save client validation logic.
875
-
876
- This is NOT a general purpose validation method.
877
- It is intended for utilities that must know if saveChanges
878
- would reject the save due to client validation errors.
879
-
880
- It only validates entities if the EntityManager's
881
- [[ValidationOptions]].validateOnSave is true.
882
-
883
- @param entitiesToSave {Array of Entity} The list of entities to save (to validate).
884
- @return {Error} Validation error or null if no error
885
- **/
886
- saveChangesValidateOnClient(entitiesToSave) {
887
- if (this.validationOptions.validateOnSave) {
888
- let failedEntities = entitiesToSave.filter(function (entity) {
889
- let aspect = entity.entityAspect;
890
- let isValid = aspect.entityState.isDeleted() || aspect.validateEntity();
891
- return !isValid;
892
- });
893
- if (failedEntities.length > 0) {
894
- let valError = new Error("Client side validation errors encountered - see the entityErrors collection on this object for more detail");
895
- valError.entityErrors = createEntityErrors(failedEntities);
896
- return valError; // TODO: type this.
897
- }
898
- }
899
- return null;
900
- }
901
- /** @hidden @internal */
902
- _findEntityGroup(entityType) {
903
- return this._entityGroupMap[entityType.name];
904
- }
905
- /**
906
- Attempts to locate an entity within this EntityManager by its [EntityKey].
907
- @param entityKey - The [[EntityKey]] of the Entity to be located.
908
- @param type - The [[EntityType]] for this key.
909
- @param typeName - The EntityType name for this key.
910
- @param keyValues - The values for this key - will usually just be a single value; an array is only needed for multipart keys.
911
- @return An Entity or null;
912
- **/
913
- getEntityByKey(...args) {
914
- let entityKey = createEntityKey(this, args).entityKey;
915
- let entityTypes = entityKey._subtypes || [entityKey.entityType];
916
- let e;
917
- // hack use of some to simulate mapFirst logic.
918
- entityTypes.some((et) => {
919
- let group = this._findEntityGroup(et);
920
- // group version of findEntityByKey doesn't care about entityType
921
- e = group && group.findEntityByKey(entityKey);
922
- return e != null;
923
- });
924
- return e || null;
925
- }
926
- /**
927
- Attempts to fetch an entity from the server by its [[EntityKey]] with
928
- an option to check the local cache first. Note the this EntityManager's queryOptions.mergeStrategy
929
- will be used to merge any server side entity returned by this method.
930
- > // assume em1 is an EntityManager containing a number of preexisting entities.
931
- > let employeeType = em1.metadataStore.getEntityType("Employee");
932
- > let employeeKey = new EntityKey(employeeType, 1);
933
- > em1.fetchEntityByKey(employeeKey).then(function(result) {
934
- > let employee = result.entity;
935
- > let entityKey = result.entityKey;
936
- > let fromCache = result.fromCache;
937
- > });
938
- @param typeName - The EntityType name for this key.
939
- @param entityType - The EntityType for this key.
940
- @param keyValues - The values for this key - will usually just be a single value; an array is only needed for multipart keys.
941
- @param entityKey - The [[EntityKey]] of the Entity to be located.
942
- @param checkLocalCacheFirst - (default = false) - Whether to check this EntityManager first before going to the server. By default, the query will NOT do this.
943
- @return {Promise}
944
- - Properties on the promise success result
945
- - entity {Object} The entity returned or null
946
- - entityKey {EntityKey} The entityKey of the entity to fetch.
947
- - fromCache {Boolean} Whether this entity was fetched from the server or was found in the local cache.
948
- **/
949
- fetchEntityByKey(...args) {
950
- let dataService = DataService.resolve([this.dataService]);
951
- if ((!dataService.hasServerMetadata) || this.metadataStore.hasMetadataFor(dataService.serviceName)) {
952
- return fetchEntityByKeyCore(this, args);
953
- }
954
- else {
955
- return this.fetchMetadata(dataService).then(() => {
956
- return fetchEntityByKeyCore(this, args);
957
- });
958
- }
959
- }
960
- /**
961
- [Deprecated] - Attempts to locate an entity within this EntityManager by its [[EntityKey]].
962
- > // assume em1 is an EntityManager containing a number of preexisting entities.
963
- > let employeeType = em1.metadataStore.getEntityType("Employee");
964
- > let employeeKey = new EntityKey(employeeType, 1);
965
- > let employee = em1.findEntityByKey(employeeKey);
966
- > // employee will either be an entity or null.
967
- @deprecated Use getEntityByKey instead
968
- @param entityKey - The [[EntityKey]] of the Entity to be located.
969
- @return An Entity or null;
970
- **/
971
- findEntityByKey(entityKey) {
972
- return this.getEntityByKey(entityKey);
973
- }
974
- /**
975
- Generates a temporary key for the specified entity. This is used to insure that newly
976
- created entities have unique keys and to register that these keys are temporary and
977
- need to be automatically replaced with 'real' key values once these entities are saved.
978
-
979
- The [[EntityManager.keyGeneratorCtor]] property is used internally by this method to actually generate
980
- the keys - See the KeyGenerator interface interface description to see
981
- how a custom key generator can be plugged in.
982
- > // assume em1 is an EntityManager containing a number of preexisting entities.
983
- > let custType = em1.metadataStore.getEntityType("Customer");
984
- > let customer = custType.createEntity();
985
- > let customerId = em.generateTempKeyValue(customer);
986
- > // The 'customer' entity 'CustomerID' property is now set to a newly generated unique id value
987
- > // This property will change again after a successful save of the 'customer' entity.
988
- >
989
- > em1.saveChanges().then( function( data) {
990
- > let sameCust1 = data.results[0];
991
- > // cust1 === sameCust1;
992
- > // but cust1.getProperty("CustomerId") != customerId
993
- > // because the server will have generated a new id
994
- > // and the client will have been updated with this
995
- > // new id.
996
- > })
997
- @param entity - The Entity to generate a key for.
998
- @return The new key value
999
- **/
1000
- generateTempKeyValue(entity) {
1001
- // TODO - check if this entity is attached to this EntityManager.
1002
- assertParam(entity, "entity").isEntity().check();
1003
- let entityType = entity.entityType;
1004
- let nextKeyValue = this.keyGenerator.generateTempKeyValue(entityType);
1005
- let keyProp = entityType.keyProperties[0];
1006
- entity.setProperty(keyProp.name, nextKeyValue);
1007
- entity.entityAspect.hasTempKey = true;
1008
- return nextKeyValue;
1009
- }
1010
- /**
1011
- Returns whether there are any changed entities of the specified [[EntityType]]s. A 'changed' Entity has
1012
- has an [[EntityState]] of either Added, Modified or Deleted.
1013
-
1014
- This method can be used to determine if an EntityManager has any changes
1015
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1016
- > if ( em1.hasChanges() {
1017
- > // do something interesting
1018
- > }
1019
-
1020
- or if it has any changes on to a specific [[EntityType]].
1021
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1022
- > let custType = em1.metadataStore.getEntityType("Customer");
1023
- > if ( em1.hasChanges(custType) {
1024
- > // do something interesting
1025
- > }
1026
-
1027
- or to a collection of [[EntityType]]s
1028
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1029
- > let custType = em1.metadataStore.getEntityType("Customer");
1030
- > let orderType = em1.metadataStore.getEntityType("Order");
1031
- > if ( em1.hasChanges( [custType, orderType]) {
1032
- > // do something interesting
1033
- > }
1034
- @param entityTypes - The [[EntityType]] or EntityTypes for which 'changed' entities will be found.
1035
- @param entityTypeNames - The [[EntityType]] name or names for which 'changed' entities will be found.
1036
- @return Whether there are any changed entities that match the types specified..
1037
- **/
1038
- hasChanges(entityTypes) {
1039
- if (!this._hasChanges)
1040
- return false;
1041
- if (entityTypes === undefined)
1042
- return this._hasChanges;
1043
- return this._hasChangesCore(entityTypes);
1044
- }
1045
- /** @hidden @internal */
1046
- // backdoor to "really" check for changes.
1047
- _hasChangesCore(entityTypes) {
1048
- let ets = checkEntityTypes(this, entityTypes);
1049
- let entityGroups = getEntityGroups(this, ets);
1050
- return entityGroups.some(function (eg) {
1051
- return eg && eg.hasChanges();
1052
- });
1053
- }
1054
- /**
1055
- Returns a array of all changed entities of the specified [[EntityType]]s. A 'changed' Entity has
1056
- has an [[EntityState]] of either Added, Modified or Deleted.
1057
-
1058
- This method can be used to get all of the changed entities within an EntityManager
1059
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1060
- > let changedEntities = em1.getChanges();
1061
-
1062
- or you can specify that you only want the changes on a specific [[EntityType]]
1063
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1064
- > let custType = em1.metadataStore.getEntityType("Customer");
1065
- > let changedCustomers = em1.getChanges(custType);
1066
-
1067
- or to a collection of [[EntityType]]s
1068
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1069
- > let custType = em1.metadataStore.getEntityType("Customer");
1070
- > let orderType = em1.metadataStore.getEntityType("Order");
1071
- > let changedCustomersAndOrders = em1.getChanges([custType, orderType]);
1072
- @param entityTypes - The [[EntityType]] or EntityTypes for which 'changed' entities will be found.
1073
- @param entityTypeNames - The [[EntityType]] name or names for which 'changed' entities will be found.
1074
- @return An array of Entities
1075
- **/
1076
- getChanges(entityTypes) {
1077
- let ets = checkEntityTypes(this, entityTypes);
1078
- return getChangesCore(this, ets);
1079
- }
1080
- /**
1081
- Rejects (reverses the effects) all of the additions, modifications and deletes from this EntityManager.
1082
- Calls [[EntityAspect.rejectChanges]] on every changed entity in this EntityManager.
1083
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1084
- > let entities = em1.rejectChanges();
1085
- @return The entities whose changes were rejected. These entities will all have EntityStates of
1086
- either 'Unchanged' or 'Detached'
1087
- **/
1088
- rejectChanges() {
1089
- if (!this._hasChanges)
1090
- return [];
1091
- let changes = getChangesCore(this);
1092
- // next line stops individual reject changes from each calling _hasChangesCore
1093
- let aspects = changes.map(function (e) {
1094
- return e.entityAspect._checkOperation("rejectChanges");
1095
- });
1096
- this._hasChanges = false;
1097
- aspects.forEach(function (aspect) {
1098
- aspect.rejectChanges();
1099
- });
1100
- this.hasChangesChanged.publish({ entityManager: this, hasChanges: false });
1101
- return changes;
1102
- }
1103
- /**
1104
- Returns a array of all entities of the specified [[EntityType]]s with the specified [[EntityState]]s.
1105
-
1106
- This method can be used to get all of the entities within an EntityManager
1107
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1108
- > let entities = em1.getEntities();
1109
-
1110
- or you can specify that you only want the changes on a specific [[EntityType]]
1111
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1112
- > let custType = em1.metadataStore.getEntityType("Customer");
1113
- > let customers = em1.getEntities(custType);
1114
-
1115
- or to a collection of [[EntityType]]s
1116
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1117
- > let custType = em1.metadataStore.getEntityType("Customer");
1118
- > let orderType = em1.metadataStore.getEntityType("Order");
1119
- > let customersAndOrders = em1.getChanges([custType, orderType]);
1120
-
1121
- You can also ask for entities with a particular [[EntityState]] or EntityStates.
1122
- > // assume em1 is an EntityManager containing a number of preexisting entities.
1123
- > let custType = em1.metadataStore.getEntityType("Customer");
1124
- > let orderType = em1.metadataStore.getEntityType("Order");
1125
- > let addedCustomersAndOrders = em1.getEntities([custType, orderType], EntityState.Added);
1126
-
1127
- @param entityTypeName - The [[EntityType]] name or names for which entities will be found.
1128
- If this parameter is omitted, all EntityTypes are searched.
1129
- @param entityTypes - The [[EntityType]] or EntityTypes for which entities will be found.
1130
- If this parameter is omitted, all EntityTypes are searched.
1131
- @param entityStates - The [[EntityState]]s for which entities will be found.
1132
- If this parameter is omitted, entities of all EntityStates are returned.
1133
- @return An array of Entities
1134
- **/
1135
- getEntities(entityTypes, entityStates) {
1136
- let entTypes = checkEntityTypes(this, entityTypes);
1137
- assertParam(entityStates, "entityStates").isOptional().isEnumOf(EntityState).or().isNonEmptyArray().isEnumOf(EntityState).check();
1138
- let states = validateEntityStates(this, entityStates);
1139
- return getEntitiesCore(this, entTypes, states);
1140
- }
1141
- // protected methods
1142
- /** @hidden @internal */
1143
- _notifyStateChange(entity, needsSave) {
1144
- let ecArgs = { entityAction: EntityAction.EntityStateChange, entity: entity };
1145
- if (needsSave) {
1146
- if (!this._hasChanges)
1147
- this._setHasChanges(true);
1148
- }
1149
- else {
1150
- // called when rejecting a change or merging an unchanged record.
1151
- // NOTE: this can be slow with lots of entities in the cache.
1152
- // so defer it during a query/import or save and call it once when complete ( if needed).
1153
- if (this._hasChanges) {
1154
- if (this.isLoading) {
1155
- this._hasChangesAction = this._hasChangesAction || function () {
1156
- this._setHasChanges(null);
1157
- this.entityChanged.publish(ecArgs);
1158
- }.bind(this);
1159
- return;
1160
- }
1161
- else {
1162
- this._setHasChanges();
1163
- }
1164
- }
1165
- }
1166
- this.entityChanged.publish(ecArgs);
1167
- }
1168
- /** @hidden @internal */
1169
- _setHasChanges(hasChanges) {
1170
- if (hasChanges == null)
1171
- hasChanges = this._hasChangesCore();
1172
- let hadChanges = this._hasChanges;
1173
- this._hasChanges = hasChanges;
1174
- if (hasChanges !== hadChanges) {
1175
- this.hasChangesChanged.publish({ entityManager: this, hasChanges: hasChanges });
1176
- }
1177
- this._hasChangesAction = undefined;
1178
- }
1179
- /** @hidden @internal */
1180
- _linkRelatedEntities(entity) {
1181
- let em = this;
1182
- let entityAspect = entity.entityAspect;
1183
- // we do not want entityState to change as a result of linkage.
1184
- core.using(em, "isLoading", true, function () {
1185
- let unattachedMap = em._unattachedChildrenMap;
1186
- let entityKey = entityAspect.getKey();
1187
- let entityType = entityKey.entityType;
1188
- while (entityType) {
1189
- let keystring = entityKey.toString(entityType);
1190
- // attach any unattachedChildren
1191
- let tuples = unattachedMap.getTuplesByString(keystring);
1192
- if (tuples) {
1193
- tuples.slice(0).forEach(function (tpl) {
1194
- let unattachedChildren = tpl.children.filter(function (e) {
1195
- return e.entityAspect.entityState !== EntityState.Detached;
1196
- });
1197
- let childToParentNp;
1198
- let parentToChildNp;
1199
- // np is usually childToParentNp
1200
- // except with unidirectional 1-n where it is parentToChildNp;
1201
- let np = tpl.navigationProperty;
1202
- let inverseNp = np.inverse;
1203
- if (inverseNp) {
1204
- // bidirectional
1205
- childToParentNp = np;
1206
- parentToChildNp = inverseNp;
1207
- if (parentToChildNp.isScalar) {
1208
- let onlyChild = unattachedChildren[0];
1209
- entity.setProperty(parentToChildNp.name, onlyChild);
1210
- onlyChild.setProperty(childToParentNp.name, entity);
1211
- }
1212
- else {
1213
- let currentChildren = entity.getProperty(parentToChildNp.name);
1214
- unattachedChildren.forEach(function (child) {
1215
- currentChildren.push(child);
1216
- child.setProperty(childToParentNp.name, entity);
1217
- });
1218
- }
1219
- unattachedMap.removeChildren(keystring, childToParentNp);
1220
- }
1221
- else {
1222
- // unidirectional
1223
- // if (np.isScalar || np.parentType !== entity.entityType) {
1224
- if (np.isScalar) {
1225
- // n -> 1 eg: child: OrderDetail parent: Product
1226
- // 1 -> 1 eg child: Employee parent: Employee ( only Manager, no DirectReports property)
1227
- childToParentNp = np;
1228
- unattachedChildren.forEach(function (child) {
1229
- child.setProperty(childToParentNp.name, entity);
1230
- });
1231
- unattachedMap.removeChildren(keystring, childToParentNp);
1232
- }
1233
- else {
1234
- // 1 -> n eg: parent: Region child: Terr
1235
- // TODO: need to remove unattached children from the map after this; only a perf issue.
1236
- parentToChildNp = np;
1237
- let currentChildren = entity.getProperty(parentToChildNp.name);
1238
- unattachedChildren.forEach(function (child) {
1239
- // we know if can't already be there.
1240
- currentChildren._push(child);
1241
- });
1242
- }
1243
- }
1244
- });
1245
- }
1246
- entityType = entityType.baseEntityType; // look for relationships up the hierarchy
1247
- }
1248
- // now add to unattachedMap if needed.
1249
- entity.entityType.navigationProperties.forEach(function (np) {
1250
- if (np.isScalar) {
1251
- let value = entity.getProperty(np.name);
1252
- // property is already linked up
1253
- if (value)
1254
- return;
1255
- }
1256
- // first determine if np contains a parent or child
1257
- // having a parentKey means that this is a child
1258
- // if a parent then no need for more work because children will attach to it.
1259
- let parentKey = entityAspect.getParentKey(np);
1260
- if (parentKey) {
1261
- // check for empty keys - meaning that parent id's are not yet set.
1262
- if (parentKey._isEmpty())
1263
- return;
1264
- // if a child - look for parent in the em cache
1265
- if (np.invForeignKeyNames.length) {
1266
- // np relates to non-PK property of parent entity
1267
- const query = new EntityQuery(parentKey.entityType.defaultResourceName).where(np.invForeignKeyNames[0], 'eq', parentKey.values[0]);
1268
- const qresult = em.executeQueryLocally(query);
1269
- if (qresult.length === 1) {
1270
- let parent = qresult[0];
1271
- entity.setProperty(np.name, parent);
1272
- }
1273
- }
1274
- else {
1275
- // np relates to PK of parent entity
1276
- let parent = em.getEntityByKey(parentKey);
1277
- if (parent) {
1278
- // if found hook it up
1279
- entity.setProperty(np.name, parent);
1280
- }
1281
- else {
1282
- // else add parent to unresolvedParentMap;
1283
- unattachedMap.addChild(parentKey, np, entity);
1284
- }
1285
- }
1286
- }
1287
- else if (np.inverse && np.inverse.invForeignKeyNames.length) {
1288
- // np relates to non-PK property of parent entity; query entities by FK
1289
- const akValue = entity.getProperty(np.inverse.invForeignKeyNames[0]);
1290
- const query = new EntityQuery(np.entityType.defaultResourceName).where(np.invForeignKeyNames[0], 'eq', akValue);
1291
- const qresult = em.executeQueryLocally(query);
1292
- qresult.forEach((child) => {
1293
- child.setProperty(np.inverse.name, entity);
1294
- });
1295
- }
1296
- });
1297
- // handle unidirectional 1-x where we set x.fk
1298
- entity.entityType.foreignKeyProperties.forEach(function (fkProp) {
1299
- let invNp = fkProp.inverseNavigationProperty;
1300
- if (!invNp)
1301
- return;
1302
- // unidirectional fk props only
1303
- let fkValue = entity.getProperty(fkProp.name);
1304
- let parentKey = new EntityKey(invNp.parentType, [fkValue]);
1305
- let parent = em.getEntityByKey(parentKey);
1306
- if (parent) {
1307
- if (invNp.isScalar) {
1308
- parent.setProperty(invNp.name, entity);
1309
- }
1310
- else {
1311
- if (em.isLoading) {
1312
- parent.getProperty(invNp.name)._push(entity);
1313
- }
1314
- else {
1315
- parent.getProperty(invNp.name).push(entity);
1316
- }
1317
- }
1318
- }
1319
- else {
1320
- // else add parent to unresolvedParentMap;
1321
- unattachedMap.addChild(parentKey, invNp, entity);
1322
- }
1323
- });
1324
- });
1325
- }
1326
- /** @hidden @internal */
1327
- _attachEntityCore(entity, entityState, mergeStrategy) {
1328
- let group = findOrCreateEntityGroup(this, entity.entityType);
1329
- let attachedEntity = group.attachEntity(entity, entityState, mergeStrategy);
1330
- this._linkRelatedEntities(attachedEntity);
1331
- return attachedEntity;
1332
- }
1333
- /** @hidden @internal */
1334
- _updateFkVal(fkProp, oldValue, newValue) {
1335
- let group = this._entityGroupMap[fkProp.parentType.name];
1336
- if (!group)
1337
- return;
1338
- group._updateFkVal(fkProp, oldValue, newValue);
1339
- }
1340
- }
1341
- EntityManager.prototype._$typeName = "EntityManager";
1342
- BreezeEvent.bubbleEvent(EntityManager.prototype);
1343
- function clearServerErrors(entities) {
1344
- entities.forEach(function (entity) {
1345
- let serverKeys = [];
1346
- let aspect = entity.entityAspect;
1347
- core.objectForEach(aspect._validationErrors, function (key, ve) {
1348
- if (ve.isServerError)
1349
- serverKeys.push(key);
1350
- });
1351
- if (serverKeys.length === 0)
1352
- return;
1353
- aspect._processValidationOpAndPublish(function () {
1354
- serverKeys.forEach(function (key) {
1355
- aspect._removeValidationError(key);
1356
- });
1357
- });
1358
- });
1359
- }
1360
- function createEntityErrors(entities) {
1361
- let entityErrors = [];
1362
- entities.forEach((entity) => {
1363
- core.objectForEach(entity.entityAspect._validationErrors, function (key, ve) {
1364
- let cfg = core.extend({
1365
- entity: entity,
1366
- errorName: ve.validator.name
1367
- }, ve, ["errorMessage", "propertyName", "isServerError", "custom"]);
1368
- entityErrors.push(cfg);
1369
- });
1370
- });
1371
- return entityErrors;
1372
- }
1373
- function processServerErrors(saveContext, saveError) {
1374
- // converting ISaveErrorFromServer -> ISaveError
1375
- let serverErrors = saveError.entityErrors;
1376
- if (!serverErrors)
1377
- return saveError;
1378
- let entityManager = saveContext.entityManager;
1379
- let metadataStore = entityManager.metadataStore;
1380
- let entityErrors = serverErrors.map((serr) => {
1381
- let entity = null;
1382
- let entityType;
1383
- if (serr.keyValues) {
1384
- entityType = metadataStore._getStructuralType(serr.entityTypeName);
1385
- let ekey = new EntityKey(entityType, serr.keyValues);
1386
- entity = entityManager.getEntityByKey(ekey);
1387
- }
1388
- if (entityType && entity) {
1389
- let context = serr.propertyName ?
1390
- {
1391
- propertyName: serr.propertyName,
1392
- property: entityType.getProperty(serr.propertyName)
1393
- } : {};
1394
- let key = ValidationError.getKey(serr.errorName || serr.errorMessage, serr.propertyName);
1395
- let ve = new ValidationError(null, context, serr.errorMessage, key);
1396
- ve.isServerError = true;
1397
- entity.entityAspect.addValidationError(ve);
1398
- }
1399
- let entityError = core.extend({
1400
- entity: entity,
1401
- isServerError: true
1402
- }, serr, ["errorName", "errorMessage", "propertyName", "custom"]);
1403
- return entityError;
1404
- });
1405
- // converting ISaveErrorFromServer -> ISaveError
1406
- saveError.entityErrors = entityErrors;
1407
- return saveError;
1408
- }
1409
- function fetchEntityByKeyCore(em, args) {
1410
- let tpl = createEntityKey(em, args);
1411
- let entityKey = tpl.entityKey;
1412
- let checkLocalCacheFirst = tpl.remainingArgs.length === 0 ? false : !!tpl.remainingArgs[0];
1413
- let entity = null;
1414
- let foundIt = false;
1415
- if (checkLocalCacheFirst) {
1416
- entity = em.getEntityByKey(entityKey);
1417
- foundIt = entity != null;
1418
- if (entity != null &&
1419
- // null the entity if it is deleted and we should exclude deleted entities
1420
- !em.queryOptions.includeDeleted && entity.entityAspect.entityState.isDeleted()) {
1421
- entity = null;
1422
- // but resume looking if we'd overwrite deleted entity with a remote entity
1423
- // note: em.queryOptions is always fully resolved by now
1424
- foundIt = em.queryOptions.mergeStrategy !== MergeStrategy.OverwriteChanges;
1425
- }
1426
- }
1427
- if (foundIt) {
1428
- return Promise.resolve({ entity: entity || undefined, entityKey: entityKey, fromCache: true });
1429
- }
1430
- else {
1431
- return EntityQuery.fromEntityKey(entityKey).using(em).execute().then(function (data) {
1432
- entity = (data.results.length === 0) ? null : data.results[0];
1433
- return Promise.resolve({ entity: entity || undefined, entityKey: entityKey, fromCache: false });
1434
- });
1435
- }
1436
- }
1437
- // private fns
1438
- // takes in entityTypes as either strings or entityTypes or arrays of either
1439
- // and returns either an entityType or an array of entityTypes or throws an error
1440
- function checkEntityTypes(em, entityTypes) {
1441
- assertParam(entityTypes, "entityTypes").isString().isOptional().or().isNonEmptyArray().isString()
1442
- .or().isInstanceOf(EntityType).or().isNonEmptyArray().isInstanceOf(EntityType).check();
1443
- let resultTypes;
1444
- if (typeof entityTypes === "string") {
1445
- resultTypes = em.metadataStore._getStructuralType(entityTypes, false);
1446
- }
1447
- else if (Array.isArray(entityTypes) && typeof entityTypes[0] === "string") {
1448
- resultTypes = entityTypes.map(function (etName) {
1449
- return em.metadataStore._getStructuralType(etName, false);
1450
- });
1451
- }
1452
- else {
1453
- resultTypes = entityTypes;
1454
- }
1455
- return resultTypes;
1456
- }
1457
- function getChangesCore(em, entityTypes) {
1458
- let entityGroups = getEntityGroups(em, entityTypes);
1459
- // TODO: think about writing a core.mapMany method if we see more of these.
1460
- let selected = [];
1461
- entityGroups.forEach(function (eg) {
1462
- // eg may be undefined or null
1463
- if (!eg)
1464
- return;
1465
- let entities = eg.getChanges();
1466
- if (selected && selected.length) {
1467
- selected = selected.concat(entities);
1468
- }
1469
- else {
1470
- selected = entities;
1471
- }
1472
- });
1473
- return selected;
1474
- }
1475
- function getEntitiesCore(em, entityTypes, entityStates) {
1476
- let entityGroups = getEntityGroups(em, entityTypes);
1477
- // TODO: think about writing a core.mapMany method if we see more of these.
1478
- let selected = [];
1479
- entityGroups.forEach(function (eg) {
1480
- // eg may be undefined or null
1481
- if (!eg)
1482
- return;
1483
- let entities = eg.getEntities(entityStates);
1484
- if (selected && selected.length) {
1485
- selected = selected.concat(entities);
1486
- }
1487
- else {
1488
- selected = entities;
1489
- }
1490
- });
1491
- return selected;
1492
- }
1493
- function createEntityKey(em, args) {
1494
- try {
1495
- if (args[0] instanceof EntityKey) {
1496
- return { entityKey: args[0], remainingArgs: core.arraySlice(args, 1) };
1497
- }
1498
- else if (args.length >= 2) {
1499
- let entityType = (typeof args[0] === 'string') ? em.metadataStore._getStructuralType(args[0], false) : args[0];
1500
- return { entityKey: new EntityKey(entityType, args[1]), remainingArgs: core.arraySlice(args, 2) };
1501
- }
1502
- }
1503
- catch (e) { /* throw below */
1504
- // throw new Error("Must supply an EntityKey OR an EntityType name or EntityType followed by a key value or an array of key values.");
1505
- }
1506
- throw new Error("Must supply an EntityKey OR an EntityType name or EntityType followed by a key value or an array of key values.");
1507
- }
1508
- function markIsBeingSaved(entities, flag) {
1509
- entities.forEach(function (entity) {
1510
- entity.entityAspect.isBeingSaved = flag;
1511
- });
1512
- }
1513
- function exportEntityGroups(em, entitiesOrEntityTypes) {
1514
- let entityGroupMap;
1515
- let first = entitiesOrEntityTypes && entitiesOrEntityTypes[0];
1516
- // check if array
1517
- if (first) {
1518
- // group entities by entityType and
1519
- // create 'groups' that look like entityGroups.
1520
- entityGroupMap = {};
1521
- if (first.entityType) {
1522
- let entities = entitiesOrEntityTypes;
1523
- // assume "entities" is an array of entities;
1524
- entities.forEach(function (e) {
1525
- if (e.entityAspect.entityState === EntityState.Detached) {
1526
- throw new Error("Unable to export an entity with an EntityState of 'Detached'");
1527
- }
1528
- let group = entityGroupMap[e.entityType.name];
1529
- if (!group) {
1530
- group = {};
1531
- group.entityType = e.entityType;
1532
- group._entities = [];
1533
- entityGroupMap[e.entityType.name] = group;
1534
- }
1535
- group._entities.push(e);
1536
- });
1537
- }
1538
- else {
1539
- // assume "entities" is an array of EntityTypes (or names)
1540
- let entityTypes = checkEntityTypes(em, entitiesOrEntityTypes);
1541
- if (entityTypes != null) {
1542
- entityTypes.forEach((et) => {
1543
- let group = em._entityGroupMap[et.name];
1544
- if (group && group._entities.length) {
1545
- entityGroupMap[et.name] = group;
1546
- }
1547
- });
1548
- }
1549
- }
1550
- }
1551
- else if (entitiesOrEntityTypes && entitiesOrEntityTypes.length === 0) {
1552
- // empty array = export nothing
1553
- entityGroupMap = {};
1554
- }
1555
- else {
1556
- entityGroupMap = em._entityGroupMap;
1557
- }
1558
- let tempKeys = [];
1559
- let newGroupMap = {};
1560
- core.objectForEach(entityGroupMap, (entityTypeName, entityGroup) => {
1561
- newGroupMap[entityTypeName] = exportEntityGroup(entityGroup, tempKeys);
1562
- });
1563
- return { entityGroupMap: newGroupMap, tempKeys: tempKeys };
1564
- }
1565
- function exportEntityGroup(entityGroup, tempKeys) {
1566
- let resultGroup = {};
1567
- let entityType = entityGroup.entityType;
1568
- let dps = entityType.dataProperties;
1569
- let serializerFn = getSerializerFn(entityType);
1570
- let rawEntities = [];
1571
- entityGroup._entities.forEach((entity) => {
1572
- if (entity) {
1573
- let rawEntity = structuralObjectToJson(entity, dps, serializerFn, tempKeys);
1574
- rawEntities.push(rawEntity);
1575
- }
1576
- });
1577
- resultGroup.entities = rawEntities;
1578
- return resultGroup;
1579
- }
1580
- function structuralObjectToJson(so, dps, serializerFn, tempKeys) {
1581
- let result = {};
1582
- dps.forEach(function (dp) {
1583
- let dpName = dp.name;
1584
- let value = so.getProperty(dpName);
1585
- if (value == null && dp.defaultValue == null)
1586
- return;
1587
- if (value && dp.isComplexProperty) {
1588
- let coDps = dp.dataType.dataProperties;
1589
- value = core.map(value, function (v) {
1590
- return structuralObjectToJson(v, coDps, serializerFn);
1591
- });
1592
- }
1593
- else {
1594
- value = serializerFn ? serializerFn(dp, value) : value;
1595
- if (dp.isUnmapped) {
1596
- value = core.toJSONSafe(value, core.toJSONSafeReplacer);
1597
- }
1598
- }
1599
- if (value === undefined)
1600
- return;
1601
- result[dpName] = value;
1602
- });
1603
- // if (so.entityAspect) {
1604
- if (EntityAspect.isEntity(so)) {
1605
- let aspect = so.entityAspect;
1606
- let entityState = aspect.entityState;
1607
- let newAspect = {
1608
- tempNavPropNames: exportTempKeyInfo(aspect, tempKeys || []),
1609
- entityState: entityState.name
1610
- };
1611
- if (aspect.extraMetadata) {
1612
- newAspect.extraMetadata = aspect.extraMetadata;
1613
- }
1614
- if (entityState.isModified() || entityState.isDeleted()) {
1615
- newAspect.originalValuesMap = aspect.originalValues;
1616
- }
1617
- result.entityAspect = newAspect;
1618
- }
1619
- else {
1620
- let aspect = so.complexAspect;
1621
- let newAspect = {};
1622
- if (aspect.originalValues && !core.isEmpty(aspect.originalValues)) {
1623
- newAspect.originalValuesMap = aspect.originalValues;
1624
- }
1625
- result.complexAspect = newAspect;
1626
- }
1627
- return result;
1628
- }
1629
- function exportTempKeyInfo(entityAspect, tempKeys) {
1630
- let entity = entityAspect.entity;
1631
- if (entityAspect.hasTempKey) {
1632
- tempKeys.push(entityAspect.getKey().toJSON());
1633
- }
1634
- // create map for this entity with foreignKeys that are 'temporary'
1635
- // map -> key: tempKey, value: fkPropName
1636
- let tempNavPropNames = [];
1637
- entity.entityType.navigationProperties.forEach(function (np) {
1638
- if (np.relatedDataProperties) {
1639
- let relatedValue = entity.getProperty(np.name);
1640
- if (relatedValue && relatedValue.entityAspect.hasTempKey) {
1641
- tempNavPropNames.push(np.name);
1642
- }
1643
- }
1644
- });
1645
- return tempNavPropNames;
1646
- }
1647
- function importEntityGroup(entityGroup, jsonGroup, importConfig) {
1648
- let tempKeyMap = importConfig.tempKeyMap;
1649
- let mergeAdds = !!importConfig.mergeAdds;
1650
- let entityType = entityGroup.entityType;
1651
- let mergeStrategy = importConfig.mergeStrategy;
1652
- let targetEntity;
1653
- let em = entityGroup.entityManager;
1654
- let entityChanged = em.entityChanged;
1655
- let entitiesToLink = [];
1656
- let rawValueFn = DataProperty.getRawValueFromClient;
1657
- jsonGroup.entities.forEach(function (rawEntity) {
1658
- let newAspect = rawEntity.entityAspect;
1659
- let entityKey = entityType.getEntityKeyFromRawEntity(rawEntity, rawValueFn);
1660
- let entityState = EntityState.fromName(newAspect.entityState);
1661
- if (!entityState || entityState === EntityState.Detached) {
1662
- throw new Error("Only entities with a non detached entity state may be imported.");
1663
- }
1664
- // Merge if raw entity is in cache UNLESS this is a new entity w/ a temp key
1665
- // Cannot safely merge such entities even if could match temp key to an entity in cache.
1666
- // Can enable merge of entities w/temp key using "mergeAdds" - use at your own risk!
1667
- let newTempKey = !mergeAdds && entityState.isAdded() && getMappedKey(tempKeyMap, entityKey);
1668
- targetEntity = newTempKey ? undefined : entityGroup.findEntityByKey(entityKey);
1669
- if (targetEntity) {
1670
- if (mergeStrategy === MergeStrategy.SkipMerge) {
1671
- // deliberate fall thru
1672
- }
1673
- else if (mergeStrategy === MergeStrategy.Disallowed) {
1674
- throw new Error("A MergeStrategy of 'Disallowed' prevents " + entityKey.toString() + " from being merged");
1675
- }
1676
- else {
1677
- let targetEntityState = targetEntity.entityAspect.entityState;
1678
- let wasUnchanged = targetEntityState.isUnchanged();
1679
- if (mergeStrategy === MergeStrategy.OverwriteChanges || wasUnchanged) {
1680
- entityType._updateTargetFromRaw(targetEntity, rawEntity, rawValueFn);
1681
- targetEntity.entityAspect.setEntityState(entityState);
1682
- entityChanged.publish({ entityAction: EntityAction.MergeOnImport, entity: targetEntity });
1683
- }
1684
- }
1685
- }
1686
- else {
1687
- targetEntity = entityType._createInstanceCore();
1688
- entityType._updateTargetFromRaw(targetEntity, rawEntity, rawValueFn);
1689
- if (newTempKey) {
1690
- targetEntity.entityAspect.hasTempKey = true;
1691
- // fixup pk
1692
- targetEntity.setProperty(entityType.keyProperties[0].name, newTempKey.values[0]);
1693
- // fixup foreign keys
1694
- // This is safe because the entity is detached here and therefore originalValues will not be updated.
1695
- if (newAspect.tempNavPropNames) {
1696
- newAspect.tempNavPropNames.forEach(function (npName) {
1697
- let np = entityType.getNavigationProperty(npName);
1698
- let fkPropName = np.relatedDataProperties[0].name;
1699
- let oldFkValue = targetEntity.getProperty(fkPropName);
1700
- let fk = new EntityKey(np.entityType, [oldFkValue]);
1701
- let newFk = getMappedKey(tempKeyMap, fk);
1702
- targetEntity.setProperty(fkPropName, newFk.values[0]);
1703
- });
1704
- }
1705
- }
1706
- // Now performed in attachEntity
1707
- targetEntity = entityGroup.attachEntity(targetEntity, entityState);
1708
- entityChanged.publish({ entityAction: EntityAction.AttachOnImport, entity: targetEntity });
1709
- if (!entityState.isUnchanged()) {
1710
- em._notifyStateChange(targetEntity, true);
1711
- }
1712
- }
1713
- entitiesToLink.push(targetEntity);
1714
- });
1715
- return entitiesToLink;
1716
- }
1717
- function getMappedKey(tempKeyMap, entityKey) {
1718
- let newKey = tempKeyMap[entityKey.toString()];
1719
- if (newKey)
1720
- return newKey;
1721
- let subtypes = entityKey._subtypes;
1722
- if (!subtypes)
1723
- return null;
1724
- for (let i = 0, j = subtypes.length; i < j; i++) {
1725
- newKey = tempKeyMap[entityKey.toString(subtypes[i])];
1726
- if (newKey)
1727
- return newKey;
1728
- }
1729
- return null;
1730
- }
1731
- function promiseWithCallbacks(promise, callback, errorCallback) {
1732
- promise = promise.then(function (data) {
1733
- if (callback)
1734
- callback(data);
1735
- return Promise.resolve(data);
1736
- }, function (error) {
1737
- if (errorCallback)
1738
- errorCallback(error);
1739
- return Promise.reject(error);
1740
- });
1741
- return promise;
1742
- }
1743
- function getEntitiesToSave(em, entities) {
1744
- let entitiesToSave;
1745
- if (entities) {
1746
- entitiesToSave = entities.filter(function (e) {
1747
- if (e.entityAspect.entityManager !== em) {
1748
- throw new Error("Only entities in this entityManager may be saved");
1749
- }
1750
- return !e.entityAspect.entityState.isDetached();
1751
- });
1752
- }
1753
- else {
1754
- entitiesToSave = em.getChanges();
1755
- }
1756
- return entitiesToSave;
1757
- }
1758
- function fixupKeys(em, keyMappings) {
1759
- em._inKeyFixup = true;
1760
- keyMappings.forEach(function (km) {
1761
- let group = em._entityGroupMap[km.entityTypeName];
1762
- if (!group) {
1763
- throw new Error("Unable to locate the following fully qualified EntityType name: " + km.entityTypeName);
1764
- }
1765
- group._fixupKey(km.tempValue, km.realValue);
1766
- });
1767
- em._inKeyFixup = false;
1768
- }
1769
- function getEntityGroups(em, entityTypes) {
1770
- let groupMap = em._entityGroupMap;
1771
- if (entityTypes) {
1772
- return core.toArray(entityTypes).map(function (et) {
1773
- if (et instanceof EntityType) {
1774
- return groupMap[et.name];
1775
- }
1776
- else {
1777
- throw new Error("The EntityManager.getChanges() 'entityTypes' parameter must be either an entityType or an array of entityTypes or null");
1778
- }
1779
- });
1780
- }
1781
- else {
1782
- return core.getOwnPropertyValues(groupMap);
1783
- }
1784
- }
1785
- function checkEntityKey(em, entity) {
1786
- let ek = entity.entityAspect.getKey();
1787
- // return properties that are = to defaultValues
1788
- let keyPropsWithDefaultValues = core.arrayZip(entity.entityType.keyProperties, ek.values, function (kp, kv) {
1789
- return (kp.defaultValue === kv) ? kp : null;
1790
- }).filter(function (kp) {
1791
- return kp !== null;
1792
- });
1793
- if (keyPropsWithDefaultValues.length) {
1794
- if (entity.entityType.autoGeneratedKeyType !== AutoGeneratedKeyType.None) {
1795
- em.generateTempKeyValue(entity);
1796
- }
1797
- else {
1798
- // we will allow attaches of entities where only part of the key is set.
1799
- if (keyPropsWithDefaultValues.length === ek.values.length) {
1800
- throw new Error("Cannot attach an object of type (" + entity.entityType.name + ") to an EntityManager without first setting its key or setting its entityType 'AutoGeneratedKeyType' property to something other than 'None'");
1801
- }
1802
- }
1803
- }
1804
- }
1805
- function validateEntityStates(em, entityStates) {
1806
- if (!entityStates)
1807
- return [];
1808
- let entStates = core.toArray(entityStates);
1809
- entStates.forEach((es) => {
1810
- if (!(es instanceof EntityState)) {
1811
- throw new Error("The EntityManager.getChanges() 'entityStates' parameter must either be null, an entityState or an array of entityStates");
1812
- }
1813
- });
1814
- return entStates;
1815
- }
1816
- function attachRelatedEntities(em, entity, entityState, mergeStrategy) {
1817
- let navProps = entity.entityType.navigationProperties;
1818
- navProps.forEach(function (np) {
1819
- let related = entity.getProperty(np.name);
1820
- if (np.isScalar) {
1821
- if (!related)
1822
- return;
1823
- em.attachEntity(related, entityState, mergeStrategy);
1824
- }
1825
- else {
1826
- related.forEach(function (e) {
1827
- em.attachEntity(e, entityState, mergeStrategy);
1828
- });
1829
- }
1830
- });
1831
- }
1832
- // returns a promise
1833
- function executeQueryCore(em, query, queryOptions, dataService) {
1834
- try {
1835
- let results;
1836
- let metadataStore = em.metadataStore;
1837
- if (metadataStore.isEmpty() && dataService.hasServerMetadata) {
1838
- throw new Error("cannot execute _executeQueryCore until metadataStore is populated.");
1839
- }
1840
- if (queryOptions.fetchStrategy === FetchStrategy.FromLocalCache) {
1841
- try {
1842
- if (typeof query === 'string') {
1843
- throw new Error("cannot execute 'string' EntityQuery locally.");
1844
- }
1845
- let qr = executeQueryLocallyCore(em, query);
1846
- return Promise.resolve({ results: qr.results, entityManager: em, inlineCount: qr.inlineCount, query: query });
1847
- }
1848
- catch (e) {
1849
- return Promise.reject(e);
1850
- }
1851
- }
1852
- let mappingContext = new MappingContext({
1853
- query: query,
1854
- entityManager: em,
1855
- dataService: dataService,
1856
- mergeOptions: {
1857
- mergeStrategy: queryOptions.mergeStrategy,
1858
- noTracking: !!query.noTrackingEnabled,
1859
- includeDeleted: queryOptions.includeDeleted
1860
- }
1861
- });
1862
- let validateOnQuery = em.validationOptions.validateOnQuery;
1863
- return dataService.adapterInstance.executeQuery(mappingContext).then(function (data) {
1864
- let result = core.wrapExecution(function () {
1865
- let state = { isLoading: em.isLoading };
1866
- em.isLoading = true;
1867
- em._pendingPubs = [];
1868
- return state;
1869
- }, function (state) {
1870
- // cleanup
1871
- em.isLoading = state.isLoading;
1872
- em._pendingPubs.forEach(function (fn) {
1873
- fn();
1874
- });
1875
- em._pendingPubs = undefined;
1876
- em._hasChangesAction && em._hasChangesAction();
1877
- // TODO: removed - not sure why needed in first place...
1878
- // // HACK for GC
1879
- // query = undefined;
1880
- mappingContext = undefined;
1881
- // HACK: some errors thrown in next function do not propogate properly - this catches them.
1882
- if (state.error) {
1883
- return Promise.reject(state.error);
1884
- }
1885
- }, function () {
1886
- let nodes = dataService.jsonResultsAdapter.extractResults(data);
1887
- nodes = core.toArray(nodes);
1888
- results = mappingContext.visitAndMerge(nodes, { nodeType: "root" });
1889
- if (validateOnQuery) {
1890
- results.forEach(function (r) {
1891
- // anon types and simple types will not have an entityAspect.
1892
- r.entityAspect && r.entityAspect.validateEntity();
1893
- });
1894
- }
1895
- mappingContext.processDeferred();
1896
- // if query has expand clauses walk each of the 'results' and mark the expanded props as loaded.
1897
- if (query instanceof EntityQuery) {
1898
- markLoadedNavProps(results, query);
1899
- }
1900
- let retrievedEntities = core.objectMap(mappingContext.refMap);
1901
- return { results: results, query: query, entityManager: em, httpResponse: data.httpResponse, inlineCount: data.inlineCount, retrievedEntities: retrievedEntities };
1902
- });
1903
- return Promise.resolve(result);
1904
- }, function (e) {
1905
- if (e) {
1906
- e.query = query;
1907
- e.entityManager = em;
1908
- }
1909
- return Promise.reject(e);
1910
- });
1911
- }
1912
- catch (e) {
1913
- if (e) {
1914
- e.query = query;
1915
- }
1916
- return Promise.reject(e);
1917
- }
1918
- }
1919
- function markLoadedNavProps(entities, query) {
1920
- if (query.noTrackingEnabled)
1921
- return;
1922
- let expandClause = query.expandClause;
1923
- if (expandClause == null)
1924
- return;
1925
- expandClause.propertyPaths.forEach(function (propertyPath) {
1926
- let propNames = propertyPath.split('.');
1927
- markLoadedNavPath(entities, propNames);
1928
- });
1929
- }
1930
- function markLoadedNavPath(entities, propNames) {
1931
- let propName = propNames[0];
1932
- entities.forEach((entity) => {
1933
- let ea = entity.entityAspect;
1934
- if (!ea)
1935
- return; // entity may not be a 'real' entity in the case of a projection.
1936
- ea._markAsLoaded(propName);
1937
- if (propNames.length === 1)
1938
- return;
1939
- let next = entity.getProperty(propName);
1940
- if (!next)
1941
- return; // no children to process.
1942
- // strange logic because nonscalar nav values are NOT really arrays
1943
- // otherwise we could use Array.isArray
1944
- if (!next.arrayChanged)
1945
- next = [next];
1946
- markLoadedNavPath(next, propNames.slice(1));
1947
- });
1948
- }
1949
- function updateConcurrencyProperties(entities) {
1950
- let candidates = entities.filter((e) => {
1951
- e.entityAspect.isBeingSaved = true;
1952
- return e.entityAspect.entityState.isModified()
1953
- && e.entityType.concurrencyProperties.length > 0;
1954
- });
1955
- if (candidates.length === 0)
1956
- return;
1957
- candidates.forEach(function (c) {
1958
- c.entityType.concurrencyProperties.forEach(function (cp) {
1959
- updateConcurrencyProperty(c, cp);
1960
- });
1961
- });
1962
- }
1963
- function updateConcurrencyProperty(entity, property) {
1964
- // check if property has already been updated
1965
- if (entity.entityAspect.originalValues[property.name])
1966
- return;
1967
- let value = entity.getProperty(property.name);
1968
- let dataType = property.dataType;
1969
- if (!value)
1970
- value = dataType.defaultValue;
1971
- if (dataType.isNumeric) {
1972
- entity.setProperty(property.name, value + 1);
1973
- }
1974
- else if (dataType.getConcurrencyValue) {
1975
- // DataType has its own implementation
1976
- let nextValue = dataType.getConcurrencyValue(value);
1977
- entity.setProperty(property.name, nextValue);
1978
- }
1979
- else if (dataType === DataType.Binary) {
1980
- // best guess - that this is a timestamp column and is computed on the server during save
1981
- // - so no need to set it here.
1982
- return;
1983
- }
1984
- else {
1985
- // this just leaves DataTypes of Boolean, String and Byte - none of which should be the
1986
- // type for a concurrency column.
1987
- // NOTE: thought about just returning here but would rather be safe for now.
1988
- throw new Error("Unable to update the value of concurrency property before saving: " + property.name);
1989
- }
1990
- }
1991
- function findOrCreateEntityGroup(em, entityType) {
1992
- let group = em._entityGroupMap[entityType.name];
1993
- if (!group) {
1994
- group = new EntityGroup(em, entityType);
1995
- em._entityGroupMap[entityType.name] = group;
1996
- }
1997
- return group;
1998
- }
1999
- function findOrCreateEntityGroups(em, entityType) {
2000
- let entityTypes = entityType.getSelfAndSubtypes();
2001
- return entityTypes.map((et) => {
2002
- return findOrCreateEntityGroup(em, et);
2003
- });
2004
- }
2005
- function unwrapInstance(structObj, transformFn) {
2006
- let rawObject = {};
2007
- let stype = EntityAspect.isEntity(structObj) ? structObj.entityType : structObj.complexType;
2008
- let serializerFn = getSerializerFn(stype);
2009
- let unmapped = {};
2010
- stype.dataProperties.forEach(function (dp) {
2011
- if (dp.isComplexProperty) {
2012
- rawObject[dp.nameOnServer] = core.map(structObj.getProperty(dp.name), function (co) {
2013
- return unwrapInstance(co, transformFn);
2014
- });
2015
- }
2016
- else {
2017
- let val = structObj.getProperty(dp.name);
2018
- val = transformFn ? transformFn(dp, val) : val;
2019
- if (val === undefined)
2020
- return;
2021
- val = serializerFn ? serializerFn(dp, val) : val;
2022
- if (val !== undefined) {
2023
- if (dp.isUnmapped) {
2024
- unmapped[dp.nameOnServer] = core.toJSONSafe(val, core.toJSONSafeReplacer);
2025
- }
2026
- else {
2027
- rawObject[dp.nameOnServer] = val;
2028
- }
2029
- }
2030
- }
2031
- });
2032
- if (!core.isEmpty(unmapped)) {
2033
- // TODO: review this.
2034
- rawObject.__unmapped = unmapped;
2035
- }
2036
- return rawObject;
2037
- }
2038
- function unwrapOriginalValues(target, metadataStore, transformFn) {
2039
- let stype = EntityAspect.isEntity(target) ? target.entityType : target.complexType;
2040
- let aspect = EntityAspect.isEntity(target) ? target.entityAspect : target.complexAspect;
2041
- let fn = metadataStore.namingConvention.clientPropertyNameToServer;
2042
- let result = {};
2043
- core.objectForEach(aspect.originalValues, function (propName, val) {
2044
- let prop = stype.getProperty(propName);
2045
- val = transformFn ? transformFn(prop, val) : val;
2046
- if (val !== undefined) {
2047
- result[fn(propName, prop)] = val;
2048
- }
2049
- });
2050
- stype.complexProperties.forEach(function (cp) {
2051
- let nextTarget = target.getProperty(cp.name);
2052
- if (cp.isScalar) {
2053
- let unwrappedCo = unwrapOriginalValues(nextTarget, metadataStore, transformFn);
2054
- if (!core.isEmpty(unwrappedCo)) {
2055
- result[fn(cp.name, cp)] = unwrappedCo;
2056
- }
2057
- }
2058
- else {
2059
- let unwrappedCos = nextTarget.map((item) => {
2060
- return unwrapOriginalValues(item, metadataStore, transformFn);
2061
- });
2062
- result[fn(cp.name, cp)] = unwrappedCos;
2063
- }
2064
- });
2065
- return result;
2066
- }
2067
- function unwrapChangedValues(entity, metadataStore, transformFn) {
2068
- let stype = entity.entityType;
2069
- let serializerFn = getSerializerFn(stype);
2070
- let fn = metadataStore.namingConvention.clientPropertyNameToServer;
2071
- let result = {};
2072
- core.objectForEach(entity.entityAspect.originalValues, function (propName, value) {
2073
- let prop = stype.getProperty(propName);
2074
- let val = entity.getProperty(propName);
2075
- val = transformFn ? transformFn(prop, val) : val;
2076
- if (val === undefined)
2077
- return;
2078
- val = serializerFn ? serializerFn(prop, val) : val;
2079
- if (val !== undefined) {
2080
- result[fn(propName, prop)] = val;
2081
- }
2082
- });
2083
- // any change to any complex object or array of complex objects returns the ENTIRE
2084
- // current complex object or complex object array. This is by design. Complex Objects
2085
- // are atomic.
2086
- stype.complexProperties.forEach((cp) => {
2087
- if (cpHasOriginalValues(entity, cp)) {
2088
- let coOrCos = entity.getProperty(cp.name);
2089
- result[fn(cp.name, cp)] = core.map(coOrCos, function (co) {
2090
- return unwrapInstance(co, transformFn);
2091
- });
2092
- }
2093
- });
2094
- return result;
2095
- }
2096
- function cpHasOriginalValues(structuralObject, cp) {
2097
- let coOrCos = structuralObject.getProperty(cp.name);
2098
- if (cp.isScalar) {
2099
- return coHasOriginalValues(coOrCos);
2100
- }
2101
- else {
2102
- // this occurs when a nonscalar co array has had cos added or removed.
2103
- if (coOrCos._origValues)
2104
- return true;
2105
- return coOrCos.some(function (co) {
2106
- return coHasOriginalValues(co);
2107
- });
2108
- }
2109
- }
2110
- function executeQueryLocallyCore(em, query) {
2111
- assertParam(query, "query").isInstanceOf(EntityQuery).check();
2112
- let metadataStore = em.metadataStore;
2113
- let entityType = query._getFromEntityType(metadataStore, true);
2114
- // there may be multiple groups is this is a base entity type.
2115
- let groups = findOrCreateEntityGroups(em, entityType);
2116
- // filter then order then skip then take
2117
- let filterFunc = query.wherePredicate && query.wherePredicate.toFunction({ entityType: entityType });
2118
- let queryOptions = QueryOptions.resolve([query.queryOptions, em.queryOptions, QueryOptions.defaultInstance]);
2119
- let includeDeleted = queryOptions.includeDeleted === true;
2120
- let newFilterFunc = function (entity) {
2121
- return entity && (includeDeleted || !entity.entityAspect.entityState.isDeleted()) && (filterFunc ? filterFunc(entity) : true);
2122
- };
2123
- let result = [];
2124
- // TODO: mapMany
2125
- groups.forEach((group) => {
2126
- let entities = group._entities.filter(newFilterFunc);
2127
- if (entities.length) {
2128
- result = result.length ? result.concat(entities) : entities;
2129
- }
2130
- });
2131
- let orderByComparer = query.orderByClause && query.orderByClause.getComparer(entityType);
2132
- if (orderByComparer) {
2133
- result.sort(orderByComparer);
2134
- }
2135
- let inlineCount = query.inlineCountEnabled ? result.length : undefined;
2136
- let skipCount = query.skipCount;
2137
- if (skipCount) {
2138
- result = result.slice(skipCount);
2139
- }
2140
- let takeCount = query.takeCount;
2141
- if (takeCount) {
2142
- result = result.slice(0, takeCount);
2143
- }
2144
- let selectClause = query.selectClause;
2145
- if (selectClause) {
2146
- let selectFn = selectClause.toFunction();
2147
- result = result.map(selectFn);
2148
- }
2149
- return { results: result, inlineCount: inlineCount };
2150
- }
2151
- function coHasOriginalValues(co) {
2152
- // next line checks all non complex properties of the co.
2153
- if (!core.isEmpty(co.complexAspect.originalValues))
2154
- return true;
2155
- // now need to recursively check each of the cps
2156
- return co.complexType.complexProperties.some(function (cp) {
2157
- return cpHasOriginalValues(co, cp);
2158
- });
2159
- }
2160
- function getSerializerFn(stype) {
2161
- return stype.serializerFn || (stype.metadataStore && stype.metadataStore.serializerFn);
2162
- }
2163
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZW50aXR5LW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLElBQUksRUFBMkIsTUFBTSxRQUFRLENBQUM7QUFDdkQsT0FBTyxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDdEMsT0FBTyxFQUFFLFlBQVksRUFBcUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNsSCxPQUFPLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBZSxZQUFZLEVBQXNCLG9CQUFvQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkksT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsWUFBWSxFQUFHLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDN0MsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDN0UsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JB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QUFLLENBQUMsU0FBUyxDQUFDLENBQUM7S0FDbEM7SUFDRCxJQUFJLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO0lBQ2hDLElBQUksU0FBUyxFQUFFO1FBQ2IsTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0tBQ3JDO0lBRUQsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQztJQUN0QyxJQUFJLFlBQVksRUFBRTtRQUNoQixJQUFJLFFBQVEsR0FBRyxZQUFZLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDekMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7S0FDL0I7SUFDRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQUM7QUFDdkQsQ0FBQztBQUVELFNBQVMsbUJBQW1CLENBQUMsRUFBaUI7SUFDNUMseURBQXlEO0lBQ3pELElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsY0FBYyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDaEUsZ0RBQWdEO0lBQ2hELE9BQU8sRUFBRSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFO1FBQ3ZELE9BQU8sbUJBQW1CLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLEtBQStCO0lBQ3RELE9BQU8sS0FBSyxDQUFDLFlBQVksSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLElBQUksS0FBSyxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUN6RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGF0YVNlcnZpY2VBZGFwdGVyIH0gZnJvbSAnLi9pbnRlcmZhY2UtcmVnaXN0cnknO1xyXG5pbXBvcnQgeyBjb3JlLCBDYWxsYmFjaywgRXJyb3JDYWxsYmFjayB9IGZyb20gJy4vY29yZSc7XHJcbmltcG9ydCB7IGFzc2VydFBhcmFtLCBhc3NlcnRDb25maWcgfSBmcm9tICcuL2Fzc2VydC1wYXJhbSc7XHJcbmltcG9ydCB7IGNvbmZpZyB9IGZyb20gJy4vY29uZmlnJztcclxuaW1wb3J0IHsgQnJlZXplRXZlbnQgfSBmcm9tICcuL2V2ZW50JztcclxuaW1wb3J0IHsgRW50aXR5QXNwZWN0LCBFbnRpdHksIENvbXBsZXhPYmplY3QsIFN0cnVjdHVyYWxPYmplY3QsIFByb3BlcnR5Q2hhbmdlZEV2ZW50QXJncyB9IGZyb20gJy4vZW50aXR5LWFzcGVjdCc7XHJcbmltcG9ydCB7IE1ldGFkYXRhU3RvcmUsIEVudGl0eVR5cGUsIENvbXBsZXhUeXBlLCBEYXRhUHJvcGVydHksIE5hdmlnYXRpb25Qcm9wZXJ0eSwgQXV0b0dlbmVyYXRlZEtleVR5cGUgfSBmcm9tICcuL2VudGl0eS1tZXRhZGF0YSc7XHJcbmltcG9ydCB7IEVudGl0eUtleSB9IGZyb20gJy4vZW50aXR5LWtleSc7XHJcbmltcG9ydCB7IEVudGl0eUFjdGlvbiAgfSBmcm9tICcuL2VudGl0eS1hY3Rpb24nO1xyXG5pbXBvcnQgeyBFbnRpdHlTdGF0ZSB9IGZyb20gJy4vZW50aXR5LXN0YXRlJztcclxuaW1wb3J0IHsgRGF0YVNlcnZpY2UgfSBmcm9tICcuL2RhdGEtc2VydmljZSc7XHJcbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi9kYXRhLXR5cGUnO1xyXG5pbXBvcnQgeyBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tICcuL3ZhbGlkYXRlJztcclxuaW1wb3J0IHsgVmFsaWRhdGlvbk9wdGlvbnMgfSBmcm9tICcuL3ZhbGlkYXRpb24tb3B0aW9ucyc7XHJcbmltcG9ydCB7IFF1ZXJ5T3B0aW9ucywgTWVyZ2VTdHJhdGVneSwgRmV0Y2hTdHJhdGVneSB9IGZyb20gJy4vcXVlcnktb3B0aW9ucyc7XHJcbmltcG9ydCB7IFNhdmVPcHRpb25zIH0gZnJvbSAnLi9zYXZlLW9wdGlvbnMnO1xyXG5pbXBvcnQgeyBLZXlHZW5lcmF0b3IgfSBmcm9tICcuL2tleS1nZW5lcmF0b3InO1xyXG5pbXBvcnQgeyBFbnRpdHlHcm91cCB9IGZyb20gJy4vZW50aXR5LWdyb3VwJztcclxuaW1wb3J0IHsgTWFwcGluZ0NvbnRleHQgfSBmcm9tICcuL21hcHBpbmctY29udGV4dCc7XHJcbmltcG9ydCB7IEVudGl0eVF1ZXJ5IH0gZnJvbSAnLi9lbnRpdHktcXVlcnknO1xyXG5pbXBvcnQgeyBVbmF0dGFjaGVkQ2hpbGRyZW5NYXAgfSBmcm9tICcuL3VuYXR0YWNoZWQtY2hpbGRyZW4tbWFwJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSHR0cFJlc3BvbnNlIHtcclxuICBjb25maWc6IGFueTtcclxuICBkYXRhOiBhbnk7XHJcbiAgZXJyb3I/OiBhbnk7XHJcbiAgc2F2ZUNvbnRleHQ/OiBhbnk7XHJcbiAgc3RhdHVzOiBudW1iZXI7XHJcbiAgZ2V0SGVhZGVycyhoZWFkZXJOYW1lOiBzdHJpbmcpOiBzdHJpbmc7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSW1wb3J0UmVzdWx0IHtcclxuICBlbnRpdGllczogRW50aXR5W107XHJcbiAgdGVtcEtleU1hcHBpbmc6IElUZW1wS2V5TWFwO1xyXG59XHJcblxyXG4vLyBzdWJjbGFzc2VzIG9mIEVycm9yXHJcblxyXG4vKiogQmFzZSBzaGFwZSBvZiBhbnkgZXJyb3JzIHJldHVybmVkIGZyb20gdGhlIHNlcnZlci4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJFcnJvciBleHRlbmRzIEVycm9yIHtcclxuICBodHRwUmVzcG9uc2U6IEh0dHBSZXNwb25zZTtcclxuICBzdGF0dXM6IG51bWJlcjtcclxuICBtZXNzYWdlOiBzdHJpbmc7XHJcbiAgc3RhdHVzVGV4dD86IHN0cmluZztcclxuICBib2R5PzogYW55O1xyXG4gIHVybD86IHN0cmluZztcclxufVxyXG5cclxuLyoqIFNoYXBlIG9mIGEgc2F2ZSBlcnJvciByZXR1cm5lZCBmcm9tIHRoZSBzZXJ2ZXIuIFxyXG5Gb3IgdXNlIGJ5IGJyZWV6ZSBwbHVnaW4gYXV0aG9ycyBvbmx5LiBUaGUgY2xhc3MgaXMgZm9yIHVzZSBpbiBidWlsZGluZyBhIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dIGltcGxlbWVudGF0aW9uLiBcclxuQGFkYXB0ZXIgKHNlZSBbW0lEYXRhU2VydmljZUFkYXB0ZXJdXSkgICAgXHJcbkBoaWRkZW4gQGludGVybmFsIFxyXG4qL1xyXG5leHBvcnQgaW50ZXJmYWNlIFNhdmVFcnJvckZyb21TZXJ2ZXIgZXh0ZW5kcyBTZXJ2ZXJFcnJvciB7XHJcbiAgZW50aXR5RXJyb3JzOiBFbnRpdHlFcnJvckZyb21TZXJ2ZXJbXTtcclxufVxyXG5cclxuLyoqIFNoYXBlIG9mIGEgc2F2ZSBlcnJvciB3aGVuIHJldHVybmVkIHRvIHRoZSBjbGllbnQuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2F2ZUVycm9yIGV4dGVuZHMgU2VydmVyRXJyb3Ige1xyXG4gIGVudGl0eUVycm9yczogRW50aXR5RXJyb3JbXTtcclxufVxyXG5cclxuLy8gbm90IHN1YmNsYXNzZXMgb2YgRXJyb3JcclxuLyoqIFxyXG5Gb3IgdXNlIGJ5IGJyZWV6ZSBwbHVnaW4gYXV0aG9ycyBvbmx5LiBUaGUgY2xhc3MgaXMgZm9yIHVzZSBpbiBidWlsZGluZyBhIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dIGltcGxlbWVudGF0aW9uLiBcclxuQGFkYXB0ZXIgKHNlZSBbW0lEYXRhU2VydmljZUFkYXB0ZXJdXSkgICAgXHJcbkBoaWRkZW4gQGludGVybmFsIFxyXG4qL1xyXG5leHBvcnQgaW50ZXJmYWNlIEVudGl0eUVycm9yRnJvbVNlcnZlciB7XHJcbiAgZW50aXR5VHlwZU5hbWU6IHN0cmluZztcclxuICBrZXlWYWx1ZXM6IGFueVtdO1xyXG5cclxuICBlcnJvck5hbWU6IHN0cmluZztcclxuICBlcnJvck1lc3NhZ2U6IHN0cmluZztcclxuICBwcm9wZXJ0eU5hbWU6IHN0cmluZztcclxuICBjdXN0b20/OiBhbnk7XHJcbn1cclxuXHJcbi8qKiBTaGFwZSBvZiBhbiBlcnJvciBvbiBhIHNwZWNpZmljIGVudGl0eS4gIFBhcnQgb2YgYSBbW0lTYXZlRXJyb3JdXSAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEVudGl0eUVycm9yIHtcclxuICBlbnRpdHk6IEVudGl0eTtcclxuICBlcnJvck5hbWU6IHN0cmluZztcclxuICBlcnJvck1lc3NhZ2U6IHN0cmluZztcclxuICBwcm9wZXJ0eU5hbWU6IHN0cmluZztcclxuICBpc1NlcnZlckVycm9yOiBib29sZWFuO1xyXG4gIGN1c3RvbT86IGFueTtcclxufVxyXG5cclxuLyoqIFRoZSBzaGFwZSBvZiB0aGUgUHJvbWlzZSByZXR1cm5lZCBieSBhbiBbW0VudGl0eU1hbmFnZXIuZXhlY3V0ZVF1ZXJ5XV0gY2FsbC4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBRdWVyeVJlc3VsdCB7XHJcbiAgLyoqIFRvcCBsZXZlbCBlbnRpdGllcyByZXR1cm5lZC4gIEV4Y2x1ZGVzIGVudGl0aWVzIHRoYXQgYXJlIERlbGV0ZWQuICovXHJcbiAgcmVzdWx0czogYW55W107XHJcbiAgLyoqIFF1ZXJ5IHRoYXQgd2FzIGV4ZWN1dGVkICovXHJcbiAgcXVlcnk6IEVudGl0eVF1ZXJ5IHwgc3RyaW5nO1xyXG4gIC8qKiBFbnRpdHlNYW5hZ2VyIHRoYXQgZXhlY3V0ZWQgdGhlIHF1ZXJ5ICovXHJcbiAgZW50aXR5TWFuYWdlcj86IEVudGl0eU1hbmFnZXI7XHJcbiAgLyoqIFRvdGFsIG51bWJlciBvZiByZXN1bHRzIGF2YWlsYWJsZSBvbiB0aGUgc2VydmVyICovXHJcbiAgaW5saW5lQ291bnQ/OiBudW1iZXI7XHJcbiAgLyoqIEFsbCBlbnRpdGllcyByZXR1cm5lZCBieSB0aGUgcXVlcnkuICBEaWZmZXJzIGZyb20gYHJlc3VsdHNgIHdoZW4gYW4gZXhwYW5kIGlzIHVzZWQuICBJbmNsdWRlcyBlbnRpdGllcyB0aGF0IGFyZSBEZWxldGVkLiAqL1xyXG4gIHJldHJpZXZlZEVudGl0aWVzPzogRW50aXR5W107XHJcbiAgICAvKiogUmF3IHJlc3BvbnNlIGZyb20gdGhlIHNlcnZlciAqL1xyXG4gIGh0dHBSZXNwb25zZT86IEh0dHBSZXNwb25zZTtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBRdWVyeVN1Y2Nlc3NDYWxsYmFjayB7XHJcbiAgKGRhdGE6IFF1ZXJ5UmVzdWx0KTogdm9pZDtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBRdWVyeUVycm9yQ2FsbGJhY2sge1xyXG4gIChlcnJvcjogeyBxdWVyeTogRW50aXR5UXVlcnk7IGh0dHBSZXNwb25zZTogSHR0cFJlc3BvbnNlOyBlbnRpdHlNYW5hZ2VyOiBFbnRpdHlNYW5hZ2VyOyBtZXNzYWdlPzogc3RyaW5nOyBzdGFjaz86IHN0cmluZyB9KTogdm9pZDtcclxufVxyXG5cclxuLyoqIEtleSBtYXBwaW5nIGluZm9ybWF0aW9uIHJldHVybmVkIGFzIHBhcnQgb2YgYW4gW1tJU2F2ZVJlc3VsdF1dLiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEtleU1hcHBpbmcge1xyXG4gIGVudGl0eVR5cGVOYW1lOiBzdHJpbmc7XHJcbiAgdGVtcFZhbHVlOiBhbnk7XHJcbiAgcmVhbFZhbHVlOiBhbnk7XHJcbn1cclxuXHJcbmludGVyZmFjZSBJVGVtcEtleU1hcCB7XHJcbiAgW2luZGV4OiBzdHJpbmddOiBFbnRpdHlLZXk7XHJcbn1cclxuXHJcbi8qKiBDb25maWd1cmF0aW9uIGluZm8gdG8gYmUgcGFzc2VkIHRvIHRoZSBbW0VudGl0eU1hbmFnZXIuaW1wb3J0RW50aXRpZXNdXSBtZXRob2QgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJbXBvcnRDb25maWcge1xyXG4gIC8qKiBJZiB0cnVlLCBtZXJnZSBBZGRlZCBlbnRpdGllcyAod2l0aCB0ZW1wIGtleXMpIGFzIHdlbGwuICBUaGlzIGNhbiBiZSBkYW5nZXJvdXMuICovXHJcbiAgbWVyZ2VBZGRzPzogYm9vbGVhbjtcclxuICBtZXJnZVN0cmF0ZWd5PzogTWVyZ2VTdHJhdGVneTsgIFxyXG4gIG1ldGFkYXRhVmVyc2lvbkZuPzogKGFyZzogeyBtZXRhZGF0YVZlcnNpb246IGFueSwgbWV0YWRhdGFTdG9yZU5hbWU6IGFueSB9KSA9PiB2b2lkO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSW1wb3J0Q29uZmlnRXh0IGV4dGVuZHMgSW1wb3J0Q29uZmlnIHtcclxuICB0ZW1wS2V5TWFwPzogSVRlbXBLZXlNYXA7XHJcbn1cclxuXHJcbi8qKiBUaGUgc2hhcGUgb2YgdGhlIFByb21pc2UgcmV0dXJuZWQgYnkgYW4gW1tFbnRpdHlNYW5hZ2VyLnNhdmVDaGFuZ2VzXV0gY2FsbC4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBTYXZlUmVzdWx0IHtcclxuICBlbnRpdGllczogRW50aXR5W107XHJcbiAga2V5TWFwcGluZ3M6IEtleU1hcHBpbmdbXTtcclxuICBkZWxldGVkS2V5cz86IHsgZW50aXR5VHlwZU5hbWU6IHN0cmluZywga2V5VmFsdWVzOiBhbnlbXX1bXTtcclxuICBodHRwUmVzcG9uc2U/OiBIdHRwUmVzcG9uc2U7XHJcbn1cclxuXHJcbi8qKiBGb3IgdXNlIGJ5IGJyZWV6ZSBwbHVnaW4gYXV0aG9ycyBvbmx5LiBUaGUgY2xhc3MgaXMgZm9yIHVzZSBpbiBidWlsZGluZyBhIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dIGltcGxlbWVudGF0aW9uLiBcclxuQGFkYXB0ZXIgKHNlZSBbW0lEYXRhU2VydmljZUFkYXB0ZXJdXSkgICAgXHJcbkBoaWRkZW4gXHJcbiovXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2F2ZUNvbnRleHQge1xyXG4gIGVudGl0eU1hbmFnZXI6IEVudGl0eU1hbmFnZXI7XHJcbiAgZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlO1xyXG4gIHByb2Nlc3NTYXZlZEVudGl0aWVzOiAoc2F2ZVJlc3VsdDogU2F2ZVJlc3VsdCkgPT4gRW50aXR5W107XHJcbiAgcmVzb3VyY2VOYW1lOiBzdHJpbmc7XHJcbiAgYWRhcHRlcj86IERhdGFTZXJ2aWNlQWRhcHRlcjtcclxuICByb3V0ZVByZWZpeD86IHN0cmluZztcclxufVxyXG5cclxuLyoqIEZvciB1c2UgYnkgYnJlZXplIHBsdWdpbiBhdXRob3JzIG9ubHkuIFRoZSBjbGFzcyBpcyBmb3IgdXNlIGluIGJ1aWxkaW5nIGEgW1tJRGF0YVNlcnZpY2VBZGFwdGVyXV0gaW1wbGVtZW50YXRpb24uIFxyXG5AYWRhcHRlciAoc2VlIFtbSURhdGFTZXJ2aWNlQWRhcHRlcl1dKSAgICBcclxuQGhpZGRlbiBcclxuKi9cclxuZXhwb3J0IGludGVyZmFjZSBTYXZlQnVuZGxlIHtcclxuICBlbnRpdGllczogRW50aXR5W107XHJcbiAgc2F2ZU9wdGlvbnM6IFNhdmVPcHRpb25zO1xyXG59XHJcblxyXG4vKiogQ29uZmlndXJhdGlvbiBpbmZvIHRvIGJlIHBhc3NlZCB0byB0aGUgW1tFbnRpdHlNYW5hZ2VyXV0gY29uc3RydWN0b3IgKi9cclxuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlNYW5hZ2VyQ29uZmlnIHtcclxuICAvKiogVGhlIHNlcnZpY2UgbmFtZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAgKiovXHJcbiAgc2VydmljZU5hbWU/OiBzdHJpbmc7XHJcbiAgLyoqIFRoZSBEYXRhU2VydmljZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAqKi9cclxuICBkYXRhU2VydmljZT86IERhdGFTZXJ2aWNlO1xyXG4gIC8qKiBUaGUgW1tRdWVyeU9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiAgKiovXHJcbiAgcXVlcnlPcHRpb25zPzogUXVlcnlPcHRpb25zO1xyXG4gIC8qKiBUaGUgW1tTYXZlT3B0aW9uc11dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICoqL1xyXG4gIHNhdmVPcHRpb25zPzogU2F2ZU9wdGlvbnM7XHJcbiAgLyoqIFRoZSBbW1ZhbGlkYXRpb25PcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gICoqL1xyXG4gIHZhbGlkYXRpb25PcHRpb25zPzogVmFsaWRhdGlvbk9wdGlvbnM7XHJcbiAgLyoqIFRoZSBbW0tleUdlbmVyYXRvcl1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICoqL1xyXG4gIGtleUdlbmVyYXRvcj86IEtleUdlbmVyYXRvcjtcclxuICAvKiogVGhlIFtbS2V5R2VuZXJhdG9yXV0gY29uc3RydWN0b3IgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gKiovXHJcbiAga2V5R2VuZXJhdG9yQ3Rvcj86IHsgbmV3ICgpOiBLZXlHZW5lcmF0b3IgfTsgLy8gVE9ETzogcmV2aWV3IHRoaXNcclxuICAvKiogVGhlIFtbTWV0YWRhdGFTdG9yZV1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuICoqL1xyXG4gIG1ldGFkYXRhU3RvcmU/OiBNZXRhZGF0YVN0b3JlO1xyXG59XHJcblxyXG4vKiogVGhlIHNoYXBlIHJldHVybmVkIGJ5IGNhbGxiYWNrcyByZWdpc3RlcmVkIHdpdGggW1tFbnRpdHlNYW5hZ2VyLmVudGl0eUNoYW5nZWRdXSBldmVudCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEVudGl0eUNoYW5nZWRFdmVudEFyZ3Mge1xyXG4gIGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uO1xyXG4gIGVudGl0eT86IEVudGl0eTtcclxuICBhcmdzPzogUHJvcGVydHlDaGFuZ2VkRXZlbnRBcmdzO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkRXZlbnRBcmdzIHtcclxuICBlbnRpdHk6IEVudGl0eTsgXHJcbiAgYWRkZWQ6IFZhbGlkYXRpb25FcnJvcltdOyBcclxuICByZW1vdmVkOiBWYWxpZGF0aW9uRXJyb3JbXTtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBIYXNDaGFuZ2VzQ2hhbmdlZEV2ZW50QXJncyB7XHJcbiAgZW50aXR5TWFuYWdlcjogRW50aXR5TWFuYWdlcjsgXHJcbiAgaGFzQ2hhbmdlczogYm9vbGVhbjtcclxufVxyXG5cclxuLyoqXHJcbkluc3RhbmNlcyBvZiB0aGUgRW50aXR5TWFuYWdlciBjb250YWluIGFuZCBtYW5hZ2UgY29sbGVjdGlvbnMgb2YgZW50aXRpZXMsIGVpdGhlciByZXRyaWV2ZWQgZnJvbSBhIGJhY2tlbmQgZGF0YXN0b3JlIG9yIGNyZWF0ZWQgb24gdGhlIGNsaWVudC5cclxuKiovXHJcbmV4cG9ydCBjbGFzcyBFbnRpdHlNYW5hZ2VyIHtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBkZWNsYXJlIF8kdHlwZU5hbWU6IHN0cmluZzsgLy8gYWN0dWFsbHkgZGVmaW5lZCBvbiBwcm90b3R5cGVcclxuXHJcbiAgLyoqIFRoZSBzZXJ2aWNlIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBkZWNsYXJlIHNlcnZpY2VOYW1lOiBzdHJpbmc7XHJcbiAgLyoqIFRoZSBEYXRhU2VydmljZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGRlY2xhcmUgZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlO1xyXG4gIC8qKiBUaGUgW1tRdWVyeU9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGRlY2xhcmUgcXVlcnlPcHRpb25zOiBRdWVyeU9wdGlvbnM7XHJcbiAgLyoqIFRoZSBbW1NhdmVPcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBkZWNsYXJlIHNhdmVPcHRpb25zOiBTYXZlT3B0aW9ucztcclxuICAvKiogVGhlIFtbVmFsaWRhdGlvbk9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGRlY2xhcmUgdmFsaWRhdGlvbk9wdGlvbnM6IFZhbGlkYXRpb25PcHRpb25zO1xyXG4gIC8qKiBUaGUgW1tLZXlHZW5lcmF0b3JdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGRlY2xhcmUga2V5R2VuZXJhdG9yOiBLZXlHZW5lcmF0b3I7XHJcbiAgLyoqIFRoZSBbW0tleUdlbmVyYXRvcl1dIGNvbnN0cnVjdG9yIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eU1hbmFnZXIuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgZGVjbGFyZSBrZXlHZW5lcmF0b3JDdG9yOiB7IG5ldyAoKTogS2V5R2VuZXJhdG9yIH07IC8vIFRPRE86IHJldmlldyB0aGlzXHJcbiAgLyoqIFRoZSBbW01ldGFkYXRhU3RvcmVdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlNYW5hZ2VyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGRlY2xhcmUgbWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZTtcclxuICBkZWNsYXJlIGlzTG9hZGluZzogYm9vbGVhbjtcclxuICBkZWNsYXJlIGlzUmVqZWN0aW5nQ2hhbmdlczogYm9vbGVhbjtcclxuXHJcbiAgLy8gZXZlbnRzXHJcbiAgLyoqXHJcbiAgQSBbW0JyZWV6ZUV2ZW50XV0gdGhhdCBmaXJlcyB3aGVuZXZlciBhIGNoYW5nZSB0byBhbnkgZW50aXR5IGluIHRoaXMgRW50aXR5TWFuYWdlciBvY2N1cnMuIF9fUmVhZCBPbmx5X19cclxuXHJcbiAgQGV2ZW50QXJncyAtIFxyXG4gIC0gZW50aXR5QWN0aW9uIC0gVGhlIFtbRW50aXR5QWN0aW9uXV0gdGhhdCBvY2N1cmVkLlxyXG4gIC0gZW50aXR5IC0gVGhlIGVudGl0eSB0aGF0IGNoYW5nZWQuICBJZiB0aGlzIGlzIG51bGwsIHRoZW4gYWxsIGVudGl0aWVzIGluIHRoZSBlbnRpdHlNYW5hZ2VyIHdlcmUgYWZmZWN0ZWQuXHJcbiAgLSBhcmdzIC0gQWRkaXRpb25hbCBpbmZvcm1hdGlvbiBhYm91dCB0aGlzIGV2ZW50LiBUaGlzIHdpbGwgZGlmZmVyIGJhc2VkIG9uIHRoZSBlbnRpdHlBY3Rpb24uXHJcblxyXG4gID4gICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcigge3NlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIgfSk7XHJcbiAgPiAgICAgIGVtLmVudGl0eUNoYW5nZWQuc3Vic2NyaWJlKGZ1bmN0aW9uKGNoYW5nZUFyZ3MpIHtcclxuICA+ICAgICAgICAgIC8vIFRoaXMgY29kZSB3aWxsIGJlIGV4ZWN1dGVkIGFueSB0aW1lIGFueSBlbnRpdHkgd2l0aGluIHRoZSBlbnRpdHlNYW5hZ2VyIFxyXG4gID4gICAgICAgICAgLy8gaXMgYWRkZWQsIG1vZGlmaWVkLCBkZWxldGVkIG9yIGRldGFjaGVkIGZvciBhbnkgcmVhc29uLlxyXG4gID4gICAgICAgICAgbGV0IGFjdGlvbiA9IGNoYW5nZUFyZ3MuZW50aXR5QWN0aW9uO1xyXG4gID4gICAgICAgICAgbGV0IGVudGl0eSA9IGNoYW5nZUFyZ3MuZW50aXR5O1xyXG4gID4gICAgICAgICAgLy8gLi4gZG8gc29tZXRoaW5nIHRvIHRoaXMgZW50aXR5IHdoZW4gaXQgaXMgY2hhbmdlZC5cclxuICA+ICAgICAgfSk7XHJcbiAgPiAgfSk7XHJcbiAgQGV2ZW50XHJcbiAgKiovXHJcbiAgZW50aXR5Q2hhbmdlZDogQnJlZXplRXZlbnQ8RW50aXR5Q2hhbmdlZEV2ZW50QXJncz47XHJcblxyXG4gIC8qKlxyXG4gIEFuIFtbQnJlZXplRXZlbnRdXSB0aGF0IGZpcmVzIHdoZW5ldmVyIHZhbGlkYXRpb25FcnJvcnMgY2hhbmdlIGZvciBhbnkgZW50aXR5IGluIHRoaXMgRW50aXR5TWFuYWdlci4gX19SZWFkIE9ubHlfX1xyXG4gIEBldmVudEFyZ3MgLVxyXG4gICAgLSBlbnRpdHkgLSBUaGUgZW50aXR5IG9uIHdoaWNoIHRoZSB2YWxpZGF0aW9uIGVycm9ycyBoYXZlIGJlZW4gYWRkZWQgb3IgcmVtb3ZlZC5cclxuICAgIC0gYWRkZWQgLSBBbiBhcnJheSBjb250YWluaW5nIGFueSBuZXdseSBhZGRlZCBbW1ZhbGlkYXRpb25FcnJvcl1dc1xyXG4gICAgLSByZW1vdmVkIC0gQW4gYXJyYXkgY29udGFpbmluZyBhbnkgbmV3bHkgcmVtb3ZlZCBbW1ZhbGlkYXRpb25FcnJvcl1dcy4gVGhpcyBpcyB0aG9zZSBlcnJvcnMgdGhhdCBoYXZlIGJlZW4gJ2ZpeGVkJyAgXHJcblxyXG4gID4gICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcigge3NlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIgfSk7XHJcbiAgPiAgICAgIGVtLnZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkLnN1YnNjcmliZShmdW5jdGlvbihjaGFuZ2VBcmdzKSB7XHJcbiAgPiAgICAgICAgICAgICAgLy8gVGhpcyBjb2RlIHdpbGwgYmUgZXhlY3V0ZWQgYW55IHRpbWUgYW55IGVudGl0eSB3aXRoaW4gdGhlIGVudGl0eU1hbmFnZXIgZXhwZXJpZW5jZXMgYSBjaGFuZ2UgdG8gaXRzIHZhbGlkYXRpb25FcnJvcnMgY29sbGVjdGlvbi5cclxuICA+ICAgICAgICAgICAgICBmdW5jdGlvbiAodmFsaWRhdGlvbkNoYW5nZUFyZ3MpIHtcclxuICA+ICAgICAgICAgICAgICAgICAgbGV0IGVudGl0eSA9PSB2YWxpZGF0aW9uQ2hhbmdlQXJncy5lbnRpdHk7XHJcbiAgPiAgICAgICAgICAgICAgICAgIGxldCBlcnJvcnNBZGRlZCA9IHZhbGlkYXRpb25DaGFuZ2VBcmdzLmFkZGVkO1xyXG4gID4gICAgICAgICAgICAgICAgICBsZXQgZXJyb3JzQ2xlYXJlZCA9IHZhbGlkYXRpb25DaGFuZ2VBcmdzLnJlbW92ZWQ7XHJcbiAgPiAgICAgICAgICAgICAgICAgIC8vIC4uLiBkbyBzb21ldGhpbmcgaW50ZXJlc3Rpbmcgd2l0aCB0aGUgb3JkZXIuXHJcbiAgPiAgICAgICAgICAgICAgfSk7XHJcbiAgPiAgICAgICAgICB9KTtcclxuICA+ICAgICAgfSk7XHJcbiAgQGV2ZW50XHJcbiAgKiovXHJcbiAgdmFsaWRhdGlvbkVycm9yc0NoYW5nZWQ6IEJyZWV6ZUV2ZW50PFZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkRXZlbnRBcmdzPjtcclxuXHJcbiAgLyoqXHJcbiAgQSBbW0JyZWV6ZUV2ZW50XV0gdGhhdCBmaXJlcyB3aGVuZXZlciBhbiBFbnRpdHlNYW5hZ2VyIHRyYW5zaXRpb25zIHRvIG9yIGZyb20gaGF2aW5nIGNoYW5nZXMuIF9fUmVhZCBPbmx5X19cclxuICBAZXZlbnRBcmdzIC1cclxuICAgIC0gZW50aXR5TWFuYWdlciAtIFRoZSBFbnRpdHlNYW5hZ2VyIHdob3NlICdoYXNDaGFuZ2VzJyBzdGF0dXMgaGFzIGNoYW5nZWQuXHJcbiAgICAtIGhhc0NoYW5nZXMgLSBXaGV0aGVyIG9yIG5vdCB0aGlzIEVudGl0eU1hbmFnZXIgaGFzIGNoYW5nZXMuXHJcblxyXG4gID4gICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcigge3NlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIgfSk7XHJcbiAgPiAgICAgIGVtLmhhc0NoYW5nZXNDaGFuZ2VkLnN1YnNjcmliZShmdW5jdGlvbihhcmdzKSB7XHJcbiAgPiAgICAgICAgICAgICAgbGV0IGhhc0NoYW5nZXNDaGFuZ2VkID0gYXJncy5oYXNDaGFuZ2VzO1xyXG4gID4gICAgICAgICAgICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gYXJncy5lbnRpdHlNYW5hZ2VyO1xyXG4gID4gICAgICAgICAgfSk7XHJcbiAgPiAgICAgIH0pO1xyXG4gIEBldmVudCBcclxuICAqKi9cclxuICBoYXNDaGFuZ2VzQ2hhbmdlZDogQnJlZXplRXZlbnQ8SGFzQ2hhbmdlc0NoYW5nZWRFdmVudEFyZ3M+O1xyXG5cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3BlbmRpbmdQdWJzPzogYW55W107IC8vIFRPRE86IHJlZmluZSBsYXRlclxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9oYXNDaGFuZ2VzQWN0aW9uPzogKCgpID0+IGJvb2xlYW4pOyAvLyBUT0RPIHJlZmluZSBsYXRlclxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9oYXNDaGFuZ2VzOiBib29sZWFuO1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9lbnRpdHlHcm91cE1hcDogeyBbaW5kZXg6IHN0cmluZ106IEVudGl0eUdyb3VwIH07XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VuYXR0YWNoZWRDaGlsZHJlbk1hcDogVW5hdHRhY2hlZENoaWxkcmVuTWFwO1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9pbktleUZpeHVwOiBib29sZWFuO1xyXG5cclxuICBoZWxwZXIgPSB7XHJcbiAgICB1bndyYXBJbnN0YW5jZTogdW53cmFwSW5zdGFuY2UsXHJcbiAgICB1bndyYXBPcmlnaW5hbFZhbHVlczogdW53cmFwT3JpZ2luYWxWYWx1ZXMsXHJcbiAgICB1bndyYXBDaGFuZ2VkVmFsdWVzOiB1bndyYXBDaGFuZ2VkVmFsdWVzXHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgRW50aXR5TWFuYWdlciBjb25zdHJ1Y3Rvci5cclxuXHJcbiAgQXQgaXRzIG1vc3QgYmFzaWMgYW4gRW50aXR5TWFuYWdlciBjYW4gYmUgY29uc3RydWN0ZWQgd2l0aCBqdXN0IGEgc2VydmljZSBuYW1lXHJcbiAgPiAgICAgbGV0IGVudGl0eU1hbmFnZXIgPSBuZXcgRW50aXR5TWFuYWdlciggXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiKTtcclxuXHJcbiAgVGhpcyBpcyB0aGUgc2FtZSBhcyBjYWxsaW5nIGl0IHdpdGggdGhlIGZvbGxvd2luZyBjb25maWd1cmF0aW9uIG9iamVjdFxyXG4gID4gICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gbmV3IEVudGl0eU1hbmFnZXIoIHtzZXJ2aWNlTmFtZTogXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiIH0pO1xyXG5cclxuICBVc3VhbGx5IGhvd2V2ZXIsIGNvbmZpZ3VyYXRpb24gb2JqZWN0cyB3aWxsIGNvbnRhaW4gbW9yZSB0aGFuIGp1c3QgdGhlICdzZXJ2aWNlTmFtZSc7XHJcbiAgPiAgICAgbGV0IG1ldGFkYXRhU3RvcmUgPSBuZXcgTWV0YWRhdGFTdG9yZSgpO1xyXG4gID4gICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gbmV3IEVudGl0eU1hbmFnZXIoIHtcclxuICA+ICAgICAgIHNlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIsXHJcbiAgPiAgICAgICBtZXRhZGF0YVN0b3JlOiBtZXRhZGF0YVN0b3JlXHJcbiAgPiAgICAgfSk7XHJcblxyXG4gIG9yXHJcbiAgPiAgICAgcmV0dXJuIG5ldyBRdWVyeU9wdGlvbnMoe1xyXG4gID4gICAgICAgICBtZXJnZVN0cmF0ZWd5OiBvYmosXHJcbiAgPiAgICAgICAgIGZldGNoU3RyYXRlZ3k6IHRoaXMuZmV0Y2hTdHJhdGVneVxyXG4gID4gICAgIH0pO1xyXG4gID4gICAgIGxldCBxdWVyeU9wdGlvbnMgPSBuZXcgUXVlcnlPcHRpb25zKHtcclxuICA+ICAgICAgICAgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneS5PdmVyd3JpdGVDaGFuZ2VzLFxyXG4gID4gICAgICAgICBmZXRjaFN0cmF0ZWd5OiBGZXRjaFN0cmF0ZWd5LkZyb21TZXJ2ZXJcclxuICA+ICAgICB9KTtcclxuICA+ICAgICBsZXQgdmFsaWRhdGlvbk9wdGlvbnMgPSBuZXcgVmFsaWRhdGlvbk9wdGlvbnMoe1xyXG4gID4gICAgICAgICB2YWxpZGF0ZU9uQXR0YWNoOiB0cnVlLFxyXG4gID4gICAgICAgICB2YWxpZGF0ZU9uU2F2ZTogdHJ1ZSxcclxuICA+ICAgICAgICAgdmFsaWRhdGVPblF1ZXJ5OiBmYWxzZVxyXG4gID4gICAgIH0pO1xyXG4gID4gICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gbmV3IEVudGl0eU1hbmFnZXIoe1xyXG4gID4gICAgICAgICBzZXJ2aWNlTmFtZTogXCJicmVlemUvTm9ydGh3aW5kSUJNb2RlbFwiLFxyXG4gID4gICAgICAgICBxdWVyeU9wdGlvbnM6IHF1ZXJ5T3B0aW9ucyxcclxuICA+ICAgICAgICAgdmFsaWRhdGlvbk9wdGlvbnM6IHZhbGlkYXRpb25PcHRpb25zXHJcbiAgPiAgICAgfSk7XHJcbiAgQHBhcmFtIGVtQ29uZmlnIC0gQ29uZmlndXJhdGlvbiBzZXR0aW5ncyBvciBhIHNlcnZpY2UgbmFtZS4gIFxyXG4gICoqL1xyXG4gIGNvbnN0cnVjdG9yKGVtQ29uZmlnPzogRW50aXR5TWFuYWdlckNvbmZpZyB8IHN0cmluZykge1xyXG5cclxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgRW50aXR5TWFuYWdlciBjdG9yIGhhcyBhIHNpbmdsZSBvcHRpb25hbCBhcmd1bWVudCB0aGF0IGlzIGVpdGhlciBhICdzZXJ2aWNlTmFtZScgb3IgYSBjb25maWd1cmF0aW9uIG9iamVjdC5cIik7XHJcbiAgICB9XHJcbiAgICBsZXQgY29uZmlnOiBFbnRpdHlNYW5hZ2VyQ29uZmlnO1xyXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgY29uZmlnID0geyBzZXJ2aWNlTmFtZTogXCJcIiB9O1xyXG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZW1Db25maWcgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIGNvbmZpZyA9IHsgc2VydmljZU5hbWU6IGVtQ29uZmlnIH07XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25maWcgPSBlbUNvbmZpZyB8fCB7fTtcclxuICAgIH1cclxuXHJcbiAgICBFbnRpdHlNYW5hZ2VyLl91cGRhdGVXaXRoQ29uZmlnKHRoaXMsIGNvbmZpZywgdHJ1ZSk7XHJcblxyXG4gICAgdGhpcy5lbnRpdHlDaGFuZ2VkID0gbmV3IEJyZWV6ZUV2ZW50KFwiZW50aXR5Q2hhbmdlZFwiLCB0aGlzKTtcclxuICAgIHRoaXMudmFsaWRhdGlvbkVycm9yc0NoYW5nZWQgPSBuZXcgQnJlZXplRXZlbnQoXCJ2YWxpZGF0aW9uRXJyb3JzQ2hhbmdlZFwiLCB0aGlzKTtcclxuICAgIHRoaXMuaGFzQ2hhbmdlc0NoYW5nZWQgPSBuZXcgQnJlZXplRXZlbnQoXCJoYXNDaGFuZ2VzQ2hhbmdlZFwiLCB0aGlzKTtcclxuXHJcbiAgICB0aGlzLmNsZWFyKCk7XHJcblxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgR2VuZXJhbCBwdXJwb3NlIHByb3BlcnR5IHNldCBtZXRob2QuICBBbnkgb2YgdGhlIHByb3BlcnRpZXMgaW4gdGhlIFtbRW50aXR5TWFuYWdlckNvbmZpZ11dXHJcbiAgbWF5IGJlIHNldC5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhIHByZXZpb3VzbHkgY3JlYXRlZCBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIC8vIHdoZXJlIHdlIHdhbnQgdG8gY2hhbmdlIHNvbWUgb2YgaXRzIHNldHRpbmdzLlxyXG4gID4gICAgICBlbTEuc2V0UHJvcGVydGllcygge1xyXG4gID4gICAgICAgICAgc2VydmljZU5hbWU6IFwiYnJlZXplL2Zvb1wiXHJcbiAgPiAgICAgIH0pO1xyXG4gIEBwYXJhbSBjb25maWcgLSBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgc2VsZWN0ZWQgcHJvcGVydGllcyBhbmQgdmFsdWVzIHRvIHNldC5cclxuICAqKi9cclxuICBzZXRQcm9wZXJ0aWVzKGNvbmZpZzogRW50aXR5TWFuYWdlckNvbmZpZykge1xyXG4gICAgRW50aXR5TWFuYWdlci5fdXBkYXRlV2l0aENvbmZpZyh0aGlzLCBjb25maWcsIGZhbHNlKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIHN0YXRpYyBfdXBkYXRlV2l0aENvbmZpZyhlbTogRW50aXR5TWFuYWdlciwgY29uZmlnOiBFbnRpdHlNYW5hZ2VyQ29uZmlnLCBpc0N0b3I6IGJvb2xlYW4pIHtcclxuICAgIGxldCBkZWZhdWx0UXVlcnlPcHRpb25zID0gaXNDdG9yID8gUXVlcnlPcHRpb25zLmRlZmF1bHRJbnN0YW5jZSA6IGVtLnF1ZXJ5T3B0aW9ucztcclxuICAgIGxldCBkZWZhdWx0U2F2ZU9wdGlvbnMgPSBpc0N0b3IgPyBTYXZlT3B0aW9ucy5kZWZhdWx0SW5zdGFuY2UgOiBlbS5zYXZlT3B0aW9ucztcclxuICAgIGxldCBkZWZhdWx0VmFsaWRhdGlvbk9wdGlvbnMgPSBpc0N0b3IgPyBWYWxpZGF0aW9uT3B0aW9ucy5kZWZhdWx0SW5zdGFuY2UgOiBlbS52YWxpZGF0aW9uT3B0aW9ucztcclxuXHJcbiAgICBsZXQgY29uZmlnUGFyYW0gPSBhc3NlcnRDb25maWcoY29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcInNlcnZpY2VOYW1lXCIpLmlzT3B0aW9uYWwoKS5pc1N0cmluZygpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiZGF0YVNlcnZpY2VcIikuaXNPcHRpb25hbCgpLmlzSW5zdGFuY2VPZihEYXRhU2VydmljZSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJxdWVyeU9wdGlvbnNcIikuaXNJbnN0YW5jZU9mKFF1ZXJ5T3B0aW9ucykuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KGRlZmF1bHRRdWVyeU9wdGlvbnMpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwic2F2ZU9wdGlvbnNcIikuaXNJbnN0YW5jZU9mKFNhdmVPcHRpb25zKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoZGVmYXVsdFNhdmVPcHRpb25zKVxyXG4gICAgICAud2hlcmVQYXJhbShcInZhbGlkYXRpb25PcHRpb25zXCIpLmlzSW5zdGFuY2VPZihWYWxpZGF0aW9uT3B0aW9ucykuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KGRlZmF1bHRWYWxpZGF0aW9uT3B0aW9ucylcclxuICAgICAgLndoZXJlUGFyYW0oXCJrZXlHZW5lcmF0b3JDdG9yXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCk7XHJcbiAgICBpZiAoaXNDdG9yKSB7XHJcbiAgICAgIGNvbmZpZ1BhcmFtID0gY29uZmlnUGFyYW1cclxuICAgICAgICAud2hlcmVQYXJhbShcIm1ldGFkYXRhU3RvcmVcIikuaXNJbnN0YW5jZU9mKE1ldGFkYXRhU3RvcmUpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChuZXcgTWV0YWRhdGFTdG9yZSgpKTtcclxuICAgIH1cclxuICAgIGNvbmZpZ1BhcmFtLmFwcGx5QWxsKGVtKTtcclxuXHJcbiAgICAvLyBpbnN1cmUgdGhhdCBlbnRpdHlNYW5hZ2VyJ3Mgb3B0aW9ucyB2ZXJzaW9ucyBhcmUgY29tcGxldGVseSBwb3B1bGF0ZWRcclxuICAgIGNvcmUudXBkYXRlV2l0aERlZmF1bHRzKGVtLnF1ZXJ5T3B0aW9ucywgZGVmYXVsdFF1ZXJ5T3B0aW9ucyk7XHJcbiAgICBjb3JlLnVwZGF0ZVdpdGhEZWZhdWx0cyhlbS5zYXZlT3B0aW9ucywgZGVmYXVsdFNhdmVPcHRpb25zKTtcclxuICAgIGNvcmUudXBkYXRlV2l0aERlZmF1bHRzKGVtLnZhbGlkYXRpb25PcHRpb25zLCBkZWZhdWx0VmFsaWRhdGlvbk9wdGlvbnMpO1xyXG5cclxuICAgIGlmIChjb25maWcuc2VydmljZU5hbWUpIHtcclxuICAgICAgZW0uZGF0YVNlcnZpY2UgPSBuZXcgRGF0YVNlcnZpY2Uoe1xyXG4gICAgICAgIHNlcnZpY2VOYW1lOiBlbS5zZXJ2aWNlTmFtZVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIGVtLnNlcnZpY2VOYW1lID0gZW0uZGF0YVNlcnZpY2UgJiYgZW0uZGF0YVNlcnZpY2Uuc2VydmljZU5hbWU7XHJcblxyXG4gICAgZW0ua2V5R2VuZXJhdG9yQ3RvciA9IGVtLmtleUdlbmVyYXRvckN0b3IgfHwgS2V5R2VuZXJhdG9yO1xyXG4gICAgaWYgKGlzQ3RvciB8fCBjb25maWcua2V5R2VuZXJhdG9yQ3Rvcikge1xyXG4gICAgICBlbS5rZXlHZW5lcmF0b3IgPSBuZXcgZW0ua2V5R2VuZXJhdG9yQ3RvcigpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgY3JlYXRlRW50aXR5KHR5cGVOYW1lOiBzdHJpbmcsIGluaXRpYWxWYWx1ZXM/OiBPYmplY3QsIGVudGl0eVN0YXRlPzogRW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3k/OiBNZXJnZVN0cmF0ZWd5KTogRW50aXR5O1xyXG4gIGNyZWF0ZUVudGl0eShlbnRpdHlUeXBlOiBFbnRpdHlUeXBlLCBpbml0aWFsVmFsdWVzPzogT2JqZWN0LCBlbnRpdHlTdGF0ZT86IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5PzogTWVyZ2VTdHJhdGVneSk6IEVudGl0eTtcclxuICAvKipcclxuICBDcmVhdGVzIGEgbmV3IGVudGl0eSBvZiBhIHNwZWNpZmllZCB0eXBlIGFuZCBvcHRpb25hbGx5IGluaXRpYWxpemVzIGl0LiBCeSBkZWZhdWx0IHRoZSBuZXcgZW50aXR5IGlzIGNyZWF0ZWQgd2l0aCBhbiBFbnRpdHlTdGF0ZSBvZiBBZGRlZFxyXG4gIGJ1dCB5b3UgY2FuIGFsc28gb3B0aW9uYWxseSBzcGVjaWZ5IGFuIEVudGl0eVN0YXRlLiAgQW4gRW50aXR5U3RhdGUgb2YgJ0RldGFjaGVkJyB3aWxsIGluc3VyZSB0aGF0IHRoZSBlbnRpdHkgaXMgY3JlYXRlZCBidXQgbm90IHlldCBhZGRlZFxyXG4gIHRvIHRoZSBFbnRpdHlNYW5hZ2VyLiBcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIC8vIGNyZWF0ZSBhbmQgYWRkIGFuIGVudGl0eTtcclxuICA+ICAgICAgbGV0IGVtcDEgPSBlbTEuY3JlYXRlRW50aXR5KFwiRW1wbG95ZWVcIik7XHJcbiAgPiAgICAgIC8vIGNyZWF0ZSBhbmQgYWRkIGFuIGluaXRpYWxpemVkIGVudGl0eTtcclxuICA+ICAgICAgbGV0IGVtcDIgPSBlbTEuY3JlYXRlRW50aXR5KFwiRW1wbG95ZWVcIiwgeyBsYXN0TmFtZTogXCJTbWl0aFwiLCBmaXJzdE5hbWU6IFwiSm9oblwiIH0pO1xyXG4gID4gICAgICAvLyBjcmVhdGUgYW5kIGF0dGFjaCAobm90IGFkZCkgYW4gaW5pdGlhbGl6ZWQgZW50aXR5XHJcbiAgPiAgICAgIGxldCBlbXAzID0gZW0xLmNyZWF0ZUVudGl0eShcIkVtcGxveWVlXCIsIHsgaWQ6IDQzNSwgbGFzdE5hbWU6IFwiU21pdGhcIiwgZmlyc3ROYW1lOiBcIkpvaG5cIiB9LCBFbnRpdHlTdGF0ZS5VbmNoYW5nZWQpO1xyXG4gID4gICAgICAvLyBjcmVhdGUgYnV0IGRvbid0IGF0dGFjaCBhbiBlbnRpdHk7XHJcbiAgPiAgICAgIGxldCBlbXA0ID0gZW0xLmNyZWF0ZUVudGl0eShcIkVtcGxveWVlXCIsIHsgaWQ6IDQzNSwgbGFzdE5hbWU6IFwiU21pdGhcIiwgZmlyc3ROYW1lOiBcIkpvaG5cIiB9LCBFbnRpdHlTdGF0ZS5EZXRhY2hlZCk7XHJcbiAgQHBhcmFtIHR5cGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIEVudGl0eVR5cGUgZm9yIHdoaWNoIGFuIGluc3RhbmNlIHNob3VsZCBiZSBjcmVhdGVkLlxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlIC0gVGhlIEVudGl0eVR5cGUgb2YgdGhlIHR5cGUgZm9yIHdoaWNoIGFuIGluc3RhbmNlIHNob3VsZCBiZSBjcmVhdGVkLlxyXG4gIEBwYXJhbSBpbml0aWFsVmFsdWVzIC0gKGRlZmF1bHQ9bnVsbCkgQ29uZmlndXJhdGlvbiBvYmplY3Qgb2YgdGhlIHByb3BlcnRpZXMgdG8gc2V0IGltbWVkaWF0ZWx5IGFmdGVyIGNyZWF0aW9uLlxyXG4gIEBwYXJhbSBlbnRpdHlTdGF0ZSAtIChkZWZhdWx0ID0gW1tFbnRpdHlTdGF0ZS5BZGRlZF1dKSBUaGUgRW50aXR5U3RhdGUgb2YgdGhlIGVudGl0eSBhZnRlciBiZWluZyBjcmVhdGVkIGFuZCBhZGRlZCB0byB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgQHBhcmFtIG1lcmdlU3RyYXRlZ3kgLSAoZGVmYXVsdCA9IFtbTWVyZ2VTdHJhdGVneS5EaXNhbGxvd2VkXV0pIC0gSG93IHRvIGhhbmRsZSBjb25mbGljdHMgaWYgYW4gZW50aXR5IHdpdGggdGhlIHNhbWUga2V5IGFscmVhZHkgZXhpc3RzIHdpdGhpbiB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgQHJldHVybiB7RW50aXR5fSBBIG5ldyBFbnRpdHkgb2YgdGhlIHNwZWNpZmllZCB0eXBlLiBcclxuICAqL1xyXG4gIGNyZWF0ZUVudGl0eShlbnRpdHlUeXBlOiBFbnRpdHlUeXBlIHwgc3RyaW5nLCBpbml0aWFsVmFsdWVzOiBPYmplY3QsIGVudGl0eVN0YXRlOiBFbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5VHlwZSwgXCJlbnRpdHlUeXBlXCIpLmlzU3RyaW5nKCkub3IoKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eVN0YXRlLCBcImVudGl0eVN0YXRlXCIpLmlzRW51bU9mKEVudGl0eVN0YXRlKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKG1lcmdlU3RyYXRlZ3ksIFwibWVyZ2VTdHJhdGVneVwiKS5pc0VudW1PZihNZXJnZVN0cmF0ZWd5KS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuXHJcbiAgICBsZXQgZXQgPSAodHlwZW9mIGVudGl0eVR5cGUgPT09IFwic3RyaW5nXCIpID8gdGhpcy5tZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShlbnRpdHlUeXBlKSBhcyBFbnRpdHlUeXBlIDogZW50aXR5VHlwZTtcclxuICAgIGVudGl0eVN0YXRlID0gZW50aXR5U3RhdGUgfHwgRW50aXR5U3RhdGUuQWRkZWQ7XHJcbiAgICBsZXQgZW50aXR5ID0ge30gYXMgRW50aXR5O1xyXG4gICAgY29yZS51c2luZyh0aGlzLCBcImlzTG9hZGluZ1wiLCB0cnVlLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIGVudGl0eSA9IGV0LmNyZWF0ZUVudGl0eShpbml0aWFsVmFsdWVzKTtcclxuICAgIH0pO1xyXG4gICAgaWYgKGVudGl0eVN0YXRlICE9PSBFbnRpdHlTdGF0ZS5EZXRhY2hlZCkge1xyXG4gICAgICBlbnRpdHkgPSB0aGlzLmF0dGFjaEVudGl0eShlbnRpdHksIGVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5KTtcclxuICAgIH1cclxuICAgIHJldHVybiBlbnRpdHk7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgaW1wb3J0RW50aXRpZXMoZXhwb3J0ZWRTdHJpbmc6IHN0cmluZywgY29uZmlnPzogSW1wb3J0Q29uZmlnKTogRW50aXR5TWFuYWdlcjtcclxuICBzdGF0aWMgaW1wb3J0RW50aXRpZXMoZXhwb3J0ZWREYXRhOiBPYmplY3QsIGNvbmZpZz86IEltcG9ydENvbmZpZyk6IEVudGl0eU1hbmFnZXI7XHJcbiAgLyoqXHJcbiAgQ3JlYXRlcyBhIG5ldyBFbnRpdHlNYW5hZ2VyIGFuZCBpbXBvcnRzIGEgcHJldmlvdXNseSBleHBvcnRlZCByZXN1bHQgaW50byBpdC5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoKTtcclxuICA+ICAgICAgLy8gY2FuIGJlIHN0b3JlZCB2aWEgdGhlIHdlYiBzdG9yYWdlIGFwaVxyXG4gID4gICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oXCJteUVudGl0eU1hbmFnZXJcIiwgYnVuZGxlKTtcclxuICA+ICAgICAgLy8gYXNzdW1lIHRoZSBjb2RlIGJlbG93IG9jY3VycyBpbiBhIGRpZmZlcmVudCBzZXNzaW9uLlxyXG4gID4gICAgICBsZXQgYnVuZGxlRnJvbVN0b3JhZ2UgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJteUVudGl0eU1hbmFnZXJcIik7XHJcbiAgPiAgICAgIC8vIGFuZCBpbXBvcnRlZFxyXG4gID4gICAgICBsZXQgZW0yID0gRW50aXR5TWFuYWdlci5pbXBvcnRFbnRpdGllcyhidW5kbGVGcm9tU3RvcmFnZSk7XHJcbiAgPiAgICAgIC8vIGVtMiB3aWxsIG5vdyBoYXZlIGEgY29tcGxldGUgY29weSBvZiB3aGF0IHdhcyBpbiBlbTFcclxuICBAcGFyYW0gZXhwb3J0ZWRTdHJpbmcgLSBUaGUgcmVzdWx0IG9mIGEgcHJldmlvdXMgJ2V4cG9ydEVudGl0aWVzJyBjYWxsIGFzIGEgc3RyaW5nXHJcbiAgQHBhcmFtIGV4cG9ydGVkRGF0YSAtIFRoZSByZXN1bHQgb2YgYSBwcmV2aW91cyAnZXhwb3J0RW50aXRpZXMnIGNhbGwgYXMgYW4gT2JqZWN0LlxyXG4gIEBwYXJhbSBjb25maWcgLSBBIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlxyXG4gIEBwYXJhbSBjb25maWcubWVyZ2VTdHJhdGVneSAtIEEgIFtbTWVyZ2VTdHJhdGVneV1dIHRvIHVzZSB3aGVuIFxyXG4gIG1lcmdpbmcgaW50byBhbiBleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gIEBwYXJhbSBjb25maWcubWV0YWRhdGFWZXJzaW9uRm4gLSBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgdHdvIGFyZ3VtZW50cyAodGhlIGN1cnJlbnQgbWV0YWRhdGFWZXJzaW9uIGFuZCB0aGUgaW1wb3J0ZWQgc3RvcmUncyAnbmFtZScpXHJcbiAgYW5kIG1heSBiZSB1c2VkIHRvIHBlcmZvcm0gdmVyc2lvbiBjaGVja2luZy5cclxuICBAcmV0dXJuIEEgbmV3IEVudGl0eU1hbmFnZXIuICBOb3RlIHRoYXQgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGlzIG1ldGhvZCBjYWxsIGlzIGRpZmZlcmVudCBmcm9tIHRoYXRcclxuICBwcm92aWRlZCBieSB0aGUgc2FtZSBuYW1lZCBtZXRob2Qgb24gYW4gRW50aXR5TWFuYWdlciBpbnN0YW5jZS4gVXNlIHRoYXQgbWV0aG9kIGlmIHlvdSBuZWVkIGFkZGl0aW9uYWwgaW5mb3JtYXRpb25cclxuICByZWdhcmRpbmcgdGhlIGltcG9ydGVkIGVudGl0aWVzLlxyXG4gICoqL1xyXG4gIHN0YXRpYyBpbXBvcnRFbnRpdGllcyhleHBvcnRlZDogc3RyaW5nIHwgT2JqZWN0LCBjb25maWc/OiBJbXBvcnRDb25maWcpIHtcclxuICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKCk7XHJcbiAgICBlbS5pbXBvcnRFbnRpdGllcyhleHBvcnRlZCwgY29uZmlnKTtcclxuICAgIHJldHVybiBlbTtcclxuICB9XHJcblxyXG4gIC8vIGluc3RhbmNlIG1ldGhvZHNcclxuXHJcbiAgLyoqXHJcbiAgQ2FsbHMgW1tFbnRpdHlBc3BlY3QuYWNjZXB0Q2hhbmdlc11dIG9uIGV2ZXJ5IGNoYW5nZWQgZW50aXR5IGluIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICAqKi9cclxuICBhY2NlcHRDaGFuZ2VzKCkge1xyXG4gICAgdGhpcy5nZXRDaGFuZ2VzKCkubWFwKGZ1bmN0aW9uIChlbnRpdHkpIHtcclxuICAgICAgcmV0dXJuIGVudGl0eS5lbnRpdHlBc3BlY3QuX2NoZWNrT3BlcmF0aW9uKFwiYWNjZXB0Q2hhbmdlc1wiKTtcclxuICAgIH0pLmZvckVhY2goZnVuY3Rpb24gKGFzcGVjdCkge1xyXG4gICAgICBhc3BlY3QuYWNjZXB0Q2hhbmdlcygpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBFeHBvcnRzIHNlbGVjdGVkIGVudGl0aWVzLCBhbGwgZW50aXRpZXMgb2Ygc2VsZWN0ZWQgdHlwZXMsIG9yIGFuIGVudGlyZSBFbnRpdHlNYW5hZ2VyIGNhY2hlLlxyXG5cclxuICBUaGlzIG1ldGhvZCB0YWtlcyBhIHNuYXBzaG90IG9mIGFuIEVudGl0eU1hbmFnZXIgdGhhdCBjYW4gYmUgc3RvcmVkIG9mZmxpbmUgb3IgaGVsZCBpbiBtZW1vcnkuXHJcbiAgVXNlIHRoZSBbW0VudGl0eU1hbmFnZXIuaW1wb3J0RW50aXRpZXNdXSBtZXRob2QgdG8gcmVzdG9yZSBvciBtZXJnZSB0aGUgc25hcHNob3RcclxuICBpbnRvIGFub3RoZXIgRW50aXR5TWFuYWdlciBhdCBzb21lIGxhdGVyIHRpbWUuXHJcbiAgPiAgICAgIC8vIGxldCBlbTEgYmUgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIC8vIGV4cG9ydCBldmVyeSBlbnRpdHkgaW4gZW0xLlxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoKTtcclxuICA+ICAgICAvLyBzYXZlIHRvIHRoZSBicm93c2VyJ3MgbG9jYWwgc3RvcmFnZVxyXG4gID4gICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2Uuc2V0SXRlbShcIm15RW50aXR5TWFuYWdlclwiLCBidW5kbGUpO1xyXG4gID4gICAgIC8vIGxhdGVyIHJldHJpZXZlIHRoZSBleHBvcnRcclxuICA+ICAgICBsZXQgYnVuZGxlRnJvbVN0b3JhZ2UgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJteUVudGl0eU1hbmFnZXJcIik7XHJcbiAgPiAgICAgLy8gaW1wb3J0IHRoZSByZXRyaWV2ZWQgZXhwb3J0IGJ1bmRsZSBpbnRvIGFub3RoZXIgbWFuYWdlclxyXG4gID4gICAgIGxldCBlbTIgPSBlbTEuY3JlYXRlRW1wdHlDb3B5KCk7XHJcbiAgPiAgICAgZW0yLmltcG9ydEVudGl0aWVzKGJ1bmRsZUZyb21TdG9yYWdlKTtcclxuICA+ICAgICAvLyBlbTIgbm93IGhhcyBhIGNvbXBsZXRlLCBmYWl0aGZ1bCBjb3B5IG9mIHRoZSBlbnRpdGllcyB0aGF0IHdlcmUgaW4gZW0xXHJcblxyXG4gIFlvdSBjYW4gYWxzbyBjb250cm9sIGV4YWN0bHkgd2hpY2ggZW50aXRpZXMgYXJlIGV4cG9ydGVkLlxyXG4gID4gICAgIC8vIGdldCBlbTEncyB1bnNhdmVkIGNoYW5nZXMgKGFuIGFycmF5KSBhbmQgZXhwb3J0IHRoZW0uXHJcbiAgPiAgICAgbGV0IGNoYW5nZXMgPSBlbTEuZ2V0Q2hhbmdlcygpO1xyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoY2hhbmdlcyk7XHJcbiAgPiAgICAgLy8gbWVyZ2UgdGhlc2UgZW50aXRpZXMgaW50byBlbTIgd2hpY2ggbWF5IGNvbnRhaW5zIHNvbWUgb2YgdGhlIHNhbWUgZW50aXRpZXMuXHJcbiAgPiAgICAgLy8gZG8gTk9UIG92ZXJ3cml0ZSB0aGUgZW50aXRpZXMgaW4gZW0yIGlmIHRoZXkgdGhlbXNlbHZlcyBoYXZlIHVuc2F2ZWQgY2hhbmdlcy5cclxuICA+ICAgICBlbTIuaW1wb3J0RW50aXRpZXMoYnVuZGxlLCB7IG1lcmdlU3RyYXRlZ3k6IE1lcmdlU3RyYXRlZ3kuUHJlc2VydmVDaGFuZ2VzfSApO1xyXG5cclxuICBNZXRhZGF0YSBhcmUgaW5jbHVkZWQgaW4gYW4gZXhwb3J0IGJ5IGRlZmF1bHQuIFlvdSBtYXkgd2FudCB0byBleGNsdWRlIHRoZSBtZXRhZGF0YVxyXG4gIGVzcGVjaWFsbHkgaWYgeW91J3JlIGV4cG9ydGluZyBqdXN0IGEgZmV3IGVudGl0aWVzIGZvciBsb2NhbCBzdG9yYWdlLlxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoYXJyYXlPZlNlbGVjdGVkRW50aXRpZXMsIHtpbmNsdWRlTWV0YWRhdGE6IGZhbHNlfSk7XHJcbiAgPiAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKFwiZ29vZFN0dWZmXCIsIGJ1bmRsZSk7XHJcblxyXG4gIFlvdSBtYXkgc3RpbGwgZXhwcmVzcyB0aGlzIG9wdGlvbiBhcyBhIGJvb2xlYW4gdmFsdWUgYWx0aG91Z2ggdGhpcyBvbGRlciBzeW50YXggaXMgZGVwcmVjYXRlZC5cclxuICA+ICAgICAvLyBFeGNsdWRlIHRoZSBtZXRhZGF0YSAoZGVwcmVjYXRlZCBzeW50YXgpXHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcyhhcnJheU9mU2VsZWN0ZWRFbnRpdGllcywgZmFsc2UpO1xyXG5cclxuICBZb3UgY2FuIGV4cG9ydCBhbGwgZW50aXRpZXMgb2Ygb25lIG9yIG1vcmUgc3BlY2lmaWVkIEVudGl0eVR5cGVzLlxyXG4gID4gICAgIC8vIEV4cG9ydCBhbGwgQ3VzdG9tZXIgYW5kIEVtcGxveWVlIGVudGl0aWVzIChhbmQgYWxzbyBleGNsdWRlIG1ldGFkYXRhKVxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoWydDdXN0b21lcicsICdFbXBsb3llZSddLCB7aW5jbHVkZU1ldGFkYXRhOiBmYWxzZX0pO1xyXG5cclxuICBBbGwgb2YgdGhlIGFib3ZlIGV4YW1wbGVzIHJldHVybiBhbiBleHBvcnQgYnVuZGxlIGFzIGEgc3RyaW5nIHdoaWNoIGlzIHRoZSBkZWZhdWx0IGZvcm1hdC5cclxuICBZb3UgY2FuIGV4cG9ydCB0aGUgYnVuZGxlIGFzIEpTT04gaWYgeW91IHByZWZlciBieSBzZXR0aW5nIHRoZSBgYXNTdHJpbmdgIG9wdGlvbiB0byBmYWxzZS5cclxuICA+ICAgICAvLyBFeHBvcnQgYWxsIEN1c3RvbWVyIGFuZCBFbXBsb3llZSBlbnRpdGllcyBhcyBKU09OIGFuZCBleGNsdWRlIHRoZSBtZXRhZGF0YVxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoWydDdXN0b21lcicsICdFbXBsb3llZSddLFxyXG4gID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge2FzU3RyaW5nOiBmYWxzZSwgaW5jbHVkZU1ldGFkYXRhOiBmYWxzZX0pO1xyXG4gID4gICAgIC8vIHN0b3JlIEpTT04gYnVuZGxlIHNvbWV3aGVyZSAuLi4gcGVyaGFwcyBpbmRleERiIC4uLiBhbmQgbGF0ZXIgaW1wb3J0IGFzIHdlIGRvIGhlcmUuXHJcbiAgPiAgICAgZW0yLmltcG9ydEVudGl0aWVzKGJ1bmRsZSk7XHJcbiAgQHBhcmFtIGVudGl0aWVzIC0gVGhlIGVudGl0aWVzIHRvIGV4cG9ydCBvciB0aGUgRW50aXR5VHlwZShzKSBvZiB0aGUgZW50aXRpZXMgdG8gZXhwb3J0O1xyXG4gICAgYWxsIGVudGl0aWVzIGFyZSBleHBvcnRlZCBpZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkIG9yIG51bGwuXHJcbiAgQHBhcmFtIGV4cG9ydENvbmZpZyAtIEV4cG9ydCBjb25maWd1cmF0aW9uIG9wdGlvbnMgb3IgYSBib29sZWFuXHJcbiAgICAtIGFzU3RyaW5nIC0gKGJvb2xlYW4pIC0gSWYgdHJ1ZSAoZGVmYXVsdCksIHJldHVybiBleHBvcnQgYnVuZGxlIGFzIGEgc3RyaW5nLlxyXG4gICAgLSBpbmNsdWRlTWV0YWRhdGEgLSAoYm9vbGVhbikgLSBJZiB0cnVlIChkZWZhdWx0KSwgaW5jbHVkZSBtZXRhZGF0YSBpbiB0aGUgZXhwb3J0IGJ1bmRsZS5cclxuICBAcmV0dXJuIFRoZSBleHBvcnQgYnVuZGxlIGVpdGhlciBzZXJpYWxpemVkIGFzIGEgc3RyaW5nIChkZWZhdWx0KSBvciBhcyBhIEpTT04gb2JqZWN0LlxyXG4gIFRoZSBidW5kbGUgY29udGFpbnMgdGhlIG1ldGFkYXRhICh1bmxlc3MgZXhjbHVkZWQpIGFuZCB0aGUgZW50aXR5IGRhdGEgZ3JvdXBlZCBieSB0eXBlLlxyXG4gIFRoZSBlbnRpdHkgZGF0YSBpbmNsdWRlIHByb3BlcnR5IHZhbHVlcywgY2hhbmdlLXN0YXRlLCBhbmQgdGVtcG9yYXJ5IGtleSBtYXBwaW5ncyAoaWYgYW55KS5cclxuXHJcbiAgVGhlIGV4cG9ydCBidW5kbGUgaW50ZXJuYWxzIGFyZSBkZWxpYmVyYXRlbHkgdW5kb2N1bWVudGVkLiAgVGhpcyBCcmVlemUtaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gb2YgZW50aXR5IGRhdGEgaXNcclxuICBzdWl0YWJsZSBmb3IgZXhwb3J0LCBzdG9yYWdlLCBhbmQgaW1wb3J0LiBUaGUgc2NoZW1hIGFuZCBjb250ZW50cyBvZiB0aGUgYnVuZGxlIG1heSBjaGFuZ2UgaW4gZnV0dXJlIHZlcnNpb25zIG9mIEJyZWV6ZS5cclxuICBNYW5pcHVsYXRlIGl0IGF0IHlvdXIgb3duIHJpc2sgd2l0aCBhcHByb3ByaWF0ZSBjYXV0aW9uLlxyXG4gICoqL1xyXG4gIGV4cG9ydEVudGl0aWVzKGVudGl0aWVzPzogRW50aXR5W10gfCBFbnRpdHlUeXBlW10gfCBzdHJpbmdbXSwgZXhwb3J0Q29uZmlnPzogeyBhc1N0cmluZz86IGJvb2xlYW4sIGluY2x1ZGVNZXRhZGF0YT86IGJvb2xlYW4gfSB8IGJvb2xlYW4pOiBzdHJpbmcgfCBPYmplY3Qge1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXRpZXMsIFwiZW50aXRpZXNcIikuaXNBcnJheSgpLmlzRW50aXR5KClcclxuICAgICAgLm9yKCkuaXNOb25FbXB0eUFycmF5KCkuaXNJbnN0YW5jZU9mKEVudGl0eVR5cGUpXHJcbiAgICAgIC5vcigpLmlzTm9uRW1wdHlBcnJheSgpLmlzU3RyaW5nKClcclxuICAgICAgLm9yKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcblxyXG4gICAgLy8gYXNzZXJ0UGFyYW0oZXhwb3J0Q29uZmlnLCBcImV4cG9ydENvbmZpZ1wiKS5pc09iamVjdCgpXHJcbiAgICAvLyAgIC5vcigpLmlzQm9vbGVhbigpXHJcbiAgICAvLyAgIC5vcigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG5cclxuICAgIGlmIChleHBvcnRDb25maWcgPT0gbnVsbCkge1xyXG4gICAgICBleHBvcnRDb25maWcgPSB7IGluY2x1ZGVNZXRhZGF0YTogdHJ1ZSwgYXNTdHJpbmc6IHRydWUgfTtcclxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGV4cG9ydENvbmZpZyA9PT0gJ2Jvb2xlYW4nKSB7IC8vIGRlcHJlY2F0ZWRcclxuICAgICAgZXhwb3J0Q29uZmlnID0geyBpbmNsdWRlTWV0YWRhdGE6IGV4cG9ydENvbmZpZywgYXNTdHJpbmc6IHRydWUgfTtcclxuICAgIH1cclxuXHJcbiAgICBhc3NlcnRDb25maWcoZXhwb3J0Q29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcImFzU3RyaW5nXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdCh0cnVlKVxyXG4gICAgICAud2hlcmVQYXJhbShcImluY2x1ZGVNZXRhZGF0YVwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQodHJ1ZSlcclxuICAgICAgLmFwcGx5QWxsKGV4cG9ydENvbmZpZyk7XHJcblxyXG4gICAgbGV0IGV4cG9ydEJ1bmRsZSA9IGV4cG9ydEVudGl0eUdyb3Vwcyh0aGlzLCBlbnRpdGllcyk7XHJcbiAgICBsZXQganNvbiA9IGNvcmUuZXh0ZW5kKHt9LCBleHBvcnRCdW5kbGUsIFtcInRlbXBLZXlzXCIsIFwiZW50aXR5R3JvdXBNYXBcIl0pO1xyXG5cclxuICAgIGlmIChleHBvcnRDb25maWcuaW5jbHVkZU1ldGFkYXRhKSB7XHJcbiAgICAgIGpzb24gPSBjb3JlLmV4dGVuZChqc29uLCB0aGlzLCBbXCJkYXRhU2VydmljZVwiLCBcInNhdmVPcHRpb25zXCIsIFwicXVlcnlPcHRpb25zXCIsIFwidmFsaWRhdGlvbk9wdGlvbnNcIl0pO1xyXG4gICAgICAoanNvbiBhcyBhbnkpLm1ldGFkYXRhU3RvcmUgPSB0aGlzLm1ldGFkYXRhU3RvcmUuZXhwb3J0TWV0YWRhdGEoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIChqc29uIGFzIGFueSkubWV0YWRhdGFWZXJzaW9uID0gTWV0YWRhdGFTdG9yZS5tZXRhZGF0YVZlcnNpb247XHJcbiAgICAgIChqc29uIGFzIGFueSkubWV0YWRhdGFTdG9yZU5hbWUgPSB0aGlzLm1ldGFkYXRhU3RvcmUubmFtZTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgcmVzdWx0ID0gZXhwb3J0Q29uZmlnLmFzU3RyaW5nID8gSlNPTi5zdHJpbmdpZnkoanNvbiwgbnVsbCwgY29uZmlnLnN0cmluZ2lmeVBhZCkgOiBqc29uO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIC8vIFRPRE86IHR5cGUgdGhlIHJldHVybiB2YWx1ZSB7IGVudGl0aWVzOiBlbnRpdGllc1RvTGluaywgdGVtcEtleU1hcHBpbmc6IHRlbXBLZXlNYXAgfVxyXG4gIGltcG9ydEVudGl0aWVzKGV4cG9ydGVkU3RyaW5nOiBzdHJpbmcsIGNvbmZpZz86IEltcG9ydENvbmZpZyk6IEltcG9ydFJlc3VsdDtcclxuICBpbXBvcnRFbnRpdGllcyhleHBvcnRlZERhdGE6IE9iamVjdCwgY29uZmlnPzogSW1wb3J0Q29uZmlnKTogSW1wb3J0UmVzdWx0O1xyXG4gIC8qKlxyXG4gIEltcG9ydHMgYSBwcmV2aW91c2x5IGV4cG9ydGVkIHJlc3VsdCBpbnRvIHRoaXMgRW50aXR5TWFuYWdlci5cclxuXHJcbiAgVGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gbWFrZSBhIGNvbXBsZXRlIGNvcHkgb2YgYW55IHByZXZpb3VzbHkgY3JlYXRlZCBlbnRpdHlNYW5hZ2VyLCBldmVuIGlmIGNyZWF0ZWRcclxuICBpbiBhIHByZXZpb3VzIHNlc3Npb24gYW5kIHN0b3JlZCBpbiBsb2NhbFN0b3JhZ2UuIFRoZSBzdGF0aWMgdmVyc2lvbiBvZiB0aGlzIG1ldGhvZCBwZXJmb3JtcyBhXHJcbiAgdmVyeSBzaW1pbGFyIHByb2Nlc3MuXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGJ1bmRsZSA9IGVtMS5leHBvcnRFbnRpdGllcygpO1xyXG4gID4gICAgIC8vIGJ1bmRsZSBjYW4gYmUgc3RvcmVkIGluIHdpbmRvdy5sb2NhbFN0b3JhZ2Ugb3IganVzdCBoZWxkIGluIG1lbW9yeS5cclxuICA+ICAgICBsZXQgZW0yID0gbmV3IEVudGl0eU1hbmFnZXIoe1xyXG4gID4gICAgICAgICBzZXJ2aWNlTmFtZTogZW0xLnNlcnZpY2VOYW1lLFxyXG4gID4gICAgICAgICBtZXRhZGF0YVN0b3JlOiBlbTEubWV0YWRhdGFTdG9yZVxyXG4gID4gICAgIH0pO1xyXG4gID4gICAgIGVtMi5pbXBvcnRFbnRpdGllcyhidW5kbGUpO1xyXG4gID4gICAgIC8vIGVtMiB3aWxsIG5vdyBoYXZlIGEgY29tcGxldGUgY29weSBvZiB3aGF0IHdhcyBpbiBlbTFcclxuXHJcbiAgSXQgY2FuIGFsc28gYmUgdXNlZCB0byBtZXJnZSB0aGUgY29udGVudHMgb2YgYSBwcmV2aW91c2x5IGNyZWF0ZWQgRW50aXR5TWFuYWdlciB3aXRoIGFuXHJcbiAgZXhpc3RpbmcgRW50aXR5TWFuYWdlciB3aXRoIGNvbnRyb2wgb3ZlciBob3cgdGhlIHR3byBhcmUgbWVyZ2VkLlxyXG4gID4gICAgIGxldCBidW5kbGUgPSBlbTEuZXhwb3J0RW50aXRpZXMoKTtcclxuICA+ICAgICAvLyBhc3N1bWUgZW0yIGlzIGFub3RoZXIgZW50aXR5TWFuYWdlciBjb250YWluaW5nIHNvbWUgb2YgdGhlIHNhbWUgZW50aXRpZXMgcG9zc2libHkgd2l0aCBtb2RpZmljYXRpb25zLlxyXG4gID4gICAgIGVtMi5pbXBvcnRFbnRpdGllcyhidW5kbGUsIHsgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneS5QcmVzZXJ2ZUNoYW5nZXN9ICk7XHJcbiAgPiAgICAgLy8gZW0yIHdpbGwgbm93IGNvbnRhaW4gYWxsIG9mIHRoZSBlbnRpdGllcyBmcm9tIGJvdGggZW0xIGFuZCBlbTIuICBBbnkgZW0yIGVudGl0aWVzIHdpdGggcHJldmlvdXNseVxyXG4gID4gICAgIC8vIG1hZGUgbW9kaWZpY2F0aW9ucyB3aWxsIG5vdCBoYXZlIGJlZW4gdG91Y2hlZCwgYnV0IGFsbCBvdGhlciBlbnRpdGllcyBmcm9tIGVtMSB3aWxsIGhhdmUgYmVlbiBpbXBvcnRlZC5cclxuICBAcGFyYW0gZXhwb3J0ZWRTdHJpbmcgLSBUaGUgcmVzdWx0IG9mIGEgcHJldmlvdXMgJ2V4cG9ydCcgY2FsbC5cclxuICBAcGFyYW0gaW1wb3J0Q29uZmlnIC0gQSBjb25maWd1cmF0aW9uIG9iamVjdC5cclxuICBAcGFyYW0gaW1wb3J0Q29uZmlnLm1lcmdlU3RyYXRlZ3kgLSAgQSBbW01lcmdlU3RyYXRlZ3ldXSB0byB1c2Ugd2hlblxyXG4gIG1lcmdpbmcgaW50byBhbiBleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gIEBwYXJhbSBpbXBvcnRDb25maWcubWV0YWRhdGFWZXJzaW9uRm4gLSBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgdHdvIGFyZ3VtZW50cyAodGhlIGN1cnJlbnQgbWV0YWRhdGFWZXJzaW9uIGFuZCB0aGUgaW1wb3J0ZWQgc3RvcmUncyAnbmFtZScpXHJcbiAgYW5kIG1heSBiZSB1c2VkIHRvIHBlcmZvcm0gdmVyc2lvbiBjaGVja2luZy5cclxuICBAcmV0dXJuIHJlc3VsdCBcclxuICAgIC0gcmVzdWx0LmVudGl0aWVzIHtBcnJheSBvZiBFbnRpdGllc30gVGhlIGVudGl0aWVzIHRoYXQgd2VyZSBpbXBvcnRlZC5cclxuICAgIC0gcmVzdWx0LnRlbXBLZXlNYXAge09iamVjdH0gTWFwcGluZyBmcm9tIG9yaWdpbmFsIEVudGl0eUtleSBpbiB0aGUgaW1wb3J0IGJ1bmRsZSB0byBpdHMgY29ycmVzcG9uZGluZyBFbnRpdHlLZXkgaW4gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gICoqL1xyXG4gIGltcG9ydEVudGl0aWVzKGV4cG9ydGVkOiBzdHJpbmcgfCBPYmplY3QsIGltcG9ydENvbmZpZz86IEltcG9ydENvbmZpZykge1xyXG4gICAgaW1wb3J0Q29uZmlnID0gaW1wb3J0Q29uZmlnIHx8IHt9O1xyXG4gICAgYXNzZXJ0Q29uZmlnKGltcG9ydENvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJtZXJnZVN0cmF0ZWd5XCIpLmlzRW51bU9mKE1lcmdlU3RyYXRlZ3kpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdCh0aGlzLnF1ZXJ5T3B0aW9ucy5tZXJnZVN0cmF0ZWd5KVxyXG4gICAgICAud2hlcmVQYXJhbShcIm1ldGFkYXRhVmVyc2lvbkZuXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJtZXJnZUFkZHNcIikuaXNCb29sZWFuKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC5hcHBseUFsbChpbXBvcnRDb25maWcpO1xyXG5cclxuICAgIGxldCBqc29uID0gKHR5cGVvZiBleHBvcnRlZCA9PT0gXCJzdHJpbmdcIikgPyBKU09OLnBhcnNlKGV4cG9ydGVkKSA6IGV4cG9ydGVkO1xyXG4gICAgaWYgKGpzb24ubWV0YWRhdGFTdG9yZSkge1xyXG4gICAgICB0aGlzLm1ldGFkYXRhU3RvcmUuaW1wb3J0TWV0YWRhdGEoanNvbi5tZXRhZGF0YVN0b3JlKTtcclxuICAgICAgLy8gdGhlIHx8IGNsYXVzZSBpcyBmb3IgYmFja3dhcmRzIGNvbXBhdCB3aXRoIGFuIGVhcmxpZXIgc2VyaWFsaXphdGlvbiBmb3JtYXQuXHJcbiAgICAgIHRoaXMuZGF0YVNlcnZpY2UgPSAoanNvbi5kYXRhU2VydmljZSAmJiBEYXRhU2VydmljZS5mcm9tSlNPTihqc29uLmRhdGFTZXJ2aWNlKSkgfHwgbmV3IERhdGFTZXJ2aWNlKHsgc2VydmljZU5hbWU6IGpzb24uc2VydmljZU5hbWUgfSk7XHJcblxyXG4gICAgICB0aGlzLnNhdmVPcHRpb25zID0gbmV3IFNhdmVPcHRpb25zKGpzb24uc2F2ZU9wdGlvbnMpO1xyXG4gICAgICB0aGlzLnF1ZXJ5T3B0aW9ucyA9IFF1ZXJ5T3B0aW9ucy5mcm9tSlNPTihqc29uLnF1ZXJ5T3B0aW9ucyk7XHJcbiAgICAgIHRoaXMudmFsaWRhdGlvbk9wdGlvbnMgPSBuZXcgVmFsaWRhdGlvbk9wdGlvbnMoanNvbi52YWxpZGF0aW9uT3B0aW9ucyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpbXBvcnRDb25maWcubWV0YWRhdGFWZXJzaW9uRm4gJiYgaW1wb3J0Q29uZmlnLm1ldGFkYXRhVmVyc2lvbkZuKHtcclxuICAgICAgICBtZXRhZGF0YVZlcnNpb246IGpzb24ubWV0YWRhdGFWZXJzaW9uLFxyXG4gICAgICAgIG1ldGFkYXRhU3RvcmVOYW1lOiBqc29uLm1ldGFkYXRhU3RvcmVOYW1lXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCB0ZW1wS2V5TWFwOiBJVGVtcEtleU1hcCA9IHt9O1xyXG4gICAganNvbi50ZW1wS2V5cy5mb3JFYWNoKChrOiBhbnkpID0+IHtcclxuICAgICAgbGV0IG9sZEtleSA9IEVudGl0eUtleS5mcm9tSlNPTihrLCB0aGlzLm1ldGFkYXRhU3RvcmUpO1xyXG4gICAgICAvLyB0cnkgdG8gdXNlIG9sZEtleSBpZiBub3QgYWxyZWFkeSB1c2VkIGluIHRoaXMga2V5R2VuZXJhdG9yLlxyXG4gICAgICB0ZW1wS2V5TWFwW29sZEtleS50b1N0cmluZygpXSA9IG5ldyBFbnRpdHlLZXkob2xkS2V5LmVudGl0eVR5cGUsIHRoaXMua2V5R2VuZXJhdG9yLmdlbmVyYXRlVGVtcEtleVZhbHVlKG9sZEtleS5lbnRpdHlUeXBlLCBvbGRLZXkudmFsdWVzWzBdKSk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBsZXQgZW50aXRpZXNUb0xpbms6IEVudGl0eVtdID0gW107XHJcbiAgICBsZXQgaW1wQ29uZmlnID0gaW1wb3J0Q29uZmlnIGFzIEltcG9ydENvbmZpZ0V4dDtcclxuXHJcbiAgICBpbXBDb25maWcudGVtcEtleU1hcCA9IHRlbXBLZXlNYXA7XHJcbiAgICBjb3JlLndyYXBFeGVjdXRpb24oKCkgPT4ge1xyXG4gICAgICB0aGlzLl9wZW5kaW5nUHVicyA9IFtdO1xyXG4gICAgfSwgKHN0YXRlKSA9PiB7XHJcbiAgICAgIHRoaXMuX3BlbmRpbmdQdWJzIS5mb3JFYWNoKChmbikgPT4gZm4oKSk7XHJcbiAgICAgIHRoaXMuX3BlbmRpbmdQdWJzID0gdW5kZWZpbmVkO1xyXG4gICAgICB0aGlzLl9oYXNDaGFuZ2VzQWN0aW9uICYmIHRoaXMuX2hhc0NoYW5nZXNBY3Rpb24oKTtcclxuICAgIH0sICgpID0+IHtcclxuICAgICAgY29yZS5vYmplY3RGb3JFYWNoKGpzb24uZW50aXR5R3JvdXBNYXAsIChlbnRpdHlUeXBlTmFtZSwganNvbkdyb3VwKSA9PiB7XHJcbiAgICAgICAgbGV0IGVudGl0eVR5cGUgPSB0aGlzLm1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKGVudGl0eVR5cGVOYW1lLCBmYWxzZSkgYXMgRW50aXR5VHlwZTtcclxuICAgICAgICBsZXQgdGFyZ2V0RW50aXR5R3JvdXAgPSBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cCh0aGlzLCBlbnRpdHlUeXBlKTtcclxuICAgICAgICBsZXQgZW50aXRpZXMgPSBpbXBvcnRFbnRpdHlHcm91cCh0YXJnZXRFbnRpdHlHcm91cCwganNvbkdyb3VwLCBpbXBDb25maWcpO1xyXG4gICAgICAgIGlmIChlbnRpdGllcyAmJiBlbnRpdGllcy5sZW5ndGgpIHtcclxuICAgICAgICAgIGVudGl0aWVzVG9MaW5rID0gZW50aXRpZXNUb0xpbmsuY29uY2F0KGVudGl0aWVzKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICBlbnRpdGllc1RvTGluay5mb3JFYWNoKChlbnRpdHkpID0+IHtcclxuICAgICAgICBpZiAoIWVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUuaXNEZWxldGVkKCkpIHtcclxuICAgICAgICAgIHRoaXMuX2xpbmtSZWxhdGVkRW50aXRpZXMoZW50aXR5KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBlbnRpdGllczogZW50aXRpZXNUb0xpbmssXHJcbiAgICAgIHRlbXBLZXlNYXBwaW5nOiB0ZW1wS2V5TWFwXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQ2xlYXJzIHRoaXMgRW50aXR5TWFuYWdlcidzIGNhY2hlIGJ1dCBrZWVwcyBhbGwgb3RoZXIgc2V0dGluZ3MuIE5vdGUgdGhhdCB0aGlzXHJcbiAgbWV0aG9kIGlzIG5vdCBhcyBmYXN0IGFzIGNyZWF0aW5nIGEgbmV3IEVudGl0eU1hbmFnZXIgdmlhICduZXcgRW50aXR5TWFuYWdlcicuXHJcbiAgVGhpcyBpcyBiZWNhdXNlIGNsZWFyIGFjdHVhbGx5IGRldGFjaGVzIGFsbCBvZiB0aGUgZW50aXRpZXMgZnJvbSB0aGUgRW50aXR5TWFuYWdlci5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBlbTEuY2xlYXIoKTtcclxuICA+ICAgICAvLyBlbTEgaXMgd2lsbCBub3cgY29udGFpbiBubyBlbnRpdGllcywgYnV0IGFsbCBvdGhlciBzZXR0aW5nIHdpbGwgYmUgbWFpbnRhaW5lZC5cclxuICAqKi9cclxuICBjbGVhcigpIHtcclxuICAgIGNvcmUub2JqZWN0TWFwKHRoaXMuX2VudGl0eUdyb3VwTWFwLCBmdW5jdGlvbiAoa2V5OiBzdHJpbmcsIGVudGl0eUdyb3VwOiBFbnRpdHlHcm91cCkge1xyXG4gICAgICByZXR1cm4gZW50aXR5R3JvdXAuX2NoZWNrT3BlcmF0aW9uKCdjbGVhcicpO1xyXG4gICAgfSkuZm9yRWFjaCgoZW50aXR5R3JvdXA6IEVudGl0eUdyb3VwKSA9PiB7XHJcbiAgICAgIGVudGl0eUdyb3VwLl9jbGVhcigpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5fZW50aXR5R3JvdXBNYXAgPSB7fTtcclxuICAgIHRoaXMuX3VuYXR0YWNoZWRDaGlsZHJlbk1hcCA9IG5ldyBVbmF0dGFjaGVkQ2hpbGRyZW5NYXAoKTtcclxuICAgIHRoaXMua2V5R2VuZXJhdG9yID0gbmV3IHRoaXMua2V5R2VuZXJhdG9yQ3RvcigpO1xyXG4gICAgdGhpcy5lbnRpdHlDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbi5DbGVhciB9KTtcclxuICAgIHRoaXMuX3NldEhhc0NoYW5nZXMoZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQ3JlYXRlcyBhbiBlbXB0eSBjb3B5IG9mIHRoaXMgRW50aXR5TWFuYWdlciBidXQgd2l0aCB0aGUgc2FtZSBEYXRhU2VydmljZSwgTWV0YWRhdGFTdG9yZSwgUXVlcnlPcHRpb25zLCBTYXZlT3B0aW9ucywgVmFsaWRhdGlvbk9wdGlvbnMsIGV0Yy4gXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGVtMiA9IGVtMS5jcmVhdGVFbXB0eUNvcHkoKTtcclxuICA+ICAgICAvLyBlbTIgaXMgYSBuZXcgRW50aXR5TWFuYWdlciB3aXRoIGFsbCBvZiBlbTEncyBzZXR0aW5nc1xyXG4gID4gICAgIC8vIGJ1dCBubyBlbnRpdGllcy5cclxuICBAcmV0dXJuIEEgbmV3IEVudGl0eU1hbmFnZXIuXHJcbiAgKiovXHJcbiAgY3JlYXRlRW1wdHlDb3B5KCkge1xyXG4gICAgbGV0IGNvcHkgPSBuZXcgRW50aXR5TWFuYWdlcihjb3JlLmV4dGVuZCh7fSwgdGhpcyxcclxuICAgICAgW1wiZGF0YVNlcnZpY2VcIiwgXCJtZXRhZGF0YVN0b3JlXCIsIFwicXVlcnlPcHRpb25zXCIsIFwic2F2ZU9wdGlvbnNcIiwgXCJ2YWxpZGF0aW9uT3B0aW9uc1wiLCBcImtleUdlbmVyYXRvckN0b3JcIl0pKTtcclxuICAgIHJldHVybiBjb3B5O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQXR0YWNoZXMgYW4gZW50aXR5IHRvIHRoaXMgRW50aXR5TWFuYWdlciB3aXRoIGFuICBbW0VudGl0eVN0YXRlXV0gb2YgJ0FkZGVkJy5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgbGV0IGN1c3QxID0gY3VzdFR5cGUuY3JlYXRlRW50aXR5KCk7XHJcbiAgPiAgICAgZW0xLmFkZEVudGl0eShjdXN0MSk7XHJcblxyXG4gIE5vdGUgdGhhdCB0aGlzIGlzIHRoZSBzYW1lIGFzIHVzaW5nICdhdHRhY2hFbnRpdHknIHdpdGggYW4gW1tFbnRpdHlTdGF0ZV1dIG9mICdBZGRlZCcuXHJcblxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICBsZXQgY3VzdDEgPSBjdXN0VHlwZS5jcmVhdGVFbnRpdHkoKTtcclxuICA+ICAgICBlbTEuYXR0YWNoRW50aXR5KGN1c3QxLCBFbnRpdHlTdGF0ZS5BZGRlZCk7XHJcbiAgQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gYWRkLlxyXG4gIEByZXR1cm4gVGhlIGFkZGVkIGVudGl0eS5cclxuICAqKi9cclxuICBhZGRFbnRpdHkoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgIHJldHVybiB0aGlzLmF0dGFjaEVudGl0eShlbnRpdHksIEVudGl0eVN0YXRlLkFkZGVkKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEF0dGFjaGVzIGFuIGVudGl0eSB0byB0aGlzIEVudGl0eU1hbmFnZXIgd2l0aCBhIHNwZWNpZmllZCBbW0VudGl0eVN0YXRlXV0uXHJcbiAgPiAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgIGxldCBjdXN0MSA9IGN1c3RUeXBlLmNyZWF0ZUVudGl0eSgpO1xyXG4gID4gICAgIGVtMS5hdHRhY2hFbnRpdHkoY3VzdDEsIEVudGl0eVN0YXRlLkFkZGVkKTtcclxuICBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byBhZGQuXHJcbiAgQHBhcmFtIGVudGl0eVN0YXRlIC0gKGRlZmF1bHQ9RW50aXR5U3RhdGUuVW5jaGFuZ2VkKSBUaGUgRW50aXR5U3RhdGUgb2YgdGhlIG5ld2x5IGF0dGFjaGVkIGVudGl0eS4gSWYgb21pdHRlZCB0aGlzIGRlZmF1bHRzIHRvIEVudGl0eVN0YXRlLlVuY2hhbmdlZC5cclxuICBAcGFyYW0gbWVyZ2VTdHJhdGVneSAtIChkZWZhdWx0ID0gTWVyZ2VTdHJhdGVneS5EaXNhbGxvd2VkKSBIb3cgdGhlIHNwZWNpZmllZCBlbnRpdHkgc2hvdWxkIGJlIG1lcmdlZCBpbnRvIHRoZSBFbnRpdHlNYW5hZ2VyIGlmIHRoaXMgRW50aXR5TWFuYWdlciBhbHJlYWR5IGNvbnRhaW5zIGFuIGVudGl0eSB3aXRoIHRoZSBzYW1lIGtleS5cclxuICBAcmV0dXJuIFRoZSBhdHRhY2hlZCBlbnRpdHkuXHJcbiAgKiovXHJcbiAgYXR0YWNoRW50aXR5KGVudGl0eTogRW50aXR5LCBlbnRpdHlTdGF0ZT86IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5PzogTWVyZ2VTdHJhdGVneSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5LCBcImVudGl0eVwiKS5pc1JlcXVpcmVkKCkuY2hlY2soKTtcclxuICAgIHRoaXMubWV0YWRhdGFTdG9yZS5fY2hlY2tFbnRpdHlUeXBlKGVudGl0eSk7XHJcbiAgICBsZXQgZXNTeW1ib2wgPSBhc3NlcnRQYXJhbShlbnRpdHlTdGF0ZSwgXCJlbnRpdHlTdGF0ZVwiKS5pc0VudW1PZihFbnRpdHlTdGF0ZSkuaXNPcHRpb25hbCgpLmNoZWNrKEVudGl0eVN0YXRlLlVuY2hhbmdlZCkgYXMgRW50aXR5U3RhdGU7XHJcbiAgICBsZXQgbXNTeW1ib2wgPSBhc3NlcnRQYXJhbShtZXJnZVN0cmF0ZWd5LCBcIm1lcmdlU3RyYXRlZ3lcIikuaXNFbnVtT2YoTWVyZ2VTdHJhdGVneSkuaXNPcHRpb25hbCgpLmNoZWNrKE1lcmdlU3RyYXRlZ3kuRGlzYWxsb3dlZCkgYXMgTWVyZ2VTdHJhdGVneTtcclxuXHJcbiAgICBpZiAoZW50aXR5LmVudGl0eVR5cGUubWV0YWRhdGFTdG9yZSAhPT0gdGhpcy5tZXRhZGF0YVN0b3JlKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBhdHRhY2ggdGhpcyBlbnRpdHkgYmVjYXVzZSB0aGUgRW50aXR5VHlwZSAoXCIgKyBlbnRpdHkuZW50aXR5VHlwZS5uYW1lICtcclxuICAgICAgICBcIikgYW5kIE1ldGFkYXRhU3RvcmUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgZW50aXR5IGRvZXMgbm90IG1hdGNoIHRoaXMgRW50aXR5TWFuYWdlcidzIE1ldGFkYXRhU3RvcmUuXCIpO1xyXG4gICAgfVxyXG4gICAgbGV0IGFzcGVjdCA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICBpZiAoYXNwZWN0KSB7XHJcbiAgICAgIC8vIHRvIGF2b2lkIHJlYXR0YWNoaW5nIGFuIGVudGl0eSBpbiBwcm9ncmVzc1xyXG4gICAgICBpZiAoYXNwZWN0Ll9pblByb2Nlc3NFbnRpdHkpIHJldHVybiBhc3BlY3QuX2luUHJvY2Vzc0VudGl0eTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIHRoaXMgb2NjdXIncyB3aGVuIGF0dGFjaGluZyBhbiBlbnRpdHkgY3JlYXRlZCB2aWEgbmV3IGluc3RlYWQgb2YgdmlhIGNyZWF0ZUVudGl0eS5cclxuICAgICAgYXNwZWN0ID0gbmV3IEVudGl0eUFzcGVjdChlbnRpdHkpO1xyXG4gICAgfVxyXG4gICAgbGV0IG1hbmFnZXIgPSBhc3BlY3QuZW50aXR5TWFuYWdlcjtcclxuICAgIGlmIChtYW5hZ2VyKSB7XHJcbiAgICAgIGlmIChtYW5hZ2VyID09PSB0aGlzKSB7XHJcbiAgICAgICAgcmV0dXJuIGVudGl0eTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIGVudGl0eSBhbHJlYWR5IGJlbG9uZ3MgdG8gYW5vdGhlciBFbnRpdHlNYW5hZ2VyXCIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGF0dGFjaGVkRW50aXR5ID0ge30gYXMgRW50aXR5O1xyXG4gICAgY29yZS51c2luZyh0aGlzLCBcImlzTG9hZGluZ1wiLCB0cnVlLCAoKSA9PiB7XHJcbiAgICAgIGlmIChlc1N5bWJvbC5pc0FkZGVkKCkpIHtcclxuICAgICAgICBjaGVja0VudGl0eUtleSh0aGlzLCBlbnRpdHkpO1xyXG4gICAgICB9XHJcbiAgICAgIC8vIGF0dGFjaGVkRW50aXR5ID09PSBlbnRpdHkgRVhDRVBUIGluIHRoZSBjYXNlIG9mIGEgbWVyZ2UuXHJcbiAgICAgIGF0dGFjaGVkRW50aXR5ID0gdGhpcy5fYXR0YWNoRW50aXR5Q29yZShlbnRpdHksIGVzU3ltYm9sLCBtc1N5bWJvbCk7XHJcbiAgICAgIGFzcGVjdC5faW5Qcm9jZXNzRW50aXR5ID0gYXR0YWNoZWRFbnRpdHk7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgLy8gZW50aXR5ICggbm90IGF0dGFjaGVkRW50aXR5KSBpcyBkZWxpYmVyYXRlIGhlcmUuXHJcbiAgICAgICAgYXR0YWNoUmVsYXRlZEVudGl0aWVzKHRoaXMsIGVudGl0eSwgZXNTeW1ib2wsIG1zU3ltYm9sKTtcclxuICAgICAgfSBmaW5hbGx5IHtcclxuICAgICAgICAvLyBpbnN1cmUgdGhhdCBfaW5Qcm9jZXNzRW50aXR5IGlzIGNsZWFyZWQuXHJcbiAgICAgICAgYXNwZWN0Ll9pblByb2Nlc3NFbnRpdHkgPSB1bmRlZmluZWQ7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgaWYgKHRoaXMudmFsaWRhdGlvbk9wdGlvbnMudmFsaWRhdGVPbkF0dGFjaCkge1xyXG4gICAgICBhdHRhY2hlZEVudGl0eS5lbnRpdHlBc3BlY3QudmFsaWRhdGVFbnRpdHkoKTtcclxuICAgIH1cclxuICAgIGlmICghZXNTeW1ib2wuaXNVbmNoYW5nZWQoKSkge1xyXG4gICAgICB0aGlzLl9ub3RpZnlTdGF0ZUNoYW5nZShhdHRhY2hlZEVudGl0eSwgdHJ1ZSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmVudGl0eUNoYW5nZWQucHVibGlzaCh7IGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uLkF0dGFjaCwgZW50aXR5OiBhdHRhY2hlZEVudGl0eSB9KTtcclxuXHJcbiAgICByZXR1cm4gYXR0YWNoZWRFbnRpdHk7XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqXHJcbiAgRGV0YWNoZXMgYW4gZW50aXR5IGZyb20gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIC8vIGFzc3VtZSBjdXN0MSBpcyBhIGN1c3RvbWVyIEVudGl0eSBwcmV2aW91c2x5IGF0dGFjaGVkIHRvIGVtMVxyXG4gID4gICAgIGVtMS5kZXRhY2hFbnRpdHkoY3VzdDEpO1xyXG4gID4gICAgIC8vIGVtMSB3aWxsIG5vdyBubyBsb25nZXIgY29udGFpbiBjdXN0MSBhbmQgY3VzdDEgd2lsbCBoYXZlIGFuXHJcbiAgPiAgICAgLy8gZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlIG9mIEVudGl0eVN0YXRlLkRldGFjaGVkXHJcbiAgQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gZGV0YWNoLlxyXG4gIEByZXR1cm4gV2hldGhlciB0aGUgZW50aXR5IGNvdWxkIGJlIGRldGFjaGVkLiBUaGlzIHdpbGwgcmV0dXJuIGZhbHNlIGlmIHRoZSBlbnRpdHkgaXMgYWxyZWFkeSBkZXRhY2hlZCBvciB3YXMgbmV2ZXIgYXR0YWNoZWQuXHJcbiAgKiovXHJcbiAgZGV0YWNoRW50aXR5KGVudGl0eTogRW50aXR5KSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHksIFwiZW50aXR5XCIpLmlzRW50aXR5KCkuY2hlY2soKTtcclxuICAgIGxldCBhc3BlY3QgPSBlbnRpdHkuZW50aXR5QXNwZWN0O1xyXG4gICAgaWYgKCFhc3BlY3QpIHtcclxuICAgICAgLy8gbm8gYXNwZWN0IG1lYW5zIGluIGNvdWxkbid0IGFwcGVhciBpbiBhbnkgZ3JvdXBcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChhc3BlY3QuZW50aXR5TWFuYWdlciAhPT0gdGhpcykge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIGVudGl0eSBkb2VzIG5vdCBiZWxvbmcgdG8gdGhpcyBFbnRpdHlNYW5hZ2VyLlwiKTtcclxuICAgIH1cclxuICAgIHJldHVybiBhc3BlY3Quc2V0RGV0YWNoZWQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEZldGNoZXMgdGhlIG1ldGFkYXRhIGFzc29jaWF0ZWQgd2l0aCB0aGUgRW50aXR5TWFuYWdlcidzIGN1cnJlbnQgJ3NlcnZpY2VOYW1lJy4gIFRoaXMgY2FsbFxyXG4gIG9jY3VycyBpbnRlcm5hbGx5IGJlZm9yZSB0aGUgZmlyc3QgcXVlcnkgdG8gYW55IHNlcnZpY2UgaWYgdGhlIG1ldGFkYXRhIGhhc24ndCBhbHJlYWR5IGJlZW5cclxuICBsb2FkZWQuIF9fQXN5bmNfX1xyXG5cclxuICBVc3VhbGx5IHlvdSB3aWxsIG5vdCBhY3R1YWxseSBwcm9jZXNzIHRoZSByZXN1bHRzIG9mIGEgZmV0Y2hNZXRhZGF0YSBjYWxsIGRpcmVjdGx5LCBidXQgd2lsbCBpbnN0ZWFkXHJcbiAgYXNrIGZvciB0aGUgbWV0YWRhdGEgZnJvbSB0aGUgRW50aXR5TWFuYWdlciBhZnRlciB0aGUgZmV0Y2hNZXRhZGF0YSBjYWxsIHJldHVybnMuXHJcbiAgPiAgICAgbGV0IGVtMSA9IG5ldyBFbnRpdHlNYW5hZ2VyKCBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIpO1xyXG4gID4gICAgIGVtMS5mZXRjaE1ldGFkYXRhKClcclxuICA+ICAgICAgIC50aGVuKGZ1bmN0aW9uKCkge1xyXG4gID4gICAgICAgICAgIGxldCBtZXRhZGF0YVN0b3JlID0gZW0xLm1ldGFkYXRhU3RvcmU7XHJcbiAgPiAgICAgICAgICAgLy8gZG8gc29tZXRoaW5nIHdpdGggdGhlIG1ldGFkYXRhXHJcbiAgPiAgICAgICB9KS5jYXRjaChmdW5jdGlvbihleGNlcHRpb24pIHtcclxuICA+ICAgICAgICAgICAvLyBoYW5kbGUgZXhjZXB0aW9uIGhlcmVcclxuICA+ICAgICAgIH0pO1xyXG4gIFxyXG4gIEBwYXJhbSBjYWxsYmFjayAtIEZ1bmN0aW9uIGNhbGxlZCBvbiBzdWNjZXNzLlxyXG4gIEBwYXJhbSBlcnJvckNhbGxiYWNrIC0gRnVuY3Rpb24gY2FsbGVkIG9uIGZhaWx1cmUuXHJcbiAgQHJldHVybiB7UHJvbWlzZX1cclxuICAgIC0gc2NoZW1hIHtPYmplY3R9IFRoZSByYXcgU2NoZW1hIG9iamVjdCBmcm9tIG1ldGFkYXRhIHByb3ZpZGVyIC0gQmVjYXVzZSB0aGlzIHNjaGVtYSB3aWxsIGRpZmZlciBkZXBlbmRpbmcgb24gdGhlIG1ldGFkYXRhIHByb3ZpZGVyXHJcbiAgICAgICAgaXQgaXMgdXN1YWxseSBiZXR0ZXIgdG8gYWNjZXNzIG1ldGFkYXRhIHZpYSB0aGUgJ21ldGFkYXRhU3RvcmUnIHByb3BlcnR5IG9mIHRoZSBFbnRpdHlNYW5hZ2VyIGluc3RlYWQgb2YgdXNpbmcgdGhpcyAncmF3JyBkYXRhLlxyXG4gICoqL1xyXG4gIGZldGNoTWV0YWRhdGEoZGF0YVNlcnZpY2U/OiBEYXRhU2VydmljZSwgY2FsbGJhY2s/OiBDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IEVycm9yQ2FsbGJhY2spIHtcclxuICAgIGlmICh0eXBlb2YgKGRhdGFTZXJ2aWNlKSA9PT0gXCJmdW5jdGlvblwiKSB7XHJcbiAgICAgIC8vIGxlZ2FjeSBzdXBwb3J0IGZvciB3aGVuIGRhdGFTZXJ2aWNlIHdhcyBub3QgYW4gYXJnLiBpLmUuIGZpcnN0IGFyZyB3YXMgY2FsbGJhY2tcclxuICAgICAgZXJyb3JDYWxsYmFjayA9IGNhbGxiYWNrO1xyXG4gICAgICBjYWxsYmFjayA9IGRhdGFTZXJ2aWNlO1xyXG4gICAgICBkYXRhU2VydmljZSA9IHVuZGVmaW5lZDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGFzc2VydFBhcmFtKGRhdGFTZXJ2aWNlLCBcImRhdGFTZXJ2aWNlXCIpLmlzSW5zdGFuY2VPZihEYXRhU2VydmljZSkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICAgIGFzc2VydFBhcmFtKGNhbGxiYWNrLCBcImNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgICAgYXNzZXJ0UGFyYW0oZXJyb3JDYWxsYmFjaywgXCJlcnJvckNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgcHJvbWlzZSA9IHRoaXMubWV0YWRhdGFTdG9yZS5mZXRjaE1ldGFkYXRhKGRhdGFTZXJ2aWNlIHx8IHRoaXMuZGF0YVNlcnZpY2UpO1xyXG4gICAgcmV0dXJuIHByb21pc2VXaXRoQ2FsbGJhY2tzKHByb21pc2UsIGNhbGxiYWNrLCBlcnJvckNhbGxiYWNrKTtcclxuICB9XHJcblxyXG5cclxuICBleGVjdXRlUXVlcnkocXVlcnk6IHN0cmluZywgY2FsbGJhY2s/OiBRdWVyeVN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IFF1ZXJ5RXJyb3JDYWxsYmFjayk6IFByb21pc2U8UXVlcnlSZXN1bHQ+O1xyXG4gIGV4ZWN1dGVRdWVyeShxdWVyeTogRW50aXR5UXVlcnksIGNhbGxiYWNrPzogUXVlcnlTdWNjZXNzQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s/OiBRdWVyeUVycm9yQ2FsbGJhY2spOiBQcm9taXNlPFF1ZXJ5UmVzdWx0PjtcclxuICAvKipcclxuICBFeGVjdXRlcyB0aGUgc3BlY2lmaWVkIHF1ZXJ5LiBfX0FzeW5jX18gXHJcbiAgXHJcbiAgPiAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKTtcclxuICA+ICAgICBlbS5leGVjdXRlUXVlcnkocXVlcnkpLnRoZW4oIGZ1bmN0aW9uKGRhdGEpIHtcclxuICA+ICAgICAgICAgbGV0IG9yZGVycyA9IGRhdGEucmVzdWx0cztcclxuICA+ICAgICAgICAgLi4uIHF1ZXJ5IHJlc3VsdHMgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICB9KS5jYXRjaCggZnVuY3Rpb24oZXJyKSB7XHJcbiAgPiAgICAgICAgIC4uLiBxdWVyeSBmYWlsdXJlIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgfSk7XHJcblxyXG4gIG9yIHdpdGggY2FsbGJhY2tzXHJcbiAgPiAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKTtcclxuICA+ICAgICBlbS5leGVjdXRlUXVlcnkocXVlcnksXHJcbiAgPiAgICAgICAgIGZ1bmN0aW9uKGRhdGEpIHtcclxuICA+ICAgICAgICAgICAgIGxldCBvcmRlcnMgPSBkYXRhLnJlc3VsdHM7XHJcbiAgPiAgICAgICAgICAgICAuLi4gcXVlcnkgcmVzdWx0cyBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgICAgICB9LFxyXG4gID4gICAgICAgICBmdW5jdGlvbihlcnIpIHtcclxuICA+ICAgICAgICAgICAgIC4uLiBxdWVyeSBmYWlsdXJlIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgICAgIH0pO1xyXG5cclxuICBFaXRoZXIgd2F5IHRoaXMgbWV0aG9kIGlzIHRoZSBzYW1lIGFzIGNhbGxpbmcgdGhlIFRoZSBbW0VudGl0eVF1ZXJ5XV0gJ2V4ZWN1dGUnIG1ldGhvZC5cclxuICA+ICAgICBsZXQgZW0gPSBuZXcgRW50aXR5TWFuYWdlcihzZXJ2aWNlTmFtZSk7XHJcbiAgPiAgICAgbGV0IHF1ZXJ5ID0gbmV3IEVudGl0eVF1ZXJ5KFwiT3JkZXJzXCIpLnVzaW5nKGVtKTtcclxuICA+ICAgICBxdWVyeS5leGVjdXRlKCkudGhlbiggZnVuY3Rpb24oZGF0YSkge1xyXG4gID4gICAgICAgICBsZXQgb3JkZXJzID0gZGF0YS5yZXN1bHRzO1xyXG4gID4gICAgICAgICAuLi4gcXVlcnkgcmVzdWx0cyBwcm9jZXNzZWQgaGVyZVxyXG4gID4gICAgIH0pLmNhdGNoKCBmdW5jdGlvbihlcnIpIHtcclxuICA+ICAgICAgICAgLi4uIHF1ZXJ5IGZhaWx1cmUgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICB9KTtcclxuICBAcGFyYW0gcXVlcnkgLSBUaGUgW1tFbnRpdHlRdWVyeV1dIG9yIE9EYXRhIHF1ZXJ5IHN0cmluZyB0byBleGVjdXRlLlxyXG4gIEBwYXJhbSBjYWxsYmFjayAtIEZ1bmN0aW9uIGNhbGxlZCBvbiBzdWNjZXNzLlxyXG4gIEBwYXJhbSBlcnJvckNhbGxiYWNrIC0ge0Z1bmN0aW9ufSBGdW5jdGlvbiBjYWxsZWQgb24gZmFpbHVyZS5cclxuICBAcmV0dXJuIFByb21pc2Ugb2YgXHJcbiAgICAtIHJlc3VsdHMgLSBBbiBhcnJheSBvZiBlbnRpdGllc1xyXG4gICAgLSByZXRyaWV2ZWRFbnRpdGllcyAtIEEgYXJyYXkgb2YgYWxsIG9mIHRoZSBlbnRpdGllcyByZXR1cm5lZCBieSB0aGUgcXVlcnkuICBEaWZmZXJzIGZyb20gcmVzdWx0cyAoYWJvdmUpIHdoZW4gLmV4cGFuZCgpIGlzIHVzZWQuXHJcbiAgICAtIHF1ZXJ5IC0gVGhlIG9yaWdpbmFsIFtbRW50aXR5UXVlcnldXSBvciBxdWVyeSBzdHJpbmdcclxuICAgIC0gZW50aXR5TWFuYWdlciAtICBUaGUgRW50aXR5TWFuYWdlci5cclxuICAgIC0gaHR0cFJlc3BvbnNlIC0gVGhlIFtbSUh0dHBSZXNwb25zZV1dIHJldHVybmVkIGZyb20gdGhlIHNlcnZlci5cclxuICAgIC0gaW5saW5lQ291bnQgLSAgT25seSBhdmFpbGFibGUgaWYgJ2lubGluZUNvdW50KHRydWUpJyB3YXMgYXBwbGllZCB0byB0aGUgcXVlcnkuICBSZXR1cm5zIHRoZSBjb3VudCBvZlxyXG4gICAgaXRlbXMgdGhhdCB3b3VsZCBoYXZlIGJlZW4gcmV0dXJuZWQgYnkgdGhlIHF1ZXJ5IGJlZm9yZSBhcHBseWluZyBhbnkgc2tpcCBvciB0YWtlIG9wZXJhdG9ycywgYnV0IGFmdGVyIGFueSBmaWx0ZXIvd2hlcmUgcHJlZGljYXRlc1xyXG4gICAgd291bGQgaGF2ZSBiZWVuIGFwcGxpZWQuXHJcbiAgKiovXHJcbiAgZXhlY3V0ZVF1ZXJ5KHF1ZXJ5OiBFbnRpdHlRdWVyeSB8IHN0cmluZywgY2FsbGJhY2s/OiBRdWVyeVN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IFF1ZXJ5RXJyb3JDYWxsYmFjaykge1xyXG4gICAgYXNzZXJ0UGFyYW0ocXVlcnksIFwicXVlcnlcIikuaXNJbnN0YW5jZU9mKEVudGl0eVF1ZXJ5KS5vcigpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGNhbGxiYWNrLCBcImNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGVycm9yQ2FsbGJhY2ssIFwiZXJyb3JDYWxsYmFja1wiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICBsZXQgcHJvbWlzZTogUHJvbWlzZTxhbnk+O1xyXG4gICAgLy8gJ3Jlc29sdmUnIG1ldGhvZHMgY3JlYXRlIGEgbmV3IHR5cGVkIG9iamVjdCB3aXRoIGFsbCBvZiBpdHMgcHJvcGVydGllcyBmdWxseSByZXNvbHZlZCBhZ2FpbnN0IGEgbGlzdCBvZiBzb3VyY2VzLlxyXG4gICAgLy8gVGhvdWdodCBhYm91dCBjcmVhdGluZyBhICdub3JtYWxpemVkJyBxdWVyeSB3aXRoIHRoZXNlICdyZXNvbHZlZCcgb2JqZWN0c1xyXG4gICAgLy8gYnV0IGRlY2lkZWQgbm90IHRvIGJlY2F1c2UgdGhlICdxdWVyeScgbWF5IG5vdCBiZSBhbiBFbnRpdHlRdWVyeSAoaXQgY2FuIGJlIGEgc3RyaW5nKSBhbmQgaGVuY2UgbWlnaHQgbm90IGhhdmUgYSBxdWVyeU9wdGlvbnMgb3IgZGF0YVNlcnZpY2VzIHByb3BlcnR5IG9uIGl0LlxyXG4gICAgbGV0IHF1ZXJ5T3B0aW9ucyA9IFF1ZXJ5T3B0aW9ucy5yZXNvbHZlKFsocXVlcnkgYXMgYW55KS5xdWVyeU9wdGlvbnMsIHRoaXMucXVlcnlPcHRpb25zLCBRdWVyeU9wdGlvbnMuZGVmYXVsdEluc3RhbmNlXSk7XHJcbiAgICBsZXQgZGF0YVNlcnZpY2UgPSBEYXRhU2VydmljZS5yZXNvbHZlKFsocXVlcnkgYXMgYW55KS5kYXRhU2VydmljZSEsIHRoaXMuZGF0YVNlcnZpY2VdKTtcclxuXHJcbiAgICBpZiAoKCFkYXRhU2VydmljZS5oYXNTZXJ2ZXJNZXRhZGF0YSkgfHwgdGhpcy5tZXRhZGF0YVN0b3JlLmhhc01ldGFkYXRhRm9yKGRhdGFTZXJ2aWNlLnNlcnZpY2VOYW1lKSkge1xyXG4gICAgICBwcm9taXNlID0gZXhlY3V0ZVF1ZXJ5Q29yZSh0aGlzLCBxdWVyeSwgcXVlcnlPcHRpb25zLCBkYXRhU2VydmljZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBwcm9taXNlID0gdGhpcy5mZXRjaE1ldGFkYXRhKGRhdGFTZXJ2aWNlKS50aGVuKCgpID0+IHtcclxuICAgICAgICByZXR1cm4gZXhlY3V0ZVF1ZXJ5Q29yZSh0aGlzLCBxdWVyeSwgcXVlcnlPcHRpb25zLCBkYXRhU2VydmljZSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBwcm9taXNlV2l0aENhbGxiYWNrcyhwcm9taXNlLCBjYWxsYmFjaywgZXJyb3JDYWxsYmFjayBhcyBFcnJvckNhbGxiYWNrKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEV4ZWN1dGVzIHRoZSBzcGVjaWZpZWQgcXVlcnkgYWdhaW5zdCB0aGlzIEVudGl0eU1hbmFnZXIncyBsb2NhbCBjYWNoZS5cclxuXHJcbiAgQmVjYXVzZSB0aGlzIG1ldGhvZCBpcyBleGVjdXRlZCBpbW1lZGlhdGVseSB0aGVyZSBpcyBubyBuZWVkIGZvciBhIHByb21pc2Ugb3IgYSBjYWxsYmFja1xyXG4gID4gICAgIGxldCBlbSA9IG5ldyBFbnRpdHlNYW5hZ2VyKHNlcnZpY2VOYW1lKTtcclxuICA+ICAgICBsZXQgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkoXCJPcmRlcnNcIik7XHJcbiAgPiAgICAgbGV0IG9yZGVycyA9IGVtLmV4ZWN1dGVRdWVyeUxvY2FsbHkocXVlcnkpO1xyXG5cclxuICBOb3RlIHRoYXQgdGhpcyBjYW4gYWxzbyBiZSBhY2NvbXBsaXNoZWQgdXNpbmcgdGhlICdleGVjdXRlUXVlcnknIG1ldGhvZCB3aXRoXHJcbiAgYSBGZXRjaFN0cmF0ZWd5IG9mIEZyb21Mb2NhbENhY2hlIGFuZCBtYWtpbmcgdXNlIG9mIHRoZSBQcm9taXNlIG9yIGNhbGxiYWNrXHJcbiAgPiAgICAgbGV0IGVtID0gbmV3IEVudGl0eU1hbmFnZXIoc2VydmljZU5hbWUpO1xyXG4gID4gICAgIGxldCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShcIk9yZGVyc1wiKS51c2luZyhGZXRjaFN0cmF0ZWd5LkZyb21Mb2NhbENhY2hlKTtcclxuICA+ICAgICBlbS5leGVjdXRlUXVlcnkocXVlcnkpLnRoZW4oIGZ1bmN0aW9uKGRhdGEpIHtcclxuICA+ICAgICAgICAgbGV0IG9yZGVycyA9IGRhdGEucmVzdWx0cztcclxuICA+ICAgICAgICAgLi4uIHF1ZXJ5IHJlc3VsdHMgcHJvY2Vzc2VkIGhlcmVcclxuICA+ICAgICB9KS5jYXRjaCggZnVuY3Rpb24oZXJyKSB7XHJcbiAgPiAgICAgICAgIC4uLiBxdWVyeSBmYWlsdXJlIHByb2Nlc3NlZCBoZXJlXHJcbiAgPiAgICAgfSk7XHJcbiAgQHBhcmFtIHF1ZXJ5IC0gVGhlIFtbRW50aXR5UXVlcnldXSB0byBleGVjdXRlLlxyXG4gIEByZXR1cm4gIHtBcnJheSBvZiBFbnRpdHl9ICBBcnJheSBvZiBlbnRpdGllcyBmcm9tIGNhY2hlIHRoYXQgc2F0aXNmeSB0aGUgcXVlcnlcclxuICAqKi9cclxuICBleGVjdXRlUXVlcnlMb2NhbGx5KHF1ZXJ5OiBFbnRpdHlRdWVyeSkge1xyXG4gICAgcmV0dXJuIGV4ZWN1dGVRdWVyeUxvY2FsbHlDb3JlKHRoaXMsIHF1ZXJ5KS5yZXN1bHRzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgU2F2ZXMgZWl0aGVyIGEgbGlzdCBvZiBzcGVjaWZpZWQgZW50aXRpZXMgb3IgYWxsIGNoYW5nZWQgZW50aXRpZXMgd2l0aGluIHRoaXMgRW50aXR5TWFuYWdlci4gSWYgdGhlcmUgYXJlIG5vIGNoYW5nZXMgdG8gYW55IG9mIHRoZSBlbnRpdGllc1xyXG4gIHNwZWNpZmllZCB0aGVuIHRoZXJlIHdpbGwgYmUgbm8gc2VydmVyIHNpZGUgY2FsbCBtYWRlIGJ1dCBhIHZhbGlkICdlbXB0eScgc2F2ZVJlc3VsdCB3aWxsIHN0aWxsIGJlIHJldHVybmVkLiBfX0FzeW5jX19cclxuXHJcbiAgT2Z0ZW4gd2Ugd2lsbCBiZSBzYXZpbmcgYWxsIG9mIHRoZSBlbnRpdGllcyB3aXRoaW4gYW4gRW50aXR5TWFuYWdlciB0aGF0IGFyZSBlaXRoZXIgYWRkZWQsIG1vZGlmaWVkIG9yIGRlbGV0ZWRcclxuICBhbmQgd2Ugd2lsbCBsZXQgdGhlICdzYXZlQ2hhbmdlcycgY2FsbCBkZXRlcm1pbmUgd2hpY2ggZW50aXRpZXMgdGhlc2UgYXJlLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgLy8gVGhpcyBjb3VsZCBpbmNsdWRlIGFkZGVkLCBtb2RpZmllZCBhbmQgZGVsZXRlZCBlbnRpdGllcy5cclxuICA+ICAgICAgZW0uc2F2ZUNoYW5nZXMoKS50aGVuKGZ1bmN0aW9uKHNhdmVSZXN1bHQpIHtcclxuICA+ICAgICAgICAgIGxldCBzYXZlZEVudGl0aWVzID0gc2F2ZVJlc3VsdC5lbnRpdGllcztcclxuICA+ICAgICAgICAgIGxldCBrZXlNYXBwaW5ncyA9IHNhdmVSZXN1bHQua2V5TWFwcGluZ3M7XHJcbiAgPiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlKSB7XHJcbiAgPiAgICAgICAgICAvLyBlIGlzIGFueSBleGNlcHRpb24gdGhhdCB3YXMgdGhyb3duLlxyXG4gID4gICAgICB9KTtcclxuXHJcbiAgQnV0IHdlIGNhbiBhbHNvIGNvbnRyb2wgZXhhY3RseSB3aGljaCBlbnRpdGllcyB0byBzYXZlIGFuZCBjYW4gc3BlY2lmeSBzcGVjaWZpYyBTYXZlT3B0aW9uc1xyXG5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVudGl0aWVzVG9TYXZlIGlzIGFuIGFycmF5IG9mIGVudGl0aWVzIHRvIHNhdmUuXHJcbiAgPiAgICAgIGxldCBzYXZlT3B0aW9ucyA9IG5ldyBTYXZlT3B0aW9ucyh7IGFsbG93Q29uY3VycmVudFNhdmVzOiB0cnVlIH0pO1xyXG4gID4gICAgICBlbS5zYXZlQ2hhbmdlcyhlbnRpdGllc1RvU2F2ZSwgc2F2ZU9wdGlvbnMpLnRoZW4oZnVuY3Rpb24oc2F2ZVJlc3VsdCkge1xyXG4gID4gICAgICAgICAgbGV0IHNhdmVkRW50aXRpZXMgPSBzYXZlUmVzdWx0LmVudGl0aWVzO1xyXG4gID4gICAgICAgICAgbGV0IGtleU1hcHBpbmdzID0gc2F2ZVJlc3VsdC5rZXlNYXBwaW5ncztcclxuICA+ICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGUpIHtcclxuICA+ICAgICAgICAgIC8vIGUgaXMgYW55IGV4Y2VwdGlvbiB0aGF0IHdhcyB0aHJvd24uXHJcbiAgPiAgICAgIH0pO1xyXG5cclxuICBDYWxsYmFjayBtZXRob2RzIGNhbiBhbHNvIGJlIHVzZWRcclxuICA+ICAgICAgZW0uc2F2ZUNoYW5nZXMoZW50aXRpZXNUb1NhdmUsIG51bGwsXHJcbiAgPiAgICAgICAgICBmdW5jdGlvbihzYXZlUmVzdWx0KSB7XHJcbiAgPiAgICAgICAgICAgICAgbGV0IHNhdmVkRW50aXRpZXMgPSBzYXZlUmVzdWx0LmVudGl0aWVzO1xyXG4gID4gICAgICAgICAgICAgIGxldCBrZXlNYXBwaW5ncyA9IHNhdmVSZXN1bHQua2V5TWFwcGluZ3M7XHJcbiAgPiAgICAgICAgICB9LCBmdW5jdGlvbiAoZSkge1xyXG4gID4gICAgICAgICAgICAgIC8vIGUgaXMgYW55IGV4Y2VwdGlvbiB0aGF0IHdhcyB0aHJvd24uXHJcbiAgPiAgICAgICAgICB9XHJcbiAgPiAgICAgICk7XHJcblxyXG4gIEBwYXJhbSBlbnRpdGllcyAtIFRoZSBsaXN0IG9mIGVudGl0aWVzIHRvIHNhdmUuXHJcbiAgRXZlcnkgZW50aXR5IGluIHRoYXQgbGlzdCB3aWxsIGJlIHNlbnQgdG8gdGhlIHNlcnZlciwgd2hldGhlciBjaGFuZ2VkIG9yIHVuY2hhbmdlZCxcclxuICBhcyBsb25nIGFzIGl0IGlzIGF0dGFjaGVkIHRvIHRoaXMgRW50aXR5TWFuYWdlci5cclxuICBJZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkLCBudWxsIG9yIGVtcHR5ICh0aGUgdXN1YWwgY2FzZSksXHJcbiAgZXZlcnkgZW50aXR5IHdpdGggcGVuZGluZyBjaGFuZ2VzIGluIHRoaXMgRW50aXR5TWFuYWdlciB3aWxsIGJlIHNhdmVkLlxyXG4gIEBwYXJhbSBzYXZlT3B0aW9ucyAtIFtbU2F2ZU9wdGlvbnNdXSBmb3IgdGhlIHNhdmUgLSB3aWxsIGRlZmF1bHQgdG9cclxuICBbW0VudGl0eU1hbmFnZXIuc2F2ZU9wdGlvbnNdXSBpZiBudWxsLlxyXG4gIEBwYXJhbSBjYWxsYmFjayAtICBGdW5jdGlvbiBjYWxsZWQgb24gc3VjY2Vzcy5cclxuICBAcGFyYW0gZXJyb3JDYWxsYmFjayAtIEZ1bmN0aW9uIGNhbGxlZCBvbiBmYWlsdXJlLlxyXG4gIEByZXR1cm4ge1Byb21pc2V9IFByb21pc2VcclxuICAqKi9cclxuICBzYXZlQ2hhbmdlcyhlbnRpdGllcz86IEVudGl0eVtdIHwgbnVsbCwgc2F2ZU9wdGlvbnM/OiBTYXZlT3B0aW9ucywgY2FsbGJhY2s/OiBGdW5jdGlvbiwgZXJyb3JDYWxsYmFjaz86IEZ1bmN0aW9uKSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdGllcywgXCJlbnRpdGllc1wiKS5pc09wdGlvbmFsKCkuaXNBcnJheSgpLmlzRW50aXR5KCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKHNhdmVPcHRpb25zLCBcInNhdmVPcHRpb25zXCIpLmlzSW5zdGFuY2VPZihTYXZlT3B0aW9ucykuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShjYWxsYmFjaywgXCJjYWxsYmFja1wiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShlcnJvckNhbGxiYWNrLCBcImVycm9yQ2FsbGJhY2tcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG5cclxuICAgIHNhdmVPcHRpb25zID0gc2F2ZU9wdGlvbnMgfHwgdGhpcy5zYXZlT3B0aW9ucyB8fCBTYXZlT3B0aW9ucy5kZWZhdWx0SW5zdGFuY2U7XHJcblxyXG4gICAgbGV0IGVudGl0aWVzVG9TYXZlID0gZ2V0RW50aXRpZXNUb1NhdmUodGhpcywgZW50aXRpZXMgPyBlbnRpdGllcyA6IHVuZGVmaW5lZCk7XHJcblxyXG4gICAgaWYgKGVudGl0aWVzVG9TYXZlLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICBsZXQgcmVzdWx0ID0geyBlbnRpdGllczogW10sIGtleU1hcHBpbmdzOiBbXSB9IGFzIFNhdmVSZXN1bHQ7XHJcbiAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2socmVzdWx0KTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghc2F2ZU9wdGlvbnMuYWxsb3dDb25jdXJyZW50U2F2ZXMpIHtcclxuICAgICAgbGV0IGFueVBlbmRpbmdTYXZlcyA9IGVudGl0aWVzVG9TYXZlLnNvbWUoZnVuY3Rpb24gKGVudGl0eSkge1xyXG4gICAgICAgIHJldHVybiBlbnRpdHkuZW50aXR5QXNwZWN0LmlzQmVpbmdTYXZlZDtcclxuICAgICAgfSk7XHJcbiAgICAgIGlmIChhbnlQZW5kaW5nU2F2ZXMpIHtcclxuICAgICAgICBsZXQgZXJyID0gbmV3IEVycm9yKFwiQ29uY3VycmVudCBzYXZlcyBub3QgYWxsb3dlZCAtIFNhdmVPcHRpb25zLmFsbG93Q29uY3VycmVudFNhdmVzIGlzIGZhbHNlXCIpO1xyXG4gICAgICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKGVycik7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjbGVhclNlcnZlckVycm9ycyhlbnRpdGllc1RvU2F2ZSk7XHJcblxyXG4gICAgbGV0IHZhbEVycm9yID0gdGhpcy5zYXZlQ2hhbmdlc1ZhbGlkYXRlT25DbGllbnQoZW50aXRpZXNUb1NhdmUpO1xyXG4gICAgaWYgKHZhbEVycm9yKSB7XHJcbiAgICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKHZhbEVycm9yKTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHZhbEVycm9yKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgZGF0YVNlcnZpY2UgPSBEYXRhU2VydmljZS5yZXNvbHZlKFtzYXZlT3B0aW9ucy5kYXRhU2VydmljZSwgdGhpcy5kYXRhU2VydmljZV0pO1xyXG4gICAgbGV0IHNhdmVDb250ZXh0OiBTYXZlQ29udGV4dCA9IHtcclxuICAgICAgZW50aXR5TWFuYWdlcjogdGhpcyxcclxuICAgICAgZGF0YVNlcnZpY2U6IGRhdGFTZXJ2aWNlLFxyXG4gICAgICBwcm9jZXNzU2F2ZWRFbnRpdGllczogcHJvY2Vzc1NhdmVkRW50aXRpZXMsXHJcbiAgICAgIHJlc291cmNlTmFtZTogc2F2ZU9wdGlvbnMucmVzb3VyY2VOYW1lIHx8IHRoaXMuc2F2ZU9wdGlvbnMucmVzb3VyY2VOYW1lIHx8IFwiU2F2ZUNoYW5nZXNcIlxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBUT0RPOiBuZWVkIHRvIGNoZWNrIHRoYXQgaWYgd2UgYXJlIGRvaW5nIGEgcGFydGlhbCBzYXZlIHRoYXQgYWxsIGVudGl0aWVzIHdob3NlIHRlbXAga2V5c1xyXG4gICAgLy8gYXJlIHJlZmVyZW5jZWQgYXJlIGFsc28gaW4gdGhlIHBhcnRpYWwgc2F2ZSBncm91cFxyXG5cclxuICAgIGxldCBzYXZlQnVuZGxlID0geyBlbnRpdGllczogZW50aXRpZXNUb1NhdmUsIHNhdmVPcHRpb25zOiBzYXZlT3B0aW9ucyB9O1xyXG5cclxuXHJcbiAgICB0cnkgeyAvLyBHdWFyZCBhZ2FpbnN0IGV4Y2VwdGlvbiB0aHJvd24gaW4gZGF0YXNlcnZpY2UgYWRhcHRlciBiZWZvcmUgaXQgZ29lcyBhc3luY1xyXG4gICAgICB1cGRhdGVDb25jdXJyZW5jeVByb3BlcnRpZXMoZW50aXRpZXNUb1NhdmUpO1xyXG4gICAgICByZXR1cm4gZGF0YVNlcnZpY2UuYWRhcHRlckluc3RhbmNlIS5zYXZlQ2hhbmdlcyhzYXZlQ29udGV4dCwgc2F2ZUJ1bmRsZSlcclxuICAgICAgICAudGhlbihzYXZlU3VjY2VzcykudGhlbigocikgPT4gciwgc2F2ZUZhaWwpO1xyXG4gICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgIC8vIHVuZG8gdGhlIG1hcmtpbmcgYnkgdXBkYXRlQ29uY3VycmVuY3lQcm9wZXJ0aWVzXHJcbiAgICAgIG1hcmtJc0JlaW5nU2F2ZWQoZW50aXRpZXNUb1NhdmUsIGZhbHNlKTtcclxuICAgICAgaWYgKGVycm9yQ2FsbGJhY2spIGVycm9yQ2FsbGJhY2soZXJyKTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycik7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gc2F2ZVN1Y2Nlc3Moc2F2ZVJlc3VsdDogU2F2ZVJlc3VsdCkge1xyXG4gICAgICBsZXQgZW0gPSBzYXZlQ29udGV4dC5lbnRpdHlNYW5hZ2VyO1xyXG4gICAgICBtYXJrSXNCZWluZ1NhdmVkKGVudGl0aWVzVG9TYXZlLCBmYWxzZSk7XHJcbiAgICAgIGxldCBzYXZlZEVudGl0aWVzID0gc2F2ZUNvbnRleHQucHJvY2Vzc1NhdmVkRW50aXRpZXMoc2F2ZVJlc3VsdCk7XHJcbiAgICAgIHNhdmVSZXN1bHQuZW50aXRpZXMgPSBzYXZlZEVudGl0aWVzO1xyXG5cclxuICAgICAgLy8gdXBkYXRlIF9oYXNDaGFuZ2VzIGFmdGVyIHNhdmUuXHJcbiAgICAgIGVtLl9zZXRIYXNDaGFuZ2VzKCk7XHJcblxyXG4gICAgICAvLyBjYW4ndCBkbyB0aGlzIGFueW1vcmUgYmVjYXVzZSBvdGhlciBjaGFuZ2VzIG1pZ2h0IGhhdmUgYmVlbiBtYWRlIHdoaWxlIHNhdmVkIGVudGl0aWVzIGluIGZsaWdodC5cclxuICAgICAgLy8gICAgICBsZXQgaGFzQ2hhbmdlcyA9IChpc0Z1bGxTYXZlICYmIGhhdmVTYW1lQ29udGVudHMoZW50aXRpZXNUb1NhdmUsIHNhdmVkRW50aXRpZXMpKSA/IGZhbHNlIDogbnVsbDtcclxuICAgICAgLy8gICAgICBlbS5fc2V0SGFzQ2hhbmdlcyhoYXNDaGFuZ2VzKTtcclxuXHJcbiAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soc2F2ZVJlc3VsdCk7XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc2F2ZVJlc3VsdCk7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1NhdmVkRW50aXRpZXMoc2F2ZVJlc3VsdDogU2F2ZVJlc3VsdCkge1xyXG4gICAgICBsZXQgc2F2ZWRFbnRpdGllcyA9IHNhdmVSZXN1bHQuZW50aXRpZXM7XHJcbiAgICAgIGxldCBkZWxldGVkS2V5cyA9IHNhdmVSZXN1bHQuZGVsZXRlZEtleXMgfHwgW107XHJcbiAgICAgIGlmIChzYXZlZEVudGl0aWVzLmxlbmd0aCA9PT0gMCAmJiBkZWxldGVkS2V5cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICByZXR1cm4gW107XHJcbiAgICAgIH1cclxuICAgICAgbGV0IGtleU1hcHBpbmdzID0gc2F2ZVJlc3VsdC5rZXlNYXBwaW5ncztcclxuICAgICAgbGV0IGVtID0gc2F2ZUNvbnRleHQuZW50aXR5TWFuYWdlcjtcclxuXHJcbiAgICAgIC8vIG11c3Qgb2NjdXIgb3V0c2lkZSBvZiBpc0xvYWRpbmcgYmxvY2tcclxuICAgICAgZml4dXBLZXlzKGVtLCBrZXlNYXBwaW5ncyk7XHJcblxyXG4gICAgICBjb3JlLnVzaW5nKGVtLCBcImlzTG9hZGluZ1wiLCB0cnVlLCAoKSA9PiB7XHJcblxyXG4gICAgICAgIGxldCBtYXBwaW5nQ29udGV4dCA9IG5ldyBNYXBwaW5nQ29udGV4dCh7XHJcbiAgICAgICAgICBxdWVyeTogdW5kZWZpbmVkLCAvLyB0ZWxscyB2aXNpdEFuZE1lcmdlIHRoaXMgaXMgYSBzYXZlIGluc3RlYWQgb2YgYSBxdWVyeVxyXG4gICAgICAgICAgZW50aXR5TWFuYWdlcjogZW0sXHJcbiAgICAgICAgICBtZXJnZU9wdGlvbnM6IHsgbWVyZ2VTdHJhdGVneTogTWVyZ2VTdHJhdGVneS5PdmVyd3JpdGVDaGFuZ2VzIH0sXHJcbiAgICAgICAgICBkYXRhU2VydmljZTogZGF0YVNlcnZpY2VcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgLy8gVGhlIHZpc2l0QW5kTWVyZ2Ugb3BlcmF0aW9uIGhhcyBiZWVuIG9wdGltaXplZCBzbyB0aGF0IHdlIGRvIG5vdCBhY3R1YWxseSBwZXJmb3JtIGEgbWVyZ2UgaWYgdGhlXHJcbiAgICAgICAgLy8gdGhlIHNhdmUgb3BlcmF0aW9uIGRpZCBub3QgYWN0dWFsbHkgcmV0dXJuIHRoZSBlbnRpdHkgLSBpLmUuIGR1cmluZyBPRGF0YSBhbmQgTW9uZ28gdXBkYXRlcyBhbmQgZGVsZXRlcy5cclxuICAgICAgICBzYXZlZEVudGl0aWVzID0gbWFwcGluZ0NvbnRleHQudmlzaXRBbmRNZXJnZShzYXZlZEVudGl0aWVzLCB7IG5vZGVUeXBlOiBcInJvb3RcIiB9KTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyBkZXRhY2ggYW55IGVudGl0aWVzIGZvdW5kIGluIHRoZSBlbSB0aGF0IGFwcGVhciBpbiB0aGUgZGVsZXRlZEtleXMgbGlzdC4gXHJcbiAgICAgIGRlbGV0ZWRLZXlzLmZvckVhY2goa2V5ID0+IHtcclxuICAgICAgICBsZXQgZW50aXR5VHlwZSA9IGVtLm1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKGtleS5lbnRpdHlUeXBlTmFtZSkgYXMgRW50aXR5VHlwZTtcclxuICAgICAgICBsZXQgZWtleSA9IG5ldyBFbnRpdHlLZXkoZW50aXR5VHlwZSwga2V5LmtleVZhbHVlcyk7XHJcbiAgICAgICAgbGV0IGVudGl0eSA9IGVtLmdldEVudGl0eUJ5S2V5KGVrZXkpO1xyXG4gICAgICAgIGlmIChlbnRpdHkpIHtcclxuICAgICAgICAgIGVudGl0eS5lbnRpdHlBc3BlY3Quc2V0RGV0YWNoZWQoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgcmV0dXJuIHNhdmVkRW50aXRpZXM7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gc2F2ZUZhaWwoc2VydmVyRXJyb3I6IFNhdmVFcnJvckZyb21TZXJ2ZXIpIHtcclxuICAgICAgbWFya0lzQmVpbmdTYXZlZChlbnRpdGllc1RvU2F2ZSwgZmFsc2UpO1xyXG4gICAgICBsZXQgY2xpZW50RXJyb3IgPSBwcm9jZXNzU2VydmVyRXJyb3JzKHNhdmVDb250ZXh0LCBzZXJ2ZXJFcnJvcik7XHJcbiAgICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKGNsaWVudEVycm9yKTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGNsaWVudEVycm9yKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJ1biB0aGUgXCJzYXZlQ2hhbmdlc1wiIHByZS1zYXZlIGNsaWVudCB2YWxpZGF0aW9uIGxvZ2ljLlxyXG4gIFxyXG4gIFRoaXMgaXMgTk9UIGEgZ2VuZXJhbCBwdXJwb3NlIHZhbGlkYXRpb24gbWV0aG9kLlxyXG4gIEl0IGlzIGludGVuZGVkIGZvciB1dGlsaXRpZXMgdGhhdCBtdXN0IGtub3cgaWYgc2F2ZUNoYW5nZXNcclxuICB3b3VsZCByZWplY3QgdGhlIHNhdmUgZHVlIHRvIGNsaWVudCB2YWxpZGF0aW9uIGVycm9ycy5cclxuICBcclxuICBJdCBvbmx5IHZhbGlkYXRlcyBlbnRpdGllcyBpZiB0aGUgRW50aXR5TWFuYWdlcidzXHJcbiAgW1tWYWxpZGF0aW9uT3B0aW9uc11dLnZhbGlkYXRlT25TYXZlIGlzIHRydWUuXHJcbiAgXHJcbiAgQHBhcmFtIGVudGl0aWVzVG9TYXZlIHtBcnJheSBvZiBFbnRpdHl9IFRoZSBsaXN0IG9mIGVudGl0aWVzIHRvIHNhdmUgKHRvIHZhbGlkYXRlKS5cclxuICBAcmV0dXJuIHtFcnJvcn0gVmFsaWRhdGlvbiBlcnJvciBvciBudWxsIGlmIG5vIGVycm9yXHJcbiAgKiovXHJcbiAgc2F2ZUNoYW5nZXNWYWxpZGF0ZU9uQ2xpZW50KGVudGl0aWVzVG9TYXZlOiBFbnRpdHlbXSkge1xyXG5cclxuICAgIGlmICh0aGlzLnZhbGlkYXRpb25PcHRpb25zLnZhbGlkYXRlT25TYXZlKSB7XHJcbiAgICAgIGxldCBmYWlsZWRFbnRpdGllcyA9IGVudGl0aWVzVG9TYXZlLmZpbHRlcihmdW5jdGlvbiAoZW50aXR5KSB7XHJcbiAgICAgICAgbGV0IGFzcGVjdCA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICAgICAgbGV0IGlzVmFsaWQgPSBhc3BlY3QuZW50aXR5U3RhdGUuaXNEZWxldGVkKCkgfHwgYXNwZWN0LnZhbGlkYXRlRW50aXR5KCk7XHJcbiAgICAgICAgcmV0dXJuICFpc1ZhbGlkO1xyXG4gICAgICB9KTtcclxuICAgICAgaWYgKGZhaWxlZEVudGl0aWVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBsZXQgdmFsRXJyb3IgPSBuZXcgRXJyb3IoXCJDbGllbnQgc2lkZSB2YWxpZGF0aW9uIGVycm9ycyBlbmNvdW50ZXJlZCAtIHNlZSB0aGUgZW50aXR5RXJyb3JzIGNvbGxlY3Rpb24gb24gdGhpcyBvYmplY3QgZm9yIG1vcmUgZGV0YWlsXCIpO1xyXG4gICAgICAgICh2YWxFcnJvciBhcyBhbnkpLmVudGl0eUVycm9ycyA9IGNyZWF0ZUVudGl0eUVycm9ycyhmYWlsZWRFbnRpdGllcyk7XHJcbiAgICAgICAgcmV0dXJuIHZhbEVycm9yOyAvLyBUT0RPOiB0eXBlIHRoaXMuXHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2ZpbmRFbnRpdHlHcm91cChlbnRpdHlUeXBlOiBFbnRpdHlUeXBlKSB7XHJcbiAgICByZXR1cm4gdGhpcy5fZW50aXR5R3JvdXBNYXBbZW50aXR5VHlwZS5uYW1lXTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGVtcGxveWVlVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJFbXBsb3llZVwiKTtcclxuICA+ICAgICAgbGV0IGVtcGxveWVlS2V5ID0gbmV3IEVudGl0eUtleShlbXBsb3llZVR5cGUsIDEpO1xyXG4gID4gICAgICBsZXQgZW1wbG95ZWUgPSBlbTEuZ2V0RW50aXR5QnlLZXkoZW1wbG95ZWVLZXkpO1xyXG4gID4gICAgICAvLyBlbXBsb3llZSB3aWxsIGVpdGhlciBiZSBhbiBlbnRpdHkgb3IgbnVsbC5cclxuICAqKi9cclxuICBnZXRFbnRpdHlCeUtleShlbnRpdHlLZXk6IEVudGl0eUtleSk6IEVudGl0eSB8IG51bGw7XHJcblxyXG4gIC8qKiAgXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgZW1wbG95ZWUgPSBlbTEuZ2V0RW50aXR5QnlLZXkoXCJFbXBsb3llZVwiLCAxKTtcclxuICA+ICAgICAgLy8gZW1wbG95ZWUgd2lsbCBlaXRoZXIgYmUgYW4gZW50aXR5IG9yIG51bGwuXHJcbiAgKiovXHJcbiAgZ2V0RW50aXR5QnlLZXkodHlwZU5hbWU6IHN0cmluZywga2V5VmFsdWVzOiBhbnkgfCBhbnlbXSk6IEVudGl0eSB8IG51bGw7XHJcblxyXG4gIC8qKiAgXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgZW1wbG95ZWVUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkVtcGxveWVlXCIpO1xyXG4gID4gICAgICBsZXQgZW1wbG95ZWUgPSBlbTEuZ2V0RW50aXR5QnlLZXkoZW1wbG95ZWVUeXBlLCAxKTtcclxuICA+ICAgICAgLy8gZW1wbG95ZWUgd2lsbCBlaXRoZXIgYmUgYW4gZW50aXR5IG9yIG51bGwuXHJcbiAgKiovXHJcbiAgZ2V0RW50aXR5QnlLZXkodHlwZTogRW50aXR5VHlwZSwga2V5VmFsdWVzOiBhbnkgfCBhbnlbXSk6IEVudGl0eSB8IG51bGw7XHJcblxyXG4gIC8qKiAgXHJcbiAgQXR0ZW1wdHMgdG8gbG9jYXRlIGFuIGVudGl0eSB3aXRoaW4gdGhpcyBFbnRpdHlNYW5hZ2VyIGJ5IGl0cyBbRW50aXR5S2V5XS5cclxuICBAcGFyYW0gZW50aXR5S2V5IC0gVGhlIFtbRW50aXR5S2V5XV0gb2YgdGhlIEVudGl0eSB0byBiZSBsb2NhdGVkLlxyXG4gIEBwYXJhbSB0eXBlIC0gVGhlIFtbRW50aXR5VHlwZV1dIGZvciB0aGlzIGtleS5cclxuICBAcGFyYW0gdHlwZU5hbWUgLSBUaGUgRW50aXR5VHlwZSBuYW1lIGZvciB0aGlzIGtleS5cclxuICBAcGFyYW0ga2V5VmFsdWVzIC0gVGhlIHZhbHVlcyBmb3IgdGhpcyBrZXkgLSB3aWxsIHVzdWFsbHkganVzdCBiZSBhIHNpbmdsZSB2YWx1ZTsgYW4gYXJyYXkgaXMgb25seSBuZWVkZWQgZm9yIG11bHRpcGFydCBrZXlzLiAgXHJcbiAgQHJldHVybiBBbiBFbnRpdHkgb3IgbnVsbDtcclxuICAqKi9cclxuICBnZXRFbnRpdHlCeUtleSguLi5hcmdzOiBhbnlbXSkge1xyXG4gICAgbGV0IGVudGl0eUtleSA9IGNyZWF0ZUVudGl0eUtleSh0aGlzLCBhcmdzKS5lbnRpdHlLZXk7XHJcbiAgICBsZXQgZW50aXR5VHlwZXMgPSBlbnRpdHlLZXkuX3N1YnR5cGVzIHx8IFtlbnRpdHlLZXkuZW50aXR5VHlwZV07XHJcbiAgICBsZXQgZTogRW50aXR5IHwgdW5kZWZpbmVkO1xyXG4gICAgLy8gaGFjayB1c2Ugb2Ygc29tZSB0byBzaW11bGF0ZSBtYXBGaXJzdCBsb2dpYy5cclxuICAgIGVudGl0eVR5cGVzLnNvbWUoKGV0KSA9PiB7XHJcbiAgICAgIGxldCBncm91cCA9IHRoaXMuX2ZpbmRFbnRpdHlHcm91cChldCk7XHJcbiAgICAgIC8vIGdyb3VwIHZlcnNpb24gb2YgZmluZEVudGl0eUJ5S2V5IGRvZXNuJ3QgY2FyZSBhYm91dCBlbnRpdHlUeXBlXHJcbiAgICAgIGUgPSBncm91cCAmJiBncm91cC5maW5kRW50aXR5QnlLZXkoZW50aXR5S2V5KTtcclxuICAgICAgcmV0dXJuIGUgIT0gbnVsbDtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGUgfHwgbnVsbDtcclxuICB9XHJcblxyXG4gIGZldGNoRW50aXR5QnlLZXkodHlwZU5hbWU6IHN0cmluZywga2V5VmFsdWVzOiBhbnkgfCBhbnlbXSwgY2hlY2tMb2NhbENhY2hlRmlyc3Q/OiBib29sZWFuKTogUHJvbWlzZTxJRW50aXR5QnlLZXlSZXN1bHQ+O1xyXG4gIGZldGNoRW50aXR5QnlLZXkoZW50aXR5VHlwZTogRW50aXR5VHlwZSwga2V5VmFsdWVzOiBhbnkgfCBhbnlbXSwgY2hlY2tMb2NhbENhY2hlRmlyc3Q/OiBib29sZWFuKTogUHJvbWlzZTxJRW50aXR5QnlLZXlSZXN1bHQ+O1xyXG4gIGZldGNoRW50aXR5QnlLZXkoZW50aXR5S2V5OiBFbnRpdHlLZXksIGNoZWNrTG9jYWxDYWNoZUZpcnN0PzogYm9vbGVhbik6IFByb21pc2U8SUVudGl0eUJ5S2V5UmVzdWx0PjtcclxuICAvKipcclxuICBBdHRlbXB0cyB0byBmZXRjaCBhbiBlbnRpdHkgZnJvbSB0aGUgc2VydmVyIGJ5IGl0cyBbW0VudGl0eUtleV1dIHdpdGhcclxuICBhbiBvcHRpb24gdG8gY2hlY2sgdGhlIGxvY2FsIGNhY2hlIGZpcnN0LiBOb3RlIHRoZSB0aGlzIEVudGl0eU1hbmFnZXIncyBxdWVyeU9wdGlvbnMubWVyZ2VTdHJhdGVneVxyXG4gIHdpbGwgYmUgdXNlZCB0byBtZXJnZSBhbnkgc2VydmVyIHNpZGUgZW50aXR5IHJldHVybmVkIGJ5IHRoaXMgbWV0aG9kLlxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGxldCBlbXBsb3llZVR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiRW1wbG95ZWVcIik7XHJcbiAgPiAgICAgbGV0IGVtcGxveWVlS2V5ID0gbmV3IEVudGl0eUtleShlbXBsb3llZVR5cGUsIDEpO1xyXG4gID4gICAgIGVtMS5mZXRjaEVudGl0eUJ5S2V5KGVtcGxveWVlS2V5KS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkge1xyXG4gID4gICAgICAgbGV0IGVtcGxveWVlID0gcmVzdWx0LmVudGl0eTtcclxuICA+ICAgICAgIGxldCBlbnRpdHlLZXkgPSByZXN1bHQuZW50aXR5S2V5O1xyXG4gID4gICAgICAgbGV0IGZyb21DYWNoZSA9IHJlc3VsdC5mcm9tQ2FjaGU7XHJcbiAgPiAgICAgfSk7XHJcbiAgQHBhcmFtIHR5cGVOYW1lICAtIFRoZSBFbnRpdHlUeXBlIG5hbWUgZm9yIHRoaXMga2V5LlxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlICAtIFRoZSBFbnRpdHlUeXBlIGZvciB0aGlzIGtleS5cclxuICBAcGFyYW0ga2V5VmFsdWVzIC0gVGhlIHZhbHVlcyBmb3IgdGhpcyBrZXkgLSB3aWxsIHVzdWFsbHkganVzdCBiZSBhIHNpbmdsZSB2YWx1ZTsgYW4gYXJyYXkgaXMgb25seSBuZWVkZWQgZm9yIG11bHRpcGFydCBrZXlzLlxyXG4gIEBwYXJhbSBlbnRpdHlLZXkgLSBUaGUgW1tFbnRpdHlLZXldXSBvZiB0aGUgRW50aXR5IHRvIGJlIGxvY2F0ZWQuXHJcbiAgQHBhcmFtIGNoZWNrTG9jYWxDYWNoZUZpcnN0IC0gKGRlZmF1bHQgPSBmYWxzZSkgLSBXaGV0aGVyIHRvIGNoZWNrIHRoaXMgRW50aXR5TWFuYWdlciBmaXJzdCBiZWZvcmUgZ29pbmcgdG8gdGhlIHNlcnZlci4gQnkgZGVmYXVsdCwgdGhlIHF1ZXJ5IHdpbGwgTk9UIGRvIHRoaXMuXHJcbiAgQHJldHVybiB7UHJvbWlzZX1cclxuICAgIC0gUHJvcGVydGllcyBvbiB0aGUgcHJvbWlzZSBzdWNjZXNzIHJlc3VsdFxyXG4gICAgICAtIGVudGl0eSB7T2JqZWN0fSBUaGUgZW50aXR5IHJldHVybmVkIG9yIG51bGxcclxuICAgICAgLSBlbnRpdHlLZXkge0VudGl0eUtleX0gVGhlIGVudGl0eUtleSBvZiB0aGUgZW50aXR5IHRvIGZldGNoLlxyXG4gICAgICAtIGZyb21DYWNoZSB7Qm9vbGVhbn0gV2hldGhlciB0aGlzIGVudGl0eSB3YXMgZmV0Y2hlZCBmcm9tIHRoZSBzZXJ2ZXIgb3Igd2FzIGZvdW5kIGluIHRoZSBsb2NhbCBjYWNoZS5cclxuICAqKi9cclxuICBmZXRjaEVudGl0eUJ5S2V5KC4uLmFyZ3M6IGFueVtdKSB7XHJcbiAgICBsZXQgZGF0YVNlcnZpY2UgPSBEYXRhU2VydmljZS5yZXNvbHZlKFt0aGlzLmRhdGFTZXJ2aWNlXSk7XHJcbiAgICBpZiAoKCFkYXRhU2VydmljZS5oYXNTZXJ2ZXJNZXRhZGF0YSkgfHwgdGhpcy5tZXRhZGF0YVN0b3JlLmhhc01ldGFkYXRhRm9yKGRhdGFTZXJ2aWNlLnNlcnZpY2VOYW1lKSkge1xyXG4gICAgICByZXR1cm4gZmV0Y2hFbnRpdHlCeUtleUNvcmUodGhpcywgYXJncyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gdGhpcy5mZXRjaE1ldGFkYXRhKGRhdGFTZXJ2aWNlKS50aGVuKCgpID0+IHtcclxuICAgICAgICByZXR1cm4gZmV0Y2hFbnRpdHlCeUtleUNvcmUodGhpcywgYXJncyk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgW0RlcHJlY2F0ZWRdIC0gQXR0ZW1wdHMgdG8gbG9jYXRlIGFuIGVudGl0eSB3aXRoaW4gdGhpcyBFbnRpdHlNYW5hZ2VyIGJ5IGl0cyAgW1tFbnRpdHlLZXldXS5cclxuICA+ICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICBsZXQgZW1wbG95ZWVUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkVtcGxveWVlXCIpO1xyXG4gID4gICAgIGxldCBlbXBsb3llZUtleSA9IG5ldyBFbnRpdHlLZXkoZW1wbG95ZWVUeXBlLCAxKTtcclxuICA+ICAgICBsZXQgZW1wbG95ZWUgPSBlbTEuZmluZEVudGl0eUJ5S2V5KGVtcGxveWVlS2V5KTtcclxuICA+ICAgICAvLyBlbXBsb3llZSB3aWxsIGVpdGhlciBiZSBhbiBlbnRpdHkgb3IgbnVsbC5cclxuICBAZGVwcmVjYXRlZCAgICBVc2UgZ2V0RW50aXR5QnlLZXkgaW5zdGVhZFxyXG4gIEBwYXJhbSBlbnRpdHlLZXkgLSBUaGUgIFtbRW50aXR5S2V5XV0gb2YgdGhlIEVudGl0eSB0byBiZSBsb2NhdGVkLlxyXG4gIEByZXR1cm4gQW4gRW50aXR5IG9yIG51bGw7XHJcbiAgKiovXHJcbiAgZmluZEVudGl0eUJ5S2V5KGVudGl0eUtleTogRW50aXR5S2V5KSB7XHJcbiAgICByZXR1cm4gdGhpcy5nZXRFbnRpdHlCeUtleShlbnRpdHlLZXkpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgR2VuZXJhdGVzIGEgdGVtcG9yYXJ5IGtleSBmb3IgdGhlIHNwZWNpZmllZCBlbnRpdHkuICBUaGlzIGlzIHVzZWQgdG8gaW5zdXJlIHRoYXQgbmV3bHlcclxuICBjcmVhdGVkIGVudGl0aWVzIGhhdmUgdW5pcXVlIGtleXMgYW5kIHRvIHJlZ2lzdGVyIHRoYXQgdGhlc2Uga2V5cyBhcmUgdGVtcG9yYXJ5IGFuZFxyXG4gIG5lZWQgdG8gYmUgYXV0b21hdGljYWxseSByZXBsYWNlZCB3aXRoICdyZWFsJyBrZXkgdmFsdWVzIG9uY2UgdGhlc2UgZW50aXRpZXMgYXJlIHNhdmVkLlxyXG4gIFxyXG4gIFRoZSBbW0VudGl0eU1hbmFnZXIua2V5R2VuZXJhdG9yQ3Rvcl1dIHByb3BlcnR5IGlzIHVzZWQgaW50ZXJuYWxseSBieSB0aGlzIG1ldGhvZCB0byBhY3R1YWxseSBnZW5lcmF0ZVxyXG4gIHRoZSBrZXlzIC0gU2VlIHRoZSAgS2V5R2VuZXJhdG9yIGludGVyZmFjZSBpbnRlcmZhY2UgZGVzY3JpcHRpb24gdG8gc2VlXHJcbiAgaG93IGEgY3VzdG9tIGtleSBnZW5lcmF0b3IgY2FuIGJlIHBsdWdnZWQgaW4uXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBjdXN0b21lciA9IGN1c3RUeXBlLmNyZWF0ZUVudGl0eSgpO1xyXG4gID4gICAgICBsZXQgY3VzdG9tZXJJZCA9IGVtLmdlbmVyYXRlVGVtcEtleVZhbHVlKGN1c3RvbWVyKTtcclxuICA+ICAgICAgLy8gVGhlICdjdXN0b21lcicgZW50aXR5ICdDdXN0b21lcklEJyBwcm9wZXJ0eSBpcyBub3cgc2V0IHRvIGEgbmV3bHkgZ2VuZXJhdGVkIHVuaXF1ZSBpZCB2YWx1ZVxyXG4gID4gICAgICAvLyBUaGlzIHByb3BlcnR5IHdpbGwgY2hhbmdlIGFnYWluIGFmdGVyIGEgc3VjY2Vzc2Z1bCBzYXZlIG9mIHRoZSAnY3VzdG9tZXInIGVudGl0eS5cclxuICA+ICBcclxuICA+ICAgICAgZW0xLnNhdmVDaGFuZ2VzKCkudGhlbiggZnVuY3Rpb24oIGRhdGEpIHtcclxuICA+ICAgICAgICAgIGxldCBzYW1lQ3VzdDEgPSBkYXRhLnJlc3VsdHNbMF07XHJcbiAgPiAgICAgICAgICAvLyBjdXN0MSA9PT0gc2FtZUN1c3QxO1xyXG4gID4gICAgICAgICAgLy8gYnV0IGN1c3QxLmdldFByb3BlcnR5KFwiQ3VzdG9tZXJJZFwiKSAhPSBjdXN0b21lcklkXHJcbiAgPiAgICAgICAgICAvLyBiZWNhdXNlIHRoZSBzZXJ2ZXIgd2lsbCBoYXZlIGdlbmVyYXRlZCBhIG5ldyBpZFxyXG4gID4gICAgICAgICAgLy8gYW5kIHRoZSBjbGllbnQgd2lsbCBoYXZlIGJlZW4gdXBkYXRlZCB3aXRoIHRoaXNcclxuICA+ICAgICAgICAgIC8vIG5ldyBpZC5cclxuICA+ICAgICAgfSlcclxuICBAcGFyYW0gZW50aXR5IC0gVGhlIEVudGl0eSB0byBnZW5lcmF0ZSBhIGtleSBmb3IuXHJcbiAgQHJldHVybiBUaGUgbmV3IGtleSB2YWx1ZVxyXG4gICoqL1xyXG4gIGdlbmVyYXRlVGVtcEtleVZhbHVlKGVudGl0eTogRW50aXR5KSB7XHJcbiAgICAvLyBUT0RPIC0gY2hlY2sgaWYgdGhpcyBlbnRpdHkgaXMgYXR0YWNoZWQgdG8gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5LCBcImVudGl0eVwiKS5pc0VudGl0eSgpLmNoZWNrKCk7XHJcbiAgICBsZXQgZW50aXR5VHlwZSA9IGVudGl0eS5lbnRpdHlUeXBlO1xyXG4gICAgbGV0IG5leHRLZXlWYWx1ZSA9IHRoaXMua2V5R2VuZXJhdG9yLmdlbmVyYXRlVGVtcEtleVZhbHVlKGVudGl0eVR5cGUpO1xyXG4gICAgbGV0IGtleVByb3AgPSBlbnRpdHlUeXBlLmtleVByb3BlcnRpZXNbMF07XHJcbiAgICBlbnRpdHkuc2V0UHJvcGVydHkoa2V5UHJvcC5uYW1lLCBuZXh0S2V5VmFsdWUpO1xyXG4gICAgZW50aXR5LmVudGl0eUFzcGVjdC5oYXNUZW1wS2V5ID0gdHJ1ZTtcclxuICAgIHJldHVybiBuZXh0S2V5VmFsdWU7XHJcbiAgfVxyXG5cclxuICBoYXNDaGFuZ2VzKCk6IGJvb2xlYW47XHJcbiAgaGFzQ2hhbmdlcyhlbnRpdHlUeXBlTmFtZXM6IHN0cmluZyB8IHN0cmluZ1tdKTogYm9vbGVhbjtcclxuICBoYXNDaGFuZ2VzKGVudGl0eVR5cGVzOiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdKTogYm9vbGVhbjtcclxuICAvKipcclxuICBSZXR1cm5zIHdoZXRoZXIgdGhlcmUgYXJlIGFueSBjaGFuZ2VkIGVudGl0aWVzIG9mIHRoZSBzcGVjaWZpZWQgW1tFbnRpdHlUeXBlXV1zLiBBICdjaGFuZ2VkJyBFbnRpdHkgaGFzXHJcbiAgaGFzIGFuIFtbRW50aXR5U3RhdGVdXSBvZiBlaXRoZXIgQWRkZWQsIE1vZGlmaWVkIG9yIERlbGV0ZWQuXHJcblxyXG4gIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGRldGVybWluZSBpZiBhbiBFbnRpdHlNYW5hZ2VyIGhhcyBhbnkgY2hhbmdlc1xyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgaWYgKCBlbTEuaGFzQ2hhbmdlcygpIHtcclxuICA+ICAgICAgICAgIC8vIGRvIHNvbWV0aGluZyBpbnRlcmVzdGluZ1xyXG4gID4gICAgICB9XHJcblxyXG4gIG9yIGlmIGl0IGhhcyBhbnkgY2hhbmdlcyBvbiB0byBhIHNwZWNpZmljIFtbRW50aXR5VHlwZV1dLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBpZiAoIGVtMS5oYXNDaGFuZ2VzKGN1c3RUeXBlKSB7XHJcbiAgPiAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgaW50ZXJlc3RpbmdcclxuICA+ICAgICAgfVxyXG5cclxuICBvciB0byBhIGNvbGxlY3Rpb24gb2YgW1tFbnRpdHlUeXBlXV1zXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBvcmRlclR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiT3JkZXJcIik7XHJcbiAgPiAgICAgIGlmICggZW0xLmhhc0NoYW5nZXMoIFtjdXN0VHlwZSwgb3JkZXJUeXBlXSkge1xyXG4gID4gICAgICAgICAgLy8gZG8gc29tZXRoaW5nIGludGVyZXN0aW5nXHJcbiAgPiAgICAgIH1cclxuICBAcGFyYW0gZW50aXR5VHlwZXMgLSBUaGUgW1tFbnRpdHlUeXBlXV0gb3IgRW50aXR5VHlwZXMgZm9yIHdoaWNoICdjaGFuZ2VkJyBlbnRpdGllcyB3aWxsIGJlIGZvdW5kLlxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlTmFtZXMgLSBUaGUgW1tFbnRpdHlUeXBlXV0gbmFtZSBvciBuYW1lcyBmb3Igd2hpY2ggJ2NoYW5nZWQnIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgQHJldHVybiBXaGV0aGVyIHRoZXJlIGFyZSBhbnkgY2hhbmdlZCBlbnRpdGllcyB0aGF0IG1hdGNoIHRoZSB0eXBlcyBzcGVjaWZpZWQuLlxyXG4gICoqL1xyXG4gIGhhc0NoYW5nZXMoZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nIHwgc3RyaW5nW10pIHtcclxuICAgIGlmICghdGhpcy5faGFzQ2hhbmdlcykgcmV0dXJuIGZhbHNlO1xyXG4gICAgaWYgKGVudGl0eVR5cGVzID09PSB1bmRlZmluZWQpIHJldHVybiB0aGlzLl9oYXNDaGFuZ2VzO1xyXG4gICAgcmV0dXJuIHRoaXMuX2hhc0NoYW5nZXNDb3JlKGVudGl0eVR5cGVzKTtcclxuICB9XHJcblxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICAvLyBiYWNrZG9vciB0byBcInJlYWxseVwiIGNoZWNrIGZvciBjaGFuZ2VzLlxyXG4gIF9oYXNDaGFuZ2VzQ29yZShlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCBzdHJpbmcgfCBzdHJpbmdbXSkge1xyXG4gICAgbGV0IGV0cyA9IGNoZWNrRW50aXR5VHlwZXModGhpcywgZW50aXR5VHlwZXMpO1xyXG4gICAgbGV0IGVudGl0eUdyb3VwcyA9IGdldEVudGl0eUdyb3Vwcyh0aGlzLCBldHMpO1xyXG4gICAgcmV0dXJuIGVudGl0eUdyb3Vwcy5zb21lKGZ1bmN0aW9uIChlZykge1xyXG4gICAgICByZXR1cm4gZWcgJiYgZWcuaGFzQ2hhbmdlcygpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBnZXRDaGFuZ2VzKCk6IEVudGl0eVtdO1xyXG4gIGdldENoYW5nZXMoZW50aXR5VHlwZU5hbWVzOiBzdHJpbmcgfCBzdHJpbmdbXSk6IEVudGl0eVtdO1xyXG4gIGdldENoYW5nZXMoZW50aXR5VHlwZXM6IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10pOiBFbnRpdHlbXTtcclxuICAvKipcclxuICBSZXR1cm5zIGEgYXJyYXkgb2YgYWxsIGNoYW5nZWQgZW50aXRpZXMgb2YgdGhlIHNwZWNpZmllZCBbW0VudGl0eVR5cGVdXXMuIEEgJ2NoYW5nZWQnIEVudGl0eSBoYXNcclxuICBoYXMgYW4gW1tFbnRpdHlTdGF0ZV1dIG9mIGVpdGhlciBBZGRlZCwgTW9kaWZpZWQgb3IgRGVsZXRlZC5cclxuICBcclxuICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBnZXQgYWxsIG9mIHRoZSBjaGFuZ2VkIGVudGl0aWVzIHdpdGhpbiBhbiBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY2hhbmdlZEVudGl0aWVzID0gZW0xLmdldENoYW5nZXMoKTtcclxuXHJcbiAgb3IgeW91IGNhbiBzcGVjaWZ5IHRoYXQgeW91IG9ubHkgd2FudCB0aGUgY2hhbmdlcyBvbiBhIHNwZWNpZmljIFtbRW50aXR5VHlwZV1dXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBjaGFuZ2VkQ3VzdG9tZXJzID0gZW0xLmdldENoYW5nZXMoY3VzdFR5cGUpO1xyXG5cclxuICBvciB0byBhIGNvbGxlY3Rpb24gb2YgW1tFbnRpdHlUeXBlXV1zXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBvcmRlclR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiT3JkZXJcIik7XHJcbiAgPiAgICAgIGxldCBjaGFuZ2VkQ3VzdG9tZXJzQW5kT3JkZXJzID0gZW0xLmdldENoYW5nZXMoW2N1c3RUeXBlLCBvcmRlclR5cGVdKTtcclxuICBAcGFyYW0gZW50aXR5VHlwZXMgLSBUaGUgW1tFbnRpdHlUeXBlXV0gb3IgRW50aXR5VHlwZXMgZm9yIHdoaWNoICdjaGFuZ2VkJyBlbnRpdGllcyB3aWxsIGJlIGZvdW5kLlxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlTmFtZXMgLSBUaGUgW1tFbnRpdHlUeXBlXV0gbmFtZSBvciBuYW1lcyBmb3Igd2hpY2ggJ2NoYW5nZWQnIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgQHJldHVybiBBbiBhcnJheSBvZiBFbnRpdGllc1xyXG4gICoqL1xyXG4gIGdldENoYW5nZXMoZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nIHwgc3RyaW5nW10pIHtcclxuICAgIGxldCBldHMgPSBjaGVja0VudGl0eVR5cGVzKHRoaXMsIGVudGl0eVR5cGVzKTtcclxuICAgIHJldHVybiBnZXRDaGFuZ2VzQ29yZSh0aGlzLCBldHMpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmVqZWN0cyAocmV2ZXJzZXMgdGhlIGVmZmVjdHMpIGFsbCBvZiB0aGUgYWRkaXRpb25zLCBtb2RpZmljYXRpb25zIGFuZCBkZWxldGVzIGZyb20gdGhpcyBFbnRpdHlNYW5hZ2VyLlxyXG4gIENhbGxzIFtbRW50aXR5QXNwZWN0LnJlamVjdENoYW5nZXNdXSBvbiBldmVyeSBjaGFuZ2VkIGVudGl0eSBpbiB0aGlzIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIHByZWV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgZW50aXRpZXMgPSBlbTEucmVqZWN0Q2hhbmdlcygpO1xyXG4gIEByZXR1cm4gVGhlIGVudGl0aWVzIHdob3NlIGNoYW5nZXMgd2VyZSByZWplY3RlZC4gVGhlc2UgZW50aXRpZXMgd2lsbCBhbGwgaGF2ZSBFbnRpdHlTdGF0ZXMgb2ZcclxuICBlaXRoZXIgJ1VuY2hhbmdlZCcgb3IgJ0RldGFjaGVkJ1xyXG4gICoqL1xyXG4gIHJlamVjdENoYW5nZXMoKSB7XHJcbiAgICBpZiAoIXRoaXMuX2hhc0NoYW5nZXMpIHJldHVybiBbXTtcclxuICAgIGxldCBjaGFuZ2VzID0gZ2V0Q2hhbmdlc0NvcmUodGhpcyk7XHJcbiAgICAvLyBuZXh0IGxpbmUgc3RvcHMgaW5kaXZpZHVhbCByZWplY3QgY2hhbmdlcyBmcm9tIGVhY2ggY2FsbGluZyBfaGFzQ2hhbmdlc0NvcmVcclxuICAgIGxldCBhc3BlY3RzID0gY2hhbmdlcy5tYXAoZnVuY3Rpb24gKGUpIHtcclxuICAgICAgcmV0dXJuIGUuZW50aXR5QXNwZWN0Ll9jaGVja09wZXJhdGlvbihcInJlamVjdENoYW5nZXNcIik7XHJcbiAgICB9KTtcclxuICAgIHRoaXMuX2hhc0NoYW5nZXMgPSBmYWxzZTtcclxuICAgIGFzcGVjdHMuZm9yRWFjaChmdW5jdGlvbiAoYXNwZWN0KSB7XHJcbiAgICAgIGFzcGVjdC5yZWplY3RDaGFuZ2VzKCk7XHJcbiAgICB9KTtcclxuICAgIHRoaXMuaGFzQ2hhbmdlc0NoYW5nZWQucHVibGlzaCh7IGVudGl0eU1hbmFnZXI6IHRoaXMsIGhhc0NoYW5nZXM6IGZhbHNlIH0pO1xyXG4gICAgcmV0dXJuIGNoYW5nZXM7XHJcbiAgfVxyXG5cclxuICBnZXRFbnRpdGllcyhlbnRpdHlUeXBlTmFtZXM/OiBzdHJpbmcgfCBzdHJpbmdbXSwgZW50aXR5U3RhdGVzPzogRW50aXR5U3RhdGUgfCBFbnRpdHlTdGF0ZVtdKTogRW50aXR5W107XHJcbiAgZ2V0RW50aXRpZXMoZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdLCBlbnRpdHlTdGF0ZXM/OiBFbnRpdHlTdGF0ZSB8IEVudGl0eVN0YXRlW10pOiBFbnRpdHlbXTtcclxuICAvKipcclxuICBSZXR1cm5zIGEgYXJyYXkgb2YgYWxsIGVudGl0aWVzIG9mIHRoZSBzcGVjaWZpZWQgW1tFbnRpdHlUeXBlXV1zIHdpdGggdGhlIHNwZWNpZmllZCBbW0VudGl0eVN0YXRlXV1zLlxyXG5cclxuICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBnZXQgYWxsIG9mIHRoZSBlbnRpdGllcyB3aXRoaW4gYW4gRW50aXR5TWFuYWdlclxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGVudGl0aWVzID0gZW0xLmdldEVudGl0aWVzKCk7XHJcblxyXG4gIG9yIHlvdSBjYW4gc3BlY2lmeSB0aGF0IHlvdSBvbmx5IHdhbnQgdGhlIGNoYW5nZXMgb24gYSBzcGVjaWZpYyBbW0VudGl0eVR5cGVdXVxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgY3VzdG9tZXJzID0gZW0xLmdldEVudGl0aWVzKGN1c3RUeXBlKTtcclxuXHJcbiAgb3IgdG8gYSBjb2xsZWN0aW9uIG9mIFtbRW50aXR5VHlwZV1dc1xyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBwcmVleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgb3JkZXJUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyXCIpO1xyXG4gID4gICAgICBsZXQgY3VzdG9tZXJzQW5kT3JkZXJzID0gZW0xLmdldENoYW5nZXMoW2N1c3RUeXBlLCBvcmRlclR5cGVdKTtcclxuXHJcbiAgWW91IGNhbiBhbHNvIGFzayBmb3IgZW50aXRpZXMgd2l0aCBhIHBhcnRpY3VsYXIgW1tFbnRpdHlTdGF0ZV1dIG9yIEVudGl0eVN0YXRlcy5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgcHJlZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IG9yZGVyVHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJPcmRlclwiKTtcclxuICA+ICAgICAgbGV0IGFkZGVkQ3VzdG9tZXJzQW5kT3JkZXJzID0gZW0xLmdldEVudGl0aWVzKFtjdXN0VHlwZSwgb3JkZXJUeXBlXSwgRW50aXR5U3RhdGUuQWRkZWQpO1xyXG4gXHJcbiAgQHBhcmFtIGVudGl0eVR5cGVOYW1lIC0gVGhlIFtbRW50aXR5VHlwZV1dIG5hbWUgb3IgbmFtZXMgZm9yIHdoaWNoIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgSWYgdGhpcyBwYXJhbWV0ZXIgaXMgb21pdHRlZCwgYWxsIEVudGl0eVR5cGVzIGFyZSBzZWFyY2hlZC4gIFxyXG4gIEBwYXJhbSBlbnRpdHlUeXBlcyAtIFRoZSBbW0VudGl0eVR5cGVdXSBvciBFbnRpdHlUeXBlcyBmb3Igd2hpY2ggZW50aXRpZXMgd2lsbCBiZSBmb3VuZC5cclxuICBJZiB0aGlzIHBhcmFtZXRlciBpcyBvbWl0dGVkLCBhbGwgRW50aXR5VHlwZXMgYXJlIHNlYXJjaGVkLiBcclxuICBAcGFyYW0gZW50aXR5U3RhdGVzIC0gVGhlIFtbRW50aXR5U3RhdGVdXXMgZm9yIHdoaWNoIGVudGl0aWVzIHdpbGwgYmUgZm91bmQuXHJcbiAgSWYgdGhpcyBwYXJhbWV0ZXIgaXMgb21pdHRlZCwgZW50aXRpZXMgb2YgYWxsIEVudGl0eVN0YXRlcyBhcmUgcmV0dXJuZWQuXHJcbiAgQHJldHVybiBBbiBhcnJheSBvZiBFbnRpdGllc1xyXG4gICoqL1xyXG4gIGdldEVudGl0aWVzKGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHN0cmluZyB8IHN0cmluZ1tdLCBlbnRpdHlTdGF0ZXM/OiBFbnRpdHlTdGF0ZSB8IEVudGl0eVN0YXRlW10pIHtcclxuICAgIGxldCBlbnRUeXBlcyA9IGNoZWNrRW50aXR5VHlwZXModGhpcywgZW50aXR5VHlwZXMpO1xyXG4gICAgYXNzZXJ0UGFyYW0oZW50aXR5U3RhdGVzLCBcImVudGl0eVN0YXRlc1wiKS5pc09wdGlvbmFsKCkuaXNFbnVtT2YoRW50aXR5U3RhdGUpLm9yKCkuaXNOb25FbXB0eUFycmF5KCkuaXNFbnVtT2YoRW50aXR5U3RhdGUpLmNoZWNrKCk7XHJcblxyXG4gICAgbGV0IHN0YXRlcyA9IHZhbGlkYXRlRW50aXR5U3RhdGVzKHRoaXMsIGVudGl0eVN0YXRlcyk7XHJcbiAgICByZXR1cm4gZ2V0RW50aXRpZXNDb3JlKHRoaXMsIGVudFR5cGVzLCBzdGF0ZXMpO1xyXG4gIH1cclxuXHJcblxyXG4gIC8vIHByb3RlY3RlZCBtZXRob2RzXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX25vdGlmeVN0YXRlQ2hhbmdlKGVudGl0eTogRW50aXR5LCBuZWVkc1NhdmU6IGJvb2xlYW4pIHtcclxuICAgIGxldCBlY0FyZ3MgPSB7IGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uLkVudGl0eVN0YXRlQ2hhbmdlLCBlbnRpdHk6IGVudGl0eSB9O1xyXG5cclxuICAgIGlmIChuZWVkc1NhdmUpIHtcclxuICAgICAgaWYgKCF0aGlzLl9oYXNDaGFuZ2VzKSB0aGlzLl9zZXRIYXNDaGFuZ2VzKHRydWUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gY2FsbGVkIHdoZW4gcmVqZWN0aW5nIGEgY2hhbmdlIG9yIG1lcmdpbmcgYW4gdW5jaGFuZ2VkIHJlY29yZC5cclxuICAgICAgLy8gTk9URTogdGhpcyBjYW4gYmUgc2xvdyB3aXRoIGxvdHMgb2YgZW50aXRpZXMgaW4gdGhlIGNhY2hlLlxyXG4gICAgICAvLyBzbyBkZWZlciBpdCBkdXJpbmcgYSBxdWVyeS9pbXBvcnQgb3Igc2F2ZSBhbmQgY2FsbCBpdCBvbmNlIHdoZW4gY29tcGxldGUgKCBpZiBuZWVkZWQpLlxyXG4gICAgICBpZiAodGhpcy5faGFzQ2hhbmdlcykge1xyXG4gICAgICAgIGlmICh0aGlzLmlzTG9hZGluZykge1xyXG4gICAgICAgICAgdGhpcy5faGFzQ2hhbmdlc0FjdGlvbiA9IHRoaXMuX2hhc0NoYW5nZXNBY3Rpb24gfHwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB0aGlzLl9zZXRIYXNDaGFuZ2VzKG51bGwpO1xyXG4gICAgICAgICAgICB0aGlzLmVudGl0eUNoYW5nZWQucHVibGlzaChlY0FyZ3MpO1xyXG4gICAgICAgICAgfS5iaW5kKHRoaXMpO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLl9zZXRIYXNDaGFuZ2VzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICB0aGlzLmVudGl0eUNoYW5nZWQucHVibGlzaChlY0FyZ3MpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3NldEhhc0NoYW5nZXMoaGFzQ2hhbmdlcz86IGJvb2xlYW4pIHtcclxuICAgIGlmIChoYXNDaGFuZ2VzID09IG51bGwpIGhhc0NoYW5nZXMgPSB0aGlzLl9oYXNDaGFuZ2VzQ29yZSgpO1xyXG4gICAgbGV0IGhhZENoYW5nZXMgPSB0aGlzLl9oYXNDaGFuZ2VzO1xyXG4gICAgdGhpcy5faGFzQ2hhbmdlcyA9IGhhc0NoYW5nZXM7XHJcbiAgICBpZiAoaGFzQ2hhbmdlcyAhPT0gaGFkQ2hhbmdlcykge1xyXG4gICAgICB0aGlzLmhhc0NoYW5nZXNDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlNYW5hZ2VyOiB0aGlzLCBoYXNDaGFuZ2VzOiBoYXNDaGFuZ2VzIH0pO1xyXG4gICAgfVxyXG4gICAgdGhpcy5faGFzQ2hhbmdlc0FjdGlvbiA9IHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9saW5rUmVsYXRlZEVudGl0aWVzKGVudGl0eTogRW50aXR5KSB7XHJcbiAgICBsZXQgZW0gPSB0aGlzO1xyXG4gICAgbGV0IGVudGl0eUFzcGVjdCA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICAvLyB3ZSBkbyBub3Qgd2FudCBlbnRpdHlTdGF0ZSB0byBjaGFuZ2UgYXMgYSByZXN1bHQgb2YgbGlua2FnZS5cclxuICAgIGNvcmUudXNpbmcoZW0sIFwiaXNMb2FkaW5nXCIsIHRydWUsIGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgICAgIGxldCB1bmF0dGFjaGVkTWFwID0gZW0uX3VuYXR0YWNoZWRDaGlsZHJlbk1hcDtcclxuICAgICAgbGV0IGVudGl0eUtleSA9IGVudGl0eUFzcGVjdC5nZXRLZXkoKTtcclxuICAgICAgbGV0IGVudGl0eVR5cGUgPSBlbnRpdHlLZXkuZW50aXR5VHlwZTtcclxuXHJcbiAgICAgIHdoaWxlIChlbnRpdHlUeXBlKSB7XHJcbiAgICAgICAgbGV0IGtleXN0cmluZyA9IGVudGl0eUtleS50b1N0cmluZyhlbnRpdHlUeXBlKTtcclxuXHJcbiAgICAgICAgLy8gYXR0YWNoIGFueSB1bmF0dGFjaGVkQ2hpbGRyZW5cclxuICAgICAgICBsZXQgdHVwbGVzID0gdW5hdHRhY2hlZE1hcC5nZXRUdXBsZXNCeVN0cmluZyhrZXlzdHJpbmcpO1xyXG4gICAgICAgIGlmICh0dXBsZXMpIHtcclxuICAgICAgICAgIHR1cGxlcy5zbGljZSgwKS5mb3JFYWNoKGZ1bmN0aW9uICh0cGwpIHtcclxuXHJcbiAgICAgICAgICAgIGxldCB1bmF0dGFjaGVkQ2hpbGRyZW4gPSB0cGwuY2hpbGRyZW4uZmlsdGVyKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIGUuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlICE9PSBFbnRpdHlTdGF0ZS5EZXRhY2hlZDtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICBsZXQgY2hpbGRUb1BhcmVudE5wOiBOYXZpZ2F0aW9uUHJvcGVydHk7XHJcbiAgICAgICAgICAgIGxldCBwYXJlbnRUb0NoaWxkTnA6IE5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuXHJcbiAgICAgICAgICAgIC8vIG5wIGlzIHVzdWFsbHkgY2hpbGRUb1BhcmVudE5wXHJcbiAgICAgICAgICAgIC8vIGV4Y2VwdCB3aXRoIHVuaWRpcmVjdGlvbmFsIDEtbiB3aGVyZSBpdCBpcyBwYXJlbnRUb0NoaWxkTnA7XHJcbiAgICAgICAgICAgIGxldCBucCA9IHRwbC5uYXZpZ2F0aW9uUHJvcGVydHk7XHJcblxyXG4gICAgICAgICAgICBsZXQgaW52ZXJzZU5wID0gbnAuaW52ZXJzZTtcclxuICAgICAgICAgICAgaWYgKGludmVyc2VOcCkge1xyXG4gICAgICAgICAgICAgIC8vIGJpZGlyZWN0aW9uYWxcclxuICAgICAgICAgICAgICBjaGlsZFRvUGFyZW50TnAgPSBucDtcclxuICAgICAgICAgICAgICBwYXJlbnRUb0NoaWxkTnAgPSBpbnZlcnNlTnA7XHJcblxyXG4gICAgICAgICAgICAgIGlmIChwYXJlbnRUb0NoaWxkTnAuaXNTY2FsYXIpIHtcclxuICAgICAgICAgICAgICAgIGxldCBvbmx5Q2hpbGQgPSB1bmF0dGFjaGVkQ2hpbGRyZW5bMF07XHJcbiAgICAgICAgICAgICAgICBlbnRpdHkuc2V0UHJvcGVydHkocGFyZW50VG9DaGlsZE5wLm5hbWUsIG9ubHlDaGlsZCk7XHJcbiAgICAgICAgICAgICAgICBvbmx5Q2hpbGQuc2V0UHJvcGVydHkoY2hpbGRUb1BhcmVudE5wLm5hbWUsIGVudGl0eSk7XHJcbiAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50Q2hpbGRyZW4gPSBlbnRpdHkuZ2V0UHJvcGVydHkocGFyZW50VG9DaGlsZE5wLm5hbWUpO1xyXG4gICAgICAgICAgICAgICAgdW5hdHRhY2hlZENoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICAgIGN1cnJlbnRDaGlsZHJlbi5wdXNoKGNoaWxkKTtcclxuICAgICAgICAgICAgICAgICAgY2hpbGQuc2V0UHJvcGVydHkoY2hpbGRUb1BhcmVudE5wLm5hbWUsIGVudGl0eSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgdW5hdHRhY2hlZE1hcC5yZW1vdmVDaGlsZHJlbihrZXlzdHJpbmcsIGNoaWxkVG9QYXJlbnROcCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgLy8gdW5pZGlyZWN0aW9uYWxcclxuICAgICAgICAgICAgICAvLyBpZiAobnAuaXNTY2FsYXIgfHwgbnAucGFyZW50VHlwZSAhPT0gZW50aXR5LmVudGl0eVR5cGUpIHtcclxuICAgICAgICAgICAgICBpZiAobnAuaXNTY2FsYXIpIHtcclxuICAgICAgICAgICAgICAgIC8vIG4gLT4gMSAgZWc6IGNoaWxkOiBPcmRlckRldGFpbCBwYXJlbnQ6IFByb2R1Y3RcclxuICAgICAgICAgICAgICAgIC8vIDEgLT4gMSBlZyBjaGlsZDogRW1wbG95ZWUgcGFyZW50OiBFbXBsb3llZSAoIG9ubHkgTWFuYWdlciwgbm8gRGlyZWN0UmVwb3J0cyBwcm9wZXJ0eSlcclxuICAgICAgICAgICAgICAgIGNoaWxkVG9QYXJlbnROcCA9IG5wO1xyXG4gICAgICAgICAgICAgICAgdW5hdHRhY2hlZENoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICAgIGNoaWxkLnNldFByb3BlcnR5KGNoaWxkVG9QYXJlbnROcC5uYW1lLCBlbnRpdHkpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB1bmF0dGFjaGVkTWFwLnJlbW92ZUNoaWxkcmVuKGtleXN0cmluZywgY2hpbGRUb1BhcmVudE5wKTtcclxuICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gMSAtPiBuICBlZzogcGFyZW50OiBSZWdpb24gY2hpbGQ6IFRlcnJcclxuICAgICAgICAgICAgICAgIC8vIFRPRE86IG5lZWQgdG8gcmVtb3ZlIHVuYXR0YWNoZWQgY2hpbGRyZW4gZnJvbSB0aGUgbWFwIGFmdGVyIHRoaXM7IG9ubHkgYSBwZXJmIGlzc3VlLlxyXG4gICAgICAgICAgICAgICAgcGFyZW50VG9DaGlsZE5wID0gbnA7XHJcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudENoaWxkcmVuID0gZW50aXR5LmdldFByb3BlcnR5KHBhcmVudFRvQ2hpbGROcC5uYW1lKTtcclxuICAgICAgICAgICAgICAgIHVuYXR0YWNoZWRDaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICAgICAgICAvLyB3ZSBrbm93IGlmIGNhbid0IGFscmVhZHkgYmUgdGhlcmUuXHJcbiAgICAgICAgICAgICAgICAgIGN1cnJlbnRDaGlsZHJlbi5fcHVzaChjaGlsZCk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbnRpdHlUeXBlID0gZW50aXR5VHlwZS5iYXNlRW50aXR5VHlwZTsgLy8gbG9vayBmb3IgcmVsYXRpb25zaGlwcyB1cCB0aGUgaGllcmFyY2h5XHJcbiAgICAgIH1cclxuXHJcblxyXG4gICAgICAvLyBub3cgYWRkIHRvIHVuYXR0YWNoZWRNYXAgaWYgbmVlZGVkLlxyXG4gICAgICBlbnRpdHkuZW50aXR5VHlwZS5uYXZpZ2F0aW9uUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChucCkge1xyXG4gICAgICAgIGlmIChucC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgbGV0IHZhbHVlID0gZW50aXR5LmdldFByb3BlcnR5KG5wLm5hbWUpO1xyXG4gICAgICAgICAgLy8gcHJvcGVydHkgaXMgYWxyZWFkeSBsaW5rZWQgdXBcclxuICAgICAgICAgIGlmICh2YWx1ZSkgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gZmlyc3QgZGV0ZXJtaW5lIGlmIG5wIGNvbnRhaW5zIGEgcGFyZW50IG9yIGNoaWxkXHJcbiAgICAgICAgLy8gaGF2aW5nIGEgcGFyZW50S2V5IG1lYW5zIHRoYXQgdGhpcyBpcyBhIGNoaWxkXHJcbiAgICAgICAgLy8gaWYgYSBwYXJlbnQgdGhlbiBubyBuZWVkIGZvciBtb3JlIHdvcmsgYmVjYXVzZSBjaGlsZHJlbiB3aWxsIGF0dGFjaCB0byBpdC5cclxuICAgICAgICBsZXQgcGFyZW50S2V5ID0gZW50aXR5QXNwZWN0LmdldFBhcmVudEtleShucCk7XHJcbiAgICAgICAgaWYgKHBhcmVudEtleSkge1xyXG4gICAgICAgICAgLy8gY2hlY2sgZm9yIGVtcHR5IGtleXMgLSBtZWFuaW5nIHRoYXQgcGFyZW50IGlkJ3MgYXJlIG5vdCB5ZXQgc2V0LlxyXG4gICAgICAgICAgaWYgKHBhcmVudEtleS5faXNFbXB0eSgpKSByZXR1cm47XHJcbiAgICAgICAgICAvLyBpZiBhIGNoaWxkIC0gbG9vayBmb3IgcGFyZW50IGluIHRoZSBlbSBjYWNoZVxyXG4gICAgICAgICAgaWYgKG5wLmludkZvcmVpZ25LZXlOYW1lcy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgLy8gbnAgcmVsYXRlcyB0byBub24tUEsgcHJvcGVydHkgb2YgcGFyZW50IGVudGl0eVxyXG4gICAgICAgICAgICBjb25zdCBxdWVyeSA9IG5ldyBFbnRpdHlRdWVyeShwYXJlbnRLZXkuZW50aXR5VHlwZS5kZWZhdWx0UmVzb3VyY2VOYW1lKS53aGVyZShucC5pbnZGb3JlaWduS2V5TmFtZXNbMF0sICdlcScsIHBhcmVudEtleS52YWx1ZXNbMF0pO1xyXG4gICAgICAgICAgICBjb25zdCBxcmVzdWx0ID0gZW0uZXhlY3V0ZVF1ZXJ5TG9jYWxseShxdWVyeSk7XHJcbiAgICAgICAgICAgIGlmIChxcmVzdWx0Lmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICAgIGxldCBwYXJlbnQgPSBxcmVzdWx0WzBdO1xyXG4gICAgICAgICAgICAgIGVudGl0eS5zZXRQcm9wZXJ0eShucC5uYW1lLCBwYXJlbnQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBucCByZWxhdGVzIHRvIFBLIG9mIHBhcmVudCBlbnRpdHlcclxuICAgICAgICAgICAgbGV0IHBhcmVudCA9IGVtLmdldEVudGl0eUJ5S2V5KHBhcmVudEtleSk7XHJcbiAgICAgICAgICAgIGlmIChwYXJlbnQpIHtcclxuICAgICAgICAgICAgICAvLyBpZiBmb3VuZCBob29rIGl0IHVwXHJcbiAgICAgICAgICAgICAgZW50aXR5LnNldFByb3BlcnR5KG5wLm5hbWUsIHBhcmVudCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgLy8gZWxzZSBhZGQgcGFyZW50IHRvIHVucmVzb2x2ZWRQYXJlbnRNYXA7XHJcbiAgICAgICAgICAgICAgdW5hdHRhY2hlZE1hcC5hZGRDaGlsZChwYXJlbnRLZXksIG5wLCBlbnRpdHkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIGlmIChucC5pbnZlcnNlICYmIG5wLmludmVyc2UuaW52Rm9yZWlnbktleU5hbWVzLmxlbmd0aCkge1xyXG4gICAgICAgICAgLy8gbnAgcmVsYXRlcyB0byBub24tUEsgcHJvcGVydHkgb2YgcGFyZW50IGVudGl0eTsgcXVlcnkgZW50aXRpZXMgYnkgRktcclxuICAgICAgICAgIGNvbnN0IGFrVmFsdWUgPSBlbnRpdHkuZ2V0UHJvcGVydHkobnAuaW52ZXJzZS5pbnZGb3JlaWduS2V5TmFtZXNbMF0pO1xyXG4gICAgICAgICAgY29uc3QgcXVlcnkgPSBuZXcgRW50aXR5UXVlcnkobnAuZW50aXR5VHlwZS5kZWZhdWx0UmVzb3VyY2VOYW1lKS53aGVyZShucC5pbnZGb3JlaWduS2V5TmFtZXNbMF0sICdlcScsIGFrVmFsdWUpO1xyXG4gICAgICAgICAgY29uc3QgcXJlc3VsdCA9IGVtLmV4ZWN1dGVRdWVyeUxvY2FsbHkocXVlcnkpO1xyXG4gICAgICAgICAgcXJlc3VsdC5mb3JFYWNoKChjaGlsZDogRW50aXR5KSA9PiB7XHJcbiAgICAgICAgICAgIGNoaWxkLnNldFByb3BlcnR5KG5wLmludmVyc2UubmFtZSwgZW50aXR5KTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyBoYW5kbGUgdW5pZGlyZWN0aW9uYWwgMS14IHdoZXJlIHdlIHNldCB4LmZrXHJcbiAgICAgIGVudGl0eS5lbnRpdHlUeXBlLmZvcmVpZ25LZXlQcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKGZrUHJvcCkge1xyXG4gICAgICAgIGxldCBpbnZOcCA9IGZrUHJvcC5pbnZlcnNlTmF2aWdhdGlvblByb3BlcnR5O1xyXG4gICAgICAgIGlmICghaW52TnApIHJldHVybjtcclxuICAgICAgICAvLyB1bmlkaXJlY3Rpb25hbCBmayBwcm9wcyBvbmx5XHJcbiAgICAgICAgbGV0IGZrVmFsdWUgPSBlbnRpdHkuZ2V0UHJvcGVydHkoZmtQcm9wLm5hbWUpO1xyXG4gICAgICAgIGxldCBwYXJlbnRLZXkgPSBuZXcgRW50aXR5S2V5KGludk5wLnBhcmVudFR5cGUsIFtma1ZhbHVlXSk7XHJcbiAgICAgICAgbGV0IHBhcmVudCA9IGVtLmdldEVudGl0eUJ5S2V5KHBhcmVudEtleSk7XHJcblxyXG4gICAgICAgIGlmIChwYXJlbnQpIHtcclxuICAgICAgICAgIGlmIChpbnZOcC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgICBwYXJlbnQuc2V0UHJvcGVydHkoaW52TnAubmFtZSwgZW50aXR5KTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGlmIChlbS5pc0xvYWRpbmcpIHtcclxuICAgICAgICAgICAgICBwYXJlbnQuZ2V0UHJvcGVydHkoaW52TnAubmFtZSkuX3B1c2goZW50aXR5KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICBwYXJlbnQuZ2V0UHJvcGVydHkoaW52TnAubmFtZSkucHVzaChlbnRpdHkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIC8vIGVsc2UgYWRkIHBhcmVudCB0byB1bnJlc29sdmVkUGFyZW50TWFwO1xyXG4gICAgICAgICAgdW5hdHRhY2hlZE1hcC5hZGRDaGlsZChwYXJlbnRLZXksIGludk5wLCBlbnRpdHkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9KTtcclxuXHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfYXR0YWNoRW50aXR5Q29yZShlbnRpdHk6IEVudGl0eSwgZW50aXR5U3RhdGU6IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5OiBNZXJnZVN0cmF0ZWd5KSB7XHJcbiAgICBsZXQgZ3JvdXAgPSBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cCh0aGlzLCBlbnRpdHkuZW50aXR5VHlwZSk7XHJcbiAgICBsZXQgYXR0YWNoZWRFbnRpdHkgPSBncm91cC5hdHRhY2hFbnRpdHkoZW50aXR5LCBlbnRpdHlTdGF0ZSwgbWVyZ2VTdHJhdGVneSk7XHJcbiAgICB0aGlzLl9saW5rUmVsYXRlZEVudGl0aWVzKGF0dGFjaGVkRW50aXR5KTtcclxuICAgIHJldHVybiBhdHRhY2hlZEVudGl0eTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF91cGRhdGVGa1ZhbChma1Byb3A6IERhdGFQcm9wZXJ0eSwgb2xkVmFsdWU6IGFueSwgbmV3VmFsdWU6IGFueSkge1xyXG4gICAgbGV0IGdyb3VwID0gdGhpcy5fZW50aXR5R3JvdXBNYXBbZmtQcm9wLnBhcmVudFR5cGUubmFtZV07XHJcbiAgICBpZiAoIWdyb3VwKSByZXR1cm47XHJcbiAgICBncm91cC5fdXBkYXRlRmtWYWwoZmtQcm9wLCBvbGRWYWx1ZSwgbmV3VmFsdWUpO1xyXG4gIH1cclxufVxyXG5cclxuRW50aXR5TWFuYWdlci5wcm90b3R5cGUuXyR0eXBlTmFtZSA9IFwiRW50aXR5TWFuYWdlclwiO1xyXG5cclxuQnJlZXplRXZlbnQuYnViYmxlRXZlbnQoRW50aXR5TWFuYWdlci5wcm90b3R5cGUpO1xyXG5cclxuZnVuY3Rpb24gY2xlYXJTZXJ2ZXJFcnJvcnMoZW50aXRpZXM6IEVudGl0eVtdKSB7XHJcbiAgZW50aXRpZXMuZm9yRWFjaChmdW5jdGlvbiAoZW50aXR5KSB7XHJcbiAgICBsZXQgc2VydmVyS2V5czogc3RyaW5nW10gPSBbXTtcclxuICAgIGxldCBhc3BlY3QgPSBlbnRpdHkuZW50aXR5QXNwZWN0O1xyXG4gICAgY29yZS5vYmplY3RGb3JFYWNoKGFzcGVjdC5fdmFsaWRhdGlvbkVycm9ycywgZnVuY3Rpb24gKGtleSwgdmUpIHtcclxuICAgICAgaWYgKHZlLmlzU2VydmVyRXJyb3IpIHNlcnZlcktleXMucHVzaChrZXkpO1xyXG4gICAgfSk7XHJcbiAgICBpZiAoc2VydmVyS2V5cy5sZW5ndGggPT09IDApIHJldHVybjtcclxuICAgIGFzcGVjdC5fcHJvY2Vzc1ZhbGlkYXRpb25PcEFuZFB1Ymxpc2goZnVuY3Rpb24gKCkge1xyXG4gICAgICBzZXJ2ZXJLZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xyXG4gICAgICAgIGFzcGVjdC5fcmVtb3ZlVmFsaWRhdGlvbkVycm9yKGtleSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUVudGl0eUVycm9ycyhlbnRpdGllczogRW50aXR5W10pIHtcclxuICBsZXQgZW50aXR5RXJyb3JzOiBFbnRpdHlFcnJvcltdID0gW107XHJcbiAgZW50aXRpZXMuZm9yRWFjaCgoZW50aXR5KSA9PiB7XHJcbiAgICBjb3JlLm9iamVjdEZvckVhY2goZW50aXR5LmVudGl0eUFzcGVjdC5fdmFsaWRhdGlvbkVycm9ycywgZnVuY3Rpb24gKGtleSwgdmUpIHtcclxuICAgICAgbGV0IGNmZyA9IGNvcmUuZXh0ZW5kKHtcclxuICAgICAgICBlbnRpdHk6IGVudGl0eSxcclxuICAgICAgICBlcnJvck5hbWU6IHZlLnZhbGlkYXRvci5uYW1lXHJcbiAgICAgIH0sIHZlLCBbXCJlcnJvck1lc3NhZ2VcIiwgXCJwcm9wZXJ0eU5hbWVcIiwgXCJpc1NlcnZlckVycm9yXCIsIFwiY3VzdG9tXCJdKSBhcyBFbnRpdHlFcnJvcjtcclxuICAgICAgZW50aXR5RXJyb3JzLnB1c2goY2ZnKTtcclxuICAgIH0pO1xyXG4gIH0pO1xyXG4gIHJldHVybiBlbnRpdHlFcnJvcnM7XHJcbn1cclxuXHJcblxyXG5mdW5jdGlvbiBwcm9jZXNzU2VydmVyRXJyb3JzKHNhdmVDb250ZXh0OiBTYXZlQ29udGV4dCwgc2F2ZUVycm9yOiBTYXZlRXJyb3JGcm9tU2VydmVyKSB7XHJcbiAgLy8gY29udmVydGluZyBJU2F2ZUVycm9yRnJvbVNlcnZlciAtPiBJU2F2ZUVycm9yXHJcbiAgbGV0IHNlcnZlckVycm9ycyA9IHNhdmVFcnJvci5lbnRpdHlFcnJvcnM7XHJcbiAgaWYgKCFzZXJ2ZXJFcnJvcnMpIHJldHVybiA8U2F2ZUVycm9yPiA8YW55PiBzYXZlRXJyb3I7XHJcbiAgbGV0IGVudGl0eU1hbmFnZXIgPSBzYXZlQ29udGV4dC5lbnRpdHlNYW5hZ2VyO1xyXG4gIGxldCBtZXRhZGF0YVN0b3JlID0gZW50aXR5TWFuYWdlci5tZXRhZGF0YVN0b3JlO1xyXG4gIGxldCBlbnRpdHlFcnJvcnMgPSBzZXJ2ZXJFcnJvcnMubWFwKChzZXJyKSA9PiB7XHJcbiAgICBsZXQgZW50aXR5OiBFbnRpdHkgfCBudWxsID0gbnVsbDtcclxuICAgIGxldCBlbnRpdHlUeXBlOiBFbnRpdHlUeXBlIHwgdW5kZWZpbmVkO1xyXG4gICAgaWYgKHNlcnIua2V5VmFsdWVzKSB7XHJcbiAgICAgIGVudGl0eVR5cGUgPSBtZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShzZXJyLmVudGl0eVR5cGVOYW1lKSBhcyBFbnRpdHlUeXBlO1xyXG4gICAgICBsZXQgZWtleSA9IG5ldyBFbnRpdHlLZXkoZW50aXR5VHlwZSwgc2Vyci5rZXlWYWx1ZXMpO1xyXG4gICAgICBlbnRpdHkgPSBlbnRpdHlNYW5hZ2VyLmdldEVudGl0eUJ5S2V5KGVrZXkpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlbnRpdHlUeXBlICYmIGVudGl0eSkge1xyXG4gICAgICBsZXQgY29udGV4dCA9IHNlcnIucHJvcGVydHlOYW1lID9cclxuICAgICAgICB7XHJcbiAgICAgICAgICBwcm9wZXJ0eU5hbWU6IHNlcnIucHJvcGVydHlOYW1lLFxyXG4gICAgICAgICAgcHJvcGVydHk6IGVudGl0eVR5cGUuZ2V0UHJvcGVydHkoc2Vyci5wcm9wZXJ0eU5hbWUpXHJcbiAgICAgICAgfSA6IHtcclxuICAgICAgICB9O1xyXG4gICAgICBsZXQga2V5ID0gVmFsaWRhdGlvbkVycm9yLmdldEtleShzZXJyLmVycm9yTmFtZSB8fCBzZXJyLmVycm9yTWVzc2FnZSwgc2Vyci5wcm9wZXJ0eU5hbWUpO1xyXG5cclxuICAgICAgbGV0IHZlID0gbmV3IFZhbGlkYXRpb25FcnJvcihudWxsLCBjb250ZXh0LCBzZXJyLmVycm9yTWVzc2FnZSwga2V5KTtcclxuICAgICAgdmUuaXNTZXJ2ZXJFcnJvciA9IHRydWU7XHJcbiAgICAgIGVudGl0eS5lbnRpdHlBc3BlY3QuYWRkVmFsaWRhdGlvbkVycm9yKHZlKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgZW50aXR5RXJyb3IgPSBjb3JlLmV4dGVuZCh7XHJcbiAgICAgIGVudGl0eTogZW50aXR5LFxyXG4gICAgICBpc1NlcnZlckVycm9yOiB0cnVlXHJcbiAgICB9LCBzZXJyLCBbXCJlcnJvck5hbWVcIiwgXCJlcnJvck1lc3NhZ2VcIiwgXCJwcm9wZXJ0eU5hbWVcIiwgXCJjdXN0b21cIl0pIGFzIEVudGl0eUVycm9yO1xyXG4gICAgcmV0dXJuIGVudGl0eUVycm9yO1xyXG4gIH0pO1xyXG4gIC8vIGNvbnZlcnRpbmcgSVNhdmVFcnJvckZyb21TZXJ2ZXIgLT4gSVNhdmVFcnJvciBcclxuICBzYXZlRXJyb3IuZW50aXR5RXJyb3JzID0gZW50aXR5RXJyb3JzIGFzIGFueTtcclxuICByZXR1cm4gPFNhdmVFcnJvcj4gPGFueT4gc2F2ZUVycm9yO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIElFbnRpdHlCeUtleVJlc3VsdCB7XHJcbiAgZW50aXR5PzogRW50aXR5O1xyXG4gIGVudGl0eUtleTogRW50aXR5S2V5O1xyXG4gIGZyb21DYWNoZTogYm9vbGVhbjtcclxufVxyXG5cclxuZnVuY3Rpb24gZmV0Y2hFbnRpdHlCeUtleUNvcmUoZW06IEVudGl0eU1hbmFnZXIsIGFyZ3M6IGFueVtdKTogUHJvbWlzZTxJRW50aXR5QnlLZXlSZXN1bHQ+IHtcclxuICBsZXQgdHBsID0gY3JlYXRlRW50aXR5S2V5KGVtLCBhcmdzKTtcclxuICBsZXQgZW50aXR5S2V5ID0gdHBsLmVudGl0eUtleTtcclxuXHJcbiAgbGV0IGNoZWNrTG9jYWxDYWNoZUZpcnN0ID0gdHBsLnJlbWFpbmluZ0FyZ3MubGVuZ3RoID09PSAwID8gZmFsc2UgOiAhIXRwbC5yZW1haW5pbmdBcmdzWzBdO1xyXG4gIGxldCBlbnRpdHk6IEVudGl0eSB8IG51bGwgPSBudWxsO1xyXG4gIGxldCBmb3VuZEl0ID0gZmFsc2U7XHJcbiAgaWYgKGNoZWNrTG9jYWxDYWNoZUZpcnN0KSB7XHJcbiAgICBlbnRpdHkgPSBlbS5nZXRFbnRpdHlCeUtleShlbnRpdHlLZXkpO1xyXG4gICAgZm91bmRJdCA9IGVudGl0eSAhPSBudWxsO1xyXG4gICAgaWYgKGVudGl0eSAhPSBudWxsICYmXHJcbiAgICAgIC8vIG51bGwgdGhlIGVudGl0eSBpZiBpdCBpcyBkZWxldGVkIGFuZCB3ZSBzaG91bGQgZXhjbHVkZSBkZWxldGVkIGVudGl0aWVzXHJcbiAgICAgICFlbS5xdWVyeU9wdGlvbnMuaW5jbHVkZURlbGV0ZWQgJiYgZW50aXR5LmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZS5pc0RlbGV0ZWQoKSkge1xyXG4gICAgICBlbnRpdHkgPSBudWxsO1xyXG4gICAgICAvLyBidXQgcmVzdW1lIGxvb2tpbmcgaWYgd2UnZCBvdmVyd3JpdGUgZGVsZXRlZCBlbnRpdHkgd2l0aCBhIHJlbW90ZSBlbnRpdHlcclxuICAgICAgLy8gbm90ZTogZW0ucXVlcnlPcHRpb25zIGlzIGFsd2F5cyBmdWxseSByZXNvbHZlZCBieSBub3dcclxuICAgICAgZm91bmRJdCA9IGVtLnF1ZXJ5T3B0aW9ucy5tZXJnZVN0cmF0ZWd5ICE9PSBNZXJnZVN0cmF0ZWd5Lk92ZXJ3cml0ZUNoYW5nZXM7XHJcbiAgICB9XHJcbiAgfVxyXG4gIGlmIChmb3VuZEl0KSB7XHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgZW50aXR5OiBlbnRpdHkgfHwgdW5kZWZpbmVkLCBlbnRpdHlLZXk6IGVudGl0eUtleSwgZnJvbUNhY2hlOiB0cnVlIH0pO1xyXG4gIH0gZWxzZSB7XHJcbiAgICByZXR1cm4gRW50aXR5UXVlcnkuZnJvbUVudGl0eUtleShlbnRpdHlLZXkpLnVzaW5nKGVtKS5leGVjdXRlKCkudGhlbihmdW5jdGlvbiAoZGF0YTogYW55KSB7XHJcbiAgICAgIGVudGl0eSA9IChkYXRhLnJlc3VsdHMubGVuZ3RoID09PSAwKSA/IG51bGwgOiBkYXRhLnJlc3VsdHNbMF07XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBlbnRpdHk6IGVudGl0eSB8fCB1bmRlZmluZWQsIGVudGl0eUtleTogZW50aXR5S2V5LCBmcm9tQ2FjaGU6IGZhbHNlIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG59XHJcblxyXG5cclxuLy8gcHJpdmF0ZSBmbnNcclxuXHJcbi8vIHRha2VzIGluIGVudGl0eVR5cGVzIGFzIGVpdGhlciBzdHJpbmdzIG9yIGVudGl0eVR5cGVzIG9yIGFycmF5cyBvZiBlaXRoZXJcclxuLy8gYW5kIHJldHVybnMgZWl0aGVyIGFuIGVudGl0eVR5cGUgb3IgYW4gYXJyYXkgb2YgZW50aXR5VHlwZXMgb3IgdGhyb3dzIGFuIGVycm9yXHJcbmZ1bmN0aW9uIGNoZWNrRW50aXR5VHlwZXMoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eVR5cGVzPzogRW50aXR5VHlwZSB8IEVudGl0eVR5cGVbXSB8IHN0cmluZyB8IHN0cmluZ1tdKSB7XHJcbiAgYXNzZXJ0UGFyYW0oZW50aXR5VHlwZXMsIFwiZW50aXR5VHlwZXNcIikuaXNTdHJpbmcoKS5pc09wdGlvbmFsKCkub3IoKS5pc05vbkVtcHR5QXJyYXkoKS5pc1N0cmluZygpXHJcbiAgICAub3IoKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSkub3IoKS5pc05vbkVtcHR5QXJyYXkoKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSkuY2hlY2soKTtcclxuICBsZXQgcmVzdWx0VHlwZXM6IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCB1bmRlZmluZWQ7XHJcbiAgaWYgKHR5cGVvZiBlbnRpdHlUeXBlcyA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgcmVzdWx0VHlwZXMgPSBlbS5tZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShlbnRpdHlUeXBlcywgZmFsc2UpIGFzIChFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdKTtcclxuICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZW50aXR5VHlwZXMpICYmIHR5cGVvZiBlbnRpdHlUeXBlc1swXSA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgcmVzdWx0VHlwZXMgPSAoZW50aXR5VHlwZXMgYXMgc3RyaW5nW10pLm1hcChmdW5jdGlvbiAoZXROYW1lKSB7XHJcbiAgICAgIHJldHVybiBlbS5tZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShldE5hbWUsIGZhbHNlKSBhcyBFbnRpdHlUeXBlO1xyXG4gICAgfSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIHJlc3VsdFR5cGVzID0gZW50aXR5VHlwZXMgYXMgKEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCB1bmRlZmluZWQpO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc3VsdFR5cGVzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRDaGFuZ2VzQ29yZShlbTogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZXM/OiBFbnRpdHlUeXBlIHwgRW50aXR5VHlwZVtdKSB7XHJcbiAgbGV0IGVudGl0eUdyb3VwcyA9IGdldEVudGl0eUdyb3VwcyhlbSwgZW50aXR5VHlwZXMpO1xyXG5cclxuICAvLyBUT0RPOiB0aGluayBhYm91dCB3cml0aW5nIGEgY29yZS5tYXBNYW55IG1ldGhvZCBpZiB3ZSBzZWUgbW9yZSBvZiB0aGVzZS5cclxuICBsZXQgc2VsZWN0ZWQ6IEVudGl0eVtdID0gW107XHJcbiAgZW50aXR5R3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGVnKSB7XHJcbiAgICAvLyBlZyBtYXkgYmUgdW5kZWZpbmVkIG9yIG51bGxcclxuICAgIGlmICghZWcpIHJldHVybjtcclxuICAgIGxldCBlbnRpdGllcyA9IGVnLmdldENoYW5nZXMoKTtcclxuICAgIGlmIChzZWxlY3RlZCAmJiBzZWxlY3RlZC5sZW5ndGgpIHtcclxuICAgICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZW50aXRpZXMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgc2VsZWN0ZWQgPSBlbnRpdGllcztcclxuICAgIH1cclxuICB9KTtcclxuICByZXR1cm4gc2VsZWN0ZWQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldEVudGl0aWVzQ29yZShlbTogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZXM6IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10gfCB1bmRlZmluZWQsIGVudGl0eVN0YXRlczogRW50aXR5U3RhdGVbXSkge1xyXG4gIGxldCBlbnRpdHlHcm91cHMgPSBnZXRFbnRpdHlHcm91cHMoZW0sIGVudGl0eVR5cGVzKTtcclxuXHJcbiAgLy8gVE9ETzogdGhpbmsgYWJvdXQgd3JpdGluZyBhIGNvcmUubWFwTWFueSBtZXRob2QgaWYgd2Ugc2VlIG1vcmUgb2YgdGhlc2UuXHJcbiAgbGV0IHNlbGVjdGVkOiBFbnRpdHlbXSA9IFtdO1xyXG4gIGVudGl0eUdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChlZykge1xyXG4gICAgLy8gZWcgbWF5IGJlIHVuZGVmaW5lZCBvciBudWxsXHJcbiAgICBpZiAoIWVnKSByZXR1cm47XHJcbiAgICBsZXQgZW50aXRpZXMgPSBlZy5nZXRFbnRpdGllcyhlbnRpdHlTdGF0ZXMpO1xyXG4gICAgaWYgKHNlbGVjdGVkICYmIHNlbGVjdGVkLmxlbmd0aCkge1xyXG4gICAgICBzZWxlY3RlZCA9IHNlbGVjdGVkLmNvbmNhdChlbnRpdGllcyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBzZWxlY3RlZCA9IGVudGl0aWVzO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJldHVybiBzZWxlY3RlZDtcclxufVxyXG5cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUVudGl0eUtleShlbTogRW50aXR5TWFuYWdlciwgYXJnczogYW55W10pIHtcclxuICB0cnkge1xyXG4gICAgaWYgKGFyZ3NbMF0gaW5zdGFuY2VvZiBFbnRpdHlLZXkpIHtcclxuICAgICAgcmV0dXJuIHsgZW50aXR5S2V5OiBhcmdzWzBdIGFzIEVudGl0eUtleSwgcmVtYWluaW5nQXJnczogY29yZS5hcnJheVNsaWNlKGFyZ3MsIDEpIH07XHJcbiAgICB9IGVsc2UgaWYgKGFyZ3MubGVuZ3RoID49IDIpIHtcclxuICAgICAgbGV0IGVudGl0eVR5cGUgPSAodHlwZW9mIGFyZ3NbMF0gPT09ICdzdHJpbmcnKSA/IGVtLm1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKGFyZ3NbMF0sIGZhbHNlKSA6IGFyZ3NbMF07XHJcbiAgICAgIHJldHVybiB7IGVudGl0eUtleTogbmV3IEVudGl0eUtleShlbnRpdHlUeXBlLCBhcmdzWzFdKSwgcmVtYWluaW5nQXJnczogY29yZS5hcnJheVNsaWNlKGFyZ3MsIDIpIH07XHJcbiAgICB9XHJcbiAgfSBjYXRjaCAoZSkgey8qIHRocm93IGJlbG93ICovXHJcbiAgICAvLyB0aHJvdyBuZXcgRXJyb3IoXCJNdXN0IHN1cHBseSBhbiBFbnRpdHlLZXkgT1IgYW4gRW50aXR5VHlwZSBuYW1lIG9yIEVudGl0eVR5cGUgZm9sbG93ZWQgYnkgYSBrZXkgdmFsdWUgb3IgYW4gYXJyYXkgb2Yga2V5IHZhbHVlcy5cIik7XHJcbiAgfVxyXG4gIHRocm93IG5ldyBFcnJvcihcIk11c3Qgc3VwcGx5IGFuIEVudGl0eUtleSBPUiBhbiBFbnRpdHlUeXBlIG5hbWUgb3IgRW50aXR5VHlwZSBmb2xsb3dlZCBieSBhIGtleSB2YWx1ZSBvciBhbiBhcnJheSBvZiBrZXkgdmFsdWVzLlwiKTtcclxufVxyXG5cclxuZnVuY3Rpb24gbWFya0lzQmVpbmdTYXZlZChlbnRpdGllczogRW50aXR5W10sIGZsYWc6IGJvb2xlYW4pIHtcclxuICBlbnRpdGllcy5mb3JFYWNoKGZ1bmN0aW9uIChlbnRpdHkpIHtcclxuICAgIGVudGl0eS5lbnRpdHlBc3BlY3QuaXNCZWluZ1NhdmVkID0gZmxhZztcclxuICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gZXhwb3J0RW50aXR5R3JvdXBzKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdGllc09yRW50aXR5VHlwZXM6IEVudGl0eVtdIHwgRW50aXR5VHlwZVtdIHwgc3RyaW5nW10pIHtcclxuICBsZXQgZW50aXR5R3JvdXBNYXA6IHsgW2luZGV4OiBzdHJpbmddOiBFbnRpdHlHcm91cCB9O1xyXG4gIGxldCBmaXJzdCA9IGVudGl0aWVzT3JFbnRpdHlUeXBlcyAmJiBlbnRpdGllc09yRW50aXR5VHlwZXNbMF07XHJcbiAgLy8gY2hlY2sgaWYgYXJyYXlcclxuICBpZiAoZmlyc3QpIHtcclxuICAgIC8vIGdyb3VwIGVudGl0aWVzIGJ5IGVudGl0eVR5cGUgYW5kXHJcbiAgICAvLyBjcmVhdGUgJ2dyb3VwcycgdGhhdCBsb29rIGxpa2UgZW50aXR5R3JvdXBzLlxyXG4gICAgZW50aXR5R3JvdXBNYXAgPSB7fTtcclxuICAgIGlmICgoZmlyc3QgYXMgYW55KS5lbnRpdHlUeXBlKSB7XHJcbiAgICAgIGxldCBlbnRpdGllcyA9IGVudGl0aWVzT3JFbnRpdHlUeXBlcyBhcyBFbnRpdHlbXTtcclxuICAgICAgLy8gYXNzdW1lIFwiZW50aXRpZXNcIiBpcyBhbiBhcnJheSBvZiBlbnRpdGllcztcclxuICAgICAgZW50aXRpZXMuZm9yRWFjaChmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGlmIChlLmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZSA9PT0gRW50aXR5U3RhdGUuRGV0YWNoZWQpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byBleHBvcnQgYW4gZW50aXR5IHdpdGggYW4gRW50aXR5U3RhdGUgb2YgJ0RldGFjaGVkJ1wiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgbGV0IGdyb3VwID0gZW50aXR5R3JvdXBNYXBbZS5lbnRpdHlUeXBlLm5hbWVdO1xyXG4gICAgICAgIGlmICghZ3JvdXApIHtcclxuICAgICAgICAgIGdyb3VwID0ge30gYXMgRW50aXR5R3JvdXA7XHJcbiAgICAgICAgICBncm91cC5lbnRpdHlUeXBlID0gZS5lbnRpdHlUeXBlO1xyXG4gICAgICAgICAgZ3JvdXAuX2VudGl0aWVzID0gW107XHJcbiAgICAgICAgICBlbnRpdHlHcm91cE1hcFtlLmVudGl0eVR5cGUubmFtZV0gPSBncm91cDtcclxuICAgICAgICB9XHJcbiAgICAgICAgZ3JvdXAuX2VudGl0aWVzLnB1c2goZSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gYXNzdW1lIFwiZW50aXRpZXNcIiBpcyBhbiBhcnJheSBvZiBFbnRpdHlUeXBlcyAob3IgbmFtZXMpXHJcbiAgICAgIGxldCBlbnRpdHlUeXBlcyA9IGNoZWNrRW50aXR5VHlwZXMoZW0sIGVudGl0aWVzT3JFbnRpdHlUeXBlcyBhcyBFbnRpdHlUeXBlW10gfCBzdHJpbmdbXSkgYXMgRW50aXR5VHlwZVtdO1xyXG4gICAgICBpZiAoZW50aXR5VHlwZXMgIT0gbnVsbCkge1xyXG4gICAgICAgIGVudGl0eVR5cGVzLmZvckVhY2goKGV0KSA9PiB7XHJcbiAgICAgICAgICBsZXQgZ3JvdXAgPSBlbS5fZW50aXR5R3JvdXBNYXBbZXQubmFtZV07XHJcbiAgICAgICAgICBpZiAoZ3JvdXAgJiYgZ3JvdXAuX2VudGl0aWVzLmxlbmd0aCkge1xyXG4gICAgICAgICAgICBlbnRpdHlHcm91cE1hcFtldC5uYW1lXSA9IGdyb3VwO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSBlbHNlIGlmIChlbnRpdGllc09yRW50aXR5VHlwZXMgJiYgZW50aXRpZXNPckVudGl0eVR5cGVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgLy8gZW1wdHkgYXJyYXkgPSBleHBvcnQgbm90aGluZ1xyXG4gICAgZW50aXR5R3JvdXBNYXAgPSB7fTtcclxuICB9IGVsc2Uge1xyXG4gICAgZW50aXR5R3JvdXBNYXAgPSBlbS5fZW50aXR5R3JvdXBNYXA7XHJcbiAgfVxyXG5cclxuICBsZXQgdGVtcEtleXM6IElUZW1wS2V5W10gPSBbXTtcclxuICBsZXQgbmV3R3JvdXBNYXAgPSB7fTtcclxuICBjb3JlLm9iamVjdEZvckVhY2goZW50aXR5R3JvdXBNYXAsIChlbnRpdHlUeXBlTmFtZSwgZW50aXR5R3JvdXApID0+IHtcclxuICAgIG5ld0dyb3VwTWFwW2VudGl0eVR5cGVOYW1lXSA9IGV4cG9ydEVudGl0eUdyb3VwKGVudGl0eUdyb3VwLCB0ZW1wS2V5cyk7XHJcbiAgfSk7XHJcblxyXG4gIHJldHVybiB7IGVudGl0eUdyb3VwTWFwOiBuZXdHcm91cE1hcCwgdGVtcEtleXM6IHRlbXBLZXlzIH07XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGV4cG9ydEVudGl0eUdyb3VwKGVudGl0eUdyb3VwOiBFbnRpdHlHcm91cCwgdGVtcEtleXM6IElUZW1wS2V5W10pIHtcclxuICBsZXQgcmVzdWx0R3JvdXAgPSB7fSBhcyB7IGVudGl0aWVzOiBhbnlbXSB9O1xyXG4gIGxldCBlbnRpdHlUeXBlID0gZW50aXR5R3JvdXAuZW50aXR5VHlwZTtcclxuICBsZXQgZHBzID0gZW50aXR5VHlwZS5kYXRhUHJvcGVydGllcztcclxuICBsZXQgc2VyaWFsaXplckZuID0gZ2V0U2VyaWFsaXplckZuKGVudGl0eVR5cGUpO1xyXG4gIGxldCByYXdFbnRpdGllczogYW55W10gPSBbXTtcclxuICBlbnRpdHlHcm91cC5fZW50aXRpZXMuZm9yRWFjaCgoZW50aXR5KSA9PiB7XHJcbiAgICBpZiAoZW50aXR5KSB7XHJcbiAgICAgIGxldCByYXdFbnRpdHkgPSBzdHJ1Y3R1cmFsT2JqZWN0VG9Kc29uKGVudGl0eSwgZHBzLCBzZXJpYWxpemVyRm4sIHRlbXBLZXlzKTtcclxuICAgICAgcmF3RW50aXRpZXMucHVzaChyYXdFbnRpdHkpO1xyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJlc3VsdEdyb3VwLmVudGl0aWVzID0gcmF3RW50aXRpZXM7XHJcbiAgcmV0dXJuIHJlc3VsdEdyb3VwO1xyXG59XHJcblxyXG5mdW5jdGlvbiBzdHJ1Y3R1cmFsT2JqZWN0VG9Kc29uKHNvOiBTdHJ1Y3R1cmFsT2JqZWN0LCBkcHM6IERhdGFQcm9wZXJ0eVtdLCBzZXJpYWxpemVyRm4/OiAoZHA6IERhdGFQcm9wZXJ0eSwgdmFsdWU6IGFueSkgPT4gYW55LCB0ZW1wS2V5cz86IElUZW1wS2V5W10pIHtcclxuXHJcbiAgbGV0IHJlc3VsdCA9IHt9O1xyXG4gIGRwcy5mb3JFYWNoKGZ1bmN0aW9uIChkcCkge1xyXG4gICAgbGV0IGRwTmFtZSA9IGRwLm5hbWU7XHJcbiAgICBsZXQgdmFsdWUgPSBzby5nZXRQcm9wZXJ0eShkcE5hbWUpO1xyXG4gICAgaWYgKHZhbHVlID09IG51bGwgJiYgZHAuZGVmYXVsdFZhbHVlID09IG51bGwpIHJldHVybjtcclxuXHJcbiAgICBpZiAodmFsdWUgJiYgZHAuaXNDb21wbGV4UHJvcGVydHkpIHtcclxuICAgICAgbGV0IGNvRHBzID0gKGRwLmRhdGFUeXBlIGFzIENvbXBsZXhUeXBlKS5kYXRhUHJvcGVydGllcztcclxuICAgICAgdmFsdWUgPSBjb3JlLm1hcCh2YWx1ZSwgZnVuY3Rpb24gKHY6IENvbXBsZXhPYmplY3QpIHtcclxuICAgICAgICByZXR1cm4gc3RydWN0dXJhbE9iamVjdFRvSnNvbih2LCBjb0Rwcywgc2VyaWFsaXplckZuKTtcclxuICAgICAgfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB2YWx1ZSA9IHNlcmlhbGl6ZXJGbiA/IHNlcmlhbGl6ZXJGbihkcCwgdmFsdWUpIDogdmFsdWU7XHJcbiAgICAgIGlmIChkcC5pc1VubWFwcGVkKSB7XHJcbiAgICAgICAgdmFsdWUgPSBjb3JlLnRvSlNPTlNhZmUodmFsdWUsIGNvcmUudG9KU09OU2FmZVJlcGxhY2VyKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybjtcclxuICAgIHJlc3VsdFtkcE5hbWVdID0gdmFsdWU7XHJcbiAgfSk7XHJcblxyXG4gIC8vIGlmIChzby5lbnRpdHlBc3BlY3QpIHtcclxuICBpZiAoRW50aXR5QXNwZWN0LmlzRW50aXR5KHNvKSkge1xyXG4gICAgbGV0IGFzcGVjdCA9IHNvLmVudGl0eUFzcGVjdDtcclxuICAgIGxldCBlbnRpdHlTdGF0ZSA9IGFzcGVjdC5lbnRpdHlTdGF0ZTtcclxuICAgIGxldCBuZXdBc3BlY3QgPSB7XHJcbiAgICAgIHRlbXBOYXZQcm9wTmFtZXM6IGV4cG9ydFRlbXBLZXlJbmZvKGFzcGVjdCwgdGVtcEtleXMgfHwgW10pLFxyXG4gICAgICBlbnRpdHlTdGF0ZTogZW50aXR5U3RhdGUubmFtZVxyXG4gICAgfSBhcyBhbnk7XHJcbiAgICBpZiAoYXNwZWN0LmV4dHJhTWV0YWRhdGEpIHtcclxuICAgICAgbmV3QXNwZWN0LmV4dHJhTWV0YWRhdGEgPSBhc3BlY3QuZXh0cmFNZXRhZGF0YTtcclxuICAgIH1cclxuICAgIGlmIChlbnRpdHlTdGF0ZS5pc01vZGlmaWVkKCkgfHwgZW50aXR5U3RhdGUuaXNEZWxldGVkKCkpIHtcclxuICAgICAgbmV3QXNwZWN0Lm9yaWdpbmFsVmFsdWVzTWFwID0gYXNwZWN0Lm9yaWdpbmFsVmFsdWVzO1xyXG4gICAgfVxyXG4gICAgKHJlc3VsdCBhcyBhbnkpLmVudGl0eUFzcGVjdCA9IG5ld0FzcGVjdDtcclxuICB9IGVsc2Uge1xyXG4gICAgbGV0IGFzcGVjdCA9IHNvLmNvbXBsZXhBc3BlY3Q7XHJcbiAgICBsZXQgbmV3QXNwZWN0ID0ge30gYXMgYW55O1xyXG4gICAgaWYgKGFzcGVjdC5vcmlnaW5hbFZhbHVlcyAmJiAhY29yZS5pc0VtcHR5KGFzcGVjdC5vcmlnaW5hbFZhbHVlcykpIHtcclxuICAgICAgbmV3QXNwZWN0Lm9yaWdpbmFsVmFsdWVzTWFwID0gYXNwZWN0Lm9yaWdpbmFsVmFsdWVzO1xyXG4gICAgfVxyXG5cclxuICAgIChyZXN1bHQgYXMgYW55KS5jb21wbGV4QXNwZWN0ID0gbmV3QXNwZWN0O1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuaW50ZXJmYWNlIElUZW1wS2V5IHtcclxuICBlbnRpdHlUeXBlOiBzdHJpbmc7XHJcbiAgdmFsdWVzOiBhbnlbXTtcclxufVxyXG5cclxuZnVuY3Rpb24gZXhwb3J0VGVtcEtleUluZm8oZW50aXR5QXNwZWN0OiBFbnRpdHlBc3BlY3QsIHRlbXBLZXlzOiBJVGVtcEtleVtdKSB7XHJcbiAgbGV0IGVudGl0eSA9IGVudGl0eUFzcGVjdC5lbnRpdHkgYXMgRW50aXR5O1xyXG4gIGlmIChlbnRpdHlBc3BlY3QuaGFzVGVtcEtleSkge1xyXG4gICAgdGVtcEtleXMucHVzaChlbnRpdHlBc3BlY3QuZ2V0S2V5KCkudG9KU09OKCkpO1xyXG4gIH1cclxuICAvLyBjcmVhdGUgbWFwIGZvciB0aGlzIGVudGl0eSB3aXRoIGZvcmVpZ25LZXlzIHRoYXQgYXJlICd0ZW1wb3JhcnknXHJcbiAgLy8gbWFwIC0+IGtleTogdGVtcEtleSwgdmFsdWU6IGZrUHJvcE5hbWVcclxuICBsZXQgdGVtcE5hdlByb3BOYW1lczogc3RyaW5nW10gPSBbXTtcclxuICBlbnRpdHkuZW50aXR5VHlwZS5uYXZpZ2F0aW9uUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChucCkge1xyXG4gICAgaWYgKG5wLnJlbGF0ZWREYXRhUHJvcGVydGllcykge1xyXG4gICAgICBsZXQgcmVsYXRlZFZhbHVlID0gZW50aXR5LmdldFByb3BlcnR5KG5wLm5hbWUpO1xyXG4gICAgICBpZiAocmVsYXRlZFZhbHVlICYmIHJlbGF0ZWRWYWx1ZS5lbnRpdHlBc3BlY3QuaGFzVGVtcEtleSkge1xyXG4gICAgICAgIHRlbXBOYXZQcm9wTmFtZXMucHVzaChucC5uYW1lKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH0pO1xyXG4gIHJldHVybiB0ZW1wTmF2UHJvcE5hbWVzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBpbXBvcnRFbnRpdHlHcm91cChlbnRpdHlHcm91cDogRW50aXR5R3JvdXAsIGpzb25Hcm91cDogeyBlbnRpdGllczogYW55W10gfSwgaW1wb3J0Q29uZmlnOiBJbXBvcnRDb25maWdFeHQpIHtcclxuXHJcbiAgbGV0IHRlbXBLZXlNYXAgPSBpbXBvcnRDb25maWcudGVtcEtleU1hcDtcclxuICBsZXQgbWVyZ2VBZGRzID0gISFpbXBvcnRDb25maWcubWVyZ2VBZGRzO1xyXG5cclxuICBsZXQgZW50aXR5VHlwZSA9IGVudGl0eUdyb3VwLmVudGl0eVR5cGU7XHJcbiAgbGV0IG1lcmdlU3RyYXRlZ3kgPSBpbXBvcnRDb25maWcubWVyZ2VTdHJhdGVneTtcclxuXHJcbiAgbGV0IHRhcmdldEVudGl0eTogRW50aXR5IHwgdW5kZWZpbmVkO1xyXG5cclxuICBsZXQgZW0gPSBlbnRpdHlHcm91cC5lbnRpdHlNYW5hZ2VyO1xyXG4gIGxldCBlbnRpdHlDaGFuZ2VkID0gZW0uZW50aXR5Q2hhbmdlZDtcclxuICBsZXQgZW50aXRpZXNUb0xpbms6IEVudGl0eVtdID0gW107XHJcbiAgbGV0IHJhd1ZhbHVlRm4gPSBEYXRhUHJvcGVydHkuZ2V0UmF3VmFsdWVGcm9tQ2xpZW50O1xyXG4gIGpzb25Hcm91cC5lbnRpdGllcy5mb3JFYWNoKGZ1bmN0aW9uIChyYXdFbnRpdHk6IGFueSkge1xyXG4gICAgbGV0IG5ld0FzcGVjdCA9IHJhd0VudGl0eS5lbnRpdHlBc3BlY3Q7XHJcblxyXG4gICAgbGV0IGVudGl0eUtleSA9IGVudGl0eVR5cGUuZ2V0RW50aXR5S2V5RnJvbVJhd0VudGl0eShyYXdFbnRpdHksIHJhd1ZhbHVlRm4pO1xyXG4gICAgbGV0IGVudGl0eVN0YXRlID0gRW50aXR5U3RhdGUuZnJvbU5hbWUobmV3QXNwZWN0LmVudGl0eVN0YXRlKSBhcyBFbnRpdHlTdGF0ZTtcclxuICAgIGlmICghZW50aXR5U3RhdGUgfHwgZW50aXR5U3RhdGUgPT09IEVudGl0eVN0YXRlLkRldGFjaGVkKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgZW50aXRpZXMgd2l0aCBhIG5vbiBkZXRhY2hlZCBlbnRpdHkgc3RhdGUgbWF5IGJlIGltcG9ydGVkLlwiKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBNZXJnZSBpZiByYXcgZW50aXR5IGlzIGluIGNhY2hlIFVOTEVTUyB0aGlzIGlzIGEgbmV3IGVudGl0eSB3LyBhIHRlbXAga2V5XHJcbiAgICAvLyBDYW5ub3Qgc2FmZWx5IG1lcmdlIHN1Y2ggZW50aXRpZXMgZXZlbiBpZiBjb3VsZCBtYXRjaCB0ZW1wIGtleSB0byBhbiBlbnRpdHkgaW4gY2FjaGUuXHJcbiAgICAvLyBDYW4gZW5hYmxlIG1lcmdlIG9mIGVudGl0aWVzIHcvdGVtcCBrZXkgdXNpbmcgXCJtZXJnZUFkZHNcIiAtIHVzZSBhdCB5b3VyIG93biByaXNrIVxyXG4gICAgbGV0IG5ld1RlbXBLZXkgPSAhbWVyZ2VBZGRzICYmIGVudGl0eVN0YXRlLmlzQWRkZWQoKSAmJiBnZXRNYXBwZWRLZXkodGVtcEtleU1hcCEsIGVudGl0eUtleSk7XHJcbiAgICB0YXJnZXRFbnRpdHkgPSBuZXdUZW1wS2V5ID8gdW5kZWZpbmVkIDogZW50aXR5R3JvdXAuZmluZEVudGl0eUJ5S2V5KGVudGl0eUtleSk7XHJcblxyXG4gICAgaWYgKHRhcmdldEVudGl0eSkge1xyXG4gICAgICBpZiAobWVyZ2VTdHJhdGVneSA9PT0gTWVyZ2VTdHJhdGVneS5Ta2lwTWVyZ2UpIHtcclxuICAgICAgICAvLyBkZWxpYmVyYXRlIGZhbGwgdGhydVxyXG4gICAgICB9IGVsc2UgaWYgKG1lcmdlU3RyYXRlZ3kgPT09IE1lcmdlU3RyYXRlZ3kuRGlzYWxsb3dlZCkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkEgTWVyZ2VTdHJhdGVneSBvZiAnRGlzYWxsb3dlZCcgcHJldmVudHMgXCIgKyBlbnRpdHlLZXkudG9TdHJpbmcoKSArIFwiIGZyb20gYmVpbmcgbWVyZ2VkXCIpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGxldCB0YXJnZXRFbnRpdHlTdGF0ZSA9IHRhcmdldEVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGU7XHJcbiAgICAgICAgbGV0IHdhc1VuY2hhbmdlZCA9IHRhcmdldEVudGl0eVN0YXRlLmlzVW5jaGFuZ2VkKCk7XHJcbiAgICAgICAgaWYgKG1lcmdlU3RyYXRlZ3kgPT09IE1lcmdlU3RyYXRlZ3kuT3ZlcndyaXRlQ2hhbmdlcyB8fCB3YXNVbmNoYW5nZWQpIHtcclxuICAgICAgICAgIGVudGl0eVR5cGUuX3VwZGF0ZVRhcmdldEZyb21SYXcodGFyZ2V0RW50aXR5LCByYXdFbnRpdHksIHJhd1ZhbHVlRm4pO1xyXG4gICAgICAgICAgdGFyZ2V0RW50aXR5LmVudGl0eUFzcGVjdC5zZXRFbnRpdHlTdGF0ZShlbnRpdHlTdGF0ZSk7XHJcbiAgICAgICAgICBlbnRpdHlDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbi5NZXJnZU9uSW1wb3J0LCBlbnRpdHk6IHRhcmdldEVudGl0eSB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRhcmdldEVudGl0eSA9IGVudGl0eVR5cGUuX2NyZWF0ZUluc3RhbmNlQ29yZSgpIGFzIEVudGl0eTtcclxuICAgICAgZW50aXR5VHlwZS5fdXBkYXRlVGFyZ2V0RnJvbVJhdyh0YXJnZXRFbnRpdHksIHJhd0VudGl0eSwgcmF3VmFsdWVGbik7XHJcbiAgICAgIGlmIChuZXdUZW1wS2V5KSB7XHJcbiAgICAgICAgdGFyZ2V0RW50aXR5LmVudGl0eUFzcGVjdC5oYXNUZW1wS2V5ID0gdHJ1ZTtcclxuICAgICAgICAvLyBmaXh1cCBwa1xyXG4gICAgICAgIHRhcmdldEVudGl0eS5zZXRQcm9wZXJ0eShlbnRpdHlUeXBlLmtleVByb3BlcnRpZXNbMF0ubmFtZSwgbmV3VGVtcEtleS52YWx1ZXNbMF0pO1xyXG5cclxuICAgICAgICAvLyBmaXh1cCBmb3JlaWduIGtleXNcclxuICAgICAgICAvLyBUaGlzIGlzIHNhZmUgYmVjYXVzZSB0aGUgZW50aXR5IGlzIGRldGFjaGVkIGhlcmUgYW5kIHRoZXJlZm9yZSBvcmlnaW5hbFZhbHVlcyB3aWxsIG5vdCBiZSB1cGRhdGVkLlxyXG4gICAgICAgIGlmIChuZXdBc3BlY3QudGVtcE5hdlByb3BOYW1lcykge1xyXG4gICAgICAgICAgbmV3QXNwZWN0LnRlbXBOYXZQcm9wTmFtZXMuZm9yRWFjaChmdW5jdGlvbiAobnBOYW1lOiBzdHJpbmcpIHtcclxuICAgICAgICAgICAgbGV0IG5wID0gZW50aXR5VHlwZS5nZXROYXZpZ2F0aW9uUHJvcGVydHkobnBOYW1lKTtcclxuICAgICAgICAgICAgbGV0IGZrUHJvcE5hbWUgPSBucCEucmVsYXRlZERhdGFQcm9wZXJ0aWVzWzBdLm5hbWU7XHJcbiAgICAgICAgICAgIGxldCBvbGRGa1ZhbHVlID0gdGFyZ2V0RW50aXR5IS5nZXRQcm9wZXJ0eShma1Byb3BOYW1lKTtcclxuICAgICAgICAgICAgbGV0IGZrID0gbmV3IEVudGl0eUtleShucCEuZW50aXR5VHlwZSwgW29sZEZrVmFsdWVdKTtcclxuICAgICAgICAgICAgbGV0IG5ld0ZrID0gZ2V0TWFwcGVkS2V5KHRlbXBLZXlNYXAhLCBmayk7XHJcbiAgICAgICAgICAgIHRhcmdldEVudGl0eSEuc2V0UHJvcGVydHkoZmtQcm9wTmFtZSwgbmV3RmshLnZhbHVlc1swXSk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgLy8gTm93IHBlcmZvcm1lZCBpbiBhdHRhY2hFbnRpdHlcclxuICAgICAgdGFyZ2V0RW50aXR5ID0gZW50aXR5R3JvdXAuYXR0YWNoRW50aXR5KHRhcmdldEVudGl0eSwgZW50aXR5U3RhdGUpO1xyXG4gICAgICBlbnRpdHlDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbi5BdHRhY2hPbkltcG9ydCwgZW50aXR5OiB0YXJnZXRFbnRpdHkgfSk7XHJcbiAgICAgIGlmICghZW50aXR5U3RhdGUuaXNVbmNoYW5nZWQoKSkge1xyXG4gICAgICAgIGVtLl9ub3RpZnlTdGF0ZUNoYW5nZSh0YXJnZXRFbnRpdHksIHRydWUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgZW50aXRpZXNUb0xpbmsucHVzaCh0YXJnZXRFbnRpdHkpO1xyXG4gIH0pO1xyXG4gIHJldHVybiBlbnRpdGllc1RvTGluaztcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0TWFwcGVkS2V5KHRlbXBLZXlNYXA6IElUZW1wS2V5TWFwLCBlbnRpdHlLZXk6IEVudGl0eUtleSkge1xyXG4gIGxldCBuZXdLZXkgPSB0ZW1wS2V5TWFwW2VudGl0eUtleS50b1N0cmluZygpXTtcclxuICBpZiAobmV3S2V5KSByZXR1cm4gbmV3S2V5O1xyXG4gIGxldCBzdWJ0eXBlcyA9IGVudGl0eUtleS5fc3VidHlwZXM7XHJcbiAgaWYgKCFzdWJ0eXBlcykgcmV0dXJuIG51bGw7XHJcbiAgZm9yIChsZXQgaSA9IDAsIGogPSBzdWJ0eXBlcy5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuICAgIG5ld0tleSA9IHRlbXBLZXlNYXBbZW50aXR5S2V5LnRvU3RyaW5nKHN1YnR5cGVzW2ldKV07XHJcbiAgICBpZiAobmV3S2V5KSByZXR1cm4gbmV3S2V5O1xyXG4gIH1cclxuICByZXR1cm4gbnVsbDtcclxufVxyXG5cclxuZnVuY3Rpb24gcHJvbWlzZVdpdGhDYWxsYmFja3M8VD4ocHJvbWlzZTogUHJvbWlzZTxUPiwgY2FsbGJhY2s/OiBDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IEVycm9yQ2FsbGJhY2spIHtcclxuICBwcm9taXNlID0gcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7XHJcbiAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKGRhdGEpO1xyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKTtcclxuICB9LCBmdW5jdGlvbiAoZXJyb3IpIHtcclxuICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKGVycm9yKTtcclxuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XHJcbiAgfSk7XHJcbiAgcmV0dXJuIHByb21pc2U7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldEVudGl0aWVzVG9TYXZlKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdGllcz86IEVudGl0eVtdKSB7XHJcbiAgbGV0IGVudGl0aWVzVG9TYXZlOiBFbnRpdHlbXTtcclxuICBpZiAoZW50aXRpZXMpIHtcclxuICAgIGVudGl0aWVzVG9TYXZlID0gZW50aXRpZXMuZmlsdGVyKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIGlmIChlLmVudGl0eUFzcGVjdC5lbnRpdHlNYW5hZ2VyICE9PSBlbSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgZW50aXRpZXMgaW4gdGhpcyBlbnRpdHlNYW5hZ2VyIG1heSBiZSBzYXZlZFwiKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gIWUuZW50aXR5QXNwZWN0LmVudGl0eVN0YXRlLmlzRGV0YWNoZWQoKTtcclxuICAgIH0pO1xyXG4gIH0gZWxzZSB7XHJcbiAgICBlbnRpdGllc1RvU2F2ZSA9IGVtLmdldENoYW5nZXMoKTtcclxuICB9XHJcbiAgcmV0dXJuIGVudGl0aWVzVG9TYXZlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBmaXh1cEtleXMoZW06IEVudGl0eU1hbmFnZXIsIGtleU1hcHBpbmdzOiBLZXlNYXBwaW5nW10pIHtcclxuICBlbS5faW5LZXlGaXh1cCA9IHRydWU7XHJcbiAga2V5TWFwcGluZ3MuZm9yRWFjaChmdW5jdGlvbiAoa20pIHtcclxuICAgIGxldCBncm91cCA9IGVtLl9lbnRpdHlHcm91cE1hcFtrbS5lbnRpdHlUeXBlTmFtZV07XHJcbiAgICBpZiAoIWdyb3VwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byBsb2NhdGUgdGhlIGZvbGxvd2luZyBmdWxseSBxdWFsaWZpZWQgRW50aXR5VHlwZSBuYW1lOiBcIiArIGttLmVudGl0eVR5cGVOYW1lKTtcclxuICAgIH1cclxuICAgIGdyb3VwLl9maXh1cEtleShrbS50ZW1wVmFsdWUsIGttLnJlYWxWYWx1ZSk7XHJcbiAgfSk7XHJcbiAgZW0uX2luS2V5Rml4dXAgPSBmYWxzZTtcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0RW50aXR5R3JvdXBzKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHlUeXBlcz86IEVudGl0eVR5cGUgfCBFbnRpdHlUeXBlW10pIHtcclxuICBsZXQgZ3JvdXBNYXAgPSBlbS5fZW50aXR5R3JvdXBNYXA7XHJcbiAgaWYgKGVudGl0eVR5cGVzKSB7XHJcbiAgICByZXR1cm4gY29yZS50b0FycmF5KGVudGl0eVR5cGVzKS5tYXAoZnVuY3Rpb24gKGV0OiBFbnRpdHlUeXBlKSB7XHJcbiAgICAgIGlmIChldCBpbnN0YW5jZW9mIEVudGl0eVR5cGUpIHtcclxuICAgICAgICByZXR1cm4gZ3JvdXBNYXBbZXQubmFtZV07XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIEVudGl0eU1hbmFnZXIuZ2V0Q2hhbmdlcygpICdlbnRpdHlUeXBlcycgcGFyYW1ldGVyIG11c3QgYmUgZWl0aGVyIGFuIGVudGl0eVR5cGUgb3IgYW4gYXJyYXkgb2YgZW50aXR5VHlwZXMgb3IgbnVsbFwiKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIHJldHVybiBjb3JlLmdldE93blByb3BlcnR5VmFsdWVzKGdyb3VwTWFwKSBhcyBFbnRpdHlHcm91cFtdO1xyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gY2hlY2tFbnRpdHlLZXkoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eTogRW50aXR5KSB7XHJcbiAgbGV0IGVrID0gZW50aXR5LmVudGl0eUFzcGVjdC5nZXRLZXkoKTtcclxuICAvLyByZXR1cm4gcHJvcGVydGllcyB0aGF0IGFyZSA9IHRvIGRlZmF1bHRWYWx1ZXNcclxuICBsZXQga2V5UHJvcHNXaXRoRGVmYXVsdFZhbHVlcyA9IGNvcmUuYXJyYXlaaXAoZW50aXR5LmVudGl0eVR5cGUua2V5UHJvcGVydGllcywgZWsudmFsdWVzLCBmdW5jdGlvbiAoa3AsIGt2KSB7XHJcbiAgICByZXR1cm4gKGtwLmRlZmF1bHRWYWx1ZSA9PT0ga3YpID8ga3AgOiBudWxsO1xyXG4gIH0pLmZpbHRlcihmdW5jdGlvbiAoa3ApIHtcclxuICAgIHJldHVybiBrcCAhPT0gbnVsbDtcclxuICB9KTtcclxuICBpZiAoa2V5UHJvcHNXaXRoRGVmYXVsdFZhbHVlcy5sZW5ndGgpIHtcclxuICAgIGlmIChlbnRpdHkuZW50aXR5VHlwZS5hdXRvR2VuZXJhdGVkS2V5VHlwZSAhPT0gQXV0b0dlbmVyYXRlZEtleVR5cGUuTm9uZSkge1xyXG4gICAgICBlbS5nZW5lcmF0ZVRlbXBLZXlWYWx1ZShlbnRpdHkpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gd2Ugd2lsbCBhbGxvdyBhdHRhY2hlcyBvZiBlbnRpdGllcyB3aGVyZSBvbmx5IHBhcnQgb2YgdGhlIGtleSBpcyBzZXQuXHJcbiAgICAgIGlmIChrZXlQcm9wc1dpdGhEZWZhdWx0VmFsdWVzLmxlbmd0aCA9PT0gZWsudmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBhdHRhY2ggYW4gb2JqZWN0IG9mIHR5cGUgIChcIiArIGVudGl0eS5lbnRpdHlUeXBlLm5hbWUgKyBcIikgdG8gYW4gRW50aXR5TWFuYWdlciB3aXRob3V0IGZpcnN0IHNldHRpbmcgaXRzIGtleSBvciBzZXR0aW5nIGl0cyBlbnRpdHlUeXBlICdBdXRvR2VuZXJhdGVkS2V5VHlwZScgcHJvcGVydHkgdG8gc29tZXRoaW5nIG90aGVyIHRoYW4gJ05vbmUnXCIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiB2YWxpZGF0ZUVudGl0eVN0YXRlcyhlbTogRW50aXR5TWFuYWdlciwgZW50aXR5U3RhdGVzPzogRW50aXR5U3RhdGUgfCBFbnRpdHlTdGF0ZVtdKSB7XHJcbiAgaWYgKCFlbnRpdHlTdGF0ZXMpIHJldHVybiBbXSBhcyBFbnRpdHlTdGF0ZVtdO1xyXG4gIGxldCBlbnRTdGF0ZXMgPSBjb3JlLnRvQXJyYXkoZW50aXR5U3RhdGVzKSBhcyBFbnRpdHlTdGF0ZVtdO1xyXG4gIGVudFN0YXRlcy5mb3JFYWNoKChlcykgPT4ge1xyXG4gICAgaWYgKCEoZXMgaW5zdGFuY2VvZiBFbnRpdHlTdGF0ZSkpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIEVudGl0eU1hbmFnZXIuZ2V0Q2hhbmdlcygpICdlbnRpdHlTdGF0ZXMnIHBhcmFtZXRlciBtdXN0IGVpdGhlciBiZSBudWxsLCBhbiBlbnRpdHlTdGF0ZSBvciBhbiBhcnJheSBvZiBlbnRpdHlTdGF0ZXNcIik7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmV0dXJuIGVudFN0YXRlcztcclxufVxyXG5cclxuZnVuY3Rpb24gYXR0YWNoUmVsYXRlZEVudGl0aWVzKGVtOiBFbnRpdHlNYW5hZ2VyLCBlbnRpdHk6IEVudGl0eSwgZW50aXR5U3RhdGU6IEVudGl0eVN0YXRlLCBtZXJnZVN0cmF0ZWd5OiBNZXJnZVN0cmF0ZWd5KSB7XHJcbiAgbGV0IG5hdlByb3BzID0gZW50aXR5LmVudGl0eVR5cGUubmF2aWdhdGlvblByb3BlcnRpZXM7XHJcbiAgbmF2UHJvcHMuZm9yRWFjaChmdW5jdGlvbiAobnApIHtcclxuICAgIGxldCByZWxhdGVkID0gZW50aXR5LmdldFByb3BlcnR5KG5wLm5hbWUpO1xyXG4gICAgaWYgKG5wLmlzU2NhbGFyKSB7XHJcbiAgICAgIGlmICghcmVsYXRlZCkgcmV0dXJuO1xyXG4gICAgICBlbS5hdHRhY2hFbnRpdHkocmVsYXRlZCwgZW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3kpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmVsYXRlZC5mb3JFYWNoKGZ1bmN0aW9uIChlOiBFbnRpdHkpIHtcclxuICAgICAgICBlbS5hdHRhY2hFbnRpdHkoZSwgZW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3kpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9KTtcclxufVxyXG5cclxuLy8gcmV0dXJucyBhIHByb21pc2VcclxuZnVuY3Rpb24gZXhlY3V0ZVF1ZXJ5Q29yZShlbTogRW50aXR5TWFuYWdlciwgcXVlcnk6IEVudGl0eVF1ZXJ5IHwgc3RyaW5nLCBxdWVyeU9wdGlvbnM6IFF1ZXJ5T3B0aW9ucywgZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlKTogUHJvbWlzZTxRdWVyeVJlc3VsdD4ge1xyXG4gIHRyeSB7XHJcbiAgICBsZXQgcmVzdWx0czogYW55W107XHJcbiAgICBsZXQgbWV0YWRhdGFTdG9yZSA9IGVtLm1ldGFkYXRhU3RvcmU7XHJcblxyXG4gICAgaWYgKG1ldGFkYXRhU3RvcmUuaXNFbXB0eSgpICYmIGRhdGFTZXJ2aWNlLmhhc1NlcnZlck1ldGFkYXRhKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImNhbm5vdCBleGVjdXRlIF9leGVjdXRlUXVlcnlDb3JlIHVudGlsIG1ldGFkYXRhU3RvcmUgaXMgcG9wdWxhdGVkLlwiKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAocXVlcnlPcHRpb25zLmZldGNoU3RyYXRlZ3kgPT09IEZldGNoU3RyYXRlZ3kuRnJvbUxvY2FsQ2FjaGUpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBpZiAodHlwZW9mIHF1ZXJ5ID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY2Fubm90IGV4ZWN1dGUgJ3N0cmluZycgRW50aXR5UXVlcnkgbG9jYWxseS5cIik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGxldCBxciA9IGV4ZWN1dGVRdWVyeUxvY2FsbHlDb3JlKGVtLCBxdWVyeSk7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IHJlc3VsdHM6IHFyLnJlc3VsdHMsIGVudGl0eU1hbmFnZXI6IGVtLCBpbmxpbmVDb3VudDogcXIuaW5saW5lQ291bnQsIHF1ZXJ5OiBxdWVyeSB9KTtcclxuICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBtYXBwaW5nQ29udGV4dDogTWFwcGluZ0NvbnRleHQgfCB1bmRlZmluZWQgPSBuZXcgTWFwcGluZ0NvbnRleHQoe1xyXG4gICAgICBxdWVyeTogcXVlcnksXHJcbiAgICAgIGVudGl0eU1hbmFnZXI6IGVtLFxyXG4gICAgICBkYXRhU2VydmljZTogZGF0YVNlcnZpY2UsXHJcbiAgICAgIG1lcmdlT3B0aW9uczoge1xyXG4gICAgICAgIG1lcmdlU3RyYXRlZ3k6IHF1ZXJ5T3B0aW9ucy5tZXJnZVN0cmF0ZWd5LFxyXG4gICAgICAgIG5vVHJhY2tpbmc6ICEhKHF1ZXJ5IGFzIGFueSkubm9UcmFja2luZ0VuYWJsZWQsXHJcbiAgICAgICAgaW5jbHVkZURlbGV0ZWQ6IHF1ZXJ5T3B0aW9ucy5pbmNsdWRlRGVsZXRlZFxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBsZXQgdmFsaWRhdGVPblF1ZXJ5ID0gZW0udmFsaWRhdGlvbk9wdGlvbnMudmFsaWRhdGVPblF1ZXJ5O1xyXG5cclxuICAgIHJldHVybiBkYXRhU2VydmljZS5hZGFwdGVySW5zdGFuY2UhLmV4ZWN1dGVRdWVyeShtYXBwaW5nQ29udGV4dCkudGhlbihmdW5jdGlvbiAoZGF0YTogYW55KSB7XHJcbiAgICAgIGxldCByZXN1bHQgPSBjb3JlLndyYXBFeGVjdXRpb24oZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGxldCBzdGF0ZSA9IHsgaXNMb2FkaW5nOiBlbS5pc0xvYWRpbmcgfTtcclxuICAgICAgICBlbS5pc0xvYWRpbmcgPSB0cnVlO1xyXG4gICAgICAgIGVtLl9wZW5kaW5nUHVicyA9IFtdO1xyXG4gICAgICAgIHJldHVybiBzdGF0ZTtcclxuICAgICAgfSwgZnVuY3Rpb24gKHN0YXRlKSB7XHJcbiAgICAgICAgLy8gY2xlYW51cFxyXG4gICAgICAgIGVtLmlzTG9hZGluZyA9IHN0YXRlLmlzTG9hZGluZztcclxuICAgICAgICBlbS5fcGVuZGluZ1B1YnMhLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7XHJcbiAgICAgICAgICBmbigpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGVtLl9wZW5kaW5nUHVicyA9IHVuZGVmaW5lZDtcclxuICAgICAgICBlbS5faGFzQ2hhbmdlc0FjdGlvbiAmJiBlbS5faGFzQ2hhbmdlc0FjdGlvbigpO1xyXG4gICAgICAgIC8vIFRPRE86IHJlbW92ZWQgLSBub3Qgc3VyZSB3aHkgbmVlZGVkIGluIGZpcnN0IHBsYWNlLi4uXHJcbiAgICAgICAgLy8gLy8gSEFDSyBmb3IgR0NcclxuICAgICAgICAvLyBxdWVyeSA9IHVuZGVmaW5lZDtcclxuICAgICAgICBtYXBwaW5nQ29udGV4dCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAvLyBIQUNLOiBzb21lIGVycm9ycyB0aHJvd24gaW4gbmV4dCBmdW5jdGlvbiBkbyBub3QgcHJvcG9nYXRlIHByb3Blcmx5IC0gdGhpcyBjYXRjaGVzIHRoZW0uXHJcblxyXG4gICAgICAgIGlmIChzdGF0ZS5lcnJvcikge1xyXG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHN0YXRlLmVycm9yKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICB9LCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgbGV0IG5vZGVzID0gZGF0YVNlcnZpY2UuanNvblJlc3VsdHNBZGFwdGVyLmV4dHJhY3RSZXN1bHRzKGRhdGEpO1xyXG4gICAgICAgIG5vZGVzID0gY29yZS50b0FycmF5KG5vZGVzKTtcclxuXHJcbiAgICAgICAgcmVzdWx0cyA9IG1hcHBpbmdDb250ZXh0IS52aXNpdEFuZE1lcmdlKG5vZGVzLCB7IG5vZGVUeXBlOiBcInJvb3RcIiB9KTtcclxuICAgICAgICBpZiAodmFsaWRhdGVPblF1ZXJ5KSB7XHJcbiAgICAgICAgICByZXN1bHRzLmZvckVhY2goZnVuY3Rpb24gKHI6IGFueSkge1xyXG4gICAgICAgICAgICAvLyBhbm9uIHR5cGVzIGFuZCBzaW1wbGUgdHlwZXMgd2lsbCBub3QgaGF2ZSBhbiBlbnRpdHlBc3BlY3QuXHJcbiAgICAgICAgICAgIHIuZW50aXR5QXNwZWN0ICYmIHIuZW50aXR5QXNwZWN0LnZhbGlkYXRlRW50aXR5KCk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgbWFwcGluZ0NvbnRleHQhLnByb2Nlc3NEZWZlcnJlZCgpO1xyXG4gICAgICAgIC8vIGlmIHF1ZXJ5IGhhcyBleHBhbmQgY2xhdXNlcyB3YWxrIGVhY2ggb2YgdGhlICdyZXN1bHRzJyBhbmQgbWFyayB0aGUgZXhwYW5kZWQgcHJvcHMgYXMgbG9hZGVkLlxyXG4gICAgICAgIGlmIChxdWVyeSBpbnN0YW5jZW9mIEVudGl0eVF1ZXJ5KSB7XHJcbiAgICAgICAgICBtYXJrTG9hZGVkTmF2UHJvcHMocmVzdWx0cywgcXVlcnkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBsZXQgcmV0cmlldmVkRW50aXRpZXMgPSBjb3JlLm9iamVjdE1hcChtYXBwaW5nQ29udGV4dCEucmVmTWFwKTtcclxuICAgICAgICByZXR1cm4geyByZXN1bHRzOiByZXN1bHRzLCBxdWVyeTogcXVlcnksIGVudGl0eU1hbmFnZXI6IGVtLCBodHRwUmVzcG9uc2U6IGRhdGEuaHR0cFJlc3BvbnNlLCBpbmxpbmVDb3VudDogZGF0YS5pbmxpbmVDb3VudCwgcmV0cmlldmVkRW50aXRpZXM6IHJldHJpZXZlZEVudGl0aWVzIH07XHJcbiAgICAgIH0pO1xyXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XHJcbiAgICB9LCBmdW5jdGlvbiAoZTogYW55KSB7XHJcbiAgICAgIGlmIChlKSB7XHJcbiAgICAgICAgZS5xdWVyeSA9IHF1ZXJ5O1xyXG4gICAgICAgIGUuZW50aXR5TWFuYWdlciA9IGVtO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTtcclxuICAgIH0pO1xyXG5cclxuICB9IGNhdGNoIChlKSB7XHJcbiAgICBpZiAoZSkge1xyXG4gICAgICBlLnF1ZXJ5ID0gcXVlcnk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBtYXJrTG9hZGVkTmF2UHJvcHMoZW50aXRpZXM6IEVudGl0eVtdLCBxdWVyeTogRW50aXR5UXVlcnkpIHtcclxuICBpZiAocXVlcnkubm9UcmFja2luZ0VuYWJsZWQpIHJldHVybjtcclxuICBsZXQgZXhwYW5kQ2xhdXNlID0gcXVlcnkuZXhwYW5kQ2xhdXNlO1xyXG4gIGlmIChleHBhbmRDbGF1c2UgPT0gbnVsbCkgcmV0dXJuO1xyXG4gIGV4cGFuZENsYXVzZS5wcm9wZXJ0eVBhdGhzLmZvckVhY2goZnVuY3Rpb24gKHByb3BlcnR5UGF0aCkge1xyXG4gICAgbGV0IHByb3BOYW1lcyA9IHByb3BlcnR5UGF0aC5zcGxpdCgnLicpO1xyXG4gICAgbWFya0xvYWRlZE5hdlBhdGgoZW50aXRpZXMsIHByb3BOYW1lcyk7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIG1hcmtMb2FkZWROYXZQYXRoKGVudGl0aWVzOiBFbnRpdHlbXSwgcHJvcE5hbWVzOiBzdHJpbmdbXSkge1xyXG4gIGxldCBwcm9wTmFtZSA9IHByb3BOYW1lc1swXTtcclxuICBlbnRpdGllcy5mb3JFYWNoKChlbnRpdHkpID0+IHtcclxuICAgIGxldCBlYSA9IGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgICBpZiAoIWVhKSByZXR1cm47IC8vIGVudGl0eSBtYXkgbm90IGJlIGEgJ3JlYWwnIGVudGl0eSBpbiB0aGUgY2FzZSBvZiBhIHByb2plY3Rpb24uXHJcbiAgICBlYS5fbWFya0FzTG9hZGVkKHByb3BOYW1lKTtcclxuICAgIGlmIChwcm9wTmFtZXMubGVuZ3RoID09PSAxKSByZXR1cm47XHJcbiAgICBsZXQgbmV4dCA9IGVudGl0eS5nZXRQcm9wZXJ0eShwcm9wTmFtZSk7XHJcbiAgICBpZiAoIW5leHQpIHJldHVybjsgLy8gbm8gY2hpbGRyZW4gdG8gcHJvY2Vzcy5cclxuICAgIC8vIHN0cmFuZ2UgbG9naWMgYmVjYXVzZSBub25zY2FsYXIgbmF2IHZhbHVlcyBhcmUgTk9UIHJlYWxseSBhcnJheXNcclxuICAgIC8vIG90aGVyd2lzZSB3ZSBjb3VsZCB1c2UgQXJyYXkuaXNBcnJheVxyXG4gICAgaWYgKCFuZXh0LmFycmF5Q2hhbmdlZCkgbmV4dCA9IFtuZXh0XTtcclxuICAgIG1hcmtMb2FkZWROYXZQYXRoKG5leHQsIHByb3BOYW1lcy5zbGljZSgxKSk7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHVwZGF0ZUNvbmN1cnJlbmN5UHJvcGVydGllcyhlbnRpdGllczogRW50aXR5W10pIHtcclxuICBsZXQgY2FuZGlkYXRlcyA9IGVudGl0aWVzLmZpbHRlcigoZSkgPT4ge1xyXG4gICAgZS5lbnRpdHlBc3BlY3QuaXNCZWluZ1NhdmVkID0gdHJ1ZTtcclxuICAgIHJldHVybiBlLmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZS5pc01vZGlmaWVkKClcclxuICAgICAgJiYgZS5lbnRpdHlUeXBlLmNvbmN1cnJlbmN5UHJvcGVydGllcy5sZW5ndGggPiAwO1xyXG5cclxuICB9KTtcclxuICBpZiAoY2FuZGlkYXRlcy5sZW5ndGggPT09IDApIHJldHVybjtcclxuICBjYW5kaWRhdGVzLmZvckVhY2goZnVuY3Rpb24gKGMpIHtcclxuICAgIGMuZW50aXR5VHlwZS5jb25jdXJyZW5jeVByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAoY3ApIHtcclxuICAgICAgdXBkYXRlQ29uY3VycmVuY3lQcm9wZXJ0eShjLCBjcCk7XHJcbiAgICB9KTtcclxuICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gdXBkYXRlQ29uY3VycmVuY3lQcm9wZXJ0eShlbnRpdHk6IEVudGl0eSwgcHJvcGVydHk6IERhdGFQcm9wZXJ0eSkge1xyXG4gIC8vIGNoZWNrIGlmIHByb3BlcnR5IGhhcyBhbHJlYWR5IGJlZW4gdXBkYXRlZFxyXG4gIGlmIChlbnRpdHkuZW50aXR5QXNwZWN0Lm9yaWdpbmFsVmFsdWVzW3Byb3BlcnR5Lm5hbWVdKSByZXR1cm47XHJcbiAgbGV0IHZhbHVlID0gZW50aXR5LmdldFByb3BlcnR5KHByb3BlcnR5Lm5hbWUpO1xyXG4gIGxldCBkYXRhVHlwZSA9IHByb3BlcnR5LmRhdGFUeXBlIGFzIERhdGFUeXBlO1xyXG4gIGlmICghdmFsdWUpIHZhbHVlID0gZGF0YVR5cGUuZGVmYXVsdFZhbHVlO1xyXG4gIGlmIChkYXRhVHlwZS5pc051bWVyaWMpIHtcclxuICAgIGVudGl0eS5zZXRQcm9wZXJ0eShwcm9wZXJ0eS5uYW1lLCB2YWx1ZSArIDEpO1xyXG4gIH0gZWxzZSBpZiAoZGF0YVR5cGUuZ2V0Q29uY3VycmVuY3lWYWx1ZSkge1xyXG4gICAgLy8gRGF0YVR5cGUgaGFzIGl0cyBvd24gaW1wbGVtZW50YXRpb25cclxuICAgIGxldCBuZXh0VmFsdWUgPSBkYXRhVHlwZS5nZXRDb25jdXJyZW5jeVZhbHVlKHZhbHVlKTtcclxuICAgIGVudGl0eS5zZXRQcm9wZXJ0eShwcm9wZXJ0eS5uYW1lLCBuZXh0VmFsdWUpO1xyXG4gIH0gZWxzZSBpZiAoZGF0YVR5cGUgPT09IERhdGFUeXBlLkJpbmFyeSkge1xyXG4gICAgLy8gYmVzdCBndWVzcyAtIHRoYXQgdGhpcyBpcyBhIHRpbWVzdGFtcCBjb2x1bW4gYW5kIGlzIGNvbXB1dGVkIG9uIHRoZSBzZXJ2ZXIgZHVyaW5nIHNhdmVcclxuICAgIC8vIC0gc28gbm8gbmVlZCB0byBzZXQgaXQgaGVyZS5cclxuICAgIHJldHVybjtcclxuICB9IGVsc2Uge1xyXG4gICAgLy8gdGhpcyBqdXN0IGxlYXZlcyBEYXRhVHlwZXMgb2YgQm9vbGVhbiwgU3RyaW5nIGFuZCBCeXRlIC0gbm9uZSBvZiB3aGljaCBzaG91bGQgYmUgdGhlXHJcbiAgICAvLyB0eXBlIGZvciBhIGNvbmN1cnJlbmN5IGNvbHVtbi5cclxuICAgIC8vIE5PVEU6IHRob3VnaHQgYWJvdXQganVzdCByZXR1cm5pbmcgaGVyZSBidXQgd291bGQgcmF0aGVyIGJlIHNhZmUgZm9yIG5vdy5cclxuICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byB1cGRhdGUgdGhlIHZhbHVlIG9mIGNvbmN1cnJlbmN5IHByb3BlcnR5IGJlZm9yZSBzYXZpbmc6IFwiICsgcHJvcGVydHkubmFtZSk7XHJcbiAgfVxyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gZmluZE9yQ3JlYXRlRW50aXR5R3JvdXAoZW06IEVudGl0eU1hbmFnZXIsIGVudGl0eVR5cGU6IEVudGl0eVR5cGUpIHtcclxuICBsZXQgZ3JvdXAgPSBlbS5fZW50aXR5R3JvdXBNYXBbZW50aXR5VHlwZS5uYW1lXTtcclxuICBpZiAoIWdyb3VwKSB7XHJcbiAgICBncm91cCA9IG5ldyBFbnRpdHlHcm91cChlbSwgZW50aXR5VHlwZSk7XHJcbiAgICBlbS5fZW50aXR5R3JvdXBNYXBbZW50aXR5VHlwZS5uYW1lXSA9IGdyb3VwO1xyXG4gIH1cclxuICByZXR1cm4gZ3JvdXA7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGZpbmRPckNyZWF0ZUVudGl0eUdyb3VwcyhlbTogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZTogRW50aXR5VHlwZSkge1xyXG4gIGxldCBlbnRpdHlUeXBlcyA9IGVudGl0eVR5cGUuZ2V0U2VsZkFuZFN1YnR5cGVzKCk7XHJcbiAgcmV0dXJuIGVudGl0eVR5cGVzLm1hcCgoZXQpID0+IHtcclxuICAgIHJldHVybiBmaW5kT3JDcmVhdGVFbnRpdHlHcm91cChlbSwgZXQpO1xyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiB1bndyYXBJbnN0YW5jZShzdHJ1Y3RPYmo6IFN0cnVjdHVyYWxPYmplY3QsIHRyYW5zZm9ybUZuPzogKGRwOiBEYXRhUHJvcGVydHksIHZhbDogYW55KSA9PiBhbnkpIHtcclxuXHJcbiAgbGV0IHJhd09iamVjdDogYW55ID0ge307XHJcbiAgbGV0IHN0eXBlID0gRW50aXR5QXNwZWN0LmlzRW50aXR5KHN0cnVjdE9iaikgPyBzdHJ1Y3RPYmouZW50aXR5VHlwZSA6IHN0cnVjdE9iai5jb21wbGV4VHlwZTtcclxuICBsZXQgc2VyaWFsaXplckZuID0gZ2V0U2VyaWFsaXplckZuKHN0eXBlKTtcclxuICBsZXQgdW5tYXBwZWQgPSB7fTtcclxuICBzdHlwZS5kYXRhUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChkcCkge1xyXG4gICAgaWYgKGRwLmlzQ29tcGxleFByb3BlcnR5KSB7XHJcbiAgICAgIHJhd09iamVjdFtkcC5uYW1lT25TZXJ2ZXJdID0gY29yZS5tYXAoc3RydWN0T2JqLmdldFByb3BlcnR5KGRwLm5hbWUpLCBmdW5jdGlvbiAoY28pIHtcclxuICAgICAgICByZXR1cm4gdW53cmFwSW5zdGFuY2UoY28sIHRyYW5zZm9ybUZuKTtcclxuICAgICAgfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsZXQgdmFsID0gc3RydWN0T2JqLmdldFByb3BlcnR5KGRwLm5hbWUpO1xyXG4gICAgICB2YWwgPSB0cmFuc2Zvcm1GbiA/IHRyYW5zZm9ybUZuKGRwLCB2YWwpIDogdmFsO1xyXG4gICAgICBpZiAodmFsID09PSB1bmRlZmluZWQpIHJldHVybjtcclxuICAgICAgdmFsID0gc2VyaWFsaXplckZuID8gc2VyaWFsaXplckZuKGRwLCB2YWwpIDogdmFsO1xyXG4gICAgICBpZiAodmFsICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICBpZiAoZHAuaXNVbm1hcHBlZCkge1xyXG4gICAgICAgICAgdW5tYXBwZWRbZHAubmFtZU9uU2VydmVyXSA9IGNvcmUudG9KU09OU2FmZSh2YWwsIGNvcmUudG9KU09OU2FmZVJlcGxhY2VyKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgcmF3T2JqZWN0W2RwLm5hbWVPblNlcnZlcl0gPSB2YWw7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSk7XHJcblxyXG4gIGlmICghY29yZS5pc0VtcHR5KHVubWFwcGVkKSkge1xyXG4gICAgLy8gVE9ETzogcmV2aWV3IHRoaXMuXHJcbiAgICAocmF3T2JqZWN0IGFzIGFueSkuX191bm1hcHBlZCA9IHVubWFwcGVkO1xyXG4gIH1cclxuICByZXR1cm4gcmF3T2JqZWN0O1xyXG59XHJcblxyXG5mdW5jdGlvbiB1bndyYXBPcmlnaW5hbFZhbHVlcyh0YXJnZXQ6IFN0cnVjdHVyYWxPYmplY3QsIG1ldGFkYXRhU3RvcmU6IE1ldGFkYXRhU3RvcmUsIHRyYW5zZm9ybUZuPzogKGRwOiBEYXRhUHJvcGVydHksIHZhbDogYW55KSA9PiBhbnkpIHtcclxuICBsZXQgc3R5cGUgPSBFbnRpdHlBc3BlY3QuaXNFbnRpdHkodGFyZ2V0KSA/IHRhcmdldC5lbnRpdHlUeXBlIDogdGFyZ2V0LmNvbXBsZXhUeXBlO1xyXG4gIGxldCBhc3BlY3QgPSBFbnRpdHlBc3BlY3QuaXNFbnRpdHkodGFyZ2V0KSA/IHRhcmdldC5lbnRpdHlBc3BlY3QgOiB0YXJnZXQuY29tcGxleEFzcGVjdDtcclxuICBsZXQgZm4gPSBtZXRhZGF0YVN0b3JlLm5hbWluZ0NvbnZlbnRpb24uY2xpZW50UHJvcGVydHlOYW1lVG9TZXJ2ZXI7XHJcbiAgbGV0IHJlc3VsdCA9IHt9IGFzIFJlY29yZDxzdHJpbmcsIGFueT47XHJcbiAgY29yZS5vYmplY3RGb3JFYWNoKGFzcGVjdC5vcmlnaW5hbFZhbHVlcywgZnVuY3Rpb24gKHByb3BOYW1lLCB2YWwpIHtcclxuICAgIGxldCBwcm9wID0gc3R5cGUuZ2V0UHJvcGVydHkocHJvcE5hbWUpIGFzIERhdGFQcm9wZXJ0eTtcclxuICAgIHZhbCA9IHRyYW5zZm9ybUZuID8gdHJhbnNmb3JtRm4ocHJvcCwgdmFsKSA6IHZhbDtcclxuICAgIGlmICh2YWwgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICByZXN1bHRbZm4ocHJvcE5hbWUsIHByb3ApXSA9IHZhbDtcclxuICAgIH1cclxuICB9KTtcclxuICBzdHlwZS5jb21wbGV4UHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChjcCkge1xyXG4gICAgbGV0IG5leHRUYXJnZXQgPSB0YXJnZXQuZ2V0UHJvcGVydHkoY3AubmFtZSk7XHJcbiAgICBpZiAoY3AuaXNTY2FsYXIpIHtcclxuICAgICAgbGV0IHVud3JhcHBlZENvID0gdW53cmFwT3JpZ2luYWxWYWx1ZXMobmV4dFRhcmdldCwgbWV0YWRhdGFTdG9yZSwgdHJhbnNmb3JtRm4pO1xyXG4gICAgICBpZiAoIWNvcmUuaXNFbXB0eSh1bndyYXBwZWRDbykpIHtcclxuICAgICAgICByZXN1bHRbZm4oY3AubmFtZSwgY3ApXSA9IHVud3JhcHBlZENvO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsZXQgdW53cmFwcGVkQ29zID0gbmV4dFRhcmdldC5tYXAoKGl0ZW06IGFueSkgPT4ge1xyXG4gICAgICAgIHJldHVybiB1bndyYXBPcmlnaW5hbFZhbHVlcyhpdGVtLCBtZXRhZGF0YVN0b3JlLCB0cmFuc2Zvcm1Gbik7XHJcbiAgICAgIH0pO1xyXG4gICAgICByZXN1bHRbZm4oY3AubmFtZSwgY3ApXSA9IHVud3JhcHBlZENvcztcclxuICAgIH1cclxuICB9KTtcclxuICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5mdW5jdGlvbiB1bndyYXBDaGFuZ2VkVmFsdWVzKGVudGl0eTogRW50aXR5LCBtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlLCB0cmFuc2Zvcm1GbjogKGRwOiBEYXRhUHJvcGVydHksIHZhbDogYW55KSA9PiBhbnkpIHtcclxuICBsZXQgc3R5cGUgPSBlbnRpdHkuZW50aXR5VHlwZTtcclxuICBsZXQgc2VyaWFsaXplckZuID0gZ2V0U2VyaWFsaXplckZuKHN0eXBlKTtcclxuICBsZXQgZm4gPSBtZXRhZGF0YVN0b3JlLm5hbWluZ0NvbnZlbnRpb24uY2xpZW50UHJvcGVydHlOYW1lVG9TZXJ2ZXI7XHJcbiAgbGV0IHJlc3VsdCA9IHt9IGFzIFJlY29yZDxzdHJpbmcsIGFueT47XHJcbiAgY29yZS5vYmplY3RGb3JFYWNoKGVudGl0eS5lbnRpdHlBc3BlY3Qub3JpZ2luYWxWYWx1ZXMsIGZ1bmN0aW9uIChwcm9wTmFtZSwgdmFsdWUpIHtcclxuICAgIGxldCBwcm9wID0gc3R5cGUuZ2V0UHJvcGVydHkocHJvcE5hbWUpIGFzIERhdGFQcm9wZXJ0eTtcclxuICAgIGxldCB2YWwgPSBlbnRpdHkuZ2V0UHJvcGVydHkocHJvcE5hbWUpO1xyXG4gICAgdmFsID0gdHJhbnNmb3JtRm4gPyB0cmFuc2Zvcm1Gbihwcm9wLCB2YWwpIDogdmFsO1xyXG4gICAgaWYgKHZhbCA9PT0gdW5kZWZpbmVkKSByZXR1cm47XHJcbiAgICB2YWwgPSBzZXJpYWxpemVyRm4gPyBzZXJpYWxpemVyRm4ocHJvcCwgdmFsKSA6IHZhbDtcclxuICAgIGlmICh2YWwgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICByZXN1bHRbZm4ocHJvcE5hbWUsIHByb3ApXSA9IHZhbDtcclxuICAgIH1cclxuICB9KTtcclxuICAvLyBhbnkgY2hhbmdlIHRvIGFueSBjb21wbGV4IG9iamVjdCBvciBhcnJheSBvZiBjb21wbGV4IG9iamVjdHMgcmV0dXJucyB0aGUgRU5USVJFXHJcbiAgLy8gY3VycmVudCBjb21wbGV4IG9iamVjdCBvciBjb21wbGV4IG9iamVjdCBhcnJheS4gIFRoaXMgaXMgYnkgZGVzaWduLiBDb21wbGV4IE9iamVjdHNcclxuICAvLyBhcmUgYXRvbWljLlxyXG4gIHN0eXBlLmNvbXBsZXhQcm9wZXJ0aWVzLmZvckVhY2goKGNwKSA9PiB7XHJcbiAgICBpZiAoY3BIYXNPcmlnaW5hbFZhbHVlcyhlbnRpdHksIGNwKSkge1xyXG4gICAgICBsZXQgY29PckNvcyA9IGVudGl0eS5nZXRQcm9wZXJ0eShjcC5uYW1lKTtcclxuICAgICAgcmVzdWx0W2ZuKGNwLm5hbWUsIGNwKV0gPSBjb3JlLm1hcChjb09yQ29zLCBmdW5jdGlvbiAoY28pIHtcclxuICAgICAgICByZXR1cm4gdW53cmFwSW5zdGFuY2UoY28sIHRyYW5zZm9ybUZuKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZnVuY3Rpb24gY3BIYXNPcmlnaW5hbFZhbHVlcyhzdHJ1Y3R1cmFsT2JqZWN0OiBTdHJ1Y3R1cmFsT2JqZWN0LCBjcDogRGF0YVByb3BlcnR5KTogYm9vbGVhbiB7XHJcbiAgbGV0IGNvT3JDb3MgPSBzdHJ1Y3R1cmFsT2JqZWN0LmdldFByb3BlcnR5KGNwLm5hbWUpO1xyXG4gIGlmIChjcC5pc1NjYWxhcikge1xyXG4gICAgcmV0dXJuIGNvSGFzT3JpZ2luYWxWYWx1ZXMoY29PckNvcyk7XHJcbiAgfSBlbHNlIHtcclxuICAgIC8vIHRoaXMgb2NjdXJzIHdoZW4gYSBub25zY2FsYXIgY28gYXJyYXkgaGFzIGhhZCBjb3MgYWRkZWQgb3IgcmVtb3ZlZC5cclxuICAgIGlmIChjb09yQ29zLl9vcmlnVmFsdWVzKSByZXR1cm4gdHJ1ZTtcclxuICAgIHJldHVybiBjb09yQ29zLnNvbWUoZnVuY3Rpb24gKGNvOiBDb21wbGV4T2JqZWN0KSB7XHJcbiAgICAgIHJldHVybiBjb0hhc09yaWdpbmFsVmFsdWVzKGNvKTtcclxuICAgIH0pO1xyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gZXhlY3V0ZVF1ZXJ5TG9jYWxseUNvcmUoZW06IEVudGl0eU1hbmFnZXIsIHF1ZXJ5OiBFbnRpdHlRdWVyeSkge1xyXG4gIGFzc2VydFBhcmFtKHF1ZXJ5LCBcInF1ZXJ5XCIpLmlzSW5zdGFuY2VPZihFbnRpdHlRdWVyeSkuY2hlY2soKTtcclxuXHJcbiAgbGV0IG1ldGFkYXRhU3RvcmUgPSBlbS5tZXRhZGF0YVN0b3JlO1xyXG4gIGxldCBlbnRpdHlUeXBlID0gcXVlcnkuX2dldEZyb21FbnRpdHlUeXBlKG1ldGFkYXRhU3RvcmUsIHRydWUpO1xyXG4gIC8vIHRoZXJlIG1heSBiZSBtdWx0aXBsZSBncm91cHMgaXMgdGhpcyBpcyBhIGJhc2UgZW50aXR5IHR5cGUuXHJcbiAgbGV0IGdyb3VwcyA9IGZpbmRPckNyZWF0ZUVudGl0eUdyb3VwcyhlbSwgZW50aXR5VHlwZSEpO1xyXG4gIC8vIGZpbHRlciB0aGVuIG9yZGVyIHRoZW4gc2tpcCB0aGVuIHRha2VcclxuICBsZXQgZmlsdGVyRnVuYyA9IHF1ZXJ5LndoZXJlUHJlZGljYXRlICYmIHF1ZXJ5LndoZXJlUHJlZGljYXRlLnRvRnVuY3Rpb24oeyBlbnRpdHlUeXBlOiBlbnRpdHlUeXBlIH0pO1xyXG5cclxuICBsZXQgcXVlcnlPcHRpb25zID0gUXVlcnlPcHRpb25zLnJlc29sdmUoW3F1ZXJ5LnF1ZXJ5T3B0aW9ucywgZW0ucXVlcnlPcHRpb25zLCBRdWVyeU9wdGlvbnMuZGVmYXVsdEluc3RhbmNlXSk7XHJcbiAgbGV0IGluY2x1ZGVEZWxldGVkID0gcXVlcnlPcHRpb25zLmluY2x1ZGVEZWxldGVkID09PSB0cnVlO1xyXG5cclxuICBsZXQgbmV3RmlsdGVyRnVuYyA9IGZ1bmN0aW9uIChlbnRpdHk6IEVudGl0eSkge1xyXG4gICAgcmV0dXJuIGVudGl0eSAmJiAoaW5jbHVkZURlbGV0ZWQgfHwgIWVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUuaXNEZWxldGVkKCkpICYmIChmaWx0ZXJGdW5jID8gZmlsdGVyRnVuYyhlbnRpdHkpIDogdHJ1ZSk7XHJcbiAgfTtcclxuXHJcbiAgbGV0IHJlc3VsdDogYW55W10gPSBbXTtcclxuICAvLyBUT0RPOiBtYXBNYW55XHJcbiAgZ3JvdXBzLmZvckVhY2goKGdyb3VwKSA9PiB7XHJcbiAgICBsZXQgZW50aXRpZXMgPSBncm91cC5fZW50aXRpZXMuZmlsdGVyKG5ld0ZpbHRlckZ1bmMpIGFzIEVudGl0eVtdO1xyXG4gICAgaWYgKGVudGl0aWVzLmxlbmd0aCkge1xyXG4gICAgICByZXN1bHQgPSByZXN1bHQubGVuZ3RoID8gcmVzdWx0LmNvbmNhdChlbnRpdGllcykgOiBlbnRpdGllcztcclxuICAgIH1cclxuICB9KTtcclxuXHJcbiAgbGV0IG9yZGVyQnlDb21wYXJlciA9IHF1ZXJ5Lm9yZGVyQnlDbGF1c2UgJiYgcXVlcnkub3JkZXJCeUNsYXVzZS5nZXRDb21wYXJlcihlbnRpdHlUeXBlISk7XHJcbiAgaWYgKG9yZGVyQnlDb21wYXJlcikge1xyXG4gICAgcmVzdWx0LnNvcnQob3JkZXJCeUNvbXBhcmVyKTtcclxuICB9XHJcblxyXG4gIGxldCBpbmxpbmVDb3VudCA9IHF1ZXJ5LmlubGluZUNvdW50RW5hYmxlZCA/IHJlc3VsdC5sZW5ndGggOiB1bmRlZmluZWQ7XHJcblxyXG4gIGxldCBza2lwQ291bnQgPSBxdWVyeS5za2lwQ291bnQ7XHJcbiAgaWYgKHNraXBDb3VudCkge1xyXG4gICAgcmVzdWx0ID0gcmVzdWx0LnNsaWNlKHNraXBDb3VudCk7XHJcbiAgfVxyXG4gIGxldCB0YWtlQ291bnQgPSBxdWVyeS50YWtlQ291bnQ7XHJcbiAgaWYgKHRha2VDb3VudCkge1xyXG4gICAgcmVzdWx0ID0gcmVzdWx0LnNsaWNlKDAsIHRha2VDb3VudCk7XHJcbiAgfVxyXG5cclxuICBsZXQgc2VsZWN0Q2xhdXNlID0gcXVlcnkuc2VsZWN0Q2xhdXNlO1xyXG4gIGlmIChzZWxlY3RDbGF1c2UpIHtcclxuICAgIGxldCBzZWxlY3RGbiA9IHNlbGVjdENsYXVzZS50b0Z1bmN0aW9uKCk7XHJcbiAgICByZXN1bHQgPSByZXN1bHQubWFwKHNlbGVjdEZuKTtcclxuICB9XHJcbiAgcmV0dXJuIHsgcmVzdWx0czogcmVzdWx0LCBpbmxpbmVDb3VudDogaW5saW5lQ291bnQgfTtcclxufVxyXG5cclxuZnVuY3Rpb24gY29IYXNPcmlnaW5hbFZhbHVlcyhjbzogQ29tcGxleE9iamVjdCkge1xyXG4gIC8vIG5leHQgbGluZSBjaGVja3MgYWxsIG5vbiBjb21wbGV4IHByb3BlcnRpZXMgb2YgdGhlIGNvLlxyXG4gIGlmICghY29yZS5pc0VtcHR5KGNvLmNvbXBsZXhBc3BlY3Qub3JpZ2luYWxWYWx1ZXMpKSByZXR1cm4gdHJ1ZTtcclxuICAvLyBub3cgbmVlZCB0byByZWN1cnNpdmVseSBjaGVjayBlYWNoIG9mIHRoZSBjcHNcclxuICByZXR1cm4gY28uY29tcGxleFR5cGUuY29tcGxleFByb3BlcnRpZXMuc29tZShmdW5jdGlvbiAoY3ApIHtcclxuICAgIHJldHVybiBjcEhhc09yaWdpbmFsVmFsdWVzKGNvLCBjcCk7XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldFNlcmlhbGl6ZXJGbihzdHlwZTogRW50aXR5VHlwZSB8IENvbXBsZXhUeXBlKSB7XHJcbiAgcmV0dXJuIHN0eXBlLnNlcmlhbGl6ZXJGbiB8fCAoc3R5cGUubWV0YWRhdGFTdG9yZSAmJiBzdHlwZS5tZXRhZGF0YVN0b3JlLnNlcmlhbGl6ZXJGbik7XHJcbn1cclxuXHJcbiJdfQ==