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.
- package/LICENSE +1 -1
- package/README.md +83 -63
- package/adapters/abstract-data-service-adapter.d.ts +120 -0
- package/adapters/abstract-data-service-adapter.js +395 -0
- package/adapters/abstract-data-service-adapter.js.map +1 -0
- package/adapters/adapter-ajax-fetch.d.ts +12 -0
- package/adapters/adapter-ajax-fetch.js +13 -0
- package/adapters/adapter-ajax-fetch.js.map +1 -0
- package/{adapter-ajax-post → adapters}/adapter-ajax-post.d.ts +40 -36
- package/{fesm2022/breeze-client-adapter-ajax-post.mjs → adapters/adapter-ajax-post.js} +80 -82
- package/adapters/adapter-ajax-post.js.map +1 -0
- package/{adapter-ajax-fetch → adapters}/adapter-core.d.ts +4 -4
- package/{fesm2022/breeze-client-adapter-uri-builder-json.mjs → adapters/adapter-core.js} +48 -91
- package/adapters/adapter-core.js.map +1 -0
- package/adapters/adapter-data-service-webapi.d.ts +9 -0
- package/{fesm2022/breeze-client-adapter-data-service-webapi.mjs → adapters/adapter-data-service-webapi.js} +105 -107
- package/adapters/adapter-data-service-webapi.js.map +1 -0
- package/adapters/adapter-model-library-backing-store.d.ts +32 -0
- package/adapters/adapter-model-library-backing-store.js +321 -0
- package/adapters/adapter-model-library-backing-store.js.map +1 -0
- package/adapters/adapter-uri-builder-json.d.ts +11 -0
- package/adapters/adapter-uri-builder-json.js +40 -0
- package/adapters/adapter-uri-builder-json.js.map +1 -0
- package/adapters/http.d.ts +52 -0
- package/adapters/http.js +202 -0
- package/adapters/http.js.map +1 -0
- package/angular/adapter-angular-httpclient.d.ts +21 -0
- package/angular/adapter-angular-httpclient.js +70 -0
- package/angular/adapter-angular-httpclient.js.map +1 -0
- package/breeze.d.ts +215 -0
- package/breeze.js +141 -0
- package/breeze.js.map +1 -0
- package/config/config.d.ts +212 -0
- package/config/config.js +392 -0
- package/config/config.js.map +1 -0
- package/config/configure.d.ts +66 -0
- package/config/configure.js +46 -0
- package/config/configure.js.map +1 -0
- package/config/default-adapters.d.ts +1 -0
- package/config/default-adapters.js +40 -0
- package/config/default-adapters.js.map +1 -0
- package/config/interface-registry.d.ts +191 -0
- package/config/interface-registry.js +5 -0
- package/config/interface-registry.js.map +1 -0
- package/{src → core}/assert-param.d.ts +52 -60
- package/core/assert-param.js +390 -0
- package/core/assert-param.js.map +1 -0
- package/core/core.d.ts +285 -0
- package/core/core.js +772 -0
- package/core/core.js.map +1 -0
- package/core/enum.d.ts +116 -0
- package/core/enum.js +167 -0
- package/core/enum.js.map +1 -0
- package/core/event.d.ts +169 -0
- package/core/event.js +338 -0
- package/core/event.js.map +1 -0
- package/entity/array.d.ts +3 -0
- package/entity/array.js +4 -0
- package/entity/array.js.map +1 -0
- package/entity/complex-array.d.ts +17 -0
- package/entity/complex-array.js +104 -0
- package/entity/complex-array.js.map +1 -0
- package/entity/default-property-interceptor.d.ts +1 -0
- package/entity/default-property-interceptor.js +496 -0
- package/entity/default-property-interceptor.js.map +1 -0
- package/{src → entity}/entity-action.d.ts +36 -42
- package/entity/entity-action.js +45 -0
- package/entity/entity-action.js.map +1 -0
- package/entity/entity-aspect.d.ts +457 -0
- package/entity/entity-aspect.js +1262 -0
- package/entity/entity-aspect.js.map +1 -0
- package/entity/entity-base.d.ts +55 -0
- package/entity/entity-base.js +41 -0
- package/entity/entity-base.js.map +1 -0
- package/entity/entity-group.d.ts +1 -0
- package/entity/entity-group.js +224 -0
- package/entity/entity-group.js.map +1 -0
- package/entity/entity-key.d.ts +95 -0
- package/entity/entity-key.js +189 -0
- package/entity/entity-key.js.map +1 -0
- package/{src → entity}/entity-state.d.ts +112 -84
- package/entity/entity-state.js +135 -0
- package/entity/entity-state.js.map +1 -0
- package/entity/key-generator.d.ts +57 -0
- package/entity/key-generator.js +155 -0
- package/entity/key-generator.js.map +1 -0
- package/entity/observable-array.d.ts +25 -0
- package/entity/observable-array.js +230 -0
- package/entity/observable-array.js.map +1 -0
- package/entity/primitive-array.d.ts +12 -0
- package/entity/primitive-array.js +71 -0
- package/entity/primitive-array.js.map +1 -0
- package/entity/relation-array.d.ts +24 -0
- package/entity/relation-array.js +176 -0
- package/entity/relation-array.js.map +1 -0
- package/entity/unattached-children-map.d.ts +1 -0
- package/entity/unattached-children-map.js +105 -0
- package/entity/unattached-children-map.js.map +1 -0
- package/generate-entity-classes.js +1176 -0
- package/manager/entity-manager.d.ts +801 -0
- package/manager/entity-manager.js +2395 -0
- package/manager/entity-manager.js.map +1 -0
- package/{src → manager}/save-options.d.ts +48 -42
- package/manager/save-options.js +51 -0
- package/manager/save-options.js.map +1 -0
- package/{src → metadata}/data-service.d.ts +229 -184
- package/metadata/data-service.js +246 -0
- package/metadata/data-service.js.map +1 -0
- package/metadata/data-type.d.ts +122 -0
- package/metadata/data-type.js +465 -0
- package/metadata/data-type.js.map +1 -0
- package/metadata/entity-metadata.d.ts +1193 -0
- package/metadata/entity-metadata.js +2502 -0
- package/metadata/entity-metadata.js.map +1 -0
- package/{src → metadata}/local-query-comparison-options.d.ts +65 -59
- package/metadata/local-query-comparison-options.js +69 -0
- package/metadata/local-query-comparison-options.js.map +1 -0
- package/{src → metadata}/naming-convention.d.ts +75 -72
- package/metadata/naming-convention.js +97 -0
- package/metadata/naming-convention.js.map +1 -0
- package/mixins/mixin-get-entity-graph.d.ts +63 -0
- package/{fesm2022/breeze-client-mixin-get-entity-graph.mjs → mixins/mixin-get-entity-graph.js} +331 -253
- package/mixins/mixin-get-entity-graph.js.map +1 -0
- package/mixins/mixin-save-queuing.d.ts +98 -0
- package/{fesm2022/breeze-client-mixin-save-queuing.mjs → mixins/mixin-save-queuing.js} +493 -365
- package/mixins/mixin-save-queuing.js.map +1 -0
- package/package.json +63 -94
- package/query/entity-query.d.ts +521 -0
- package/query/entity-query.js +1149 -0
- package/query/entity-query.js.map +1 -0
- package/{src → query}/mapping-context.d.ts +44 -46
- package/query/mapping-context.js +412 -0
- package/query/mapping-context.js.map +1 -0
- package/query/predicate.d.ts +394 -0
- package/query/predicate.js +1294 -0
- package/query/predicate.js.map +1 -0
- package/query/property-path.d.ts +252 -0
- package/query/property-path.js +2 -0
- package/query/property-path.js.map +1 -0
- package/{src → query}/query-options.d.ts +143 -119
- package/query/query-options.js +180 -0
- package/query/query-options.js.map +1 -0
- package/rxjs/breeze-rxjs.d.ts +72 -0
- package/rxjs/breeze-rxjs.js +117 -0
- package/rxjs/breeze-rxjs.js.map +1 -0
- package/validation/validate.d.ts +583 -0
- package/validation/validate.js +961 -0
- package/validation/validate.js.map +1 -0
- package/{src → validation}/validation-options.d.ts +67 -63
- package/validation/validation-options.js +70 -0
- package/validation/validation-options.js.map +1 -0
- package/adapter-ajax-angularjs/adapter-ajax-angularjs.d.ts +0 -17
- package/adapter-ajax-angularjs/adapter-core.d.ts +0 -4
- package/adapter-ajax-angularjs/index.d.ts +0 -5
- package/adapter-ajax-fetch/adapter-ajax-fetch.d.ts +0 -18
- package/adapter-ajax-fetch/index.d.ts +0 -5
- package/adapter-ajax-httpclient/adapter-ajax-httpclient.d.ts +0 -13
- package/adapter-ajax-httpclient/adapter-core.d.ts +0 -4
- package/adapter-ajax-httpclient/index.d.ts +0 -5
- package/adapter-ajax-jquery/adapter-ajax-jquery.d.ts +0 -15
- package/adapter-ajax-jquery/index.d.ts +0 -5
- package/adapter-ajax-post/index.d.ts +0 -5
- package/adapter-data-service-odata/adapter-core.d.ts +0 -4
- package/adapter-data-service-odata/adapter-data-service-odata.d.ts +0 -17
- package/adapter-data-service-odata/index.d.ts +0 -5
- package/adapter-data-service-webapi/adapter-data-service-webapi.d.ts +0 -15
- package/adapter-data-service-webapi/index.d.ts +0 -5
- package/adapter-model-library-backing-store/adapter-model-library-backing-store.d.ts +0 -10
- package/adapter-model-library-backing-store/index.d.ts +0 -5
- package/adapter-model-library-ko/adapter-model-library-ko.d.ts +0 -10
- package/adapter-model-library-ko/index.d.ts +0 -5
- package/adapter-uri-builder-json/adapter-core.d.ts +0 -4
- package/adapter-uri-builder-json/adapter-uri-builder-json.d.ts +0 -8
- package/adapter-uri-builder-json/index.d.ts +0 -5
- package/adapter-uri-builder-odata/adapter-core.d.ts +0 -4
- package/adapter-uri-builder-odata/adapter-uri-builder-odata.d.ts +0 -8
- package/adapter-uri-builder-odata/index.d.ts +0 -5
- package/esm2022/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +0 -135
- package/esm2022/adapter-ajax-angularjs/adapter-core.mjs +0 -49
- package/esm2022/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +0 -5
- package/esm2022/adapter-ajax-fetch/adapter-ajax-fetch.mjs +0 -135
- package/esm2022/adapter-ajax-fetch/adapter-core.mjs +0 -49
- package/esm2022/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +0 -5
- package/esm2022/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +0 -139
- package/esm2022/adapter-ajax-httpclient/adapter-core.mjs +0 -49
- package/esm2022/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +0 -5
- package/esm2022/adapter-ajax-jquery/adapter-ajax-jquery.mjs +0 -107
- package/esm2022/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +0 -5
- package/esm2022/adapter-ajax-post/adapter-ajax-post.mjs +0 -77
- package/esm2022/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +0 -5
- package/esm2022/adapter-data-service-odata/adapter-core.mjs +0 -49
- package/esm2022/adapter-data-service-odata/adapter-data-service-odata.mjs +0 -461
- package/esm2022/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +0 -5
- package/esm2022/adapter-data-service-webapi/adapter-data-service-webapi.mjs +0 -100
- package/esm2022/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +0 -5
- package/esm2022/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +0 -269
- package/esm2022/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +0 -5
- package/esm2022/adapter-model-library-ko/adapter-model-library-ko.mjs +0 -241
- package/esm2022/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +0 -5
- package/esm2022/adapter-uri-builder-json/adapter-core.mjs +0 -49
- package/esm2022/adapter-uri-builder-json/adapter-uri-builder-json.mjs +0 -37
- package/esm2022/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +0 -5
- package/esm2022/adapter-uri-builder-odata/adapter-core.mjs +0 -49
- package/esm2022/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +0 -191
- package/esm2022/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +0 -5
- package/esm2022/breeze-client.mjs +0 -5
- package/esm2022/index.mjs +0 -2
- package/esm2022/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +0 -5
- package/esm2022/mixin-get-entity-graph/mixin-get-entity-graph.mjs +0 -269
- package/esm2022/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +0 -5
- package/esm2022/mixin-save-queuing/mixin-save-queuing.mjs +0 -421
- package/esm2022/src/abstract-data-service-adapter.mjs +0 -325
- package/esm2022/src/array.mjs +0 -4
- package/esm2022/src/assert-param.mjs +0 -330
- package/esm2022/src/breeze.mjs +0 -85
- package/esm2022/src/complex-array.mjs +0 -117
- package/esm2022/src/config.mjs +0 -232
- package/esm2022/src/core.mjs +0 -712
- package/esm2022/src/csdl-metadata-parser.mjs +0 -385
- package/esm2022/src/data-service.mjs +0 -221
- package/esm2022/src/data-type.mjs +0 -510
- package/esm2022/src/default-property-interceptor.mjs +0 -460
- package/esm2022/src/entity-action.mjs +0 -45
- package/esm2022/src/entity-aspect.mjs +0 -897
- package/esm2022/src/entity-group.mjs +0 -192
- package/esm2022/src/entity-key.mjs +0 -125
- package/esm2022/src/entity-manager.mjs +0 -2163
- package/esm2022/src/entity-metadata.mjs +0 -2242
- package/esm2022/src/entity-query.mjs +0 -1024
- package/esm2022/src/entity-state.mjs +0 -107
- package/esm2022/src/enum.mjs +0 -143
- package/esm2022/src/event.mjs +0 -264
- package/esm2022/src/interface-registry.mjs +0 -39
- package/esm2022/src/key-generator.mjs +0 -110
- package/esm2022/src/local-query-comparison-options.mjs +0 -65
- package/esm2022/src/mapping-context.mjs +0 -411
- package/esm2022/src/naming-convention.mjs +0 -92
- package/esm2022/src/observable-array.mjs +0 -183
- package/esm2022/src/predicate.mjs +0 -1259
- package/esm2022/src/primitive-array.mjs +0 -85
- package/esm2022/src/query-options.mjs +0 -152
- package/esm2022/src/relation-array.mjs +0 -173
- package/esm2022/src/save-options.mjs +0 -41
- package/esm2022/src/unattached-children-map.mjs +0 -56
- package/esm2022/src/validate.mjs +0 -995
- package/esm2022/src/validation-options.mjs +0 -64
- package/fesm2022/breeze-client-adapter-ajax-angularjs.mjs +0 -190
- package/fesm2022/breeze-client-adapter-ajax-angularjs.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-ajax-fetch.mjs +0 -190
- package/fesm2022/breeze-client-adapter-ajax-fetch.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-ajax-httpclient.mjs +0 -194
- package/fesm2022/breeze-client-adapter-ajax-httpclient.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-ajax-jquery.mjs +0 -114
- package/fesm2022/breeze-client-adapter-ajax-jquery.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-ajax-post.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-data-service-odata.mjs +0 -516
- package/fesm2022/breeze-client-adapter-data-service-odata.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-data-service-webapi.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-model-library-backing-store.mjs +0 -276
- package/fesm2022/breeze-client-adapter-model-library-backing-store.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-model-library-ko.mjs +0 -248
- package/fesm2022/breeze-client-adapter-model-library-ko.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-uri-builder-json.mjs.map +0 -1
- package/fesm2022/breeze-client-adapter-uri-builder-odata.mjs +0 -246
- package/fesm2022/breeze-client-adapter-uri-builder-odata.mjs.map +0 -1
- package/fesm2022/breeze-client-mixin-get-entity-graph.mjs.map +0 -1
- package/fesm2022/breeze-client-mixin-save-queuing.mjs.map +0 -1
- package/fesm2022/breeze-client.mjs +0 -14144
- package/fesm2022/breeze-client.mjs.map +0 -1
- package/index.d.ts +0 -1
- package/mixin-get-entity-graph/index.d.ts +0 -5
- package/mixin-get-entity-graph/mixin-get-entity-graph.d.ts +0 -31
- package/mixin-save-queuing/index.d.ts +0 -5
- package/mixin-save-queuing/mixin-save-queuing.d.ts +0 -32
- package/src/abstract-data-service-adapter.d.ts +0 -84
- package/src/array.d.ts +0 -3
- package/src/breeze.d.ts +0 -139
- package/src/complex-array.d.ts +0 -13
- package/src/config.d.ts +0 -104
- package/src/core.d.ts +0 -164
- package/src/csdl-metadata-parser.d.ts +0 -7
- package/src/data-type.d.ts +0 -89
- package/src/default-property-interceptor.d.ts +0 -4
- package/src/entity-aspect.d.ts +0 -332
- package/src/entity-group.d.ts +0 -28
- package/src/entity-key.d.ts +0 -77
- package/src/entity-manager.d.ts +0 -680
- package/src/entity-metadata.d.ts +0 -988
- package/src/entity-query.d.ts +0 -444
- package/src/enum.d.ts +0 -100
- package/src/event.d.ts +0 -142
- package/src/interface-registry.d.ts +0 -150
- package/src/key-generator.d.ts +0 -12
- package/src/observable-array.d.ts +0 -52
- package/src/predicate.d.ts +0 -376
- package/src/primitive-array.d.ts +0 -7
- package/src/relation-array.d.ts +0 -18
- package/src/unattached-children-map.d.ts +0 -19
- 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==
|