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