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,2109 +0,0 @@
|
|
|
1
|
-
import { core } from './core';
|
|
2
|
-
import { config } from './config';
|
|
3
|
-
import { BreezeEvent } from './event';
|
|
4
|
-
import { assertParam, assertConfig, Param } from './assert-param';
|
|
5
|
-
import { DataType } from './data-type';
|
|
6
|
-
import { EntityAspect, ComplexAspect } from './entity-aspect';
|
|
7
|
-
import { EntityKey } from './entity-key';
|
|
8
|
-
import { Validator } from './validate';
|
|
9
|
-
import { BreezeEnum } from './enum';
|
|
10
|
-
import { DataService } from './data-service';
|
|
11
|
-
import { NamingConvention } from './naming-convention';
|
|
12
|
-
import { CsdlMetadataParser } from './csdl-metadata-parser'; // TODO isolate this later;
|
|
13
|
-
import { LocalQueryComparisonOptions } from './local-query-comparison-options';
|
|
14
|
-
import { defaultPropertyInterceptor } from './default-property-interceptor';
|
|
15
|
-
/**
|
|
16
|
-
An instance of the MetadataStore contains all of the metadata about a collection of [[EntityType]]'s.
|
|
17
|
-
MetadataStores may be shared across [[EntityManager]]'s. If an EntityManager is created without an
|
|
18
|
-
explicit MetadataStore, the MetadataStore from the MetadataStore.defaultInstance property will be used.
|
|
19
|
-
@dynamic
|
|
20
|
-
**/
|
|
21
|
-
export class MetadataStore {
|
|
22
|
-
/**
|
|
23
|
-
Constructs a new MetadataStore.
|
|
24
|
-
|
|
25
|
-
> let ms = new MetadataStore();
|
|
26
|
-
|
|
27
|
-
The store can then be associated with an EntityManager
|
|
28
|
-
> let entityManager = new EntityManager( {
|
|
29
|
-
> serviceName: "breeze/NorthwindIBModel",
|
|
30
|
-
> metadataStore: ms
|
|
31
|
-
> });
|
|
32
|
-
|
|
33
|
-
or for an existing EntityManager
|
|
34
|
-
> // Assume em1 is an existing EntityManager
|
|
35
|
-
> em1.setProperties( { metadataStore: ms });
|
|
36
|
-
|
|
37
|
-
@param config - Configuration settings .
|
|
38
|
-
- namingConvention - (default=NamingConvention.defaultInstance) NamingConvention to be used in mapping property names
|
|
39
|
-
between client and server. Uses the NamingConvention.defaultInstance if not specified.
|
|
40
|
-
- localQueryComparisonOptions - (default=LocalQueryComparisonOptions.defaultInstance) The LocalQueryComparisonOptions to be
|
|
41
|
-
used when performing "local queries" in order to match the semantics of queries against a remote service.
|
|
42
|
-
- serializerFn - A function that is used to mediate the serialization of instances of this type.
|
|
43
|
-
**/
|
|
44
|
-
constructor(config) {
|
|
45
|
-
config = config || {};
|
|
46
|
-
assertConfig(config)
|
|
47
|
-
.whereParam("namingConvention").isOptional().isInstanceOf(NamingConvention).withDefault(NamingConvention.defaultInstance)
|
|
48
|
-
.whereParam("localQueryComparisonOptions").isOptional().isInstanceOf(LocalQueryComparisonOptions).withDefault(LocalQueryComparisonOptions.defaultInstance)
|
|
49
|
-
.whereParam("serializerFn").isOptional().isFunction()
|
|
50
|
-
.applyAll(this);
|
|
51
|
-
this.dataServices = []; // array of dataServices;
|
|
52
|
-
this._resourceEntityTypeMap = {}; // key is resource name - value is qualified entityType name
|
|
53
|
-
this._structuralTypeMap = {}; // key is qualified structuraltype name - value is structuralType. ( structural = entityType or complexType).
|
|
54
|
-
this._shortNameMap = {}; // key is shortName, value is qualified name - does not need to be serialized.
|
|
55
|
-
this._ctorRegistry = {}; // key is either short or qual type name - value is ctor;
|
|
56
|
-
this._incompleteTypeMap = {}; // key is entityTypeName; value is array of nav props
|
|
57
|
-
this._incompleteComplexTypeMap = {}; // key is complexTypeName; value is array of complexType props
|
|
58
|
-
this._id = MetadataStore.__id++;
|
|
59
|
-
this.metadataFetched = new BreezeEvent("metadataFetched", this);
|
|
60
|
-
}
|
|
61
|
-
// for debugging use the line below instead.
|
|
62
|
-
//ctor.normalizeTypeName = function (rawTypeName) { return parseTypeName(rawTypeName).typeName; };
|
|
63
|
-
/**
|
|
64
|
-
General purpose property set method
|
|
65
|
-
|
|
66
|
-
> // assume em1 is an EntityManager containing a number of existing entities.
|
|
67
|
-
> em1.metadataStore.setProperties( {
|
|
68
|
-
> version: "6.1.3",
|
|
69
|
-
> serializerFn: function(prop, value) {
|
|
70
|
-
> return (prop.isUnmapped) ? undefined : value;
|
|
71
|
-
> }
|
|
72
|
-
> )};
|
|
73
|
-
@param config - An object containing the selected properties and values to set.
|
|
74
|
-
**/
|
|
75
|
-
setProperties(config) {
|
|
76
|
-
assertConfig(config)
|
|
77
|
-
.whereParam("name").isString().isOptional()
|
|
78
|
-
.whereParam("serializerFn").isFunction().isOptional()
|
|
79
|
-
.applyAll(this);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
Adds a DataService to this MetadataStore. If a DataService with the same serviceName is already
|
|
83
|
-
in the MetadataStore an exception will be thrown.
|
|
84
|
-
@param dataService - The [[DataService]] to add
|
|
85
|
-
@param shouldOverwrite - (default=false) Permit overwrite of existing DataService rather than throw exception
|
|
86
|
-
**/
|
|
87
|
-
addDataService(dataService, shouldOverwrite) {
|
|
88
|
-
assertParam(dataService, "dataService").isInstanceOf(DataService).check();
|
|
89
|
-
assertParam(shouldOverwrite, "shouldOverwrite").isBoolean().isOptional().check();
|
|
90
|
-
let ix = this._getDataServiceIndex(dataService.serviceName);
|
|
91
|
-
if (ix >= 0) {
|
|
92
|
-
if (!!shouldOverwrite) {
|
|
93
|
-
this.dataServices[ix] = dataService;
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
throw new Error("A dataService with this name '" + dataService.serviceName + "' already exists in this MetadataStore");
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
this.dataServices.push(dataService);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
/** @hidden @internal */
|
|
104
|
-
_getDataServiceIndex(serviceName) {
|
|
105
|
-
return core.arrayIndexOf(this.dataServices, function (ds) {
|
|
106
|
-
return ds.serviceName === serviceName;
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
Adds an EntityType to this MetadataStore. No additional properties may be added to the EntityType after its has
|
|
111
|
-
been added to the MetadataStore.
|
|
112
|
-
@param structuralType - The EntityType or ComplexType to add
|
|
113
|
-
**/
|
|
114
|
-
addEntityType(stype) {
|
|
115
|
-
let structuralType;
|
|
116
|
-
if (stype instanceof EntityType || stype instanceof ComplexType) {
|
|
117
|
-
structuralType = stype;
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
structuralType = stype.isComplexType ? new ComplexType(stype) : new EntityType(stype);
|
|
121
|
-
}
|
|
122
|
-
// if (!structuralType.isComplexType) { // same as below but isn't a 'type guard'
|
|
123
|
-
if (structuralType instanceof EntityType) {
|
|
124
|
-
if (structuralType.baseTypeName && !structuralType.baseEntityType) {
|
|
125
|
-
let baseEntityType = this._getStructuralType(structuralType.baseTypeName, true);
|
|
126
|
-
// safe cast because we know that baseEntityType must be an EntityType if the structuralType is an EntityType
|
|
127
|
-
structuralType._updateFromBase(baseEntityType);
|
|
128
|
-
}
|
|
129
|
-
if (structuralType.keyProperties.length === 0 && !structuralType.isAbstract) {
|
|
130
|
-
throw new Error("Unable to add " + structuralType.name +
|
|
131
|
-
" to this MetadataStore. An EntityType must have at least one property designated as a key property - See the 'DataProperty.isPartOfKey' property.");
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
structuralType.metadataStore = this;
|
|
135
|
-
// don't register anon types
|
|
136
|
-
if (!structuralType.isAnonymous) {
|
|
137
|
-
if (this._structuralTypeMap[structuralType.name]) {
|
|
138
|
-
throw new Error("Type " + structuralType.name + " already exists in this MetadataStore.");
|
|
139
|
-
}
|
|
140
|
-
this._structuralTypeMap[structuralType.name] = structuralType;
|
|
141
|
-
this._shortNameMap[structuralType.shortName] = structuralType.name;
|
|
142
|
-
}
|
|
143
|
-
structuralType.getProperties().forEach(p => {
|
|
144
|
-
structuralType._updateNames(p);
|
|
145
|
-
if (!p.isUnmapped) {
|
|
146
|
-
structuralType._mappedPropertiesCount++;
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
structuralType._updateCps();
|
|
150
|
-
// 'isEntityType' is a type guard
|
|
151
|
-
if (structuralType instanceof EntityType) {
|
|
152
|
-
structuralType._updateNps();
|
|
153
|
-
// give the type it's base's resource name if it doesn't have its own.
|
|
154
|
-
let defResourceName = structuralType.defaultResourceName || (structuralType.baseEntityType && structuralType.baseEntityType.defaultResourceName);
|
|
155
|
-
if (defResourceName && !this.getEntityTypeNameForResourceName(defResourceName)) {
|
|
156
|
-
this.setEntityTypeForResourceName(defResourceName, structuralType.name);
|
|
157
|
-
}
|
|
158
|
-
structuralType.defaultResourceName = defResourceName;
|
|
159
|
-
// check if this structural type's name, short version or qualified version has a registered ctor.
|
|
160
|
-
structuralType.getEntityCtor();
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
Exports this MetadataStore to a serialized string appropriate for local storage. This operation is also called
|
|
165
|
-
internally when exporting an EntityManager.
|
|
166
|
-
> // assume ms is a previously created MetadataStore
|
|
167
|
-
> let metadataAsString = ms.exportMetadata();
|
|
168
|
-
> window.localStorage.setItem("metadata", metadataAsString);
|
|
169
|
-
> // and later, usually in a different session imported
|
|
170
|
-
> let metadataFromStorage = window.localStorage.getItem("metadata");
|
|
171
|
-
> let newMetadataStore = new MetadataStore();
|
|
172
|
-
> newMetadataStore.importMetadata(metadataFromStorage);
|
|
173
|
-
@return A serialized version of this MetadataStore that may be stored locally and later restored.
|
|
174
|
-
**/
|
|
175
|
-
exportMetadata() {
|
|
176
|
-
let result = JSON.stringify({
|
|
177
|
-
"metadataVersion": MetadataStore.metadataVersion,
|
|
178
|
-
"name": this.name,
|
|
179
|
-
"namingConvention": this.namingConvention.name,
|
|
180
|
-
"localQueryComparisonOptions": this.localQueryComparisonOptions.name,
|
|
181
|
-
"dataServices": this.dataServices,
|
|
182
|
-
"structuralTypes": core.objectMap(this._structuralTypeMap),
|
|
183
|
-
"resourceEntityTypeMap": this._resourceEntityTypeMap
|
|
184
|
-
}, null, config.stringifyPad);
|
|
185
|
-
return result;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
Imports a previously exported serialized MetadataStore into this MetadataStore.
|
|
189
|
-
|
|
190
|
-
> // assume ms is a previously created MetadataStore
|
|
191
|
-
> let metadataAsString = ms.exportMetadata();
|
|
192
|
-
> window.localStorage.setItem("metadata", metadataAsString);
|
|
193
|
-
> // and later, usually in a different session
|
|
194
|
-
> let metadataFromStorage = window.localStorage.getItem("metadata");
|
|
195
|
-
> let newMetadataStore = new MetadataStore();
|
|
196
|
-
> newMetadataStore.importMetadata(metadataFromStorage);
|
|
197
|
-
@param exportedMetadata - A previously exported MetadataStore.
|
|
198
|
-
@param allowMerge - Allows custom metadata to be merged into existing metadata types.
|
|
199
|
-
@return This MetadataStore.
|
|
200
|
-
@chainable
|
|
201
|
-
**/
|
|
202
|
-
importMetadata(exportedMetadata, allowMerge = false) {
|
|
203
|
-
assertParam(allowMerge, "allowMerge").isOptional().isBoolean().check();
|
|
204
|
-
this._deferredTypes = {};
|
|
205
|
-
// insure that we don't mutate incoming exportedMetadata ( if its an object)
|
|
206
|
-
let metadataAsString = (typeof (exportedMetadata) === "string") ? exportedMetadata : JSON.stringify(exportedMetadata);
|
|
207
|
-
const metadataJson = JSON.parse(metadataAsString);
|
|
208
|
-
if (metadataJson.schema) {
|
|
209
|
-
return CsdlMetadataParser.parse(this, metadataJson.schema, metadataJson.altMetadata);
|
|
210
|
-
}
|
|
211
|
-
let json = metadataJson;
|
|
212
|
-
if (json.metadataVersion && json.metadataVersion !== MetadataStore.metadataVersion) {
|
|
213
|
-
let msg = core.formatString("Cannot import metadata with a different 'metadataVersion' (%1) than the current 'MetadataStore.metadataVersion' (%2) ", json.metadataVersion, MetadataStore.metadataVersion);
|
|
214
|
-
throw new Error(msg);
|
|
215
|
-
}
|
|
216
|
-
let ncName = json.namingConvention;
|
|
217
|
-
let lqcoName = json.localQueryComparisonOptions;
|
|
218
|
-
if (this.isEmpty()) {
|
|
219
|
-
this.namingConvention = config._fetchObject(NamingConvention, ncName) || this.namingConvention;
|
|
220
|
-
this.localQueryComparisonOptions = config._fetchObject(LocalQueryComparisonOptions, lqcoName) || this.localQueryComparisonOptions;
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
if (ncName && this.namingConvention.name !== ncName) {
|
|
224
|
-
throw new Error("Cannot import metadata with a different 'namingConvention' from the current MetadataStore");
|
|
225
|
-
}
|
|
226
|
-
if (lqcoName && this.localQueryComparisonOptions.name !== lqcoName) {
|
|
227
|
-
throw new Error("Cannot import metadata with different 'localQueryComparisonOptions' from the current MetadataStore");
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
//noinspection JSHint
|
|
231
|
-
json.dataServices && json.dataServices.forEach((ds) => {
|
|
232
|
-
let realDs = DataService.fromJSON(ds);
|
|
233
|
-
this.addDataService(realDs, true);
|
|
234
|
-
});
|
|
235
|
-
json.structuralTypes && json.structuralTypes.forEach((stype) => {
|
|
236
|
-
structuralTypeFromJson(this, stype, allowMerge);
|
|
237
|
-
});
|
|
238
|
-
core.extend(this._resourceEntityTypeMap, json.resourceEntityTypeMap);
|
|
239
|
-
core.extend(this._incompleteTypeMap, json.incompleteTypeMap);
|
|
240
|
-
return this;
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
Creates a new MetadataStore from a previously exported serialized MetadataStore
|
|
244
|
-
> // assume ms is a previously created MetadataStore
|
|
245
|
-
> let metadataAsString = ms.exportMetadata();
|
|
246
|
-
> window.localStorage.setItem("metadata", metadataAsString);
|
|
247
|
-
> // and later, usually in a different session
|
|
248
|
-
> let metadataFromStorage = window.localStorage.getItem("metadata");
|
|
249
|
-
> let newMetadataStore = MetadataStore.importMetadata(metadataFromStorage);
|
|
250
|
-
@param exportedString - A previously exported MetadataStore.
|
|
251
|
-
@return A new MetadataStore.
|
|
252
|
-
**/
|
|
253
|
-
static importMetadata(exportedString) {
|
|
254
|
-
let ms = new MetadataStore();
|
|
255
|
-
ms.importMetadata(exportedString);
|
|
256
|
-
return ms;
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
Returns whether Metadata has been retrieved for a specified service name.
|
|
260
|
-
> // Assume em1 is an existing EntityManager.
|
|
261
|
-
> if (!em1.metadataStore.hasMetadataFor("breeze/NorthwindIBModel"))) {
|
|
262
|
-
> // do something interesting
|
|
263
|
-
> }
|
|
264
|
-
@param serviceName - The service name.
|
|
265
|
-
@return Whether metadata has already been retrieved for the specified service name.
|
|
266
|
-
**/
|
|
267
|
-
hasMetadataFor(serviceName) {
|
|
268
|
-
return !!this.getDataService(serviceName);
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
Returns the DataService for a specified service name
|
|
272
|
-
> // Assume em1 is an existing EntityManager.
|
|
273
|
-
> let ds = em1.metadataStore.getDataService("breeze/NorthwindIBModel");
|
|
274
|
-
> let adapterName = ds.adapterName; // may be null
|
|
275
|
-
@param serviceName - The service name.
|
|
276
|
-
@return The DataService with the specified name.
|
|
277
|
-
**/
|
|
278
|
-
getDataService(serviceName) {
|
|
279
|
-
assertParam(serviceName, "serviceName").isString().check();
|
|
280
|
-
serviceName = DataService._normalizeServiceName(serviceName);
|
|
281
|
-
return core.arrayFirst(this.dataServices, function (ds) {
|
|
282
|
-
return ds.serviceName === serviceName;
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
Fetches the metadata for a specified 'service'. This method is automatically called
|
|
287
|
-
internally by an EntityManager before its first query against a new service. __Async__
|
|
288
|
-
|
|
289
|
-
Usually you will not actually process the results of a fetchMetadata call directly, but will instead
|
|
290
|
-
ask for the metadata from the EntityManager after the fetchMetadata call returns.
|
|
291
|
-
> let ms = new MetadataStore();
|
|
292
|
-
> // or more commonly
|
|
293
|
-
> // let ms = anEntityManager.metadataStore;
|
|
294
|
-
> ms.fetchMetadata("breeze/NorthwindIBModel").then(function(rawMetadata) {
|
|
295
|
-
> // do something with the metadata
|
|
296
|
-
> }).catch(function(exception) {
|
|
297
|
-
> // handle exception here
|
|
298
|
-
> });
|
|
299
|
-
@param dataService - Either a DataService or just the name of the DataService to fetch metadata for.
|
|
300
|
-
@param callback - Function called on success.
|
|
301
|
-
@param errorCallback - Function called on failure.
|
|
302
|
-
@return Promise
|
|
303
|
-
**/
|
|
304
|
-
fetchMetadata(dataService, callback, errorCallback) {
|
|
305
|
-
try {
|
|
306
|
-
assertParam(dataService, "dataService").isString().or().isInstanceOf(DataService).check();
|
|
307
|
-
assertParam(callback, "callback").isFunction().isOptional().check();
|
|
308
|
-
assertParam(errorCallback, "errorCallback").isFunction().isOptional().check();
|
|
309
|
-
if (typeof dataService === "string") {
|
|
310
|
-
// use the dataService with a matching name or create a new one.
|
|
311
|
-
dataService = this.getDataService(dataService) || new DataService({ serviceName: dataService });
|
|
312
|
-
}
|
|
313
|
-
dataService = DataService.resolve([dataService]);
|
|
314
|
-
if (this.hasMetadataFor(dataService.serviceName)) {
|
|
315
|
-
throw new Error("Metadata for a specific serviceName may only be fetched once per MetadataStore. ServiceName: " + dataService.serviceName);
|
|
316
|
-
}
|
|
317
|
-
return dataService.adapterInstance.fetchMetadata(this, dataService).then((rawMetadata) => {
|
|
318
|
-
this.metadataFetched.publish({ metadataStore: this, dataService: dataService, rawMetadata: rawMetadata });
|
|
319
|
-
if (callback)
|
|
320
|
-
callback(rawMetadata);
|
|
321
|
-
return Promise.resolve(rawMetadata);
|
|
322
|
-
}, function (error) {
|
|
323
|
-
if (errorCallback)
|
|
324
|
-
errorCallback(error);
|
|
325
|
-
return Promise.reject(error);
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
catch (e) {
|
|
329
|
-
return Promise.reject(e);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
// TODO: strongly type interceptor below.
|
|
333
|
-
/**
|
|
334
|
-
Used to register a constructor for an EntityType that is not known via standard Metadata discovery;
|
|
335
|
-
i.e. an unmapped type.
|
|
336
|
-
@param entityCtor - The constructor function for the 'unmapped' type.
|
|
337
|
-
@param interceptor - An interceptor function
|
|
338
|
-
**/
|
|
339
|
-
trackUnmappedType(entityCtor, interceptor) {
|
|
340
|
-
assertParam(entityCtor, "entityCtor").isFunction().check();
|
|
341
|
-
assertParam(interceptor, "interceptor").isFunction().isOptional().check();
|
|
342
|
-
// TODO: think about adding this to the MetadataStore.
|
|
343
|
-
let entityType = new EntityType(this);
|
|
344
|
-
entityType._setCtor(entityCtor, interceptor);
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
Provides a mechanism to register a 'custom' constructor to be used when creating new instances
|
|
348
|
-
of the specified entity type. If this call is not made, a default constructor is created for
|
|
349
|
-
the entity as needed.
|
|
350
|
-
This call may be made before or after the corresponding EntityType has been discovered via
|
|
351
|
-
Metadata discovery.
|
|
352
|
-
> let Customer = function () {
|
|
353
|
-
> this.miscData = "asdf";
|
|
354
|
-
> };
|
|
355
|
-
> Customer.prototype.doFoo() {
|
|
356
|
-
> ...
|
|
357
|
-
> }
|
|
358
|
-
> // assume em1 is a preexisting EntityManager;
|
|
359
|
-
> em1.metadataStore.registerEntityTypeCtor("Customer", Customer);
|
|
360
|
-
> // any queries or EntityType.create calls from this point on will call the Customer constructor
|
|
361
|
-
> // registered above.
|
|
362
|
-
@param structuralTypeName - The name of the EntityType or ComplexType.
|
|
363
|
-
@param aCtor - The constructor for this EntityType or ComplexType; may be null if all you want to do is set the next parameter.
|
|
364
|
-
@param initFn - A function or the name of a function on the entity that is to be executed immediately after the entity has been created
|
|
365
|
-
and populated with any initial values. Called with 'initFn(entity)'
|
|
366
|
-
@param noTrackingFn - A function that is executed immediately after a noTracking entity has been created and whose return
|
|
367
|
-
value will be used in place of the noTracking entity.
|
|
368
|
-
**/
|
|
369
|
-
registerEntityTypeCtor(structuralTypeName, aCtor, initFn, noTrackingFn) {
|
|
370
|
-
assertParam(structuralTypeName, "structuralTypeName").isString().check();
|
|
371
|
-
assertParam(aCtor, "aCtor").isFunction().isOptional().check();
|
|
372
|
-
assertParam(initFn, "initFn").isOptional().isFunction().or().isString().check();
|
|
373
|
-
assertParam(noTrackingFn, "noTrackingFn").isOptional().isFunction().check();
|
|
374
|
-
let qualifiedTypeName = getQualifiedTypeName(this, structuralTypeName, false);
|
|
375
|
-
let typeName = qualifiedTypeName || structuralTypeName;
|
|
376
|
-
if (aCtor) {
|
|
377
|
-
if (aCtor._$typeName && aCtor._$typeName !== typeName) {
|
|
378
|
-
// TODO: wrap this - console and especially console.warn does not exist in all browsers.
|
|
379
|
-
console.warn("Registering a constructor for " + typeName + " that is already used for " + aCtor._$typeName + ".");
|
|
380
|
-
}
|
|
381
|
-
aCtor._$typeName = typeName;
|
|
382
|
-
}
|
|
383
|
-
this._ctorRegistry[typeName] = { ctor: aCtor, initFn: initFn, noTrackingFn: noTrackingFn };
|
|
384
|
-
if (qualifiedTypeName) {
|
|
385
|
-
let stype = this._structuralTypeMap[qualifiedTypeName];
|
|
386
|
-
stype && stype.getCtor(true); // this will complete the registration if avail now.
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
Returns whether this MetadataStore contains any metadata yet.
|
|
391
|
-
> // assume em1 is a preexisting EntityManager;
|
|
392
|
-
> if (em1.metadataStore.isEmpty()) {
|
|
393
|
-
> // do something interesting
|
|
394
|
-
> }
|
|
395
|
-
**/
|
|
396
|
-
isEmpty() {
|
|
397
|
-
return core.isEmpty(this._structuralTypeMap);
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
Returns an [[EntityType]] or null given its name.
|
|
401
|
-
> // assume em1 is a preexisting EntityManager
|
|
402
|
-
> let odType = em1.metadataStore.getAsEntityType("OrderDetail");
|
|
403
|
-
|
|
404
|
-
or to throw an error if the type is not found
|
|
405
|
-
> let badType = em1.metadataStore.getAsEntityType("Foo", false);
|
|
406
|
-
> // badType will not get set and an exception will be thrown.
|
|
407
|
-
@param structuralTypeName - Either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
|
|
408
|
-
that same short name an exception will be thrown.
|
|
409
|
-
@param okIfNotFound - (default=false) Whether to throw an error if the specified EntityType is not found.
|
|
410
|
-
@return The EntityType. ComplexType or 'null' if not not found.
|
|
411
|
-
**/
|
|
412
|
-
getAsEntityType(typeName, okIfNotFound = false) {
|
|
413
|
-
const st = this.getStructuralType(typeName, okIfNotFound);
|
|
414
|
-
if (st instanceof EntityType) {
|
|
415
|
-
return st;
|
|
416
|
-
}
|
|
417
|
-
else if (okIfNotFound) {
|
|
418
|
-
return null;
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
let msg = core.formatString("Unable to locate an 'EntityType' by the name: '%1'. Be sure to execute a query or call fetchMetadata first.", typeName);
|
|
422
|
-
throw new Error(msg);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
/**
|
|
426
|
-
Returns an [[EntityType]] or null given its name.
|
|
427
|
-
> // assume em1 is a preexisting EntityManager
|
|
428
|
-
> let locType = em1.metadataStore.getAsComplexType("Location");
|
|
429
|
-
|
|
430
|
-
or to throw an error if the type is not found
|
|
431
|
-
> let badType = em1.metadataStore.getAsComplexType("Foo", false);
|
|
432
|
-
> // badType will not get set and an exception will be thrown.
|
|
433
|
-
@param structuralTypeName - Either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
|
|
434
|
-
that same short name an exception will be thrown.
|
|
435
|
-
@param okIfNotFound - (default=false) Whether to throw an error if the specified EntityType is not found.
|
|
436
|
-
@return The EntityType. ComplexType or 'null' if not not found.
|
|
437
|
-
**/
|
|
438
|
-
getAsComplexType(typeName, okIfNotFound = false) {
|
|
439
|
-
const st = this.getStructuralType(typeName, okIfNotFound);
|
|
440
|
-
if (st instanceof ComplexType) {
|
|
441
|
-
return st;
|
|
442
|
-
}
|
|
443
|
-
else if (okIfNotFound) {
|
|
444
|
-
return null;
|
|
445
|
-
}
|
|
446
|
-
else {
|
|
447
|
-
let msg = core.formatString("Unable to locate an 'ComplexType' by the name: '%1'. Be sure to execute a query or call fetchMetadata first.", typeName);
|
|
448
|
-
throw new Error(msg);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
/**
|
|
452
|
-
Returns an [[EntityType]] or a [[ComplexType]] given its name.
|
|
453
|
-
@deprecated Replaced by getStructuralType but ... it is probably more usefull to call either getAsEntityType or getAsComplexType instead
|
|
454
|
-
@param typeName - Either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
|
|
455
|
-
that same short name an exception will be thrown.
|
|
456
|
-
@param okIfNotFound - (default=false) Whether to throw an error if the specified EntityType is not found.
|
|
457
|
-
@return The EntityType. ComplexType or 'null' if not not found.
|
|
458
|
-
**/
|
|
459
|
-
getEntityType(typeName, okIfNotFound = false) {
|
|
460
|
-
return this.getStructuralType(typeName, okIfNotFound);
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
Returns an [[EntityType]] or a [[ComplexType]] given its name.
|
|
464
|
-
> // assume em1 is a preexisting EntityManager
|
|
465
|
-
> let odType = em1.metadataStore.getStructuralType("OrderDetail");
|
|
466
|
-
|
|
467
|
-
or to throw an error if the type is not found
|
|
468
|
-
> let badType = em1.metadataStore.getStructuralType("Foo", false);
|
|
469
|
-
> // badType will not get set and an exception will be thrown.
|
|
470
|
-
@deprecated Preferably use either getAsEntityType or getAsComplexType. Get
|
|
471
|
-
@param typeName - Either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
|
|
472
|
-
that same short name an exception will be thrown.
|
|
473
|
-
@param okIfNotFound - (default=false) Whether to throw an error if the specified EntityType is not found.
|
|
474
|
-
@return The EntityType. ComplexType or 'null' if not not found.
|
|
475
|
-
**/
|
|
476
|
-
getStructuralType(typeName, okIfNotFound = false) {
|
|
477
|
-
assertParam(typeName, "typeName").isString().check();
|
|
478
|
-
assertParam(okIfNotFound, "okIfNotFound").isBoolean().isOptional().check(false);
|
|
479
|
-
return this._getStructuralType(typeName, okIfNotFound);
|
|
480
|
-
}
|
|
481
|
-
/** @hidden @internal */
|
|
482
|
-
_getStructuralType(typeName, okIfNotFound = false) {
|
|
483
|
-
let qualTypeName = getQualifiedTypeName(this, typeName, false);
|
|
484
|
-
let type = this._structuralTypeMap[qualTypeName];
|
|
485
|
-
if (!type) {
|
|
486
|
-
if (okIfNotFound)
|
|
487
|
-
return null;
|
|
488
|
-
let msg = core.formatString("Unable to locate a 'Type' by the name: '%1'. Be sure to execute a query or call fetchMetadata first.", typeName);
|
|
489
|
-
throw new Error(msg);
|
|
490
|
-
}
|
|
491
|
-
return type;
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
Returns an array containing all of the [[EntityType]]s or [[ComplexType]]s in this MetadataStore.
|
|
495
|
-
> // assume em1 is a preexisting EntityManager
|
|
496
|
-
> let allTypes = em1.metadataStore.getEntityTypes();
|
|
497
|
-
**/
|
|
498
|
-
getEntityTypes() {
|
|
499
|
-
return getTypesFromMap(this._structuralTypeMap);
|
|
500
|
-
}
|
|
501
|
-
getIncompleteNavigationProperties() {
|
|
502
|
-
return core.objectMap(this._incompleteTypeMap, function (key, value) {
|
|
503
|
-
return value;
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
/**
|
|
507
|
-
Returns a fully qualified entityTypeName for a specified resource name. The reverse of this operation
|
|
508
|
-
can be obtained via the [[EntityType.defaultResourceName]] property
|
|
509
|
-
**/
|
|
510
|
-
getEntityTypeNameForResourceName(resourceName) {
|
|
511
|
-
assertParam(resourceName, "resourceName").isString().check();
|
|
512
|
-
return this._resourceEntityTypeMap[resourceName];
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
Associates a resourceName with an entityType.
|
|
516
|
-
|
|
517
|
-
This method is only needed in those cases where multiple resources return the same
|
|
518
|
-
entityType. In this case Metadata discovery will only determine a single resource name for
|
|
519
|
-
each entityType.
|
|
520
|
-
@param resourceName - The resource name
|
|
521
|
-
@param entityTypeOrName - If passing a string either the fully qualified name or a short name may be used. If a short name is specified and multiple types share
|
|
522
|
-
that same short name an exception will be thrown. If the entityType has not yet been discovered then a fully qualified name must be used.
|
|
523
|
-
**/
|
|
524
|
-
setEntityTypeForResourceName(resourceName, entityTypeOrName) {
|
|
525
|
-
assertParam(resourceName, "resourceName").isString().check();
|
|
526
|
-
assertParam(entityTypeOrName, "entityTypeOrName").isInstanceOf(EntityType).or().isString().check();
|
|
527
|
-
let entityTypeName;
|
|
528
|
-
if (entityTypeOrName instanceof EntityType) {
|
|
529
|
-
entityTypeName = entityTypeOrName.name;
|
|
530
|
-
}
|
|
531
|
-
else {
|
|
532
|
-
entityTypeName = getQualifiedTypeName(this, entityTypeOrName, true);
|
|
533
|
-
}
|
|
534
|
-
this._resourceEntityTypeMap[resourceName] = entityTypeName;
|
|
535
|
-
let entityType = this._getStructuralType(entityTypeName, true);
|
|
536
|
-
if (entityType && entityType instanceof EntityType && !entityType.defaultResourceName) {
|
|
537
|
-
entityType.defaultResourceName = resourceName;
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
/** __Dev Only__ - for use when creating a new MetadataParserAdapter */
|
|
541
|
-
static parseTypeName(entityTypeName) {
|
|
542
|
-
// TODO: removed
|
|
543
|
-
// if (!entityTypeName) {
|
|
544
|
-
// return null;
|
|
545
|
-
// }
|
|
546
|
-
let typeParts = entityTypeName.split(":#");
|
|
547
|
-
if (typeParts.length > 1) {
|
|
548
|
-
return MetadataStore.makeTypeHash(typeParts[0], typeParts[1]);
|
|
549
|
-
}
|
|
550
|
-
if (core.stringStartsWith(entityTypeName, MetadataStore.ANONTYPE_PREFIX)) {
|
|
551
|
-
let typeHash = MetadataStore.makeTypeHash(entityTypeName);
|
|
552
|
-
typeHash.isAnonymous = true;
|
|
553
|
-
return typeHash;
|
|
554
|
-
}
|
|
555
|
-
let entityTypeNameNoAssembly = entityTypeName.split(",")[0];
|
|
556
|
-
typeParts = entityTypeNameNoAssembly.split(".");
|
|
557
|
-
if (typeParts.length > 1) {
|
|
558
|
-
let shortName = typeParts[typeParts.length - 1];
|
|
559
|
-
let namespaceParts = typeParts.slice(0, typeParts.length - 1);
|
|
560
|
-
let ns = namespaceParts.join(".");
|
|
561
|
-
return MetadataStore.makeTypeHash(shortName, ns);
|
|
562
|
-
}
|
|
563
|
-
else {
|
|
564
|
-
return MetadataStore.makeTypeHash(entityTypeName);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
/** __Dev Only__ - for use when creating a new MetadataParserAdapter */
|
|
568
|
-
static makeTypeHash(shortName, ns) {
|
|
569
|
-
return {
|
|
570
|
-
shortTypeName: shortName,
|
|
571
|
-
namespace: ns,
|
|
572
|
-
typeName: qualifyTypeName(shortName, ns)
|
|
573
|
-
};
|
|
574
|
-
}
|
|
575
|
-
// protected methods
|
|
576
|
-
/** @hidden @internal */
|
|
577
|
-
_checkEntityType(entity) {
|
|
578
|
-
if (entity.entityType)
|
|
579
|
-
return;
|
|
580
|
-
let typeName = entity.prototype._$typeName;
|
|
581
|
-
if (!typeName) {
|
|
582
|
-
throw new Error("This entity has not been registered. See the MetadataStore.registerEntityTypeCtor method");
|
|
583
|
-
}
|
|
584
|
-
// we know that it is an EntityType ( as opposed to a ComplexType)
|
|
585
|
-
let entityType = this._getStructuralType(typeName);
|
|
586
|
-
if (entityType) {
|
|
587
|
-
entity.entityType = entityType;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
/** @hidden @internal */
|
|
592
|
-
MetadataStore.__id = 0;
|
|
593
|
-
/** @hidden @internal */
|
|
594
|
-
MetadataStore.ANONTYPE_PREFIX = "_IB_";
|
|
595
|
-
/** The version of any MetadataStores created by this class */
|
|
596
|
-
MetadataStore.metadataVersion = '1.0.5';
|
|
597
|
-
// needs to be made avail to dataService.xxx files
|
|
598
|
-
MetadataStore.normalizeTypeName = core.memoize(function (rawTypeName) {
|
|
599
|
-
return rawTypeName && MetadataStore.parseTypeName(rawTypeName).typeName;
|
|
600
|
-
});
|
|
601
|
-
MetadataStore.prototype._$typeName = "MetadataStore";
|
|
602
|
-
BreezeEvent.bubbleEvent(MetadataStore.prototype);
|
|
603
|
-
function getTypesFromMap(typeMap) {
|
|
604
|
-
let types = [];
|
|
605
|
-
for (let key in typeMap) {
|
|
606
|
-
let value = typeMap[key];
|
|
607
|
-
// skip 'shortName' entries
|
|
608
|
-
if (key === value.name) {
|
|
609
|
-
types.push(typeMap[key]);
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
return types;
|
|
613
|
-
}
|
|
614
|
-
function structuralTypeFromJson(metadataStore, json, allowMerge) {
|
|
615
|
-
let typeName = qualifyTypeName(json.shortName, json.namespace);
|
|
616
|
-
let stype = metadataStore._getStructuralType(typeName, true);
|
|
617
|
-
if (stype) {
|
|
618
|
-
if (allowMerge) {
|
|
619
|
-
return mergeStructuralType(stype, json);
|
|
620
|
-
}
|
|
621
|
-
else {
|
|
622
|
-
// allow it but don't replace anything.
|
|
623
|
-
return stype;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
let config = {
|
|
627
|
-
shortName: json.shortName,
|
|
628
|
-
namespace: json.namespace,
|
|
629
|
-
isAbstract: json.isAbstract,
|
|
630
|
-
autoGeneratedKeyType: AutoGeneratedKeyType.fromName(json.autoGeneratedKeyType),
|
|
631
|
-
defaultResourceName: json.defaultResourceName,
|
|
632
|
-
custom: json.custom
|
|
633
|
-
};
|
|
634
|
-
stype = json.isComplexType ? new ComplexType(config) : new EntityType(config);
|
|
635
|
-
// baseType may not have been imported yet so we need to defer handling this type until later.
|
|
636
|
-
if (json.baseTypeName && stype instanceof EntityType) {
|
|
637
|
-
stype.baseTypeName = json.baseTypeName;
|
|
638
|
-
let baseEntityType = metadataStore._getStructuralType(json.baseTypeName, true);
|
|
639
|
-
if (baseEntityType) {
|
|
640
|
-
completeStructuralTypeFromJson(metadataStore, json, stype);
|
|
641
|
-
}
|
|
642
|
-
else {
|
|
643
|
-
core.getArray(metadataStore._deferredTypes, json.baseTypeName).push({ json: json, stype: stype });
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
else {
|
|
647
|
-
completeStructuralTypeFromJson(metadataStore, json, stype);
|
|
648
|
-
}
|
|
649
|
-
// stype may or may not have been added to the metadataStore at this point.
|
|
650
|
-
return stype;
|
|
651
|
-
}
|
|
652
|
-
function mergeStructuralType(stype, json) {
|
|
653
|
-
if (json.custom) {
|
|
654
|
-
stype.custom = json.custom;
|
|
655
|
-
}
|
|
656
|
-
mergeProps(stype, json.dataProperties);
|
|
657
|
-
mergeProps(stype, json.navigationProperties);
|
|
658
|
-
return stype;
|
|
659
|
-
}
|
|
660
|
-
function mergeProps(stype, jsonProps) {
|
|
661
|
-
if (!jsonProps)
|
|
662
|
-
return;
|
|
663
|
-
jsonProps.forEach((jsonProp) => {
|
|
664
|
-
let propName = jsonProp.name;
|
|
665
|
-
if (!propName) {
|
|
666
|
-
if (jsonProp.nameOnServer) {
|
|
667
|
-
propName = stype.metadataStore.namingConvention.serverPropertyNameToClient(jsonProp.nameOnServer, {});
|
|
668
|
-
}
|
|
669
|
-
else {
|
|
670
|
-
// backslash-quote works around compiler bug
|
|
671
|
-
const msg = "Unable to complete \'importMetadata\' - cannot locate a \'name\' or \'nameOnServer\' for one of the imported property nodes";
|
|
672
|
-
throw new Error(msg);
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
if (jsonProp.custom) {
|
|
676
|
-
let prop = stype.getProperty(propName, true);
|
|
677
|
-
prop.custom = jsonProp.custom;
|
|
678
|
-
}
|
|
679
|
-
});
|
|
680
|
-
}
|
|
681
|
-
function completeStructuralTypeFromJson(metadataStore, json, stype) {
|
|
682
|
-
// validators from baseType work because validation walks thru base types
|
|
683
|
-
// so no need to copy down.
|
|
684
|
-
if (json.validators) {
|
|
685
|
-
stype.validators = json.validators.map(Validator.fromJSON);
|
|
686
|
-
}
|
|
687
|
-
json.dataProperties.forEach(function (dp) {
|
|
688
|
-
stype._addPropertyCore(DataProperty.fromJSON(dp));
|
|
689
|
-
});
|
|
690
|
-
let isEntityType = !json.isComplexType;
|
|
691
|
-
if (isEntityType) {
|
|
692
|
-
//noinspection JSHint
|
|
693
|
-
json.navigationProperties && json.navigationProperties.forEach(function (np) {
|
|
694
|
-
stype._addPropertyCore(NavigationProperty.fromJSON(np));
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
metadataStore.addEntityType(stype);
|
|
698
|
-
let deferredTypes = metadataStore._deferredTypes;
|
|
699
|
-
let deferrals = deferredTypes[stype.name];
|
|
700
|
-
if (deferrals) {
|
|
701
|
-
deferrals.forEach(function (d) {
|
|
702
|
-
completeStructuralTypeFromJson(metadataStore, d.json, d.stype);
|
|
703
|
-
});
|
|
704
|
-
delete deferredTypes[stype.name];
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
function getQualifiedTypeName(metadataStore, structTypeName, throwIfNotFound) {
|
|
708
|
-
if (isQualifiedTypeName(structTypeName))
|
|
709
|
-
return structTypeName;
|
|
710
|
-
let result = metadataStore._shortNameMap[structTypeName];
|
|
711
|
-
if (!result && throwIfNotFound) {
|
|
712
|
-
throw new Error("Unable to locate 'entityTypeName' of: " + structTypeName);
|
|
713
|
-
}
|
|
714
|
-
return result;
|
|
715
|
-
}
|
|
716
|
-
/** Container for all of the metadata about a specific type of Entity.
|
|
717
|
-
**/
|
|
718
|
-
export class EntityType {
|
|
719
|
-
/** EntityType constructor
|
|
720
|
-
> let entityType = new EntityType( {
|
|
721
|
-
> shortName: "person",
|
|
722
|
-
> namespace: "myAppNamespace"
|
|
723
|
-
> });
|
|
724
|
-
@param config - Configuration settings or a MetadataStore. If this parameter is just a MetadataStore
|
|
725
|
-
then what will be created is an 'anonymous' type that will never be communicated to or from the server. It is purely for
|
|
726
|
-
client side use and will be given an automatically generated name. Normally, however, you will use a configuration object.
|
|
727
|
-
**/
|
|
728
|
-
constructor(config) {
|
|
729
|
-
/** Always false for an EntityType. **/
|
|
730
|
-
this.isComplexType = false;
|
|
731
|
-
/**
|
|
732
|
-
@deprecated Use [[getCtor]] instead.
|
|
733
|
-
*/
|
|
734
|
-
this.getEntityCtor = this.getCtor;
|
|
735
|
-
if (arguments.length > 1) {
|
|
736
|
-
throw new Error("The EntityType ctor has a single argument that is either a 'MetadataStore' or a configuration object.");
|
|
737
|
-
}
|
|
738
|
-
// let etConfig = <EntityTypeConfig> <any> undefined;
|
|
739
|
-
let etConfig = undefined;
|
|
740
|
-
if (config._$typeName === "MetadataStore") {
|
|
741
|
-
this.metadataStore = config;
|
|
742
|
-
this.shortName = "Anon_" + (++EntityType.__nextAnonIx);
|
|
743
|
-
this.namespace = "";
|
|
744
|
-
this.isAnonymous = true;
|
|
745
|
-
// etConfig = undefined;
|
|
746
|
-
}
|
|
747
|
-
else {
|
|
748
|
-
etConfig = config;
|
|
749
|
-
assertConfig(config)
|
|
750
|
-
.whereParam("shortName").isNonEmptyString()
|
|
751
|
-
.whereParam("namespace").isString().isOptional().withDefault("")
|
|
752
|
-
.whereParam("baseTypeName").isString().isOptional()
|
|
753
|
-
.whereParam("isAbstract").isBoolean().isOptional().withDefault(false)
|
|
754
|
-
.whereParam("autoGeneratedKeyType").isEnumOf(AutoGeneratedKeyType).isOptional().withDefault(AutoGeneratedKeyType.None)
|
|
755
|
-
.whereParam("defaultResourceName").isNonEmptyString().isOptional().withDefault(null)
|
|
756
|
-
.whereParam("dataProperties").isOptional()
|
|
757
|
-
.whereParam("navigationProperties").isOptional()
|
|
758
|
-
.whereParam("serializerFn").isOptional().isFunction()
|
|
759
|
-
.whereParam("custom").isOptional()
|
|
760
|
-
.applyAll(this);
|
|
761
|
-
}
|
|
762
|
-
this.name = qualifyTypeName(this.shortName, this.namespace);
|
|
763
|
-
// the defaultResourceName may also be set up either via metadata lookup or first query or via the 'setProperties' method
|
|
764
|
-
this.dataProperties = [];
|
|
765
|
-
this.navigationProperties = [];
|
|
766
|
-
this.complexProperties = [];
|
|
767
|
-
this.keyProperties = [];
|
|
768
|
-
this.foreignKeyProperties = [];
|
|
769
|
-
this.inverseForeignKeyProperties = [];
|
|
770
|
-
this.concurrencyProperties = [];
|
|
771
|
-
this.unmappedProperties = []; // will be updated later.
|
|
772
|
-
this.validators = [];
|
|
773
|
-
this.warnings = [];
|
|
774
|
-
this._mappedPropertiesCount = 0;
|
|
775
|
-
this.subtypes = [];
|
|
776
|
-
// now process any data/nav props
|
|
777
|
-
if (etConfig && etConfig.dataProperties) {
|
|
778
|
-
addProperties(this, etConfig.dataProperties, DataProperty);
|
|
779
|
-
}
|
|
780
|
-
if (etConfig && etConfig.navigationProperties) {
|
|
781
|
-
addProperties(this, etConfig.navigationProperties, NavigationProperty);
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
/**
|
|
785
|
-
General purpose property set method
|
|
786
|
-
> // assume em1 is an EntityManager containing a number of existing entities.
|
|
787
|
-
> let custType = em1.metadataStore.getEntityType("Customer");
|
|
788
|
-
> custType.setProperties( {
|
|
789
|
-
> autoGeneratedKeyType: AutoGeneratedKeyType.Identity;
|
|
790
|
-
> defaultResourceName: "CustomersAndIncludedOrders"
|
|
791
|
-
> )};
|
|
792
|
-
@param config - a configuration object
|
|
793
|
-
**/
|
|
794
|
-
setProperties(config) {
|
|
795
|
-
assertConfig(config)
|
|
796
|
-
.whereParam("autoGeneratedKeyType").isEnumOf(AutoGeneratedKeyType).isOptional()
|
|
797
|
-
.whereParam("defaultResourceName").isString().isOptional()
|
|
798
|
-
.whereParam("serializerFn").isFunction().isOptional()
|
|
799
|
-
.whereParam("custom").isOptional()
|
|
800
|
-
.applyAll(this);
|
|
801
|
-
if (config.defaultResourceName) {
|
|
802
|
-
this.defaultResourceName = config.defaultResourceName;
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
/**
|
|
806
|
-
Returns whether this type is a subtype of a specified type.
|
|
807
|
-
**/
|
|
808
|
-
isSubtypeOf(entityType) {
|
|
809
|
-
assertParam(entityType, "entityType").isInstanceOf(EntityType).check();
|
|
810
|
-
let baseType = this;
|
|
811
|
-
do {
|
|
812
|
-
if (baseType === entityType)
|
|
813
|
-
return true;
|
|
814
|
-
baseType = baseType.baseEntityType;
|
|
815
|
-
} while (baseType);
|
|
816
|
-
return false;
|
|
817
|
-
}
|
|
818
|
-
/**
|
|
819
|
-
Returns an array containing this type and any/all subtypes of this type down thru the hierarchy.
|
|
820
|
-
**/
|
|
821
|
-
getSelfAndSubtypes() {
|
|
822
|
-
let result = [this];
|
|
823
|
-
this.subtypes.forEach(function (st) {
|
|
824
|
-
let subtypes = st.getSelfAndSubtypes();
|
|
825
|
-
result.push.apply(result, subtypes);
|
|
826
|
-
});
|
|
827
|
-
return result;
|
|
828
|
-
}
|
|
829
|
-
getAllValidators() {
|
|
830
|
-
let result = this.validators.slice(0);
|
|
831
|
-
let bt = this.baseEntityType;
|
|
832
|
-
while (bt) {
|
|
833
|
-
result.push.apply(result, bt.validators);
|
|
834
|
-
bt = bt.baseEntityType;
|
|
835
|
-
}
|
|
836
|
-
return result;
|
|
837
|
-
}
|
|
838
|
-
/**
|
|
839
|
-
Adds a [[DataProperty]] or a [[NavigationProperty]] to this EntityType.
|
|
840
|
-
> // assume myEntityType is a newly constructed EntityType.
|
|
841
|
-
> myEntityType.addProperty(dataProperty1);
|
|
842
|
-
> myEntityType.addProperty(dataProperty2);
|
|
843
|
-
> myEntityType.addProperty(navigationProperty1);
|
|
844
|
-
**/
|
|
845
|
-
addProperty(property) {
|
|
846
|
-
assertParam(property, "property").isInstanceOf(DataProperty).or().isInstanceOf(NavigationProperty).check();
|
|
847
|
-
// true is 2nd arg to force resolve of any navigation properties.
|
|
848
|
-
let newprop = this._addPropertyCore(property, true);
|
|
849
|
-
if (this.subtypes && this.subtypes.length) {
|
|
850
|
-
let stype = this;
|
|
851
|
-
stype.getSelfAndSubtypes().forEach(function (st) {
|
|
852
|
-
if (st !== stype) {
|
|
853
|
-
if (property.isNavigationProperty) {
|
|
854
|
-
st._addPropertyCore(new NavigationProperty(property), true);
|
|
855
|
-
}
|
|
856
|
-
else {
|
|
857
|
-
st._addPropertyCore(new DataProperty(property), true);
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
});
|
|
861
|
-
}
|
|
862
|
-
return newprop;
|
|
863
|
-
}
|
|
864
|
-
/** @hidden @internal */
|
|
865
|
-
_updateFromBase(baseEntityType) {
|
|
866
|
-
this.baseEntityType = baseEntityType;
|
|
867
|
-
if (this.autoGeneratedKeyType === AutoGeneratedKeyType.None) {
|
|
868
|
-
this.autoGeneratedKeyType = baseEntityType.autoGeneratedKeyType;
|
|
869
|
-
}
|
|
870
|
-
baseEntityType.dataProperties.forEach((dp) => {
|
|
871
|
-
let newDp = new DataProperty(dp);
|
|
872
|
-
// don't need to copy validators becaue we will walk the hierarchy to find them
|
|
873
|
-
newDp.validators = [];
|
|
874
|
-
newDp.baseProperty = dp;
|
|
875
|
-
this._addPropertyCore(newDp);
|
|
876
|
-
}, this);
|
|
877
|
-
baseEntityType.navigationProperties.forEach((np) => {
|
|
878
|
-
let newNp = new NavigationProperty(np);
|
|
879
|
-
// don't need to copy validators becaue we will walk the hierarchy to find them
|
|
880
|
-
newNp.validators = [];
|
|
881
|
-
newNp.baseProperty = np;
|
|
882
|
-
this._addPropertyCore(newNp);
|
|
883
|
-
}, this);
|
|
884
|
-
baseEntityType.subtypes.push(this);
|
|
885
|
-
}
|
|
886
|
-
/** @hidden @internal */
|
|
887
|
-
_addPropertyCore(property, shouldResolve = false) {
|
|
888
|
-
if (this.isFrozen) {
|
|
889
|
-
throw new Error("The '" + this.name + "' EntityType/ComplexType has been frozen. You can only add properties to an EntityType/ComplexType before any instances of that type have been created and attached to an entityManager.");
|
|
890
|
-
}
|
|
891
|
-
let parentType = property.parentType;
|
|
892
|
-
if (parentType) {
|
|
893
|
-
if (parentType !== this) {
|
|
894
|
-
throw new Error("This property: " + property.name + " has already been added to " + property.parentType.name);
|
|
895
|
-
}
|
|
896
|
-
else {
|
|
897
|
-
// adding the same property more than once to the same entityType is just ignored.
|
|
898
|
-
return;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
property.parentType = this;
|
|
902
|
-
let ms = this.metadataStore;
|
|
903
|
-
// if (property.isDataProperty) { // modified because doesn't act as a type guard
|
|
904
|
-
if (property instanceof DataProperty) {
|
|
905
|
-
this._addDataProperty(property);
|
|
906
|
-
}
|
|
907
|
-
else {
|
|
908
|
-
this._addNavigationProperty(property);
|
|
909
|
-
// metadataStore can be undefined if this entityType has not yet been added to a MetadataStore.
|
|
910
|
-
if (shouldResolve && ms) {
|
|
911
|
-
tryResolveNp(property, ms);
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
// unmapped properties can be added AFTER entityType has already resolved all property names.
|
|
915
|
-
if (ms && !(property.name && property.nameOnServer)) {
|
|
916
|
-
updateClientServerNames(ms.namingConvention, property, "name");
|
|
917
|
-
}
|
|
918
|
-
// props can be added after entity prototype has already been wrapped.
|
|
919
|
-
if (ms && this._extra) {
|
|
920
|
-
if (this._extra.alreadyWrappedProps) {
|
|
921
|
-
let proto = this._ctor.prototype;
|
|
922
|
-
config.interfaceRegistry.modelLibrary.getDefaultInstance().initializeEntityPrototype(proto);
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
/**
|
|
927
|
-
Create a new entity of this type.
|
|
928
|
-
> // assume em1 is an EntityManager containing a number of existing entities.
|
|
929
|
-
> let custType = em1.metadataStore.getAsEntityType("Customer");
|
|
930
|
-
> let cust1 = custType.createEntity();
|
|
931
|
-
> em1.addEntity(cust1);
|
|
932
|
-
@param initialValues- Configuration object of the properties to set immediately after creation.
|
|
933
|
-
@return The new entity.
|
|
934
|
-
**/
|
|
935
|
-
createEntity(initialValues) {
|
|
936
|
-
// ignore the _$eref once the entity is attached to an entityManager.
|
|
937
|
-
if (initialValues && initialValues._$eref && !initialValues._$eref.entityAspect.entityManager)
|
|
938
|
-
return initialValues._$eref;
|
|
939
|
-
let instance = this._createInstanceCore();
|
|
940
|
-
if (initialValues) {
|
|
941
|
-
// only assign an _eref if the object is fully "keyed"
|
|
942
|
-
if (this.keyProperties.every(function (kp) {
|
|
943
|
-
return initialValues[kp.name] != null;
|
|
944
|
-
})) {
|
|
945
|
-
initialValues._$eref = instance;
|
|
946
|
-
}
|
|
947
|
-
this._updateTargetFromRaw(instance, initialValues, getRawValueFromConfig);
|
|
948
|
-
this.navigationProperties.forEach(function (np) {
|
|
949
|
-
let relatedEntity;
|
|
950
|
-
let val = initialValues[np.name];
|
|
951
|
-
if (val != undefined) {
|
|
952
|
-
let navEntityType = np.entityType;
|
|
953
|
-
if (np.isScalar) {
|
|
954
|
-
relatedEntity = val.entityAspect ? val : navEntityType.createEntity(val);
|
|
955
|
-
instance.setProperty(np.name, relatedEntity);
|
|
956
|
-
}
|
|
957
|
-
else {
|
|
958
|
-
let relatedEntities = instance.getProperty(np.name);
|
|
959
|
-
val.forEach((v) => {
|
|
960
|
-
relatedEntity = v.entityAspect ? v : navEntityType.createEntity(v);
|
|
961
|
-
relatedEntities.push(relatedEntity);
|
|
962
|
-
});
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
});
|
|
966
|
-
}
|
|
967
|
-
this._initializeInstance(instance);
|
|
968
|
-
return instance;
|
|
969
|
-
}
|
|
970
|
-
/** @hidden @internal */
|
|
971
|
-
_createInstanceCore() {
|
|
972
|
-
let aCtor = this.getCtor();
|
|
973
|
-
let instance = new aCtor();
|
|
974
|
-
new EntityAspect(instance);
|
|
975
|
-
return instance;
|
|
976
|
-
}
|
|
977
|
-
/** @hidden @internal */
|
|
978
|
-
_initializeInstance(instance) {
|
|
979
|
-
if (this.baseEntityType) {
|
|
980
|
-
this.baseEntityType._initializeInstance(instance);
|
|
981
|
-
}
|
|
982
|
-
let initFn = this.initFn;
|
|
983
|
-
if (initFn) {
|
|
984
|
-
let fn = (typeof initFn === "string") ? instance[initFn] : initFn;
|
|
985
|
-
fn(instance);
|
|
986
|
-
}
|
|
987
|
-
this.complexProperties && this.complexProperties.forEach(function (cp) {
|
|
988
|
-
let complexType = cp.dataType;
|
|
989
|
-
let ctInstance = instance.getProperty(cp.name);
|
|
990
|
-
if (Array.isArray(ctInstance)) {
|
|
991
|
-
ctInstance.forEach((ctInst) => {
|
|
992
|
-
complexType._initializeInstance(ctInst);
|
|
993
|
-
});
|
|
994
|
-
}
|
|
995
|
-
else {
|
|
996
|
-
complexType._initializeInstance(ctInstance);
|
|
997
|
-
}
|
|
998
|
-
});
|
|
999
|
-
// not needed for complexObjects
|
|
1000
|
-
if (instance.entityAspect) {
|
|
1001
|
-
instance.entityAspect._initialized = true;
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
/**
|
|
1005
|
-
Returns the constructor for this EntityType.
|
|
1006
|
-
@param forceRefresh - Whether to ignore any cached version of this constructor. (default == false)
|
|
1007
|
-
@return The constructor for this EntityType.
|
|
1008
|
-
**/
|
|
1009
|
-
getCtor(forceRefresh = false) {
|
|
1010
|
-
if (this._ctor && !forceRefresh)
|
|
1011
|
-
return this._ctor;
|
|
1012
|
-
let ctorRegistry = this.metadataStore._ctorRegistry;
|
|
1013
|
-
let r = ctorRegistry[this.name] || ctorRegistry[this.shortName] || {};
|
|
1014
|
-
let aCtor = r.ctor || this._ctor;
|
|
1015
|
-
let ctorType = aCtor && aCtor.prototype && (aCtor.prototype.entityType || aCtor.prototype.complexType);
|
|
1016
|
-
if (ctorType && ctorType.metadataStore !== this.metadataStore) {
|
|
1017
|
-
// We can't risk a mismatch between the ctor and the type info in a specific metadatastore
|
|
1018
|
-
// because modelLibraries rely on type info to intercept ctor properties
|
|
1019
|
-
throw new Error("Cannot register the same constructor for " + this.name + " in different metadata stores. Please define a separate constructor for each metadata store.");
|
|
1020
|
-
}
|
|
1021
|
-
if (r.ctor && forceRefresh) {
|
|
1022
|
-
this._extra = undefined;
|
|
1023
|
-
}
|
|
1024
|
-
if (!aCtor) {
|
|
1025
|
-
let createCtor = config.interfaceRegistry.modelLibrary.getDefaultInstance().createCtor;
|
|
1026
|
-
aCtor = createCtor ? createCtor(this) : createEmptyCtor(this);
|
|
1027
|
-
}
|
|
1028
|
-
this.initFn = r.initFn;
|
|
1029
|
-
this.noTrackingFn = r.noTrackingFn;
|
|
1030
|
-
aCtor.prototype._$typeName = this.name;
|
|
1031
|
-
this._setCtor(aCtor);
|
|
1032
|
-
return aCtor;
|
|
1033
|
-
}
|
|
1034
|
-
/** @hidden @internal */
|
|
1035
|
-
// May make public later.
|
|
1036
|
-
_setCtor(aCtor, interceptor) {
|
|
1037
|
-
let instanceProto = aCtor.prototype;
|
|
1038
|
-
// place for extra breeze related data
|
|
1039
|
-
this._extra = this._extra || {};
|
|
1040
|
-
let instance = new aCtor();
|
|
1041
|
-
calcUnmappedProperties(this, instance);
|
|
1042
|
-
if (this._$typeName === "EntityType") {
|
|
1043
|
-
// insure that all of the properties are on the 'template' instance before watching the class.
|
|
1044
|
-
instanceProto.entityType = this;
|
|
1045
|
-
}
|
|
1046
|
-
else {
|
|
1047
|
-
instanceProto.complexType = this;
|
|
1048
|
-
}
|
|
1049
|
-
// defaultPropertyInterceptor is a 'global' (but internal to breeze) function;
|
|
1050
|
-
instanceProto._$interceptor = interceptor || defaultPropertyInterceptor;
|
|
1051
|
-
config.interfaceRegistry.modelLibrary.getDefaultInstance().initializeEntityPrototype(instanceProto);
|
|
1052
|
-
this._ctor = aCtor;
|
|
1053
|
-
}
|
|
1054
|
-
/**
|
|
1055
|
-
Adds either an entity or property level validator to this EntityType.
|
|
1056
|
-
> // assume em1 is an EntityManager containing a number of existing entities.
|
|
1057
|
-
> let custType = em1.metadataStore.getEntityType("Customer");
|
|
1058
|
-
> let countryProp = custType.getProperty("Country");
|
|
1059
|
-
> let valFn = function (v) {
|
|
1060
|
-
> if (v == null) return true;
|
|
1061
|
-
> return (core.stringStartsWith(v, "US"));
|
|
1062
|
-
> };
|
|
1063
|
-
> let countryValidator = new Validator("countryIsUS", valFn,
|
|
1064
|
-
> { displayName: "Country", messageTemplate: "'%displayName%' must start with 'US'" });
|
|
1065
|
-
> custType.addValidator(countryValidator, countryProp);
|
|
1066
|
-
|
|
1067
|
-
This is the same as adding an entity level validator via the 'validators' property of DataProperty or NavigationProperty
|
|
1068
|
-
> countryProp.validators.push(countryValidator);
|
|
1069
|
-
|
|
1070
|
-
Entity level validators can also be added by omitting the 'property' parameter.
|
|
1071
|
-
> custType.addValidator(someEntityLevelValidator);
|
|
1072
|
-
|
|
1073
|
-
or
|
|
1074
|
-
> custType.validators.push(someEntityLevelValidator);
|
|
1075
|
-
@param validator - Validator to add.
|
|
1076
|
-
@param property - Property to add this validator to. If omitted, the validator is assumed to be an
|
|
1077
|
-
entity level validator and is added to the EntityType's 'validators'.
|
|
1078
|
-
**/
|
|
1079
|
-
addValidator(validator, property) {
|
|
1080
|
-
assertParam(validator, "validator").isInstanceOf(Validator).check();
|
|
1081
|
-
assertParam(property, "property").isOptional().isString().or().isEntityProperty().check();
|
|
1082
|
-
if (property != null) {
|
|
1083
|
-
let prop = (typeof property === 'string') ? this.getProperty(property, true) : property;
|
|
1084
|
-
prop.validators.push(validator);
|
|
1085
|
-
}
|
|
1086
|
-
else {
|
|
1087
|
-
this.validators.push(validator);
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
/**
|
|
1091
|
-
Returns all of the properties ( dataProperties and navigationProperties) for this EntityType.
|
|
1092
|
-
> // assume em1 is an EntityManager containing a number of existing entities.
|
|
1093
|
-
> let custType = em1.metadataStore.getEntityType("Customer");
|
|
1094
|
-
> let arrayOfProps = custType.getProperties();
|
|
1095
|
-
@return An array of Data and Navigation properties.
|
|
1096
|
-
**/
|
|
1097
|
-
getProperties() {
|
|
1098
|
-
return this.dataProperties.concat(this.navigationProperties);
|
|
1099
|
-
}
|
|
1100
|
-
/**
|
|
1101
|
-
Returns all of the property names ( for both dataProperties and navigationProperties) for this EntityType.
|
|
1102
|
-
> // assume em1 is an EntityManager containing a number of existing entities.
|
|
1103
|
-
> let custType = em1.metadataStore.getEntityType("Customer");
|
|
1104
|
-
> let arrayOfPropNames = custType.getPropertyNames();
|
|
1105
|
-
**/
|
|
1106
|
-
getPropertyNames() {
|
|
1107
|
-
return this.getProperties().map(core.pluck('name'));
|
|
1108
|
-
}
|
|
1109
|
-
/**
|
|
1110
|
-
Returns a data property with the specified name or null.
|
|
1111
|
-
> // assume em1 is an EntityManager containing a number of existing entities.
|
|
1112
|
-
> let custType = em1.metadataStore.getEntityType("Customer");
|
|
1113
|
-
> let customerNameDataProp = custType.getDataProperty("CustomerName");
|
|
1114
|
-
@return A DataProperty or null if not found.
|
|
1115
|
-
**/
|
|
1116
|
-
getDataProperty(propertyName) {
|
|
1117
|
-
return core.arrayFirst(this.dataProperties, core.propEq('name', propertyName));
|
|
1118
|
-
}
|
|
1119
|
-
/**
|
|
1120
|
-
Returns a navigation property with the specified name or null.
|
|
1121
|
-
> // assume em1 is an EntityManager containing a number of existing entities.
|
|
1122
|
-
> let custType = em1.metadataStore.getEntityType("Customer");
|
|
1123
|
-
> let customerOrdersNavProp = custType.getDataProperty("Orders");
|
|
1124
|
-
@return A NavigationProperty or null if not found.
|
|
1125
|
-
**/
|
|
1126
|
-
getNavigationProperty(propertyName) {
|
|
1127
|
-
return core.arrayFirst(this.navigationProperties, core.propEq('name', propertyName));
|
|
1128
|
-
}
|
|
1129
|
-
/**
|
|
1130
|
-
Returns either a DataProperty or a NavigationProperty with the specified name or null.
|
|
1131
|
-
|
|
1132
|
-
This method also accepts a '.' delimited property path and will return the 'property' at the
|
|
1133
|
-
end of the path.
|
|
1134
|
-
> let custType = em1.metadataStore.getEntityType("Customer");
|
|
1135
|
-
> let companyNameProp = custType.getProperty("CompanyName");
|
|
1136
|
-
|
|
1137
|
-
This method can also walk a property path to return a property
|
|
1138
|
-
> let orderDetailType = em1.metadataStore.getEntityType("OrderDetail");
|
|
1139
|
-
> let companyNameProp2 = orderDetailType.getProperty("Order.Customer.CompanyName");
|
|
1140
|
-
> // companyNameProp === companyNameProp2
|
|
1141
|
-
@param [throwIfNotFound=false] {Boolean} Whether to throw an exception if not found.
|
|
1142
|
-
@return A DataProperty or NavigationProperty or null if not found.
|
|
1143
|
-
**/
|
|
1144
|
-
getProperty(propertyPath, throwIfNotFound = false) {
|
|
1145
|
-
let props = this.getPropertiesOnPath(propertyPath, false, throwIfNotFound);
|
|
1146
|
-
return (props && props.length > 0) ? props[props.length - 1] : null;
|
|
1147
|
-
}
|
|
1148
|
-
/** @hidden @internal */
|
|
1149
|
-
// TODO: have this return empty array instead of null and fix consumers.
|
|
1150
|
-
// TODO: think about renaming with '_' prefix.
|
|
1151
|
-
getPropertiesOnPath(propertyPath, useServerName, throwIfNotFound = false) {
|
|
1152
|
-
let propertyNames = (Array.isArray(propertyPath)) ? propertyPath : propertyPath.trim().split('.');
|
|
1153
|
-
let ok = true;
|
|
1154
|
-
let key = useServerName === true ? "nameOnServer" : useServerName === false ? "name" : null;
|
|
1155
|
-
let parentType = this;
|
|
1156
|
-
const getProps = (propName) => {
|
|
1157
|
-
const fn = key === null ? core.propsEq("name", "nameOnServer", propName) : core.propEq(key, propName);
|
|
1158
|
-
let prop = core.arrayFirst(parentType.getProperties(), fn);
|
|
1159
|
-
if (prop) {
|
|
1160
|
-
parentType = (prop instanceof NavigationProperty) ? prop.entityType : prop.dataType;
|
|
1161
|
-
// parentType = prop.isNavigationProperty ? prop.entityType : prop.dataType;
|
|
1162
|
-
}
|
|
1163
|
-
else if (throwIfNotFound) {
|
|
1164
|
-
throw new Error("unable to locate property: " + propName + " on entityType: " + parentType.name);
|
|
1165
|
-
}
|
|
1166
|
-
else {
|
|
1167
|
-
ok = false;
|
|
1168
|
-
}
|
|
1169
|
-
return prop;
|
|
1170
|
-
};
|
|
1171
|
-
let props = propertyNames.map(getProps);
|
|
1172
|
-
return ok ? props : null;
|
|
1173
|
-
}
|
|
1174
|
-
/** For use in pluggable adapters. */
|
|
1175
|
-
// TODO: document use
|
|
1176
|
-
clientPropertyPathToServer(propertyPath, delimiter = '.') {
|
|
1177
|
-
let propNames;
|
|
1178
|
-
if (this.isAnonymous) {
|
|
1179
|
-
let fn = this.metadataStore.namingConvention.clientPropertyNameToServer;
|
|
1180
|
-
propNames = propertyPath.split(".").map(function (propName) {
|
|
1181
|
-
return fn(propName);
|
|
1182
|
-
});
|
|
1183
|
-
}
|
|
1184
|
-
else {
|
|
1185
|
-
let props = this.getPropertiesOnPath(propertyPath, false, true);
|
|
1186
|
-
propNames = props.map((prop) => prop.nameOnServer);
|
|
1187
|
-
}
|
|
1188
|
-
return propNames.join(delimiter);
|
|
1189
|
-
}
|
|
1190
|
-
/** For use in pluggable adapters. */
|
|
1191
|
-
// TODO: document use
|
|
1192
|
-
getEntityKeyFromRawEntity(rawEntity, rawValueFn) {
|
|
1193
|
-
let keyValues = this.keyProperties.map((dp) => {
|
|
1194
|
-
let val = rawValueFn(rawEntity, dp);
|
|
1195
|
-
return DataType.parseRawValue(val, dp.dataType);
|
|
1196
|
-
});
|
|
1197
|
-
return new EntityKey(this, keyValues);
|
|
1198
|
-
}
|
|
1199
|
-
/** @hidden @internal */
|
|
1200
|
-
_updateTargetFromRaw(target, raw, rawValueFn) {
|
|
1201
|
-
// called recursively for complex properties
|
|
1202
|
-
this.dataProperties.forEach((dp) => {
|
|
1203
|
-
if (!dp.isSettable)
|
|
1204
|
-
return;
|
|
1205
|
-
let rawVal = rawValueFn(raw, dp);
|
|
1206
|
-
if (rawVal === undefined)
|
|
1207
|
-
return;
|
|
1208
|
-
let dataType = dp.dataType; // this will be a complexType when dp is a complexProperty
|
|
1209
|
-
let oldVal;
|
|
1210
|
-
if (dp.isComplexProperty) {
|
|
1211
|
-
let complexType = dp.dataType;
|
|
1212
|
-
if (rawVal === null)
|
|
1213
|
-
return; // rawVal may be null in nosql dbs where it was never defined for the given row.
|
|
1214
|
-
oldVal = target.getProperty(dp.name);
|
|
1215
|
-
if (dp.isScalar) {
|
|
1216
|
-
complexType._updateTargetFromRaw(oldVal, rawVal, rawValueFn);
|
|
1217
|
-
}
|
|
1218
|
-
else {
|
|
1219
|
-
if (Array.isArray(rawVal)) {
|
|
1220
|
-
let newVal = rawVal.map(function (rawCo) {
|
|
1221
|
-
let newCo = complexType._createInstanceCore(target, dp);
|
|
1222
|
-
complexType._updateTargetFromRaw(newCo, rawCo, rawValueFn);
|
|
1223
|
-
complexType._initializeInstance(newCo);
|
|
1224
|
-
return newCo;
|
|
1225
|
-
});
|
|
1226
|
-
if (!core.arrayEquals(oldVal, newVal, coEquals)) {
|
|
1227
|
-
// clear the old array and push new objects into it.
|
|
1228
|
-
oldVal.length = 0;
|
|
1229
|
-
newVal.forEach(function (nv) {
|
|
1230
|
-
oldVal.push(nv);
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
else {
|
|
1235
|
-
oldVal.length = 0;
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
else {
|
|
1240
|
-
if (dp.isScalar) {
|
|
1241
|
-
let newVal = DataType.parseRawValue(rawVal, dataType);
|
|
1242
|
-
target.setProperty(dp.name, newVal);
|
|
1243
|
-
}
|
|
1244
|
-
else {
|
|
1245
|
-
oldVal = target.getProperty(dp.name);
|
|
1246
|
-
if (Array.isArray(rawVal)) {
|
|
1247
|
-
// need to compare values
|
|
1248
|
-
let newVal = rawVal.map((rv) => {
|
|
1249
|
-
return DataType.parseRawValue(rv, dataType);
|
|
1250
|
-
});
|
|
1251
|
-
if (!core.arrayEquals(oldVal, newVal)) {
|
|
1252
|
-
// clear the old array and push new objects into it.
|
|
1253
|
-
oldVal.length = 0;
|
|
1254
|
-
newVal.forEach(function (nv) {
|
|
1255
|
-
oldVal.push(nv);
|
|
1256
|
-
});
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
else {
|
|
1260
|
-
oldVal.length = 0;
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
});
|
|
1265
|
-
// if merging from an import then raw will have an entityAspect or a complexAspect
|
|
1266
|
-
let rawAspect = raw.entityAspect || raw.complexAspect;
|
|
1267
|
-
if (rawAspect) {
|
|
1268
|
-
let targetAspect = EntityAspect.isEntity(target) ? target.entityAspect : target.complexAspect;
|
|
1269
|
-
if (rawAspect.originalValuesMap) {
|
|
1270
|
-
targetAspect.originalValues = rawAspect.originalValuesMap;
|
|
1271
|
-
}
|
|
1272
|
-
if (rawAspect.extraMetadata) {
|
|
1273
|
-
targetAspect.extraMetadata = rawAspect.extraMetadata;
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
/**
|
|
1278
|
-
Returns a string representation of this EntityType.
|
|
1279
|
-
**/
|
|
1280
|
-
toString() {
|
|
1281
|
-
return this.name;
|
|
1282
|
-
}
|
|
1283
|
-
toJSON() {
|
|
1284
|
-
return core.toJson(this, {
|
|
1285
|
-
shortName: null,
|
|
1286
|
-
namespace: null,
|
|
1287
|
-
baseTypeName: null,
|
|
1288
|
-
isAbstract: false,
|
|
1289
|
-
autoGeneratedKeyType: null,
|
|
1290
|
-
defaultResourceName: null,
|
|
1291
|
-
dataProperties: localPropsOnly,
|
|
1292
|
-
navigationProperties: localPropsOnly,
|
|
1293
|
-
validators: null,
|
|
1294
|
-
custom: null
|
|
1295
|
-
});
|
|
1296
|
-
}
|
|
1297
|
-
/** @hidden @internal */
|
|
1298
|
-
_updateNames(property) {
|
|
1299
|
-
let nc = this.metadataStore.namingConvention;
|
|
1300
|
-
updateClientServerNames(nc, property, "name");
|
|
1301
|
-
if (property.isNavigationProperty) {
|
|
1302
|
-
updateClientServerNames(nc, property, "foreignKeyNames");
|
|
1303
|
-
updateClientServerNames(nc, property, "invForeignKeyNames");
|
|
1304
|
-
// these will get set later via _updateNps
|
|
1305
|
-
// this.inverse
|
|
1306
|
-
// this.entityType
|
|
1307
|
-
// this.relatedDataProperties
|
|
1308
|
-
// dataProperty.relatedNavigationProperty
|
|
1309
|
-
// dataProperty.inverseNavigationProperty
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1312
|
-
/** @hidden @internal */
|
|
1313
|
-
_checkNavProperty(navigationProperty) {
|
|
1314
|
-
// if (navigationProperty.isNavigationProperty) {
|
|
1315
|
-
if (navigationProperty instanceof NavigationProperty) {
|
|
1316
|
-
if (navigationProperty.parentType !== this) {
|
|
1317
|
-
throw new Error(core.formatString("The navigationProperty '%1' is not a property of entity type '%2'", navigationProperty.name, this.name));
|
|
1318
|
-
}
|
|
1319
|
-
return navigationProperty;
|
|
1320
|
-
}
|
|
1321
|
-
if (typeof (navigationProperty) === 'string') {
|
|
1322
|
-
let np = this.getProperty(navigationProperty);
|
|
1323
|
-
// if (np && np.isNavigationProperty) return np;
|
|
1324
|
-
if (np && np instanceof NavigationProperty)
|
|
1325
|
-
return np;
|
|
1326
|
-
}
|
|
1327
|
-
throw new Error("The 'navigationProperty' parameter must either be a NavigationProperty or the name of a NavigationProperty");
|
|
1328
|
-
}
|
|
1329
|
-
/** @hidden @internal */
|
|
1330
|
-
_addDataProperty(dp) {
|
|
1331
|
-
this.dataProperties.push(dp);
|
|
1332
|
-
if (dp.isPartOfKey) {
|
|
1333
|
-
this.keyProperties.push(dp);
|
|
1334
|
-
}
|
|
1335
|
-
if (dp.isComplexProperty) {
|
|
1336
|
-
this.complexProperties.push(dp);
|
|
1337
|
-
}
|
|
1338
|
-
if (dp.concurrencyMode && dp.concurrencyMode !== "None") {
|
|
1339
|
-
this.concurrencyProperties.push(dp);
|
|
1340
|
-
}
|
|
1341
|
-
if (dp.isUnmapped) {
|
|
1342
|
-
this.unmappedProperties.push(dp);
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
/** @hidden @internal */
|
|
1346
|
-
_addNavigationProperty(np) {
|
|
1347
|
-
this.navigationProperties.push(np);
|
|
1348
|
-
if (!isQualifiedTypeName(np.entityTypeName)) {
|
|
1349
|
-
np.entityTypeName = qualifyTypeName(np.entityTypeName, this.namespace);
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
/** @hidden @internal */
|
|
1353
|
-
_updateCps() {
|
|
1354
|
-
let metadataStore = this.metadataStore;
|
|
1355
|
-
let incompleteTypeMap = metadataStore._incompleteComplexTypeMap;
|
|
1356
|
-
this.complexProperties.forEach(function (cp) {
|
|
1357
|
-
if (cp.complexType)
|
|
1358
|
-
return;
|
|
1359
|
-
if (!resolveCp(cp, metadataStore)) {
|
|
1360
|
-
core.getArray(incompleteTypeMap, cp.complexTypeName).push(cp);
|
|
1361
|
-
}
|
|
1362
|
-
});
|
|
1363
|
-
if (this.isComplexType) {
|
|
1364
|
-
(incompleteTypeMap[this.name] || []).forEach(function (cp) {
|
|
1365
|
-
resolveCp(cp, metadataStore);
|
|
1366
|
-
});
|
|
1367
|
-
delete incompleteTypeMap[this.name];
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
/** @hidden @internal */
|
|
1371
|
-
_updateNps() {
|
|
1372
|
-
let metadataStore = this.metadataStore;
|
|
1373
|
-
// resolve all navProps for this entityType
|
|
1374
|
-
this.navigationProperties.forEach(function (np) {
|
|
1375
|
-
tryResolveNp(np, metadataStore);
|
|
1376
|
-
});
|
|
1377
|
-
let incompleteTypeMap = metadataStore._incompleteTypeMap;
|
|
1378
|
-
// next resolve all navProp that point to this entityType.
|
|
1379
|
-
(incompleteTypeMap[this.name] || []).forEach(function (np) {
|
|
1380
|
-
tryResolveNp(np, metadataStore);
|
|
1381
|
-
});
|
|
1382
|
-
// every navProp that pointed to this type should now be resolved
|
|
1383
|
-
delete incompleteTypeMap[this.name];
|
|
1384
|
-
}
|
|
1385
|
-
}
|
|
1386
|
-
/** @hidden @internal */
|
|
1387
|
-
EntityType.__nextAnonIx = 0;
|
|
1388
|
-
/** @hidden @internal */
|
|
1389
|
-
EntityType.qualifyTypeName = qualifyTypeName;
|
|
1390
|
-
EntityType.prototype._$typeName = "EntityType";
|
|
1391
|
-
function getRawValueFromConfig(rawEntity, dp) {
|
|
1392
|
-
// 'true' fork can happen if an initializer contains an actaul instance of an already created complex object.
|
|
1393
|
-
return (rawEntity.entityAspect || rawEntity.complexAspect) ? rawEntity.getProperty(dp.name) : rawEntity[dp.name];
|
|
1394
|
-
}
|
|
1395
|
-
function updateClientServerNames(nc, parent, clientPropName) {
|
|
1396
|
-
let serverPropName = clientPropName + "OnServer";
|
|
1397
|
-
let clientName = parent[clientPropName];
|
|
1398
|
-
if (clientName && clientName.length) {
|
|
1399
|
-
// if (parent.isUnmapped) return;
|
|
1400
|
-
let serverNames = core.toArray(clientName).map(function (cName) {
|
|
1401
|
-
let sName = nc.clientPropertyNameToServer(cName, parent);
|
|
1402
|
-
let testName = nc.serverPropertyNameToClient(sName, parent);
|
|
1403
|
-
if (cName !== testName) {
|
|
1404
|
-
throw new Error("NamingConvention for this client property name does not roundtrip properly:" + cName + "-->" + testName);
|
|
1405
|
-
}
|
|
1406
|
-
return sName;
|
|
1407
|
-
});
|
|
1408
|
-
parent[serverPropName] = Array.isArray(clientName) ? serverNames : serverNames[0];
|
|
1409
|
-
}
|
|
1410
|
-
else {
|
|
1411
|
-
let serverName = parent[serverPropName];
|
|
1412
|
-
if ((!serverName) || serverName.length === 0)
|
|
1413
|
-
return;
|
|
1414
|
-
let clientNames = core.toArray(serverName).map(function (sName) {
|
|
1415
|
-
let cName = nc.serverPropertyNameToClient(sName, parent);
|
|
1416
|
-
let testName = nc.clientPropertyNameToServer(cName, parent);
|
|
1417
|
-
if (sName !== testName) {
|
|
1418
|
-
throw new Error("NamingConvention for this server property name does not roundtrip properly:" + sName + "-->" + testName);
|
|
1419
|
-
}
|
|
1420
|
-
return cName;
|
|
1421
|
-
});
|
|
1422
|
-
parent[clientPropName] = Array.isArray(serverName) ? clientNames : clientNames[0];
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
function createEmptyCtor(type) {
|
|
1426
|
-
if (config.noEval) {
|
|
1427
|
-
let Entity = function () { };
|
|
1428
|
-
return Entity;
|
|
1429
|
-
}
|
|
1430
|
-
else {
|
|
1431
|
-
let name = type.name.replace(/\W/g, '_');
|
|
1432
|
-
return Function('return function ' + name + '(){}')();
|
|
1433
|
-
}
|
|
1434
|
-
}
|
|
1435
|
-
function coEquals(co1, co2) {
|
|
1436
|
-
let complexType = co1.complexAspect.parentProperty.dataType;
|
|
1437
|
-
let dataProps = complexType.dataProperties;
|
|
1438
|
-
let areEqual = dataProps.every(function (dp) {
|
|
1439
|
-
if (!dp.isSettable)
|
|
1440
|
-
return true;
|
|
1441
|
-
let v1 = co1.getProperty(dp.name);
|
|
1442
|
-
let v2 = co2.getProperty(dp.name);
|
|
1443
|
-
if (dp.isComplexProperty && dp.isScalar) {
|
|
1444
|
-
return coEquals(v1, v2);
|
|
1445
|
-
}
|
|
1446
|
-
else if (dp.isComplexProperty && !dp.isScalar) {
|
|
1447
|
-
return core.arrayEquals(v1, v2, coEquals);
|
|
1448
|
-
}
|
|
1449
|
-
else {
|
|
1450
|
-
let dataType = dp.dataType; // this will be a complexType when dp is a complexProperty
|
|
1451
|
-
return (v1 === v2 || (dataType && dataType.normalize && v1 && v2 && dataType.normalize(v1) === dataType.normalize(v2)));
|
|
1452
|
-
}
|
|
1453
|
-
});
|
|
1454
|
-
return areEqual;
|
|
1455
|
-
}
|
|
1456
|
-
function localPropsOnly(props) {
|
|
1457
|
-
return props.filter(function (prop) {
|
|
1458
|
-
return prop.baseProperty == null;
|
|
1459
|
-
});
|
|
1460
|
-
}
|
|
1461
|
-
function resolveCp(cp, metadataStore) {
|
|
1462
|
-
let complexType = metadataStore._getStructuralType(cp.complexTypeName, true);
|
|
1463
|
-
if (!complexType)
|
|
1464
|
-
return false;
|
|
1465
|
-
if (!(complexType instanceof ComplexType)) {
|
|
1466
|
-
throw new Error("Unable to resolve ComplexType with the name: " + cp.complexTypeName + " for the property: " + cp.name);
|
|
1467
|
-
}
|
|
1468
|
-
cp.dataType = complexType;
|
|
1469
|
-
cp.defaultValue = null;
|
|
1470
|
-
return true;
|
|
1471
|
-
}
|
|
1472
|
-
function tryResolveNp(np, metadataStore) {
|
|
1473
|
-
if (np.entityType)
|
|
1474
|
-
return true;
|
|
1475
|
-
let entityType = metadataStore._getStructuralType(np.entityTypeName, true);
|
|
1476
|
-
if (entityType) {
|
|
1477
|
-
np.entityType = entityType;
|
|
1478
|
-
np._resolveNp();
|
|
1479
|
-
// don't bother removing - _updateNps will do it later.
|
|
1480
|
-
// __arrayRemoveItem(incompleteNps, np, false);
|
|
1481
|
-
}
|
|
1482
|
-
else {
|
|
1483
|
-
let incompleteNps = core.getArray(metadataStore._incompleteTypeMap, np.entityTypeName);
|
|
1484
|
-
core.arrayAddItemUnique(incompleteNps, np);
|
|
1485
|
-
}
|
|
1486
|
-
return !!entityType;
|
|
1487
|
-
}
|
|
1488
|
-
function calcUnmappedProperties(stype, instance) {
|
|
1489
|
-
let metadataPropNames = stype.getPropertyNames();
|
|
1490
|
-
let modelLib = config.interfaceRegistry.modelLibrary.getDefaultInstance();
|
|
1491
|
-
let trackablePropNames = modelLib.getTrackablePropertyNames(instance);
|
|
1492
|
-
trackablePropNames.forEach(function (pn) {
|
|
1493
|
-
if (metadataPropNames.indexOf(pn) === -1) {
|
|
1494
|
-
let val = instance[pn];
|
|
1495
|
-
try {
|
|
1496
|
-
if (typeof val === "function")
|
|
1497
|
-
val = val();
|
|
1498
|
-
}
|
|
1499
|
-
catch (e) {
|
|
1500
|
-
}
|
|
1501
|
-
let dt = DataType.fromValue(val);
|
|
1502
|
-
let newProp = new DataProperty({
|
|
1503
|
-
name: pn,
|
|
1504
|
-
dataType: dt,
|
|
1505
|
-
isNullable: true,
|
|
1506
|
-
isUnmapped: true
|
|
1507
|
-
});
|
|
1508
|
-
newProp.isSettable = core.isSettable(instance, pn);
|
|
1509
|
-
if (stype instanceof EntityType && stype.subtypes != null && stype.subtypes.length) {
|
|
1510
|
-
stype.getSelfAndSubtypes().forEach((st) => {
|
|
1511
|
-
st._addPropertyCore(new DataProperty(newProp));
|
|
1512
|
-
});
|
|
1513
|
-
}
|
|
1514
|
-
else {
|
|
1515
|
-
stype._addPropertyCore(newProp);
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
});
|
|
1519
|
-
}
|
|
1520
|
-
/** Container for all of the metadata about a specific type of Complex object.
|
|
1521
|
-
> let complexType = new ComplexType( {
|
|
1522
|
-
> shortName: "address",
|
|
1523
|
-
> namespace: "myAppNamespace"
|
|
1524
|
-
> });
|
|
1525
|
-
@param config - Configuration settings
|
|
1526
|
-
**/
|
|
1527
|
-
export class ComplexType {
|
|
1528
|
-
constructor(config) {
|
|
1529
|
-
/** For polymorphic purpose only - always true here */
|
|
1530
|
-
this.isComplexType = true;
|
|
1531
|
-
// copy entityType methods onto complexType
|
|
1532
|
-
/** See [[EntityType.getCtor]] */
|
|
1533
|
-
this.getCtor = EntityType.prototype.getCtor;
|
|
1534
|
-
// note the name change.
|
|
1535
|
-
this.createInstance = EntityType.prototype.createEntity;
|
|
1536
|
-
/** See [EntityType.addValidator] */
|
|
1537
|
-
this.addValidator = EntityType.prototype.addValidator;
|
|
1538
|
-
this.getProperty = EntityType.prototype.getProperty;
|
|
1539
|
-
this.getPropertiesOnPath = EntityType.prototype.getPropertiesOnPath;
|
|
1540
|
-
this.getPropertyNames = EntityType.prototype.getPropertyNames;
|
|
1541
|
-
/** @hidden @internal */
|
|
1542
|
-
this._addPropertyCore = EntityType.prototype._addPropertyCore;
|
|
1543
|
-
/** @hidden @internal */
|
|
1544
|
-
this._addDataProperty = EntityType.prototype._addDataProperty;
|
|
1545
|
-
/** @hidden @internal */
|
|
1546
|
-
this._updateNames = EntityType.prototype._updateNames;
|
|
1547
|
-
/** @hidden @internal */
|
|
1548
|
-
this._updateCps = EntityType.prototype._updateCps;
|
|
1549
|
-
/** @hidden @internal */
|
|
1550
|
-
this._initializeInstance = EntityType.prototype._initializeInstance;
|
|
1551
|
-
/** @hidden @internal */
|
|
1552
|
-
this._updateTargetFromRaw = EntityType.prototype._updateTargetFromRaw;
|
|
1553
|
-
/** @hidden @internal */
|
|
1554
|
-
this._setCtor = EntityType.prototype._setCtor;
|
|
1555
|
-
if (arguments.length > 1) {
|
|
1556
|
-
throw new Error("The ComplexType ctor has a single argument that is a configuration object.");
|
|
1557
|
-
}
|
|
1558
|
-
assertConfig(config)
|
|
1559
|
-
.whereParam("shortName").isNonEmptyString()
|
|
1560
|
-
.whereParam("namespace").isString().isOptional().withDefault("")
|
|
1561
|
-
.whereParam("dataProperties").isOptional()
|
|
1562
|
-
.whereParam("isComplexType").isOptional().isBoolean() // needed because this ctor can get called from the addEntityType method which needs the isComplexType prop
|
|
1563
|
-
.whereParam("custom").isOptional()
|
|
1564
|
-
.applyAll(this);
|
|
1565
|
-
this.name = qualifyTypeName(this.shortName, this.namespace);
|
|
1566
|
-
this.isComplexType = true;
|
|
1567
|
-
this.dataProperties = [];
|
|
1568
|
-
this.complexProperties = [];
|
|
1569
|
-
this.validators = [];
|
|
1570
|
-
this.concurrencyProperties = [];
|
|
1571
|
-
this.unmappedProperties = [];
|
|
1572
|
-
this._mappedPropertiesCount = 0;
|
|
1573
|
-
// keyProperties and navigationProperties are not used on complexTypes - but here to allow sharing of code between EntityType and ComplexType.
|
|
1574
|
-
this.navigationProperties = [];
|
|
1575
|
-
this.keyProperties = []; // may be used later to enforce uniqueness on arrays of complextypes.
|
|
1576
|
-
if (config.dataProperties) {
|
|
1577
|
-
addProperties(this, config.dataProperties, DataProperty);
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
/**
|
|
1581
|
-
General purpose property set method
|
|
1582
|
-
> // assume em1 is an EntityManager
|
|
1583
|
-
> let addresstType = em1.metadataStore.getEntityType("Address");
|
|
1584
|
-
> addressType.setProperties( {
|
|
1585
|
-
> custom: { foo: 7, bar: "test" }
|
|
1586
|
-
> });
|
|
1587
|
-
@param config - Custom config object
|
|
1588
|
-
@param config.custom - {Object}
|
|
1589
|
-
**/
|
|
1590
|
-
setProperties(config) {
|
|
1591
|
-
assertConfig(config)
|
|
1592
|
-
.whereParam("custom").isOptional()
|
|
1593
|
-
.applyAll(this);
|
|
1594
|
-
}
|
|
1595
|
-
getAllValidators() {
|
|
1596
|
-
// ComplexType inheritance is not YET supported.
|
|
1597
|
-
return this.validators;
|
|
1598
|
-
}
|
|
1599
|
-
/** @hidden @internal */
|
|
1600
|
-
_createInstanceCore(parent, parentProperty) {
|
|
1601
|
-
let aCtor = this.getCtor();
|
|
1602
|
-
let instance = new aCtor();
|
|
1603
|
-
new ComplexAspect(instance, parent, parentProperty);
|
|
1604
|
-
// initialization occurs during either attach or in createInstance call.
|
|
1605
|
-
return instance;
|
|
1606
|
-
}
|
|
1607
|
-
addProperty(dataProperty) {
|
|
1608
|
-
assertParam(dataProperty, "dataProperty").isInstanceOf(DataProperty).check();
|
|
1609
|
-
return this._addPropertyCore(dataProperty);
|
|
1610
|
-
}
|
|
1611
|
-
getProperties() {
|
|
1612
|
-
return this.dataProperties;
|
|
1613
|
-
}
|
|
1614
|
-
toJSON() {
|
|
1615
|
-
return core.toJson(this, {
|
|
1616
|
-
shortName: null,
|
|
1617
|
-
namespace: null,
|
|
1618
|
-
isComplexType: null,
|
|
1619
|
-
dataProperties: null,
|
|
1620
|
-
validators: null,
|
|
1621
|
-
custom: null
|
|
1622
|
-
});
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
ComplexType.prototype._$typeName = "ComplexType";
|
|
1626
|
-
/** Creates an instance of this complexType */
|
|
1627
|
-
ComplexType.prototype.createInstance = EntityType.prototype.createEntity;
|
|
1628
|
-
/**
|
|
1629
|
-
A DataProperty describes the metadata for a single property of an [[EntityType]] that contains simple data.
|
|
1630
|
-
|
|
1631
|
-
Instances of the DataProperty class are constructed automatically during Metadata retrieval. However it is also possible to construct them
|
|
1632
|
-
directly via the constructor.
|
|
1633
|
-
**/
|
|
1634
|
-
export class DataProperty {
|
|
1635
|
-
/** DataProperty constructor
|
|
1636
|
-
> let lastNameProp = new DataProperty( {
|
|
1637
|
-
> name: "lastName",
|
|
1638
|
-
> dataType: DataType.String,
|
|
1639
|
-
> isNullable: true,
|
|
1640
|
-
> maxLength: 20
|
|
1641
|
-
> });
|
|
1642
|
-
> // assuming personEntityType is a newly constructed EntityType
|
|
1643
|
-
> personEntityType.addProperty(lastNameProperty);
|
|
1644
|
-
@param config - A configuration Object or a DataProperty
|
|
1645
|
-
*/
|
|
1646
|
-
constructor(config) {
|
|
1647
|
-
/** Is this a DataProperty? - always true here. Allows polymorphic treatment of DataProperties and NavigationProperties. __Read Only__ */
|
|
1648
|
-
this.isDataProperty = true;
|
|
1649
|
-
/** Is this a NavigationProperty? - always false here. Allows polymorphic treatment of DataProperties and NavigationProperties. __Read Only__ */
|
|
1650
|
-
this.isNavigationProperty = false;
|
|
1651
|
-
assertConfig(config)
|
|
1652
|
-
.whereParam("name").isString().isOptional()
|
|
1653
|
-
.whereParam("nameOnServer").isString().isOptional()
|
|
1654
|
-
.whereParam("dataType").isEnumOf(DataType).isOptional().or().isString().or().isInstanceOf(ComplexType)
|
|
1655
|
-
.whereParam("complexTypeName").isOptional()
|
|
1656
|
-
.whereParam("isNullable").isBoolean().isOptional().withDefault(true)
|
|
1657
|
-
.whereParam("isScalar").isOptional().withDefault(true) // will be false for some NoSQL databases.
|
|
1658
|
-
.whereParam("defaultValue").isOptional()
|
|
1659
|
-
.whereParam("isPartOfKey").isBoolean().isOptional()
|
|
1660
|
-
.whereParam("isUnmapped").isBoolean().isOptional()
|
|
1661
|
-
.whereParam("isSettable").isBoolean().isOptional().withDefault(true)
|
|
1662
|
-
.whereParam("concurrencyMode").isString().isOptional()
|
|
1663
|
-
.whereParam("maxLength").isNumber().isOptional()
|
|
1664
|
-
.whereParam("validators").isInstanceOf(Validator).isArray().isOptional().withDefault([])
|
|
1665
|
-
.whereParam("displayName").isOptional()
|
|
1666
|
-
.whereParam("enumType").isOptional()
|
|
1667
|
-
.whereParam("rawTypeName").isOptional() // occurs with undefined datatypes
|
|
1668
|
-
.whereParam("custom").isOptional()
|
|
1669
|
-
.applyAll(this);
|
|
1670
|
-
let hasName = !!(this.name || this.nameOnServer);
|
|
1671
|
-
if (!hasName) {
|
|
1672
|
-
throw new Error("A DataProperty must be instantiated with either a 'name' or a 'nameOnServer' property");
|
|
1673
|
-
}
|
|
1674
|
-
// name/nameOnServer is resolved later when a metadataStore is available.
|
|
1675
|
-
if (this.complexTypeName) {
|
|
1676
|
-
this.isComplexProperty = true;
|
|
1677
|
-
// this.dataType = null; // TODO: would like to remove this line because dataType will be set later.
|
|
1678
|
-
}
|
|
1679
|
-
else if (typeof (this.dataType) === "string") {
|
|
1680
|
-
let dt = DataType.fromName(this.dataType);
|
|
1681
|
-
if (!dt) {
|
|
1682
|
-
throw new Error("Unable to find a DataType enumeration by the name of: " + this.dataType);
|
|
1683
|
-
}
|
|
1684
|
-
this.dataType = dt;
|
|
1685
|
-
}
|
|
1686
|
-
else if (!this.dataType) {
|
|
1687
|
-
this.dataType = DataType.String;
|
|
1688
|
-
}
|
|
1689
|
-
// == as opposed to === is deliberate here.
|
|
1690
|
-
if (this.defaultValue == null) {
|
|
1691
|
-
if (this.isNullable) {
|
|
1692
|
-
this.defaultValue = null;
|
|
1693
|
-
}
|
|
1694
|
-
else {
|
|
1695
|
-
if (this.isComplexProperty) {
|
|
1696
|
-
// what to do? - shouldn't happen from EF - but otherwise ???
|
|
1697
|
-
}
|
|
1698
|
-
else if (this.dataType === DataType.Binary) {
|
|
1699
|
-
this.defaultValue = "AAAAAAAAJ3U="; // hack for all binary fields but value is specifically valid for timestamp fields - arbitrary valid 8 byte base64 value.
|
|
1700
|
-
}
|
|
1701
|
-
else {
|
|
1702
|
-
this.defaultValue = this.dataType.defaultValue;
|
|
1703
|
-
const msg = "A nonnullable DataProperty cannot have a null defaultValue. Name: " + (this.name || this.nameOnServer);
|
|
1704
|
-
if (this.defaultValue === null) {
|
|
1705
|
-
throw new Error(msg); // if defaultValue is explicity set to null, that's an error
|
|
1706
|
-
}
|
|
1707
|
-
else if (this.defaultValue == null) {
|
|
1708
|
-
console.warn(msg); // if defaultValue is not set, that's a warning
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
}
|
|
1713
|
-
else if (this.dataType.isNumeric) {
|
|
1714
|
-
// in case the defaultValue comes in as a string ( which it does in EF6).
|
|
1715
|
-
if (typeof (this.defaultValue) === "string") {
|
|
1716
|
-
this.defaultValue = parseFloat(this.defaultValue);
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
if (this.isComplexProperty) {
|
|
1720
|
-
this.isScalar = this.isScalar == null || this.isScalar === true;
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
static getRawValueFromServer(rawEntity, dp) {
|
|
1724
|
-
if (dp.isUnmapped) {
|
|
1725
|
-
return rawEntity[dp.nameOnServer || dp.name];
|
|
1726
|
-
}
|
|
1727
|
-
else {
|
|
1728
|
-
let val = rawEntity[dp.nameOnServer];
|
|
1729
|
-
return val !== undefined ? val : dp.defaultValue;
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
static getRawValueFromClient(rawEntity, dp) {
|
|
1733
|
-
let val = rawEntity[dp.name];
|
|
1734
|
-
return val !== undefined ? val : dp.defaultValue;
|
|
1735
|
-
}
|
|
1736
|
-
resolveProperty(propName) {
|
|
1737
|
-
let result = this[propName];
|
|
1738
|
-
let baseProp = this.baseProperty;
|
|
1739
|
-
while (result == undefined && baseProp != null) {
|
|
1740
|
-
result = baseProp[propName];
|
|
1741
|
-
baseProp = baseProp.baseProperty;
|
|
1742
|
-
}
|
|
1743
|
-
return result;
|
|
1744
|
-
}
|
|
1745
|
-
formatName() {
|
|
1746
|
-
return this.parentType.name + "--" + this.name;
|
|
1747
|
-
}
|
|
1748
|
-
/**
|
|
1749
|
-
General purpose property set method
|
|
1750
|
-
> // assume em1 is an EntityManager
|
|
1751
|
-
> let prop = myEntityType.getProperty("myProperty");
|
|
1752
|
-
> prop.setProperties( {
|
|
1753
|
-
> custom: { foo: 7, bar: "test" }
|
|
1754
|
-
> });
|
|
1755
|
-
@param config - A configuration object.
|
|
1756
|
-
**/
|
|
1757
|
-
setProperties(config) {
|
|
1758
|
-
assertConfig(config)
|
|
1759
|
-
.whereParam("displayName").isOptional()
|
|
1760
|
-
.whereParam("custom").isOptional()
|
|
1761
|
-
.applyAll(this);
|
|
1762
|
-
}
|
|
1763
|
-
getAllValidators() {
|
|
1764
|
-
let validators = this.validators.slice(0);
|
|
1765
|
-
let baseProp = this.baseProperty;
|
|
1766
|
-
while (baseProp) {
|
|
1767
|
-
validators.push.apply(validators, baseProp.validators);
|
|
1768
|
-
baseProp = baseProp.baseProperty;
|
|
1769
|
-
}
|
|
1770
|
-
return validators;
|
|
1771
|
-
}
|
|
1772
|
-
toJSON() {
|
|
1773
|
-
// do not serialize dataTypes that are complexTypes
|
|
1774
|
-
return core.toJson(this, {
|
|
1775
|
-
name: null,
|
|
1776
|
-
dataType: function (v) {
|
|
1777
|
-
return (v && v instanceof DataType) ? v.name : undefined;
|
|
1778
|
-
},
|
|
1779
|
-
complexTypeName: null,
|
|
1780
|
-
isNullable: true,
|
|
1781
|
-
defaultValue: null,
|
|
1782
|
-
isPartOfKey: false,
|
|
1783
|
-
isUnmapped: false,
|
|
1784
|
-
isSettable: true,
|
|
1785
|
-
concurrencyMode: null,
|
|
1786
|
-
maxLength: null,
|
|
1787
|
-
validators: null,
|
|
1788
|
-
displayName: null,
|
|
1789
|
-
enumType: null,
|
|
1790
|
-
rawTypeName: null,
|
|
1791
|
-
isScalar: true,
|
|
1792
|
-
custom: null
|
|
1793
|
-
});
|
|
1794
|
-
}
|
|
1795
|
-
static fromJSON(json) {
|
|
1796
|
-
json.dataType = DataType.fromName(json.dataType);
|
|
1797
|
-
// Parse default value into correct data type. (dateTime instances require extra work to deserialize properly.)
|
|
1798
|
-
if (json.defaultValue && json.dataType && json.dataType.parse) {
|
|
1799
|
-
json.defaultValue = json.dataType.parse(json.defaultValue, typeof json.defaultValue);
|
|
1800
|
-
}
|
|
1801
|
-
if (json.validators) {
|
|
1802
|
-
json.validators = json.validators.map(Validator.fromJSON);
|
|
1803
|
-
}
|
|
1804
|
-
return new DataProperty(json);
|
|
1805
|
-
}
|
|
1806
|
-
}
|
|
1807
|
-
DataProperty.prototype._$typeName = "DataProperty";
|
|
1808
|
-
/** A NavigationProperty describes the metadata for a single property of an [[EntityType]] that return instances of other EntityTypes.
|
|
1809
|
-
|
|
1810
|
-
Instances of the NavigationProperty class are constructed automatically during Metadata retrieval. However it is also possible to construct them
|
|
1811
|
-
directly via the constructor.
|
|
1812
|
-
**/
|
|
1813
|
-
export class NavigationProperty {
|
|
1814
|
-
/** NavigationProperty constructor
|
|
1815
|
-
> let homeAddressProp = new NavigationProperty( {
|
|
1816
|
-
> name: "homeAddress",
|
|
1817
|
-
> entityTypeName: "Address:#myNamespace",
|
|
1818
|
-
> isScalar: true,
|
|
1819
|
-
> associationName: "address_person",
|
|
1820
|
-
> foreignKeyNames: ["homeAddressId"]
|
|
1821
|
-
> });
|
|
1822
|
-
> let homeAddressIdProp = new DataProperty( {
|
|
1823
|
-
> name: "homeAddressId"
|
|
1824
|
-
> dataType: DataType.Integer
|
|
1825
|
-
> });
|
|
1826
|
-
> // assuming personEntityType is a newly constructed EntityType
|
|
1827
|
-
> personEntityType.addProperty(homeAddressProp);
|
|
1828
|
-
> personEntityType.addProperty(homeAddressIdProp);
|
|
1829
|
-
@param config - A configuration object.
|
|
1830
|
-
**/
|
|
1831
|
-
constructor(config) {
|
|
1832
|
-
/** Is this a DataProperty? - always false here
|
|
1833
|
-
Allows polymorphic treatment of DataProperties and NavigationProperties. __Read Only__ */
|
|
1834
|
-
this.isDataProperty = false;
|
|
1835
|
-
/** Is this a NavigationProperty? - always true here
|
|
1836
|
-
Allows polymorphic treatment of DataProperties and NavigationProperties. __Read Only__ */
|
|
1837
|
-
this.isNavigationProperty = true;
|
|
1838
|
-
this.formatName = DataProperty.prototype.formatName;
|
|
1839
|
-
this.getAllValidators = DataProperty.prototype.getAllValidators;
|
|
1840
|
-
this.resolveProperty = DataProperty.prototype.resolveProperty;
|
|
1841
|
-
assertConfig(config)
|
|
1842
|
-
.whereParam("name").isString().isOptional()
|
|
1843
|
-
.whereParam("nameOnServer").isString().isOptional()
|
|
1844
|
-
.whereParam("entityTypeName").isString()
|
|
1845
|
-
.whereParam("isScalar").isBoolean().isOptional().withDefault(true)
|
|
1846
|
-
.whereParam("associationName").isString().isOptional()
|
|
1847
|
-
.whereParam("foreignKeyNames").isArray().isString().isOptional().withDefault([])
|
|
1848
|
-
.whereParam("foreignKeyNamesOnServer").isArray().isString().isOptional().withDefault([])
|
|
1849
|
-
.whereParam("invForeignKeyNames").isArray().isString().isOptional().withDefault([])
|
|
1850
|
-
.whereParam("invForeignKeyNamesOnServer").isArray().isString().isOptional().withDefault([])
|
|
1851
|
-
.whereParam("validators").isInstanceOf(Validator).isArray().isOptional().withDefault([])
|
|
1852
|
-
.whereParam("displayName").isOptional()
|
|
1853
|
-
.whereParam("custom").isOptional()
|
|
1854
|
-
.applyAll(this);
|
|
1855
|
-
let hasName = !!(this.name || this.nameOnServer);
|
|
1856
|
-
if (!hasName) {
|
|
1857
|
-
throw new Error("A Navigation property must be instantiated with either a 'name' or a 'nameOnServer' property");
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1860
|
-
/**
|
|
1861
|
-
General purpose property set method
|
|
1862
|
-
> // assume myEntityType is an EntityType
|
|
1863
|
-
> let prop = myEntityType.getProperty("myProperty");
|
|
1864
|
-
> prop.setProperties( {
|
|
1865
|
-
> custom: { foo: 7, bar: "test" }
|
|
1866
|
-
> });
|
|
1867
|
-
@param config - A config object
|
|
1868
|
-
**/
|
|
1869
|
-
// TODO: create an interface for this.
|
|
1870
|
-
setProperties(config) {
|
|
1871
|
-
if (!this.parentType) {
|
|
1872
|
-
throw new Error("Cannot call NavigationProperty.setProperties until the parent EntityType of the NavigationProperty has been set.");
|
|
1873
|
-
}
|
|
1874
|
-
let inverse = config.inverse;
|
|
1875
|
-
if (inverse)
|
|
1876
|
-
delete config.inverse;
|
|
1877
|
-
assertConfig(config)
|
|
1878
|
-
.whereParam("displayName").isOptional()
|
|
1879
|
-
.whereParam("foreignKeyNames").isArray().isString().isOptional().withDefault([])
|
|
1880
|
-
.whereParam("invForeignKeyNames").isArray().isString().isOptional().withDefault([])
|
|
1881
|
-
.whereParam("custom").isOptional()
|
|
1882
|
-
.applyAll(this);
|
|
1883
|
-
this.parentType._updateNames(this);
|
|
1884
|
-
this._resolveNp();
|
|
1885
|
-
if (inverse) {
|
|
1886
|
-
this.setInverse(inverse);
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1889
|
-
/** The inverse of this NavigationProperty. The NavigationProperty that represents a navigation in the opposite direction
|
|
1890
|
-
to this NavigationProperty. May be undefined for a undirectional NavigationProperty. __Read Only__ */
|
|
1891
|
-
get inverse() {
|
|
1892
|
-
return this.getInverse();
|
|
1893
|
-
}
|
|
1894
|
-
/** @hidden @internal */
|
|
1895
|
-
getInverse() {
|
|
1896
|
-
let np = this;
|
|
1897
|
-
while (!np._inverse && np.baseProperty) {
|
|
1898
|
-
np = np.baseProperty;
|
|
1899
|
-
}
|
|
1900
|
-
return np._inverse;
|
|
1901
|
-
}
|
|
1902
|
-
setInverse(inverseNp) {
|
|
1903
|
-
// let invNp: NavigationProperty;
|
|
1904
|
-
let invNp = (inverseNp instanceof NavigationProperty) ? inverseNp : this.entityType.getNavigationProperty(inverseNp);
|
|
1905
|
-
if (!invNp) {
|
|
1906
|
-
throw throwSetInverseError(this, "Unable to find inverse property: " + inverseNp);
|
|
1907
|
-
}
|
|
1908
|
-
if (this._inverse || invNp._inverse) {
|
|
1909
|
-
throwSetInverseError(this, "It has already been set on one side or the other.");
|
|
1910
|
-
}
|
|
1911
|
-
if (invNp.entityType !== this.parentType) {
|
|
1912
|
-
throwSetInverseError(this, invNp.formatName + " is not a valid inverse property for this.");
|
|
1913
|
-
}
|
|
1914
|
-
if (this.associationName) {
|
|
1915
|
-
invNp.associationName = this.associationName;
|
|
1916
|
-
}
|
|
1917
|
-
else {
|
|
1918
|
-
if (!invNp.associationName) {
|
|
1919
|
-
invNp.associationName = this.formatName() + "_" + invNp.formatName();
|
|
1920
|
-
}
|
|
1921
|
-
this.associationName = invNp.associationName;
|
|
1922
|
-
}
|
|
1923
|
-
this._resolveNp();
|
|
1924
|
-
invNp._resolveNp();
|
|
1925
|
-
}
|
|
1926
|
-
// // In progress - will be used for manual metadata config
|
|
1927
|
-
// createInverse(config: any) {
|
|
1928
|
-
// if (!this.entityType) {
|
|
1929
|
-
// throwCreateInverseError(this, "has not yet been defined.");
|
|
1930
|
-
// }
|
|
1931
|
-
// if (this.entityType.isFrozen) {
|
|
1932
|
-
// throwCreateInverseError(this, "is frozen.");
|
|
1933
|
-
// }
|
|
1934
|
-
// let metadataStore = this.entityType.metadataStore;
|
|
1935
|
-
// if (metadataStore == null) {
|
|
1936
|
-
// throwCreateInverseError(this, "has not yet been added to the metadataStore.");
|
|
1937
|
-
// }
|
|
1938
|
-
// config.entityTypeName = this.parentEntityType.name;
|
|
1939
|
-
// config.associationName = this.associationName;
|
|
1940
|
-
// let invNp = new NavigationProperty(config);
|
|
1941
|
-
// this.parentEntityType.addNavigationProperty(invNp);
|
|
1942
|
-
// return invNp;
|
|
1943
|
-
// };
|
|
1944
|
-
toJSON() {
|
|
1945
|
-
return core.toJson(this, {
|
|
1946
|
-
name: null,
|
|
1947
|
-
entityTypeName: null,
|
|
1948
|
-
isScalar: null,
|
|
1949
|
-
associationName: null,
|
|
1950
|
-
validators: null,
|
|
1951
|
-
displayName: null,
|
|
1952
|
-
foreignKeyNames: null,
|
|
1953
|
-
invForeignKeyNames: null,
|
|
1954
|
-
custom: null
|
|
1955
|
-
});
|
|
1956
|
-
}
|
|
1957
|
-
static fromJSON(json) {
|
|
1958
|
-
if (json.validators) {
|
|
1959
|
-
json.validators = json.validators.map(Validator.fromJSON);
|
|
1960
|
-
}
|
|
1961
|
-
return new NavigationProperty(json);
|
|
1962
|
-
}
|
|
1963
|
-
/** @hidden @internal */
|
|
1964
|
-
_resolveNp() {
|
|
1965
|
-
let np = this;
|
|
1966
|
-
let entityType = np.entityType;
|
|
1967
|
-
let invNp = core.arrayFirst(entityType.navigationProperties, (altNp) => {
|
|
1968
|
-
// Can't do this because of possibility of comparing a base class np with a subclass altNp.
|
|
1969
|
-
// return altNp.associationName === np.associationName
|
|
1970
|
-
// && altNp !== np;
|
|
1971
|
-
// So use this instead.
|
|
1972
|
-
return altNp.associationName === np.associationName &&
|
|
1973
|
-
(altNp.name !== np.name || altNp.entityTypeName !== np.entityTypeName);
|
|
1974
|
-
});
|
|
1975
|
-
np._inverse = invNp || undefined;
|
|
1976
|
-
//if (invNp && invNp.inverse == null) {
|
|
1977
|
-
// invNp._resolveNp();
|
|
1978
|
-
//}
|
|
1979
|
-
if (!invNp) {
|
|
1980
|
-
// unidirectional 1-n relationship
|
|
1981
|
-
np.invForeignKeyNames.forEach(function (invFkName) {
|
|
1982
|
-
let fkProp = entityType.getDataProperty(invFkName);
|
|
1983
|
-
if (fkProp == null) {
|
|
1984
|
-
throw new Error("EntityType '" + np.entityTypeName + "' has no foreign key matching '" + invFkName + "'");
|
|
1985
|
-
}
|
|
1986
|
-
let invEntityType = np.parentType;
|
|
1987
|
-
invNp = core.arrayFirst(invEntityType.navigationProperties, (np2) => {
|
|
1988
|
-
return np2.invForeignKeyNames && np2.invForeignKeyNames.indexOf(fkProp.name) >= 0 && np2.entityType === fkProp.parentType;
|
|
1989
|
-
});
|
|
1990
|
-
fkProp.inverseNavigationProperty = invNp || undefined;
|
|
1991
|
-
core.arrayAddItemUnique(entityType.foreignKeyProperties, fkProp);
|
|
1992
|
-
});
|
|
1993
|
-
}
|
|
1994
|
-
resolveRelated(np);
|
|
1995
|
-
}
|
|
1996
|
-
}
|
|
1997
|
-
NavigationProperty.prototype._$typeName = "NavigationProperty";
|
|
1998
|
-
function throwSetInverseError(np, message) {
|
|
1999
|
-
throw new Error("Cannot set the inverse property for: " + np.formatName() + ". " + message);
|
|
2000
|
-
}
|
|
2001
|
-
// Not current used.
|
|
2002
|
-
// function throwCreateInverseError(np: NavigationProperty, message: string) {
|
|
2003
|
-
// throw new Error("Cannot create inverse for: " + np.formatName() + ". The entityType for this navigation property " + message);
|
|
2004
|
-
// }
|
|
2005
|
-
// sets navigation property: relatedDataProperties and dataProperty: relatedNavigationProperty
|
|
2006
|
-
function resolveRelated(np) {
|
|
2007
|
-
let fkNames = np.foreignKeyNames;
|
|
2008
|
-
if (fkNames.length === 0)
|
|
2009
|
-
return;
|
|
2010
|
-
let parentEntityType = np.parentType;
|
|
2011
|
-
let fkProps = fkNames.map(function (fkName) {
|
|
2012
|
-
return parentEntityType.getDataProperty(fkName);
|
|
2013
|
-
});
|
|
2014
|
-
let fkPropCollection = parentEntityType.foreignKeyProperties;
|
|
2015
|
-
fkProps.forEach((dp) => {
|
|
2016
|
-
core.arrayAddItemUnique(fkPropCollection, dp);
|
|
2017
|
-
dp.relatedNavigationProperty = np;
|
|
2018
|
-
// now update the inverse
|
|
2019
|
-
core.arrayAddItemUnique(np.entityType.inverseForeignKeyProperties, dp);
|
|
2020
|
-
if (np.relatedDataProperties) {
|
|
2021
|
-
core.arrayAddItemUnique(np.relatedDataProperties, dp);
|
|
2022
|
-
}
|
|
2023
|
-
else {
|
|
2024
|
-
np.relatedDataProperties = [dp];
|
|
2025
|
-
}
|
|
2026
|
-
});
|
|
2027
|
-
}
|
|
2028
|
-
/**
|
|
2029
|
-
AutoGeneratedKeyType is an 'Enum' containing all of the valid states for an automatically generated key.
|
|
2030
|
-
**/
|
|
2031
|
-
export class AutoGeneratedKeyType extends BreezeEnum {
|
|
2032
|
-
}
|
|
2033
|
-
/**
|
|
2034
|
-
This entity does not have an autogenerated key.
|
|
2035
|
-
The client must set the key before adding the entity to the EntityManager
|
|
2036
|
-
**/
|
|
2037
|
-
AutoGeneratedKeyType.None = new AutoGeneratedKeyType();
|
|
2038
|
-
/**
|
|
2039
|
-
This entity's key is an Identity column and is set by the backend database.
|
|
2040
|
-
Keys for new entities will be temporary until the entities are saved at which point the keys will
|
|
2041
|
-
be converted to their 'real' versions.
|
|
2042
|
-
**/
|
|
2043
|
-
AutoGeneratedKeyType.Identity = new AutoGeneratedKeyType();
|
|
2044
|
-
/**
|
|
2045
|
-
This entity's key is generated by a KeyGenerator and is set by the backend database.
|
|
2046
|
-
Keys for new entities will be temporary until the entities are saved at which point the keys will
|
|
2047
|
-
be converted to their 'real' versions.
|
|
2048
|
-
**/
|
|
2049
|
-
AutoGeneratedKeyType.KeyGenerator = new AutoGeneratedKeyType();
|
|
2050
|
-
AutoGeneratedKeyType.prototype._$typeName = "AutoGeneratedKeyType";
|
|
2051
|
-
Error['x'] = AutoGeneratedKeyType.resolveSymbols();
|
|
2052
|
-
let proto = Param.prototype;
|
|
2053
|
-
// 'this' below is TS annotation
|
|
2054
|
-
proto.isEntity = function () {
|
|
2055
|
-
return this._addContext({
|
|
2056
|
-
fn: isEntity,
|
|
2057
|
-
msg: " must be an entity"
|
|
2058
|
-
});
|
|
2059
|
-
};
|
|
2060
|
-
function isEntity(context, v) {
|
|
2061
|
-
if (v == null)
|
|
2062
|
-
return false;
|
|
2063
|
-
return (v.entityType !== undefined);
|
|
2064
|
-
}
|
|
2065
|
-
proto.isEntityProperty = function () {
|
|
2066
|
-
return this._addContext({
|
|
2067
|
-
fn: isEntityProperty,
|
|
2068
|
-
msg: " must be either a DataProperty or a NavigationProperty"
|
|
2069
|
-
});
|
|
2070
|
-
};
|
|
2071
|
-
function isEntityProperty(context, v) {
|
|
2072
|
-
if (v == null)
|
|
2073
|
-
return false;
|
|
2074
|
-
return (v.isDataProperty || v.isNavigationProperty);
|
|
2075
|
-
}
|
|
2076
|
-
// functions shared between classes related to Metadata
|
|
2077
|
-
function isQualifiedTypeName(entityTypeName) {
|
|
2078
|
-
return entityTypeName.indexOf(":#") >= 0;
|
|
2079
|
-
}
|
|
2080
|
-
export function qualifyTypeName(shortName, ns) {
|
|
2081
|
-
if (ns && ns.length > 0) {
|
|
2082
|
-
return shortName + ":#" + ns;
|
|
2083
|
-
}
|
|
2084
|
-
else {
|
|
2085
|
-
return shortName;
|
|
2086
|
-
}
|
|
2087
|
-
}
|
|
2088
|
-
// Used by both ComplexType and EntityType
|
|
2089
|
-
function addProperties(entityType, propObj, ctor) {
|
|
2090
|
-
if (propObj == null)
|
|
2091
|
-
return;
|
|
2092
|
-
if (Array.isArray(propObj)) {
|
|
2093
|
-
propObj.forEach(entityType._addPropertyCore.bind(entityType));
|
|
2094
|
-
}
|
|
2095
|
-
else if (typeof (propObj) === 'object') {
|
|
2096
|
-
for (let key in propObj) {
|
|
2097
|
-
if (core.hasOwnProperty(propObj, key)) {
|
|
2098
|
-
let value = propObj[key];
|
|
2099
|
-
value.name = key;
|
|
2100
|
-
let prop = new ctor(value);
|
|
2101
|
-
entityType._addPropertyCore(prop);
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
else {
|
|
2106
|
-
throw new Error("The 'dataProperties' or 'navigationProperties' values must be either an array of data/nav properties or an object where each property defines a data/nav property");
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LW1ldGFkYXRhLmpzIiwic291cmNlUm9vdCI6Im5nOi8vYnJlZXplLWNsaWVudC8iLCJzb3VyY2VzIjpbInNyYy9lbnRpdHktbWV0YWRhdGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBaUIsTUFBTSxRQUFRLENBQUM7QUFDN0MsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNsQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDdkMsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQTJDLE1BQU0saUJBQWlCLENBQUM7QUFDdkcsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDcEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDLENBQUMsMkJBQTJCO0FBQ3hGLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQy9FLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBdUM1RTs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBcUR4Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BcUJHO0lBQ0gsWUFBWSxNQUE0QjtRQUN0QyxNQUFNLEdBQUcsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUN0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Q0wsTUFBTSxJQUFJLEtBQUssQ0FBQyxtS0FBbUssQ0FBQyxDQUFDO0tBQ3RMO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNvcmUsIEVycm9yQ2FsbGJhY2sgfSBmcm9tICcuL2NvcmUnO1xyXG5pbXBvcnQgeyBjb25maWcgfSBmcm9tICcuL2NvbmZpZyc7XHJcbmltcG9ydCB7IEJyZWV6ZUV2ZW50IH0gZnJvbSAnLi9ldmVudCc7XHJcbmltcG9ydCB7IGFzc2VydFBhcmFtLCBhc3NlcnRDb25maWcsIFBhcmFtIH0gZnJvbSAnLi9hc3NlcnQtcGFyYW0nO1xyXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4vZGF0YS10eXBlJztcclxuaW1wb3J0IHsgRW50aXR5QXNwZWN0LCBDb21wbGV4QXNwZWN0LCBFbnRpdHksIENvbXBsZXhPYmplY3QsIFN0cnVjdHVyYWxPYmplY3QgfSBmcm9tICcuL2VudGl0eS1hc3BlY3QnO1xyXG5pbXBvcnQgeyBFbnRpdHlLZXkgfSBmcm9tICcuL2VudGl0eS1rZXknO1xyXG5pbXBvcnQgeyBWYWxpZGF0b3IgfSBmcm9tICcuL3ZhbGlkYXRlJztcclxuaW1wb3J0IHsgQnJlZXplRW51bSB9IGZyb20gJy4vZW51bSc7XHJcbmltcG9ydCB7IERhdGFTZXJ2aWNlIH0gZnJvbSAnLi9kYXRhLXNlcnZpY2UnO1xyXG5pbXBvcnQgeyBOYW1pbmdDb252ZW50aW9uIH0gZnJvbSAnLi9uYW1pbmctY29udmVudGlvbic7XHJcbmltcG9ydCB7IENzZGxNZXRhZGF0YVBhcnNlciB9IGZyb20gJy4vY3NkbC1tZXRhZGF0YS1wYXJzZXInOyAvLyBUT0RPIGlzb2xhdGUgdGhpcyBsYXRlcjtcclxuaW1wb3J0IHsgTG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zIH0gZnJvbSAnLi9sb2NhbC1xdWVyeS1jb21wYXJpc29uLW9wdGlvbnMnO1xyXG5pbXBvcnQgeyBkZWZhdWx0UHJvcGVydHlJbnRlcmNlcHRvciB9IGZyb20gJy4vZGVmYXVsdC1wcm9wZXJ0eS1pbnRlcmNlcHRvcic7XHJcblxyXG5leHBvcnQgdHlwZSBFbnRpdHlQcm9wZXJ0eSA9IERhdGFQcm9wZXJ0eSB8IE5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuZXhwb3J0IHR5cGUgU3RydWN0dXJhbFR5cGUgPSBFbnRpdHlUeXBlIHwgQ29tcGxleFR5cGU7XHJcblxyXG4vKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJU3RydWN0dXJhbFR5cGVNYXAge1xyXG4gIFtpbmRleDogc3RyaW5nXTogU3RydWN0dXJhbFR5cGU7XHJcbn1cclxuXHJcbi8vIFRPRE86IGNvbnNpZGVyIGV4cG9zaW5nIGxhdGVyXHJcbi8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElNZXRhZGF0YUpzb24ge1xyXG4gIG1ldGFkYXRhVmVyc2lvbjogc3RyaW5nO1xyXG4gIG5hbWU6IHN0cmluZztcclxuICBuYW1pbmdDb252ZW50aW9uOiBzdHJpbmc7XHJcbiAgbG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zOiBzdHJpbmc7XHJcbiAgZGF0YVNlcnZpY2VzOiBPYmplY3RbXTsgLy8gSURhdGFTZXJ2aWNlSnNvbltdXHJcbiAgc3RydWN0dXJhbFR5cGVzOiBPYmplY3RbXTsgLy8gSVN0cnVjdHVyYWxUeXBlSnNvbltdOyBcclxuICByZXNvdXJjZUVudGl0eVR5cGVNYXA6IE9iamVjdFtdOyAvLyBJUmVzb3VyY2VFbnRpdHlUeXBlSnNvbltdXHJcbiAgaW5jb21wbGV0ZVR5cGVNYXA6IE9iamVjdFtdO1xyXG59XHJcblxyXG4vKiogQ29uZmlndXJhdGlvbiBpbmZvIHRvIGJlIHBhc3NlZCB0byB0aGUgW1tNZXRhZGF0YVN0b3JlXV0gY29uc3RydWN0b3IgKi9cclxuZXhwb3J0IGludGVyZmFjZSBNZXRhZGF0YVN0b3JlQ29uZmlnIHtcclxuICAvKiogVGhlICBbW05hbWluZ0NvbnZlbnRpb25dXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBNZXRhZGF0YVN0b3JlLiAqL1xyXG4gIG5hbWluZ0NvbnZlbnRpb24/OiBOYW1pbmdDb252ZW50aW9uO1xyXG4gIC8qKiBUaGUgIFtbTG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgTWV0YWRhdGFTdG9yZS4gKi9cclxuICBsb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnM/OiBMb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnM7XHJcbiAgc2VyaWFsaXplckZuPzogKHByb3A6IEVudGl0eVByb3BlcnR5LCB2YWw6IGFueSkgPT4gYW55O1xyXG4gIG5hbWU/OiBzdHJpbmc7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgTWV0YWRhdGFGZXRjaGVkRXZlbnRBcmdzIHtcclxuICBtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlO1xyXG4gIGRhdGFTZXJ2aWNlOiBEYXRhU2VydmljZSB8IHN0cmluZztcclxuICByYXdNZXRhZGF0YTogYW55O1xyXG59XHJcblxyXG4vKipcclxuQW4gaW5zdGFuY2Ugb2YgdGhlIE1ldGFkYXRhU3RvcmUgY29udGFpbnMgYWxsIG9mIHRoZSBtZXRhZGF0YSBhYm91dCBhIGNvbGxlY3Rpb24gb2YgW1tFbnRpdHlUeXBlXV0ncy5cclxuTWV0YWRhdGFTdG9yZXMgbWF5IGJlIHNoYXJlZCBhY3Jvc3MgW1tFbnRpdHlNYW5hZ2VyXV0ncy4gIElmIGFuIEVudGl0eU1hbmFnZXIgaXMgY3JlYXRlZCB3aXRob3V0IGFuXHJcbmV4cGxpY2l0IE1ldGFkYXRhU3RvcmUsIHRoZSBNZXRhZGF0YVN0b3JlIGZyb20gdGhlIE1ldGFkYXRhU3RvcmUuZGVmYXVsdEluc3RhbmNlIHByb3BlcnR5IHdpbGwgYmUgdXNlZC5cclxuQGR5bmFtaWNcclxuKiovXHJcbmV4cG9ydCBjbGFzcyBNZXRhZGF0YVN0b3JlIHtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfJHR5cGVOYW1lOiBzdHJpbmc7IC8vIG9uIHByb3RvXHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIHN0YXRpYyBfX2lkID0gMDtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBzdGF0aWMgQU5PTlRZUEVfUFJFRklYID0gXCJfSUJfXCI7XHJcbiAgLyoqIFRoZSB2ZXJzaW9uIG9mIGFueSBNZXRhZGF0YVN0b3JlcyBjcmVhdGVkIGJ5IHRoaXMgY2xhc3MgKi9cclxuICBzdGF0aWMgbWV0YWRhdGFWZXJzaW9uID0gJzEuMC41JztcclxuXHJcbiAgbmFtZTogc3RyaW5nO1xyXG4gIGRhdGFTZXJ2aWNlczogRGF0YVNlcnZpY2VbXTtcclxuXHJcbiAgLyoqIFRoZSAgW1tOYW1pbmdDb252ZW50aW9uXV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgTWV0YWRhdGFTdG9yZS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIG5hbWluZ0NvbnZlbnRpb246IE5hbWluZ0NvbnZlbnRpb247XHJcbiAgLyoqIFRoZSAgW1tMb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnNdXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBNZXRhZGF0YVN0b3JlLiBfX1JlYWQgT25seV9fICovXHJcbiAgbG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zOiBMb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnM7XHJcbiAgc2VyaWFsaXplckZuPzogKHByb3A6IEVudGl0eVByb3BlcnR5LCB2YWw6IGFueSkgPT4gYW55O1xyXG4gIC8qKlxyXG4gIEFuIFtbQnJlZXplRXZlbnRdXSB0aGF0IGZpcmVzIGFmdGVyIGEgTWV0YWRhdGFTdG9yZSBoYXMgY29tcGxldGVkIGZldGNoaW5nIG1ldGFkYXRhIGZyb20gYSByZW1vdGUgc2VydmljZS5cclxuICBcclxuICBAZXZlbnRBcmdzIC1cclxuICAgIC0gbWV0YWRhdGFTdG9yZSAtIFRoZSBNZXRhZGF0YVN0b3JlIGludG8gd2hpY2ggdGhlIG1ldGFkYXRhIHdhcyBmZXRjaGVkLlxyXG4gICAgLSBkYXRhU2VydmljZSAtIFRoZSBbW0RhdGFTZXJ2aWNlXV0gdGhhdCBtZXRhZGF0YSB3YXMgZmV0Y2hlZCBmcm9tLlxyXG4gICAgLSByYXdNZXRhZGF0YSAtIHtPYmplY3R9IFRoZSByYXcgbWV0YWRhdGEgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmljZS4gKEl0IHdpbGwgaGF2ZSBhbHJlYWR5IGJlZW4gcHJvY2Vzc2VkIGJ5IHRoaXMgcG9pbnQpLlxyXG4gID4gICAgICBsZXQgbXMgPSBteUVudGl0eU1hbmFnZXIubWV0YWRhdGFTdG9yZTtcclxuICA+ICAgICAgbXMubWV0YWRhdGFGZXRjaGVkLnN1YnNjcmliZShmdW5jdGlvbihhcmdzKSB7XHJcbiAgPiAgICAgICAgICBsZXQgbWV0YWRhdGFTdG9yZSA9IGFyZ3MubWV0YWRhdGFTdG9yZTtcclxuICA+ICAgICAgICAgIGxldCBkYXRhU2VydmljZSA9IGFyZ3MuZGF0YVNlcnZpY2U7XHJcbiAgPiAgICAgIH0pO1xyXG4gIEBldmVudFxyXG4gICoqL1xyXG4gIG1ldGFkYXRhRmV0Y2hlZDogQnJlZXplRXZlbnQ8TWV0YWRhdGFGZXRjaGVkRXZlbnRBcmdzPjtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfcmVzb3VyY2VFbnRpdHlUeXBlTWFwOiB7fTtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfZW50aXR5VHlwZVJlc291cmNlTWFwOiB7fTtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfc3RydWN0dXJhbFR5cGVNYXA6IElTdHJ1Y3R1cmFsVHlwZU1hcDsgLy8ga2V5IGlzIHF1YWxpZmllZCBzdHJ1Y3R1cmFsdHlwZSBuYW1lIC0gdmFsdWUgaXMgc3RydWN0dXJhbFR5cGUuICggc3RydWN0dXJhbCA9IGVudGl0eVR5cGUgb3IgY29tcGxleFR5cGUpLlxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqKi9cclxuICBfc2hvcnROYW1lTWFwOiB7fTsgLy8ga2V5IGlzIHNob3J0TmFtZSwgdmFsdWUgaXMgcXVhbGlmaWVkIG5hbWUgLSBkb2VzIG5vdCBuZWVkIHRvIGJlIHNlcmlhbGl6ZWQuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICoqL1xyXG4gIF9jdG9yUmVnaXN0cnk6IHt9OyAvLyBrZXkgaXMgZWl0aGVyIHNob3J0IG9yIHF1YWwgdHlwZSBuYW1lIC0gdmFsdWUgaXMgY3RvcjtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKiovXHJcbiAgX2luY29tcGxldGVUeXBlTWFwOiB7fTsgLy8ga2V5IGlzIGVudGl0eVR5cGVOYW1lOyB2YWx1ZSBpcyBhcnJheSBvZiBuYXYgcHJvcHNcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKiovXHJcbiAgX2luY29tcGxldGVDb21wbGV4VHlwZU1hcDoge307IC8vXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICoqL1xyXG4gIF9kZWZlcnJlZFR5cGVzOiB7fTtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKiovXHJcbiAgX2lkOiBudW1iZXI7XHJcblxyXG4gIC8qKlxyXG4gIENvbnN0cnVjdHMgYSBuZXcgTWV0YWRhdGFTdG9yZS5cclxuICBcclxuICA+ICAgICBsZXQgbXMgPSBuZXcgTWV0YWRhdGFTdG9yZSgpO1xyXG5cclxuICBUaGUgc3RvcmUgY2FuIHRoZW4gYmUgYXNzb2NpYXRlZCB3aXRoIGFuIEVudGl0eU1hbmFnZXJcclxuICA+ICAgICBsZXQgZW50aXR5TWFuYWdlciA9IG5ldyBFbnRpdHlNYW5hZ2VyKCB7XHJcbiAgPiAgICAgICAgIHNlcnZpY2VOYW1lOiBcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIsIFxyXG4gID4gICAgICAgICBtZXRhZGF0YVN0b3JlOiBtcyBcclxuICA+ICAgICB9KTtcclxuXHJcbiAgb3IgZm9yIGFuIGV4aXN0aW5nIEVudGl0eU1hbmFnZXJcclxuICA+ICAgIC8vIEFzc3VtZSBlbTEgaXMgYW4gZXhpc3RpbmcgRW50aXR5TWFuYWdlclxyXG4gID4gICAgZW0xLnNldFByb3BlcnRpZXMoIHsgbWV0YWRhdGFTdG9yZTogbXMgfSk7XHJcbiAgXHJcbiAgQHBhcmFtIGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gc2V0dGluZ3MgLlxyXG4gICAgLSBuYW1pbmdDb252ZW50aW9uIC0gKGRlZmF1bHQ9TmFtaW5nQ29udmVudGlvbi5kZWZhdWx0SW5zdGFuY2UpIE5hbWluZ0NvbnZlbnRpb24gdG8gYmUgdXNlZCBpbiBtYXBwaW5nIHByb3BlcnR5IG5hbWVzXHJcbiAgYmV0d2VlbiBjbGllbnQgYW5kIHNlcnZlci4gVXNlcyB0aGUgTmFtaW5nQ29udmVudGlvbi5kZWZhdWx0SW5zdGFuY2UgaWYgbm90IHNwZWNpZmllZC5cclxuICAgIC0gbG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zIC0gKGRlZmF1bHQ9TG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zLmRlZmF1bHRJbnN0YW5jZSkgVGhlIExvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucyB0byBiZVxyXG4gIHVzZWQgd2hlbiBwZXJmb3JtaW5nIFwibG9jYWwgcXVlcmllc1wiIGluIG9yZGVyIHRvIG1hdGNoIHRoZSBzZW1hbnRpY3Mgb2YgcXVlcmllcyBhZ2FpbnN0IGEgcmVtb3RlIHNlcnZpY2UuXHJcbiAgICAtIHNlcmlhbGl6ZXJGbiAtIEEgZnVuY3Rpb24gdGhhdCBpcyB1c2VkIHRvIG1lZGlhdGUgdGhlIHNlcmlhbGl6YXRpb24gb2YgaW5zdGFuY2VzIG9mIHRoaXMgdHlwZS5cclxuICAqKi9cclxuICBjb25zdHJ1Y3Rvcihjb25maWc/OiBNZXRhZGF0YVN0b3JlQ29uZmlnKSB7XHJcbiAgICBjb25maWcgPSBjb25maWcgfHwge307XHJcbiAgICBhc3NlcnRDb25maWcoY29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcIm5hbWluZ0NvbnZlbnRpb25cIikuaXNPcHRpb25hbCgpLmlzSW5zdGFuY2VPZihOYW1pbmdDb252ZW50aW9uKS53aXRoRGVmYXVsdChOYW1pbmdDb252ZW50aW9uLmRlZmF1bHRJbnN0YW5jZSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJsb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnNcIikuaXNPcHRpb25hbCgpLmlzSW5zdGFuY2VPZihMb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnMpLndpdGhEZWZhdWx0KExvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucy5kZWZhdWx0SW5zdGFuY2UpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwic2VyaWFsaXplckZuXCIpLmlzT3B0aW9uYWwoKS5pc0Z1bmN0aW9uKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG4gICAgdGhpcy5kYXRhU2VydmljZXMgPSBbXTsgLy8gYXJyYXkgb2YgZGF0YVNlcnZpY2VzO1xyXG4gICAgdGhpcy5fcmVzb3VyY2VFbnRpdHlUeXBlTWFwID0ge307IC8vIGtleSBpcyByZXNvdXJjZSBuYW1lIC0gdmFsdWUgaXMgcXVhbGlmaWVkIGVudGl0eVR5cGUgbmFtZVxyXG4gICAgdGhpcy5fc3RydWN0dXJhbFR5cGVNYXAgPSB7fTsgLy8ga2V5IGlzIHF1YWxpZmllZCBzdHJ1Y3R1cmFsdHlwZSBuYW1lIC0gdmFsdWUgaXMgc3RydWN0dXJhbFR5cGUuICggc3RydWN0dXJhbCA9IGVudGl0eVR5cGUgb3IgY29tcGxleFR5cGUpLlxyXG4gICAgdGhpcy5fc2hvcnROYW1lTWFwID0ge307IC8vIGtleSBpcyBzaG9ydE5hbWUsIHZhbHVlIGlzIHF1YWxpZmllZCBuYW1lIC0gZG9lcyBub3QgbmVlZCB0byBiZSBzZXJpYWxpemVkLlxyXG4gICAgdGhpcy5fY3RvclJlZ2lzdHJ5ID0ge307IC8vIGtleSBpcyBlaXRoZXIgc2hvcnQgb3IgcXVhbCB0eXBlIG5hbWUgLSB2YWx1ZSBpcyBjdG9yO1xyXG5cclxuICAgIHRoaXMuX2luY29tcGxldGVUeXBlTWFwID0ge307IC8vIGtleSBpcyBlbnRpdHlUeXBlTmFtZTsgdmFsdWUgaXMgYXJyYXkgb2YgbmF2IHByb3BzXHJcbiAgICB0aGlzLl9pbmNvbXBsZXRlQ29tcGxleFR5cGVNYXAgPSB7fTsgLy8ga2V5IGlzIGNvbXBsZXhUeXBlTmFtZTsgdmFsdWUgaXMgYXJyYXkgb2YgY29tcGxleFR5cGUgcHJvcHNcclxuICAgIHRoaXMuX2lkID0gTWV0YWRhdGFTdG9yZS5fX2lkKys7XHJcbiAgICB0aGlzLm1ldGFkYXRhRmV0Y2hlZCA9IG5ldyBCcmVlemVFdmVudChcIm1ldGFkYXRhRmV0Y2hlZFwiLCB0aGlzKTtcclxuXHJcbiAgfVxyXG5cclxuICAvLyBuZWVkcyB0byBiZSBtYWRlIGF2YWlsIHRvIGRhdGFTZXJ2aWNlLnh4eCBmaWxlc1xyXG4gIHN0YXRpYyBub3JtYWxpemVUeXBlTmFtZSA9IGNvcmUubWVtb2l6ZShmdW5jdGlvbiAocmF3VHlwZU5hbWU6IHN0cmluZykge1xyXG4gICAgcmV0dXJuIHJhd1R5cGVOYW1lICYmIE1ldGFkYXRhU3RvcmUucGFyc2VUeXBlTmFtZShyYXdUeXBlTmFtZSkudHlwZU5hbWU7XHJcbiAgfSk7XHJcbiAgLy8gZm9yIGRlYnVnZ2luZyB1c2UgdGhlIGxpbmUgYmVsb3cgaW5zdGVhZC5cclxuICAvL2N0b3Iubm9ybWFsaXplVHlwZU5hbWUgPSBmdW5jdGlvbiAocmF3VHlwZU5hbWUpIHsgcmV0dXJuIHBhcnNlVHlwZU5hbWUocmF3VHlwZU5hbWUpLnR5cGVOYW1lOyB9O1xyXG5cclxuICAvKipcclxuICBHZW5lcmFsIHB1cnBvc2UgcHJvcGVydHkgc2V0IG1ldGhvZFxyXG4gIFxyXG4gID4gICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgIGVtMS5tZXRhZGF0YVN0b3JlLnNldFByb3BlcnRpZXMoIHtcclxuICA+ICAgICAgICAgdmVyc2lvbjogXCI2LjEuM1wiLFxyXG4gID4gICAgICAgICBzZXJpYWxpemVyRm46IGZ1bmN0aW9uKHByb3AsIHZhbHVlKSB7XHJcbiAgPiAgICAgICAgIHJldHVybiAocHJvcC5pc1VubWFwcGVkKSA/IHVuZGVmaW5lZCA6IHZhbHVlO1xyXG4gID4gICAgICAgICB9XHJcbiAgPiAgICAgKX07XHJcbiAgQHBhcmFtIGNvbmZpZyAtICBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgc2VsZWN0ZWQgcHJvcGVydGllcyBhbmQgdmFsdWVzIHRvIHNldC5cclxuICAqKi9cclxuICBzZXRQcm9wZXJ0aWVzKGNvbmZpZzogTWV0YWRhdGFTdG9yZUNvbmZpZykge1xyXG4gICAgYXNzZXJ0Q29uZmlnKGNvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJuYW1lXCIpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwic2VyaWFsaXplckZuXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQWRkcyBhIERhdGFTZXJ2aWNlIHRvIHRoaXMgTWV0YWRhdGFTdG9yZS4gSWYgYSBEYXRhU2VydmljZSB3aXRoIHRoZSBzYW1lIHNlcnZpY2VOYW1lIGlzIGFscmVhZHlcclxuICBpbiB0aGUgTWV0YWRhdGFTdG9yZSBhbiBleGNlcHRpb24gd2lsbCBiZSB0aHJvd24uXHJcbiAgQHBhcmFtIGRhdGFTZXJ2aWNlIC0gVGhlIFtbRGF0YVNlcnZpY2VdXSB0byBhZGRcclxuICBAcGFyYW0gc2hvdWxkT3ZlcndyaXRlIC0gKGRlZmF1bHQ9ZmFsc2UpIFBlcm1pdCBvdmVyd3JpdGUgb2YgZXhpc3RpbmcgRGF0YVNlcnZpY2UgcmF0aGVyIHRoYW4gdGhyb3cgZXhjZXB0aW9uXHJcbiAgKiovXHJcbiAgYWRkRGF0YVNlcnZpY2UoZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlLCBzaG91bGRPdmVyd3JpdGU/OiBib29sZWFuKSB7XHJcbiAgICBhc3NlcnRQYXJhbShkYXRhU2VydmljZSwgXCJkYXRhU2VydmljZVwiKS5pc0luc3RhbmNlT2YoRGF0YVNlcnZpY2UpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShzaG91bGRPdmVyd3JpdGUsIFwic2hvdWxkT3ZlcndyaXRlXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgbGV0IGl4ID0gdGhpcy5fZ2V0RGF0YVNlcnZpY2VJbmRleChkYXRhU2VydmljZS5zZXJ2aWNlTmFtZSk7XHJcbiAgICBpZiAoaXggPj0gMCkge1xyXG4gICAgICBpZiAoISFzaG91bGRPdmVyd3JpdGUpIHtcclxuICAgICAgICB0aGlzLmRhdGFTZXJ2aWNlc1tpeF0gPSBkYXRhU2VydmljZTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBIGRhdGFTZXJ2aWNlIHdpdGggdGhpcyBuYW1lICdcIiArIGRhdGFTZXJ2aWNlLnNlcnZpY2VOYW1lICsgXCInIGFscmVhZHkgZXhpc3RzIGluIHRoaXMgTWV0YWRhdGFTdG9yZVwiKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5kYXRhU2VydmljZXMucHVzaChkYXRhU2VydmljZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfZ2V0RGF0YVNlcnZpY2VJbmRleChzZXJ2aWNlTmFtZTogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4gY29yZS5hcnJheUluZGV4T2YodGhpcy5kYXRhU2VydmljZXMsIGZ1bmN0aW9uIChkcykge1xyXG4gICAgICByZXR1cm4gZHMuc2VydmljZU5hbWUgPT09IHNlcnZpY2VOYW1lO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBBZGRzIGFuIEVudGl0eVR5cGUgdG8gdGhpcyBNZXRhZGF0YVN0b3JlLiAgTm8gYWRkaXRpb25hbCBwcm9wZXJ0aWVzIG1heSBiZSBhZGRlZCB0byB0aGUgRW50aXR5VHlwZSBhZnRlciBpdHMgaGFzXHJcbiAgYmVlbiBhZGRlZCB0byB0aGUgTWV0YWRhdGFTdG9yZS5cclxuICBAcGFyYW0gc3RydWN0dXJhbFR5cGUgLSBUaGUgRW50aXR5VHlwZSBvciBDb21wbGV4VHlwZSB0byBhZGRcclxuICAqKi9cclxuICBhZGRFbnRpdHlUeXBlKHN0eXBlOiBTdHJ1Y3R1cmFsVHlwZSB8IEVudGl0eVR5cGVDb25maWcgfCBDb21wbGV4VHlwZUNvbmZpZykge1xyXG4gICAgbGV0IHN0cnVjdHVyYWxUeXBlOiBTdHJ1Y3R1cmFsVHlwZTtcclxuICAgIGlmIChzdHlwZSBpbnN0YW5jZW9mIEVudGl0eVR5cGUgfHwgc3R5cGUgaW5zdGFuY2VvZiBDb21wbGV4VHlwZSkge1xyXG4gICAgICBzdHJ1Y3R1cmFsVHlwZSA9IHN0eXBlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgc3RydWN0dXJhbFR5cGUgPSAoc3R5cGUgYXMgYW55KS5pc0NvbXBsZXhUeXBlID8gbmV3IENvbXBsZXhUeXBlKHN0eXBlKSA6IG5ldyBFbnRpdHlUeXBlKHN0eXBlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBpZiAoIXN0cnVjdHVyYWxUeXBlLmlzQ29tcGxleFR5cGUpIHsgLy8gc2FtZSBhcyBiZWxvdyBidXQgaXNuJ3QgYSAndHlwZSBndWFyZCdcclxuICAgIGlmIChzdHJ1Y3R1cmFsVHlwZSBpbnN0YW5jZW9mIEVudGl0eVR5cGUpIHtcclxuICAgICAgaWYgKHN0cnVjdHVyYWxUeXBlLmJhc2VUeXBlTmFtZSAmJiAhc3RydWN0dXJhbFR5cGUuYmFzZUVudGl0eVR5cGUpIHtcclxuICAgICAgICBsZXQgYmFzZUVudGl0eVR5cGUgPSB0aGlzLl9nZXRTdHJ1Y3R1cmFsVHlwZShzdHJ1Y3R1cmFsVHlwZS5iYXNlVHlwZU5hbWUsIHRydWUpO1xyXG4gICAgICAgIC8vIHNhZmUgY2FzdCBiZWNhdXNlIHdlIGtub3cgdGhhdCBiYXNlRW50aXR5VHlwZSBtdXN0IGJlIGFuIEVudGl0eVR5cGUgaWYgdGhlIHN0cnVjdHVyYWxUeXBlIGlzIGFuIEVudGl0eVR5cGVcclxuICAgICAgICBzdHJ1Y3R1cmFsVHlwZS5fdXBkYXRlRnJvbUJhc2UoYmFzZUVudGl0eVR5cGUgYXMgRW50aXR5VHlwZSk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHN0cnVjdHVyYWxUeXBlLmtleVByb3BlcnRpZXMubGVuZ3RoID09PSAwICYmICFzdHJ1Y3R1cmFsVHlwZS5pc0Fic3RyYWN0KSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIGFkZCBcIiArIHN0cnVjdHVyYWxUeXBlLm5hbWUgK1xyXG4gICAgICAgICAgXCIgdG8gdGhpcyBNZXRhZGF0YVN0b3JlLiAgQW4gRW50aXR5VHlwZSBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIHByb3BlcnR5IGRlc2lnbmF0ZWQgYXMgYSBrZXkgcHJvcGVydHkgLSBTZWUgdGhlICdEYXRhUHJvcGVydHkuaXNQYXJ0T2ZLZXknIHByb3BlcnR5LlwiKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHN0cnVjdHVyYWxUeXBlLm1ldGFkYXRhU3RvcmUgPSB0aGlzO1xyXG4gICAgLy8gZG9uJ3QgcmVnaXN0ZXIgYW5vbiB0eXBlc1xyXG4gICAgaWYgKCEoc3RydWN0dXJhbFR5cGUgYXMgYW55KS5pc0Fub255bW91cykge1xyXG4gICAgICBpZiAodGhpcy5fc3RydWN0dXJhbFR5cGVNYXBbc3RydWN0dXJhbFR5cGUubmFtZV0pIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUeXBlIFwiICsgc3RydWN0dXJhbFR5cGUubmFtZSArIFwiIGFscmVhZHkgZXhpc3RzIGluIHRoaXMgTWV0YWRhdGFTdG9yZS5cIik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuX3N0cnVjdHVyYWxUeXBlTWFwW3N0cnVjdHVyYWxUeXBlLm5hbWVdID0gc3RydWN0dXJhbFR5cGU7XHJcbiAgICAgIHRoaXMuX3Nob3J0TmFtZU1hcFtzdHJ1Y3R1cmFsVHlwZS5zaG9ydE5hbWVdID0gc3RydWN0dXJhbFR5cGUubmFtZTtcclxuICAgIH1cclxuXHJcbiAgICBzdHJ1Y3R1cmFsVHlwZS5nZXRQcm9wZXJ0aWVzKCkuZm9yRWFjaChwID0+IHtcclxuICAgICAgc3RydWN0dXJhbFR5cGUuX3VwZGF0ZU5hbWVzKHApO1xyXG4gICAgICBpZiAoIXAuaXNVbm1hcHBlZCkge1xyXG4gICAgICAgIHN0cnVjdHVyYWxUeXBlLl9tYXBwZWRQcm9wZXJ0aWVzQ291bnQrKztcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgc3RydWN0dXJhbFR5cGUuX3VwZGF0ZUNwcygpO1xyXG5cclxuICAgIC8vICdpc0VudGl0eVR5cGUnIGlzIGEgdHlwZSBndWFyZFxyXG4gICAgaWYgKHN0cnVjdHVyYWxUeXBlIGluc3RhbmNlb2YgRW50aXR5VHlwZSkge1xyXG4gICAgICBzdHJ1Y3R1cmFsVHlwZS5fdXBkYXRlTnBzKCk7XHJcbiAgICAgIC8vIGdpdmUgdGhlIHR5cGUgaXQncyBiYXNlJ3MgcmVzb3VyY2UgbmFtZSBpZiBpdCBkb2Vzbid0IGhhdmUgaXRzIG93bi5cclxuICAgICAgbGV0IGRlZlJlc291cmNlTmFtZSA9IHN0cnVjdHVyYWxUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUgfHwgKHN0cnVjdHVyYWxUeXBlLmJhc2VFbnRpdHlUeXBlICYmIHN0cnVjdHVyYWxUeXBlLmJhc2VFbnRpdHlUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUpO1xyXG4gICAgICBpZiAoZGVmUmVzb3VyY2VOYW1lICYmICF0aGlzLmdldEVudGl0eVR5cGVOYW1lRm9yUmVzb3VyY2VOYW1lKGRlZlJlc291cmNlTmFtZSkpIHtcclxuICAgICAgICB0aGlzLnNldEVudGl0eVR5cGVGb3JSZXNvdXJjZU5hbWUoZGVmUmVzb3VyY2VOYW1lLCBzdHJ1Y3R1cmFsVHlwZS5uYW1lKTtcclxuICAgICAgfVxyXG4gICAgICBzdHJ1Y3R1cmFsVHlwZS5kZWZhdWx0UmVzb3VyY2VOYW1lID0gZGVmUmVzb3VyY2VOYW1lO1xyXG4gICAgICAvLyBjaGVjayBpZiB0aGlzIHN0cnVjdHVyYWwgdHlwZSdzIG5hbWUsIHNob3J0IHZlcnNpb24gb3IgcXVhbGlmaWVkIHZlcnNpb24gaGFzIGEgcmVnaXN0ZXJlZCBjdG9yLlxyXG4gICAgICBzdHJ1Y3R1cmFsVHlwZS5nZXRFbnRpdHlDdG9yKCk7XHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcblxyXG4gIC8qKlxyXG4gIEV4cG9ydHMgdGhpcyBNZXRhZGF0YVN0b3JlIHRvIGEgc2VyaWFsaXplZCBzdHJpbmcgYXBwcm9wcmlhdGUgZm9yIGxvY2FsIHN0b3JhZ2UuICAgVGhpcyBvcGVyYXRpb24gaXMgYWxzbyBjYWxsZWRcclxuICBpbnRlcm5hbGx5IHdoZW4gZXhwb3J0aW5nIGFuIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBtcyBpcyBhIHByZXZpb3VzbHkgY3JlYXRlZCBNZXRhZGF0YVN0b3JlXHJcbiAgPiAgICAgIGxldCBtZXRhZGF0YUFzU3RyaW5nID0gbXMuZXhwb3J0TWV0YWRhdGEoKTtcclxuICA+ICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKFwibWV0YWRhdGFcIiwgbWV0YWRhdGFBc1N0cmluZyk7XHJcbiAgPiAgICAgIC8vIGFuZCBsYXRlciwgdXN1YWxseSBpbiBhIGRpZmZlcmVudCBzZXNzaW9uIGltcG9ydGVkXHJcbiAgPiAgICAgIGxldCBtZXRhZGF0YUZyb21TdG9yYWdlID0gd2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKFwibWV0YWRhdGFcIik7XHJcbiAgPiAgICAgIGxldCBuZXdNZXRhZGF0YVN0b3JlID0gbmV3IE1ldGFkYXRhU3RvcmUoKTtcclxuICA+ICAgICAgbmV3TWV0YWRhdGFTdG9yZS5pbXBvcnRNZXRhZGF0YShtZXRhZGF0YUZyb21TdG9yYWdlKTtcclxuICBAcmV0dXJuIEEgc2VyaWFsaXplZCB2ZXJzaW9uIG9mIHRoaXMgTWV0YWRhdGFTdG9yZSB0aGF0IG1heSBiZSBzdG9yZWQgbG9jYWxseSBhbmQgbGF0ZXIgcmVzdG9yZWQuXHJcbiAgKiovXHJcbiAgZXhwb3J0TWV0YWRhdGEoKSB7XHJcbiAgICBsZXQgcmVzdWx0ID0gSlNPTi5zdHJpbmdpZnkoe1xyXG4gICAgICBcIm1ldGFkYXRhVmVyc2lvblwiOiBNZXRhZGF0YVN0b3JlLm1ldGFkYXRhVmVyc2lvbixcclxuICAgICAgXCJuYW1lXCI6IHRoaXMubmFtZSxcclxuICAgICAgXCJuYW1pbmdDb252ZW50aW9uXCI6IHRoaXMubmFtaW5nQ29udmVudGlvbi5uYW1lLFxyXG4gICAgICBcImxvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9uc1wiOiB0aGlzLmxvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucy5uYW1lLFxyXG4gICAgICBcImRhdGFTZXJ2aWNlc1wiOiB0aGlzLmRhdGFTZXJ2aWNlcyxcclxuICAgICAgXCJzdHJ1Y3R1cmFsVHlwZXNcIjogY29yZS5vYmplY3RNYXAodGhpcy5fc3RydWN0dXJhbFR5cGVNYXApLFxyXG4gICAgICBcInJlc291cmNlRW50aXR5VHlwZU1hcFwiOiB0aGlzLl9yZXNvdXJjZUVudGl0eVR5cGVNYXBcclxuICAgIH0sIG51bGwsIGNvbmZpZy5zdHJpbmdpZnlQYWQpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEltcG9ydHMgYSBwcmV2aW91c2x5IGV4cG9ydGVkIHNlcmlhbGl6ZWQgTWV0YWRhdGFTdG9yZSBpbnRvIHRoaXMgTWV0YWRhdGFTdG9yZS5cclxuICAgIFxyXG4gID4gICAgICAvLyBhc3N1bWUgbXMgaXMgYSBwcmV2aW91c2x5IGNyZWF0ZWQgTWV0YWRhdGFTdG9yZVxyXG4gID4gICAgICBsZXQgbWV0YWRhdGFBc1N0cmluZyA9IG1zLmV4cG9ydE1ldGFkYXRhKCk7XHJcbiAgPiAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2Uuc2V0SXRlbShcIm1ldGFkYXRhXCIsIG1ldGFkYXRhQXNTdHJpbmcpO1xyXG4gID4gICAgICAvLyBhbmQgbGF0ZXIsIHVzdWFsbHkgaW4gYSBkaWZmZXJlbnQgc2Vzc2lvblxyXG4gID4gICAgICBsZXQgbWV0YWRhdGFGcm9tU3RvcmFnZSA9IHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbShcIm1ldGFkYXRhXCIpO1xyXG4gID4gICAgICBsZXQgbmV3TWV0YWRhdGFTdG9yZSA9IG5ldyBNZXRhZGF0YVN0b3JlKCk7XHJcbiAgPiAgICAgIG5ld01ldGFkYXRhU3RvcmUuaW1wb3J0TWV0YWRhdGEobWV0YWRhdGFGcm9tU3RvcmFnZSk7XHJcbiAgQHBhcmFtIGV4cG9ydGVkTWV0YWRhdGEgLSBBIHByZXZpb3VzbHkgZXhwb3J0ZWQgTWV0YWRhdGFTdG9yZS5cclxuICBAcGFyYW0gYWxsb3dNZXJnZSAtICBBbGxvd3MgY3VzdG9tIG1ldGFkYXRhIHRvIGJlIG1lcmdlZCBpbnRvIGV4aXN0aW5nIG1ldGFkYXRhIHR5cGVzLlxyXG4gIEByZXR1cm4gVGhpcyBNZXRhZGF0YVN0b3JlLlxyXG4gIEBjaGFpbmFibGVcclxuICAqKi9cclxuICBpbXBvcnRNZXRhZGF0YShleHBvcnRlZE1ldGFkYXRhOiBzdHJpbmcgfCBPYmplY3QsIGFsbG93TWVyZ2U6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oYWxsb3dNZXJnZSwgXCJhbGxvd01lcmdlXCIpLmlzT3B0aW9uYWwoKS5pc0Jvb2xlYW4oKS5jaGVjaygpO1xyXG4gICAgdGhpcy5fZGVmZXJyZWRUeXBlcyA9IHt9O1xyXG4gICAgLy8gaW5zdXJlIHRoYXQgd2UgZG9uJ3QgbXV0YXRlIGluY29taW5nIGV4cG9ydGVkTWV0YWRhdGEgKCBpZiBpdHMgYW4gb2JqZWN0KVxyXG4gICAgbGV0IG1ldGFkYXRhQXNTdHJpbmcgPSAodHlwZW9mIChleHBvcnRlZE1ldGFkYXRhKSA9PT0gXCJzdHJpbmdcIikgPyBleHBvcnRlZE1ldGFkYXRhIDogSlNPTi5zdHJpbmdpZnkoZXhwb3J0ZWRNZXRhZGF0YSk7XHJcbiAgICBjb25zdCBtZXRhZGF0YUpzb24gPSBKU09OLnBhcnNlKG1ldGFkYXRhQXNTdHJpbmcpO1xyXG5cclxuICAgIGlmIChtZXRhZGF0YUpzb24uc2NoZW1hKSB7XHJcbiAgICAgIHJldHVybiBDc2RsTWV0YWRhdGFQYXJzZXIucGFyc2UodGhpcywgbWV0YWRhdGFKc29uLnNjaGVtYSwgbWV0YWRhdGFKc29uLmFsdE1ldGFkYXRhKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQganNvbiA9IG1ldGFkYXRhSnNvbiBhcyBJTWV0YWRhdGFKc29uO1xyXG4gICAgaWYgKGpzb24ubWV0YWRhdGFWZXJzaW9uICYmIGpzb24ubWV0YWRhdGFWZXJzaW9uICE9PSBNZXRhZGF0YVN0b3JlLm1ldGFkYXRhVmVyc2lvbikge1xyXG4gICAgICBsZXQgbXNnID0gY29yZS5mb3JtYXRTdHJpbmcoXCJDYW5ub3QgaW1wb3J0IG1ldGFkYXRhIHdpdGggYSBkaWZmZXJlbnQgJ21ldGFkYXRhVmVyc2lvbicgKCUxKSB0aGFuIHRoZSBjdXJyZW50ICdNZXRhZGF0YVN0b3JlLm1ldGFkYXRhVmVyc2lvbicgKCUyKSBcIixcclxuICAgICAgICBqc29uLm1ldGFkYXRhVmVyc2lvbiwgTWV0YWRhdGFTdG9yZS5tZXRhZGF0YVZlcnNpb24pO1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgbmNOYW1lID0ganNvbi5uYW1pbmdDb252ZW50aW9uO1xyXG4gICAgbGV0IGxxY29OYW1lID0ganNvbi5sb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnM7XHJcbiAgICBpZiAodGhpcy5pc0VtcHR5KCkpIHtcclxuICAgICAgdGhpcy5uYW1pbmdDb252ZW50aW9uID0gY29uZmlnLl9mZXRjaE9iamVjdChOYW1pbmdDb252ZW50aW9uLCBuY05hbWUpIHx8IHRoaXMubmFtaW5nQ29udmVudGlvbjtcclxuICAgICAgdGhpcy5sb2NhbFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnMgPSBjb25maWcuX2ZldGNoT2JqZWN0KExvY2FsUXVlcnlDb21wYXJpc29uT3B0aW9ucywgbHFjb05hbWUpIHx8IHRoaXMubG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKG5jTmFtZSAmJiB0aGlzLm5hbWluZ0NvbnZlbnRpb24ubmFtZSAhPT0gbmNOYW1lKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGltcG9ydCBtZXRhZGF0YSB3aXRoIGEgZGlmZmVyZW50ICduYW1pbmdDb252ZW50aW9uJyBmcm9tIHRoZSBjdXJyZW50IE1ldGFkYXRhU3RvcmVcIik7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGxxY29OYW1lICYmIHRoaXMubG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zLm5hbWUgIT09IGxxY29OYW1lKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGltcG9ydCBtZXRhZGF0YSB3aXRoIGRpZmZlcmVudCAnbG9jYWxRdWVyeUNvbXBhcmlzb25PcHRpb25zJyBmcm9tIHRoZSBjdXJyZW50IE1ldGFkYXRhU3RvcmVcIik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvL25vaW5zcGVjdGlvbiBKU0hpbnRcclxuICAgIGpzb24uZGF0YVNlcnZpY2VzICYmIGpzb24uZGF0YVNlcnZpY2VzLmZvckVhY2goKGRzKSA9PiB7XHJcbiAgICAgIGxldCByZWFsRHMgPSBEYXRhU2VydmljZS5mcm9tSlNPTihkcyk7XHJcbiAgICAgIHRoaXMuYWRkRGF0YVNlcnZpY2UocmVhbERzLCB0cnVlKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGpzb24uc3RydWN0dXJhbFR5cGVzICYmIGpzb24uc3RydWN0dXJhbFR5cGVzLmZvckVhY2goKHN0eXBlKSA9PiB7XHJcbiAgICAgIHN0cnVjdHVyYWxUeXBlRnJvbUpzb24odGhpcywgc3R5cGUsIGFsbG93TWVyZ2UpO1xyXG4gICAgfSk7XHJcbiAgICBjb3JlLmV4dGVuZCh0aGlzLl9yZXNvdXJjZUVudGl0eVR5cGVNYXAsIGpzb24ucmVzb3VyY2VFbnRpdHlUeXBlTWFwKTtcclxuICAgIGNvcmUuZXh0ZW5kKHRoaXMuX2luY29tcGxldGVUeXBlTWFwLCBqc29uLmluY29tcGxldGVUeXBlTWFwKTtcclxuXHJcbiAgICByZXR1cm4gdGhpcztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIENyZWF0ZXMgYSBuZXcgTWV0YWRhdGFTdG9yZSBmcm9tIGEgcHJldmlvdXNseSBleHBvcnRlZCBzZXJpYWxpemVkIE1ldGFkYXRhU3RvcmVcclxuICA+ICAgICAgLy8gYXNzdW1lIG1zIGlzIGEgcHJldmlvdXNseSBjcmVhdGVkIE1ldGFkYXRhU3RvcmVcclxuICA+ICAgICAgbGV0IG1ldGFkYXRhQXNTdHJpbmcgPSBtcy5leHBvcnRNZXRhZGF0YSgpO1xyXG4gID4gICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oXCJtZXRhZGF0YVwiLCBtZXRhZGF0YUFzU3RyaW5nKTtcclxuICA+ICAgICAgLy8gYW5kIGxhdGVyLCB1c3VhbGx5IGluIGEgZGlmZmVyZW50IHNlc3Npb25cclxuICA+ICAgICAgbGV0IG1ldGFkYXRhRnJvbVN0b3JhZ2UgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJtZXRhZGF0YVwiKTtcclxuICA+ICAgICAgbGV0IG5ld01ldGFkYXRhU3RvcmUgPSBNZXRhZGF0YVN0b3JlLmltcG9ydE1ldGFkYXRhKG1ldGFkYXRhRnJvbVN0b3JhZ2UpO1xyXG4gIEBwYXJhbSBleHBvcnRlZFN0cmluZyAtIEEgcHJldmlvdXNseSBleHBvcnRlZCBNZXRhZGF0YVN0b3JlLlxyXG4gIEByZXR1cm4gQSBuZXcgTWV0YWRhdGFTdG9yZS5cclxuICAqKi9cclxuICBzdGF0aWMgaW1wb3J0TWV0YWRhdGEoZXhwb3J0ZWRTdHJpbmc6IHN0cmluZykge1xyXG4gICAgbGV0IG1zID0gbmV3IE1ldGFkYXRhU3RvcmUoKTtcclxuICAgIG1zLmltcG9ydE1ldGFkYXRhKGV4cG9ydGVkU3RyaW5nKTtcclxuICAgIHJldHVybiBtcztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgd2hldGhlciBNZXRhZGF0YSBoYXMgYmVlbiByZXRyaWV2ZWQgZm9yIGEgc3BlY2lmaWVkIHNlcnZpY2UgbmFtZS5cclxuICA+ICAgICAgLy8gQXNzdW1lIGVtMSBpcyBhbiBleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICBpZiAoIWVtMS5tZXRhZGF0YVN0b3JlLmhhc01ldGFkYXRhRm9yKFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIikpKSB7XHJcbiAgPiAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgaW50ZXJlc3RpbmdcclxuICA+ICAgICAgfVxyXG4gIEBwYXJhbSBzZXJ2aWNlTmFtZSAtIFRoZSBzZXJ2aWNlIG5hbWUuXHJcbiAgQHJldHVybiBXaGV0aGVyIG1ldGFkYXRhIGhhcyBhbHJlYWR5IGJlZW4gcmV0cmlldmVkIGZvciB0aGUgc3BlY2lmaWVkIHNlcnZpY2UgbmFtZS5cclxuICAqKi9cclxuICBoYXNNZXRhZGF0YUZvcihzZXJ2aWNlTmFtZTogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4gISF0aGlzLmdldERhdGFTZXJ2aWNlKHNlcnZpY2VOYW1lKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgdGhlIERhdGFTZXJ2aWNlIGZvciBhIHNwZWNpZmllZCBzZXJ2aWNlIG5hbWVcclxuICA+ICAgICAgLy8gQXNzdW1lIGVtMSBpcyBhbiBleGlzdGluZyBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICBsZXQgZHMgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXREYXRhU2VydmljZShcImJyZWV6ZS9Ob3J0aHdpbmRJQk1vZGVsXCIpO1xyXG4gID4gICAgICBsZXQgYWRhcHRlck5hbWUgPSBkcy5hZGFwdGVyTmFtZTsgLy8gbWF5IGJlIG51bGxcclxuICBAcGFyYW0gc2VydmljZU5hbWUgLSBUaGUgc2VydmljZSBuYW1lLlxyXG4gIEByZXR1cm4gVGhlIERhdGFTZXJ2aWNlIHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLlxyXG4gICoqL1xyXG4gIGdldERhdGFTZXJ2aWNlKHNlcnZpY2VOYW1lOiBzdHJpbmcpIHtcclxuICAgIGFzc2VydFBhcmFtKHNlcnZpY2VOYW1lLCBcInNlcnZpY2VOYW1lXCIpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuXHJcbiAgICBzZXJ2aWNlTmFtZSA9IERhdGFTZXJ2aWNlLl9ub3JtYWxpemVTZXJ2aWNlTmFtZShzZXJ2aWNlTmFtZSk7XHJcbiAgICByZXR1cm4gY29yZS5hcnJheUZpcnN0KHRoaXMuZGF0YVNlcnZpY2VzLCBmdW5jdGlvbiAoZHM6IERhdGFTZXJ2aWNlKSB7XHJcbiAgICAgIHJldHVybiBkcy5zZXJ2aWNlTmFtZSA9PT0gc2VydmljZU5hbWU7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEZldGNoZXMgdGhlIG1ldGFkYXRhIGZvciBhIHNwZWNpZmllZCAnc2VydmljZScuIFRoaXMgbWV0aG9kIGlzIGF1dG9tYXRpY2FsbHkgY2FsbGVkXHJcbiAgaW50ZXJuYWxseSBieSBhbiBFbnRpdHlNYW5hZ2VyIGJlZm9yZSBpdHMgZmlyc3QgcXVlcnkgYWdhaW5zdCBhIG5ldyBzZXJ2aWNlLiBfX0FzeW5jX19cclxuXHJcbiAgVXN1YWxseSB5b3Ugd2lsbCBub3QgYWN0dWFsbHkgcHJvY2VzcyB0aGUgcmVzdWx0cyBvZiBhIGZldGNoTWV0YWRhdGEgY2FsbCBkaXJlY3RseSwgYnV0IHdpbGwgaW5zdGVhZFxyXG4gIGFzayBmb3IgdGhlIG1ldGFkYXRhIGZyb20gdGhlIEVudGl0eU1hbmFnZXIgYWZ0ZXIgdGhlIGZldGNoTWV0YWRhdGEgY2FsbCByZXR1cm5zLlxyXG4gID4gICAgICBsZXQgbXMgPSBuZXcgTWV0YWRhdGFTdG9yZSgpO1xyXG4gID4gICAgICAvLyBvciBtb3JlIGNvbW1vbmx5XHJcbiAgPiAgICAgIC8vIGxldCBtcyA9IGFuRW50aXR5TWFuYWdlci5tZXRhZGF0YVN0b3JlO1xyXG4gID4gICAgICBtcy5mZXRjaE1ldGFkYXRhKFwiYnJlZXplL05vcnRod2luZElCTW9kZWxcIikudGhlbihmdW5jdGlvbihyYXdNZXRhZGF0YSkge1xyXG4gID4gICAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgd2l0aCB0aGUgbWV0YWRhdGFcclxuICA+ICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oZXhjZXB0aW9uKSB7XHJcbiAgPiAgICAgICAgICAvLyBoYW5kbGUgZXhjZXB0aW9uIGhlcmVcclxuICA+ICAgICAgfSk7XHJcbiAgQHBhcmFtIGRhdGFTZXJ2aWNlIC0gIEVpdGhlciBhIERhdGFTZXJ2aWNlIG9yIGp1c3QgdGhlIG5hbWUgb2YgdGhlIERhdGFTZXJ2aWNlIHRvIGZldGNoIG1ldGFkYXRhIGZvci5cclxuICBAcGFyYW0gY2FsbGJhY2sgLSBGdW5jdGlvbiBjYWxsZWQgb24gc3VjY2Vzcy5cclxuICBAcGFyYW0gZXJyb3JDYWxsYmFjayAtIEZ1bmN0aW9uIGNhbGxlZCBvbiBmYWlsdXJlLlxyXG4gIEByZXR1cm4gUHJvbWlzZVxyXG4gICoqL1xyXG4gIGZldGNoTWV0YWRhdGEoZGF0YVNlcnZpY2U6IHN0cmluZyB8IERhdGFTZXJ2aWNlLCBjYWxsYmFjaz86IChzY2hlbWE6IGFueSkgPT4gdm9pZCwgZXJyb3JDYWxsYmFjaz86IEVycm9yQ2FsbGJhY2spIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGFzc2VydFBhcmFtKGRhdGFTZXJ2aWNlLCBcImRhdGFTZXJ2aWNlXCIpLmlzU3RyaW5nKCkub3IoKS5pc0luc3RhbmNlT2YoRGF0YVNlcnZpY2UpLmNoZWNrKCk7XHJcbiAgICAgIGFzc2VydFBhcmFtKGNhbGxiYWNrLCBcImNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuICAgICAgYXNzZXJ0UGFyYW0oZXJyb3JDYWxsYmFjaywgXCJlcnJvckNhbGxiYWNrXCIpLmlzRnVuY3Rpb24oKS5pc09wdGlvbmFsKCkuY2hlY2soKTtcclxuXHJcbiAgICAgIGlmICh0eXBlb2YgZGF0YVNlcnZpY2UgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAvLyB1c2UgdGhlIGRhdGFTZXJ2aWNlIHdpdGggYSBtYXRjaGluZyBuYW1lIG9yIGNyZWF0ZSBhIG5ldyBvbmUuXHJcbiAgICAgICAgZGF0YVNlcnZpY2UgPSB0aGlzLmdldERhdGFTZXJ2aWNlKGRhdGFTZXJ2aWNlKSB8fCBuZXcgRGF0YVNlcnZpY2UoeyBzZXJ2aWNlTmFtZTogZGF0YVNlcnZpY2UgfSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGRhdGFTZXJ2aWNlID0gRGF0YVNlcnZpY2UucmVzb2x2ZShbZGF0YVNlcnZpY2VdKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLmhhc01ldGFkYXRhRm9yKGRhdGFTZXJ2aWNlLnNlcnZpY2VOYW1lKSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1ldGFkYXRhIGZvciBhIHNwZWNpZmljIHNlcnZpY2VOYW1lIG1heSBvbmx5IGJlIGZldGNoZWQgb25jZSBwZXIgTWV0YWRhdGFTdG9yZS4gU2VydmljZU5hbWU6IFwiICsgZGF0YVNlcnZpY2Uuc2VydmljZU5hbWUpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gZGF0YVNlcnZpY2UuYWRhcHRlckluc3RhbmNlIS5mZXRjaE1ldGFkYXRhKHRoaXMsIGRhdGFTZXJ2aWNlKS50aGVuKChyYXdNZXRhZGF0YTogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5tZXRhZGF0YUZldGNoZWQucHVibGlzaCh7IG1ldGFkYXRhU3RvcmU6IHRoaXMsIGRhdGFTZXJ2aWNlOiBkYXRhU2VydmljZSwgcmF3TWV0YWRhdGE6IHJhd01ldGFkYXRhIH0pO1xyXG4gICAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2socmF3TWV0YWRhdGEpO1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmF3TWV0YWRhdGEpO1xyXG4gICAgICB9LCBmdW5jdGlvbiAoZXJyb3I6IGFueSkge1xyXG4gICAgICAgIGlmIChlcnJvckNhbGxiYWNrKSBlcnJvckNhbGxiYWNrKGVycm9yKTtcclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xyXG4gICAgICB9KTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcblxyXG4gIC8vIFRPRE86IHN0cm9uZ2x5IHR5cGUgaW50ZXJjZXB0b3IgYmVsb3cuXHJcbiAgLyoqXHJcbiAgVXNlZCB0byByZWdpc3RlciBhIGNvbnN0cnVjdG9yIGZvciBhbiBFbnRpdHlUeXBlIHRoYXQgaXMgbm90IGtub3duIHZpYSBzdGFuZGFyZCBNZXRhZGF0YSBkaXNjb3Zlcnk7XHJcbiAgaS5lLiBhbiB1bm1hcHBlZCB0eXBlLlxyXG4gIEBwYXJhbSBlbnRpdHlDdG9yIC0gVGhlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIGZvciB0aGUgJ3VubWFwcGVkJyB0eXBlLlxyXG4gIEBwYXJhbSBpbnRlcmNlcHRvciAtIEFuIGludGVyY2VwdG9yIGZ1bmN0aW9uXHJcbiAgKiovXHJcbiAgdHJhY2tVbm1hcHBlZFR5cGUoZW50aXR5Q3RvcjogYW55LCBpbnRlcmNlcHRvcjogYW55KSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHlDdG9yLCBcImVudGl0eUN0b3JcIikuaXNGdW5jdGlvbigpLmNoZWNrKCk7XHJcbiAgICBhc3NlcnRQYXJhbShpbnRlcmNlcHRvciwgXCJpbnRlcmNlcHRvclwiKS5pc0Z1bmN0aW9uKCkuaXNPcHRpb25hbCgpLmNoZWNrKCk7XHJcbiAgICAvLyBUT0RPOiB0aGluayBhYm91dCBhZGRpbmcgdGhpcyB0byB0aGUgTWV0YWRhdGFTdG9yZS5cclxuICAgIGxldCBlbnRpdHlUeXBlID0gbmV3IEVudGl0eVR5cGUodGhpcyk7XHJcbiAgICBlbnRpdHlUeXBlLl9zZXRDdG9yKGVudGl0eUN0b3IsIGludGVyY2VwdG9yKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFByb3ZpZGVzIGEgbWVjaGFuaXNtIHRvIHJlZ2lzdGVyIGEgJ2N1c3RvbScgY29uc3RydWN0b3IgdG8gYmUgdXNlZCB3aGVuIGNyZWF0aW5nIG5ldyBpbnN0YW5jZXNcclxuICBvZiB0aGUgc3BlY2lmaWVkIGVudGl0eSB0eXBlLiAgSWYgdGhpcyBjYWxsIGlzIG5vdCBtYWRlLCBhIGRlZmF1bHQgY29uc3RydWN0b3IgaXMgY3JlYXRlZCBmb3JcclxuICB0aGUgZW50aXR5IGFzIG5lZWRlZC5cclxuICBUaGlzIGNhbGwgbWF5IGJlIG1hZGUgYmVmb3JlIG9yIGFmdGVyIHRoZSBjb3JyZXNwb25kaW5nIEVudGl0eVR5cGUgaGFzIGJlZW4gZGlzY292ZXJlZCB2aWFcclxuICBNZXRhZGF0YSBkaXNjb3ZlcnkuXHJcbiAgPiAgICAgIGxldCBDdXN0b21lciA9IGZ1bmN0aW9uICgpIHtcclxuICA+ICAgICAgICAgICAgICB0aGlzLm1pc2NEYXRhID0gXCJhc2RmXCI7XHJcbiAgPiAgICAgICAgICB9O1xyXG4gID4gICAgICBDdXN0b21lci5wcm90b3R5cGUuZG9Gb28oKSB7XHJcbiAgPiAgICAgICAgICAgICAgLi4uXHJcbiAgPiAgICAgICAgICB9XHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyO1xyXG4gID4gICAgICBlbTEubWV0YWRhdGFTdG9yZS5yZWdpc3RlckVudGl0eVR5cGVDdG9yKFwiQ3VzdG9tZXJcIiwgQ3VzdG9tZXIpO1xyXG4gID4gICAgICAvLyBhbnkgcXVlcmllcyBvciBFbnRpdHlUeXBlLmNyZWF0ZSBjYWxscyBmcm9tIHRoaXMgcG9pbnQgb24gd2lsbCBjYWxsIHRoZSBDdXN0b21lciBjb25zdHJ1Y3RvclxyXG4gID4gICAgICAvLyByZWdpc3RlcmVkIGFib3ZlLlxyXG4gIEBwYXJhbSBzdHJ1Y3R1cmFsVHlwZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgRW50aXR5VHlwZSBvciBDb21wbGV4VHlwZS5cclxuICBAcGFyYW0gYUN0b3IgLSBUaGUgY29uc3RydWN0b3IgZm9yIHRoaXMgRW50aXR5VHlwZSBvciBDb21wbGV4VHlwZTsgbWF5IGJlIG51bGwgaWYgYWxsIHlvdSB3YW50IHRvIGRvIGlzIHNldCB0aGUgbmV4dCBwYXJhbWV0ZXIuXHJcbiAgQHBhcmFtIGluaXRGbiAtIEEgZnVuY3Rpb24gb3IgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiBvbiB0aGUgZW50aXR5IHRoYXQgaXMgdG8gYmUgZXhlY3V0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhlIGVudGl0eSBoYXMgYmVlbiBjcmVhdGVkXHJcbiAgYW5kIHBvcHVsYXRlZCB3aXRoIGFueSBpbml0aWFsIHZhbHVlcy4gQ2FsbGVkIHdpdGggJ2luaXRGbihlbnRpdHkpJ1xyXG4gIEBwYXJhbSBub1RyYWNraW5nRm4gLSBBIGZ1bmN0aW9uIHRoYXQgaXMgZXhlY3V0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgYSBub1RyYWNraW5nIGVudGl0eSBoYXMgYmVlbiBjcmVhdGVkIGFuZCB3aG9zZSByZXR1cm5cclxuICB2YWx1ZSB3aWxsIGJlIHVzZWQgaW4gcGxhY2Ugb2YgdGhlIG5vVHJhY2tpbmcgZW50aXR5LlxyXG4gICoqL1xyXG4gIHJlZ2lzdGVyRW50aXR5VHlwZUN0b3Ioc3RydWN0dXJhbFR5cGVOYW1lOiBzdHJpbmcsIGFDdG9yPzogYW55LCBpbml0Rm4/OiBGdW5jdGlvbiB8IHN0cmluZywgbm9UcmFja2luZ0ZuPzogRnVuY3Rpb24pIHtcclxuICAgIGFzc2VydFBhcmFtKHN0cnVjdHVyYWxUeXBlTmFtZSwgXCJzdHJ1Y3R1cmFsVHlwZU5hbWVcIikuaXNTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oYUN0b3IsIFwiYUN0b3JcIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0oaW5pdEZuLCBcImluaXRGblwiKS5pc09wdGlvbmFsKCkuaXNGdW5jdGlvbigpLm9yKCkuaXNTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0obm9UcmFja2luZ0ZuLCBcIm5vVHJhY2tpbmdGblwiKS5pc09wdGlvbmFsKCkuaXNGdW5jdGlvbigpLmNoZWNrKCk7XHJcblxyXG4gICAgbGV0IHF1YWxpZmllZFR5cGVOYW1lID0gZ2V0UXVhbGlmaWVkVHlwZU5hbWUodGhpcywgc3RydWN0dXJhbFR5cGVOYW1lLCBmYWxzZSk7XHJcbiAgICBsZXQgdHlwZU5hbWUgPSBxdWFsaWZpZWRUeXBlTmFtZSB8fCBzdHJ1Y3R1cmFsVHlwZU5hbWU7XHJcblxyXG4gICAgaWYgKGFDdG9yKSB7XHJcbiAgICAgIGlmIChhQ3Rvci5fJHR5cGVOYW1lICYmIGFDdG9yLl8kdHlwZU5hbWUgIT09IHR5cGVOYW1lKSB7XHJcbiAgICAgICAgLy8gVE9ETzogd3JhcCB0aGlzIC0gY29uc29sZSBhbmQgZXNwZWNpYWxseSBjb25zb2xlLndhcm4gZG9lcyBub3QgZXhpc3QgaW4gYWxsIGJyb3dzZXJzLlxyXG4gICAgICAgIGNvbnNvbGUud2FybihcIlJlZ2lzdGVyaW5nIGEgY29uc3RydWN0b3IgZm9yIFwiICsgdHlwZU5hbWUgKyBcIiB0aGF0IGlzIGFscmVhZHkgdXNlZCBmb3IgXCIgKyBhQ3Rvci5fJHR5cGVOYW1lICsgXCIuXCIpO1xyXG4gICAgICB9XHJcbiAgICAgIGFDdG9yLl8kdHlwZU5hbWUgPSB0eXBlTmFtZTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLl9jdG9yUmVnaXN0cnlbdHlwZU5hbWVdID0geyBjdG9yOiBhQ3RvciwgaW5pdEZuOiBpbml0Rm4sIG5vVHJhY2tpbmdGbjogbm9UcmFja2luZ0ZuIH07XHJcbiAgICBpZiAocXVhbGlmaWVkVHlwZU5hbWUpIHtcclxuICAgICAgbGV0IHN0eXBlID0gdGhpcy5fc3RydWN0dXJhbFR5cGVNYXBbcXVhbGlmaWVkVHlwZU5hbWVdO1xyXG4gICAgICBzdHlwZSAmJiBzdHlwZS5nZXRDdG9yKHRydWUpOyAvLyB0aGlzIHdpbGwgY29tcGxldGUgdGhlIHJlZ2lzdHJhdGlvbiBpZiBhdmFpbCBub3cuXHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyB3aGV0aGVyIHRoaXMgTWV0YWRhdGFTdG9yZSBjb250YWlucyBhbnkgbWV0YWRhdGEgeWV0LlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGEgcHJlZXhpc3RpbmcgRW50aXR5TWFuYWdlcjtcclxuICA+ICAgICAgaWYgKGVtMS5tZXRhZGF0YVN0b3JlLmlzRW1wdHkoKSkge1xyXG4gID4gICAgICAgICAgLy8gZG8gc29tZXRoaW5nIGludGVyZXN0aW5nXHJcbiAgPiAgICAgIH1cclxuICAqKi9cclxuICBpc0VtcHR5KCkge1xyXG4gICAgcmV0dXJuIGNvcmUuaXNFbXB0eSh0aGlzLl9zdHJ1Y3R1cmFsVHlwZU1hcCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGFuIFtbRW50aXR5VHlwZV1dIG9yIG51bGwgZ2l2ZW4gaXRzIG5hbWUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIGxldCBvZFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRBc0VudGl0eVR5cGUoXCJPcmRlckRldGFpbFwiKTtcclxuXHJcbiAgb3IgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHR5cGUgaXMgbm90IGZvdW5kXHJcbiAgPiAgICAgIGxldCBiYWRUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0QXNFbnRpdHlUeXBlKFwiRm9vXCIsIGZhbHNlKTtcclxuICA+ICAgICAgLy8gYmFkVHlwZSB3aWxsIG5vdCBnZXQgc2V0IGFuZCBhbiBleGNlcHRpb24gd2lsbCBiZSB0aHJvd24uXHJcbiAgQHBhcmFtIHN0cnVjdHVyYWxUeXBlTmFtZSAtIEVpdGhlciB0aGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb3IgYSBzaG9ydCBuYW1lIG1heSBiZSB1c2VkLiBJZiBhIHNob3J0IG5hbWUgaXMgc3BlY2lmaWVkIGFuZCBtdWx0aXBsZSB0eXBlcyBzaGFyZVxyXG4gIHRoYXQgc2FtZSBzaG9ydCBuYW1lIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi5cclxuICBAcGFyYW0gb2tJZk5vdEZvdW5kIC0gKGRlZmF1bHQ9ZmFsc2UpIFdoZXRoZXIgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHNwZWNpZmllZCBFbnRpdHlUeXBlIGlzIG5vdCBmb3VuZC5cclxuICBAcmV0dXJuIFRoZSBFbnRpdHlUeXBlLiBDb21wbGV4VHlwZSBvciAnbnVsbCcgaWYgbm90IG5vdCBmb3VuZC5cclxuICAqKi9cclxuICBnZXRBc0VudGl0eVR5cGUodHlwZU5hbWU6IHN0cmluZywgb2tJZk5vdEZvdW5kOiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IHN0ID0gdGhpcy5nZXRTdHJ1Y3R1cmFsVHlwZSh0eXBlTmFtZSwgb2tJZk5vdEZvdW5kKTtcclxuICAgIGlmIChzdCBpbnN0YW5jZW9mIEVudGl0eVR5cGUpIHtcclxuICAgICAgcmV0dXJuIHN0IGFzIEVudGl0eVR5cGU7XHJcbiAgICB9IGVsc2UgaWYgKG9rSWZOb3RGb3VuZCkge1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGxldCBtc2cgPSBjb3JlLmZvcm1hdFN0cmluZyhcIlVuYWJsZSB0byBsb2NhdGUgYW4gJ0VudGl0eVR5cGUnIGJ5IHRoZSBuYW1lOiAnJTEnLiBCZSBzdXJlIHRvIGV4ZWN1dGUgYSBxdWVyeSBvciBjYWxsIGZldGNoTWV0YWRhdGEgZmlyc3QuXCIsIHR5cGVOYW1lKTtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGFuIFtbRW50aXR5VHlwZV1dIG9yIG51bGwgZ2l2ZW4gaXRzIG5hbWUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIGxldCBsb2NUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0QXNDb21wbGV4VHlwZShcIkxvY2F0aW9uXCIpO1xyXG5cclxuICBvciB0byB0aHJvdyBhbiBlcnJvciBpZiB0aGUgdHlwZSBpcyBub3QgZm91bmRcclxuICA+ICAgICAgbGV0IGJhZFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRBc0NvbXBsZXhUeXBlKFwiRm9vXCIsIGZhbHNlKTtcclxuICA+ICAgICAgLy8gYmFkVHlwZSB3aWxsIG5vdCBnZXQgc2V0IGFuZCBhbiBleGNlcHRpb24gd2lsbCBiZSB0aHJvd24uXHJcbiAgQHBhcmFtIHN0cnVjdHVyYWxUeXBlTmFtZSAtIEVpdGhlciB0aGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb3IgYSBzaG9ydCBuYW1lIG1heSBiZSB1c2VkLiBJZiBhIHNob3J0IG5hbWUgaXMgc3BlY2lmaWVkIGFuZCBtdWx0aXBsZSB0eXBlcyBzaGFyZVxyXG4gIHRoYXQgc2FtZSBzaG9ydCBuYW1lIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi5cclxuICBAcGFyYW0gb2tJZk5vdEZvdW5kIC0gKGRlZmF1bHQ9ZmFsc2UpIFdoZXRoZXIgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHNwZWNpZmllZCBFbnRpdHlUeXBlIGlzIG5vdCBmb3VuZC5cclxuICBAcmV0dXJuIFRoZSBFbnRpdHlUeXBlLiBDb21wbGV4VHlwZSBvciAnbnVsbCcgaWYgbm90IG5vdCBmb3VuZC5cclxuICAqKi9cclxuIGdldEFzQ29tcGxleFR5cGUodHlwZU5hbWU6IHN0cmluZywgb2tJZk5vdEZvdW5kOiBib29sZWFuID0gZmFsc2UpIHtcclxuICBjb25zdCBzdCA9IHRoaXMuZ2V0U3RydWN0dXJhbFR5cGUodHlwZU5hbWUsIG9rSWZOb3RGb3VuZCk7XHJcbiAgaWYgKHN0IGluc3RhbmNlb2YgQ29tcGxleFR5cGUpIHtcclxuICAgIHJldHVybiBzdCBhcyBDb21wbGV4VHlwZTtcclxuICB9IGVsc2UgaWYgKG9rSWZOb3RGb3VuZCkge1xyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfSBlbHNlIHtcclxuICAgIGxldCBtc2cgPSBjb3JlLmZvcm1hdFN0cmluZyhcIlVuYWJsZSB0byBsb2NhdGUgYW4gJ0NvbXBsZXhUeXBlJyBieSB0aGUgbmFtZTogJyUxJy4gQmUgc3VyZSB0byBleGVjdXRlIGEgcXVlcnkgb3IgY2FsbCBmZXRjaE1ldGFkYXRhIGZpcnN0LlwiLCB0eXBlTmFtZSk7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcclxuICB9XHJcbn1cclxuXHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYW4gW1tFbnRpdHlUeXBlXV0gb3IgYSBbW0NvbXBsZXhUeXBlXV0gZ2l2ZW4gaXRzIG5hbWUuXHJcbiAgQGRlcHJlY2F0ZWQgUmVwbGFjZWQgYnkgZ2V0U3RydWN0dXJhbFR5cGUgYnV0IC4uLiBpdCBpcyBwcm9iYWJseSBtb3JlIHVzZWZ1bGwgdG8gY2FsbCBlaXRoZXIgZ2V0QXNFbnRpdHlUeXBlIG9yIGdldEFzQ29tcGxleFR5cGUgaW5zdGVhZFxyXG4gIEBwYXJhbSB0eXBlTmFtZSAtIEVpdGhlciB0aGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb3IgYSBzaG9ydCBuYW1lIG1heSBiZSB1c2VkLiBJZiBhIHNob3J0IG5hbWUgaXMgc3BlY2lmaWVkIGFuZCBtdWx0aXBsZSB0eXBlcyBzaGFyZVxyXG4gIHRoYXQgc2FtZSBzaG9ydCBuYW1lIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi5cclxuICBAcGFyYW0gb2tJZk5vdEZvdW5kIC0gKGRlZmF1bHQ9ZmFsc2UpIFdoZXRoZXIgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHNwZWNpZmllZCBFbnRpdHlUeXBlIGlzIG5vdCBmb3VuZC5cclxuICBAcmV0dXJuIFRoZSBFbnRpdHlUeXBlLiBDb21wbGV4VHlwZSBvciAnbnVsbCcgaWYgbm90IG5vdCBmb3VuZC5cclxuICAqKi9cclxuICBnZXRFbnRpdHlUeXBlKHR5cGVOYW1lOiBzdHJpbmcsIG9rSWZOb3RGb3VuZDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICByZXR1cm4gdGhpcy5nZXRTdHJ1Y3R1cmFsVHlwZSh0eXBlTmFtZSwgb2tJZk5vdEZvdW5kKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYW4gW1tFbnRpdHlUeXBlXV0gb3IgYSBbW0NvbXBsZXhUeXBlXV0gZ2l2ZW4gaXRzIG5hbWUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIGxldCBvZFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRTdHJ1Y3R1cmFsVHlwZShcIk9yZGVyRGV0YWlsXCIpO1xyXG5cclxuICBvciB0byB0aHJvdyBhbiBlcnJvciBpZiB0aGUgdHlwZSBpcyBub3QgZm91bmRcclxuICA+ICAgICAgbGV0IGJhZFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRTdHJ1Y3R1cmFsVHlwZShcIkZvb1wiLCBmYWxzZSk7XHJcbiAgPiAgICAgIC8vIGJhZFR5cGUgd2lsbCBub3QgZ2V0IHNldCBhbmQgYW4gZXhjZXB0aW9uIHdpbGwgYmUgdGhyb3duLlxyXG4gIEBkZXByZWNhdGVkIFByZWZlcmFibHkgdXNlIGVpdGhlciBnZXRBc0VudGl0eVR5cGUgb3IgZ2V0QXNDb21wbGV4VHlwZS4gIEdldFxyXG4gIEBwYXJhbSB0eXBlTmFtZSAtIEVpdGhlciB0aGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb3IgYSBzaG9ydCBuYW1lIG1heSBiZSB1c2VkLiBJZiBhIHNob3J0IG5hbWUgaXMgc3BlY2lmaWVkIGFuZCBtdWx0aXBsZSB0eXBlcyBzaGFyZVxyXG4gIHRoYXQgc2FtZSBzaG9ydCBuYW1lIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi5cclxuICBAcGFyYW0gb2tJZk5vdEZvdW5kIC0gKGRlZmF1bHQ9ZmFsc2UpIFdoZXRoZXIgdG8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHNwZWNpZmllZCBFbnRpdHlUeXBlIGlzIG5vdCBmb3VuZC5cclxuICBAcmV0dXJuIFRoZSBFbnRpdHlUeXBlLiBDb21wbGV4VHlwZSBvciAnbnVsbCcgaWYgbm90IG5vdCBmb3VuZC5cclxuICAqKi9cclxuICBnZXRTdHJ1Y3R1cmFsVHlwZSh0eXBlTmFtZTogc3RyaW5nLCBva0lmTm90Rm91bmQ6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gICAgYXNzZXJ0UGFyYW0odHlwZU5hbWUsIFwidHlwZU5hbWVcIikuaXNTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgYXNzZXJ0UGFyYW0ob2tJZk5vdEZvdW5kLCBcIm9rSWZOb3RGb3VuZFwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkuY2hlY2soZmFsc2UpO1xyXG4gICAgcmV0dXJuIHRoaXMuX2dldFN0cnVjdHVyYWxUeXBlKHR5cGVOYW1lLCBva0lmTm90Rm91bmQpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2dldFN0cnVjdHVyYWxUeXBlKHR5cGVOYW1lOiBzdHJpbmcsIG9rSWZOb3RGb3VuZDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICBsZXQgcXVhbFR5cGVOYW1lID0gZ2V0UXVhbGlmaWVkVHlwZU5hbWUodGhpcywgdHlwZU5hbWUsIGZhbHNlKTtcclxuICAgIGxldCB0eXBlID0gdGhpcy5fc3RydWN0dXJhbFR5cGVNYXBbcXVhbFR5cGVOYW1lXTtcclxuICAgIGlmICghdHlwZSkge1xyXG4gICAgICBpZiAob2tJZk5vdEZvdW5kKSByZXR1cm4gbnVsbDtcclxuICAgICAgbGV0IG1zZyA9IGNvcmUuZm9ybWF0U3RyaW5nKFwiVW5hYmxlIHRvIGxvY2F0ZSBhICdUeXBlJyBieSB0aGUgbmFtZTogJyUxJy4gQmUgc3VyZSB0byBleGVjdXRlIGEgcXVlcnkgb3IgY2FsbCBmZXRjaE1ldGFkYXRhIGZpcnN0LlwiLCB0eXBlTmFtZSk7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHR5cGU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIG9mIHRoZSBbW0VudGl0eVR5cGVdXXMgb3IgW1tDb21wbGV4VHlwZV1dcyBpbiB0aGlzIE1ldGFkYXRhU3RvcmUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYSBwcmVleGlzdGluZyBFbnRpdHlNYW5hZ2VyXHJcbiAgPiAgICAgIGxldCBhbGxUeXBlcyA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGVzKCk7XHJcbiAgKiovXHJcbiAgZ2V0RW50aXR5VHlwZXMoKSB7XHJcbiAgICByZXR1cm4gZ2V0VHlwZXNGcm9tTWFwKHRoaXMuX3N0cnVjdHVyYWxUeXBlTWFwKTtcclxuICB9XHJcblxyXG4gIGdldEluY29tcGxldGVOYXZpZ2F0aW9uUHJvcGVydGllcygpIHtcclxuICAgIHJldHVybiBjb3JlLm9iamVjdE1hcCh0aGlzLl9pbmNvbXBsZXRlVHlwZU1hcCwgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcclxuICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgZnVsbHkgcXVhbGlmaWVkIGVudGl0eVR5cGVOYW1lIGZvciBhIHNwZWNpZmllZCByZXNvdXJjZSBuYW1lLiAgVGhlIHJldmVyc2Ugb2YgdGhpcyBvcGVyYXRpb25cclxuICBjYW4gYmUgb2J0YWluZWQgdmlhIHRoZSAgW1tFbnRpdHlUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWVdXSBwcm9wZXJ0eVxyXG4gICoqL1xyXG4gIGdldEVudGl0eVR5cGVOYW1lRm9yUmVzb3VyY2VOYW1lKHJlc291cmNlTmFtZTogc3RyaW5nKSB7XHJcbiAgICBhc3NlcnRQYXJhbShyZXNvdXJjZU5hbWUsIFwicmVzb3VyY2VOYW1lXCIpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuICAgIHJldHVybiB0aGlzLl9yZXNvdXJjZUVudGl0eVR5cGVNYXBbcmVzb3VyY2VOYW1lXTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEFzc29jaWF0ZXMgYSByZXNvdXJjZU5hbWUgd2l0aCBhbiBlbnRpdHlUeXBlLlxyXG5cclxuICBUaGlzIG1ldGhvZCBpcyBvbmx5IG5lZWRlZCBpbiB0aG9zZSBjYXNlcyB3aGVyZSBtdWx0aXBsZSByZXNvdXJjZXMgcmV0dXJuIHRoZSBzYW1lXHJcbiAgZW50aXR5VHlwZS4gIEluIHRoaXMgY2FzZSBNZXRhZGF0YSBkaXNjb3Zlcnkgd2lsbCBvbmx5IGRldGVybWluZSBhIHNpbmdsZSByZXNvdXJjZSBuYW1lIGZvclxyXG4gIGVhY2ggZW50aXR5VHlwZS5cclxuICBAcGFyYW0gcmVzb3VyY2VOYW1lIC0gVGhlIHJlc291cmNlIG5hbWVcclxuICBAcGFyYW0gZW50aXR5VHlwZU9yTmFtZSAtIElmIHBhc3NpbmcgYSBzdHJpbmcgZWl0aGVyIHRoZSBmdWxseSBxdWFsaWZpZWQgbmFtZSBvciBhIHNob3J0IG5hbWUgbWF5IGJlIHVzZWQuIElmIGEgc2hvcnQgbmFtZSBpcyBzcGVjaWZpZWQgYW5kIG11bHRpcGxlIHR5cGVzIHNoYXJlXHJcbiAgdGhhdCBzYW1lIHNob3J0IG5hbWUgYW4gZXhjZXB0aW9uIHdpbGwgYmUgdGhyb3duLiBJZiB0aGUgZW50aXR5VHlwZSBoYXMgbm90IHlldCBiZWVuIGRpc2NvdmVyZWQgdGhlbiBhIGZ1bGx5IHF1YWxpZmllZCBuYW1lIG11c3QgYmUgdXNlZC5cclxuICAqKi9cclxuICBzZXRFbnRpdHlUeXBlRm9yUmVzb3VyY2VOYW1lKHJlc291cmNlTmFtZTogc3RyaW5nLCBlbnRpdHlUeXBlT3JOYW1lOiBFbnRpdHlUeXBlIHwgc3RyaW5nKSB7XHJcbiAgICBhc3NlcnRQYXJhbShyZXNvdXJjZU5hbWUsIFwicmVzb3VyY2VOYW1lXCIpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKGVudGl0eVR5cGVPck5hbWUsIFwiZW50aXR5VHlwZU9yTmFtZVwiKS5pc0luc3RhbmNlT2YoRW50aXR5VHlwZSkub3IoKS5pc1N0cmluZygpLmNoZWNrKCk7XHJcblxyXG4gICAgbGV0IGVudGl0eVR5cGVOYW1lOiBzdHJpbmc7XHJcbiAgICBpZiAoZW50aXR5VHlwZU9yTmFtZSBpbnN0YW5jZW9mIEVudGl0eVR5cGUpIHtcclxuICAgICAgZW50aXR5VHlwZU5hbWUgPSBlbnRpdHlUeXBlT3JOYW1lLm5hbWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBlbnRpdHlUeXBlTmFtZSA9IGdldFF1YWxpZmllZFR5cGVOYW1lKHRoaXMsIGVudGl0eVR5cGVPck5hbWUsIHRydWUpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuX3Jlc291cmNlRW50aXR5VHlwZU1hcFtyZXNvdXJjZU5hbWVdID0gZW50aXR5VHlwZU5hbWU7XHJcbiAgICBsZXQgZW50aXR5VHlwZSA9IHRoaXMuX2dldFN0cnVjdHVyYWxUeXBlKGVudGl0eVR5cGVOYW1lLCB0cnVlKTtcclxuICAgIGlmIChlbnRpdHlUeXBlICYmIGVudGl0eVR5cGUgaW5zdGFuY2VvZiBFbnRpdHlUeXBlICYmICFlbnRpdHlUeXBlLmRlZmF1bHRSZXNvdXJjZU5hbWUpIHtcclxuICAgICAgZW50aXR5VHlwZS5kZWZhdWx0UmVzb3VyY2VOYW1lID0gcmVzb3VyY2VOYW1lO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIF9fRGV2IE9ubHlfXyAtIGZvciB1c2Ugd2hlbiBjcmVhdGluZyBhIG5ldyBNZXRhZGF0YVBhcnNlckFkYXB0ZXIgICovXHJcbiAgc3RhdGljIHBhcnNlVHlwZU5hbWUoZW50aXR5VHlwZU5hbWU6IHN0cmluZykge1xyXG4gICAgLy8gVE9ETzogcmVtb3ZlZCBcclxuICAgIC8vIGlmICghZW50aXR5VHlwZU5hbWUpIHtcclxuICAgIC8vICAgcmV0dXJuIG51bGw7XHJcbiAgICAvLyB9XHJcblxyXG4gICAgbGV0IHR5cGVQYXJ0cyA9IGVudGl0eVR5cGVOYW1lLnNwbGl0KFwiOiNcIik7XHJcbiAgICBpZiAodHlwZVBhcnRzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgcmV0dXJuIE1ldGFkYXRhU3RvcmUubWFrZVR5cGVIYXNoKHR5cGVQYXJ0c1swXSwgdHlwZVBhcnRzWzFdKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoY29yZS5zdHJpbmdTdGFydHNXaXRoKGVudGl0eVR5cGVOYW1lLCBNZXRhZGF0YVN0b3JlLkFOT05UWVBFX1BSRUZJWCkpIHtcclxuICAgICAgbGV0IHR5cGVIYXNoID0gTWV0YWRhdGFTdG9yZS5tYWtlVHlwZUhhc2goZW50aXR5VHlwZU5hbWUpO1xyXG4gICAgICAodHlwZUhhc2ggYXMgYW55KS5pc0Fub255bW91cyA9IHRydWU7XHJcbiAgICAgIHJldHVybiB0eXBlSGFzaDtcclxuICAgIH1cclxuICAgIGxldCBlbnRpdHlUeXBlTmFtZU5vQXNzZW1ibHkgPSBlbnRpdHlUeXBlTmFtZS5zcGxpdChcIixcIilbMF07XHJcbiAgICB0eXBlUGFydHMgPSBlbnRpdHlUeXBlTmFtZU5vQXNzZW1ibHkuc3BsaXQoXCIuXCIpO1xyXG4gICAgaWYgKHR5cGVQYXJ0cy5sZW5ndGggPiAxKSB7XHJcbiAgICAgIGxldCBzaG9ydE5hbWUgPSB0eXBlUGFydHNbdHlwZVBhcnRzLmxlbmd0aCAtIDFdO1xyXG4gICAgICBsZXQgbmFtZXNwYWNlUGFydHMgPSB0eXBlUGFydHMuc2xpY2UoMCwgdHlwZVBhcnRzLmxlbmd0aCAtIDEpO1xyXG4gICAgICBsZXQgbnMgPSBuYW1lc3BhY2VQYXJ0cy5qb2luKFwiLlwiKTtcclxuICAgICAgcmV0dXJuIE1ldGFkYXRhU3RvcmUubWFrZVR5cGVIYXNoKHNob3J0TmFtZSwgbnMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIE1ldGFkYXRhU3RvcmUubWFrZVR5cGVIYXNoKGVudGl0eVR5cGVOYW1lKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBfX0RldiBPbmx5X18gLSBmb3IgdXNlIHdoZW4gY3JlYXRpbmcgYSBuZXcgTWV0YWRhdGFQYXJzZXJBZGFwdGVyICAqL1xyXG4gIHN0YXRpYyBtYWtlVHlwZUhhc2goc2hvcnROYW1lOiBzdHJpbmcsIG5zPzogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBzaG9ydFR5cGVOYW1lOiBzaG9ydE5hbWUsXHJcbiAgICAgIG5hbWVzcGFjZTogbnMsXHJcbiAgICAgIHR5cGVOYW1lOiBxdWFsaWZ5VHlwZU5hbWUoc2hvcnROYW1lLCBucylcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvLyBwcm90ZWN0ZWQgbWV0aG9kc1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9jaGVja0VudGl0eVR5cGUoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgIGlmIChlbnRpdHkuZW50aXR5VHlwZSkgcmV0dXJuO1xyXG4gICAgbGV0IHR5cGVOYW1lID0gZW50aXR5LnByb3RvdHlwZS5fJHR5cGVOYW1lO1xyXG4gICAgaWYgKCF0eXBlTmFtZSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIGVudGl0eSBoYXMgbm90IGJlZW4gcmVnaXN0ZXJlZC4gU2VlIHRoZSBNZXRhZGF0YVN0b3JlLnJlZ2lzdGVyRW50aXR5VHlwZUN0b3IgbWV0aG9kXCIpO1xyXG4gICAgfVxyXG4gICAgLy8gd2Uga25vdyB0aGF0IGl0IGlzIGFuIEVudGl0eVR5cGUgKCBhcyBvcHBvc2VkIHRvIGEgQ29tcGxleFR5cGUpXHJcbiAgICBsZXQgZW50aXR5VHlwZSA9IHRoaXMuX2dldFN0cnVjdHVyYWxUeXBlKHR5cGVOYW1lKSBhcyBFbnRpdHlUeXBlO1xyXG4gICAgaWYgKGVudGl0eVR5cGUpIHtcclxuICAgICAgZW50aXR5LmVudGl0eVR5cGUgPSBlbnRpdHlUeXBlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcblxyXG59XHJcbk1ldGFkYXRhU3RvcmUucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIk1ldGFkYXRhU3RvcmVcIjtcclxuXHJcbkJyZWV6ZUV2ZW50LmJ1YmJsZUV2ZW50KE1ldGFkYXRhU3RvcmUucHJvdG90eXBlKTtcclxuXHJcbmZ1bmN0aW9uIGdldFR5cGVzRnJvbU1hcCh0eXBlTWFwOiBJU3RydWN0dXJhbFR5cGVNYXApIHtcclxuICBsZXQgdHlwZXM6IChTdHJ1Y3R1cmFsVHlwZSlbXSA9IFtdO1xyXG4gIGZvciAobGV0IGtleSBpbiB0eXBlTWFwKSB7XHJcbiAgICBsZXQgdmFsdWUgPSB0eXBlTWFwW2tleV07XHJcbiAgICAvLyBza2lwICdzaG9ydE5hbWUnIGVudHJpZXNcclxuICAgIGlmIChrZXkgPT09IHZhbHVlLm5hbWUpIHtcclxuICAgICAgdHlwZXMucHVzaCh0eXBlTWFwW2tleV0pO1xyXG4gICAgfVxyXG4gIH1cclxuICByZXR1cm4gdHlwZXM7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHN0cnVjdHVyYWxUeXBlRnJvbUpzb24obWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZSwganNvbjogYW55LCBhbGxvd01lcmdlOiBib29sZWFuKSB7XHJcbiAgbGV0IHR5cGVOYW1lID0gcXVhbGlmeVR5cGVOYW1lKGpzb24uc2hvcnROYW1lLCBqc29uLm5hbWVzcGFjZSk7XHJcbiAgbGV0IHN0eXBlID0gbWV0YWRhdGFTdG9yZS5fZ2V0U3RydWN0dXJhbFR5cGUodHlwZU5hbWUsIHRydWUpO1xyXG4gIGlmIChzdHlwZSkge1xyXG4gICAgaWYgKGFsbG93TWVyZ2UpIHtcclxuICAgICAgcmV0dXJuIG1lcmdlU3RydWN0dXJhbFR5cGUoc3R5cGUsIGpzb24pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gYWxsb3cgaXQgYnV0IGRvbid0IHJlcGxhY2UgYW55dGhpbmcuXHJcbiAgICAgIHJldHVybiBzdHlwZTtcclxuICAgIH1cclxuICB9XHJcbiAgbGV0IGNvbmZpZyA9IHtcclxuICAgIHNob3J0TmFtZToganNvbi5zaG9ydE5hbWUsXHJcbiAgICBuYW1lc3BhY2U6IGpzb24ubmFtZXNwYWNlLFxyXG4gICAgaXNBYnN0cmFjdDoganNvbi5pc0Fic3RyYWN0LFxyXG4gICAgYXV0b0dlbmVyYXRlZEtleVR5cGU6IEF1dG9HZW5lcmF0ZWRLZXlUeXBlLmZyb21OYW1lKGpzb24uYXV0b0dlbmVyYXRlZEtleVR5cGUpLFxyXG4gICAgZGVmYXVsdFJlc291cmNlTmFtZToganNvbi5kZWZhdWx0UmVzb3VyY2VOYW1lLFxyXG4gICAgY3VzdG9tOiBqc29uLmN1c3RvbVxyXG4gIH07XHJcblxyXG4gIHN0eXBlID0ganNvbi5pc0NvbXBsZXhUeXBlID8gbmV3IENvbXBsZXhUeXBlKGNvbmZpZykgOiBuZXcgRW50aXR5VHlwZShjb25maWcpO1xyXG5cclxuICAvLyBiYXNlVHlwZSBtYXkgbm90IGhhdmUgYmVlbiBpbXBvcnRlZCB5ZXQgc28gd2UgbmVlZCB0byBkZWZlciBoYW5kbGluZyB0aGlzIHR5cGUgdW50aWwgbGF0ZXIuXHJcbiAgaWYgKGpzb24uYmFzZVR5cGVOYW1lICYmIHN0eXBlIGluc3RhbmNlb2YgRW50aXR5VHlwZSkge1xyXG4gICAgc3R5cGUuYmFzZVR5cGVOYW1lID0ganNvbi5iYXNlVHlwZU5hbWU7XHJcbiAgICBsZXQgYmFzZUVudGl0eVR5cGUgPSBtZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShqc29uLmJhc2VUeXBlTmFtZSwgdHJ1ZSk7XHJcbiAgICBpZiAoYmFzZUVudGl0eVR5cGUpIHtcclxuICAgICAgY29tcGxldGVTdHJ1Y3R1cmFsVHlwZUZyb21Kc29uKG1ldGFkYXRhU3RvcmUsIGpzb24sIHN0eXBlKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvcmUuZ2V0QXJyYXkobWV0YWRhdGFTdG9yZS5fZGVmZXJyZWRUeXBlcywganNvbi5iYXNlVHlwZU5hbWUpLnB1c2goeyBqc29uOiBqc29uLCBzdHlwZTogc3R5cGUgfSk7XHJcblxyXG4gICAgfVxyXG4gIH0gZWxzZSB7XHJcbiAgICBjb21wbGV0ZVN0cnVjdHVyYWxUeXBlRnJvbUpzb24obWV0YWRhdGFTdG9yZSwganNvbiwgc3R5cGUpO1xyXG4gIH1cclxuXHJcbiAgLy8gc3R5cGUgbWF5IG9yIG1heSBub3QgaGF2ZSBiZWVuIGFkZGVkIHRvIHRoZSBtZXRhZGF0YVN0b3JlIGF0IHRoaXMgcG9pbnQuXHJcbiAgcmV0dXJuIHN0eXBlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBtZXJnZVN0cnVjdHVyYWxUeXBlKHN0eXBlOiBTdHJ1Y3R1cmFsVHlwZSwganNvbjogYW55KSB7XHJcbiAgaWYgKGpzb24uY3VzdG9tKSB7XHJcbiAgICBzdHlwZS5jdXN0b20gPSBqc29uLmN1c3RvbTtcclxuICB9XHJcblxyXG4gIG1lcmdlUHJvcHMoc3R5cGUsIGpzb24uZGF0YVByb3BlcnRpZXMpO1xyXG4gIG1lcmdlUHJvcHMoc3R5cGUsIGpzb24ubmF2aWdhdGlvblByb3BlcnRpZXMpO1xyXG4gIHJldHVybiBzdHlwZTtcclxufVxyXG5cclxuZnVuY3Rpb24gbWVyZ2VQcm9wcyhzdHlwZTogU3RydWN0dXJhbFR5cGUsIGpzb25Qcm9wczogYW55W10pIHtcclxuICBpZiAoIWpzb25Qcm9wcykgcmV0dXJuO1xyXG4gIGpzb25Qcm9wcy5mb3JFYWNoKChqc29uUHJvcCkgPT4ge1xyXG4gICAgbGV0IHByb3BOYW1lID0ganNvblByb3AubmFtZTtcclxuICAgIGlmICghcHJvcE5hbWUpIHtcclxuICAgICAgaWYgKGpzb25Qcm9wLm5hbWVPblNlcnZlcikge1xyXG4gICAgICAgIHByb3BOYW1lID0gc3R5cGUubWV0YWRhdGFTdG9yZS5uYW1pbmdDb252ZW50aW9uLnNlcnZlclByb3BlcnR5TmFtZVRvQ2xpZW50KGpzb25Qcm9wLm5hbWVPblNlcnZlciwge30pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIGJhY2tzbGFzaC1xdW90ZSB3b3JrcyBhcm91bmQgY29tcGlsZXIgYnVnXHJcbiAgICAgICAgY29uc3QgbXNnID0gXCJVbmFibGUgdG8gY29tcGxldGUgXFwnaW1wb3J0TWV0YWRhdGFcXCcgLSBjYW5ub3QgbG9jYXRlIGEgXFwnbmFtZVxcJyBvciBcXCduYW1lT25TZXJ2ZXJcXCcgZm9yIG9uZSBvZiB0aGUgaW1wb3J0ZWQgcHJvcGVydHkgbm9kZXNcIjtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKGpzb25Qcm9wLmN1c3RvbSkge1xyXG4gICAgICBsZXQgcHJvcCA9IHN0eXBlLmdldFByb3BlcnR5KHByb3BOYW1lLCB0cnVlKTtcclxuICAgICAgcHJvcCEuY3VzdG9tID0ganNvblByb3AuY3VzdG9tO1xyXG4gICAgfVxyXG4gIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBjb21wbGV0ZVN0cnVjdHVyYWxUeXBlRnJvbUpzb24obWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZSwganNvbjogYW55LCBzdHlwZTogYW55KSB7XHJcblxyXG4gIC8vIHZhbGlkYXRvcnMgZnJvbSBiYXNlVHlwZSB3b3JrIGJlY2F1c2UgdmFsaWRhdGlvbiB3YWxrcyB0aHJ1IGJhc2UgdHlwZXNcclxuICAvLyBzbyBubyBuZWVkIHRvIGNvcHkgZG93bi5cclxuICBpZiAoanNvbi52YWxpZGF0b3JzKSB7XHJcbiAgICBzdHlwZS52YWxpZGF0b3JzID0ganNvbi52YWxpZGF0b3JzLm1hcChWYWxpZGF0b3IuZnJvbUpTT04pO1xyXG4gIH1cclxuXHJcbiAganNvbi5kYXRhUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChkcDogT2JqZWN0KSB7XHJcbiAgICBzdHlwZS5fYWRkUHJvcGVydHlDb3JlKERhdGFQcm9wZXJ0eS5mcm9tSlNPTihkcCkpO1xyXG4gIH0pO1xyXG5cclxuXHJcbiAgbGV0IGlzRW50aXR5VHlwZSA9ICFqc29uLmlzQ29tcGxleFR5cGU7XHJcbiAgaWYgKGlzRW50aXR5VHlwZSkge1xyXG4gICAgLy9ub2luc3BlY3Rpb24gSlNIaW50XHJcbiAgICBqc29uLm5hdmlnYXRpb25Qcm9wZXJ0aWVzICYmIGpzb24ubmF2aWdhdGlvblByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAobnA6IE9iamVjdCkge1xyXG4gICAgICBzdHlwZS5fYWRkUHJvcGVydHlDb3JlKE5hdmlnYXRpb25Qcm9wZXJ0eS5mcm9tSlNPTihucCkpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBtZXRhZGF0YVN0b3JlLmFkZEVudGl0eVR5cGUoc3R5cGUpO1xyXG5cclxuICBsZXQgZGVmZXJyZWRUeXBlcyA9IG1ldGFkYXRhU3RvcmUuX2RlZmVycmVkVHlwZXM7XHJcbiAgbGV0IGRlZmVycmFscyA9IGRlZmVycmVkVHlwZXNbc3R5cGUubmFtZV07XHJcbiAgaWYgKGRlZmVycmFscykge1xyXG4gICAgZGVmZXJyYWxzLmZvckVhY2goZnVuY3Rpb24gKGQ6IGFueSkge1xyXG4gICAgICBjb21wbGV0ZVN0cnVjdHVyYWxUeXBlRnJvbUpzb24obWV0YWRhdGFTdG9yZSwgZC5qc29uLCBkLnN0eXBlKTtcclxuICAgIH0pO1xyXG4gICAgZGVsZXRlIGRlZmVycmVkVHlwZXNbc3R5cGUubmFtZV07XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRRdWFsaWZpZWRUeXBlTmFtZShtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlLCBzdHJ1Y3RUeXBlTmFtZTogc3RyaW5nLCB0aHJvd0lmTm90Rm91bmQ/OiBib29sZWFuKSB7XHJcbiAgaWYgKGlzUXVhbGlmaWVkVHlwZU5hbWUoc3RydWN0VHlwZU5hbWUpKSByZXR1cm4gc3RydWN0VHlwZU5hbWU7XHJcbiAgbGV0IHJlc3VsdCA9IG1ldGFkYXRhU3RvcmUuX3Nob3J0TmFtZU1hcFtzdHJ1Y3RUeXBlTmFtZV07XHJcbiAgaWYgKCFyZXN1bHQgJiYgdGhyb3dJZk5vdEZvdW5kKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gbG9jYXRlICdlbnRpdHlUeXBlTmFtZScgb2Y6IFwiICsgc3RydWN0VHlwZU5hbWUpO1xyXG4gIH1cclxuICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG4vKiogQ29uZmlndXJhdGlvbiBpbmZvIHRvIGJlIHBhc3NlZCB0byB0aGUgW1tFbnRpdHlUeXBlXV0gY29uc3RydWN0b3IgKi9cclxuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlUeXBlQ29uZmlnIHtcclxuICBzaG9ydE5hbWU/OiBzdHJpbmc7XHJcbiAgbmFtZXNwYWNlPzogc3RyaW5nO1xyXG4gIGJhc2VUeXBlTmFtZT86IHN0cmluZztcclxuICBpc0Fic3RyYWN0PzogYm9vbGVhbjtcclxuICBhdXRvR2VuZXJhdGVkS2V5VHlwZT86IEF1dG9HZW5lcmF0ZWRLZXlUeXBlO1xyXG4gIGRlZmF1bHRSZXNvdXJjZU5hbWU/OiBzdHJpbmc7XHJcbiAgZGF0YVByb3BlcnRpZXM/OiBEYXRhUHJvcGVydHlbXSB8IE9iamVjdFtdIHwgT2JqZWN0OyAgLy8gVE9ETzogc2VlIGlmIHdlIGNhbid0IHF1YWxpZnkgT2JqZWN0W10gYSBsaXR0bGUgYmV0dGVyLlxyXG4gIG5hdmlnYXRpb25Qcm9wZXJ0aWVzPzogTmF2aWdhdGlvblByb3BlcnR5W10gfCBPYmplY3RbXSB8IE9iamVjdDtcclxuICBzZXJpYWxpemVyRm4/OiAocHJvcDogRW50aXR5UHJvcGVydHksIHZhbDogYW55KSA9PiBhbnk7XHJcbiAgY3VzdG9tPzogT2JqZWN0O1xyXG59XHJcblxyXG4vKiogQ29uZmlndXJhdGlvbiBpbmZvIHRvIGJlIHBhc3NlZCB0byB0aGUgW1tFbnRpdHlUeXBlLnNldFByb3BlcnRpZXNdXSBtZXRob2QgKi9cclxuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlUeXBlU2V0Q29uZmlnIHtcclxuICBhdXRvR2VuZXJhdGVkS2V5VHlwZT86IEF1dG9HZW5lcmF0ZWRLZXlUeXBlO1xyXG4gIGRlZmF1bHRSZXNvdXJjZU5hbWU/OiBzdHJpbmc7XHJcbiAgc2VyaWFsaXplckZuPzogKHByb3A6IEVudGl0eVByb3BlcnR5LCB2YWw6IGFueSkgPT4gYW55O1xyXG4gIGN1c3RvbT86IE9iamVjdDtcclxufVxyXG5cclxuLyoqIENvbnRhaW5lciBmb3IgYWxsIG9mIHRoZSBtZXRhZGF0YSBhYm91dCBhIHNwZWNpZmljIHR5cGUgb2YgRW50aXR5LlxyXG4qKi9cclxuZXhwb3J0IGNsYXNzIEVudGl0eVR5cGUge1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF8kdHlwZU5hbWU6IHN0cmluZzsgLy8gb24gcHJvdG9cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBzdGF0aWMgX19uZXh0QW5vbkl4ID0gMDtcclxuICAvKiogQWx3YXlzIGZhbHNlIGZvciBhbiBFbnRpdHlUeXBlLiAqKi9cclxuICBpc0NvbXBsZXhUeXBlID0gZmFsc2U7XHJcbiAgLyoqIFRoZSBbW01ldGFkYXRhU3RvcmVdXSB0aGF0IGNvbnRhaW5zIHRoaXMgRW50aXR5VHlwZS4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlO1xyXG4gIC8qKiBUaGUgRGF0YVByb3BlcnRpZXMgKHNlZSBbW0RhdGFQcm9wZXJ0eV1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eVR5cGUuIF9fUmVhZCBPbmx5X18gICoqL1xyXG4gIGRhdGFQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvKiogIFRoZSBOYXZpZ2F0aW9uUHJvcGVydGllcyAoc2VlIFtbTmF2aWdhdGlvblByb3BlcnR5XV0gYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5VHlwZS4gX19SZWFkIE9ubHlfXyAgKiovXHJcbiAgbmF2aWdhdGlvblByb3BlcnRpZXM6IE5hdmlnYXRpb25Qcm9wZXJ0eVtdO1xyXG4gIC8qKlxyXG4gIFRoZSBEYXRhUHJvcGVydGllcyBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlUeXBlIHRoYXQgbWFrZSB1cCBpdCdzIFtbRW50aXR5S2V5XV0uIF9fUmVhZCBPbmx5X18gKiovXHJcbiAga2V5UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcbiAgLyoqIFRoZSBEYXRhUHJvcGVydGllcyBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlUeXBlIHRoYXQgYXJlIGZvcmVpZ24ga2V5IHByb3BlcnRpZXMuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgZm9yZWlnbktleVByb3BlcnRpZXM6IERhdGFQcm9wZXJ0eVtdO1xyXG4gIGludmVyc2VGb3JlaWduS2V5UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcbiAgLyoqICBUaGUgRGF0YVByb3BlcnRpZXMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5VHlwZSB0aGF0IGFyZSBjb25jdXJyZW5jeSBwcm9wZXJ0aWVzLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGNvbmN1cnJlbmN5UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcbiAgLyoqIFRoZSBEYXRhUHJvcGVydGllcyBmb3IgdGhpcyBFbnRpdHlUeXBlIHRoYXQgY29udGFpbiBpbnN0YW5jZXMgb2YgYSBbW0NvbXBsZXhUeXBlXV0uIF9fUmVhZCBPbmx5X18gICAqKi9cclxuICBjb21wbGV4UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcbiAgLyoqIFRoZSBEYXRhUHJvcGVydGllcyBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHlUeXBlIHRoYXQgYXJlIG5vdCBtYXBwZWQgdG8gYW55IGJhY2tlbmQgZGF0YXN0b3JlLiBUaGVzZSBhcmUgZWZmZWN0aXZlbHkgZnJlZSBzdGFuZGluZ1xyXG4gIHByb3BlcnRpZXMuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgdW5tYXBwZWRQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuXHJcbiAgLyoqIFRoZSBmdWxseSBxdWFsaWZpZWQgbmFtZSBvZiB0aGlzIEVudGl0eVR5cGUuIF9fUmVhZCBPbmx5X18gICoqL1xyXG4gIG5hbWU6IHN0cmluZztcclxuICAvKiogVGhlIHNob3J0LCB1bnF1YWxpZmllZCwgbmFtZSBmb3IgdGhpcyBFbnRpdHlUeXBlLiBfX1JlYWQgT25seV9fICAqKi9cclxuICBzaG9ydE5hbWU6IHN0cmluZztcclxuICAvKiogVGhlIG5hbWVzcGFjZSBmb3IgdGhpcyBFbnRpdHlUeXBlLiBfX1JlYWQgT25seV9fICAqKi9cclxuICBuYW1lc3BhY2U6IHN0cmluZztcclxuICAvKiogVGhlIG5hbWUgb2YgdGhpcyBFbnRpdHlUeXBlJ3MgYmFzZSBFbnRpdHlUeXBlICAoaWYgYW55KSAqL1xyXG4gIGJhc2VUeXBlTmFtZT86IHN0cmluZztcclxuICAvKiogVGhlIGJhc2UgRW50aXR5VHlwZSAoaWYgYW55KSBmb3IgdGhpcyBFbnRpdHlUeXBlLiBfX1JlYWQgT25seV9fICAgKiovXHJcbiAgYmFzZUVudGl0eVR5cGU6IEVudGl0eVR5cGU7XHJcbiAgc3VidHlwZXM6IEVudGl0eVR5cGVbXTtcclxuXHJcbiAgLyoqICBXaGV0aGVyIHRoaXMgRW50aXR5VHlwZSBpcyBhYnN0cmFjdC4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBpc0Fic3RyYWN0OiBib29sZWFuO1xyXG4gIC8qKiAgV2hldGhlciB0aGlzIEVudGl0eVR5cGUgaXMgYW5vbnltb3VzLiBBbm9ueW1vdXMgdHlwZXMgd2lsbCBuZXZlciBiZSBjb21tdW5pY2F0ZWQgdG8gb3IgZnJvbSB0aGUgc2VydmVyLiBUaGV5IGFyZSBwdXJlbHkgZm9yXHJcbiAgY2xpZW50IHNpZGUgdXNlIGFuZCBhcmUgZ2l2ZW4gYW4gYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgbmFtZS4gIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgaXNBbm9ueW1vdXM6IGJvb2xlYW47XHJcbiAgLyoqIFdoZXRoZXIgdGhpcyBFbnRpdHlUeXBlIGhhcyBiZWVuICdmcm96ZW4nLiAgRW50aXR5VHlwZXMgYmVjb21lIGZyb3plbiBhZnRlciB0aGUgZmlyc3QgaW5zdGFuY2UgXHJcbiAgb2YgdGhhdCB0eXBlIGhhcyBiZWVuIGNyZWF0ZWQgYW5kIGF0dGFjaGVkIHRvIGFuIEVudGl0eU1hbmFnZXIuICovXHJcbiAgaXNGcm96ZW46IGJvb2xlYW47XHJcblxyXG4gIC8qKiBUaGUgW1tBdXRvR2VuZXJhdGVkS2V5VHlwZV1dIGZvciB0aGlzIEVudGl0eVR5cGUuIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgYXV0b0dlbmVyYXRlZEtleVR5cGU6IEF1dG9HZW5lcmF0ZWRLZXlUeXBlO1xyXG4gIC8qKiAgIFRoZSBkZWZhdWx0IHJlc291cmNlIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgRW50aXR5VHlwZS4gIEFuIEVudGl0eVR5cGUgbWF5IGJlIHF1ZXJpZWQgdmlhIGEgdmFyaWV0eSBvZiAncmVzb3VyY2UgbmFtZXMnIGJ1dCB0aGlzIG9uZVxyXG4gIGlzIHVzZWQgYXMgdGhlIGRlZmF1bHQgd2hlbiBubyByZXNvdXJjZSBuYW1lIGlzIHByb3ZpZGVkLiAgVGhpcyB3aWxsIG9jY3VyIHdoZW4gY2FsbGluZyBbW0VudGl0eUFzcGVjdC5sb2FkTmF2aWdhdGlvblByb3BlcnR5XV1cclxuICBvciB3aGVuIGV4ZWN1dGluZyBhbnkgW1tFbnRpdHlRdWVyeV1dIHRoYXQgd2FzIGNyZWF0ZWQgdmlhIGFuIFtbRW50aXR5S2V5XV0uIF9fUmVhZCBPbmx5X18gKiovXHJcbiAgZGVmYXVsdFJlc291cmNlTmFtZTogc3RyaW5nO1xyXG4gIC8qKiBBIGZ1bmN0aW9uIHRoYXQgaXMgdXNlZCB0byBjdXN0b21pemUgdGhlIHNlcmlhbGl6YXRpb24gb2YgYW55IEVudGl0eVByb3BlcnRpZXMgb2YgdGhpcyB0eXBlLiAqL1xyXG4gIHNlcmlhbGl6ZXJGbj86IChwcm9wOiBFbnRpdHlQcm9wZXJ0eSwgdmFsOiBhbnkpID0+IGFueTtcclxuICAvKiogIEEgZnJlZSBmb3JtIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIGRlZmluZSBhbnkgY3VzdG9tIG1ldGFkYXRhIGZvciB0aGlzIEVudGl0eVR5cGUuIF9fUmVhZCBPbmx5X18gICoqL1xyXG4gIGN1c3RvbT86IE9iamVjdDtcclxuICAvKiogVGhlIGVudGl0eSBsZXZlbCB2YWxpZGF0b3JzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIEVudGl0eVR5cGUuIFZhbGlkYXRvcnMgY2FuIGJlIGFkZGVkIGFuZFxyXG4gIHJlbW92ZWQgZnJvbSB0aGlzIGNvbGxlY3Rpb24uIF9fUmVhZCBPbmx5X18uICAgKiovXHJcbiAgdmFsaWRhdG9yczogVmFsaWRhdG9yW107XHJcblxyXG4gIHdhcm5pbmdzOiBhbnlbXTtcclxuICBpbml0Rm46IEZ1bmN0aW9uIHwgc3RyaW5nO1xyXG4gIG5vVHJhY2tpbmdGbjogRnVuY3Rpb247XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9leHRyYTogYW55O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9jdG9yOiB7IG5ldyAoKTogU3RydWN0dXJhbE9iamVjdCB9O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9tYXBwZWRQcm9wZXJ0aWVzQ291bnQ6IG51bWJlcjtcclxuXHJcbiAgLyoqIFxyXG4gIEBkZXByZWNhdGVkIFVzZSBbW2dldEN0b3JdXSBpbnN0ZWFkLiAgIFxyXG4gICovXHJcbiAgZ2V0RW50aXR5Q3RvciA9IHRoaXMuZ2V0Q3RvcjtcclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgc3RhdGljIHF1YWxpZnlUeXBlTmFtZSA9IHF1YWxpZnlUeXBlTmFtZTtcclxuXHJcblxyXG4gIC8qKiBFbnRpdHlUeXBlIGNvbnN0cnVjdG9yICBcclxuICA+ICAgICAgbGV0IGVudGl0eVR5cGUgPSBuZXcgRW50aXR5VHlwZSgge1xyXG4gID4gICAgICAgICAgc2hvcnROYW1lOiBcInBlcnNvblwiLFxyXG4gID4gICAgICAgICAgbmFtZXNwYWNlOiBcIm15QXBwTmFtZXNwYWNlXCJcclxuICA+ICAgICAgfSk7XHJcbiAgQHBhcmFtIGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gc2V0dGluZ3Mgb3IgYSBNZXRhZGF0YVN0b3JlLiAgSWYgdGhpcyBwYXJhbWV0ZXIgaXMganVzdCBhIE1ldGFkYXRhU3RvcmVcclxuICB0aGVuIHdoYXQgd2lsbCBiZSBjcmVhdGVkIGlzIGFuICdhbm9ueW1vdXMnIHR5cGUgdGhhdCB3aWxsIG5ldmVyIGJlIGNvbW11bmljYXRlZCB0byBvciBmcm9tIHRoZSBzZXJ2ZXIuIEl0IGlzIHB1cmVseSBmb3JcclxuICBjbGllbnQgc2lkZSB1c2UgYW5kIHdpbGwgYmUgZ2l2ZW4gYW4gYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgbmFtZS4gTm9ybWFsbHksIGhvd2V2ZXIsIHlvdSB3aWxsIHVzZSBhIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlxyXG4gICoqL1xyXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogTWV0YWRhdGFTdG9yZSB8IEVudGl0eVR5cGVDb25maWcpIHtcclxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgRW50aXR5VHlwZSBjdG9yIGhhcyBhIHNpbmdsZSBhcmd1bWVudCB0aGF0IGlzIGVpdGhlciBhICdNZXRhZGF0YVN0b3JlJyBvciBhIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlwiKTtcclxuICAgIH1cclxuICAgIC8vIGxldCBldENvbmZpZyA9ICA8RW50aXR5VHlwZUNvbmZpZz4gPGFueT4gdW5kZWZpbmVkO1xyXG4gICAgbGV0IGV0Q29uZmlnOiBFbnRpdHlUeXBlQ29uZmlnIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xyXG5cclxuICAgIGlmICgoY29uZmlnIGFzIGFueSkuXyR0eXBlTmFtZSA9PT0gXCJNZXRhZGF0YVN0b3JlXCIpIHtcclxuICAgICAgdGhpcy5tZXRhZGF0YVN0b3JlID0gY29uZmlnIGFzIE1ldGFkYXRhU3RvcmU7XHJcbiAgICAgIHRoaXMuc2hvcnROYW1lID0gXCJBbm9uX1wiICsgKCsrRW50aXR5VHlwZS5fX25leHRBbm9uSXgpO1xyXG4gICAgICB0aGlzLm5hbWVzcGFjZSA9IFwiXCI7XHJcbiAgICAgIHRoaXMuaXNBbm9ueW1vdXMgPSB0cnVlO1xyXG4gICAgICAvLyBldENvbmZpZyA9IHVuZGVmaW5lZDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGV0Q29uZmlnID0gY29uZmlnIGFzIEVudGl0eVR5cGVDb25maWc7XHJcbiAgICAgIGFzc2VydENvbmZpZyhjb25maWcpXHJcbiAgICAgICAgLndoZXJlUGFyYW0oXCJzaG9ydE5hbWVcIikuaXNOb25FbXB0eVN0cmluZygpXHJcbiAgICAgICAgLndoZXJlUGFyYW0oXCJuYW1lc3BhY2VcIikuaXNTdHJpbmcoKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoXCJcIilcclxuICAgICAgICAud2hlcmVQYXJhbShcImJhc2VUeXBlTmFtZVwiKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAgIC53aGVyZVBhcmFtKFwiaXNBYnN0cmFjdFwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoZmFsc2UpXHJcbiAgICAgICAgLndoZXJlUGFyYW0oXCJhdXRvR2VuZXJhdGVkS2V5VHlwZVwiKS5pc0VudW1PZihBdXRvR2VuZXJhdGVkS2V5VHlwZSkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KEF1dG9HZW5lcmF0ZWRLZXlUeXBlLk5vbmUpXHJcbiAgICAgICAgLndoZXJlUGFyYW0oXCJkZWZhdWx0UmVzb3VyY2VOYW1lXCIpLmlzTm9uRW1wdHlTdHJpbmcoKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQobnVsbClcclxuICAgICAgICAud2hlcmVQYXJhbShcImRhdGFQcm9wZXJ0aWVzXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAgIC53aGVyZVBhcmFtKFwibmF2aWdhdGlvblByb3BlcnRpZXNcIikuaXNPcHRpb25hbCgpXHJcbiAgICAgICAgLndoZXJlUGFyYW0oXCJzZXJpYWxpemVyRm5cIikuaXNPcHRpb25hbCgpLmlzRnVuY3Rpb24oKVxyXG4gICAgICAgIC53aGVyZVBhcmFtKFwiY3VzdG9tXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAgIC5hcHBseUFsbCh0aGlzKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLm5hbWUgPSBxdWFsaWZ5VHlwZU5hbWUodGhpcy5zaG9ydE5hbWUsIHRoaXMubmFtZXNwYWNlKTtcclxuXHJcbiAgICAvLyB0aGUgZGVmYXVsdFJlc291cmNlTmFtZSBtYXkgYWxzbyBiZSBzZXQgdXAgZWl0aGVyIHZpYSBtZXRhZGF0YSBsb29rdXAgb3IgZmlyc3QgcXVlcnkgb3IgdmlhIHRoZSAnc2V0UHJvcGVydGllcycgbWV0aG9kXHJcbiAgICB0aGlzLmRhdGFQcm9wZXJ0aWVzID0gW107XHJcbiAgICB0aGlzLm5hdmlnYXRpb25Qcm9wZXJ0aWVzID0gW107XHJcbiAgICB0aGlzLmNvbXBsZXhQcm9wZXJ0aWVzID0gW107XHJcbiAgICB0aGlzLmtleVByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMuZm9yZWlnbktleVByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMuaW52ZXJzZUZvcmVpZ25LZXlQcm9wZXJ0aWVzID0gW107XHJcbiAgICB0aGlzLmNvbmN1cnJlbmN5UHJvcGVydGllcyA9IFtdO1xyXG4gICAgdGhpcy51bm1hcHBlZFByb3BlcnRpZXMgPSBbXTsgLy8gd2lsbCBiZSB1cGRhdGVkIGxhdGVyLlxyXG4gICAgdGhpcy52YWxpZGF0b3JzID0gW107XHJcbiAgICB0aGlzLndhcm5pbmdzID0gW107XHJcbiAgICB0aGlzLl9tYXBwZWRQcm9wZXJ0aWVzQ291bnQgPSAwO1xyXG4gICAgdGhpcy5zdWJ0eXBlcyA9IFtdO1xyXG4gICAgLy8gbm93IHByb2Nlc3MgYW55IGRhdGEvbmF2IHByb3BzXHJcbiAgICBpZiAoZXRDb25maWcgJiYgZXRDb25maWcuZGF0YVByb3BlcnRpZXMpIHtcclxuICAgICAgYWRkUHJvcGVydGllcyh0aGlzLCBldENvbmZpZy5kYXRhUHJvcGVydGllcywgRGF0YVByb3BlcnR5KTtcclxuICAgIH1cclxuICAgIGlmIChldENvbmZpZyAmJiBldENvbmZpZy5uYXZpZ2F0aW9uUHJvcGVydGllcykge1xyXG4gICAgICBhZGRQcm9wZXJ0aWVzKHRoaXMsIGV0Q29uZmlnLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLCBOYXZpZ2F0aW9uUHJvcGVydHkpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgR2VuZXJhbCBwdXJwb3NlIHByb3BlcnR5IHNldCBtZXRob2RcclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgY3VzdFR5cGUuc2V0UHJvcGVydGllcygge1xyXG4gID4gICAgICAgICAgYXV0b0dlbmVyYXRlZEtleVR5cGU6IEF1dG9HZW5lcmF0ZWRLZXlUeXBlLklkZW50aXR5O1xyXG4gID4gICAgICAgICAgZGVmYXVsdFJlc291cmNlTmFtZTogXCJDdXN0b21lcnNBbmRJbmNsdWRlZE9yZGVyc1wiXHJcbiAgPiAgICAgICl9O1xyXG4gIEBwYXJhbSBjb25maWcgLSBhIGNvbmZpZ3VyYXRpb24gb2JqZWN0XHJcbiAgKiovXHJcbiAgc2V0UHJvcGVydGllcyhjb25maWc6IEVudGl0eVR5cGVTZXRDb25maWcpIHtcclxuICAgIGFzc2VydENvbmZpZyhjb25maWcpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiYXV0b0dlbmVyYXRlZEtleVR5cGVcIikuaXNFbnVtT2YoQXV0b0dlbmVyYXRlZEtleVR5cGUpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImRlZmF1bHRSZXNvdXJjZU5hbWVcIikuaXNTdHJpbmcoKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJzZXJpYWxpemVyRm5cIikuaXNGdW5jdGlvbigpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImN1c3RvbVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG4gICAgaWYgKGNvbmZpZy5kZWZhdWx0UmVzb3VyY2VOYW1lKSB7XHJcbiAgICAgIHRoaXMuZGVmYXVsdFJlc291cmNlTmFtZSA9IGNvbmZpZy5kZWZhdWx0UmVzb3VyY2VOYW1lO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyB3aGV0aGVyIHRoaXMgdHlwZSBpcyBhIHN1YnR5cGUgb2YgYSBzcGVjaWZpZWQgdHlwZS5cclxuICAqKi9cclxuICBpc1N1YnR5cGVPZihlbnRpdHlUeXBlOiBFbnRpdHlUeXBlKSB7XHJcbiAgICBhc3NlcnRQYXJhbShlbnRpdHlUeXBlLCBcImVudGl0eVR5cGVcIikuaXNJbnN0YW5jZU9mKEVudGl0eVR5cGUpLmNoZWNrKCk7XHJcbiAgICBsZXQgYmFzZVR5cGU6IEVudGl0eVR5cGUgPSB0aGlzO1xyXG4gICAgZG8ge1xyXG4gICAgICBpZiAoYmFzZVR5cGUgPT09IGVudGl0eVR5cGUpIHJldHVybiB0cnVlO1xyXG4gICAgICBiYXNlVHlwZSA9IGJhc2VUeXBlLmJhc2VFbnRpdHlUeXBlO1xyXG4gICAgfSB3aGlsZSAoYmFzZVR5cGUpO1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhbiBhcnJheSBjb250YWluaW5nIHRoaXMgdHlwZSBhbmQgYW55L2FsbCBzdWJ0eXBlcyBvZiB0aGlzIHR5cGUgZG93biB0aHJ1IHRoZSBoaWVyYXJjaHkuXHJcbiAgKiovXHJcbiAgZ2V0U2VsZkFuZFN1YnR5cGVzKCkge1xyXG4gICAgbGV0IHJlc3VsdCA9IFt0aGlzXTtcclxuICAgIHRoaXMuc3VidHlwZXMuZm9yRWFjaChmdW5jdGlvbiAoc3QpIHtcclxuICAgICAgbGV0IHN1YnR5cGVzID0gc3QuZ2V0U2VsZkFuZFN1YnR5cGVzKCk7XHJcbiAgICAgIHJlc3VsdC5wdXNoLmFwcGx5KHJlc3VsdCwgc3VidHlwZXMpO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgZ2V0QWxsVmFsaWRhdG9ycygpIHtcclxuICAgIGxldCByZXN1bHQgPSB0aGlzLnZhbGlkYXRvcnMuc2xpY2UoMCk7XHJcbiAgICBsZXQgYnQgPSB0aGlzLmJhc2VFbnRpdHlUeXBlO1xyXG4gICAgd2hpbGUgKGJ0KSB7XHJcbiAgICAgIHJlc3VsdC5wdXNoLmFwcGx5KHJlc3VsdCwgYnQudmFsaWRhdG9ycyk7XHJcbiAgICAgIGJ0ID0gYnQuYmFzZUVudGl0eVR5cGU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQWRkcyBhICBbW0RhdGFQcm9wZXJ0eV1dIG9yIGEgW1tOYXZpZ2F0aW9uUHJvcGVydHldXSB0byB0aGlzIEVudGl0eVR5cGUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBteUVudGl0eVR5cGUgaXMgYSBuZXdseSBjb25zdHJ1Y3RlZCBFbnRpdHlUeXBlLlxyXG4gID4gICAgICBteUVudGl0eVR5cGUuYWRkUHJvcGVydHkoZGF0YVByb3BlcnR5MSk7XHJcbiAgPiAgICAgIG15RW50aXR5VHlwZS5hZGRQcm9wZXJ0eShkYXRhUHJvcGVydHkyKTtcclxuICA+ICAgICAgbXlFbnRpdHlUeXBlLmFkZFByb3BlcnR5KG5hdmlnYXRpb25Qcm9wZXJ0eTEpO1xyXG4gICoqL1xyXG4gIGFkZFByb3BlcnR5KHByb3BlcnR5OiBFbnRpdHlQcm9wZXJ0eSkge1xyXG4gICAgYXNzZXJ0UGFyYW0ocHJvcGVydHksIFwicHJvcGVydHlcIikuaXNJbnN0YW5jZU9mKERhdGFQcm9wZXJ0eSkub3IoKS5pc0luc3RhbmNlT2YoTmF2aWdhdGlvblByb3BlcnR5KS5jaGVjaygpO1xyXG5cclxuICAgIC8vIHRydWUgaXMgMm5kIGFyZyB0byBmb3JjZSByZXNvbHZlIG9mIGFueSBuYXZpZ2F0aW9uIHByb3BlcnRpZXMuXHJcbiAgICBsZXQgbmV3cHJvcCA9IHRoaXMuX2FkZFByb3BlcnR5Q29yZShwcm9wZXJ0eSwgdHJ1ZSk7XHJcblxyXG4gICAgaWYgKHRoaXMuc3VidHlwZXMgJiYgdGhpcy5zdWJ0eXBlcy5sZW5ndGgpIHtcclxuICAgICAgbGV0IHN0eXBlID0gdGhpcztcclxuICAgICAgc3R5cGUuZ2V0U2VsZkFuZFN1YnR5cGVzKCkuZm9yRWFjaChmdW5jdGlvbiAoc3QpIHtcclxuICAgICAgICBpZiAoc3QgIT09IHN0eXBlKSB7XHJcbiAgICAgICAgICBpZiAocHJvcGVydHkuaXNOYXZpZ2F0aW9uUHJvcGVydHkpIHtcclxuICAgICAgICAgICAgc3QuX2FkZFByb3BlcnR5Q29yZShuZXcgTmF2aWdhdGlvblByb3BlcnR5KHByb3BlcnR5KSwgdHJ1ZSk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBzdC5fYWRkUHJvcGVydHlDb3JlKG5ldyBEYXRhUHJvcGVydHkocHJvcGVydHkgYXMgRGF0YVByb3BlcnR5KSwgdHJ1ZSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIHJldHVybiBuZXdwcm9wO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VwZGF0ZUZyb21CYXNlKGJhc2VFbnRpdHlUeXBlOiBFbnRpdHlUeXBlKSB7XHJcbiAgICB0aGlzLmJhc2VFbnRpdHlUeXBlID0gYmFzZUVudGl0eVR5cGU7XHJcbiAgICBpZiAodGhpcy5hdXRvR2VuZXJhdGVkS2V5VHlwZSA9PT0gQXV0b0dlbmVyYXRlZEtleVR5cGUuTm9uZSkge1xyXG4gICAgICB0aGlzLmF1dG9HZW5lcmF0ZWRLZXlUeXBlID0gYmFzZUVudGl0eVR5cGUuYXV0b0dlbmVyYXRlZEtleVR5cGU7XHJcbiAgICB9XHJcblxyXG4gICAgYmFzZUVudGl0eVR5cGUuZGF0YVByb3BlcnRpZXMuZm9yRWFjaCgoZHApID0+IHtcclxuICAgICAgbGV0IG5ld0RwID0gbmV3IERhdGFQcm9wZXJ0eShkcCk7XHJcbiAgICAgIC8vIGRvbid0IG5lZWQgdG8gY29weSB2YWxpZGF0b3JzIGJlY2F1ZSB3ZSB3aWxsIHdhbGsgdGhlIGhpZXJhcmNoeSB0byBmaW5kIHRoZW1cclxuICAgICAgbmV3RHAudmFsaWRhdG9ycyA9IFtdO1xyXG4gICAgICBuZXdEcC5iYXNlUHJvcGVydHkgPSBkcDtcclxuICAgICAgdGhpcy5fYWRkUHJvcGVydHlDb3JlKG5ld0RwKTtcclxuICAgIH0sIHRoaXMpO1xyXG4gICAgYmFzZUVudGl0eVR5cGUubmF2aWdhdGlvblByb3BlcnRpZXMuZm9yRWFjaCgobnApID0+IHtcclxuICAgICAgbGV0IG5ld05wID0gbmV3IE5hdmlnYXRpb25Qcm9wZXJ0eShucCk7XHJcbiAgICAgIC8vIGRvbid0IG5lZWQgdG8gY29weSB2YWxpZGF0b3JzIGJlY2F1ZSB3ZSB3aWxsIHdhbGsgdGhlIGhpZXJhcmNoeSB0byBmaW5kIHRoZW1cclxuICAgICAgbmV3TnAudmFsaWRhdG9ycyA9IFtdO1xyXG4gICAgICBuZXdOcC5iYXNlUHJvcGVydHkgPSBucDtcclxuICAgICAgdGhpcy5fYWRkUHJvcGVydHlDb3JlKG5ld05wKTtcclxuICAgIH0sIHRoaXMpO1xyXG4gICAgYmFzZUVudGl0eVR5cGUuc3VidHlwZXMucHVzaCh0aGlzKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9hZGRQcm9wZXJ0eUNvcmUocHJvcGVydHk6IEVudGl0eVByb3BlcnR5LCBzaG91bGRSZXNvbHZlOiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgIGlmICh0aGlzLmlzRnJvemVuKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSAnXCIgKyB0aGlzLm5hbWUgKyBcIicgRW50aXR5VHlwZS9Db21wbGV4VHlwZSBoYXMgYmVlbiBmcm96ZW4uIFlvdSBjYW4gb25seSBhZGQgcHJvcGVydGllcyB0byBhbiBFbnRpdHlUeXBlL0NvbXBsZXhUeXBlIGJlZm9yZSBhbnkgaW5zdGFuY2VzIG9mIHRoYXQgdHlwZSBoYXZlIGJlZW4gY3JlYXRlZCBhbmQgYXR0YWNoZWQgdG8gYW4gZW50aXR5TWFuYWdlci5cIik7XHJcbiAgICB9XHJcbiAgICBsZXQgcGFyZW50VHlwZSA9IHByb3BlcnR5LnBhcmVudFR5cGU7XHJcbiAgICBpZiAocGFyZW50VHlwZSkge1xyXG4gICAgICBpZiAocGFyZW50VHlwZSAhPT0gdGhpcykge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaXMgcHJvcGVydHk6IFwiICsgcHJvcGVydHkubmFtZSArIFwiIGhhcyBhbHJlYWR5IGJlZW4gYWRkZWQgdG8gXCIgKyBwcm9wZXJ0eS5wYXJlbnRUeXBlLm5hbWUpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIGFkZGluZyB0aGUgc2FtZSBwcm9wZXJ0eSBtb3JlIHRoYW4gb25jZSB0byB0aGUgc2FtZSBlbnRpdHlUeXBlIGlzIGp1c3QgaWdub3JlZC5cclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHByb3BlcnR5LnBhcmVudFR5cGUgPSB0aGlzO1xyXG4gICAgbGV0IG1zID0gdGhpcy5tZXRhZGF0YVN0b3JlO1xyXG4gICAgLy8gaWYgKHByb3BlcnR5LmlzRGF0YVByb3BlcnR5KSB7IC8vIG1vZGlmaWVkIGJlY2F1c2UgZG9lc24ndCBhY3QgYXMgYSB0eXBlIGd1YXJkIFxyXG4gICAgaWYgKHByb3BlcnR5IGluc3RhbmNlb2YgRGF0YVByb3BlcnR5KSB7XHJcbiAgICAgIHRoaXMuX2FkZERhdGFQcm9wZXJ0eShwcm9wZXJ0eSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLl9hZGROYXZpZ2F0aW9uUHJvcGVydHkocHJvcGVydHkpO1xyXG4gICAgICAvLyBtZXRhZGF0YVN0b3JlIGNhbiBiZSB1bmRlZmluZWQgaWYgdGhpcyBlbnRpdHlUeXBlIGhhcyBub3QgeWV0IGJlZW4gYWRkZWQgdG8gYSBNZXRhZGF0YVN0b3JlLlxyXG4gICAgICBpZiAoc2hvdWxkUmVzb2x2ZSAmJiBtcykge1xyXG4gICAgICAgIHRyeVJlc29sdmVOcChwcm9wZXJ0eSwgbXMpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvLyB1bm1hcHBlZCBwcm9wZXJ0aWVzIGNhbiBiZSBhZGRlZCBBRlRFUiBlbnRpdHlUeXBlIGhhcyBhbHJlYWR5IHJlc29sdmVkIGFsbCBwcm9wZXJ0eSBuYW1lcy5cclxuICAgIGlmIChtcyAmJiAhKHByb3BlcnR5Lm5hbWUgJiYgcHJvcGVydHkubmFtZU9uU2VydmVyKSkge1xyXG4gICAgICB1cGRhdGVDbGllbnRTZXJ2ZXJOYW1lcyhtcy5uYW1pbmdDb252ZW50aW9uLCBwcm9wZXJ0eSwgXCJuYW1lXCIpO1xyXG4gICAgfVxyXG4gICAgLy8gcHJvcHMgY2FuIGJlIGFkZGVkIGFmdGVyIGVudGl0eSBwcm90b3R5cGUgaGFzIGFscmVhZHkgYmVlbiB3cmFwcGVkLlxyXG4gICAgaWYgKG1zICYmIHRoaXMuX2V4dHJhKSB7XHJcbiAgICAgIGlmICh0aGlzLl9leHRyYS5hbHJlYWR5V3JhcHBlZFByb3BzKSB7XHJcbiAgICAgICAgbGV0IHByb3RvID0gdGhpcy5fY3Rvci5wcm90b3R5cGU7XHJcbiAgICAgICAgY29uZmlnLmludGVyZmFjZVJlZ2lzdHJ5Lm1vZGVsTGlicmFyeS5nZXREZWZhdWx0SW5zdGFuY2UoKS5pbml0aWFsaXplRW50aXR5UHJvdG90eXBlKHByb3RvKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQ3JlYXRlIGEgbmV3IGVudGl0eSBvZiB0aGlzIHR5cGUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRBc0VudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IGN1c3QxID0gY3VzdFR5cGUuY3JlYXRlRW50aXR5KCk7XHJcbiAgPiAgICAgIGVtMS5hZGRFbnRpdHkoY3VzdDEpO1xyXG4gIEBwYXJhbSBpbml0aWFsVmFsdWVzLSBDb25maWd1cmF0aW9uIG9iamVjdCBvZiB0aGUgcHJvcGVydGllcyB0byBzZXQgaW1tZWRpYXRlbHkgYWZ0ZXIgY3JlYXRpb24uXHJcbiAgQHJldHVybiBUaGUgbmV3IGVudGl0eS5cclxuICAqKi9cclxuICBjcmVhdGVFbnRpdHkoaW5pdGlhbFZhbHVlcz86IGFueSk6IGFueSB7XHJcbiAgICAvLyBpZ25vcmUgdGhlIF8kZXJlZiBvbmNlIHRoZSBlbnRpdHkgaXMgYXR0YWNoZWQgdG8gYW4gZW50aXR5TWFuYWdlci5cclxuICAgIGlmIChpbml0aWFsVmFsdWVzICYmIGluaXRpYWxWYWx1ZXMuXyRlcmVmICYmICFpbml0aWFsVmFsdWVzLl8kZXJlZi5lbnRpdHlBc3BlY3QuZW50aXR5TWFuYWdlcikgcmV0dXJuIGluaXRpYWxWYWx1ZXMuXyRlcmVmO1xyXG5cclxuICAgIGxldCBpbnN0YW5jZSA9IHRoaXMuX2NyZWF0ZUluc3RhbmNlQ29yZSgpO1xyXG5cclxuICAgIGlmIChpbml0aWFsVmFsdWVzKSB7XHJcbiAgICAgIC8vIG9ubHkgYXNzaWduIGFuIF9lcmVmIGlmIHRoZSBvYmplY3QgaXMgZnVsbHkgXCJrZXllZFwiXHJcbiAgICAgIGlmICh0aGlzLmtleVByb3BlcnRpZXMuZXZlcnkoZnVuY3Rpb24gKGtwKSB7XHJcbiAgICAgICAgcmV0dXJuIGluaXRpYWxWYWx1ZXNba3AubmFtZV0gIT0gbnVsbDtcclxuICAgICAgfSkpIHtcclxuICAgICAgICBpbml0aWFsVmFsdWVzLl8kZXJlZiA9IGluc3RhbmNlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLl91cGRhdGVUYXJnZXRGcm9tUmF3KGluc3RhbmNlLCBpbml0aWFsVmFsdWVzLCBnZXRSYXdWYWx1ZUZyb21Db25maWcpO1xyXG5cclxuICAgICAgdGhpcy5uYXZpZ2F0aW9uUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChucCkge1xyXG4gICAgICAgIGxldCByZWxhdGVkRW50aXR5OiBhbnk7XHJcbiAgICAgICAgbGV0IHZhbCA9IGluaXRpYWxWYWx1ZXNbbnAubmFtZV07XHJcbiAgICAgICAgaWYgKHZhbCAhPSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgIGxldCBuYXZFbnRpdHlUeXBlID0gbnAuZW50aXR5VHlwZTtcclxuICAgICAgICAgIGlmIChucC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgICByZWxhdGVkRW50aXR5ID0gdmFsLmVudGl0eUFzcGVjdCA/IHZhbCA6IG5hdkVudGl0eVR5cGUuY3JlYXRlRW50aXR5KHZhbCk7XHJcbiAgICAgICAgICAgIGluc3RhbmNlLnNldFByb3BlcnR5KG5wLm5hbWUsIHJlbGF0ZWRFbnRpdHkpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbGV0IHJlbGF0ZWRFbnRpdGllcyA9IGluc3RhbmNlLmdldFByb3BlcnR5KG5wLm5hbWUpO1xyXG4gICAgICAgICAgICB2YWwuZm9yRWFjaCgodjogYW55KSA9PiB7XHJcbiAgICAgICAgICAgICAgcmVsYXRlZEVudGl0eSA9IHYuZW50aXR5QXNwZWN0ID8gdiA6IG5hdkVudGl0eVR5cGUuY3JlYXRlRW50aXR5KHYpO1xyXG4gICAgICAgICAgICAgIHJlbGF0ZWRFbnRpdGllcy5wdXNoKHJlbGF0ZWRFbnRpdHkpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuX2luaXRpYWxpemVJbnN0YW5jZShpbnN0YW5jZSk7XHJcbiAgICByZXR1cm4gaW5zdGFuY2U7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfY3JlYXRlSW5zdGFuY2VDb3JlKCkge1xyXG4gICAgbGV0IGFDdG9yID0gdGhpcy5nZXRDdG9yKCk7XHJcbiAgICBsZXQgaW5zdGFuY2UgPSBuZXcgYUN0b3IoKTtcclxuICAgIG5ldyBFbnRpdHlBc3BlY3QoaW5zdGFuY2UgYXMgRW50aXR5KTtcclxuICAgIHJldHVybiBpbnN0YW5jZTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9pbml0aWFsaXplSW5zdGFuY2UoaW5zdGFuY2U6IGFueSkge1xyXG4gICAgaWYgKHRoaXMuYmFzZUVudGl0eVR5cGUpIHtcclxuICAgICAgdGhpcy5iYXNlRW50aXR5VHlwZS5faW5pdGlhbGl6ZUluc3RhbmNlKGluc3RhbmNlKTtcclxuICAgIH1cclxuICAgIGxldCBpbml0Rm4gPSB0aGlzLmluaXRGbjtcclxuICAgIGlmIChpbml0Rm4pIHtcclxuICAgICAgbGV0IGZuID0gKHR5cGVvZiBpbml0Rm4gPT09IFwic3RyaW5nXCIpID8gaW5zdGFuY2VbaW5pdEZuXSA6IGluaXRGbjtcclxuICAgICAgZm4oaW5zdGFuY2UpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5jb21wbGV4UHJvcGVydGllcyAmJiB0aGlzLmNvbXBsZXhQcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKGNwKSB7XHJcbiAgICAgIGxldCBjb21wbGV4VHlwZSA9IGNwLmRhdGFUeXBlIGFzIENvbXBsZXhUeXBlO1xyXG4gICAgICBsZXQgY3RJbnN0YW5jZSA9IGluc3RhbmNlLmdldFByb3BlcnR5KGNwLm5hbWUpO1xyXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShjdEluc3RhbmNlKSkge1xyXG4gICAgICAgIGN0SW5zdGFuY2UuZm9yRWFjaCgoY3RJbnN0KSA9PiB7XHJcbiAgICAgICAgICBjb21wbGV4VHlwZS5faW5pdGlhbGl6ZUluc3RhbmNlKGN0SW5zdCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY29tcGxleFR5cGUuX2luaXRpYWxpemVJbnN0YW5jZShjdEluc3RhbmNlKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICAvLyBub3QgbmVlZGVkIGZvciBjb21wbGV4T2JqZWN0c1xyXG4gICAgaWYgKGluc3RhbmNlLmVudGl0eUFzcGVjdCkge1xyXG4gICAgICBpbnN0YW5jZS5lbnRpdHlBc3BlY3QuX2luaXRpYWxpemVkID0gdHJ1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgdGhlIGNvbnN0cnVjdG9yIGZvciB0aGlzIEVudGl0eVR5cGUuXHJcbiAgQHBhcmFtIGZvcmNlUmVmcmVzaCAtIFdoZXRoZXIgdG8gaWdub3JlIGFueSBjYWNoZWQgdmVyc2lvbiBvZiB0aGlzIGNvbnN0cnVjdG9yLiAoZGVmYXVsdCA9PSBmYWxzZSlcclxuICBAcmV0dXJuIFRoZSBjb25zdHJ1Y3RvciBmb3IgdGhpcyBFbnRpdHlUeXBlLlxyXG4gICoqL1xyXG4gIGdldEN0b3IoZm9yY2VSZWZyZXNoOiBib29sZWFuID0gZmFsc2UpOiB7IG5ldyAoKTogU3RydWN0dXJhbE9iamVjdCB9IHtcclxuICAgIGlmICh0aGlzLl9jdG9yICYmICFmb3JjZVJlZnJlc2gpIHJldHVybiB0aGlzLl9jdG9yO1xyXG5cclxuICAgIGxldCBjdG9yUmVnaXN0cnkgPSB0aGlzLm1ldGFkYXRhU3RvcmUuX2N0b3JSZWdpc3RyeTtcclxuICAgIGxldCByID0gY3RvclJlZ2lzdHJ5W3RoaXMubmFtZV0gfHwgY3RvclJlZ2lzdHJ5W3RoaXMuc2hvcnROYW1lXSB8fCB7fTtcclxuICAgIGxldCBhQ3RvciA9IHIuY3RvciB8fCB0aGlzLl9jdG9yO1xyXG5cclxuICAgIGxldCBjdG9yVHlwZSA9IGFDdG9yICYmIGFDdG9yLnByb3RvdHlwZSAmJiAoYUN0b3IucHJvdG90eXBlLmVudGl0eVR5cGUgfHwgYUN0b3IucHJvdG90eXBlLmNvbXBsZXhUeXBlKTtcclxuICAgIGlmIChjdG9yVHlwZSAmJiBjdG9yVHlwZS5tZXRhZGF0YVN0b3JlICE9PSB0aGlzLm1ldGFkYXRhU3RvcmUpIHtcclxuICAgICAgLy8gV2UgY2FuJ3QgcmlzayBhIG1pc21hdGNoIGJldHdlZW4gdGhlIGN0b3IgYW5kIHRoZSB0eXBlIGluZm8gaW4gYSBzcGVjaWZpYyBtZXRhZGF0YXN0b3JlXHJcbiAgICAgIC8vIGJlY2F1c2UgbW9kZWxMaWJyYXJpZXMgcmVseSBvbiB0eXBlIGluZm8gdG8gaW50ZXJjZXB0IGN0b3IgcHJvcGVydGllc1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgcmVnaXN0ZXIgdGhlIHNhbWUgY29uc3RydWN0b3IgZm9yIFwiICsgdGhpcy5uYW1lICsgXCIgaW4gZGlmZmVyZW50IG1ldGFkYXRhIHN0b3Jlcy4gIFBsZWFzZSBkZWZpbmUgYSBzZXBhcmF0ZSBjb25zdHJ1Y3RvciBmb3IgZWFjaCBtZXRhZGF0YSBzdG9yZS5cIik7XHJcbiAgICB9XHJcblxyXG5cclxuICAgIGlmIChyLmN0b3IgJiYgZm9yY2VSZWZyZXNoKSB7XHJcbiAgICAgIHRoaXMuX2V4dHJhID0gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghYUN0b3IpIHtcclxuICAgICAgbGV0IGNyZWF0ZUN0b3IgPSBjb25maWcuaW50ZXJmYWNlUmVnaXN0cnkubW9kZWxMaWJyYXJ5LmdldERlZmF1bHRJbnN0YW5jZSgpLmNyZWF0ZUN0b3I7XHJcbiAgICAgIGFDdG9yID0gY3JlYXRlQ3RvciA/IGNyZWF0ZUN0b3IodGhpcykgOiBjcmVhdGVFbXB0eUN0b3IodGhpcyk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5pbml0Rm4gPSByLmluaXRGbjtcclxuICAgIHRoaXMubm9UcmFja2luZ0ZuID0gci5ub1RyYWNraW5nRm47XHJcblxyXG4gICAgYUN0b3IucHJvdG90eXBlLl8kdHlwZU5hbWUgPSB0aGlzLm5hbWU7XHJcbiAgICB0aGlzLl9zZXRDdG9yKGFDdG9yKTtcclxuICAgIHJldHVybiBhQ3RvcjtcclxuICB9XHJcblxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICAvLyBNYXkgbWFrZSBwdWJsaWMgbGF0ZXIuXHJcbiAgX3NldEN0b3IoYUN0b3I6IHsgbmV3ICgpOiBTdHJ1Y3R1cmFsT2JqZWN0IH0sIGludGVyY2VwdG9yPzogYW55KSB7XHJcblxyXG4gICAgbGV0IGluc3RhbmNlUHJvdG8gPSBhQ3Rvci5wcm90b3R5cGU7XHJcblxyXG4gICAgLy8gcGxhY2UgZm9yIGV4dHJhIGJyZWV6ZSByZWxhdGVkIGRhdGFcclxuICAgIHRoaXMuX2V4dHJhID0gdGhpcy5fZXh0cmEgfHwge307XHJcblxyXG4gICAgbGV0IGluc3RhbmNlID0gbmV3IGFDdG9yKCk7XHJcbiAgICBjYWxjVW5tYXBwZWRQcm9wZXJ0aWVzKHRoaXMsIGluc3RhbmNlKTtcclxuXHJcbiAgICBpZiAodGhpcy5fJHR5cGVOYW1lID09PSBcIkVudGl0eVR5cGVcIikge1xyXG4gICAgICAvLyBpbnN1cmUgdGhhdCBhbGwgb2YgdGhlIHByb3BlcnRpZXMgYXJlIG9uIHRoZSAndGVtcGxhdGUnIGluc3RhbmNlIGJlZm9yZSB3YXRjaGluZyB0aGUgY2xhc3MuXHJcbiAgICAgIGluc3RhbmNlUHJvdG8uZW50aXR5VHlwZSA9IHRoaXM7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpbnN0YW5jZVByb3RvLmNvbXBsZXhUeXBlID0gdGhpcztcclxuICAgIH1cclxuXHJcbiAgICAvLyBkZWZhdWx0UHJvcGVydHlJbnRlcmNlcHRvciBpcyBhICdnbG9iYWwnIChidXQgaW50ZXJuYWwgdG8gYnJlZXplKSBmdW5jdGlvbjtcclxuICAgIChpbnN0YW5jZVByb3RvIGFzIGFueSkuXyRpbnRlcmNlcHRvciA9IGludGVyY2VwdG9yIHx8IGRlZmF1bHRQcm9wZXJ0eUludGVyY2VwdG9yO1xyXG4gICAgY29uZmlnLmludGVyZmFjZVJlZ2lzdHJ5Lm1vZGVsTGlicmFyeS5nZXREZWZhdWx0SW5zdGFuY2UoKS5pbml0aWFsaXplRW50aXR5UHJvdG90eXBlKGluc3RhbmNlUHJvdG8pO1xyXG4gICAgdGhpcy5fY3RvciA9IGFDdG9yO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQWRkcyBlaXRoZXIgYW4gZW50aXR5IG9yIHByb3BlcnR5IGxldmVsIHZhbGlkYXRvciB0byB0aGlzIEVudGl0eVR5cGUuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlciBjb250YWluaW5nIGEgbnVtYmVyIG9mIGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBjb3VudHJ5UHJvcCA9IGN1c3RUeXBlLmdldFByb3BlcnR5KFwiQ291bnRyeVwiKTtcclxuICA+ICAgICAgbGV0IHZhbEZuID0gZnVuY3Rpb24gKHYpIHtcclxuICA+ICAgICAgICAgICAgICBpZiAodiA9PSBudWxsKSByZXR1cm4gdHJ1ZTtcclxuICA+ICAgICAgICAgICAgICByZXR1cm4gKGNvcmUuc3RyaW5nU3RhcnRzV2l0aCh2LCBcIlVTXCIpKTtcclxuICA+ICAgICAgICAgIH07XHJcbiAgPiAgICAgIGxldCBjb3VudHJ5VmFsaWRhdG9yID0gbmV3IFZhbGlkYXRvcihcImNvdW50cnlJc1VTXCIsIHZhbEZuLFxyXG4gID4gICAgICB7IGRpc3BsYXlOYW1lOiBcIkNvdW50cnlcIiwgbWVzc2FnZVRlbXBsYXRlOiBcIiclZGlzcGxheU5hbWUlJyBtdXN0IHN0YXJ0IHdpdGggJ1VTJ1wiIH0pO1xyXG4gID4gICAgICBjdXN0VHlwZS5hZGRWYWxpZGF0b3IoY291bnRyeVZhbGlkYXRvciwgY291bnRyeVByb3ApO1xyXG5cclxuICBUaGlzIGlzIHRoZSBzYW1lIGFzIGFkZGluZyBhbiBlbnRpdHkgbGV2ZWwgdmFsaWRhdG9yIHZpYSB0aGUgJ3ZhbGlkYXRvcnMnIHByb3BlcnR5IG9mIERhdGFQcm9wZXJ0eSBvciBOYXZpZ2F0aW9uUHJvcGVydHlcclxuICA+ICAgICAgY291bnRyeVByb3AudmFsaWRhdG9ycy5wdXNoKGNvdW50cnlWYWxpZGF0b3IpO1xyXG5cclxuICBFbnRpdHkgbGV2ZWwgdmFsaWRhdG9ycyBjYW4gYWxzbyBiZSBhZGRlZCBieSBvbWl0dGluZyB0aGUgJ3Byb3BlcnR5JyBwYXJhbWV0ZXIuXHJcbiAgPiAgICAgIGN1c3RUeXBlLmFkZFZhbGlkYXRvcihzb21lRW50aXR5TGV2ZWxWYWxpZGF0b3IpO1xyXG5cclxuICBvclxyXG4gID4gICAgICBjdXN0VHlwZS52YWxpZGF0b3JzLnB1c2goc29tZUVudGl0eUxldmVsVmFsaWRhdG9yKTtcclxuICBAcGFyYW0gdmFsaWRhdG9yIC0gVmFsaWRhdG9yIHRvIGFkZC5cclxuICBAcGFyYW0gcHJvcGVydHkgLSBQcm9wZXJ0eSB0byBhZGQgdGhpcyB2YWxpZGF0b3IgdG8uICBJZiBvbWl0dGVkLCB0aGUgdmFsaWRhdG9yIGlzIGFzc3VtZWQgdG8gYmUgYW5cclxuICBlbnRpdHkgbGV2ZWwgdmFsaWRhdG9yIGFuZCBpcyBhZGRlZCB0byB0aGUgRW50aXR5VHlwZSdzICd2YWxpZGF0b3JzJy5cclxuICAqKi9cclxuICBhZGRWYWxpZGF0b3IodmFsaWRhdG9yOiBWYWxpZGF0b3IsIHByb3BlcnR5PzogRW50aXR5UHJvcGVydHkgfCBzdHJpbmcpIHtcclxuICAgIGFzc2VydFBhcmFtKHZhbGlkYXRvciwgXCJ2YWxpZGF0b3JcIikuaXNJbnN0YW5jZU9mKFZhbGlkYXRvcikuY2hlY2soKTtcclxuICAgIGFzc2VydFBhcmFtKHByb3BlcnR5LCBcInByb3BlcnR5XCIpLmlzT3B0aW9uYWwoKS5pc1N0cmluZygpLm9yKCkuaXNFbnRpdHlQcm9wZXJ0eSgpLmNoZWNrKCk7XHJcbiAgICBpZiAocHJvcGVydHkgIT0gbnVsbCkge1xyXG4gICAgICBsZXQgcHJvcCA9ICh0eXBlb2YgcHJvcGVydHkgPT09ICdzdHJpbmcnKSA/IHRoaXMuZ2V0UHJvcGVydHkocHJvcGVydHksIHRydWUpIDogcHJvcGVydHk7XHJcbiAgICAgIHByb3AhLnZhbGlkYXRvcnMucHVzaCh2YWxpZGF0b3IpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy52YWxpZGF0b3JzLnB1c2godmFsaWRhdG9yKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIFJldHVybnMgYWxsIG9mIHRoZSBwcm9wZXJ0aWVzICggZGF0YVByb3BlcnRpZXMgYW5kIG5hdmlnYXRpb25Qcm9wZXJ0aWVzKSBmb3IgdGhpcyBFbnRpdHlUeXBlLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgYXJyYXlPZlByb3BzID0gY3VzdFR5cGUuZ2V0UHJvcGVydGllcygpO1xyXG4gIEByZXR1cm4gQW4gYXJyYXkgb2YgRGF0YSBhbmQgTmF2aWdhdGlvbiBwcm9wZXJ0aWVzLlxyXG4gICoqL1xyXG4gIGdldFByb3BlcnRpZXMoKTogRW50aXR5UHJvcGVydHlbXSB7XHJcbiAgICByZXR1cm4gKHRoaXMuZGF0YVByb3BlcnRpZXMgYXMgRW50aXR5UHJvcGVydHlbXSkuY29uY2F0KHRoaXMubmF2aWdhdGlvblByb3BlcnRpZXMpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhbGwgb2YgdGhlIHByb3BlcnR5IG5hbWVzICggZm9yIGJvdGggZGF0YVByb3BlcnRpZXMgYW5kIG5hdmlnYXRpb25Qcm9wZXJ0aWVzKSBmb3IgdGhpcyBFbnRpdHlUeXBlLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgYXJyYXlPZlByb3BOYW1lcyA9IGN1c3RUeXBlLmdldFByb3BlcnR5TmFtZXMoKTtcclxuICAqKi9cclxuICBnZXRQcm9wZXJ0eU5hbWVzKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuZ2V0UHJvcGVydGllcygpLm1hcChjb3JlLnBsdWNrKCduYW1lJykpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIGRhdGEgcHJvcGVydHkgd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUgb3IgbnVsbC5cclxuICA+ICAgICAgLy8gYXNzdW1lIGVtMSBpcyBhbiBFbnRpdHlNYW5hZ2VyIGNvbnRhaW5pbmcgYSBudW1iZXIgb2YgZXhpc3RpbmcgZW50aXRpZXMuXHJcbiAgPiAgICAgIGxldCBjdXN0VHlwZSA9IGVtMS5tZXRhZGF0YVN0b3JlLmdldEVudGl0eVR5cGUoXCJDdXN0b21lclwiKTtcclxuICA+ICAgICAgbGV0IGN1c3RvbWVyTmFtZURhdGFQcm9wID0gY3VzdFR5cGUuZ2V0RGF0YVByb3BlcnR5KFwiQ3VzdG9tZXJOYW1lXCIpO1xyXG4gIEByZXR1cm4gQSBEYXRhUHJvcGVydHkgb3IgbnVsbCBpZiBub3QgZm91bmQuXHJcbiAgKiovXHJcbiAgZ2V0RGF0YVByb3BlcnR5KHByb3BlcnR5TmFtZTogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4gY29yZS5hcnJheUZpcnN0KHRoaXMuZGF0YVByb3BlcnRpZXMsIGNvcmUucHJvcEVxKCduYW1lJywgcHJvcGVydHlOYW1lKSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGEgbmF2aWdhdGlvbiBwcm9wZXJ0eSB3aXRoIHRoZSBzcGVjaWZpZWQgbmFtZSBvciBudWxsLlxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXIgY29udGFpbmluZyBhIG51bWJlciBvZiBleGlzdGluZyBlbnRpdGllcy5cclxuICA+ICAgICAgbGV0IGN1c3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkN1c3RvbWVyXCIpO1xyXG4gID4gICAgICBsZXQgY3VzdG9tZXJPcmRlcnNOYXZQcm9wID0gY3VzdFR5cGUuZ2V0RGF0YVByb3BlcnR5KFwiT3JkZXJzXCIpO1xyXG4gIEByZXR1cm4gQSBOYXZpZ2F0aW9uUHJvcGVydHkgb3IgbnVsbCBpZiBub3QgZm91bmQuXHJcbiAgKiovXHJcbiAgZ2V0TmF2aWdhdGlvblByb3BlcnR5KHByb3BlcnR5TmFtZTogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4gY29yZS5hcnJheUZpcnN0KHRoaXMubmF2aWdhdGlvblByb3BlcnRpZXMsIGNvcmUucHJvcEVxKCduYW1lJywgcHJvcGVydHlOYW1lKSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIGVpdGhlciBhIERhdGFQcm9wZXJ0eSBvciBhIE5hdmlnYXRpb25Qcm9wZXJ0eSB3aXRoIHRoZSBzcGVjaWZpZWQgbmFtZSBvciBudWxsLlxyXG4gIFxyXG4gIFRoaXMgbWV0aG9kIGFsc28gYWNjZXB0cyBhICcuJyBkZWxpbWl0ZWQgcHJvcGVydHkgcGF0aCBhbmQgd2lsbCByZXR1cm4gdGhlICdwcm9wZXJ0eScgYXQgdGhlXHJcbiAgZW5kIG9mIHRoZSBwYXRoLlxyXG4gID4gICAgICBsZXQgY3VzdFR5cGUgPSBlbTEubWV0YWRhdGFTdG9yZS5nZXRFbnRpdHlUeXBlKFwiQ3VzdG9tZXJcIik7XHJcbiAgPiAgICAgIGxldCBjb21wYW55TmFtZVByb3AgPSBjdXN0VHlwZS5nZXRQcm9wZXJ0eShcIkNvbXBhbnlOYW1lXCIpO1xyXG5cclxuICBUaGlzIG1ldGhvZCBjYW4gYWxzbyB3YWxrIGEgcHJvcGVydHkgcGF0aCB0byByZXR1cm4gYSBwcm9wZXJ0eVxyXG4gID4gICAgICBsZXQgb3JkZXJEZXRhaWxUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIk9yZGVyRGV0YWlsXCIpO1xyXG4gID4gICAgICBsZXQgY29tcGFueU5hbWVQcm9wMiA9IG9yZGVyRGV0YWlsVHlwZS5nZXRQcm9wZXJ0eShcIk9yZGVyLkN1c3RvbWVyLkNvbXBhbnlOYW1lXCIpO1xyXG4gID4gICAgICAvLyBjb21wYW55TmFtZVByb3AgPT09IGNvbXBhbnlOYW1lUHJvcDJcclxuICBAcGFyYW0gW3Rocm93SWZOb3RGb3VuZD1mYWxzZV0ge0Jvb2xlYW59IFdoZXRoZXIgdG8gdGhyb3cgYW4gZXhjZXB0aW9uIGlmIG5vdCBmb3VuZC5cclxuICBAcmV0dXJuIEEgRGF0YVByb3BlcnR5IG9yIE5hdmlnYXRpb25Qcm9wZXJ0eSBvciBudWxsIGlmIG5vdCBmb3VuZC5cclxuICAqKi9cclxuICBnZXRQcm9wZXJ0eShwcm9wZXJ0eVBhdGg6IHN0cmluZywgdGhyb3dJZk5vdEZvdW5kOiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgIGxldCBwcm9wcyA9IHRoaXMuZ2V0UHJvcGVydGllc09uUGF0aChwcm9wZXJ0eVBhdGgsIGZhbHNlLCB0aHJvd0lmTm90Rm91bmQpO1xyXG4gICAgcmV0dXJuIChwcm9wcyAmJiBwcm9wcy5sZW5ndGggPiAwKSA/IHByb3BzW3Byb3BzLmxlbmd0aCAtIDFdIDogbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIC8vIFRPRE86IGhhdmUgdGhpcyByZXR1cm4gZW1wdHkgYXJyYXkgaW5zdGVhZCBvZiBudWxsIGFuZCBmaXggY29uc3VtZXJzLlxyXG4gIC8vIFRPRE86IHRoaW5rIGFib3V0IHJlbmFtaW5nIHdpdGggJ18nIHByZWZpeC5cclxuICBnZXRQcm9wZXJ0aWVzT25QYXRoKHByb3BlcnR5UGF0aDogc3RyaW5nLCB1c2VTZXJ2ZXJOYW1lOiBib29sZWFuIHwgbnVsbCwgdGhyb3dJZk5vdEZvdW5kOiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgIGxldCBwcm9wZXJ0eU5hbWVzOiBzdHJpbmdbXSA9IChBcnJheS5pc0FycmF5KHByb3BlcnR5UGF0aCkpID8gcHJvcGVydHlQYXRoIDogcHJvcGVydHlQYXRoLnRyaW0oKS5zcGxpdCgnLicpO1xyXG5cclxuICAgIGxldCBvayA9IHRydWU7XHJcbiAgICBsZXQga2V5ID0gdXNlU2VydmVyTmFtZSA9PT0gdHJ1ZSA/IFwibmFtZU9uU2VydmVyXCIgOiB1c2VTZXJ2ZXJOYW1lID09PSBmYWxzZSA/IFwibmFtZVwiIDogbnVsbDtcclxuICAgIGxldCBwYXJlbnRUeXBlID0gdGhpcyBhcyBTdHJ1Y3R1cmFsVHlwZTtcclxuICAgIFxyXG4gICAgY29uc3QgZ2V0UHJvcHMgPSAocHJvcE5hbWU6IHN0cmluZykgPT4geyBcclxuICAgICAgY29uc3QgZm4gPSBrZXkgPT09IG51bGwgPyBjb3JlLnByb3BzRXEoXCJuYW1lXCIsIFwibmFtZU9uU2VydmVyXCIsIHByb3BOYW1lKSA6IGNvcmUucHJvcEVxKGtleSwgcHJvcE5hbWUpO1xyXG4gICAgICBsZXQgcHJvcCA9IGNvcmUuYXJyYXlGaXJzdChwYXJlbnRUeXBlLmdldFByb3BlcnRpZXMoKSwgZm4pO1xyXG4gICAgICBpZiAocHJvcCkge1xyXG4gICAgICAgIHBhcmVudFR5cGUgPSAocHJvcCBpbnN0YW5jZW9mIE5hdmlnYXRpb25Qcm9wZXJ0eSkgPyBwcm9wLmVudGl0eVR5cGUgOiBwcm9wLmRhdGFUeXBlIGFzIENvbXBsZXhUeXBlO1xyXG4gICAgICAgIC8vIHBhcmVudFR5cGUgPSBwcm9wLmlzTmF2aWdhdGlvblByb3BlcnR5ID8gcHJvcC5lbnRpdHlUeXBlIDogcHJvcC5kYXRhVHlwZTtcclxuICAgICAgfSBlbHNlIGlmICh0aHJvd0lmTm90Rm91bmQpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ1bmFibGUgdG8gbG9jYXRlIHByb3BlcnR5OiBcIiArIHByb3BOYW1lICsgXCIgb24gZW50aXR5VHlwZTogXCIgKyBwYXJlbnRUeXBlLm5hbWUpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIG9rID0gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHByb3A7XHJcbiAgICB9O1xyXG5cclxuICAgIGxldCBwcm9wcyA9IHByb3BlcnR5TmFtZXMubWFwKGdldFByb3BzKSBhcyBFbnRpdHlQcm9wZXJ0eVtdO1xyXG4gICAgcmV0dXJuIG9rID8gcHJvcHMgOiBudWxsO1xyXG4gIH1cclxuXHJcbiAgLyoqIEZvciB1c2UgaW4gcGx1Z2dhYmxlIGFkYXB0ZXJzLiAqL1xyXG4gIC8vIFRPRE86IGRvY3VtZW50IHVzZVxyXG4gIGNsaWVudFByb3BlcnR5UGF0aFRvU2VydmVyKHByb3BlcnR5UGF0aDogc3RyaW5nLCBkZWxpbWl0ZXI6IHN0cmluZyA9ICcuJykge1xyXG4gICAgbGV0IHByb3BOYW1lczogc3RyaW5nW107XHJcbiAgICBpZiAodGhpcy5pc0Fub255bW91cykge1xyXG4gICAgICBsZXQgZm4gPSB0aGlzLm1ldGFkYXRhU3RvcmUubmFtaW5nQ29udmVudGlvbi5jbGllbnRQcm9wZXJ0eU5hbWVUb1NlcnZlcjtcclxuICAgICAgcHJvcE5hbWVzID0gcHJvcGVydHlQYXRoLnNwbGl0KFwiLlwiKS5tYXAoZnVuY3Rpb24gKHByb3BOYW1lKSB7XHJcbiAgICAgICAgcmV0dXJuIGZuKHByb3BOYW1lKTtcclxuICAgICAgfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsZXQgcHJvcHMgPSB0aGlzLmdldFByb3BlcnRpZXNPblBhdGgocHJvcGVydHlQYXRoLCBmYWxzZSwgdHJ1ZSk7XHJcbiAgICAgIHByb3BOYW1lcyA9IHByb3BzIS5tYXAoKHByb3A6IEVudGl0eVByb3BlcnR5KSA9PiBwcm9wLm5hbWVPblNlcnZlcik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcHJvcE5hbWVzLmpvaW4oZGVsaW1pdGVyKTtcclxuICB9XHJcblxyXG4gIC8qKiBGb3IgdXNlIGluIHBsdWdnYWJsZSBhZGFwdGVycy4gKi9cclxuICAvLyBUT0RPOiBkb2N1bWVudCB1c2VcclxuICBnZXRFbnRpdHlLZXlGcm9tUmF3RW50aXR5KHJhd0VudGl0eTogYW55LCByYXdWYWx1ZUZuOiBGdW5jdGlvbikge1xyXG4gICAgbGV0IGtleVZhbHVlcyA9IHRoaXMua2V5UHJvcGVydGllcy5tYXAoKGRwKSA9PiB7XHJcbiAgICAgIGxldCB2YWwgPSByYXdWYWx1ZUZuKHJhd0VudGl0eSwgZHApO1xyXG4gICAgICByZXR1cm4gRGF0YVR5cGUucGFyc2VSYXdWYWx1ZSh2YWwsIGRwLmRhdGFUeXBlIGFzIERhdGFUeXBlKTtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIG5ldyBFbnRpdHlLZXkodGhpcywga2V5VmFsdWVzKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF91cGRhdGVUYXJnZXRGcm9tUmF3KHRhcmdldDogU3RydWN0dXJhbE9iamVjdCwgcmF3OiBhbnksIHJhd1ZhbHVlRm46IEZ1bmN0aW9uKSB7XHJcbiAgICAvLyBjYWxsZWQgcmVjdXJzaXZlbHkgZm9yIGNvbXBsZXggcHJvcGVydGllc1xyXG4gICAgdGhpcy5kYXRhUHJvcGVydGllcy5mb3JFYWNoKChkcCkgPT4ge1xyXG4gICAgICBpZiAoIWRwLmlzU2V0dGFibGUpIHJldHVybjtcclxuICAgICAgbGV0IHJhd1ZhbCA9IHJhd1ZhbHVlRm4ocmF3LCBkcCk7XHJcbiAgICAgIGlmIChyYXdWYWwgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xyXG4gICAgICBsZXQgZGF0YVR5cGUgPSBkcC5kYXRhVHlwZTsgLy8gdGhpcyB3aWxsIGJlIGEgY29tcGxleFR5cGUgd2hlbiBkcCBpcyBhIGNvbXBsZXhQcm9wZXJ0eVxyXG4gICAgICBsZXQgb2xkVmFsOiBhbnk7XHJcbiAgICAgIGlmIChkcC5pc0NvbXBsZXhQcm9wZXJ0eSkge1xyXG4gICAgICAgIGxldCBjb21wbGV4VHlwZSA9IGRwLmRhdGFUeXBlIGFzIENvbXBsZXhUeXBlO1xyXG4gICAgICAgIGlmIChyYXdWYWwgPT09IG51bGwpIHJldHVybjsgLy8gcmF3VmFsIG1heSBiZSBudWxsIGluIG5vc3FsIGRicyB3aGVyZSBpdCB3YXMgbmV2ZXIgZGVmaW5lZCBmb3IgdGhlIGdpdmVuIHJvdy5cclxuICAgICAgICBvbGRWYWwgPSB0YXJnZXQuZ2V0UHJvcGVydHkoZHAubmFtZSk7XHJcbiAgICAgICAgaWYgKGRwLmlzU2NhbGFyKSB7XHJcbiAgICAgICAgICBjb21wbGV4VHlwZS5fdXBkYXRlVGFyZ2V0RnJvbVJhdyhvbGRWYWwsIHJhd1ZhbCwgcmF3VmFsdWVGbik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJhd1ZhbCkpIHtcclxuICAgICAgICAgICAgbGV0IG5ld1ZhbCA9IHJhd1ZhbC5tYXAoZnVuY3Rpb24gKHJhd0NvKSB7XHJcbiAgICAgICAgICAgICAgbGV0IG5ld0NvID0gY29tcGxleFR5cGUuX2NyZWF0ZUluc3RhbmNlQ29yZSh0YXJnZXQsIGRwKTtcclxuICAgICAgICAgICAgICBjb21wbGV4VHlwZS5fdXBkYXRlVGFyZ2V0RnJvbVJhdyhuZXdDbywgcmF3Q28sIHJhd1ZhbHVlRm4pO1xyXG4gICAgICAgICAgICAgIGNvbXBsZXhUeXBlLl9pbml0aWFsaXplSW5zdGFuY2UobmV3Q28pO1xyXG4gICAgICAgICAgICAgIHJldHVybiBuZXdDbztcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGlmICghY29yZS5hcnJheUVxdWFscyhvbGRWYWwsIG5ld1ZhbCwgY29FcXVhbHMpKSB7XHJcbiAgICAgICAgICAgICAgLy8gY2xlYXIgdGhlIG9sZCBhcnJheSBhbmQgcHVzaCBuZXcgb2JqZWN0cyBpbnRvIGl0LlxyXG4gICAgICAgICAgICAgIG9sZFZhbC5sZW5ndGggPSAwO1xyXG4gICAgICAgICAgICAgIG5ld1ZhbC5mb3JFYWNoKGZ1bmN0aW9uIChudikge1xyXG4gICAgICAgICAgICAgICAgb2xkVmFsLnB1c2gobnYpO1xyXG4gICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBvbGRWYWwubGVuZ3RoID0gMDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKGRwLmlzU2NhbGFyKSB7XHJcbiAgICAgICAgICBsZXQgbmV3VmFsID0gRGF0YVR5cGUucGFyc2VSYXdWYWx1ZShyYXdWYWwsIGRhdGFUeXBlIGFzIERhdGFUeXBlKTtcclxuICAgICAgICAgIHRhcmdldC5zZXRQcm9wZXJ0eShkcC5uYW1lLCBuZXdWYWwpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBvbGRWYWwgPSB0YXJnZXQuZ2V0UHJvcGVydHkoZHAubmFtZSk7XHJcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyYXdWYWwpKSB7XHJcbiAgICAgICAgICAgIC8vIG5lZWQgdG8gY29tcGFyZSB2YWx1ZXNcclxuICAgICAgICAgICAgbGV0IG5ld1ZhbCA9IHJhd1ZhbC5tYXAoKHJ2KSA9PiB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIERhdGFUeXBlLnBhcnNlUmF3VmFsdWUocnYsIGRhdGFUeXBlIGFzIERhdGFUeXBlKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGlmICghY29yZS5hcnJheUVxdWFscyhvbGRWYWwsIG5ld1ZhbCkpIHtcclxuICAgICAgICAgICAgICAvLyBjbGVhciB0aGUgb2xkIGFycmF5IGFuZCBwdXNoIG5ldyBvYmplY3RzIGludG8gaXQuXHJcbiAgICAgICAgICAgICAgb2xkVmFsLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgICAgICAgbmV3VmFsLmZvckVhY2goZnVuY3Rpb24gKG52KSB7XHJcbiAgICAgICAgICAgICAgICBvbGRWYWwucHVzaChudik7XHJcbiAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIG9sZFZhbC5sZW5ndGggPSAwO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIC8vIGlmIG1lcmdpbmcgZnJvbSBhbiBpbXBvcnQgdGhlbiByYXcgd2lsbCBoYXZlIGFuIGVudGl0eUFzcGVjdCBvciBhIGNvbXBsZXhBc3BlY3RcclxuICAgIGxldCByYXdBc3BlY3QgPSByYXcuZW50aXR5QXNwZWN0IHx8IHJhdy5jb21wbGV4QXNwZWN0O1xyXG4gICAgaWYgKHJhd0FzcGVjdCkge1xyXG5cclxuICAgICAgbGV0IHRhcmdldEFzcGVjdCA9IEVudGl0eUFzcGVjdC5pc0VudGl0eSh0YXJnZXQpID8gdGFyZ2V0LmVudGl0eUFzcGVjdCA6IHRhcmdldC5jb21wbGV4QXNwZWN0O1xyXG4gICAgICBpZiAocmF3QXNwZWN0Lm9yaWdpbmFsVmFsdWVzTWFwKSB7XHJcbiAgICAgICAgdGFyZ2V0QXNwZWN0Lm9yaWdpbmFsVmFsdWVzID0gcmF3QXNwZWN0Lm9yaWdpbmFsVmFsdWVzTWFwO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChyYXdBc3BlY3QuZXh0cmFNZXRhZGF0YSkge1xyXG4gICAgICAgIHRhcmdldEFzcGVjdC5leHRyYU1ldGFkYXRhID0gcmF3QXNwZWN0LmV4dHJhTWV0YWRhdGE7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG5cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIEVudGl0eVR5cGUuXHJcbiAgKiovXHJcbiAgdG9TdHJpbmcoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5uYW1lO1xyXG4gIH1cclxuXHJcbiAgdG9KU09OKCkge1xyXG4gICAgcmV0dXJuIGNvcmUudG9Kc29uKHRoaXMsIHtcclxuICAgICAgc2hvcnROYW1lOiBudWxsLFxyXG4gICAgICBuYW1lc3BhY2U6IG51bGwsXHJcbiAgICAgIGJhc2VUeXBlTmFtZTogbnVsbCxcclxuICAgICAgaXNBYnN0cmFjdDogZmFsc2UsXHJcbiAgICAgIGF1dG9HZW5lcmF0ZWRLZXlUeXBlOiBudWxsLCAvLyBkbyBub3Qgc3VwcHJlc3MgZGVmYXVsdCB2YWx1ZVxyXG4gICAgICBkZWZhdWx0UmVzb3VyY2VOYW1lOiBudWxsLFxyXG4gICAgICBkYXRhUHJvcGVydGllczogbG9jYWxQcm9wc09ubHksXHJcbiAgICAgIG5hdmlnYXRpb25Qcm9wZXJ0aWVzOiBsb2NhbFByb3BzT25seSxcclxuICAgICAgdmFsaWRhdG9yczogbnVsbCxcclxuICAgICAgY3VzdG9tOiBudWxsXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF91cGRhdGVOYW1lcyhwcm9wZXJ0eTogRW50aXR5UHJvcGVydHkpIHtcclxuICAgIGxldCBuYyA9IHRoaXMubWV0YWRhdGFTdG9yZS5uYW1pbmdDb252ZW50aW9uO1xyXG4gICAgdXBkYXRlQ2xpZW50U2VydmVyTmFtZXMobmMsIHByb3BlcnR5LCBcIm5hbWVcIik7XHJcblxyXG4gICAgaWYgKHByb3BlcnR5LmlzTmF2aWdhdGlvblByb3BlcnR5KSB7XHJcbiAgICAgIHVwZGF0ZUNsaWVudFNlcnZlck5hbWVzKG5jLCBwcm9wZXJ0eSwgXCJmb3JlaWduS2V5TmFtZXNcIik7XHJcbiAgICAgIHVwZGF0ZUNsaWVudFNlcnZlck5hbWVzKG5jLCBwcm9wZXJ0eSwgXCJpbnZGb3JlaWduS2V5TmFtZXNcIik7XHJcblxyXG4gICAgICAvLyB0aGVzZSB3aWxsIGdldCBzZXQgbGF0ZXIgdmlhIF91cGRhdGVOcHNcclxuICAgICAgLy8gdGhpcy5pbnZlcnNlXHJcbiAgICAgIC8vIHRoaXMuZW50aXR5VHlwZVxyXG4gICAgICAvLyB0aGlzLnJlbGF0ZWREYXRhUHJvcGVydGllc1xyXG4gICAgICAvLyAgICBkYXRhUHJvcGVydHkucmVsYXRlZE5hdmlnYXRpb25Qcm9wZXJ0eVxyXG4gICAgICAvLyAgICBkYXRhUHJvcGVydHkuaW52ZXJzZU5hdmlnYXRpb25Qcm9wZXJ0eVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2NoZWNrTmF2UHJvcGVydHkobmF2aWdhdGlvblByb3BlcnR5OiBOYXZpZ2F0aW9uUHJvcGVydHkgfCBzdHJpbmcpIHtcclxuICAgIC8vIGlmIChuYXZpZ2F0aW9uUHJvcGVydHkuaXNOYXZpZ2F0aW9uUHJvcGVydHkpIHtcclxuICAgIGlmIChuYXZpZ2F0aW9uUHJvcGVydHkgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uUHJvcGVydHkpIHtcclxuICAgICAgaWYgKG5hdmlnYXRpb25Qcm9wZXJ0eS5wYXJlbnRUeXBlICE9PSB0aGlzKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGNvcmUuZm9ybWF0U3RyaW5nKFwiVGhlIG5hdmlnYXRpb25Qcm9wZXJ0eSAnJTEnIGlzIG5vdCBhIHByb3BlcnR5IG9mIGVudGl0eSB0eXBlICclMidcIixcclxuICAgICAgICAgIG5hdmlnYXRpb25Qcm9wZXJ0eS5uYW1lLCB0aGlzLm5hbWUpKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gbmF2aWdhdGlvblByb3BlcnR5O1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlb2YgKG5hdmlnYXRpb25Qcm9wZXJ0eSkgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIGxldCBucCA9IHRoaXMuZ2V0UHJvcGVydHkobmF2aWdhdGlvblByb3BlcnR5KTtcclxuICAgICAgLy8gaWYgKG5wICYmIG5wLmlzTmF2aWdhdGlvblByb3BlcnR5KSByZXR1cm4gbnA7XHJcbiAgICAgIGlmIChucCAmJiBucCBpbnN0YW5jZW9mIE5hdmlnYXRpb25Qcm9wZXJ0eSkgcmV0dXJuIG5wO1xyXG4gICAgfVxyXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlICduYXZpZ2F0aW9uUHJvcGVydHknIHBhcmFtZXRlciBtdXN0IGVpdGhlciBiZSBhIE5hdmlnYXRpb25Qcm9wZXJ0eSBvciB0aGUgbmFtZSBvZiBhIE5hdmlnYXRpb25Qcm9wZXJ0eVwiKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9hZGREYXRhUHJvcGVydHkoZHA6IERhdGFQcm9wZXJ0eSkge1xyXG5cclxuICAgIHRoaXMuZGF0YVByb3BlcnRpZXMucHVzaChkcCk7XHJcblxyXG4gICAgaWYgKGRwLmlzUGFydE9mS2V5KSB7XHJcbiAgICAgIHRoaXMua2V5UHJvcGVydGllcy5wdXNoKGRwKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoZHAuaXNDb21wbGV4UHJvcGVydHkpIHtcclxuICAgICAgdGhpcy5jb21wbGV4UHJvcGVydGllcy5wdXNoKGRwKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoZHAuY29uY3VycmVuY3lNb2RlICYmIGRwLmNvbmN1cnJlbmN5TW9kZSAhPT0gXCJOb25lXCIpIHtcclxuICAgICAgdGhpcy5jb25jdXJyZW5jeVByb3BlcnRpZXMucHVzaChkcCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGRwLmlzVW5tYXBwZWQpIHtcclxuICAgICAgdGhpcy51bm1hcHBlZFByb3BlcnRpZXMucHVzaChkcCk7XHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2FkZE5hdmlnYXRpb25Qcm9wZXJ0eShucDogTmF2aWdhdGlvblByb3BlcnR5KSB7XHJcblxyXG4gICAgdGhpcy5uYXZpZ2F0aW9uUHJvcGVydGllcy5wdXNoKG5wKTtcclxuXHJcbiAgICBpZiAoIWlzUXVhbGlmaWVkVHlwZU5hbWUobnAuZW50aXR5VHlwZU5hbWUpKSB7XHJcbiAgICAgIG5wLmVudGl0eVR5cGVOYW1lID0gcXVhbGlmeVR5cGVOYW1lKG5wLmVudGl0eVR5cGVOYW1lLCB0aGlzLm5hbWVzcGFjZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfdXBkYXRlQ3BzKCkge1xyXG4gICAgbGV0IG1ldGFkYXRhU3RvcmUgPSB0aGlzLm1ldGFkYXRhU3RvcmU7XHJcbiAgICBsZXQgaW5jb21wbGV0ZVR5cGVNYXAgPSBtZXRhZGF0YVN0b3JlLl9pbmNvbXBsZXRlQ29tcGxleFR5cGVNYXA7XHJcbiAgICB0aGlzLmNvbXBsZXhQcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKGNwKSB7XHJcbiAgICAgIGlmIChjcC5jb21wbGV4VHlwZSkgcmV0dXJuO1xyXG4gICAgICBpZiAoIXJlc29sdmVDcChjcCwgbWV0YWRhdGFTdG9yZSkpIHtcclxuICAgICAgICBjb3JlLmdldEFycmF5KGluY29tcGxldGVUeXBlTWFwLCBjcC5jb21wbGV4VHlwZU5hbWUpLnB1c2goY3ApO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAodGhpcy5pc0NvbXBsZXhUeXBlKSB7XHJcbiAgICAgIChpbmNvbXBsZXRlVHlwZU1hcFt0aGlzLm5hbWVdIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChjcDogRGF0YVByb3BlcnR5KSB7XHJcbiAgICAgICAgcmVzb2x2ZUNwKGNwLCBtZXRhZGF0YVN0b3JlKTtcclxuICAgICAgfSk7XHJcbiAgICAgIGRlbGV0ZSBpbmNvbXBsZXRlVHlwZU1hcFt0aGlzLm5hbWVdO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VwZGF0ZU5wcygpIHtcclxuICAgIGxldCBtZXRhZGF0YVN0b3JlID0gdGhpcy5tZXRhZGF0YVN0b3JlO1xyXG5cclxuICAgIC8vIHJlc29sdmUgYWxsIG5hdlByb3BzIGZvciB0aGlzIGVudGl0eVR5cGVcclxuICAgIHRoaXMubmF2aWdhdGlvblByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAobnApIHtcclxuICAgICAgdHJ5UmVzb2x2ZU5wKG5wLCBtZXRhZGF0YVN0b3JlKTtcclxuICAgIH0pO1xyXG4gICAgbGV0IGluY29tcGxldGVUeXBlTWFwID0gbWV0YWRhdGFTdG9yZS5faW5jb21wbGV0ZVR5cGVNYXA7XHJcbiAgICAvLyBuZXh0IHJlc29sdmUgYWxsIG5hdlByb3AgdGhhdCBwb2ludCB0byB0aGlzIGVudGl0eVR5cGUuXHJcbiAgICAoaW5jb21wbGV0ZVR5cGVNYXBbdGhpcy5uYW1lXSB8fCBbXSkuZm9yRWFjaChmdW5jdGlvbiAobnA6IE5hdmlnYXRpb25Qcm9wZXJ0eSkge1xyXG4gICAgICB0cnlSZXNvbHZlTnAobnAsIG1ldGFkYXRhU3RvcmUpO1xyXG4gICAgfSk7XHJcbiAgICAvLyBldmVyeSBuYXZQcm9wIHRoYXQgcG9pbnRlZCB0byB0aGlzIHR5cGUgc2hvdWxkIG5vdyBiZSByZXNvbHZlZFxyXG4gICAgZGVsZXRlIGluY29tcGxldGVUeXBlTWFwW3RoaXMubmFtZV07XHJcbiAgfVxyXG59XHJcblxyXG5FbnRpdHlUeXBlLnByb3RvdHlwZS5fJHR5cGVOYW1lID0gXCJFbnRpdHlUeXBlXCI7XHJcblxyXG5mdW5jdGlvbiBnZXRSYXdWYWx1ZUZyb21Db25maWcocmF3RW50aXR5OiBhbnksIGRwOiBEYXRhUHJvcGVydHkpIHtcclxuICAvLyAndHJ1ZScgZm9yayBjYW4gaGFwcGVuIGlmIGFuIGluaXRpYWxpemVyIGNvbnRhaW5zIGFuIGFjdGF1bCBpbnN0YW5jZSBvZiBhbiBhbHJlYWR5IGNyZWF0ZWQgY29tcGxleCBvYmplY3QuXHJcbiAgcmV0dXJuIChyYXdFbnRpdHkuZW50aXR5QXNwZWN0IHx8IHJhd0VudGl0eS5jb21wbGV4QXNwZWN0KSA/IHJhd0VudGl0eS5nZXRQcm9wZXJ0eShkcC5uYW1lKSA6IHJhd0VudGl0eVtkcC5uYW1lXTtcclxufVxyXG5cclxuZnVuY3Rpb24gdXBkYXRlQ2xpZW50U2VydmVyTmFtZXMobmM6IE5hbWluZ0NvbnZlbnRpb24sIHBhcmVudDogYW55LCBjbGllbnRQcm9wTmFtZTogc3RyaW5nKSB7XHJcbiAgbGV0IHNlcnZlclByb3BOYW1lID0gY2xpZW50UHJvcE5hbWUgKyBcIk9uU2VydmVyXCI7XHJcbiAgbGV0IGNsaWVudE5hbWUgPSBwYXJlbnRbY2xpZW50UHJvcE5hbWVdO1xyXG4gIGlmIChjbGllbnROYW1lICYmIGNsaWVudE5hbWUubGVuZ3RoKSB7XHJcbiAgICAvLyBpZiAocGFyZW50LmlzVW5tYXBwZWQpIHJldHVybjtcclxuICAgIGxldCBzZXJ2ZXJOYW1lcyA9IGNvcmUudG9BcnJheShjbGllbnROYW1lKS5tYXAoZnVuY3Rpb24gKGNOYW1lKSB7XHJcbiAgICAgIGxldCBzTmFtZSA9IG5jLmNsaWVudFByb3BlcnR5TmFtZVRvU2VydmVyKGNOYW1lLCBwYXJlbnQpO1xyXG4gICAgICBsZXQgdGVzdE5hbWUgPSBuYy5zZXJ2ZXJQcm9wZXJ0eU5hbWVUb0NsaWVudChzTmFtZSwgcGFyZW50KTtcclxuICAgICAgaWYgKGNOYW1lICE9PSB0ZXN0TmFtZSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWluZ0NvbnZlbnRpb24gZm9yIHRoaXMgY2xpZW50IHByb3BlcnR5IG5hbWUgZG9lcyBub3Qgcm91bmR0cmlwIHByb3Blcmx5OlwiICsgY05hbWUgKyBcIi0tPlwiICsgdGVzdE5hbWUpO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBzTmFtZTtcclxuICAgIH0pO1xyXG4gICAgcGFyZW50W3NlcnZlclByb3BOYW1lXSA9IEFycmF5LmlzQXJyYXkoY2xpZW50TmFtZSkgPyBzZXJ2ZXJOYW1lcyA6IHNlcnZlck5hbWVzWzBdO1xyXG4gIH0gZWxzZSB7XHJcbiAgICBsZXQgc2VydmVyTmFtZSA9IHBhcmVudFtzZXJ2ZXJQcm9wTmFtZV07XHJcbiAgICBpZiAoKCFzZXJ2ZXJOYW1lKSB8fCBzZXJ2ZXJOYW1lLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xyXG4gICAgbGV0IGNsaWVudE5hbWVzID0gY29yZS50b0FycmF5KHNlcnZlck5hbWUpLm1hcChmdW5jdGlvbiAoc05hbWUpIHtcclxuICAgICAgbGV0IGNOYW1lID0gbmMuc2VydmVyUHJvcGVydHlOYW1lVG9DbGllbnQoc05hbWUsIHBhcmVudCk7XHJcbiAgICAgIGxldCB0ZXN0TmFtZSA9IG5jLmNsaWVudFByb3BlcnR5TmFtZVRvU2VydmVyKGNOYW1lLCBwYXJlbnQpO1xyXG4gICAgICBpZiAoc05hbWUgIT09IHRlc3ROYW1lKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtaW5nQ29udmVudGlvbiBmb3IgdGhpcyBzZXJ2ZXIgcHJvcGVydHkgbmFtZSBkb2VzIG5vdCByb3VuZHRyaXAgcHJvcGVybHk6XCIgKyBzTmFtZSArIFwiLS0+XCIgKyB0ZXN0TmFtZSk7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGNOYW1lO1xyXG4gICAgfSk7XHJcbiAgICBwYXJlbnRbY2xpZW50UHJvcE5hbWVdID0gQXJyYXkuaXNBcnJheShzZXJ2ZXJOYW1lKSA/IGNsaWVudE5hbWVzIDogY2xpZW50TmFtZXNbMF07XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVFbXB0eUN0b3IodHlwZTogYW55KSB7XHJcbiAgaWYgKGNvbmZpZy5ub0V2YWwpIHtcclxuICAgIGxldCBFbnRpdHkgPSBmdW5jdGlvbigpIHt9O1xyXG4gICAgcmV0dXJuIEVudGl0eTtcclxuICB9IGVsc2Uge1xyXG4gICAgbGV0IG5hbWUgPSB0eXBlLm5hbWUucmVwbGFjZSgvXFxXL2csICdfJyk7XHJcbiAgICByZXR1cm4gRnVuY3Rpb24oJ3JldHVybiBmdW5jdGlvbiAnICsgbmFtZSArICcoKXt9JykoKTtcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNvRXF1YWxzKGNvMTogQ29tcGxleE9iamVjdCwgY28yOiBDb21wbGV4T2JqZWN0KTogYm9vbGVhbiB7XHJcbiAgbGV0IGNvbXBsZXhUeXBlID0gY28xLmNvbXBsZXhBc3BlY3QhLnBhcmVudFByb3BlcnR5IS5kYXRhVHlwZSBhcyBDb21wbGV4VHlwZTtcclxuICBsZXQgZGF0YVByb3BzID0gY29tcGxleFR5cGUuZGF0YVByb3BlcnRpZXM7XHJcbiAgbGV0IGFyZUVxdWFsID0gZGF0YVByb3BzLmV2ZXJ5KGZ1bmN0aW9uIChkcCkge1xyXG4gICAgaWYgKCFkcC5pc1NldHRhYmxlKSByZXR1cm4gdHJ1ZTtcclxuICAgIGxldCB2MSA9IGNvMS5nZXRQcm9wZXJ0eShkcC5uYW1lKTtcclxuICAgIGxldCB2MiA9IGNvMi5nZXRQcm9wZXJ0eShkcC5uYW1lKTtcclxuICAgIGlmIChkcC5pc0NvbXBsZXhQcm9wZXJ0eSAmJiBkcC5pc1NjYWxhcikge1xyXG4gICAgICByZXR1cm4gY29FcXVhbHModjEsIHYyKTtcclxuICAgIH1cclxuICAgIGVsc2UgaWYgKGRwLmlzQ29tcGxleFByb3BlcnR5ICYmICFkcC5pc1NjYWxhcikge1xyXG4gICAgICByZXR1cm4gY29yZS5hcnJheUVxdWFscyh2MSwgdjIsIGNvRXF1YWxzKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGxldCBkYXRhVHlwZSA9IDxhbnk+ZHAuZGF0YVR5cGU7IC8vIHRoaXMgd2lsbCBiZSBhIGNvbXBsZXhUeXBlIHdoZW4gZHAgaXMgYSBjb21wbGV4UHJvcGVydHlcclxuICAgICAgcmV0dXJuICh2MSA9PT0gdjIgfHwgKGRhdGFUeXBlICYmIGRhdGFUeXBlLm5vcm1hbGl6ZSAmJiB2MSAmJiB2MiAmJiBkYXRhVHlwZS5ub3JtYWxpemUodjEpID09PSBkYXRhVHlwZS5ub3JtYWxpemUodjIpKSk7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgcmV0dXJuIGFyZUVxdWFsO1xyXG59XHJcblxyXG5mdW5jdGlvbiBsb2NhbFByb3BzT25seShwcm9wczogRW50aXR5UHJvcGVydHlbXSkge1xyXG4gIHJldHVybiBwcm9wcy5maWx0ZXIoZnVuY3Rpb24gKHByb3ApIHtcclxuICAgIHJldHVybiBwcm9wLmJhc2VQcm9wZXJ0eSA9PSBudWxsO1xyXG4gIH0pO1xyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gcmVzb2x2ZUNwKGNwOiBEYXRhUHJvcGVydHksIG1ldGFkYXRhU3RvcmU6IE1ldGFkYXRhU3RvcmUpIHtcclxuICBsZXQgY29tcGxleFR5cGUgPSBtZXRhZGF0YVN0b3JlLl9nZXRTdHJ1Y3R1cmFsVHlwZShjcC5jb21wbGV4VHlwZU5hbWUsIHRydWUpO1xyXG4gIGlmICghY29tcGxleFR5cGUpIHJldHVybiBmYWxzZTtcclxuICBpZiAoIShjb21wbGV4VHlwZSBpbnN0YW5jZW9mIENvbXBsZXhUeXBlKSkge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIHJlc29sdmUgQ29tcGxleFR5cGUgd2l0aCB0aGUgbmFtZTogXCIgKyBjcC5jb21wbGV4VHlwZU5hbWUgKyBcIiBmb3IgdGhlIHByb3BlcnR5OiBcIiArIGNwLm5hbWUpO1xyXG4gIH1cclxuICBjcC5kYXRhVHlwZSA9IGNvbXBsZXhUeXBlO1xyXG4gIGNwLmRlZmF1bHRWYWx1ZSA9IG51bGw7XHJcbiAgcmV0dXJuIHRydWU7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHRyeVJlc29sdmVOcChucDogTmF2aWdhdGlvblByb3BlcnR5LCBtZXRhZGF0YVN0b3JlOiBNZXRhZGF0YVN0b3JlKSB7XHJcbiAgaWYgKG5wLmVudGl0eVR5cGUpIHJldHVybiB0cnVlO1xyXG5cclxuICBsZXQgZW50aXR5VHlwZSA9IG1ldGFkYXRhU3RvcmUuX2dldFN0cnVjdHVyYWxUeXBlKG5wLmVudGl0eVR5cGVOYW1lLCB0cnVlKSBhcyBFbnRpdHlUeXBlO1xyXG4gIGlmIChlbnRpdHlUeXBlKSB7XHJcbiAgICBucC5lbnRpdHlUeXBlID0gZW50aXR5VHlwZTtcclxuICAgIG5wLl9yZXNvbHZlTnAoKTtcclxuICAgIC8vIGRvbid0IGJvdGhlciByZW1vdmluZyAtIF91cGRhdGVOcHMgd2lsbCBkbyBpdCBsYXRlci5cclxuICAgIC8vIF9fYXJyYXlSZW1vdmVJdGVtKGluY29tcGxldGVOcHMsIG5wLCBmYWxzZSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIGxldCBpbmNvbXBsZXRlTnBzID0gY29yZS5nZXRBcnJheShtZXRhZGF0YVN0b3JlLl9pbmNvbXBsZXRlVHlwZU1hcCwgbnAuZW50aXR5VHlwZU5hbWUpO1xyXG4gICAgY29yZS5hcnJheUFkZEl0ZW1VbmlxdWUoaW5jb21wbGV0ZU5wcywgbnApO1xyXG4gIH1cclxuICByZXR1cm4gISFlbnRpdHlUeXBlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBjYWxjVW5tYXBwZWRQcm9wZXJ0aWVzKHN0eXBlOiBTdHJ1Y3R1cmFsVHlwZSwgaW5zdGFuY2U6IGFueSkge1xyXG4gIGxldCBtZXRhZGF0YVByb3BOYW1lcyA9IHN0eXBlLmdldFByb3BlcnR5TmFtZXMoKTtcclxuICBsZXQgbW9kZWxMaWIgPSBjb25maWcuaW50ZXJmYWNlUmVnaXN0cnkubW9kZWxMaWJyYXJ5LmdldERlZmF1bHRJbnN0YW5jZSgpO1xyXG4gIGxldCB0cmFja2FibGVQcm9wTmFtZXMgPSBtb2RlbExpYi5nZXRUcmFja2FibGVQcm9wZXJ0eU5hbWVzKGluc3RhbmNlKTtcclxuICB0cmFja2FibGVQcm9wTmFtZXMuZm9yRWFjaChmdW5jdGlvbiAocG46IHN0cmluZykge1xyXG4gICAgaWYgKG1ldGFkYXRhUHJvcE5hbWVzLmluZGV4T2YocG4pID09PSAtMSkge1xyXG4gICAgICBsZXQgdmFsID0gaW5zdGFuY2VbcG5dO1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgdmFsID09PSBcImZ1bmN0aW9uXCIpIHZhbCA9IHZhbCgpO1xyXG4gICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgIH1cclxuICAgICAgbGV0IGR0ID0gRGF0YVR5cGUuZnJvbVZhbHVlKHZhbCk7XHJcbiAgICAgIGxldCBuZXdQcm9wID0gbmV3IERhdGFQcm9wZXJ0eSh7XHJcbiAgICAgICAgbmFtZTogcG4sXHJcbiAgICAgICAgZGF0YVR5cGU6IGR0LFxyXG4gICAgICAgIGlzTnVsbGFibGU6IHRydWUsXHJcbiAgICAgICAgaXNVbm1hcHBlZDogdHJ1ZVxyXG4gICAgICB9KTtcclxuICAgICAgbmV3UHJvcC5pc1NldHRhYmxlID0gY29yZS5pc1NldHRhYmxlKGluc3RhbmNlLCBwbik7XHJcbiAgICAgIGlmIChzdHlwZSBpbnN0YW5jZW9mIEVudGl0eVR5cGUgJiYgc3R5cGUuc3VidHlwZXMgIT0gbnVsbCAmJiBzdHlwZS5zdWJ0eXBlcy5sZW5ndGgpIHtcclxuICAgICAgICBzdHlwZS5nZXRTZWxmQW5kU3VidHlwZXMoKS5mb3JFYWNoKChzdCkgPT4ge1xyXG4gICAgICAgICAgc3QuX2FkZFByb3BlcnR5Q29yZShuZXcgRGF0YVByb3BlcnR5KG5ld1Byb3ApKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBzdHlwZS5fYWRkUHJvcGVydHlDb3JlKG5ld1Byb3ApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ29tcGxleFR5cGVDb25maWcge1xyXG4gIHNob3J0TmFtZT86IHN0cmluZztcclxuICBuYW1lc3BhY2U/OiBzdHJpbmc7XHJcbiAgZGF0YVByb3BlcnRpZXM/OiBEYXRhUHJvcGVydHlbXSB8IE9iamVjdFtdIHwgT2JqZWN0O1xyXG4gIGlzQ29tcGxleFR5cGU/OiBib29sZWFuOyAgLy8gbmVlZGVkIGJlY2F1c2UgdGhpcyBjdG9yIGNhbiBnZXQgY2FsbGVkIGZyb20gdGhlIGFkZEVudGl0eVR5cGUgbWV0aG9kIHdoaWNoIG5lZWRzIHRoZSBpc0NvbXBsZXhUeXBlIHByb3BcclxuICBjdXN0b20/OiBPYmplY3Q7XHJcbn1cclxuXHJcbi8qKiAgQ29udGFpbmVyIGZvciBhbGwgb2YgdGhlIG1ldGFkYXRhIGFib3V0IGEgc3BlY2lmaWMgdHlwZSBvZiBDb21wbGV4IG9iamVjdC5cclxuPiAgICAgbGV0IGNvbXBsZXhUeXBlID0gbmV3IENvbXBsZXhUeXBlKCB7XHJcbj4gICAgICAgICBzaG9ydE5hbWU6IFwiYWRkcmVzc1wiLFxyXG4+ICAgICAgICAgbmFtZXNwYWNlOiBcIm15QXBwTmFtZXNwYWNlXCJcclxuPiAgICAgfSk7XHJcbkBwYXJhbSBjb25maWcgLSBDb25maWd1cmF0aW9uIHNldHRpbmdzXHJcbioqL1xyXG5leHBvcnQgY2xhc3MgQ29tcGxleFR5cGUge1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF8kdHlwZU5hbWU6IHN0cmluZzsgLy8gb24gcHJvdG9cclxuICAvKiogRm9yIHBvbHltb3JwaGljIHB1cnBvc2Ugb25seSAtIGFsd2F5cyB0cnVlIGhlcmUgKi9cclxuICBpc0NvbXBsZXhUeXBlID0gdHJ1ZTtcclxuXHJcbiAgLyoqIFRoZSBbW01ldGFkYXRhU3RvcmVdXSBjb250YWluaW5nIHRoaXMgQ29tcGxleFR5cGUuICovXHJcbiAgbWV0YWRhdGFTdG9yZTogTWV0YWRhdGFTdG9yZTtcclxuXHJcbiAgLyoqICBUaGUgZnVsbHkgcXVhbGlmZWQgbmFtZSBvZiB0aGlzIENvbXBsZXhUeXBlLiBfX1JlYWQgT25seV9fICAqKi9cclxuICBuYW1lOiBzdHJpbmc7XHJcbiAgLyoqICBUaGUgc2hvcnQsIHVucXVhbGlmaWVkLCBuYW1lIGZvciB0aGlzIENvbXBsZXhUeXBlLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIHNob3J0TmFtZTogc3RyaW5nO1xyXG5cclxuICAvKiogVGhlIG5hbWVzcGFjZSBmb3IgdGhpcyBDb21wbGV4VHlwZS4gX19SZWFkIE9ubHlfXyAqKi9cclxuICBuYW1lc3BhY2U6IHN0cmluZztcclxuICAvKiogVGhlIERhdGFQcm9wZXJ0aWVzIChzZWUgW1tEYXRhUHJvcGVydHldXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBDb21wbGV4VHlwZS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRhdGFQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvKiogVGhlIERhdGFQcm9wZXJ0aWVzIGZvciB0aGlzIENvbXBsZXhUeXBlIHRoYXQgY29udGFpbiBpbnN0YW5jZXMgb2YgYSBbW0NvbXBsZXhUeXBlXV0uIF9fUmVhZCBPbmx5X18gKi9cclxuICBjb21wbGV4UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcblxyXG4gIC8qKlxyXG4gIFRoZSBlbnRpdHkgbGV2ZWwgdmFsaWRhdG9ycyBhc3NvY2lhdGVkIHdpdGggdGhpcyBDb21wbGV4VHlwZS4gVmFsaWRhdG9ycyBjYW4gYmUgYWRkZWQgYW5kXHJcbiAgcmVtb3ZlZCBmcm9tIHRoaXMgY29sbGVjdGlvbi4gX19SZWFkIE9ubHlfXyAgKiovXHJcbiAgdmFsaWRhdG9yczogVmFsaWRhdG9yW107XHJcbiAgLyoqIEZvciBwb2x5bW9ycGhpYyBwdXJwb3NlIG9ubHkgLSBhbHdheXMgZW1wdHkgaGVyZSAqL1xyXG4gIGNvbmN1cnJlbmN5UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcbiAgLyoqIFRoZSBEYXRhUHJvcGVydGllcyBhc3NvY2lhdGVkIHdpdGggdGhpcyBDb21wbGV4VHlwZSB0aGF0IGFyZSBub3QgbWFwcGVkIHRvIGFueSBiYWNrZW5kIGRhdGFzdG9yZS4gVGhlc2UgYXJlIGVmZmVjdGl2ZWx5IGZyZWUgc3RhbmRpbmdcclxuICBwcm9wZXJ0aWVzLiBfX1JlYWQgT25seV9fICAgKiovXHJcbiAgdW5tYXBwZWRQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuXHJcbiAgLy8ga2V5UHJvcGVydGllcyBhbmQgbmF2aWdhdGlvblByb3BlcnRpZXMgYXJlIG5vdCB1c2VkIG9uIGNvbXBsZXhUeXBlcyAtIGJ1dCBoZXJlIHRvIGFsbG93IHNoYXJpbmcgb2YgY29kZSBiZXR3ZWVuIEVudGl0eVR5cGUgYW5kIENvbXBsZXhUeXBlLlxyXG4gIG5hdmlnYXRpb25Qcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvLyBhbmQgbWF5IGJlIHVzZWQgbGF0ZXIgdG8gZW5mb3JjZSB1bmlxdWVuZXNzIG9uIGFycmF5cyBvZiBjb21wbGV4dHlwZXMuXHJcbiAga2V5UHJvcGVydGllczogRGF0YVByb3BlcnR5W107XHJcbiAgd2FybmluZ3M6IGFueVtdO1xyXG4gIHNlcmlhbGl6ZXJGbj86IChwcm9wOiBFbnRpdHlQcm9wZXJ0eSwgdmFsOiBhbnkpID0+IGFueTtcclxuXHJcbiAgLyoqIEEgZnJlZSBmb3JtIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIGRlZmluZSBhbnkgY3VzdG9tIG1ldGFkYXRhIGZvciB0aGlzIENvbXBsZXhUeXBlLiAqKiovXHJcbiAgY3VzdG9tPzogYW55O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9tYXBwZWRQcm9wZXJ0aWVzQ291bnQ6IG51bWJlcjtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfZXh0cmE/OiBhbnk7XHJcblxyXG4gIC8vIGNvcHkgZW50aXR5VHlwZSBtZXRob2RzIG9udG8gY29tcGxleFR5cGVcclxuICAvKiogU2VlIFtbRW50aXR5VHlwZS5nZXRDdG9yXV0gKi9cclxuICBnZXRDdG9yID0gRW50aXR5VHlwZS5wcm90b3R5cGUuZ2V0Q3RvcjtcclxuICAvLyBub3RlIHRoZSBuYW1lIGNoYW5nZS5cclxuICBjcmVhdGVJbnN0YW5jZSA9IEVudGl0eVR5cGUucHJvdG90eXBlLmNyZWF0ZUVudGl0eTtcclxuICAvKiogU2VlIFtFbnRpdHlUeXBlLmFkZFZhbGlkYXRvcl0gKi9cclxuICBhZGRWYWxpZGF0b3IgPSBFbnRpdHlUeXBlLnByb3RvdHlwZS5hZGRWYWxpZGF0b3I7XHJcbiAgZ2V0UHJvcGVydHkgPSBFbnRpdHlUeXBlLnByb3RvdHlwZS5nZXRQcm9wZXJ0eTtcclxuICBnZXRQcm9wZXJ0aWVzT25QYXRoID0gRW50aXR5VHlwZS5wcm90b3R5cGUuZ2V0UHJvcGVydGllc09uUGF0aDtcclxuICBnZXRQcm9wZXJ0eU5hbWVzID0gRW50aXR5VHlwZS5wcm90b3R5cGUuZ2V0UHJvcGVydHlOYW1lcztcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfYWRkUHJvcGVydHlDb3JlID0gRW50aXR5VHlwZS5wcm90b3R5cGUuX2FkZFByb3BlcnR5Q29yZTtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfYWRkRGF0YVByb3BlcnR5ID0gRW50aXR5VHlwZS5wcm90b3R5cGUuX2FkZERhdGFQcm9wZXJ0eTtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfdXBkYXRlTmFtZXMgPSBFbnRpdHlUeXBlLnByb3RvdHlwZS5fdXBkYXRlTmFtZXM7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VwZGF0ZUNwcyA9IEVudGl0eVR5cGUucHJvdG90eXBlLl91cGRhdGVDcHM7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2luaXRpYWxpemVJbnN0YW5jZSA9IEVudGl0eVR5cGUucHJvdG90eXBlLl9pbml0aWFsaXplSW5zdGFuY2U7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3VwZGF0ZVRhcmdldEZyb21SYXcgPSBFbnRpdHlUeXBlLnByb3RvdHlwZS5fdXBkYXRlVGFyZ2V0RnJvbVJhdztcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfc2V0Q3RvciA9IEVudGl0eVR5cGUucHJvdG90eXBlLl9zZXRDdG9yO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihjb25maWc6IENvbXBsZXhUeXBlQ29uZmlnKSB7XHJcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIENvbXBsZXhUeXBlIGN0b3IgaGFzIGEgc2luZ2xlIGFyZ3VtZW50IHRoYXQgaXMgYSBjb25maWd1cmF0aW9uIG9iamVjdC5cIik7XHJcbiAgICB9XHJcblxyXG4gICAgYXNzZXJ0Q29uZmlnKGNvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJzaG9ydE5hbWVcIikuaXNOb25FbXB0eVN0cmluZygpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwibmFtZXNwYWNlXCIpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KFwiXCIpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiZGF0YVByb3BlcnRpZXNcIikuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiaXNDb21wbGV4VHlwZVwiKS5pc09wdGlvbmFsKCkuaXNCb29sZWFuKCkgICAvLyBuZWVkZWQgYmVjYXVzZSB0aGlzIGN0b3IgY2FuIGdldCBjYWxsZWQgZnJvbSB0aGUgYWRkRW50aXR5VHlwZSBtZXRob2Qgd2hpY2ggbmVlZHMgdGhlIGlzQ29tcGxleFR5cGUgcHJvcFxyXG4gICAgICAud2hlcmVQYXJhbShcImN1c3RvbVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG5cclxuICAgIHRoaXMubmFtZSA9IHF1YWxpZnlUeXBlTmFtZSh0aGlzLnNob3J0TmFtZSwgdGhpcy5uYW1lc3BhY2UpO1xyXG4gICAgdGhpcy5pc0NvbXBsZXhUeXBlID0gdHJ1ZTtcclxuICAgIHRoaXMuZGF0YVByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMuY29tcGxleFByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMudmFsaWRhdG9ycyA9IFtdO1xyXG4gICAgdGhpcy5jb25jdXJyZW5jeVByb3BlcnRpZXMgPSBbXTtcclxuICAgIHRoaXMudW5tYXBwZWRQcm9wZXJ0aWVzID0gW107XHJcbiAgICB0aGlzLl9tYXBwZWRQcm9wZXJ0aWVzQ291bnQgPSAwO1xyXG4gICAgLy8ga2V5UHJvcGVydGllcyBhbmQgbmF2aWdhdGlvblByb3BlcnRpZXMgYXJlIG5vdCB1c2VkIG9uIGNvbXBsZXhUeXBlcyAtIGJ1dCBoZXJlIHRvIGFsbG93IHNoYXJpbmcgb2YgY29kZSBiZXR3ZWVuIEVudGl0eVR5cGUgYW5kIENvbXBsZXhUeXBlLlxyXG4gICAgdGhpcy5uYXZpZ2F0aW9uUHJvcGVydGllcyA9IFtdO1xyXG4gICAgdGhpcy5rZXlQcm9wZXJ0aWVzID0gW107IC8vIG1heSBiZSB1c2VkIGxhdGVyIHRvIGVuZm9yY2UgdW5pcXVlbmVzcyBvbiBhcnJheXMgb2YgY29tcGxleHR5cGVzLlxyXG4gICAgaWYgKGNvbmZpZy5kYXRhUHJvcGVydGllcykge1xyXG4gICAgICBhZGRQcm9wZXJ0aWVzKHRoaXMsIGNvbmZpZy5kYXRhUHJvcGVydGllcywgRGF0YVByb3BlcnR5KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEdlbmVyYWwgcHVycG9zZSBwcm9wZXJ0eSBzZXQgbWV0aG9kXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBlbTEgaXMgYW4gRW50aXR5TWFuYWdlclxyXG4gID4gICAgICBsZXQgYWRkcmVzc3RUeXBlID0gZW0xLm1ldGFkYXRhU3RvcmUuZ2V0RW50aXR5VHlwZShcIkFkZHJlc3NcIik7XHJcbiAgPiAgICAgIGFkZHJlc3NUeXBlLnNldFByb3BlcnRpZXMoIHtcclxuICA+ICAgICAgICAgIGN1c3RvbTogeyBmb286IDcsIGJhcjogXCJ0ZXN0XCIgfVxyXG4gID4gICAgICB9KTtcclxuICBAcGFyYW0gY29uZmlnIC0gQ3VzdG9tIGNvbmZpZyBvYmplY3RcclxuICBAcGFyYW0gY29uZmlnLmN1c3RvbSAtIHtPYmplY3R9XHJcbiAgKiovXHJcbiAgc2V0UHJvcGVydGllcyhjb25maWc6IHsgY3VzdG9tPzogT2JqZWN0IH0pIHtcclxuICAgIGFzc2VydENvbmZpZyhjb25maWcpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiY3VzdG9tXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAuYXBwbHlBbGwodGhpcyk7XHJcbiAgfVxyXG5cclxuXHJcbiAgZ2V0QWxsVmFsaWRhdG9ycygpIHtcclxuICAgIC8vIENvbXBsZXhUeXBlIGluaGVyaXRhbmNlIGlzIG5vdCBZRVQgc3VwcG9ydGVkLlxyXG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdG9ycztcclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9jcmVhdGVJbnN0YW5jZUNvcmUocGFyZW50OiBTdHJ1Y3R1cmFsT2JqZWN0LCBwYXJlbnRQcm9wZXJ0eTogRGF0YVByb3BlcnR5KSB7XHJcbiAgICBsZXQgYUN0b3IgPSB0aGlzLmdldEN0b3IoKTtcclxuICAgIGxldCBpbnN0YW5jZSA9IG5ldyBhQ3RvcigpIGFzIENvbXBsZXhPYmplY3Q7XHJcbiAgICBuZXcgQ29tcGxleEFzcGVjdChpbnN0YW5jZSwgcGFyZW50LCBwYXJlbnRQcm9wZXJ0eSk7XHJcbiAgICAvLyBpbml0aWFsaXphdGlvbiBvY2N1cnMgZHVyaW5nIGVpdGhlciBhdHRhY2ggb3IgaW4gY3JlYXRlSW5zdGFuY2UgY2FsbC5cclxuICAgIHJldHVybiBpbnN0YW5jZTtcclxuICB9XHJcblxyXG5cclxuICBhZGRQcm9wZXJ0eShkYXRhUHJvcGVydHk6IERhdGFQcm9wZXJ0eSkge1xyXG4gICAgYXNzZXJ0UGFyYW0oZGF0YVByb3BlcnR5LCBcImRhdGFQcm9wZXJ0eVwiKS5pc0luc3RhbmNlT2YoRGF0YVByb3BlcnR5KS5jaGVjaygpO1xyXG4gICAgcmV0dXJuIHRoaXMuX2FkZFByb3BlcnR5Q29yZShkYXRhUHJvcGVydHkpO1xyXG4gIH1cclxuXHJcbiAgZ2V0UHJvcGVydGllcygpOiBFbnRpdHlQcm9wZXJ0eVtdIHtcclxuICAgIHJldHVybiB0aGlzLmRhdGFQcm9wZXJ0aWVzO1xyXG4gIH1cclxuXHJcbiAgdG9KU09OKCkge1xyXG4gICAgcmV0dXJuIGNvcmUudG9Kc29uKHRoaXMsIHtcclxuICAgICAgc2hvcnROYW1lOiBudWxsLFxyXG4gICAgICBuYW1lc3BhY2U6IG51bGwsXHJcbiAgICAgIGlzQ29tcGxleFR5cGU6IG51bGwsXHJcbiAgICAgIGRhdGFQcm9wZXJ0aWVzOiBudWxsLFxyXG4gICAgICB2YWxpZGF0b3JzOiBudWxsLFxyXG4gICAgICBjdXN0b206IG51bGxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbn1cclxuQ29tcGxleFR5cGUucHJvdG90eXBlLl8kdHlwZU5hbWUgPSBcIkNvbXBsZXhUeXBlXCI7XHJcbi8qKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIHRoaXMgY29tcGxleFR5cGUgKi9cclxuQ29tcGxleFR5cGUucHJvdG90eXBlLmNyZWF0ZUluc3RhbmNlID0gRW50aXR5VHlwZS5wcm90b3R5cGUuY3JlYXRlRW50aXR5O1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBEYXRhUHJvcGVydHlDb25maWcge1xyXG4gIG5hbWU/OiBzdHJpbmc7XHJcbiAgbmFtZU9uU2VydmVyPzogc3RyaW5nO1xyXG4gIGRhdGFUeXBlPzogRGF0YVR5cGUgfCBzdHJpbmcgfCBDb21wbGV4VHlwZTtcclxuICBjb21wbGV4VHlwZU5hbWU/OiBzdHJpbmc7XHJcbiAgaXNOdWxsYWJsZT86IGJvb2xlYW47XHJcbiAgaXNTY2FsYXI/OiBib29sZWFuOyAvLyB3aWxsIGJlIGZhbHNlIGZvciBzb21lIE5vU1FMIGRhdGFiYXNlcy5cclxuICBkZWZhdWx0VmFsdWU/OiBhbnk7XHJcbiAgaXNQYXJ0T2ZLZXk/OiBib29sZWFuO1xyXG4gIGlzVW5tYXBwZWQ/OiBib29sZWFuO1xyXG4gIGlzU2V0dGFibGU/OiBib29sZWFuO1xyXG4gIGNvbmN1cnJlbmN5TW9kZT86IHN0cmluZztcclxuICBtYXhMZW5ndGg/OiBudW1iZXI7XHJcbiAgdmFsaWRhdG9ycz86IFZhbGlkYXRvcltdO1xyXG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nO1xyXG4gIGVudW1UeXBlPzogYW55O1xyXG4gIHJhd1R5cGVOYW1lPzogc3RyaW5nOyAgLy8gb2NjdXJzIHdpdGggdW5kZWZpbmVkIGRhdGF0eXBlc1xyXG4gIGN1c3RvbT86IE9iamVjdDtcclxufVxyXG5cclxuLyoqXHJcbkEgRGF0YVByb3BlcnR5IGRlc2NyaWJlcyB0aGUgbWV0YWRhdGEgZm9yIGEgc2luZ2xlIHByb3BlcnR5IG9mIGFuICBbW0VudGl0eVR5cGVdXSB0aGF0IGNvbnRhaW5zIHNpbXBsZSBkYXRhLlxyXG5cclxuSW5zdGFuY2VzIG9mIHRoZSBEYXRhUHJvcGVydHkgY2xhc3MgYXJlIGNvbnN0cnVjdGVkIGF1dG9tYXRpY2FsbHkgZHVyaW5nIE1ldGFkYXRhIHJldHJpZXZhbC4gSG93ZXZlciBpdCBpcyBhbHNvIHBvc3NpYmxlIHRvIGNvbnN0cnVjdCB0aGVtXHJcbmRpcmVjdGx5IHZpYSB0aGUgY29uc3RydWN0b3IuXHJcbioqL1xyXG5leHBvcnQgY2xhc3MgRGF0YVByb3BlcnR5IHtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfJHR5cGVOYW1lOiBzdHJpbmc7IC8vIG9uIHByb3RvXHJcbiAgLyoqIElzIHRoaXMgYSBEYXRhUHJvcGVydHk/IC0gYWx3YXlzIHRydWUgaGVyZS4gQWxsb3dzIHBvbHltb3JwaGljIHRyZWF0bWVudCBvZiBEYXRhUHJvcGVydGllcyBhbmQgTmF2aWdhdGlvblByb3BlcnRpZXMuIF9fUmVhZCBPbmx5X18gKi9cclxuICBpc0RhdGFQcm9wZXJ0eSA9IHRydWU7XHJcbiAgLyoqIElzIHRoaXMgYSBOYXZpZ2F0aW9uUHJvcGVydHk/IC0gYWx3YXlzIGZhbHNlIGhlcmUuICBBbGxvd3MgcG9seW1vcnBoaWMgdHJlYXRtZW50IG9mIERhdGFQcm9wZXJ0aWVzIGFuZCBOYXZpZ2F0aW9uUHJvcGVydGllcy4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGlzTmF2aWdhdGlvblByb3BlcnR5ID0gZmFsc2U7XHJcbiAgLyoqIFRoZSBuYW1lIG9mIHRoaXMgcHJvcGVydHkuIF9fUmVhZCBPbmx5X18gICoqL1xyXG4gIG5hbWU6IHN0cmluZztcclxuICAvKiogVGhlIG5hbWUgb2YgdGhpcyBwcm9wZXJ0eSBvbiB0aGUgc2VydmVyLiBfX1JlYWQgT25seV9fICoqL1xyXG4gIG5hbWVPblNlcnZlcjogc3RyaW5nO1xyXG4gIC8qKiBUaGUgW1tEYXRhVHlwZV1dIG9mIHRoaXMgcHJvcGVydHkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBkYXRhVHlwZTogRGF0YVR5cGUgfCBDb21wbGV4VHlwZTsgLy8gdGhpcyB3aWxsIGJlIGEgY29tcGxleFR5cGUgd2hlbiBkcCBpcyBhIGNvbXBsZXhQcm9wZXJ0eVxyXG4gIC8qKiBUaGUgbmFtZSBvZiB0aGUgW1tDb21wbGV4VHlwZV1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHByb3BlcnR5OyBtYXkgYmUgbnVsbC4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGNvbXBsZXhUeXBlTmFtZTogc3RyaW5nO1xyXG4gIC8qKiBUaGUgW1tDb21wbGV4VHlwZV1dIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHByb3BlcnR5OyBtYXkgYmUgdW5kZWZpbmVkLiBfX1JlYWQgT25seV9fICovXHJcbiAgY29tcGxleFR5cGU/OiBDb21wbGV4VHlwZTtcclxuICAvKiogIFdoZXRoZXIgdGhlIGNvbnRlbnRzIG9mIHRoaXMgcHJvcGVydHkgaXMgYW4gaW5zdGFuY2Ugb2YgYSBbW0NvbXBsZXhUeXBlXV0uIF9fUmVhZCBPbmx5X18gKi9cclxuICBpc0NvbXBsZXhQcm9wZXJ0eTogYm9vbGVhbjtcclxuICAvKiogV2hldGhlciB0aGlzIHByb3BlcnR5IGlzIG51bGxhYmxlLiBfX1JlYWQgT25seV9fICovXHJcbiAgaXNOdWxsYWJsZTogYm9vbGVhbjtcclxuICAvKiogIFdoZXRoZXIgdGhpcyBwcm9wZXJ0eSBpcyBzY2FsYXIgKGkuZS4sIHJldHVybnMgYSBzaW5nbGUgdmFsdWUgYXMgb3Bwb3NlZCB0byBhbiBhcnJheSkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBpc1NjYWxhcjogYm9vbGVhbjsgLy8gd2lsbCBiZSBmYWxzZSBmb3Igc29tZSBOb1NRTCBkYXRhYmFzZXMuXHJcbiAgLyoqIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGlzIHByb3BlcnR5LiBfX1JlYWQgT25seV9fICovXHJcbiAgZGVmYXVsdFZhbHVlOiBhbnk7XHJcbiAgLyoqICBXaGV0aGVyIHRoaXMgcHJvcGVydHkgaXMgYSAna2V5JyBwcm9wZXJ0eS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGlzUGFydE9mS2V5OiBib29sZWFuO1xyXG4gIC8qKiBXaGV0aGVyIHRoaXMgcHJvcGVydHkgaXMgYW4gJ3VubWFwcGVkJyBwcm9wZXJ0eS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGlzVW5tYXBwZWQ6IGJvb2xlYW47XHJcbiAgLyoqIFdoZXRoZXIgdGhpcyBwcm9wZXJ0eSBpcyAnc2V0dGFibGUnLiBfX1JlYWQgT25seV9fICovXHJcbiAgaXNTZXR0YWJsZTogYm9vbGVhbjtcclxuICAvLyBUT0RPOiBkb2MgdGhpc1xyXG4gIGNvbmN1cnJlbmN5TW9kZTogc3RyaW5nO1xyXG4gIC8qKiAgVGhlIG1heGltdW0gbGVuZ3RoIGZvciB0aGUgdmFsdWUgb2YgdGhpcyBwcm9wZXJ0eS4gT25seSBtZWFuaW5nZnVsIGZvciBzdHJpbmdzLiBfX1JlYWQgT25seV9fICovXHJcbiAgbWF4TGVuZ3RoPzogbnVtYmVyO1xyXG4gIC8qKiBUaGUgW1tWYWxpZGF0b3JdXSBpbnN0YW5jZXMgdGhhdCBhcmUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgcHJvcGVydHkuIFZhbGlkYXRvcnMgY2FuIGJlIGFkZGVkIGFuZFxyXG4gIHJlbW92ZWQgZnJvbSB0aGlzIGNvbGxlY3Rpb24uIF9fUmVhZCBPbmx5X18gKi9cclxuICB2YWxpZGF0b3JzOiBWYWxpZGF0b3JbXTtcclxuICAvKiogVGhlIGRpc3BsYXkgbmFtZSBvZiB0aGlzIHByb3BlcnR5LiBfX1JlYWQgT25seV9fICovXHJcbiAgZGlzcGxheU5hbWU6IHN0cmluZztcclxuICAvLyBUT0RPOiBkb2MgdGhpc1xyXG4gIGVudW1UeXBlPzogYW55O1xyXG4gIC8qKiBUaGUgcmF3IHR5cGUgbmFtZSBvZiB0aGlzIHByb3BlcnR5LiB3aWxsIG9ubHkgYmUgZGVmaW5lZCBmb3IgcHJvcGVydGllcyB3aXRoIGEgRGF0YVR5cGUgb2YgJ1VuZGVmaW5lZCcgKi9cclxuICByYXdUeXBlTmFtZT86IHN0cmluZzsgIC8vIG9jY3VycyB3aXRoIHVuZGVmaW5lZCBkYXRhdHlwZXNcclxuICAvKiogIEEgZnJlZSBmb3JtIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIGRlZmluZSBhbnkgY3VzdG9tIG1ldGFkYXRhIGZvciB0aGlzIERhdGFQcm9wZXJ0eS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGN1c3RvbT86IE9iamVjdDtcclxuICAvLyBUT0RPOiBkb2MgdGhpc1xyXG4gIGludmVyc2VOYXZpZ2F0aW9uUHJvcGVydHk/OiBOYXZpZ2F0aW9uUHJvcGVydHk7XHJcbiAgLyoqXHJcbiAgVGhlIG5hdmlnYXRpb24gcHJvcGVydHkgcmVsYXRlZCB0byB0aGlzIHByb3BlcnR5LiAgV2lsbCBvbmx5IGJlIHNldCBpZiB0aGlzIGlzIGEgZm9yZWlnbiBrZXkgcHJvcGVydHkuIF9fUmVhZCBPbmx5X18gKi9cclxuICByZWxhdGVkTmF2aWdhdGlvblByb3BlcnR5PzogTmF2aWdhdGlvblByb3BlcnR5O1xyXG4gIC8qKiBUaGUgcGFyZW50IHR5cGUgdGhhdCB0aGlzIHByb3BlcnR5IGJlbG9uZ3MgdG8gLSB3aWxsIGJlIGVpdGhlciBhIFtbRW50aXR5VHlwZV1dIG9yIGEgW1tDb21wbGV4VHlwZV1dLiBfX1JlYWQgT25seV9fICovXHJcbiAgcGFyZW50VHlwZTogU3RydWN0dXJhbFR5cGU7XHJcbiAgLyoqIFByb3BlcnR5IG9uIHRoZSBiYXNlIHR5cGUgdGhhdCB0aGlzIHByb3BlcnR5IGlzIGluaGVyaXRlZCBmcm9tLiBXaWxsIGJlIG51bGwgaWYgdGhlIHByb3BlcnR5IGlzIG5vdCBvbiB0aGUgYmFzZSB0eXBlLiBfX1JlYWQgT25seV9fICovXHJcbiAgYmFzZVByb3BlcnR5PzogRGF0YVByb3BlcnR5O1xyXG5cclxuICAvKiogRGF0YVByb3BlcnR5IGNvbnN0cnVjdG9yXHJcbiAgPiAgICAgIGxldCBsYXN0TmFtZVByb3AgPSBuZXcgRGF0YVByb3BlcnR5KCB7XHJcbiAgPiAgICAgICAgICBuYW1lOiBcImxhc3ROYW1lXCIsXHJcbiAgPiAgICAgICAgICBkYXRhVHlwZTogRGF0YVR5cGUuU3RyaW5nLFxyXG4gID4gICAgICAgICAgaXNOdWxsYWJsZTogdHJ1ZSxcclxuICA+ICAgICAgICAgIG1heExlbmd0aDogMjBcclxuICA+ICAgICAgfSk7XHJcbiAgPiAgICAgIC8vIGFzc3VtaW5nIHBlcnNvbkVudGl0eVR5cGUgaXMgYSBuZXdseSBjb25zdHJ1Y3RlZCBFbnRpdHlUeXBlXHJcbiAgPiAgICAgIHBlcnNvbkVudGl0eVR5cGUuYWRkUHJvcGVydHkobGFzdE5hbWVQcm9wZXJ0eSk7XHJcbiAgQHBhcmFtIGNvbmZpZyAtIEEgY29uZmlndXJhdGlvbiBPYmplY3Qgb3IgYSBEYXRhUHJvcGVydHlcclxuICAqL1xyXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogRGF0YVByb3BlcnR5Q29uZmlnIHwgRGF0YVByb3BlcnR5KSB7XHJcbiAgICBhc3NlcnRDb25maWcoY29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcIm5hbWVcIikuaXNTdHJpbmcoKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJuYW1lT25TZXJ2ZXJcIikuaXNTdHJpbmcoKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJkYXRhVHlwZVwiKS5pc0VudW1PZihEYXRhVHlwZSkuaXNPcHRpb25hbCgpLm9yKCkuaXNTdHJpbmcoKS5vcigpLmlzSW5zdGFuY2VPZihDb21wbGV4VHlwZSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJjb21wbGV4VHlwZU5hbWVcIikuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiaXNOdWxsYWJsZVwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQodHJ1ZSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJpc1NjYWxhclwiKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQodHJ1ZSkvLyB3aWxsIGJlIGZhbHNlIGZvciBzb21lIE5vU1FMIGRhdGFiYXNlcy5cclxuICAgICAgLndoZXJlUGFyYW0oXCJkZWZhdWx0VmFsdWVcIikuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiaXNQYXJ0T2ZLZXlcIikuaXNCb29sZWFuKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiaXNVbm1hcHBlZFwiKS5pc0Jvb2xlYW4oKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJpc1NldHRhYmxlXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdCh0cnVlKVxyXG4gICAgICAud2hlcmVQYXJhbShcImNvbmN1cnJlbmN5TW9kZVwiKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcIm1heExlbmd0aFwiKS5pc051bWJlcigpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcInZhbGlkYXRvcnNcIikuaXNJbnN0YW5jZU9mKFZhbGlkYXRvcikuaXNBcnJheSgpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChbXSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJkaXNwbGF5TmFtZVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJlbnVtVHlwZVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJyYXdUeXBlTmFtZVwiKS5pc09wdGlvbmFsKCkgLy8gb2NjdXJzIHdpdGggdW5kZWZpbmVkIGRhdGF0eXBlc1xyXG4gICAgICAud2hlcmVQYXJhbShcImN1c3RvbVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG4gICAgbGV0IGhhc05hbWUgPSAhISh0aGlzLm5hbWUgfHwgdGhpcy5uYW1lT25TZXJ2ZXIpO1xyXG4gICAgaWYgKCFoYXNOYW1lKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkEgRGF0YVByb3BlcnR5IG11c3QgYmUgaW5zdGFudGlhdGVkIHdpdGggZWl0aGVyIGEgJ25hbWUnIG9yIGEgJ25hbWVPblNlcnZlcicgcHJvcGVydHlcIik7XHJcbiAgICB9XHJcbiAgICAvLyBuYW1lL25hbWVPblNlcnZlciBpcyByZXNvbHZlZCBsYXRlciB3aGVuIGEgbWV0YWRhdGFTdG9yZSBpcyBhdmFpbGFibGUuXHJcblxyXG4gICAgaWYgKHRoaXMuY29tcGxleFR5cGVOYW1lKSB7XHJcbiAgICAgIHRoaXMuaXNDb21wbGV4UHJvcGVydHkgPSB0cnVlO1xyXG4gICAgICAvLyB0aGlzLmRhdGFUeXBlID0gbnVsbDsgLy8gVE9ETzogd291bGQgbGlrZSB0byByZW1vdmUgdGhpcyBsaW5lIGJlY2F1c2UgZGF0YVR5cGUgd2lsbCBiZSBzZXQgbGF0ZXIuXHJcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiAodGhpcy5kYXRhVHlwZSkgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgbGV0IGR0ID0gRGF0YVR5cGUuZnJvbU5hbWUodGhpcy5kYXRhVHlwZSk7XHJcbiAgICAgIGlmICghZHQpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gZmluZCBhIERhdGFUeXBlIGVudW1lcmF0aW9uIGJ5IHRoZSBuYW1lIG9mOiBcIiArIHRoaXMuZGF0YVR5cGUpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuZGF0YVR5cGUgPSBkdDtcclxuICAgIH0gZWxzZSBpZiAoIXRoaXMuZGF0YVR5cGUpIHtcclxuICAgICAgdGhpcy5kYXRhVHlwZSA9IERhdGFUeXBlLlN0cmluZztcclxuICAgIH1cclxuXHJcbiAgICAvLyA9PSBhcyBvcHBvc2VkIHRvID09PSBpcyBkZWxpYmVyYXRlIGhlcmUuXHJcbiAgICBpZiAodGhpcy5kZWZhdWx0VmFsdWUgPT0gbnVsbCkge1xyXG4gICAgICBpZiAodGhpcy5pc051bGxhYmxlKSB7XHJcbiAgICAgICAgdGhpcy5kZWZhdWx0VmFsdWUgPSBudWxsO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGlmICh0aGlzLmlzQ29tcGxleFByb3BlcnR5KSB7XHJcbiAgICAgICAgICAvLyB3aGF0IHRvIGRvPyAtIHNob3VsZG4ndCBoYXBwZW4gZnJvbSBFRiAtIGJ1dCBvdGhlcndpc2UgPz8/XHJcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmRhdGFUeXBlID09PSBEYXRhVHlwZS5CaW5hcnkpIHtcclxuICAgICAgICAgIHRoaXMuZGVmYXVsdFZhbHVlID0gXCJBQUFBQUFBQUozVT1cIjsgLy8gaGFjayBmb3IgYWxsIGJpbmFyeSBmaWVsZHMgYnV0IHZhbHVlIGlzIHNwZWNpZmljYWxseSB2YWxpZCBmb3IgdGltZXN0YW1wIGZpZWxkcyAtIGFyYml0cmFyeSB2YWxpZCA4IGJ5dGUgYmFzZTY0IHZhbHVlLlxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLmRlZmF1bHRWYWx1ZSA9ICh0aGlzLmRhdGFUeXBlIGFzIGFueSkuZGVmYXVsdFZhbHVlO1xyXG4gICAgICAgICAgY29uc3QgbXNnID0gXCJBIG5vbm51bGxhYmxlIERhdGFQcm9wZXJ0eSBjYW5ub3QgaGF2ZSBhIG51bGwgZGVmYXVsdFZhbHVlLiBOYW1lOiBcIiArICh0aGlzLm5hbWUgfHwgdGhpcy5uYW1lT25TZXJ2ZXIpO1xyXG4gICAgICAgICAgaWYgKHRoaXMuZGVmYXVsdFZhbHVlID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpOyAgLy8gaWYgZGVmYXVsdFZhbHVlIGlzIGV4cGxpY2l0eSBzZXQgdG8gbnVsbCwgdGhhdCdzIGFuIGVycm9yXHJcbiAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZGVmYXVsdFZhbHVlID09IG51bGwpIHtcclxuICAgICAgICAgICAgY29uc29sZS53YXJuKG1zZyk7ICAvLyBpZiBkZWZhdWx0VmFsdWUgaXMgbm90IHNldCwgdGhhdCdzIGEgd2FybmluZ1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSBlbHNlIGlmICgodGhpcy5kYXRhVHlwZSBhcyBhbnkpLmlzTnVtZXJpYykge1xyXG4gICAgICAvLyBpbiBjYXNlIHRoZSBkZWZhdWx0VmFsdWUgY29tZXMgaW4gYXMgYSBzdHJpbmcgKCB3aGljaCBpdCBkb2VzIGluIEVGNikuXHJcbiAgICAgIGlmICh0eXBlb2YgKHRoaXMuZGVmYXVsdFZhbHVlKSA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICAgIHRoaXMuZGVmYXVsdFZhbHVlID0gcGFyc2VGbG9hdCh0aGlzLmRlZmF1bHRWYWx1ZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5pc0NvbXBsZXhQcm9wZXJ0eSkge1xyXG4gICAgICB0aGlzLmlzU2NhbGFyID0gdGhpcy5pc1NjYWxhciA9PSBudWxsIHx8IHRoaXMuaXNTY2FsYXIgPT09IHRydWU7XHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgc3RhdGljIGdldFJhd1ZhbHVlRnJvbVNlcnZlcihyYXdFbnRpdHk6IE9iamVjdCwgZHA6IERhdGFQcm9wZXJ0eSkge1xyXG4gICAgaWYgKGRwLmlzVW5tYXBwZWQpIHtcclxuICAgICAgcmV0dXJuIHJhd0VudGl0eVtkcC5uYW1lT25TZXJ2ZXIgfHwgZHAubmFtZV07XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsZXQgdmFsID0gcmF3RW50aXR5W2RwLm5hbWVPblNlcnZlcl07XHJcbiAgICAgIHJldHVybiB2YWwgIT09IHVuZGVmaW5lZCA/IHZhbCA6IGRwLmRlZmF1bHRWYWx1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHN0YXRpYyBnZXRSYXdWYWx1ZUZyb21DbGllbnQocmF3RW50aXR5OiBPYmplY3QsIGRwOiBEYXRhUHJvcGVydHkpIHtcclxuICAgIGxldCB2YWwgPSByYXdFbnRpdHlbZHAubmFtZV07XHJcbiAgICByZXR1cm4gdmFsICE9PSB1bmRlZmluZWQgPyB2YWwgOiBkcC5kZWZhdWx0VmFsdWU7XHJcbiAgfVxyXG5cclxuICByZXNvbHZlUHJvcGVydHkocHJvcE5hbWU6IHN0cmluZykge1xyXG4gICAgbGV0IHJlc3VsdCA9IHRoaXNbcHJvcE5hbWVdO1xyXG4gICAgbGV0IGJhc2VQcm9wID0gdGhpcy5iYXNlUHJvcGVydHk7XHJcbiAgICB3aGlsZSAocmVzdWx0ID09IHVuZGVmaW5lZCAmJiBiYXNlUHJvcCAhPSBudWxsKSB7XHJcbiAgICAgIHJlc3VsdCA9IGJhc2VQcm9wW3Byb3BOYW1lXTtcclxuICAgICAgYmFzZVByb3AgPSBiYXNlUHJvcC5iYXNlUHJvcGVydHk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgZm9ybWF0TmFtZSgpIHtcclxuICAgIHJldHVybiB0aGlzLnBhcmVudFR5cGUubmFtZSArIFwiLS1cIiArIHRoaXMubmFtZTtcclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICBHZW5lcmFsIHB1cnBvc2UgcHJvcGVydHkgc2V0IG1ldGhvZFxyXG4gID4gICAgICAvLyBhc3N1bWUgZW0xIGlzIGFuIEVudGl0eU1hbmFnZXJcclxuICA+ICAgICAgbGV0IHByb3AgPSBteUVudGl0eVR5cGUuZ2V0UHJvcGVydHkoXCJteVByb3BlcnR5XCIpO1xyXG4gID4gICAgICBwcm9wLnNldFByb3BlcnRpZXMoIHtcclxuICA+ICAgICAgICAgIGN1c3RvbTogeyBmb286IDcsIGJhcjogXCJ0ZXN0XCIgfVxyXG4gID4gICAgICB9KTtcclxuICBAcGFyYW0gY29uZmlnIC0gQSBjb25maWd1cmF0aW9uIG9iamVjdC5cclxuICAqKi9cclxuICBzZXRQcm9wZXJ0aWVzKGNvbmZpZzogeyBkaXNwbGF5TmFtZT86IHN0cmluZywgY3VzdG9tPzogT2JqZWN0IH0pIHtcclxuICAgIGFzc2VydENvbmZpZyhjb25maWcpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiZGlzcGxheU5hbWVcIikuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiY3VzdG9tXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAuYXBwbHlBbGwodGhpcyk7XHJcbiAgfVxyXG5cclxuICBnZXRBbGxWYWxpZGF0b3JzKCkge1xyXG4gICAgbGV0IHZhbGlkYXRvcnMgPSB0aGlzLnZhbGlkYXRvcnMuc2xpY2UoMCk7XHJcbiAgICBsZXQgYmFzZVByb3AgPSB0aGlzLmJhc2VQcm9wZXJ0eTtcclxuICAgIHdoaWxlIChiYXNlUHJvcCkge1xyXG4gICAgICB2YWxpZGF0b3JzLnB1c2guYXBwbHkodmFsaWRhdG9ycywgYmFzZVByb3AudmFsaWRhdG9ycyk7XHJcbiAgICAgIGJhc2VQcm9wID0gYmFzZVByb3AuYmFzZVByb3BlcnR5O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHZhbGlkYXRvcnM7XHJcbiAgfVxyXG5cclxuICB0b0pTT04oKSB7XHJcbiAgICAvLyBkbyBub3Qgc2VyaWFsaXplIGRhdGFUeXBlcyB0aGF0IGFyZSBjb21wbGV4VHlwZXNcclxuICAgIHJldHVybiBjb3JlLnRvSnNvbih0aGlzLCB7XHJcbiAgICAgIG5hbWU6IG51bGwsXHJcbiAgICAgIGRhdGFUeXBlOiBmdW5jdGlvbiAodjogYW55KSB7XHJcbiAgICAgICAgcmV0dXJuICh2ICYmIHYgaW5zdGFuY2VvZiBEYXRhVHlwZSkgPyB2Lm5hbWUgOiB1bmRlZmluZWQ7XHJcbiAgICAgIH0sIC8vIGRvIG5vdCBzZXJpYWxpemUgZGF0YVR5cGVzIHRoYXQgYXJlIGNvbXBsZXhUeXBlc1xyXG4gICAgICBjb21wbGV4VHlwZU5hbWU6IG51bGwsXHJcbiAgICAgIGlzTnVsbGFibGU6IHRydWUsXHJcbiAgICAgIGRlZmF1bHRWYWx1ZTogbnVsbCxcclxuICAgICAgaXNQYXJ0T2ZLZXk6IGZhbHNlLFxyXG4gICAgICBpc1VubWFwcGVkOiBmYWxzZSxcclxuICAgICAgaXNTZXR0YWJsZTogdHJ1ZSxcclxuICAgICAgY29uY3VycmVuY3lNb2RlOiBudWxsLFxyXG4gICAgICBtYXhMZW5ndGg6IG51bGwsXHJcbiAgICAgIHZhbGlkYXRvcnM6IG51bGwsXHJcbiAgICAgIGRpc3BsYXlOYW1lOiBudWxsLFxyXG4gICAgICBlbnVtVHlwZTogbnVsbCxcclxuICAgICAgcmF3VHlwZU5hbWU6IG51bGwsXHJcbiAgICAgIGlzU2NhbGFyOiB0cnVlLFxyXG4gICAgICBjdXN0b206IG51bGxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc3RhdGljIGZyb21KU09OKGpzb246IGFueSkge1xyXG4gICAganNvbi5kYXRhVHlwZSA9IERhdGFUeXBlLmZyb21OYW1lKGpzb24uZGF0YVR5cGUpO1xyXG4gICAgLy8gUGFyc2UgZGVmYXVsdCB2YWx1ZSBpbnRvIGNvcnJlY3QgZGF0YSB0eXBlLiAoZGF0ZVRpbWUgaW5zdGFuY2VzIHJlcXVpcmUgZXh0cmEgd29yayB0byBkZXNlcmlhbGl6ZSBwcm9wZXJseS4pXHJcbiAgICBpZiAoanNvbi5kZWZhdWx0VmFsdWUgJiYganNvbi5kYXRhVHlwZSAmJiBqc29uLmRhdGFUeXBlLnBhcnNlKSB7XHJcbiAgICAgIGpzb24uZGVmYXVsdFZhbHVlID0ganNvbi5kYXRhVHlwZS5wYXJzZShqc29uLmRlZmF1bHRWYWx1ZSwgdHlwZW9mIGpzb24uZGVmYXVsdFZhbHVlKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoanNvbi52YWxpZGF0b3JzKSB7XHJcbiAgICAgIGpzb24udmFsaWRhdG9ycyA9IGpzb24udmFsaWRhdG9ycy5tYXAoVmFsaWRhdG9yLmZyb21KU09OKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbmV3IERhdGFQcm9wZXJ0eShqc29uKTtcclxuICB9XHJcblxyXG59XHJcbkRhdGFQcm9wZXJ0eS5wcm90b3R5cGUuXyR0eXBlTmFtZSA9IFwiRGF0YVByb3BlcnR5XCI7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIE5hdmlnYXRpb25Qcm9wZXJ0eUNvbmZpZyB7XHJcbiAgbmFtZT86IHN0cmluZztcclxuICBuYW1lT25TZXJ2ZXI/OiBzdHJpbmc7XHJcbiAgZW50aXR5VHlwZU5hbWU/OiBzdHJpbmc7XHJcbiAgaXNTY2FsYXI/OiBib29sZWFuO1xyXG4gIGFzc29jaWF0aW9uTmFtZT86IHN0cmluZztcclxuICBmb3JlaWduS2V5TmFtZXM/OiBzdHJpbmdbXTtcclxuICBmb3JlaWduS2V5TmFtZXNPblNlcnZlcj86IHN0cmluZ1tdO1xyXG4gIGludkZvcmVpZ25LZXlOYW1lcz86IHN0cmluZ1tdO1xyXG4gIGludkZvcmVpZ25LZXlOYW1lc09uU2VydmVyPzogc3RyaW5nW107XHJcbiAgdmFsaWRhdG9ycz86IFZhbGlkYXRvcltdO1xyXG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nO1xyXG4gIGN1c3RvbT86IE9iamVjdDtcclxufVxyXG5cclxuLyoqICAgQSBOYXZpZ2F0aW9uUHJvcGVydHkgZGVzY3JpYmVzIHRoZSBtZXRhZGF0YSBmb3IgYSBzaW5nbGUgcHJvcGVydHkgb2YgYW4gW1tFbnRpdHlUeXBlXV0gdGhhdCByZXR1cm4gaW5zdGFuY2VzIG9mIG90aGVyIEVudGl0eVR5cGVzLlxyXG5cclxuSW5zdGFuY2VzIG9mIHRoZSBOYXZpZ2F0aW9uUHJvcGVydHkgY2xhc3MgYXJlIGNvbnN0cnVjdGVkIGF1dG9tYXRpY2FsbHkgZHVyaW5nIE1ldGFkYXRhIHJldHJpZXZhbC4gICBIb3dldmVyIGl0IGlzIGFsc28gcG9zc2libGUgdG8gY29uc3RydWN0IHRoZW1cclxuZGlyZWN0bHkgdmlhIHRoZSBjb25zdHJ1Y3Rvci5cclxuKiovXHJcbmV4cG9ydCBjbGFzcyBOYXZpZ2F0aW9uUHJvcGVydHkge1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF8kdHlwZU5hbWU6IHN0cmluZztcclxuICAvKiogSXMgdGhpcyBhIERhdGFQcm9wZXJ0eT8gLSBhbHdheXMgZmFsc2UgaGVyZSBcclxuICBBbGxvd3MgcG9seW1vcnBoaWMgdHJlYXRtZW50IG9mIERhdGFQcm9wZXJ0aWVzIGFuZCBOYXZpZ2F0aW9uUHJvcGVydGllcy4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGlzRGF0YVByb3BlcnR5ID0gZmFsc2U7XHJcbiAgLyoqIElzIHRoaXMgYSBOYXZpZ2F0aW9uUHJvcGVydHk/IC0gYWx3YXlzIHRydWUgaGVyZVxyXG4gIEFsbG93cyBwb2x5bW9ycGhpYyB0cmVhdG1lbnQgb2YgRGF0YVByb3BlcnRpZXMgYW5kIE5hdmlnYXRpb25Qcm9wZXJ0aWVzLiBfX1JlYWQgT25seV9fICovXHJcbiAgaXNOYXZpZ2F0aW9uUHJvcGVydHkgPSB0cnVlO1xyXG5cclxuICBmb3JtYXROYW1lID0gRGF0YVByb3BlcnR5LnByb3RvdHlwZS5mb3JtYXROYW1lO1xyXG4gIGdldEFsbFZhbGlkYXRvcnMgPSBEYXRhUHJvcGVydHkucHJvdG90eXBlLmdldEFsbFZhbGlkYXRvcnM7XHJcbiAgcmVzb2x2ZVByb3BlcnR5ID0gRGF0YVByb3BlcnR5LnByb3RvdHlwZS5yZXNvbHZlUHJvcGVydHk7XHJcblxyXG4gIC8qKiBUaGUgW1tFbnRpdHlUeXBlXV0gcmV0dXJuZWQgYnkgdGhpcyBwcm9wZXJ0eS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGVudGl0eVR5cGU6IEVudGl0eVR5cGU7XHJcbiAgLyoqIFRoZSBuYW1lIG9mIHRoZSBbW0VudGl0eVR5cGVdXSByZXR1cm5lZCBieSB0aGlzIHByb3BlcnR5LiBfX1JlYWQgT25seV9fICovXHJcbiAgZW50aXR5VHlwZU5hbWU6IHN0cmluZztcclxuICAvKiogVGhlIFtbRW50aXR5VHlwZV1dIHRoYXQgdGhpcyBwcm9wZXJ0eSBiZWxvbmdzIHRvLiAoIHNhbWUgYXMgZW50aXR5VHlwZSkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBwYXJlbnRUeXBlOiBFbnRpdHlUeXBlOyAvLyA/PyBzYW1lIGFzIGVudGl0eVR5cGVcclxuICAvKiogVGhlIFtbRW50aXR5VHlwZV1dIHRoYXQgdGhpcyBwcm9wZXJ0eSBiZWxvbmdzIHRvLiAoIHNhbWUgYXMgZW50aXR5VHlwZSkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBwYXJlbnRFbnRpdHlUeXBlOiBFbnRpdHlUeXBlOyAvLyA/PyBzYW1lIGFzIGFib3ZlXHJcbiAgLyoqIFByb3BlcnR5IG9uIHRoZSBiYXNlIHR5cGUgdGhhdCB0aGlzIHByb3BlcnR5IGlzIGluaGVyaXRlZCBmcm9tLiBXaWxsIGJlIG51bGwgaWYgdGhlIHByb3BlcnR5IGlzIG5vdCBvbiB0aGUgYmFzZSB0eXBlLiBfX1JlYWQgT25seV9fICovXHJcbiAgYmFzZVByb3BlcnR5PzogTmF2aWdhdGlvblByb3BlcnR5O1xyXG4gIC8qKiBUaGUgaW52ZXJzZSBvZiB0aGlzIE5hdmlnYXRpb25Qcm9wZXJ0eS4gIFRoZSBOYXZpZ2F0aW9uUHJvcGVydHkgdGhhdCByZXByZXNlbnRzIGEgbmF2aWdhdGlvbiBpbiB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uXHJcbiAgdG8gdGhpcyBOYXZpZ2F0aW9uUHJvcGVydHkuIE1heSBiZSB1bmRlZmluZWQgZm9yIGEgdW5kaXJlY3Rpb25hbCBOYXZpZ2F0aW9uUHJvcGVydHkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBwcml2YXRlIF9pbnZlcnNlPzogTmF2aWdhdGlvblByb3BlcnR5O1xyXG4gIC8qKiBUaGUgbmFtZSBvZiB0aGlzIHByb3BlcnR5LiBfX1JlYWQgT25seV9fICovXHJcbiAgbmFtZTogc3RyaW5nO1xyXG4gIC8qKiBUaGUgbmFtZSBvZiB0aGlzIHByb3BlcnR5IG9uIHRoZSBzZXJ2ZXIuIF9fUmVhZCBPbmx5X18gKi9cclxuICBuYW1lT25TZXJ2ZXI6IHN0cmluZztcclxuICAvKipcclxuICBXaGV0aGVyIHRoaXMgcHJvcGVydHkgcmV0dXJucyBhIHNpbmdsZSBlbnRpdHkgYXMgb3Bwb3NlZCB0byAgYW4gYXJyYXkgb2YgZW50aXRpZXMuIF9fUmVhZCBPbmx5X18gKi9cclxuICBpc1NjYWxhcjogYm9vbGVhbjtcclxuICAvKiogVGhlIG5hbWUgb2YgdGhlIGFzc29jaWF0aW9uIHRvIHdoaWNoIHRoYXQgdGhpcyBwcm9wZXJ0eSBiZWxvbmdzLiAgVGhpcyBhc3NvY2lhdGlvbk5hbWUgd2lsbCBiZSBzaGFyZWQgd2l0aCB0aGlzXHJcbiAgcHJvcGVydGllcyAnaW52ZXJzZScuIF9fUmVhZCBPbmx5X18gKi9cclxuICBhc3NvY2lhdGlvbk5hbWU6IHN0cmluZztcclxuICAvKiogVGhlIG5hbWVzIG9mIHRoZSBmb3JlaWduIGtleSBEYXRhUHJvcGVydGllcyBhc3NvY2lhdGVkIHdpdGggdGhpcyBOYXZpZ2F0aW9uUHJvcGVydHkuIFRoZXJlIHdpbGwgdXN1YWxseSBvbmx5IGJlIGEgc2luZ2xlIERhdGFQcm9wZXJ0eSBhc3NvY2lhdGVkXHJcbiAgd2l0aCBhIE5hdmlnYXRpb24gcHJvcGVydHkgZXhjZXB0IGluIHRoZSBjYXNlIG9mIGVudGl0aWVzIHdpdGggbXVsdGlwYXJ0IGtleXMuIF9fUmVhZCBPbmx5X18gKi9cclxuICBmb3JlaWduS2V5TmFtZXM6IHN0cmluZ1tdO1xyXG4gIC8qKiBUaGUgc2VydmVyIHNpZGUgbmFtZXMgb2YgdGhlIGZvcmVpZ24ga2V5IERhdGFQcm9wZXJ0aWVzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIE5hdmlnYXRpb25Qcm9wZXJ0eS4gVGhlcmUgd2lsbCB1c3VhbGx5IG9ubHkgYmUgYSBzaW5nbGUgRGF0YVByb3BlcnR5IGFzc29jaWF0ZWRcclxuICB3aXRoIGEgTmF2aWdhdGlvbiBwcm9wZXJ0eSBleGNlcHQgaW4gdGhlIGNhc2Ugb2YgZW50aXRpZXMgd2l0aCBtdWx0aXBhcnQga2V5cy4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGZvcmVpZ25LZXlOYW1lc09uU2VydmVyOiBzdHJpbmdbXTtcclxuICAvKiogVGhlIG5hbWVzIG9mIHRoZSBmb3JlaWduIGtleSBEYXRhUHJvcGVydGllcyBhdCB0aGUgb3RoZXIgZW5kIG9mIHRoZSByZWxhdGlvbnNoaXAuIF9fUmVhZCBPbmx5X18gKi9cclxuICBpbnZGb3JlaWduS2V5TmFtZXM6IHN0cmluZ1tdO1xyXG4gIC8qKiBUaGUgc2VydmVyIHNpZGUgbmFtZXMgb2YgdGhlIGZvcmVpZ24ga2V5IERhdGFQcm9wZXJ0aWVzIGF0IHRoZSBvdGhlciBlbmQgb2YgdGhlIHJlbGF0aW9uc2hpcC4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGludkZvcmVpZ25LZXlOYW1lc09uU2VydmVyOiBzdHJpbmdbXTtcclxuICAvKiogVGhlICdmb3JlaWduIGtleScgRGF0YVByb3BlcnRpZXMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgTmF2aWdhdGlvblByb3BlcnR5LiBUaGVyZSB3aWxsIHVzdWFsbHkgb25seSBiZSBhIHNpbmdsZSBEYXRhUHJvcGVydHkgYXNzb2NpYXRlZFxyXG4gIHdpdGggYSBOYXZpZ2F0aW9uIHByb3BlcnR5IGV4Y2VwdCBpbiB0aGUgY2FzZSBvZiBlbnRpdGllcyB3aXRoIG11bHRpcGFydCBrZXlzLiBfX1JlYWQgT25seV9fICovXHJcbiAgcmVsYXRlZERhdGFQcm9wZXJ0aWVzOiBEYXRhUHJvcGVydHlbXTtcclxuICAvKiogVGhlIFtbVmFsaWRhdG9yXV0gaW5zdGFuY2VzIHRoYXQgYXJlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHByb3BlcnR5LiBWYWxpZGF0b3JzIGNhbiBiZSBhZGRlZCBhbmRcclxuICByZW1vdmVkIGZyb20gdGhpcyBjb2xsZWN0aW9uLiBfX1JlYWQgT25seV9fICovXHJcbiAgdmFsaWRhdG9yczogVmFsaWRhdG9yW107XHJcbiAgLyoqIFRoZSBkaXNwbGF5IG5hbWUgb2YgdGhpcyBwcm9wZXJ0eS4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGRpc3BsYXlOYW1lOiBzdHJpbmc7XHJcbiAgaXNVbm1hcHBlZDogYm9vbGVhbjtcclxuICAvKiogQSBmcmVlIGZvcm0gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gZGVmaW5lIGFueSBjdXN0b20gbWV0YWRhdGEgZm9yIHRoaXMgTmF2aWdhdGlvblByb3BlcnR5LiAgICoqL1xyXG4gIGN1c3RvbTogT2JqZWN0O1xyXG5cclxuICAvKiogTmF2aWdhdGlvblByb3BlcnR5IGNvbnN0cnVjdG9yXHJcbiAgPiAgICAgIGxldCBob21lQWRkcmVzc1Byb3AgPSBuZXcgTmF2aWdhdGlvblByb3BlcnR5KCB7XHJcbiAgPiAgICAgICAgICBuYW1lOiBcImhvbWVBZGRyZXNzXCIsXHJcbiAgPiAgICAgICAgICBlbnRpdHlUeXBlTmFtZTogXCJBZGRyZXNzOiNteU5hbWVzcGFjZVwiLFxyXG4gID4gICAgICAgICAgaXNTY2FsYXI6IHRydWUsXHJcbiAgPiAgICAgICAgICBhc3NvY2lhdGlvbk5hbWU6IFwiYWRkcmVzc19wZXJzb25cIixcclxuICA+ICAgICAgICAgIGZvcmVpZ25LZXlOYW1lczogW1wiaG9tZUFkZHJlc3NJZFwiXVxyXG4gID4gICAgICB9KTtcclxuICA+ICAgICAgbGV0IGhvbWVBZGRyZXNzSWRQcm9wID0gbmV3IERhdGFQcm9wZXJ0eSgge1xyXG4gID4gICAgICAgICAgbmFtZTogXCJob21lQWRkcmVzc0lkXCJcclxuICA+ICAgICAgICAgIGRhdGFUeXBlOiBEYXRhVHlwZS5JbnRlZ2VyXHJcbiAgPiAgICAgIH0pO1xyXG4gID4gICAgICAvLyBhc3N1bWluZyBwZXJzb25FbnRpdHlUeXBlIGlzIGEgbmV3bHkgY29uc3RydWN0ZWQgRW50aXR5VHlwZVxyXG4gID4gICAgICBwZXJzb25FbnRpdHlUeXBlLmFkZFByb3BlcnR5KGhvbWVBZGRyZXNzUHJvcCk7XHJcbiAgPiAgICAgIHBlcnNvbkVudGl0eVR5cGUuYWRkUHJvcGVydHkoaG9tZUFkZHJlc3NJZFByb3ApO1xyXG4gIEBwYXJhbSBjb25maWcgLSBBIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlxyXG4gICoqL1xyXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogTmF2aWdhdGlvblByb3BlcnR5Q29uZmlnKSB7XHJcbiAgICBhc3NlcnRDb25maWcoY29uZmlnKVxyXG4gICAgICAud2hlcmVQYXJhbShcIm5hbWVcIikuaXNTdHJpbmcoKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJuYW1lT25TZXJ2ZXJcIikuaXNTdHJpbmcoKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJlbnRpdHlUeXBlTmFtZVwiKS5pc1N0cmluZygpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiaXNTY2FsYXJcIikuaXNCb29sZWFuKCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KHRydWUpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiYXNzb2NpYXRpb25OYW1lXCIpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiZm9yZWlnbktleU5hbWVzXCIpLmlzQXJyYXkoKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChbXSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJmb3JlaWduS2V5TmFtZXNPblNlcnZlclwiKS5pc0FycmF5KCkuaXNTdHJpbmcoKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoW10pXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiaW52Rm9yZWlnbktleU5hbWVzXCIpLmlzQXJyYXkoKS5pc1N0cmluZygpLmlzT3B0aW9uYWwoKS53aXRoRGVmYXVsdChbXSlcclxuICAgICAgLndoZXJlUGFyYW0oXCJpbnZGb3JlaWduS2V5TmFtZXNPblNlcnZlclwiKS5pc0FycmF5KCkuaXNTdHJpbmcoKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoW10pXHJcbiAgICAgIC53aGVyZVBhcmFtKFwidmFsaWRhdG9yc1wiKS5pc0luc3RhbmNlT2YoVmFsaWRhdG9yKS5pc0FycmF5KCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KFtdKVxyXG4gICAgICAud2hlcmVQYXJhbShcImRpc3BsYXlOYW1lXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAud2hlcmVQYXJhbShcImN1c3RvbVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLmFwcGx5QWxsKHRoaXMpO1xyXG4gICAgbGV0IGhhc05hbWUgPSAhISh0aGlzLm5hbWUgfHwgdGhpcy5uYW1lT25TZXJ2ZXIpO1xyXG5cclxuICAgIGlmICghaGFzTmFtZSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBIE5hdmlnYXRpb24gcHJvcGVydHkgbXVzdCBiZSBpbnN0YW50aWF0ZWQgd2l0aCBlaXRoZXIgYSAnbmFtZScgb3IgYSAnbmFtZU9uU2VydmVyJyBwcm9wZXJ0eVwiKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gIEdlbmVyYWwgcHVycG9zZSBwcm9wZXJ0eSBzZXQgbWV0aG9kXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBteUVudGl0eVR5cGUgaXMgYW4gRW50aXR5VHlwZVxyXG4gID4gICAgICBsZXQgcHJvcCA9IG15RW50aXR5VHlwZS5nZXRQcm9wZXJ0eShcIm15UHJvcGVydHlcIik7XHJcbiAgPiAgICAgIHByb3Auc2V0UHJvcGVydGllcygge1xyXG4gID4gICAgICAgICAgY3VzdG9tOiB7IGZvbzogNywgYmFyOiBcInRlc3RcIiB9XHJcbiAgPiAgICAgIH0pO1xyXG4gIEBwYXJhbSBjb25maWcgLSBBIGNvbmZpZyBvYmplY3RcclxuICAqKi9cclxuICAvLyBUT0RPOiBjcmVhdGUgYW4gaW50ZXJmYWNlIGZvciB0aGlzLlxyXG4gIHNldFByb3BlcnRpZXMoY29uZmlnOiB7XHJcbiAgICBkaXNwbGF5TmFtZT86IHN0cmluZyxcclxuICAgIGZvcmVpZ25LZXlOYW1lcz86IHN0cmluZ1tdLFxyXG4gICAgaW52Rm9yZWlnbktleU5hbWVzPzogc3RyaW5nW10sXHJcbiAgICBpbnZlcnNlPzogTmF2aWdhdGlvblByb3BlcnR5IHwgc3RyaW5nLFxyXG4gICAgY3VzdG9tPzogT2JqZWN0XHJcbiAgfSkge1xyXG4gICAgaWYgKCF0aGlzLnBhcmVudFR5cGUpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNhbGwgTmF2aWdhdGlvblByb3BlcnR5LnNldFByb3BlcnRpZXMgdW50aWwgdGhlIHBhcmVudCBFbnRpdHlUeXBlIG9mIHRoZSBOYXZpZ2F0aW9uUHJvcGVydHkgaGFzIGJlZW4gc2V0LlwiKTtcclxuICAgIH1cclxuICAgIGxldCBpbnZlcnNlID0gY29uZmlnLmludmVyc2U7XHJcbiAgICBpZiAoaW52ZXJzZSkgZGVsZXRlIGNvbmZpZy5pbnZlcnNlO1xyXG4gICAgYXNzZXJ0Q29uZmlnKGNvbmZpZylcclxuICAgICAgLndoZXJlUGFyYW0oXCJkaXNwbGF5TmFtZVwiKS5pc09wdGlvbmFsKClcclxuICAgICAgLndoZXJlUGFyYW0oXCJmb3JlaWduS2V5TmFtZXNcIikuaXNBcnJheSgpLmlzU3RyaW5nKCkuaXNPcHRpb25hbCgpLndpdGhEZWZhdWx0KFtdKVxyXG4gICAgICAud2hlcmVQYXJhbShcImludkZvcmVpZ25LZXlOYW1lc1wiKS5pc0FycmF5KCkuaXNTdHJpbmcoKS5pc09wdGlvbmFsKCkud2l0aERlZmF1bHQoW10pXHJcbiAgICAgIC53aGVyZVBhcmFtKFwiY3VzdG9tXCIpLmlzT3B0aW9uYWwoKVxyXG4gICAgICAuYXBwbHlBbGwodGhpcyk7XHJcbiAgICB0aGlzLnBhcmVudFR5cGUuX3VwZGF0ZU5hbWVzKHRoaXMpO1xyXG5cclxuICAgIHRoaXMuX3Jlc29sdmVOcCgpO1xyXG4gICAgaWYgKGludmVyc2UpIHtcclxuICAgICAgdGhpcy5zZXRJbnZlcnNlKGludmVyc2UpO1xyXG4gICAgfVxyXG5cclxuICB9XHJcblxyXG4gIC8qKiBUaGUgaW52ZXJzZSBvZiB0aGlzIE5hdmlnYXRpb25Qcm9wZXJ0eS4gIFRoZSBOYXZpZ2F0aW9uUHJvcGVydHkgdGhhdCByZXByZXNlbnRzIGEgbmF2aWdhdGlvbiBpbiB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uXHJcbiAgdG8gdGhpcyBOYXZpZ2F0aW9uUHJvcGVydHkuIE1heSBiZSB1bmRlZmluZWQgZm9yIGEgdW5kaXJlY3Rpb25hbCBOYXZpZ2F0aW9uUHJvcGVydHkuIF9fUmVhZCBPbmx5X18gKi9cclxuICBnZXQgaW52ZXJzZSgpOiBOYXZpZ2F0aW9uUHJvcGVydHkgfCB1bmRlZmluZWQge1xyXG4gICAgcmV0dXJuIHRoaXMuZ2V0SW52ZXJzZSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgZ2V0SW52ZXJzZSgpOiBOYXZpZ2F0aW9uUHJvcGVydHkgfCB1bmRlZmluZWQge1xyXG4gICAgbGV0IG5wOiBOYXZpZ2F0aW9uUHJvcGVydHkgPSB0aGlzO1xyXG4gICAgd2hpbGUgKCFucC5faW52ZXJzZSAmJiBucC5iYXNlUHJvcGVydHkpIHtcclxuICAgICAgbnAgPSBucC5iYXNlUHJvcGVydHk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnAuX2ludmVyc2U7XHJcbiAgfVxyXG5cclxuICBzZXRJbnZlcnNlKGludmVyc2VOcDogTmF2aWdhdGlvblByb3BlcnR5IHwgc3RyaW5nKSB7XHJcbiAgICAvLyBsZXQgaW52TnA6IE5hdmlnYXRpb25Qcm9wZXJ0eTtcclxuICAgIGxldCBpbnZOcCA9IChpbnZlcnNlTnAgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uUHJvcGVydHkpID8gaW52ZXJzZU5wIDogdGhpcy5lbnRpdHlUeXBlLmdldE5hdmlnYXRpb25Qcm9wZXJ0eShpbnZlcnNlTnApO1xyXG5cclxuICAgIGlmICghaW52TnApIHtcclxuICAgICAgdGhyb3cgdGhyb3dTZXRJbnZlcnNlRXJyb3IodGhpcywgXCJVbmFibGUgdG8gZmluZCBpbnZlcnNlIHByb3BlcnR5OiBcIiArIGludmVyc2VOcCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuX2ludmVyc2UgfHwgaW52TnAuX2ludmVyc2UpIHtcclxuICAgICAgdGhyb3dTZXRJbnZlcnNlRXJyb3IodGhpcywgXCJJdCBoYXMgYWxyZWFkeSBiZWVuIHNldCBvbiBvbmUgc2lkZSBvciB0aGUgb3RoZXIuXCIpO1xyXG4gICAgfVxyXG4gICAgaWYgKGludk5wLmVudGl0eVR5cGUgIT09IHRoaXMucGFyZW50VHlwZSkge1xyXG4gICAgICB0aHJvd1NldEludmVyc2VFcnJvcih0aGlzLCBpbnZOcC5mb3JtYXROYW1lICsgXCIgaXMgbm90IGEgdmFsaWQgaW52ZXJzZSBwcm9wZXJ0eSBmb3IgdGhpcy5cIik7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5hc3NvY2lhdGlvbk5hbWUpIHtcclxuICAgICAgaW52TnAuYXNzb2NpYXRpb25OYW1lID0gdGhpcy5hc3NvY2lhdGlvbk5hbWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAoIWludk5wLmFzc29jaWF0aW9uTmFtZSkge1xyXG4gICAgICAgIGludk5wLmFzc29jaWF0aW9uTmFtZSA9IHRoaXMuZm9ybWF0TmFtZSgpICsgXCJfXCIgKyBpbnZOcC5mb3JtYXROYW1lKCk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5hc3NvY2lhdGlvbk5hbWUgPSBpbnZOcC5hc3NvY2lhdGlvbk5hbWU7XHJcbiAgICB9XHJcbiAgICB0aGlzLl9yZXNvbHZlTnAoKTtcclxuICAgIGludk5wLl9yZXNvbHZlTnAoKTtcclxuICB9XHJcblxyXG4gIC8vIC8vIEluIHByb2dyZXNzIC0gd2lsbCBiZSB1c2VkIGZvciBtYW51YWwgbWV0YWRhdGEgY29uZmlnXHJcbiAgLy8gY3JlYXRlSW52ZXJzZShjb25maWc6IGFueSkge1xyXG5cclxuICAvLyAgIGlmICghdGhpcy5lbnRpdHlUeXBlKSB7XHJcbiAgLy8gICAgIHRocm93Q3JlYXRlSW52ZXJzZUVycm9yKHRoaXMsIFwiaGFzIG5vdCB5ZXQgYmVlbiBkZWZpbmVkLlwiKTtcclxuICAvLyAgIH1cclxuICAvLyAgIGlmICh0aGlzLmVudGl0eVR5cGUuaXNGcm96ZW4pIHtcclxuICAvLyAgICAgdGhyb3dDcmVhdGVJbnZlcnNlRXJyb3IodGhpcywgXCJpcyBmcm96ZW4uXCIpO1xyXG4gIC8vICAgfVxyXG4gIC8vICAgbGV0IG1ldGFkYXRhU3RvcmUgPSB0aGlzLmVudGl0eVR5cGUubWV0YWRhdGFTdG9yZTtcclxuICAvLyAgIGlmIChtZXRhZGF0YVN0b3JlID09IG51bGwpIHtcclxuICAvLyAgICAgdGhyb3dDcmVhdGVJbnZlcnNlRXJyb3IodGhpcywgXCJoYXMgbm90IHlldCBiZWVuIGFkZGVkIHRvIHRoZSBtZXRhZGF0YVN0b3JlLlwiKTtcclxuICAvLyAgIH1cclxuXHJcbiAgLy8gICBjb25maWcuZW50aXR5VHlwZU5hbWUgPSB0aGlzLnBhcmVudEVudGl0eVR5cGUubmFtZTtcclxuICAvLyAgIGNvbmZpZy5hc3NvY2lhdGlvbk5hbWUgPSB0aGlzLmFzc29jaWF0aW9uTmFtZTtcclxuICAvLyAgIGxldCBpbnZOcCA9IG5ldyBOYXZpZ2F0aW9uUHJvcGVydHkoY29uZmlnKTtcclxuICAvLyAgIHRoaXMucGFyZW50RW50aXR5VHlwZS5hZGROYXZpZ2F0aW9uUHJvcGVydHkoaW52TnApO1xyXG4gIC8vICAgcmV0dXJuIGludk5wO1xyXG4gIC8vIH07XHJcblxyXG5cclxuXHJcbiAgdG9KU09OKCkge1xyXG4gICAgcmV0dXJuIGNvcmUudG9Kc29uKHRoaXMsIHtcclxuICAgICAgbmFtZTogbnVsbCxcclxuICAgICAgZW50aXR5VHlwZU5hbWU6IG51bGwsXHJcbiAgICAgIGlzU2NhbGFyOiBudWxsLFxyXG4gICAgICBhc3NvY2lhdGlvbk5hbWU6IG51bGwsXHJcbiAgICAgIHZhbGlkYXRvcnM6IG51bGwsXHJcbiAgICAgIGRpc3BsYXlOYW1lOiBudWxsLFxyXG4gICAgICBmb3JlaWduS2V5TmFtZXM6IG51bGwsXHJcbiAgICAgIGludkZvcmVpZ25LZXlOYW1lczogbnVsbCxcclxuICAgICAgY3VzdG9tOiBudWxsXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHN0YXRpYyBmcm9tSlNPTihqc29uOiBhbnkpIHtcclxuICAgIGlmIChqc29uLnZhbGlkYXRvcnMpIHtcclxuICAgICAganNvbi52YWxpZGF0b3JzID0ganNvbi52YWxpZGF0b3JzLm1hcChWYWxpZGF0b3IuZnJvbUpTT04pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5ldyBOYXZpZ2F0aW9uUHJvcGVydHkoanNvbik7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfcmVzb2x2ZU5wKCkge1xyXG4gICAgbGV0IG5wID0gdGhpcztcclxuICAgIGxldCBlbnRpdHlUeXBlID0gbnAuZW50aXR5VHlwZTtcclxuICAgIGxldCBpbnZOcCA9IGNvcmUuYXJyYXlGaXJzdChlbnRpdHlUeXBlLm5hdmlnYXRpb25Qcm9wZXJ0aWVzLCAoYWx0TnApID0+IHtcclxuICAgICAgLy8gQ2FuJ3QgZG8gdGhpcyBiZWNhdXNlIG9mIHBvc3NpYmlsaXR5IG9mIGNvbXBhcmluZyBhIGJhc2UgY2xhc3MgbnAgd2l0aCBhIHN1YmNsYXNzIGFsdE5wLlxyXG4gICAgICAvLyByZXR1cm4gYWx0TnAuYXNzb2NpYXRpb25OYW1lID09PSBucC5hc3NvY2lhdGlvbk5hbWVcclxuICAgICAgLy8gICAgJiYgYWx0TnAgIT09IG5wO1xyXG4gICAgICAvLyBTbyB1c2UgdGhpcyBpbnN0ZWFkLlxyXG4gICAgICByZXR1cm4gYWx0TnAuYXNzb2NpYXRpb25OYW1lID09PSBucC5hc3NvY2lhdGlvbk5hbWUgJiZcclxuICAgICAgICAoYWx0TnAubmFtZSAhPT0gbnAubmFtZSB8fCBhbHROcC5lbnRpdHlUeXBlTmFtZSAhPT0gbnAuZW50aXR5VHlwZU5hbWUpO1xyXG4gICAgfSk7XHJcbiAgICBucC5faW52ZXJzZSA9IGludk5wIHx8IHVuZGVmaW5lZDtcclxuICAgIC8vaWYgKGludk5wICYmIGludk5wLmludmVyc2UgPT0gbnVsbCkge1xyXG4gICAgLy8gICAgaW52TnAuX3Jlc29sdmVOcCgpO1xyXG4gICAgLy99XHJcbiAgICBpZiAoIWludk5wKSB7XHJcbiAgICAgIC8vIHVuaWRpcmVjdGlvbmFsIDEtbiByZWxhdGlvbnNoaXBcclxuICAgICAgbnAuaW52Rm9yZWlnbktleU5hbWVzLmZvckVhY2goZnVuY3Rpb24gKGludkZrTmFtZSkge1xyXG4gICAgICAgIGxldCBma1Byb3AgPSBlbnRpdHlUeXBlLmdldERhdGFQcm9wZXJ0eShpbnZGa05hbWUpO1xyXG4gICAgICAgIGlmIChma1Byb3AgPT0gbnVsbCkge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRW50aXR5VHlwZSAnXCIgKyBucC5lbnRpdHlUeXBlTmFtZSArIFwiJyBoYXMgbm8gZm9yZWlnbiBrZXkgbWF0Y2hpbmcgJ1wiICsgaW52RmtOYW1lICsgXCInXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBsZXQgaW52RW50aXR5VHlwZSA9IG5wLnBhcmVudFR5cGU7XHJcbiAgICAgICAgaW52TnAgPSBjb3JlLmFycmF5Rmlyc3QoaW52RW50aXR5VHlwZS5uYXZpZ2F0aW9uUHJvcGVydGllcywgKG5wMikgPT4ge1xyXG4gICAgICAgICAgcmV0dXJuIG5wMi5pbnZGb3JlaWduS2V5TmFtZXMgJiYgbnAyLmludkZvcmVpZ25LZXlOYW1lcy5pbmRleE9mKGZrUHJvcCEubmFtZSkgPj0gMCAmJiBucDIuZW50aXR5VHlwZSA9PT0gZmtQcm9wIS5wYXJlbnRUeXBlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGZrUHJvcC5pbnZlcnNlTmF2aWdhdGlvblByb3BlcnR5ID0gaW52TnAgfHwgdW5kZWZpbmVkO1xyXG4gICAgICAgIGNvcmUuYXJyYXlBZGRJdGVtVW5pcXVlKGVudGl0eVR5cGUuZm9yZWlnbktleVByb3BlcnRpZXMsIGZrUHJvcCk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHJlc29sdmVSZWxhdGVkKG5wKTtcclxuICB9XHJcblxyXG59XHJcbk5hdmlnYXRpb25Qcm9wZXJ0eS5wcm90b3R5cGUuXyR0eXBlTmFtZSA9IFwiTmF2aWdhdGlvblByb3BlcnR5XCI7XHJcblxyXG5mdW5jdGlvbiB0aHJvd1NldEludmVyc2VFcnJvcihucDogTmF2aWdhdGlvblByb3BlcnR5LCBtZXNzYWdlOiBzdHJpbmcpIHtcclxuICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3Qgc2V0IHRoZSBpbnZlcnNlIHByb3BlcnR5IGZvcjogXCIgKyBucC5mb3JtYXROYW1lKCkgKyBcIi4gXCIgKyBtZXNzYWdlKTtcclxufVxyXG5cclxuLy8gTm90IGN1cnJlbnQgdXNlZC5cclxuLy8gZnVuY3Rpb24gdGhyb3dDcmVhdGVJbnZlcnNlRXJyb3IobnA6IE5hdmlnYXRpb25Qcm9wZXJ0eSwgbWVzc2FnZTogc3RyaW5nKSB7XHJcbi8vICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNyZWF0ZSBpbnZlcnNlIGZvcjogXCIgKyBucC5mb3JtYXROYW1lKCkgKyBcIi4gVGhlIGVudGl0eVR5cGUgZm9yIHRoaXMgbmF2aWdhdGlvbiBwcm9wZXJ0eSBcIiArIG1lc3NhZ2UpO1xyXG4vLyB9XHJcblxyXG4vLyBzZXRzIG5hdmlnYXRpb24gcHJvcGVydHk6IHJlbGF0ZWREYXRhUHJvcGVydGllcyBhbmQgZGF0YVByb3BlcnR5OiByZWxhdGVkTmF2aWdhdGlvblByb3BlcnR5XHJcbmZ1bmN0aW9uIHJlc29sdmVSZWxhdGVkKG5wOiBOYXZpZ2F0aW9uUHJvcGVydHkpIHtcclxuXHJcbiAgbGV0IGZrTmFtZXMgPSBucC5mb3JlaWduS2V5TmFtZXM7XHJcbiAgaWYgKGZrTmFtZXMubGVuZ3RoID09PSAwKSByZXR1cm47XHJcblxyXG4gIGxldCBwYXJlbnRFbnRpdHlUeXBlID0gbnAucGFyZW50VHlwZTtcclxuICBsZXQgZmtQcm9wcyA9IGZrTmFtZXMubWFwKGZ1bmN0aW9uIChma05hbWUpIHtcclxuICAgIHJldHVybiBwYXJlbnRFbnRpdHlUeXBlLmdldERhdGFQcm9wZXJ0eShma05hbWUpO1xyXG4gIH0pO1xyXG4gIGxldCBma1Byb3BDb2xsZWN0aW9uID0gcGFyZW50RW50aXR5VHlwZS5mb3JlaWduS2V5UHJvcGVydGllcztcclxuXHJcbiAgZmtQcm9wcy5mb3JFYWNoKChkcDogRGF0YVByb3BlcnR5KSA9PiB7XHJcbiAgICBjb3JlLmFycmF5QWRkSXRlbVVuaXF1ZShma1Byb3BDb2xsZWN0aW9uLCBkcCk7XHJcbiAgICBkcC5yZWxhdGVkTmF2aWdhdGlvblByb3BlcnR5ID0gbnA7XHJcbiAgICAvLyBub3cgdXBkYXRlIHRoZSBpbnZlcnNlXHJcbiAgICBjb3JlLmFycmF5QWRkSXRlbVVuaXF1ZShucC5lbnRpdHlUeXBlLmludmVyc2VGb3JlaWduS2V5UHJvcGVydGllcywgZHApO1xyXG4gICAgaWYgKG5wLnJlbGF0ZWREYXRhUHJvcGVydGllcykge1xyXG4gICAgICBjb3JlLmFycmF5QWRkSXRlbVVuaXF1ZShucC5yZWxhdGVkRGF0YVByb3BlcnRpZXMsIGRwKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIG5wLnJlbGF0ZWREYXRhUHJvcGVydGllcyA9IFtkcF07XHJcbiAgICB9XHJcbiAgfSk7XHJcbn1cclxuXHJcblxyXG4vKipcclxuQXV0b0dlbmVyYXRlZEtleVR5cGUgaXMgYW4gJ0VudW0nIGNvbnRhaW5pbmcgYWxsIG9mIHRoZSB2YWxpZCBzdGF0ZXMgZm9yIGFuIGF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkIGtleS5cclxuKiovXHJcbmV4cG9ydCBjbGFzcyBBdXRvR2VuZXJhdGVkS2V5VHlwZSBleHRlbmRzIEJyZWV6ZUVudW0ge1xyXG5cclxuICAvKipcclxuICBUaGlzIGVudGl0eSBkb2VzIG5vdCBoYXZlIGFuIGF1dG9nZW5lcmF0ZWQga2V5LlxyXG4gIFRoZSBjbGllbnQgbXVzdCBzZXQgdGhlIGtleSBiZWZvcmUgYWRkaW5nIHRoZSBlbnRpdHkgdG8gdGhlIEVudGl0eU1hbmFnZXJcclxuICAqKi9cclxuICBzdGF0aWMgTm9uZSA9IG5ldyBBdXRvR2VuZXJhdGVkS2V5VHlwZSgpO1xyXG4gIC8qKiBcclxuICBUaGlzIGVudGl0eSdzIGtleSBpcyBhbiBJZGVudGl0eSBjb2x1bW4gYW5kIGlzIHNldCBieSB0aGUgYmFja2VuZCBkYXRhYmFzZS5cclxuICBLZXlzIGZvciBuZXcgZW50aXRpZXMgd2lsbCBiZSB0ZW1wb3JhcnkgdW50aWwgdGhlIGVudGl0aWVzIGFyZSBzYXZlZCBhdCB3aGljaCBwb2ludCB0aGUga2V5cyB3aWxsXHJcbiAgYmUgY29udmVydGVkIHRvIHRoZWlyICdyZWFsJyB2ZXJzaW9ucy5cclxuICAqKi9cclxuICBzdGF0aWMgSWRlbnRpdHkgPSBuZXcgQXV0b0dlbmVyYXRlZEtleVR5cGUoKTtcclxuICAvKipcclxuICBUaGlzIGVudGl0eSdzIGtleSBpcyBnZW5lcmF0ZWQgYnkgYSBLZXlHZW5lcmF0b3IgYW5kIGlzIHNldCBieSB0aGUgYmFja2VuZCBkYXRhYmFzZS5cclxuICBLZXlzIGZvciBuZXcgZW50aXRpZXMgd2lsbCBiZSB0ZW1wb3JhcnkgdW50aWwgdGhlIGVudGl0aWVzIGFyZSBzYXZlZCBhdCB3aGljaCBwb2ludCB0aGUga2V5cyB3aWxsXHJcbiAgYmUgY29udmVydGVkIHRvIHRoZWlyICdyZWFsJyB2ZXJzaW9ucy5cclxuICAqKi9cclxuICBzdGF0aWMgS2V5R2VuZXJhdG9yID0gbmV3IEF1dG9HZW5lcmF0ZWRLZXlUeXBlKCk7XHJcblxyXG59XHJcbkF1dG9HZW5lcmF0ZWRLZXlUeXBlLnByb3RvdHlwZS5fJHR5cGVOYW1lID0gXCJBdXRvR2VuZXJhdGVkS2V5VHlwZVwiO1xyXG5FcnJvclsneCddID0gQXV0b0dlbmVyYXRlZEtleVR5cGUucmVzb2x2ZVN5bWJvbHMoKTtcclxuXHJcblxyXG4vLyBtaXhpbiBtZXRob2RzXHJcbi8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG5kZWNsYXJlIG1vZHVsZSBcIi4vYXNzZXJ0LXBhcmFtXCIge1xyXG4gIGludGVyZmFjZSBQYXJhbSB7XHJcbiAgICBpc0VudGl0eSgpOiBQYXJhbTtcclxuICAgIGlzRW50aXR5UHJvcGVydHkoKTogUGFyYW07XHJcbiAgfVxyXG59XHJcblxyXG5sZXQgcHJvdG8gPSBQYXJhbS5wcm90b3R5cGU7XHJcblxyXG4vLyAndGhpcycgYmVsb3cgaXMgVFMgYW5ub3RhdGlvbiBcclxucHJvdG8uaXNFbnRpdHkgPSBmdW5jdGlvbiAodGhpczogUGFyYW0pIHtcclxuICByZXR1cm4gdGhpcy5fYWRkQ29udGV4dCh7XHJcbiAgICBmbjogaXNFbnRpdHksXHJcbiAgICBtc2c6IFwiIG11c3QgYmUgYW4gZW50aXR5XCJcclxuICB9KTtcclxufTtcclxuXHJcbmZ1bmN0aW9uIGlzRW50aXR5KGNvbnRleHQ6IGFueSwgdjogYW55KSB7XHJcbiAgaWYgKHYgPT0gbnVsbCkgcmV0dXJuIGZhbHNlO1xyXG4gIHJldHVybiAodi5lbnRpdHlUeXBlICE9PSB1bmRlZmluZWQpO1xyXG59XHJcblxyXG5wcm90by5pc0VudGl0eVByb3BlcnR5ID0gZnVuY3Rpb24gKHRoaXM6IFBhcmFtKSB7XHJcbiAgcmV0dXJuIHRoaXMuX2FkZENvbnRleHQoe1xyXG4gICAgZm46IGlzRW50aXR5UHJvcGVydHksXHJcbiAgICBtc2c6IFwiIG11c3QgYmUgZWl0aGVyIGEgRGF0YVByb3BlcnR5IG9yIGEgTmF2aWdhdGlvblByb3BlcnR5XCJcclxuICB9KTtcclxufTtcclxuXHJcbmZ1bmN0aW9uIGlzRW50aXR5UHJvcGVydHkoY29udGV4dDogYW55LCB2OiBhbnkpIHtcclxuICBpZiAodiA9PSBudWxsKSByZXR1cm4gZmFsc2U7XHJcbiAgcmV0dXJuICh2LmlzRGF0YVByb3BlcnR5IHx8IHYuaXNOYXZpZ2F0aW9uUHJvcGVydHkpO1xyXG59XHJcblxyXG4vLyBmdW5jdGlvbnMgc2hhcmVkIGJldHdlZW4gY2xhc3NlcyByZWxhdGVkIHRvIE1ldGFkYXRhXHJcblxyXG5mdW5jdGlvbiBpc1F1YWxpZmllZFR5cGVOYW1lKGVudGl0eVR5cGVOYW1lOiBzdHJpbmcpIHtcclxuICByZXR1cm4gZW50aXR5VHlwZU5hbWUuaW5kZXhPZihcIjojXCIpID49IDA7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBxdWFsaWZ5VHlwZU5hbWUoc2hvcnROYW1lOiBzdHJpbmcsIG5zPzogc3RyaW5nKSB7XHJcbiAgaWYgKG5zICYmIG5zLmxlbmd0aCA+IDApIHtcclxuICAgIHJldHVybiBzaG9ydE5hbWUgKyBcIjojXCIgKyBucztcclxuICB9IGVsc2Uge1xyXG4gICAgcmV0dXJuIHNob3J0TmFtZTtcclxuICB9XHJcbn1cclxuXHJcbi8vIFVzZWQgYnkgYm90aCBDb21wbGV4VHlwZSBhbmQgRW50aXR5VHlwZVxyXG5mdW5jdGlvbiBhZGRQcm9wZXJ0aWVzKGVudGl0eVR5cGU6IFN0cnVjdHVyYWxUeXBlLCBwcm9wT2JqOiBPYmplY3QgfCB1bmRlZmluZWQsIGN0b3I6IGFueSkge1xyXG4gIGlmIChwcm9wT2JqID09IG51bGwpIHJldHVybjtcclxuICBpZiAoQXJyYXkuaXNBcnJheShwcm9wT2JqKSkge1xyXG4gICAgcHJvcE9iai5mb3JFYWNoKGVudGl0eVR5cGUuX2FkZFByb3BlcnR5Q29yZS5iaW5kKGVudGl0eVR5cGUpKTtcclxuICB9IGVsc2UgaWYgKHR5cGVvZiAocHJvcE9iaikgPT09ICdvYmplY3QnKSB7XHJcbiAgICBmb3IgKGxldCBrZXkgaW4gcHJvcE9iaikge1xyXG4gICAgICBpZiAoY29yZS5oYXNPd25Qcm9wZXJ0eShwcm9wT2JqLCBrZXkpKSB7XHJcbiAgICAgICAgbGV0IHZhbHVlID0gcHJvcE9ialtrZXldO1xyXG4gICAgICAgIHZhbHVlLm5hbWUgPSBrZXk7XHJcbiAgICAgICAgbGV0IHByb3AgPSBuZXcgY3Rvcih2YWx1ZSk7XHJcbiAgICAgICAgZW50aXR5VHlwZS5fYWRkUHJvcGVydHlDb3JlKHByb3ApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSBlbHNlIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSAnZGF0YVByb3BlcnRpZXMnIG9yICduYXZpZ2F0aW9uUHJvcGVydGllcycgdmFsdWVzIG11c3QgYmUgZWl0aGVyIGFuIGFycmF5IG9mIGRhdGEvbmF2IHByb3BlcnRpZXMgb3IgYW4gb2JqZWN0IHdoZXJlIGVhY2ggcHJvcGVydHkgZGVmaW5lcyBhIGRhdGEvbmF2IHByb3BlcnR5XCIpO1xyXG4gIH1cclxufVxyXG5cclxuXHJcblxyXG5cclxuXHJcbiJdfQ==
|