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