breeze-client 2.2.1-cjs → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapter-ajax-angularjs/{breeze-client-adapter-ajax-angularjs.d.ts → index.d.ts} +1 -0
- package/adapter-ajax-fetch/{breeze-client-adapter-ajax-fetch.d.ts → index.d.ts} +1 -0
- package/adapter-ajax-httpclient/{breeze-client-adapter-ajax-httpclient.d.ts → index.d.ts} +1 -0
- package/adapter-ajax-jquery/{breeze-client-adapter-ajax-jquery.d.ts → index.d.ts} +1 -0
- package/adapter-ajax-post/{breeze-client-adapter-ajax-post.d.ts → index.d.ts} +1 -0
- package/adapter-data-service-odata/{breeze-client-adapter-data-service-odata.d.ts → index.d.ts} +1 -0
- package/adapter-data-service-webapi/{breeze-client-adapter-data-service-webapi.d.ts → index.d.ts} +1 -0
- package/adapter-model-library-backing-store/{breeze-client-adapter-model-library-backing-store.d.ts → index.d.ts} +1 -0
- package/adapter-model-library-ko/{breeze-client-adapter-model-library-ko.d.ts → index.d.ts} +1 -0
- package/adapter-uri-builder-json/{breeze-client-adapter-uri-builder-json.d.ts → index.d.ts} +1 -0
- package/adapter-uri-builder-odata/{breeze-client-adapter-uri-builder-odata.d.ts → index.d.ts} +1 -0
- package/esm2022/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +135 -0
- package/esm2022/adapter-ajax-angularjs/adapter-core.mjs +49 -0
- package/esm2022/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +5 -0
- package/esm2022/adapter-ajax-fetch/adapter-ajax-fetch.mjs +135 -0
- package/esm2022/adapter-ajax-fetch/adapter-core.mjs +49 -0
- package/esm2022/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +5 -0
- package/esm2022/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +139 -0
- package/esm2022/adapter-ajax-httpclient/adapter-core.mjs +49 -0
- package/esm2022/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +5 -0
- package/esm2022/adapter-ajax-jquery/adapter-ajax-jquery.mjs +107 -0
- package/esm2022/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +5 -0
- package/esm2022/adapter-ajax-post/adapter-ajax-post.mjs +77 -0
- package/esm2022/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +5 -0
- package/esm2022/adapter-data-service-odata/adapter-core.mjs +49 -0
- package/{esm5/adapter-data-service-odata/adapter-data-service-odata.js → esm2022/adapter-data-service-odata/adapter-data-service-odata.mjs} +138 -147
- package/esm2022/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +5 -0
- package/esm2022/adapter-data-service-webapi/adapter-data-service-webapi.mjs +100 -0
- package/esm2022/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +5 -0
- package/esm2022/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +269 -0
- package/esm2022/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +5 -0
- package/esm2022/adapter-model-library-ko/adapter-model-library-ko.mjs +241 -0
- package/esm2022/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +5 -0
- package/esm2022/adapter-uri-builder-json/adapter-core.mjs +49 -0
- package/esm2022/adapter-uri-builder-json/adapter-uri-builder-json.mjs +37 -0
- package/esm2022/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +5 -0
- package/esm2022/adapter-uri-builder-odata/adapter-core.mjs +49 -0
- package/esm2022/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +191 -0
- package/esm2022/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +5 -0
- package/esm2022/breeze-client.mjs +5 -0
- package/esm2022/index.mjs +2 -0
- package/esm2022/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +5 -0
- package/esm2022/mixin-get-entity-graph/mixin-get-entity-graph.mjs +269 -0
- package/esm2022/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +5 -0
- package/esm2022/mixin-save-queuing/mixin-save-queuing.mjs +421 -0
- package/esm2022/src/abstract-data-service-adapter.mjs +325 -0
- package/esm2022/src/array.mjs +4 -0
- package/esm2022/src/assert-param.mjs +330 -0
- package/esm2022/src/breeze.mjs +85 -0
- package/esm2022/src/complex-array.mjs +117 -0
- package/esm2022/src/config.mjs +232 -0
- package/esm2022/src/core.mjs +712 -0
- package/esm2022/src/csdl-metadata-parser.mjs +385 -0
- package/esm2022/src/data-service.mjs +221 -0
- package/esm2022/src/data-type.mjs +510 -0
- package/esm2022/src/default-property-interceptor.mjs +460 -0
- package/{esm2015/src/entity-action.js → esm2022/src/entity-action.mjs} +25 -25
- package/esm2022/src/entity-aspect.mjs +897 -0
- package/esm2022/src/entity-group.mjs +192 -0
- package/esm2022/src/entity-key.mjs +125 -0
- package/esm2022/src/entity-manager.mjs +2163 -0
- package/esm2022/src/entity-metadata.mjs +2242 -0
- package/esm2022/src/entity-query.mjs +1024 -0
- package/esm2022/src/entity-state.mjs +107 -0
- package/esm2022/src/enum.mjs +143 -0
- package/esm2022/src/event.mjs +264 -0
- package/esm2022/src/interface-registry.mjs +39 -0
- package/esm2022/src/key-generator.mjs +110 -0
- package/esm2022/src/local-query-comparison-options.mjs +65 -0
- package/esm2022/src/mapping-context.mjs +411 -0
- package/esm2022/src/naming-convention.mjs +92 -0
- package/esm2022/src/observable-array.mjs +183 -0
- package/esm2022/src/predicate.mjs +1259 -0
- package/esm2022/src/primitive-array.mjs +85 -0
- package/esm2022/src/query-options.mjs +152 -0
- package/esm2022/src/relation-array.mjs +173 -0
- package/esm2022/src/save-options.mjs +41 -0
- package/esm2022/src/unattached-children-map.mjs +56 -0
- package/esm2022/src/validate.mjs +995 -0
- package/esm2022/src/validation-options.mjs +64 -0
- package/{fesm2015/breeze-client-adapter-ajax-angularjs.js → fesm2022/breeze-client-adapter-ajax-angularjs.mjs} +6 -1
- package/fesm2022/breeze-client-adapter-ajax-angularjs.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-ajax-fetch.js → fesm2022/breeze-client-adapter-ajax-fetch.mjs} +9 -4
- package/fesm2022/breeze-client-adapter-ajax-fetch.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-ajax-httpclient.js → fesm2022/breeze-client-adapter-ajax-httpclient.mjs} +6 -4
- package/fesm2022/breeze-client-adapter-ajax-httpclient.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-ajax-jquery.js → fesm2022/breeze-client-adapter-ajax-jquery.mjs} +6 -2
- package/fesm2022/breeze-client-adapter-ajax-jquery.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-ajax-post.js → fesm2022/breeze-client-adapter-ajax-post.mjs} +1 -1
- package/fesm2022/breeze-client-adapter-ajax-post.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-data-service-odata.js → fesm2022/breeze-client-adapter-data-service-odata.mjs} +68 -69
- package/fesm2022/breeze-client-adapter-data-service-odata.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-data-service-webapi.js → fesm2022/breeze-client-adapter-data-service-webapi.mjs} +30 -30
- package/fesm2022/breeze-client-adapter-data-service-webapi.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-model-library-backing-store.js → fesm2022/breeze-client-adapter-model-library-backing-store.mjs} +14 -13
- package/fesm2022/breeze-client-adapter-model-library-backing-store.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-model-library-ko.js → fesm2022/breeze-client-adapter-model-library-ko.mjs} +14 -13
- package/fesm2022/breeze-client-adapter-model-library-ko.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-uri-builder-json.js → fesm2022/breeze-client-adapter-uri-builder-json.mjs} +9 -8
- package/fesm2022/breeze-client-adapter-uri-builder-json.mjs.map +1 -0
- package/{fesm2015/breeze-client-adapter-uri-builder-odata.js → fesm2022/breeze-client-adapter-uri-builder-odata.mjs} +86 -86
- package/fesm2022/breeze-client-adapter-uri-builder-odata.mjs.map +1 -0
- package/{fesm2015/breeze-client-mixin-get-entity-graph.js → fesm2022/breeze-client-mixin-get-entity-graph.mjs} +1 -1
- package/fesm2022/breeze-client-mixin-get-entity-graph.mjs.map +1 -0
- package/{fesm2015/breeze-client-mixin-save-queuing.js → fesm2022/breeze-client-mixin-save-queuing.mjs} +23 -2
- package/fesm2022/breeze-client-mixin-save-queuing.mjs.map +1 -0
- package/{fesm2015/breeze-client.js → fesm2022/breeze-client.mjs} +1933 -1538
- package/fesm2022/breeze-client.mjs.map +1 -0
- package/mixin-get-entity-graph/{breeze-client-mixin-get-entity-graph.d.ts → index.d.ts} +1 -0
- package/mixin-save-queuing/{breeze-client-mixin-save-queuing.d.ts → index.d.ts} +1 -0
- package/package.json +94 -12
- package/src/config.d.ts +1 -1
- package/src/core.d.ts +1 -1
- package/src/entity-aspect.d.ts +1 -1
- package/src/entity-metadata.d.ts +8 -6
- 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 -13
- package/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.metadata.json +0 -1
- package/adapter-ajax-jquery/package.json +0 -13
- package/adapter-ajax-post/breeze-client-adapter-ajax-post.metadata.json +0 -1
- package/adapter-ajax-post/package.json +0 -13
- package/adapter-data-service-odata/breeze-client-adapter-data-service-odata.metadata.json +0 -1
- package/adapter-data-service-odata/package.json +0 -13
- package/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.metadata.json +0 -1
- package/adapter-data-service-webapi/package.json +0 -13
- package/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.metadata.json +0 -1
- package/adapter-model-library-backing-store/package.json +0 -13
- package/adapter-model-library-ko/breeze-client-adapter-model-library-ko.metadata.json +0 -1
- package/adapter-model-library-ko/package.json +0 -13
- package/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.metadata.json +0 -1
- package/adapter-uri-builder-json/package.json +0 -13
- package/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.metadata.json +0 -1
- package/adapter-uri-builder-odata/package.json +0 -13
- package/breeze-client.d.ts +0 -8
- package/breeze-client.metadata.json +0 -1
- package/bundles/breeze-client-adapter-ajax-angularjs.umd.js +0 -190
- package/bundles/breeze-client-adapter-ajax-angularjs.umd.js.map +0 -1
- package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js +0 -2
- package/bundles/breeze-client-adapter-ajax-angularjs.umd.min.js.map +0 -1
- package/bundles/breeze-client-adapter-ajax-fetch.umd.js +0 -190
- package/bundles/breeze-client-adapter-ajax-fetch.umd.js.map +0 -1
- package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js +0 -2
- package/bundles/breeze-client-adapter-ajax-fetch.umd.min.js.map +0 -1
- package/bundles/breeze-client-adapter-ajax-httpclient.umd.js +0 -195
- package/bundles/breeze-client-adapter-ajax-httpclient.umd.js.map +0 -1
- package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js +0 -2
- package/bundles/breeze-client-adapter-ajax-httpclient.umd.min.js.map +0 -1
- package/bundles/breeze-client-adapter-ajax-jquery.umd.js +0 -115
- package/bundles/breeze-client-adapter-ajax-jquery.umd.js.map +0 -1
- package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js +0 -2
- package/bundles/breeze-client-adapter-ajax-jquery.umd.min.js.map +0 -1
- package/bundles/breeze-client-adapter-ajax-post.umd.js +0 -92
- package/bundles/breeze-client-adapter-ajax-post.umd.js.map +0 -1
- package/bundles/breeze-client-adapter-ajax-post.umd.min.js +0 -2
- package/bundles/breeze-client-adapter-ajax-post.umd.min.js.map +0 -1
- package/bundles/breeze-client-adapter-data-service-odata.umd.js +0 -747
- 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 -333
- 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 -14234
- 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 -463
- 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 -100
- package/esm2015/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +0 -5
- package/esm2015/adapter-model-library-backing-store/adapter-model-library-backing-store.js +0 -268
- package/esm2015/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +0 -5
- package/esm2015/adapter-model-library-ko/adapter-model-library-ko.js +0 -240
- package/esm2015/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +0 -5
- package/esm2015/adapter-uri-builder-json/adapter-core.js +0 -49
- package/esm2015/adapter-uri-builder-json/adapter-uri-builder-json.js +0 -36
- package/esm2015/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +0 -5
- package/esm2015/adapter-uri-builder-odata/adapter-core.js +0 -49
- package/esm2015/adapter-uri-builder-odata/adapter-uri-builder-odata.js +0 -192
- package/esm2015/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +0 -5
- package/esm2015/breeze-client.js +0 -9
- package/esm2015/index.js +0 -2
- package/esm2015/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +0 -5
- package/esm2015/mixin-get-entity-graph/mixin-get-entity-graph.js +0 -269
- package/esm2015/mixin-save-queuing/breeze-client-mixin-save-queuing.js +0 -5
- package/esm2015/mixin-save-queuing/mixin-save-queuing.js +0 -400
- package/esm2015/src/abstract-data-service-adapter.js +0 -327
- 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 -714
- package/esm2015/src/csdl-metadata-parser.js +0 -385
- package/esm2015/src/data-service.js +0 -203
- package/esm2015/src/data-type.js +0 -506
- package/esm2015/src/default-property-interceptor.js +0 -460
- package/esm2015/src/entity-aspect.js +0 -804
- 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 -1015
- package/esm2015/src/entity-state.js +0 -107
- 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 -411
- package/esm2015/src/naming-convention.js +0 -88
- package/esm2015/src/observable-array.js +0 -185
- package/esm2015/src/predicate.js +0 -1242
- 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/breeze-client-adapter-data-service-odata.js +0 -5
- package/esm5/adapter-data-service-webapi/adapter-data-service-webapi.js +0 -105
- package/esm5/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.js +0 -5
- package/esm5/adapter-model-library-backing-store/adapter-model-library-backing-store.js +0 -270
- package/esm5/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.js +0 -5
- package/esm5/adapter-model-library-ko/adapter-model-library-ko.js +0 -242
- package/esm5/adapter-model-library-ko/breeze-client-adapter-model-library-ko.js +0 -5
- package/esm5/adapter-uri-builder-json/adapter-core.js +0 -49
- package/esm5/adapter-uri-builder-json/adapter-uri-builder-json.js +0 -38
- package/esm5/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.js +0 -5
- package/esm5/adapter-uri-builder-odata/adapter-core.js +0 -49
- package/esm5/adapter-uri-builder-odata/adapter-uri-builder-odata.js +0 -197
- package/esm5/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.js +0 -5
- package/esm5/breeze-client.js +0 -9
- package/esm5/index.js +0 -2
- package/esm5/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.js +0 -5
- package/esm5/mixin-get-entity-graph/mixin-get-entity-graph.js +0 -269
- package/esm5/mixin-save-queuing/breeze-client-mixin-save-queuing.js +0 -5
- package/esm5/mixin-save-queuing/mixin-save-queuing.js +0 -412
- package/esm5/src/abstract-data-service-adapter.js +0 -333
- 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 -722
- package/esm5/src/csdl-metadata-parser.js +0 -385
- package/esm5/src/data-service.js +0 -207
- package/esm5/src/data-type.js +0 -513
- package/esm5/src/default-property-interceptor.js +0 -460
- package/esm5/src/entity-action.js +0 -52
- package/esm5/src/entity-aspect.js +0 -810
- 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 -1042
- package/esm5/src/entity-state.js +0 -114
- 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 -413
- package/esm5/src/naming-convention.js +0 -90
- package/esm5/src/observable-array.js +0 -201
- package/esm5/src/predicate.js +0 -1307
- 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 +0 -186
- package/fesm5/breeze-client-adapter-ajax-angularjs.js.map +0 -1
- package/fesm5/breeze-client-adapter-ajax-fetch.js +0 -186
- package/fesm5/breeze-client-adapter-ajax-fetch.js.map +0 -1
- package/fesm5/breeze-client-adapter-ajax-httpclient.js +0 -193
- package/fesm5/breeze-client-adapter-ajax-httpclient.js.map +0 -1
- package/fesm5/breeze-client-adapter-ajax-jquery.js +0 -111
- package/fesm5/breeze-client-adapter-ajax-jquery.js.map +0 -1
- package/fesm5/breeze-client-adapter-ajax-post.js +0 -86
- package/fesm5/breeze-client-adapter-ajax-post.js.map +0 -1
- package/fesm5/breeze-client-adapter-data-service-odata.js +0 -523
- package/fesm5/breeze-client-adapter-data-service-odata.js.map +0 -1
- package/fesm5/breeze-client-adapter-data-service-webapi.js +0 -111
- package/fesm5/breeze-client-adapter-data-service-webapi.js.map +0 -1
- package/fesm5/breeze-client-adapter-model-library-backing-store.js +0 -276
- package/fesm5/breeze-client-adapter-model-library-backing-store.js.map +0 -1
- package/fesm5/breeze-client-adapter-model-library-ko.js +0 -248
- package/fesm5/breeze-client-adapter-model-library-ko.js.map +0 -1
- package/fesm5/breeze-client-adapter-uri-builder-json.js +0 -92
- package/fesm5/breeze-client-adapter-uri-builder-json.js.map +0 -1
- package/fesm5/breeze-client-adapter-uri-builder-odata.js +0 -250
- package/fesm5/breeze-client-adapter-uri-builder-odata.js.map +0 -1
- package/fesm5/breeze-client-mixin-get-entity-graph.js +0 -254
- package/fesm5/breeze-client-mixin-get-entity-graph.js.map +0 -1
- package/fesm5/breeze-client-mixin-save-queuing.js +0 -356
- package/fesm5/breeze-client-mixin-save-queuing.js.map +0 -1
- package/fesm5/breeze-client.js +0 -13956
- 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
|
@@ -0,0 +1,897 @@
|
|
|
1
|
+
import { core } from './core';
|
|
2
|
+
import { config } from './config';
|
|
3
|
+
import { BreezeEvent } from './event';
|
|
4
|
+
import { assertParam } from './assert-param';
|
|
5
|
+
import { EntityState } from './entity-state';
|
|
6
|
+
import { EntityAction } from './entity-action';
|
|
7
|
+
import { EntityType } from './entity-metadata';
|
|
8
|
+
import { EntityKey } from './entity-key';
|
|
9
|
+
import { Validator, ValidationError } from './validate';
|
|
10
|
+
import { EntityQuery } from './entity-query';
|
|
11
|
+
/**
|
|
12
|
+
An EntityAspect instance is associated with every attached entity and is accessed via the entity's 'entityAspect' property.
|
|
13
|
+
|
|
14
|
+
The EntityAspect itself provides properties to determine and modify the EntityState of the entity and has methods
|
|
15
|
+
that provide a variety of services including validation and change tracking.
|
|
16
|
+
|
|
17
|
+
An EntityAspect will almost never need to be constructed directly. You will usually get an EntityAspect by accessing
|
|
18
|
+
an entities 'entityAspect' property. This property will be automatically attached when an entity is created via either
|
|
19
|
+
a query, import or [[EntityManager.createEntity]] call.
|
|
20
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
21
|
+
> var aspect = order.entityAspect;
|
|
22
|
+
> var currentState = aspect.entityState;
|
|
23
|
+
|
|
24
|
+
**/
|
|
25
|
+
export class EntityAspect {
|
|
26
|
+
/** The Entity that this aspect is associated with. __Read Only__ **/
|
|
27
|
+
entity;
|
|
28
|
+
/** The [[EntityManager]] that contains this entity. __Read Only__ **/
|
|
29
|
+
entityManager;
|
|
30
|
+
/** @hidden @internal */
|
|
31
|
+
entityGroup;
|
|
32
|
+
/** The [[EntityState]] of this entity. __Read Only__ **/
|
|
33
|
+
entityState;
|
|
34
|
+
/** Whether this entity is in the process of being saved. __Read Only__ */
|
|
35
|
+
isBeingSaved;
|
|
36
|
+
/** The 'original values' of this entity where they are different from the 'current values'.
|
|
37
|
+
This is a map where the key is a property name and the value is the 'original value' of the property. */
|
|
38
|
+
originalValues;
|
|
39
|
+
/** Whether this entity has any validation errors. __Read Only__ */
|
|
40
|
+
hasValidationErrors;
|
|
41
|
+
/** Whether this entity has a temporary [[EntityKey]]. */
|
|
42
|
+
hasTempKey;
|
|
43
|
+
/** Whether this entity was created by being loaded from the database */
|
|
44
|
+
wasLoaded;
|
|
45
|
+
/** Extra metadata about this entity such as the entity's etag.
|
|
46
|
+
You may extend this object with your own metadata information.
|
|
47
|
+
Breeze (de)serializes this object when importing/exporting the entity. **/
|
|
48
|
+
extraMetadata;
|
|
49
|
+
/**
|
|
50
|
+
A [[BreezeEvent]] that fires whenever any of the validation errors on this entity change.
|
|
51
|
+
Note that this might be the removal of an error when some data on the entity is fixed.
|
|
52
|
+
@eventArgs -
|
|
53
|
+
- entity - The entity on which the validation errors are being added or removed.
|
|
54
|
+
- added - An array containing any newly added [[ValidationError]]s
|
|
55
|
+
- removed - An array containing any newly removed [[ValidationError]]s. This is those
|
|
56
|
+
errors that have been 'fixed'.
|
|
57
|
+
|
|
58
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
59
|
+
> order.entityAspect.validationErrorsChanged.subscribe(
|
|
60
|
+
> function (validationChangeArgs) {
|
|
61
|
+
> // this code will be executed anytime a property value changes on the 'order' entity.
|
|
62
|
+
> var entity == validationChangeArgs.entity; // Note: entity === order
|
|
63
|
+
> var errorsAdded = validationChangeArgs.added;
|
|
64
|
+
> var errorsCleared = validationChangeArgs.removed;
|
|
65
|
+
> });
|
|
66
|
+
@event
|
|
67
|
+
**/
|
|
68
|
+
validationErrorsChanged;
|
|
69
|
+
/**
|
|
70
|
+
A [[BreezeEvent]] that fires whenever a value of one of this entity's properties change.
|
|
71
|
+
@eventArgs -
|
|
72
|
+
- entity - The entity whose property has changed.
|
|
73
|
+
- property - The [[DataProperty]] that changed.
|
|
74
|
+
- propertyName - The name of the property that changed. This value will be 'null' for operations that replace the entire entity. This includes
|
|
75
|
+
queries, imports and saves that require a merge. The remaining parameters will not exist in this case either. This will actually be a "property path"
|
|
76
|
+
for any properties of a complex type.
|
|
77
|
+
- oldValue - The old value of this property before the change.
|
|
78
|
+
- newValue - The new value of this property after the change.
|
|
79
|
+
- parent - The immediate parent object for the changed property. This will be a ComplexType instance as opposed to an Entity
|
|
80
|
+
for any complex type or nested complex type properties.
|
|
81
|
+
|
|
82
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
83
|
+
> order.entityAspect.propertyChanged.subscribe(
|
|
84
|
+
> function (propertyChangedArgs) {
|
|
85
|
+
> // this code will be executed anytime a property value changes on the 'order' entity.
|
|
86
|
+
> var entity = propertyChangedArgs.entity; // Note: entity === order
|
|
87
|
+
> var propertyNameChanged = propertyChangedArgs.propertyName;
|
|
88
|
+
> var oldValue = propertyChangedArgs.oldValue;
|
|
89
|
+
> var newValue = propertyChangedArgs.newValue;
|
|
90
|
+
> });
|
|
91
|
+
@event
|
|
92
|
+
**/
|
|
93
|
+
propertyChanged;
|
|
94
|
+
/** @hidden @internal */
|
|
95
|
+
_validationErrors;
|
|
96
|
+
/** @hidden @internal */
|
|
97
|
+
_pendingValidationResult;
|
|
98
|
+
/** @hidden @internal */
|
|
99
|
+
_entityKey;
|
|
100
|
+
/** @hidden @internal */
|
|
101
|
+
_loadedNps;
|
|
102
|
+
/** @hidden @internal */
|
|
103
|
+
_initialized;
|
|
104
|
+
/** @hidden @internal */
|
|
105
|
+
_inProcess; // used in defaultPropertyInterceptor for temp storage.
|
|
106
|
+
/** @hidden @internal */
|
|
107
|
+
_inProcessEntity; // used in EntityManager
|
|
108
|
+
/** @hidden @internal */
|
|
109
|
+
static _nullInstance = new EntityAspect(); // TODO: determine if this works
|
|
110
|
+
/** @hidden @internal */
|
|
111
|
+
constructor(entity) {
|
|
112
|
+
// if called without new
|
|
113
|
+
// if (!(this instanceof EntityAspect)) {
|
|
114
|
+
// return new EntityAspect(entity);
|
|
115
|
+
// }
|
|
116
|
+
this.entity = entity;
|
|
117
|
+
// TODO: keep public or not?
|
|
118
|
+
this.entityGroup = undefined;
|
|
119
|
+
this.entityManager = undefined;
|
|
120
|
+
this.entityState = EntityState.Detached;
|
|
121
|
+
this.isBeingSaved = false;
|
|
122
|
+
this.originalValues = {};
|
|
123
|
+
this.hasValidationErrors = false;
|
|
124
|
+
this._validationErrors = {};
|
|
125
|
+
// Uncomment when we implement entityAspect.isNavigationPropertyLoaded method
|
|
126
|
+
// this._loadedNavPropMap = {};
|
|
127
|
+
this.validationErrorsChanged = new BreezeEvent("validationErrorsChanged", this);
|
|
128
|
+
this.propertyChanged = new BreezeEvent("propertyChanged", this);
|
|
129
|
+
// in case this is the NULL entityAspect. - used with ComplexAspects that have no parent.
|
|
130
|
+
if (entity != null) {
|
|
131
|
+
// remove properties that should be on prototype but placed on instance by Babel
|
|
132
|
+
if (entity.hasOwnProperty('entityType')) {
|
|
133
|
+
// throw new Error("Entity instance has entityType property; should only be on prototype");
|
|
134
|
+
delete (entity.entityType);
|
|
135
|
+
}
|
|
136
|
+
entity.entityAspect = this;
|
|
137
|
+
// entityType should already be on the entity from 'watch'
|
|
138
|
+
let entityType = entity.entityType || entity._$entityType;
|
|
139
|
+
if (!entityType) {
|
|
140
|
+
let typeName = entity.prototype._$typeName;
|
|
141
|
+
if (!typeName) {
|
|
142
|
+
throw new Error("This entity is not registered as a valid EntityType");
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
throw new Error("Metadata for this entityType has not yet been resolved: " + typeName);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
let entityCtor = entityType.getCtor();
|
|
149
|
+
config.interfaceRegistry.modelLibrary.getDefaultInstance().startTracking(entity, entityCtor.prototype);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** @hidden */
|
|
153
|
+
// type-guard
|
|
154
|
+
static isEntity(obj) {
|
|
155
|
+
return obj.entityAspect != null;
|
|
156
|
+
}
|
|
157
|
+
// No longer used
|
|
158
|
+
// static createFrom(entity: Entity): EntityAspect {
|
|
159
|
+
// if (entity == null) {
|
|
160
|
+
// return EntityAspect._nullInstance;
|
|
161
|
+
// } else if (entity.entityAspect) {
|
|
162
|
+
// return entity.entityAspect;
|
|
163
|
+
// }
|
|
164
|
+
// return new EntityAspect(entity);
|
|
165
|
+
// }
|
|
166
|
+
// TODO: refactor this and the instance getPropertyValue method.
|
|
167
|
+
/**
|
|
168
|
+
Returns the value of a specified 'property path' for a specified entity.
|
|
169
|
+
|
|
170
|
+
The propertyPath can be either a string delimited with '.' or a string array.
|
|
171
|
+
**/
|
|
172
|
+
// used by EntityQuery and Predicate
|
|
173
|
+
static getPropertyPathValue(obj, propertyPath) {
|
|
174
|
+
let properties = Array.isArray(propertyPath) ? propertyPath : propertyPath.split(".");
|
|
175
|
+
if (properties.length === 1) {
|
|
176
|
+
return obj.getProperty(propertyPath);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
let nextValue = obj;
|
|
180
|
+
// hack use of some to perform mapFirst operation.
|
|
181
|
+
properties.some((prop) => {
|
|
182
|
+
nextValue = nextValue.getProperty(prop);
|
|
183
|
+
return nextValue == null;
|
|
184
|
+
});
|
|
185
|
+
return nextValue;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
Returns the [[EntityKey]] for this Entity.
|
|
190
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
191
|
+
> var entityKey = order.entityAspect.getKey();
|
|
192
|
+
@param forceRefresh - (boolean=false) Forces the recalculation of the key. This should normally be unnecessary.
|
|
193
|
+
@return The [[EntityKey]] associated with this Entity.
|
|
194
|
+
**/
|
|
195
|
+
getKey(forceRefresh = false) {
|
|
196
|
+
forceRefresh = assertParam(forceRefresh, "forceRefresh").isBoolean().isOptional().check(false);
|
|
197
|
+
if (forceRefresh || !this._entityKey) {
|
|
198
|
+
let entityType = this.entity.entityType;
|
|
199
|
+
let keyProps = entityType.keyProperties;
|
|
200
|
+
let values = keyProps.map(function (p) {
|
|
201
|
+
return this.entity.getProperty(p.name);
|
|
202
|
+
}, this);
|
|
203
|
+
this._entityKey = new EntityKey(entityType, values);
|
|
204
|
+
}
|
|
205
|
+
return this._entityKey;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
Returns the entity to an [[EntityState]] of 'Unchanged' by committing all changes made since the entity was last queried
|
|
209
|
+
had 'acceptChanges' called on it.
|
|
210
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
211
|
+
> order.entityAspect.acceptChanges();
|
|
212
|
+
> // The 'order' entity will now be in an 'Unchanged' state with any changes committed.
|
|
213
|
+
**/
|
|
214
|
+
acceptChanges() {
|
|
215
|
+
if (!this.entity)
|
|
216
|
+
return;
|
|
217
|
+
this._checkOperation("acceptChanges");
|
|
218
|
+
let em = this.entityManager;
|
|
219
|
+
if (this.entityState.isDeleted()) {
|
|
220
|
+
em.detachEntity(this.entity);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
this.setUnchanged();
|
|
224
|
+
}
|
|
225
|
+
em.entityChanged.publish({ entityAction: EntityAction.AcceptChanges, entity: this.entity });
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
Returns the entity to an [[EntityState]] of 'Unchanged' by rejecting all changes made to it since the entity was last queried
|
|
229
|
+
had 'rejectChanges' called on it.
|
|
230
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
231
|
+
> order.entityAspect.rejectChanges();
|
|
232
|
+
> // The 'order' entity will now be in an 'Unchanged' state with any changes rejected.
|
|
233
|
+
**/
|
|
234
|
+
rejectChanges() {
|
|
235
|
+
this._checkOperation("rejectChanges");
|
|
236
|
+
let entity = this.entity;
|
|
237
|
+
let entityManager = this.entityManager;
|
|
238
|
+
// we do not want PropertyChange or EntityChange events to occur here
|
|
239
|
+
core.using(entityManager, "isRejectingChanges", true, function () {
|
|
240
|
+
rejectChangesCore(entity);
|
|
241
|
+
});
|
|
242
|
+
if (this.entityState.isAdded()) {
|
|
243
|
+
// next line is needed because the following line will cause this.entityManager -> null;
|
|
244
|
+
entityManager.detachEntity(entity);
|
|
245
|
+
// need to tell em that an entity that needed to be saved no longer does.
|
|
246
|
+
entityManager._notifyStateChange(entity, false);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
if (this.entityState.isDeleted()) {
|
|
250
|
+
entityManager._linkRelatedEntities(entity);
|
|
251
|
+
}
|
|
252
|
+
this.setUnchanged();
|
|
253
|
+
// propertyChanged propertyName is not specified because more than one property may have changed.
|
|
254
|
+
this.propertyChanged.publish({ entity: entity, propertyName: null });
|
|
255
|
+
entityManager.entityChanged.publish({ entityAction: EntityAction.RejectChanges, entity: entity });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/** @hidden @internal */
|
|
259
|
+
// TODO: rename - and use '_'; used on both EntityAspect and ComplexAspect for polymorphic reasons.
|
|
260
|
+
getPropertyPath(propName) {
|
|
261
|
+
return propName;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
Sets the entity to an EntityState of 'Added'. This is NOT the equivalent of calling [[EntityManager.addEntity]]
|
|
265
|
+
because no key generation will occur for autogenerated keys as a result of this operation. As a result this operation can be problematic
|
|
266
|
+
unless you are certain that the entity being marked 'Added' does not already exist in the database and does not have an autogenerated key.
|
|
267
|
+
The same operation can be performed by calling [[EntityAspect.setEntityState]].
|
|
268
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
269
|
+
> order.entityAspect.setAdded();
|
|
270
|
+
> // The 'order' entity will now be in an 'Added' state.
|
|
271
|
+
**/
|
|
272
|
+
setAdded() {
|
|
273
|
+
return this.setEntityState(EntityState.Added);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
Sets the entity to an EntityState of 'Unchanged'. This is also the equivalent of calling [[EntityAspect.acceptChanges]].
|
|
277
|
+
The same operation can be performed by calling [[EntityAspect.setEntityState]].
|
|
278
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
279
|
+
> order.entityAspect.setUnchanged();
|
|
280
|
+
> // The 'order' entity will now be in an 'Unchanged' state with any changes committed.
|
|
281
|
+
**/
|
|
282
|
+
setUnchanged = function () {
|
|
283
|
+
return this.setEntityState(EntityState.Unchanged);
|
|
284
|
+
};
|
|
285
|
+
/**
|
|
286
|
+
Sets the entity to an EntityState of 'Modified'. This can also be achieved by changing the value of any property on an 'Unchanged' entity.
|
|
287
|
+
The same operation can be performed by calling [[EntityAspect.setEntityState]].
|
|
288
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
289
|
+
> order.entityAspect.setModified();
|
|
290
|
+
> // The 'order' entity will now be in a 'Modified' state.
|
|
291
|
+
**/
|
|
292
|
+
setModified = function () {
|
|
293
|
+
return this.setEntityState(EntityState.Modified);
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
Sets the entity to an EntityState of 'Deleted'. This both marks the entity as being scheduled for deletion during the next 'Save' call
|
|
297
|
+
but also removes the entity from all of its related entities. If the current entityState is 'Added', then `setDeleted()` will mark it 'Detached'
|
|
298
|
+
The same operation can be performed by calling [[EntityAspect.setEntityState]].
|
|
299
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
300
|
+
> order.entityAspect.setDeleted();
|
|
301
|
+
> // The 'order' entity will now be in a 'Deleted' state and it will no longer have any 'related' entities.
|
|
302
|
+
**/
|
|
303
|
+
setDeleted = function () {
|
|
304
|
+
return this.setEntityState(EntityState.Deleted);
|
|
305
|
+
};
|
|
306
|
+
/**
|
|
307
|
+
Sets the entity to an EntityState of 'Detached'. This removes the entity from all of its related entities, but does NOT change the EntityState of any existing entities.
|
|
308
|
+
The same operation can be performed by calling [[EntityAspect.setEntityState]].
|
|
309
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
310
|
+
> order.entityAspect.setDetached();
|
|
311
|
+
> // The 'order' entity will now be in a 'Detached' state and it will no longer have any 'related' entities.
|
|
312
|
+
**/
|
|
313
|
+
setDetached = function () {
|
|
314
|
+
return this.setEntityState(EntityState.Detached);
|
|
315
|
+
};
|
|
316
|
+
/**
|
|
317
|
+
Sets the entity to the specified EntityState. See also 'setUnchanged', 'setModified', 'setDetached', etc.
|
|
318
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
319
|
+
> order.entityAspect.setEntityState(EntityState.Unchanged);
|
|
320
|
+
> // The 'order' entity will now be in a 'Unchanged' state.
|
|
321
|
+
**/
|
|
322
|
+
setEntityState(entityState) {
|
|
323
|
+
if (this.entityState === entityState)
|
|
324
|
+
return false;
|
|
325
|
+
this._checkOperation("setEntityState");
|
|
326
|
+
if (this.entityState.isDetached()) {
|
|
327
|
+
throw new Error("You cannot set the 'entityState' of an entity when it is detached - except by first attaching it to an EntityManager");
|
|
328
|
+
}
|
|
329
|
+
let entity = this.entity;
|
|
330
|
+
let em = this.entityManager;
|
|
331
|
+
let needsSave = true;
|
|
332
|
+
if (entityState === EntityState.Unchanged) {
|
|
333
|
+
clearOriginalValues(entity);
|
|
334
|
+
delete this.hasTempKey;
|
|
335
|
+
needsSave = false;
|
|
336
|
+
}
|
|
337
|
+
else if (entityState === EntityState.Added) {
|
|
338
|
+
clearOriginalValues(entity);
|
|
339
|
+
// TODO: more to do here... like regenerating key ???
|
|
340
|
+
}
|
|
341
|
+
else if (entityState === EntityState.Deleted) {
|
|
342
|
+
if (this.entityState.isAdded()) {
|
|
343
|
+
// turn it into a detach and exit early
|
|
344
|
+
this.setEntityState(EntityState.Detached);
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
// TODO: think about cascade deletes
|
|
349
|
+
// entityState needs to be set it early in this one case to insure that fk's are not cleared.
|
|
350
|
+
this.entityState = EntityState.Deleted;
|
|
351
|
+
removeFromRelations(entity, EntityState.Deleted);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else if (entityState === EntityState.Modified) {
|
|
355
|
+
// nothing extra needed
|
|
356
|
+
}
|
|
357
|
+
else if (entityState === EntityState.Detached) {
|
|
358
|
+
let group = this.entityGroup;
|
|
359
|
+
// no group === already detached.
|
|
360
|
+
if (!group)
|
|
361
|
+
return false;
|
|
362
|
+
group.detachEntity(entity);
|
|
363
|
+
// needs to occur early here - so this IS deliberately redundent with the same code later in this method.
|
|
364
|
+
this.entityState = entityState;
|
|
365
|
+
removeFromRelations(entity, EntityState.Detached);
|
|
366
|
+
this._detach();
|
|
367
|
+
em.entityChanged.publish({ entityAction: EntityAction.Detach, entity: entity });
|
|
368
|
+
needsSave = false;
|
|
369
|
+
}
|
|
370
|
+
this.entityState = entityState;
|
|
371
|
+
em._notifyStateChange(entity, needsSave);
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
Performs a query for the value of a specified [[NavigationProperty]]. __Async__
|
|
376
|
+
> emp.entityAspect.loadNavigationProperty("Orders").then(function (data) {
|
|
377
|
+
> var orders = data.results;
|
|
378
|
+
> }).catch(function (exception) {
|
|
379
|
+
> // handle exception here;
|
|
380
|
+
> });
|
|
381
|
+
@param navigationProperty - The NavigationProperty or the name of the NavigationProperty to 'load'.
|
|
382
|
+
@param callback - Function to call on success.
|
|
383
|
+
@param errorCallback - Function to call on failure.
|
|
384
|
+
@return Promise with shape
|
|
385
|
+
- results {Array of Entity}
|
|
386
|
+
- query {EntityQuery} The original query
|
|
387
|
+
- httpResponse {httpResponse} The HttpResponse returned from the server.
|
|
388
|
+
**/
|
|
389
|
+
loadNavigationProperty(navigationProperty, callback, errorCallback) {
|
|
390
|
+
let entity = this.entity;
|
|
391
|
+
let navProperty = entity.entityType._checkNavProperty(navigationProperty);
|
|
392
|
+
let query = EntityQuery.fromEntityNavigation(entity, navProperty);
|
|
393
|
+
// return entity.entityAspect.entityManager.executeQuery(query, callback, errorCallback);
|
|
394
|
+
let promise = entity.entityAspect.entityManager.executeQuery(query);
|
|
395
|
+
return promise.then((data) => {
|
|
396
|
+
this._markAsLoaded(navProperty.name);
|
|
397
|
+
if (callback)
|
|
398
|
+
callback(data);
|
|
399
|
+
return Promise.resolve(data);
|
|
400
|
+
}, (error) => {
|
|
401
|
+
if (errorCallback)
|
|
402
|
+
errorCallback(error);
|
|
403
|
+
return Promise.reject(error);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
Marks this navigationProperty on this entity as already having been loaded.
|
|
408
|
+
> emp.entityAspect.markNavigationPropertyAsLoaded("Orders");
|
|
409
|
+
@param navigationProperty - The NavigationProperty or name of NavigationProperty to 'load'.
|
|
410
|
+
**/
|
|
411
|
+
markNavigationPropertyAsLoaded(navigationProperty) {
|
|
412
|
+
if (!this.entity)
|
|
413
|
+
return;
|
|
414
|
+
let navProperty = this.entity.entityType._checkNavProperty(navigationProperty);
|
|
415
|
+
this._markAsLoaded(navProperty.name);
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
Determines whether a navigationProperty on this entity has already been loaded.
|
|
419
|
+
|
|
420
|
+
A navigation property is considered loaded when any of the following three conditions applies:
|
|
421
|
+
|
|
422
|
+
1. It was fetched from the backend server.
|
|
423
|
+
<br/> This can be the result of an expand query or a call to the [[EntityAspect.loadNavigationProperty]] method.
|
|
424
|
+
<br/> Note that even if the fetch returns nothing the property is still marked as loaded in this case.
|
|
425
|
+
1. The property is scalar and has been set to a nonnull value.
|
|
426
|
+
1. The [[EntityAspect.markNavigationPropertyAsLoaded]] was called.
|
|
427
|
+
|
|
428
|
+
> var wasLoaded = emp.entityAspect.isNavigationPropertyLoaded("Orders");
|
|
429
|
+
@param navigationProperty - The NavigationProperty or name of NavigationProperty to 'load'.
|
|
430
|
+
**/
|
|
431
|
+
isNavigationPropertyLoaded(navigationProperty) {
|
|
432
|
+
if (!this.entity)
|
|
433
|
+
return;
|
|
434
|
+
let navProperty = this.entity.entityType._checkNavProperty(navigationProperty);
|
|
435
|
+
if (navProperty.isScalar && this.entity.getProperty(navProperty.name) != null) {
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
return this._loadedNps && this._loadedNps.indexOf(navProperty.name) >= 0;
|
|
439
|
+
}
|
|
440
|
+
/** @hidden @internal */
|
|
441
|
+
_markAsLoaded(navPropName) {
|
|
442
|
+
this._loadedNps = this._loadedNps || [];
|
|
443
|
+
core.arrayAddItemUnique(this._loadedNps, navPropName);
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
Performs validation on the entity, any errors encountered during the validation are available via the
|
|
447
|
+
[[EntityAspect.getValidationErrors]] method. Validating an entity means executing
|
|
448
|
+
all of the validators on both the entity itself as well as those on each of its properties.
|
|
449
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
450
|
+
> var isOk = order.entityAspect.validateEntity();
|
|
451
|
+
> // isOk will be 'true' if there are no errors on the entity.
|
|
452
|
+
> if (!isOk) {
|
|
453
|
+
> var errors = order.entityAspect.getValidationErrors();
|
|
454
|
+
> }
|
|
455
|
+
@return Whether the entity passed validation.
|
|
456
|
+
**/
|
|
457
|
+
validateEntity() {
|
|
458
|
+
let ok = true;
|
|
459
|
+
this._processValidationOpAndPublish(function (that) {
|
|
460
|
+
ok = validateTarget(that.entity);
|
|
461
|
+
});
|
|
462
|
+
return ok;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
Performs validation on a specific property of this entity, any errors encountered during the validation are available via the
|
|
466
|
+
[[EntityAspect.getValidationErrors]] method. Validating a property means executing
|
|
467
|
+
all of the validators on the specified property. This call is also made automatically anytime a property
|
|
468
|
+
of an entity is changed.
|
|
469
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
470
|
+
> var isOk = order.entityAspect.validateProperty("Order");
|
|
471
|
+
|
|
472
|
+
or
|
|
473
|
+
> var orderDateProperty = order.entityType.getProperty("OrderDate");
|
|
474
|
+
> var isOk = order.entityAspect.validateProperty(OrderDateProperty);
|
|
475
|
+
@param property - The [[DataProperty]] or [[NavigationProperty]] to validate or a string
|
|
476
|
+
with the name of the property or a property path with the path to a property of a complex object.
|
|
477
|
+
@param context - A context object used to pass additional information to each [[Validator]].
|
|
478
|
+
@return Whether the entity passed validation.
|
|
479
|
+
**/
|
|
480
|
+
validateProperty(property, context) {
|
|
481
|
+
let value = this.getPropertyValue(property); // performs validations
|
|
482
|
+
if (value && value.complexAspect) {
|
|
483
|
+
return validateTarget(value);
|
|
484
|
+
}
|
|
485
|
+
context = context || {};
|
|
486
|
+
context.entity = this.entity;
|
|
487
|
+
if (typeof property === "string") {
|
|
488
|
+
context.property = this.entity.entityType.getProperty(property, true);
|
|
489
|
+
context.propertyName = property;
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
context.property = property;
|
|
493
|
+
context.propertyName = property.name;
|
|
494
|
+
}
|
|
495
|
+
return this._validateProperty(value, context);
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
Returns the validation errors associated with either the entire entity or any specified property.
|
|
499
|
+
|
|
500
|
+
This method can return all of the errors for an Entity
|
|
501
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
502
|
+
> var valErrors = order.entityAspect.getValidationErrors();
|
|
503
|
+
|
|
504
|
+
as well as those for just a specific property.
|
|
505
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
506
|
+
> var orderDateErrors = order.entityAspect.getValidationErrors("OrderDate");
|
|
507
|
+
|
|
508
|
+
which can also be expressed as
|
|
509
|
+
> // assume order is an order entity attached to an EntityManager.
|
|
510
|
+
> var orderDateProperty = order.entityType.getProperty("OrderDate");
|
|
511
|
+
> var orderDateErrors = order.entityAspect.getValidationErrors(orderDateProperty);
|
|
512
|
+
@param property - The property for which validation errors should be retrieved.
|
|
513
|
+
If omitted, all of the validation errors for this entity will be returned.
|
|
514
|
+
@return A array of validation errors.
|
|
515
|
+
**/
|
|
516
|
+
getValidationErrors(property) {
|
|
517
|
+
assertParam(property, "property").isOptional().isEntityProperty().or().isString().check();
|
|
518
|
+
let result = core.getOwnPropertyValues(this._validationErrors);
|
|
519
|
+
if (property) {
|
|
520
|
+
let propertyName = typeof (property) === 'string' ? property : property.name;
|
|
521
|
+
result = result.filter(function (ve) {
|
|
522
|
+
return ve.property && (ve.property.name === propertyName || (propertyName.indexOf(".") !== -1 && ve.propertyName === propertyName));
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
return result;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
Adds a validation error.
|
|
529
|
+
**/
|
|
530
|
+
addValidationError(validationError) {
|
|
531
|
+
assertParam(validationError, "validationError").isInstanceOf(ValidationError).check();
|
|
532
|
+
this._processValidationOpAndPublish(function (that) {
|
|
533
|
+
that._addValidationError(validationError);
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
Removes a validation error.
|
|
538
|
+
@param validationErrorOrKey - Either a ValidationError or a ValidationError 'key' value
|
|
539
|
+
**/
|
|
540
|
+
removeValidationError(validationErrorOrKey) {
|
|
541
|
+
assertParam(validationErrorOrKey, "validationErrorOrKey").isString().or().isInstanceOf(ValidationError).or().isInstanceOf(Validator).check();
|
|
542
|
+
let key = (typeof (validationErrorOrKey) === "string") ? validationErrorOrKey : validationErrorOrKey.key;
|
|
543
|
+
this._processValidationOpAndPublish(function (that) {
|
|
544
|
+
that._removeValidationError(key);
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
Removes all of the validation errors for a specified entity
|
|
549
|
+
**/
|
|
550
|
+
clearValidationErrors() {
|
|
551
|
+
this._processValidationOpAndPublish(function (that) {
|
|
552
|
+
core.objectForEach(that._validationErrors, function (key, valError) {
|
|
553
|
+
if (valError) {
|
|
554
|
+
delete that._validationErrors[key];
|
|
555
|
+
that._pendingValidationResult.removed.push(valError);
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
that.hasValidationErrors = !core.isEmpty(that._validationErrors);
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
Returns an [[EntityKey]] for the entity pointed to by the specified scalar NavigationProperty.
|
|
563
|
+
This only returns an EntityKey if the current entity is a 'child' entity along the specified NavigationProperty.
|
|
564
|
+
i.e. has a single parent.
|
|
565
|
+
|
|
566
|
+
@param navigationProperty - The [[NavigationProperty]] ( pointing to a parent).
|
|
567
|
+
@returns Either a parent EntityKey if this is a 'child' entity or null;
|
|
568
|
+
*/
|
|
569
|
+
getParentKey(navigationProperty) {
|
|
570
|
+
if (!this.entity)
|
|
571
|
+
return null;
|
|
572
|
+
// TODO: review this - not sure about the comment.
|
|
573
|
+
// NavigationProperty doesn't yet exist
|
|
574
|
+
// assertParam(navigationProperty, "navigationProperty").isInstanceOf(NavigationProperty).check();
|
|
575
|
+
let fkNames = navigationProperty.foreignKeyNames;
|
|
576
|
+
if (fkNames.length === 0)
|
|
577
|
+
return null;
|
|
578
|
+
let that = this;
|
|
579
|
+
let fkValues = fkNames.map(function (fkn) {
|
|
580
|
+
return that.entity.getProperty(fkn);
|
|
581
|
+
});
|
|
582
|
+
return new EntityKey(navigationProperty.entityType, fkValues);
|
|
583
|
+
}
|
|
584
|
+
// TODO: refactor this and the static getPropertyPathValue.
|
|
585
|
+
/**
|
|
586
|
+
Returns the value of a specified DataProperty or NavigationProperty or 'property path'.
|
|
587
|
+
**/
|
|
588
|
+
getPropertyValue(property) {
|
|
589
|
+
assertParam(property, "property").isString().or().isEntityProperty().check();
|
|
590
|
+
let value;
|
|
591
|
+
if (typeof (property) === 'string') {
|
|
592
|
+
let propNames = property.trim().split(".");
|
|
593
|
+
let propName = propNames.shift();
|
|
594
|
+
value = this.entity;
|
|
595
|
+
value = value.getProperty(propName);
|
|
596
|
+
while (propNames.length > 0) {
|
|
597
|
+
propName = propNames.shift();
|
|
598
|
+
value = value.getProperty(propName);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
if (!(property.parentType instanceof EntityType)) {
|
|
603
|
+
throw new Error("The validateProperty method does not accept a 'property' parameter whose parentType is a ComplexType; " +
|
|
604
|
+
"Pass a 'property path' string as the 'property' parameter instead ");
|
|
605
|
+
}
|
|
606
|
+
value = this.entity.getProperty(property.name);
|
|
607
|
+
}
|
|
608
|
+
return value;
|
|
609
|
+
}
|
|
610
|
+
// internal methods
|
|
611
|
+
/** @hidden @internal */
|
|
612
|
+
_checkOperation(operationName) {
|
|
613
|
+
if (this.isBeingSaved) {
|
|
614
|
+
throw new Error("Cannot perform a '" + operationName + "' on an entity that is in the process of being saved");
|
|
615
|
+
}
|
|
616
|
+
// allows chaining
|
|
617
|
+
return this;
|
|
618
|
+
}
|
|
619
|
+
/** @hidden @internal */
|
|
620
|
+
_detach() {
|
|
621
|
+
this.entityGroup = undefined;
|
|
622
|
+
this.entityManager = undefined;
|
|
623
|
+
this.entityState = EntityState.Detached;
|
|
624
|
+
this.originalValues = {};
|
|
625
|
+
this._validationErrors = {};
|
|
626
|
+
this.hasValidationErrors = false;
|
|
627
|
+
this.validationErrorsChanged.clear();
|
|
628
|
+
this.propertyChanged.clear();
|
|
629
|
+
}
|
|
630
|
+
// called from defaultInterceptor.
|
|
631
|
+
/** @hidden @internal */
|
|
632
|
+
_validateProperty(value, context) {
|
|
633
|
+
let ok = true;
|
|
634
|
+
this._processValidationOpAndPublish(function (that) {
|
|
635
|
+
context.property.getAllValidators().forEach(function (validator) {
|
|
636
|
+
ok = validate(that, validator, value, context) && ok;
|
|
637
|
+
});
|
|
638
|
+
});
|
|
639
|
+
return ok;
|
|
640
|
+
}
|
|
641
|
+
/** @hidden @internal */
|
|
642
|
+
_processValidationOpAndPublish(validationFn) {
|
|
643
|
+
if (this._pendingValidationResult) {
|
|
644
|
+
// only top level processValidations call publishes
|
|
645
|
+
validationFn(this);
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
try {
|
|
649
|
+
this._pendingValidationResult = { entity: this.entity, added: [], removed: [] };
|
|
650
|
+
validationFn(this);
|
|
651
|
+
if (this._pendingValidationResult.added.length > 0 || this._pendingValidationResult.removed.length > 0) {
|
|
652
|
+
this.validationErrorsChanged.publish(this._pendingValidationResult);
|
|
653
|
+
// this might be a detached entity hence the guard below.
|
|
654
|
+
this.entityManager && this.entityManager.validationErrorsChanged.publish(this._pendingValidationResult);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
finally {
|
|
658
|
+
this._pendingValidationResult = undefined;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
/** @hidden @internal */
|
|
663
|
+
// TODO: add/use a ValidationError type
|
|
664
|
+
_addValidationError(validationError) {
|
|
665
|
+
this._validationErrors[validationError.key] = validationError;
|
|
666
|
+
this.hasValidationErrors = true;
|
|
667
|
+
this._pendingValidationResult.added.push(validationError);
|
|
668
|
+
}
|
|
669
|
+
/** @hidden @internal */
|
|
670
|
+
_removeValidationError(key) {
|
|
671
|
+
let valError = this._validationErrors[key];
|
|
672
|
+
if (valError) {
|
|
673
|
+
delete this._validationErrors[key];
|
|
674
|
+
this.hasValidationErrors = !core.isEmpty(this._validationErrors);
|
|
675
|
+
this._pendingValidationResult.removed.push(valError);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
BreezeEvent.bubbleEvent(EntityAspect.prototype, function () {
|
|
680
|
+
return this.entityManager;
|
|
681
|
+
});
|
|
682
|
+
function rejectChangesCore(target) {
|
|
683
|
+
let aspect = target.entityAspect || target.complexAspect;
|
|
684
|
+
let stype = target.entityType || target.complexType;
|
|
685
|
+
let originalValues = aspect.originalValues;
|
|
686
|
+
for (let propName in originalValues) {
|
|
687
|
+
target.setProperty(propName, originalValues[propName]);
|
|
688
|
+
}
|
|
689
|
+
stype.complexProperties.forEach(function (cp) {
|
|
690
|
+
let cos = target.getProperty(cp.name);
|
|
691
|
+
if (cp.isScalar) {
|
|
692
|
+
rejectChangesCore(cos);
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
cos._rejectChanges();
|
|
696
|
+
cos.forEach(rejectChangesCore);
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
function removeFromRelations(entity, entityState) {
|
|
701
|
+
// remove this entity from any collections.
|
|
702
|
+
// mark the entity deleted or detached
|
|
703
|
+
let isDeleted = entityState.isDeleted();
|
|
704
|
+
if (isDeleted) {
|
|
705
|
+
removeFromRelationsCore(entity);
|
|
706
|
+
}
|
|
707
|
+
else {
|
|
708
|
+
core.using(entity.entityAspect.entityManager, "isLoading", true, function () {
|
|
709
|
+
removeFromRelationsCore(entity);
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
function removeFromRelationsCore(entity) {
|
|
714
|
+
entity.entityType.navigationProperties.forEach(function (np) {
|
|
715
|
+
let inverseNp = np.inverse;
|
|
716
|
+
let npValue = entity.getProperty(np.name);
|
|
717
|
+
if (np.isScalar) {
|
|
718
|
+
if (npValue) {
|
|
719
|
+
if (inverseNp) {
|
|
720
|
+
if (inverseNp.isScalar) {
|
|
721
|
+
npValue.setProperty(inverseNp.name, null);
|
|
722
|
+
}
|
|
723
|
+
else {
|
|
724
|
+
let collection = npValue.getProperty(inverseNp.name);
|
|
725
|
+
if (collection.length) {
|
|
726
|
+
core.arrayRemoveItem(collection, entity);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
entity.setProperty(np.name, null);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
if (inverseNp != null) {
|
|
735
|
+
// npValue is a live list so we need to copy it first.
|
|
736
|
+
npValue.slice(0).forEach((v) => {
|
|
737
|
+
if (inverseNp.isScalar) {
|
|
738
|
+
v.setProperty(inverseNp.name, null);
|
|
739
|
+
}
|
|
740
|
+
else {
|
|
741
|
+
// TODO: many to many - not yet handled.
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
// now clear it.
|
|
746
|
+
npValue.length = 0;
|
|
747
|
+
}
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
// note entityAspect only - ( no complex aspect allowed on the call).
|
|
751
|
+
function validate(entityAspect, validator, value, context) {
|
|
752
|
+
let ve = validator.validate(value, context);
|
|
753
|
+
if (ve) {
|
|
754
|
+
entityAspect._addValidationError(ve);
|
|
755
|
+
return false;
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
let key = ValidationError.getKey(validator, context ? context.propertyName : null);
|
|
759
|
+
entityAspect._removeValidationError(key);
|
|
760
|
+
return true;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
// coIndex is only used where target is a complex object that is part of an array of complex objects
|
|
764
|
+
// in which case ctIndex is the index of the target within the array.
|
|
765
|
+
function validateTarget(target, coIndex) {
|
|
766
|
+
let ok = true;
|
|
767
|
+
let stype = target.entityType || target.complexType;
|
|
768
|
+
let aspect = target.entityAspect || target.complexAspect;
|
|
769
|
+
let entityAspect = target.entityAspect || target.complexAspect.getEntityAspect();
|
|
770
|
+
let context = { entity: entityAspect.entity };
|
|
771
|
+
if (coIndex !== undefined) {
|
|
772
|
+
context.index = coIndex;
|
|
773
|
+
}
|
|
774
|
+
stype.getProperties().forEach(function (p) {
|
|
775
|
+
let value = target.getProperty(p.name);
|
|
776
|
+
let validators = p.getAllValidators();
|
|
777
|
+
if (validators.length > 0) {
|
|
778
|
+
context.property = p;
|
|
779
|
+
context.propertyName = aspect.getPropertyPath(p.name);
|
|
780
|
+
ok = entityAspect._validateProperty(value, context) && ok;
|
|
781
|
+
}
|
|
782
|
+
if (p.isComplexProperty) {
|
|
783
|
+
if (p.isScalar) {
|
|
784
|
+
ok = validateTarget(value) && ok;
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
ok = value.reduce(function (pv, cv, ix) {
|
|
788
|
+
return validateTarget(cv, ix) && pv;
|
|
789
|
+
}, ok);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
// then target level
|
|
794
|
+
stype.getAllValidators().forEach(function (validator) {
|
|
795
|
+
ok = validate(entityAspect, validator, target) && ok;
|
|
796
|
+
});
|
|
797
|
+
return ok;
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
An ComplexAspect instance is associated with every complex object instance and is accessed via the complex object's 'complexAspect' property.
|
|
801
|
+
|
|
802
|
+
The ComplexAspect itself provides properties to determine the parent object, parent property and original values for the complex object.
|
|
803
|
+
|
|
804
|
+
A ComplexAspect will almost never need to be constructed directly. You will usually get an ComplexAspect by accessing
|
|
805
|
+
an entities 'complexAspect' property. This property will be automatically attached when an complex object is created as part of an
|
|
806
|
+
entity via either a query, import or EntityManager.createEntity call.
|
|
807
|
+
> // assume address is a complex property on the 'Customer' type
|
|
808
|
+
> var aspect = aCustomer.address.complexAspect;
|
|
809
|
+
> // aCustomer === aspect.parent;
|
|
810
|
+
**/
|
|
811
|
+
export class ComplexAspect {
|
|
812
|
+
/** The complex object that this aspect is associated with. __Read Only__ */
|
|
813
|
+
complexObject;
|
|
814
|
+
/** The 'original values' of this complex object where they are different from the 'current values'.
|
|
815
|
+
This is a map where the key is a property name and the value is the 'original value' of the property.
|
|
816
|
+
__Read Only__ */
|
|
817
|
+
originalValues;
|
|
818
|
+
/** The parent object that to which this aspect belongs; this will either be an entity or another complex object. __Read Only__ */
|
|
819
|
+
parent;
|
|
820
|
+
/** The [[DataProperty]] on the 'parent' that contains this complex object. __Read Only__ */
|
|
821
|
+
parentProperty;
|
|
822
|
+
extraMetadata;
|
|
823
|
+
/** You will rarely, if ever, create a ComplexAspect directly. */
|
|
824
|
+
constructor(complexObject, parent, parentProperty) {
|
|
825
|
+
if (!complexObject) {
|
|
826
|
+
throw new Error("The ComplexAspect ctor requires an entity as its only argument.");
|
|
827
|
+
}
|
|
828
|
+
if (complexObject.complexAspect) {
|
|
829
|
+
return complexObject.complexAspect;
|
|
830
|
+
}
|
|
831
|
+
// if called without new
|
|
832
|
+
if (!(this instanceof ComplexAspect)) {
|
|
833
|
+
return new ComplexAspect(complexObject, parent, parentProperty);
|
|
834
|
+
}
|
|
835
|
+
// entityType should already be on the entity from 'watch'
|
|
836
|
+
this.complexObject = complexObject;
|
|
837
|
+
complexObject.complexAspect = this;
|
|
838
|
+
// TODO: keep public or not?
|
|
839
|
+
this.originalValues = {};
|
|
840
|
+
// if a standalone complexObject
|
|
841
|
+
if (parent != null) {
|
|
842
|
+
this.parent = parent;
|
|
843
|
+
this.parentProperty = parentProperty;
|
|
844
|
+
}
|
|
845
|
+
let complexType = complexObject.complexType;
|
|
846
|
+
if (!complexType) {
|
|
847
|
+
let typeName = complexObject.prototype._$typeName;
|
|
848
|
+
if (!typeName) {
|
|
849
|
+
throw new Error("This entity is not registered as a valid ComplexType");
|
|
850
|
+
}
|
|
851
|
+
else {
|
|
852
|
+
throw new Error("Metadata for this complexType has not yet been resolved: " + typeName);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
let complexCtor = complexType.getCtor();
|
|
856
|
+
config.interfaceRegistry.modelLibrary.getDefaultInstance().startTracking(complexObject, complexCtor.prototype);
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
Returns the EntityAspect for the top level entity that contains this complex object.
|
|
860
|
+
**/
|
|
861
|
+
getEntityAspect() {
|
|
862
|
+
let parent = this.parent;
|
|
863
|
+
if (!parent)
|
|
864
|
+
return new EntityAspect();
|
|
865
|
+
let entityAspect = parent.entityAspect;
|
|
866
|
+
while (parent && !entityAspect) {
|
|
867
|
+
parent = parent.complexAspect && parent.complexAspect.parent;
|
|
868
|
+
entityAspect = parent && parent.entityAspect;
|
|
869
|
+
}
|
|
870
|
+
return entityAspect || new EntityAspect();
|
|
871
|
+
}
|
|
872
|
+
/** @hidden @internal */
|
|
873
|
+
// TODO: rename - and use '_'; used on both EntityAspect and ComplexAspect for polymorphic reasons.
|
|
874
|
+
getPropertyPath(propName) {
|
|
875
|
+
let parent = this.parent;
|
|
876
|
+
if (!parent)
|
|
877
|
+
return null;
|
|
878
|
+
let aspect = parent.complexAspect || parent.entityAspect;
|
|
879
|
+
return aspect.getPropertyPath(this.parentProperty.name + "." + propName);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
function clearOriginalValues(target) {
|
|
883
|
+
let aspect = target.entityAspect || target.complexAspect;
|
|
884
|
+
aspect.originalValues = {};
|
|
885
|
+
let stype = target.entityType || target.complexType;
|
|
886
|
+
stype.complexProperties.forEach(function (cp) {
|
|
887
|
+
let cos = target.getProperty(cp.name);
|
|
888
|
+
if (cp.isScalar) {
|
|
889
|
+
clearOriginalValues(cos);
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
cos._acceptChanges();
|
|
893
|
+
cos.forEach(clearOriginalValues);
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWFzcGVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9lbnRpdHktYXNwZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDOUIsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNsQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsV0FBVyxFQUFHLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQWlFLE1BQU0sbUJBQW1CLENBQUM7QUFDOUcsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUd6QyxPQUFPLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN4RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUF5QzdDOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLE9BQU8sWUFBWTtJQUN2QixzRUFBc0U7SUFDdEUsTUFBTSxDQUFVO0lBQ2hCLHNFQUFzRTtJQUN0RSxhQUFhLENBQWlCO0lBQzlCLHlCQUF5QjtJQUN6QixXQUFXLENBQWU7SUFDMUIseURBQXlEO0lBQ3pELFdBQVcsQ0FBYztJQUN6Qiw0RUFBNEU7SUFDNUUsWUFBWSxDQUFVO0lBQ3RCOzRHQUN3RztJQUN4RyxjQUFjLENBQXNCO0lBQ3BDLG9FQUFvRTtJQUNwRSxtQkFBbUIsQ0FBVTtJQUM3Qix5REFBeUQ7SUFDekQsVUFBVSxDQUFVO0lBQ3BCLHdFQUF3RTtJQUN4RSxTQUFTLENBQVc7SUFDcEI7OzhFQUUwRTtJQUMxRSxhQUFhLENBQU87SUFDcEI7Ozs7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RyxNQUFNLENBQUMsYUFBYSxJQUFJLE1BQU0sQ0FBQyxZQUFZLENBQUM7UUFDekQsT0FBTyxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxjQUFlLENBQUMsSUFBSSxHQUFHLEdBQUcsR0FBRyxRQUFRLENBQUMsQ0FBQztJQUM1RSxDQUFDO0NBRUY7QUFFRCxTQUFTLG1CQUFtQixDQUFDLE1BQVc7SUFDdEMsSUFBSSxNQUFNLEdBQUcsTUFBTSxDQUFDLFlBQVksSUFBSSxNQUFNLENBQUMsYUFBYSxDQUFDO0lBQ3pELE1BQU0sQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO0lBQzNCLElBQUksS0FBSyxHQUFHLE1BQU0sQ0FBQyxVQUFVLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQztJQUNwRCxLQUFLLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBTztRQUMvQyxJQUFJLEdBQUcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QyxJQUFJLEVBQUUsQ0FBQyxRQUFRLEVBQUU7WUFDZixtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUMxQjthQUFNO1lBQ0wsR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3JCLEdBQUcsQ0FBQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztTQUNsQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNvcmUgfSBmcm9tICcuL2NvcmUnO1xyXG5pbXBvcnQgeyBjb25maWcgfSBmcm9tICcuL2NvbmZpZyc7XHJcbmltcG9ydCB7IEJyZWV6ZUV2ZW50IH0gZnJvbSAnLi9ldmVudCc7XHJcbmltcG9ydCB7IGFzc2VydFBhcmFtIH0gZnJvbSAnLi9hc3NlcnQtcGFyYW0nO1xyXG5pbXBvcnQgeyBFbnRpdHlTdGF0ZSAgfSBmcm9tICcuL2VudGl0eS1zdGF0ZSc7XHJcbmltcG9ydCB7IEVudGl0eUFjdGlvbiB9IGZyb20gJy4vZW50aXR5LWFjdGlvbic7XHJcbmltcG9ydCB7IEVudGl0eVR5cGUsIENvbXBsZXhUeXBlLCBEYXRhUHJvcGVydHksIE5hdmlnYXRpb25Qcm9wZXJ0eSwgRW50aXR5UHJvcGVydHkgfSBmcm9tICcuL2VudGl0eS1tZXRhZGF0YSc7XHJcbmltcG9ydCB7IEVudGl0eUtleSB9IGZyb20gJy4vZW50aXR5LWtleSc7XHJcbmltcG9ydCB7IEVudGl0eUdyb3VwIH0gZnJvbSAnLi9lbnRpdHktZ3JvdXAnO1xyXG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyLCBRdWVyeVJlc3VsdCwgUXVlcnlFcnJvckNhbGxiYWNrLCBRdWVyeVN1Y2Nlc3NDYWxsYmFjayB9IGZyb20gJy4vZW50aXR5LW1hbmFnZXInO1xyXG5pbXBvcnQgeyBWYWxpZGF0b3IsIFZhbGlkYXRpb25FcnJvciB9IGZyb20gJy4vdmFsaWRhdGUnO1xyXG5pbXBvcnQgeyBFbnRpdHlRdWVyeSB9IGZyb20gJy4vZW50aXR5LXF1ZXJ5JztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgRW50aXR5IHtcclxuICBlbnRpdHlBc3BlY3Q6IEVudGl0eUFzcGVjdDtcclxuICBlbnRpdHlUeXBlOiBFbnRpdHlUeXBlO1xyXG4gIC8qKiBHZXQgdGhlIHByb3BlcnR5IHdpdGggdGhlIGdpdmVuIG5hbWUgKi9cclxuICBnZXRQcm9wZXJ0eT8ocHJvcDogc3RyaW5nKTogYW55O1xyXG4gIC8qKiBTZXQgdGhlIHByb3BlcnR5IHdpdGggdGhlIGdpdmVuIG5hbWUgKi9cclxuICBzZXRQcm9wZXJ0eT8ocHJvcDogYW55LCB2YWx1ZTogYW55KTogdm9pZDtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBwcm90b3R5cGU/OiB7IF8kdHlwZU5hbWU6IHN0cmluZyB9O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF8kZW50aXR5VHlwZT86IEVudGl0eVR5cGU7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ29tcGxleE9iamVjdCB7XHJcbiAgY29tcGxleEFzcGVjdDogQ29tcGxleEFzcGVjdDtcclxuICBjb21wbGV4VHlwZTogQ29tcGxleFR5cGU7XHJcbiAgZ2V0UHJvcGVydHk/KHByb3A6IHN0cmluZyk6IGFueTtcclxuICBzZXRQcm9wZXJ0eT8ocHJvcDogYW55LCB2YWx1ZTogYW55KTogdm9pZDtcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBwcm90b3R5cGU/OiB7IF8kdHlwZU5hbWU6IHN0cmluZyB9O1xyXG59XHJcblxyXG5leHBvcnQgdHlwZSBTdHJ1Y3R1cmFsT2JqZWN0ID0gRW50aXR5IHwgQ29tcGxleE9iamVjdDtcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUHJvcGVydHlDaGFuZ2VkRXZlbnRBcmdzIHtcclxuICBlbnRpdHk6IEVudGl0eTtcclxuICBwcm9wZXJ0eU5hbWU6IHN0cmluZyB8IG51bGw7XHJcbiAgcGFyZW50PzogU3RydWN0dXJhbE9iamVjdDtcclxuICBwcm9wZXJ0eT86IEVudGl0eVByb3BlcnR5O1xyXG4gIG9sZFZhbHVlPzogYW55O1xyXG4gIG5ld1ZhbHVlPzogYW55O1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkRXZlbnRBcmdzIHtcclxuICBlbnRpdHk6IEVudGl0eTtcclxuICBhZGRlZDogVmFsaWRhdGlvbkVycm9yW107XHJcbiAgcmVtb3ZlZDogVmFsaWRhdGlvbkVycm9yW107XHJcbn1cclxuXHJcbi8qKlxyXG5BbiBFbnRpdHlBc3BlY3QgaW5zdGFuY2UgaXMgYXNzb2NpYXRlZCB3aXRoIGV2ZXJ5IGF0dGFjaGVkIGVudGl0eSBhbmQgaXMgYWNjZXNzZWQgdmlhIHRoZSBlbnRpdHkncyAnZW50aXR5QXNwZWN0JyBwcm9wZXJ0eS5cclxuXHJcblRoZSBFbnRpdHlBc3BlY3QgaXRzZWxmIHByb3ZpZGVzIHByb3BlcnRpZXMgdG8gZGV0ZXJtaW5lIGFuZCBtb2RpZnkgdGhlIEVudGl0eVN0YXRlIG9mIHRoZSBlbnRpdHkgYW5kIGhhcyBtZXRob2RzXHJcbnRoYXQgcHJvdmlkZSBhIHZhcmlldHkgb2Ygc2VydmljZXMgaW5jbHVkaW5nIHZhbGlkYXRpb24gYW5kIGNoYW5nZSB0cmFja2luZy5cclxuXHJcbkFuIEVudGl0eUFzcGVjdCB3aWxsIGFsbW9zdCBuZXZlciBuZWVkIHRvIGJlIGNvbnN0cnVjdGVkIGRpcmVjdGx5LiBZb3Ugd2lsbCB1c3VhbGx5IGdldCBhbiBFbnRpdHlBc3BlY3QgYnkgYWNjZXNzaW5nXHJcbmFuIGVudGl0aWVzICdlbnRpdHlBc3BlY3QnIHByb3BlcnR5LiAgVGhpcyBwcm9wZXJ0eSB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYXR0YWNoZWQgd2hlbiBhbiBlbnRpdHkgaXMgY3JlYXRlZCB2aWEgZWl0aGVyXHJcbmEgcXVlcnksIGltcG9ydCBvciBbW0VudGl0eU1hbmFnZXIuY3JlYXRlRW50aXR5XV0gY2FsbC5cclxuPiAgICAgIC8vIGFzc3VtZSBvcmRlciBpcyBhbiBvcmRlciBlbnRpdHkgYXR0YWNoZWQgdG8gYW4gRW50aXR5TWFuYWdlci5cclxuPiAgICAgIHZhciBhc3BlY3QgPSBvcmRlci5lbnRpdHlBc3BlY3Q7XHJcbj4gICAgICB2YXIgY3VycmVudFN0YXRlID0gYXNwZWN0LmVudGl0eVN0YXRlO1xyXG5cclxuKiovXHJcbmV4cG9ydCBjbGFzcyBFbnRpdHlBc3BlY3Qge1xyXG4gIC8qKiBUaGUgRW50aXR5IHRoYXQgdGhpcyBhc3BlY3QgaXMgYXNzb2NpYXRlZCB3aXRoLiBfX1JlYWQgT25seV9fICAqKi9cclxuICBlbnRpdHk/OiBFbnRpdHk7XHJcbiAgLyoqIFRoZSBbW0VudGl0eU1hbmFnZXJdXSB0aGF0IGNvbnRhaW5zIHRoaXMgZW50aXR5LiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGVudGl0eU1hbmFnZXI/OiBFbnRpdHlNYW5hZ2VyO1xyXG4gIC8qKiAgQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBlbnRpdHlHcm91cD86IEVudGl0eUdyb3VwO1xyXG4gIC8qKiBUaGUgW1tFbnRpdHlTdGF0ZV1dIG9mIHRoaXMgZW50aXR5LiBfX1JlYWQgT25seV9fICoqL1xyXG4gIGVudGl0eVN0YXRlOiBFbnRpdHlTdGF0ZTtcclxuICAvKiogICBXaGV0aGVyIHRoaXMgZW50aXR5IGlzIGluIHRoZSBwcm9jZXNzIG9mIGJlaW5nIHNhdmVkLiBfX1JlYWQgT25seV9fICovXHJcbiAgaXNCZWluZ1NhdmVkOiBib29sZWFuO1xyXG4gIC8qKiBUaGUgJ29yaWdpbmFsIHZhbHVlcycgb2YgdGhpcyBlbnRpdHkgd2hlcmUgdGhleSBhcmUgZGlmZmVyZW50IGZyb20gdGhlICdjdXJyZW50IHZhbHVlcycuXHJcbiAgVGhpcyBpcyBhIG1hcCB3aGVyZSB0aGUga2V5IGlzIGEgcHJvcGVydHkgbmFtZSBhbmQgdGhlIHZhbHVlIGlzIHRoZSAnb3JpZ2luYWwgdmFsdWUnIG9mIHRoZSBwcm9wZXJ0eS4gKi9cclxuICBvcmlnaW5hbFZhbHVlczogUmVjb3JkPHN0cmluZywgYW55PjtcclxuICAvKiogIFdoZXRoZXIgdGhpcyBlbnRpdHkgaGFzIGFueSB2YWxpZGF0aW9uIGVycm9ycy4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGhhc1ZhbGlkYXRpb25FcnJvcnM6IGJvb2xlYW47XHJcbiAgLyoqIFdoZXRoZXIgdGhpcyBlbnRpdHkgaGFzIGEgdGVtcG9yYXJ5IFtbRW50aXR5S2V5XV0uICovXHJcbiAgaGFzVGVtcEtleTogYm9vbGVhbjtcclxuICAvKiogV2hldGhlciB0aGlzIGVudGl0eSB3YXMgY3JlYXRlZCBieSBiZWluZyBsb2FkZWQgZnJvbSB0aGUgZGF0YWJhc2UgKi9cclxuICB3YXNMb2FkZWQ/OiBib29sZWFuO1xyXG4gIC8qKiBFeHRyYSBtZXRhZGF0YSBhYm91dCB0aGlzIGVudGl0eSBzdWNoIGFzIHRoZSBlbnRpdHkncyBldGFnLlxyXG4gIFlvdSBtYXkgZXh0ZW5kIHRoaXMgb2JqZWN0IHdpdGggeW91ciBvd24gbWV0YWRhdGEgaW5mb3JtYXRpb24uXHJcbiAgQnJlZXplIChkZSlzZXJpYWxpemVzIHRoaXMgb2JqZWN0IHdoZW4gaW1wb3J0aW5nL2V4cG9ydGluZyB0aGUgZW50aXR5LiAqKi9cclxuICBleHRyYU1ldGFkYXRhPzogYW55O1xyXG4gIC8qKlxyXG4gIEEgW1tCcmVlemVFdmVudF1dIHRoYXQgZmlyZXMgd2hlbmV2ZXIgYW55IG9mIHRoZSB2YWxpZGF0aW9uIGVycm9ycyBvbiB0aGlzIGVudGl0eSBjaGFuZ2UuXHJcbiAgTm90ZSB0aGF0IHRoaXMgbWlnaHQgYmUgdGhlIHJlbW92YWwgb2YgYW4gZXJyb3Igd2hlbiBzb21lIGRhdGEgb24gdGhlIGVudGl0eSBpcyBmaXhlZC5cclxuICBAZXZlbnRBcmdzIC0gXHJcbiAgICAtIGVudGl0eSAtIFRoZSBlbnRpdHkgb24gd2hpY2ggdGhlIHZhbGlkYXRpb24gZXJyb3JzIGFyZSBiZWluZyBhZGRlZCBvciByZW1vdmVkLlxyXG4gICAgLSBhZGRlZCAtIEFuIGFycmF5IGNvbnRhaW5pbmcgYW55IG5ld2x5IGFkZGVkIFtbVmFsaWRhdGlvbkVycm9yXV1zXHJcbiAgICAtIHJlbW92ZWQgLSBBbiBhcnJheSBjb250YWluaW5nIGFueSBuZXdseSByZW1vdmVkIFtbVmFsaWRhdGlvbkVycm9yXV1zLiBUaGlzIGlzIHRob3NlXHJcbiAgICAgIGVycm9ycyB0aGF0IGhhdmUgYmVlbiAnZml4ZWQnLlxyXG5cclxuPiAgICAgIC8vIGFzc3VtZSBvcmRlciBpcyBhbiBvcmRlciBlbnRpdHkgYXR0YWNoZWQgdG8gYW4gRW50aXR5TWFuYWdlci5cclxuPiAgICAgIG9yZGVyLmVudGl0eUFzcGVjdC52YWxpZGF0aW9uRXJyb3JzQ2hhbmdlZC5zdWJzY3JpYmUoXHJcbj4gICAgICBmdW5jdGlvbiAodmFsaWRhdGlvbkNoYW5nZUFyZ3MpIHtcclxuPiAgICAgICAgICAvLyB0aGlzIGNvZGUgd2lsbCBiZSBleGVjdXRlZCBhbnl0aW1lIGEgcHJvcGVydHkgdmFsdWUgY2hhbmdlcyBvbiB0aGUgJ29yZGVyJyBlbnRpdHkuXHJcbj4gICAgICAgICAgdmFyIGVudGl0eSA9PSB2YWxpZGF0aW9uQ2hhbmdlQXJncy5lbnRpdHk7IC8vIE5vdGU6IGVudGl0eSA9PT0gb3JkZXJcclxuPiAgICAgICAgICB2YXIgZXJyb3JzQWRkZWQgPSB2YWxpZGF0aW9uQ2hhbmdlQXJncy5hZGRlZDtcclxuPiAgICAgICAgICB2YXIgZXJyb3JzQ2xlYXJlZCA9IHZhbGlkYXRpb25DaGFuZ2VBcmdzLnJlbW92ZWQ7XHJcbj4gICAgICB9KTtcclxuICBAZXZlbnRcclxuICAqKi9cclxuICB2YWxpZGF0aW9uRXJyb3JzQ2hhbmdlZDogQnJlZXplRXZlbnQ8VmFsaWRhdGlvbkVycm9yc0NoYW5nZWRFdmVudEFyZ3M+O1xyXG4gIC8qKlxyXG4gIEEgW1tCcmVlemVFdmVudF1dIHRoYXQgZmlyZXMgd2hlbmV2ZXIgYSB2YWx1ZSBvZiBvbmUgb2YgdGhpcyBlbnRpdHkncyBwcm9wZXJ0aWVzIGNoYW5nZS5cclxuICBAZXZlbnRBcmdzIC1cclxuICAgIC0gZW50aXR5IC0gVGhlIGVudGl0eSB3aG9zZSBwcm9wZXJ0eSBoYXMgY2hhbmdlZC5cclxuICAgIC0gcHJvcGVydHkgLSBUaGUgW1tEYXRhUHJvcGVydHldXSB0aGF0IGNoYW5nZWQuXHJcbiAgICAtIHByb3BlcnR5TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgd2lsbCBiZSAnbnVsbCcgZm9yIG9wZXJhdGlvbnMgdGhhdCByZXBsYWNlIHRoZSBlbnRpcmUgZW50aXR5LiAgVGhpcyBpbmNsdWRlc1xyXG4gICAgICBxdWVyaWVzLCBpbXBvcnRzIGFuZCBzYXZlcyB0aGF0IHJlcXVpcmUgYSBtZXJnZS4gVGhlIHJlbWFpbmluZyBwYXJhbWV0ZXJzIHdpbGwgbm90IGV4aXN0IGluIHRoaXMgY2FzZSBlaXRoZXIuIFRoaXMgd2lsbCBhY3R1YWxseSBiZSBhIFwicHJvcGVydHkgcGF0aFwiXHJcbiAgICAgIGZvciBhbnkgcHJvcGVydGllcyBvZiBhIGNvbXBsZXggdHlwZS5cclxuICAgIC0gb2xkVmFsdWUgLSBUaGUgb2xkIHZhbHVlIG9mIHRoaXMgcHJvcGVydHkgYmVmb3JlIHRoZSBjaGFuZ2UuXHJcbiAgICAtIG5ld1ZhbHVlIC0gVGhlIG5ldyB2YWx1ZSBvZiB0aGlzIHByb3BlcnR5IGFmdGVyIHRoZSBjaGFuZ2UuXHJcbiAgICAtIHBhcmVudCAtIFRoZSBpbW1lZGlhdGUgcGFyZW50IG9iamVjdCBmb3IgdGhlIGNoYW5nZWQgcHJvcGVydHkuICBUaGlzIHdpbGwgYmUgYSBDb21wbGV4VHlwZSBpbnN0YW5jZSBhcyBvcHBvc2VkIHRvIGFuIEVudGl0eSBcclxuICAgICAgZm9yIGFueSBjb21wbGV4IHR5cGUgb3IgbmVzdGVkIGNvbXBsZXggdHlwZSBwcm9wZXJ0aWVzLlxyXG5cclxuICA+ICAgICAgLy8gYXNzdW1lIG9yZGVyIGlzIGFuIG9yZGVyIGVudGl0eSBhdHRhY2hlZCB0byBhbiBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICBvcmRlci5lbnRpdHlBc3BlY3QucHJvcGVydHlDaGFuZ2VkLnN1YnNjcmliZShcclxuICA+ICAgICAgZnVuY3Rpb24gKHByb3BlcnR5Q2hhbmdlZEFyZ3MpIHtcclxuICA+ICAgICAgICAgIC8vIHRoaXMgY29kZSB3aWxsIGJlIGV4ZWN1dGVkIGFueXRpbWUgYSBwcm9wZXJ0eSB2YWx1ZSBjaGFuZ2VzIG9uIHRoZSAnb3JkZXInIGVudGl0eS5cclxuICA+ICAgICAgICAgIHZhciBlbnRpdHkgPSBwcm9wZXJ0eUNoYW5nZWRBcmdzLmVudGl0eTsgLy8gTm90ZTogZW50aXR5ID09PSBvcmRlclxyXG4gID4gICAgICAgICAgdmFyIHByb3BlcnR5TmFtZUNoYW5nZWQgPSBwcm9wZXJ0eUNoYW5nZWRBcmdzLnByb3BlcnR5TmFtZTtcclxuICA+ICAgICAgICAgIHZhciBvbGRWYWx1ZSA9IHByb3BlcnR5Q2hhbmdlZEFyZ3Mub2xkVmFsdWU7XHJcbiAgPiAgICAgICAgICB2YXIgbmV3VmFsdWUgPSBwcm9wZXJ0eUNoYW5nZWRBcmdzLm5ld1ZhbHVlO1xyXG4gID4gICAgICB9KTtcclxuICBAZXZlbnRcclxuICAqKi9cclxuICBwcm9wZXJ0eUNoYW5nZWQ6IEJyZWV6ZUV2ZW50PFByb3BlcnR5Q2hhbmdlZEV2ZW50QXJncz47XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF92YWxpZGF0aW9uRXJyb3JzOiB7IFtpbmRleDogc3RyaW5nXTogVmFsaWRhdGlvbkVycm9yIH07XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3BlbmRpbmdWYWxpZGF0aW9uUmVzdWx0OiBhbnk7XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2VudGl0eUtleTogRW50aXR5S2V5O1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9sb2FkZWROcHM6IGFueVtdO1xyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF9pbml0aWFsaXplZD86IGJvb2xlYW47XHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2luUHJvY2VzczogYW55W107IC8vIHVzZWQgaW4gZGVmYXVsdFByb3BlcnR5SW50ZXJjZXB0b3IgZm9yIHRlbXAgc3RvcmFnZS5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfaW5Qcm9jZXNzRW50aXR5PzogRW50aXR5OyAvLyB1c2VkIGluIEVudGl0eU1hbmFnZXJcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBzdGF0aWMgX251bGxJbnN0YW5jZSA9IG5ldyBFbnRpdHlBc3BlY3QoKTsgLy8gVE9ETzogZGV0ZXJtaW5lIGlmIHRoaXMgd29ya3NcclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBjb25zdHJ1Y3RvcihlbnRpdHk/OiBFbnRpdHkpIHtcclxuXHJcbiAgICAvLyBpZiBjYWxsZWQgd2l0aG91dCBuZXdcclxuICAgIC8vIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFbnRpdHlBc3BlY3QpKSB7XHJcbiAgICAvLyAgIHJldHVybiBuZXcgRW50aXR5QXNwZWN0KGVudGl0eSk7XHJcbiAgICAvLyB9XHJcblxyXG4gICAgdGhpcy5lbnRpdHkgPSBlbnRpdHk7XHJcbiAgICAvLyBUT0RPOiBrZWVwIHB1YmxpYyBvciBub3Q/XHJcbiAgICB0aGlzLmVudGl0eUdyb3VwID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy5lbnRpdHlNYW5hZ2VyID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy5lbnRpdHlTdGF0ZSA9IEVudGl0eVN0YXRlLkRldGFjaGVkO1xyXG4gICAgdGhpcy5pc0JlaW5nU2F2ZWQgPSBmYWxzZTtcclxuICAgIHRoaXMub3JpZ2luYWxWYWx1ZXMgPSB7fTtcclxuICAgIHRoaXMuaGFzVmFsaWRhdGlvbkVycm9ycyA9IGZhbHNlO1xyXG4gICAgdGhpcy5fdmFsaWRhdGlvbkVycm9ycyA9IHt9O1xyXG5cclxuICAgIC8vIFVuY29tbWVudCB3aGVuIHdlIGltcGxlbWVudCBlbnRpdHlBc3BlY3QuaXNOYXZpZ2F0aW9uUHJvcGVydHlMb2FkZWQgbWV0aG9kXHJcbiAgICAvLyB0aGlzLl9sb2FkZWROYXZQcm9wTWFwID0ge307XHJcblxyXG4gICAgdGhpcy52YWxpZGF0aW9uRXJyb3JzQ2hhbmdlZCA9IG5ldyBCcmVlemVFdmVudChcInZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkXCIsIHRoaXMpO1xyXG4gICAgdGhpcy5wcm9wZXJ0eUNoYW5nZWQgPSBuZXcgQnJlZXplRXZlbnQoXCJwcm9wZXJ0eUNoYW5nZWRcIiwgdGhpcyk7XHJcbiAgICAvLyBpbiBjYXNlIHRoaXMgaXMgdGhlIE5VTEwgZW50aXR5QXNwZWN0LiAtIHVzZWQgd2l0aCBDb21wbGV4QXNwZWN0cyB0aGF0IGhhdmUgbm8gcGFyZW50LlxyXG5cclxuICAgIGlmIChlbnRpdHkgIT0gbnVsbCkge1xyXG4gICAgICAvLyByZW1vdmUgcHJvcGVydGllcyB0aGF0IHNob3VsZCBiZSBvbiBwcm90b3R5cGUgYnV0IHBsYWNlZCBvbiBpbnN0YW5jZSBieSBCYWJlbFxyXG4gICAgICBpZiAoZW50aXR5Lmhhc093blByb3BlcnR5KCdlbnRpdHlUeXBlJykpIHtcclxuICAgICAgICAvLyB0aHJvdyBuZXcgRXJyb3IoXCJFbnRpdHkgaW5zdGFuY2UgaGFzIGVudGl0eVR5cGUgcHJvcGVydHk7IHNob3VsZCBvbmx5IGJlIG9uIHByb3RvdHlwZVwiKTtcclxuICAgICAgICBkZWxldGUoZW50aXR5LmVudGl0eVR5cGUpO1xyXG4gICAgICB9XHJcbiAgICAgIGVudGl0eS5lbnRpdHlBc3BlY3QgPSB0aGlzO1xyXG5cclxuICAgICAgLy8gZW50aXR5VHlwZSBzaG91bGQgYWxyZWFkeSBiZSBvbiB0aGUgZW50aXR5IGZyb20gJ3dhdGNoJ1xyXG4gICAgICBsZXQgZW50aXR5VHlwZSA9IGVudGl0eS5lbnRpdHlUeXBlIHx8IGVudGl0eS5fJGVudGl0eVR5cGU7XHJcbiAgICAgIGlmICghZW50aXR5VHlwZSkge1xyXG4gICAgICAgIGxldCB0eXBlTmFtZSA9IGVudGl0eS5wcm90b3R5cGUuXyR0eXBlTmFtZTtcclxuICAgICAgICBpZiAoIXR5cGVOYW1lKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIGVudGl0eSBpcyBub3QgcmVnaXN0ZXJlZCBhcyBhIHZhbGlkIEVudGl0eVR5cGVcIik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1ldGFkYXRhIGZvciB0aGlzIGVudGl0eVR5cGUgaGFzIG5vdCB5ZXQgYmVlbiByZXNvbHZlZDogXCIgKyB0eXBlTmFtZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGxldCBlbnRpdHlDdG9yID0gZW50aXR5VHlwZS5nZXRDdG9yKCk7XHJcbiAgICAgIGNvbmZpZy5pbnRlcmZhY2VSZWdpc3RyeS5tb2RlbExpYnJhcnkuZ2V0RGVmYXVsdEluc3RhbmNlKCkuc3RhcnRUcmFja2luZyhlbnRpdHksIGVudGl0eUN0b3IucHJvdG90eXBlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuICovXHJcbiAgLy8gdHlwZS1ndWFyZFxyXG4gIHN0YXRpYyBpc0VudGl0eShvYmo6IFN0cnVjdHVyYWxPYmplY3QpOiBvYmogaXMgRW50aXR5IHtcclxuICAgIHJldHVybiAob2JqIGFzIGFueSkuZW50aXR5QXNwZWN0ICE9IG51bGw7XHJcbiAgfVxyXG5cclxuICAvLyBObyBsb25nZXIgdXNlZFxyXG4gIC8vIHN0YXRpYyBjcmVhdGVGcm9tKGVudGl0eTogRW50aXR5KTogRW50aXR5QXNwZWN0IHtcclxuICAvLyAgIGlmIChlbnRpdHkgPT0gbnVsbCkge1xyXG4gIC8vICAgICByZXR1cm4gRW50aXR5QXNwZWN0Ll9udWxsSW5zdGFuY2U7XHJcbiAgLy8gICB9IGVsc2UgaWYgKGVudGl0eS5lbnRpdHlBc3BlY3QpIHtcclxuICAvLyAgICAgcmV0dXJuIGVudGl0eS5lbnRpdHlBc3BlY3Q7XHJcbiAgLy8gICB9XHJcbiAgLy8gICByZXR1cm4gbmV3IEVudGl0eUFzcGVjdChlbnRpdHkpO1xyXG4gIC8vIH1cclxuXHJcbiAgLy8gVE9ETzogcmVmYWN0b3IgdGhpcyBhbmQgdGhlIGluc3RhbmNlIGdldFByb3BlcnR5VmFsdWUgbWV0aG9kLlxyXG4gIC8qKlxyXG4gIFJldHVybnMgdGhlIHZhbHVlIG9mIGEgc3BlY2lmaWVkICdwcm9wZXJ0eSBwYXRoJyBmb3IgYSBzcGVjaWZpZWQgZW50aXR5LlxyXG5cclxuICBUaGUgcHJvcGVydHlQYXRoIGNhbiBiZSBlaXRoZXIgYSBzdHJpbmcgZGVsaW1pdGVkIHdpdGggJy4nIG9yIGEgc3RyaW5nIGFycmF5LiAgXHJcbiAgKiovXHJcbiAgLy8gdXNlZCBieSBFbnRpdHlRdWVyeSBhbmQgUHJlZGljYXRlXHJcbiAgc3RhdGljIGdldFByb3BlcnR5UGF0aFZhbHVlKG9iajogRW50aXR5LCBwcm9wZXJ0eVBhdGg6IHN0cmluZyB8IHN0cmluZ1tdKSB7XHJcbiAgICBsZXQgcHJvcGVydGllcyA9IEFycmF5LmlzQXJyYXkocHJvcGVydHlQYXRoKSA/IHByb3BlcnR5UGF0aCA6IHByb3BlcnR5UGF0aC5zcGxpdChcIi5cIik7XHJcbiAgICBpZiAocHJvcGVydGllcy5sZW5ndGggPT09IDEpIHtcclxuICAgICAgcmV0dXJuIG9iai5nZXRQcm9wZXJ0eShwcm9wZXJ0eVBhdGggYXMgc3RyaW5nKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGxldCBuZXh0VmFsdWUgPSBvYmo7XHJcbiAgICAgIC8vIGhhY2sgdXNlIG9mIHNvbWUgdG8gcGVyZm9ybSBtYXBGaXJzdCBvcGVyYXRpb24uXHJcbiAgICAgIHByb3BlcnRpZXMuc29tZSgocHJvcCkgPT4ge1xyXG4gICAgICAgIG5leHRWYWx1ZSA9IG5leHRWYWx1ZS5nZXRQcm9wZXJ0eShwcm9wKTtcclxuICAgICAgICByZXR1cm4gbmV4dFZhbHVlID09IG51bGw7XHJcbiAgICAgIH0pO1xyXG4gICAgICByZXR1cm4gbmV4dFZhbHVlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyB0aGUgW1tFbnRpdHlLZXldXSBmb3IgdGhpcyBFbnRpdHkuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBvcmRlciBpcyBhbiBvcmRlciBlbnRpdHkgYXR0YWNoZWQgdG8gYW4gRW50aXR5TWFuYWdlci5cclxuICA+ICAgICAgdmFyIGVudGl0eUtleSA9IG9yZGVyLmVudGl0eUFzcGVjdC5nZXRLZXkoKTtcclxuICBAcGFyYW0gZm9yY2VSZWZyZXNoIC0gKGJvb2xlYW49ZmFsc2UpIEZvcmNlcyB0aGUgcmVjYWxjdWxhdGlvbiBvZiB0aGUga2V5LiAgVGhpcyBzaG91bGQgbm9ybWFsbHkgYmUgdW5uZWNlc3NhcnkuXHJcbiAgQHJldHVybiBUaGUgW1tFbnRpdHlLZXldXSBhc3NvY2lhdGVkIHdpdGggdGhpcyBFbnRpdHkuXHJcbiAgKiovXHJcbiAgZ2V0S2V5KGZvcmNlUmVmcmVzaDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICBmb3JjZVJlZnJlc2ggPSBhc3NlcnRQYXJhbShmb3JjZVJlZnJlc2gsIFwiZm9yY2VSZWZyZXNoXCIpLmlzQm9vbGVhbigpLmlzT3B0aW9uYWwoKS5jaGVjayhmYWxzZSk7XHJcbiAgICBpZiAoZm9yY2VSZWZyZXNoIHx8ICF0aGlzLl9lbnRpdHlLZXkpIHtcclxuICAgICAgbGV0IGVudGl0eVR5cGUgPSB0aGlzLmVudGl0eSEuZW50aXR5VHlwZTtcclxuICAgICAgbGV0IGtleVByb3BzID0gZW50aXR5VHlwZS5rZXlQcm9wZXJ0aWVzO1xyXG4gICAgICBsZXQgdmFsdWVzID0ga2V5UHJvcHMubWFwKGZ1bmN0aW9uIChwKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZW50aXR5LmdldFByb3BlcnR5KHAubmFtZSk7XHJcbiAgICAgIH0sIHRoaXMpO1xyXG4gICAgICB0aGlzLl9lbnRpdHlLZXkgPSBuZXcgRW50aXR5S2V5KGVudGl0eVR5cGUsIHZhbHVlcyk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5fZW50aXR5S2V5O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyB0aGUgZW50aXR5IHRvIGFuIFtbRW50aXR5U3RhdGVdXSBvZiAnVW5jaGFuZ2VkJyBieSBjb21taXR0aW5nIGFsbCBjaGFuZ2VzIG1hZGUgc2luY2UgdGhlIGVudGl0eSB3YXMgbGFzdCBxdWVyaWVkXHJcbiAgaGFkICdhY2NlcHRDaGFuZ2VzJyBjYWxsZWQgb24gaXQuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBvcmRlciBpcyBhbiBvcmRlciBlbnRpdHkgYXR0YWNoZWQgdG8gYW4gRW50aXR5TWFuYWdlci5cclxuICA+ICAgICAgb3JkZXIuZW50aXR5QXNwZWN0LmFjY2VwdENoYW5nZXMoKTtcclxuICA+ICAgICAgLy8gVGhlICdvcmRlcicgZW50aXR5IHdpbGwgbm93IGJlIGluIGFuICdVbmNoYW5nZWQnIHN0YXRlIHdpdGggYW55IGNoYW5nZXMgY29tbWl0dGVkLlxyXG4gICoqL1xyXG4gIGFjY2VwdENoYW5nZXMoKSB7XHJcbiAgICBpZiAoIXRoaXMuZW50aXR5KSByZXR1cm47XHJcbiAgICB0aGlzLl9jaGVja09wZXJhdGlvbihcImFjY2VwdENoYW5nZXNcIik7XHJcbiAgICBsZXQgZW0gPSB0aGlzLmVudGl0eU1hbmFnZXIhO1xyXG4gICAgaWYgKHRoaXMuZW50aXR5U3RhdGUuaXNEZWxldGVkKCkpIHtcclxuICAgICAgZW0uZGV0YWNoRW50aXR5KHRoaXMuZW50aXR5KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc2V0VW5jaGFuZ2VkKCk7XHJcbiAgICB9XHJcbiAgICBlbS5lbnRpdHlDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHlBY3Rpb246IEVudGl0eUFjdGlvbi5BY2NlcHRDaGFuZ2VzLCBlbnRpdHk6IHRoaXMuZW50aXR5IH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyB0aGUgZW50aXR5IHRvIGFuIFtbRW50aXR5U3RhdGVdXSBvZiAnVW5jaGFuZ2VkJyBieSByZWplY3RpbmcgYWxsIGNoYW5nZXMgbWFkZSB0byBpdCBzaW5jZSB0aGUgZW50aXR5IHdhcyBsYXN0IHF1ZXJpZWRcclxuICBoYWQgJ3JlamVjdENoYW5nZXMnIGNhbGxlZCBvbiBpdC5cclxuICA+ICAgICAgLy8gYXNzdW1lIG9yZGVyIGlzIGFuIG9yZGVyIGVudGl0eSBhdHRhY2hlZCB0byBhbiBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICBvcmRlci5lbnRpdHlBc3BlY3QucmVqZWN0Q2hhbmdlcygpO1xyXG4gID4gICAgICAvLyBUaGUgJ29yZGVyJyBlbnRpdHkgd2lsbCBub3cgYmUgaW4gYW4gJ1VuY2hhbmdlZCcgc3RhdGUgd2l0aCBhbnkgY2hhbmdlcyByZWplY3RlZC5cclxuICAqKi9cclxuICByZWplY3RDaGFuZ2VzKCkge1xyXG4gICAgdGhpcy5fY2hlY2tPcGVyYXRpb24oXCJyZWplY3RDaGFuZ2VzXCIpO1xyXG4gICAgbGV0IGVudGl0eSA9IHRoaXMuZW50aXR5ITtcclxuICAgIGxldCBlbnRpdHlNYW5hZ2VyID0gdGhpcy5lbnRpdHlNYW5hZ2VyITtcclxuICAgIC8vIHdlIGRvIG5vdCB3YW50IFByb3BlcnR5Q2hhbmdlIG9yIEVudGl0eUNoYW5nZSBldmVudHMgdG8gb2NjdXIgaGVyZVxyXG4gICAgY29yZS51c2luZyhlbnRpdHlNYW5hZ2VyLCBcImlzUmVqZWN0aW5nQ2hhbmdlc1wiLCB0cnVlLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHJlamVjdENoYW5nZXNDb3JlKGVudGl0eSk7XHJcbiAgICB9KTtcclxuICAgIGlmICh0aGlzLmVudGl0eVN0YXRlLmlzQWRkZWQoKSkge1xyXG4gICAgICAvLyBuZXh0IGxpbmUgaXMgbmVlZGVkIGJlY2F1c2UgdGhlIGZvbGxvd2luZyBsaW5lIHdpbGwgY2F1c2UgdGhpcy5lbnRpdHlNYW5hZ2VyIC0+IG51bGw7XHJcbiAgICAgIGVudGl0eU1hbmFnZXIuZGV0YWNoRW50aXR5KGVudGl0eSk7XHJcbiAgICAgIC8vIG5lZWQgdG8gdGVsbCBlbSB0aGF0IGFuIGVudGl0eSB0aGF0IG5lZWRlZCB0byBiZSBzYXZlZCBubyBsb25nZXIgZG9lcy5cclxuICAgICAgZW50aXR5TWFuYWdlci5fbm90aWZ5U3RhdGVDaGFuZ2UoZW50aXR5LCBmYWxzZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAodGhpcy5lbnRpdHlTdGF0ZS5pc0RlbGV0ZWQoKSkge1xyXG4gICAgICAgIGVudGl0eU1hbmFnZXIuX2xpbmtSZWxhdGVkRW50aXRpZXMoZW50aXR5KTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnNldFVuY2hhbmdlZCgpO1xyXG4gICAgICAvLyBwcm9wZXJ0eUNoYW5nZWQgcHJvcGVydHlOYW1lIGlzIG5vdCBzcGVjaWZpZWQgYmVjYXVzZSBtb3JlIHRoYW4gb25lIHByb3BlcnR5IG1heSBoYXZlIGNoYW5nZWQuXHJcbiAgICAgIHRoaXMucHJvcGVydHlDaGFuZ2VkLnB1Ymxpc2goeyBlbnRpdHk6IGVudGl0eSwgcHJvcGVydHlOYW1lOiBudWxsIH0pO1xyXG4gICAgICBlbnRpdHlNYW5hZ2VyLmVudGl0eUNoYW5nZWQucHVibGlzaCh7IGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uLlJlamVjdENoYW5nZXMsIGVudGl0eTogZW50aXR5IH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqICBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIC8vIFRPRE86IHJlbmFtZSAtIGFuZCB1c2UgJ18nOyB1c2VkIG9uIGJvdGggRW50aXR5QXNwZWN0IGFuZCBDb21wbGV4QXNwZWN0IGZvciBwb2x5bW9ycGhpYyByZWFzb25zLlxyXG4gIGdldFByb3BlcnR5UGF0aChwcm9wTmFtZTogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4gcHJvcE5hbWU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBTZXRzIHRoZSBlbnRpdHkgdG8gYW4gRW50aXR5U3RhdGUgb2YgJ0FkZGVkJy4gIFRoaXMgaXMgTk9UIHRoZSBlcXVpdmFsZW50IG9mIGNhbGxpbmcgW1tFbnRpdHlNYW5hZ2VyLmFkZEVudGl0eV1dXHJcbiAgYmVjYXVzZSBubyBrZXkgZ2VuZXJhdGlvbiB3aWxsIG9jY3VyIGZvciBhdXRvZ2VuZXJhdGVkIGtleXMgYXMgYSByZXN1bHQgb2YgdGhpcyBvcGVyYXRpb24uIEFzIGEgcmVzdWx0IHRoaXMgb3BlcmF0aW9uIGNhbiBiZSBwcm9ibGVtYXRpY1xyXG4gIHVubGVzcyB5b3UgYXJlIGNlcnRhaW4gdGhhdCB0aGUgZW50aXR5IGJlaW5nIG1hcmtlZCAnQWRkZWQnIGRvZXMgbm90IGFscmVhZHkgZXhpc3QgaW4gdGhlIGRhdGFiYXNlIGFuZCBkb2VzIG5vdCBoYXZlIGFuIGF1dG9nZW5lcmF0ZWQga2V5LlxyXG4gIFRoZSBzYW1lIG9wZXJhdGlvbiBjYW4gYmUgcGVyZm9ybWVkIGJ5IGNhbGxpbmcgW1tFbnRpdHlBc3BlY3Quc2V0RW50aXR5U3RhdGVdXS5cclxuICA+ICAgICAgLy8gYXNzdW1lIG9yZGVyIGlzIGFuIG9yZGVyIGVudGl0eSBhdHRhY2hlZCB0byBhbiBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICBvcmRlci5lbnRpdHlBc3BlY3Quc2V0QWRkZWQoKTtcclxuICA+ICAgICAgLy8gVGhlICdvcmRlcicgZW50aXR5IHdpbGwgbm93IGJlIGluIGFuICdBZGRlZCcgc3RhdGUuXHJcbiAgKiovXHJcbiAgc2V0QWRkZWQoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5zZXRFbnRpdHlTdGF0ZShFbnRpdHlTdGF0ZS5BZGRlZCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBTZXRzIHRoZSBlbnRpdHkgdG8gYW4gRW50aXR5U3RhdGUgb2YgJ1VuY2hhbmdlZCcuICBUaGlzIGlzIGFsc28gdGhlIGVxdWl2YWxlbnQgb2YgY2FsbGluZyBbW0VudGl0eUFzcGVjdC5hY2NlcHRDaGFuZ2VzXV0uXHJcbiAgVGhlIHNhbWUgb3BlcmF0aW9uIGNhbiBiZSBwZXJmb3JtZWQgYnkgY2FsbGluZyBbW0VudGl0eUFzcGVjdC5zZXRFbnRpdHlTdGF0ZV1dLlxyXG4gID4gICAgICAvLyBhc3N1bWUgb3JkZXIgaXMgYW4gb3JkZXIgZW50aXR5IGF0dGFjaGVkIHRvIGFuIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgIG9yZGVyLmVudGl0eUFzcGVjdC5zZXRVbmNoYW5nZWQoKTtcclxuICA+ICAgICAgLy8gVGhlICdvcmRlcicgZW50aXR5IHdpbGwgbm93IGJlIGluIGFuICdVbmNoYW5nZWQnIHN0YXRlIHdpdGggYW55IGNoYW5nZXMgY29tbWl0dGVkLlxyXG4gICoqL1xyXG4gIHNldFVuY2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcclxuICAgIHJldHVybiB0aGlzLnNldEVudGl0eVN0YXRlKEVudGl0eVN0YXRlLlVuY2hhbmdlZCk7XHJcbiAgfTtcclxuXHJcblxyXG4gIC8qKlxyXG4gIFNldHMgdGhlIGVudGl0eSB0byBhbiBFbnRpdHlTdGF0ZSBvZiAnTW9kaWZpZWQnLiAgVGhpcyBjYW4gYWxzbyBiZSBhY2hpZXZlZCBieSBjaGFuZ2luZyB0aGUgdmFsdWUgb2YgYW55IHByb3BlcnR5IG9uIGFuICdVbmNoYW5nZWQnIGVudGl0eS5cclxuICBUaGUgc2FtZSBvcGVyYXRpb24gY2FuIGJlIHBlcmZvcm1lZCBieSBjYWxsaW5nIFtbRW50aXR5QXNwZWN0LnNldEVudGl0eVN0YXRlXV0uXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBvcmRlciBpcyBhbiBvcmRlciBlbnRpdHkgYXR0YWNoZWQgdG8gYW4gRW50aXR5TWFuYWdlci5cclxuICA+ICAgICAgb3JkZXIuZW50aXR5QXNwZWN0LnNldE1vZGlmaWVkKCk7XHJcbiAgPiAgICAgIC8vIFRoZSAnb3JkZXInIGVudGl0eSB3aWxsIG5vdyBiZSBpbiBhICdNb2RpZmllZCcgc3RhdGUuXHJcbiAgKiovXHJcbiAgc2V0TW9kaWZpZWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5zZXRFbnRpdHlTdGF0ZShFbnRpdHlTdGF0ZS5Nb2RpZmllZCk7XHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgU2V0cyB0aGUgZW50aXR5IHRvIGFuIEVudGl0eVN0YXRlIG9mICdEZWxldGVkJy4gIFRoaXMgYm90aCBtYXJrcyB0aGUgZW50aXR5IGFzIGJlaW5nIHNjaGVkdWxlZCBmb3IgZGVsZXRpb24gZHVyaW5nIHRoZSBuZXh0ICdTYXZlJyBjYWxsXHJcbiAgYnV0IGFsc28gcmVtb3ZlcyB0aGUgZW50aXR5IGZyb20gYWxsIG9mIGl0cyByZWxhdGVkIGVudGl0aWVzLiAgSWYgdGhlIGN1cnJlbnQgZW50aXR5U3RhdGUgaXMgJ0FkZGVkJywgdGhlbiBgc2V0RGVsZXRlZCgpYCB3aWxsIG1hcmsgaXQgJ0RldGFjaGVkJ1xyXG4gIFRoZSBzYW1lIG9wZXJhdGlvbiBjYW4gYmUgcGVyZm9ybWVkIGJ5IGNhbGxpbmcgW1tFbnRpdHlBc3BlY3Quc2V0RW50aXR5U3RhdGVdXS5cclxuICA+ICAgICAgLy8gYXNzdW1lIG9yZGVyIGlzIGFuIG9yZGVyIGVudGl0eSBhdHRhY2hlZCB0byBhbiBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICBvcmRlci5lbnRpdHlBc3BlY3Quc2V0RGVsZXRlZCgpO1xyXG4gID4gICAgICAvLyBUaGUgJ29yZGVyJyBlbnRpdHkgd2lsbCBub3cgYmUgaW4gYSAnRGVsZXRlZCcgc3RhdGUgYW5kIGl0IHdpbGwgbm8gbG9uZ2VyIGhhdmUgYW55ICdyZWxhdGVkJyBlbnRpdGllcy5cclxuICAqKi9cclxuICBzZXREZWxldGVkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuc2V0RW50aXR5U3RhdGUoRW50aXR5U3RhdGUuRGVsZXRlZCk7XHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgU2V0cyB0aGUgZW50aXR5IHRvIGFuIEVudGl0eVN0YXRlIG9mICdEZXRhY2hlZCcuICBUaGlzIHJlbW92ZXMgdGhlIGVudGl0eSBmcm9tIGFsbCBvZiBpdHMgcmVsYXRlZCBlbnRpdGllcywgYnV0IGRvZXMgTk9UIGNoYW5nZSB0aGUgRW50aXR5U3RhdGUgb2YgYW55IGV4aXN0aW5nIGVudGl0aWVzLlxyXG4gIFRoZSBzYW1lIG9wZXJhdGlvbiBjYW4gYmUgcGVyZm9ybWVkIGJ5IGNhbGxpbmcgW1tFbnRpdHlBc3BlY3Quc2V0RW50aXR5U3RhdGVdXS5cclxuICA+ICAgICAgLy8gYXNzdW1lIG9yZGVyIGlzIGFuIG9yZGVyIGVudGl0eSBhdHRhY2hlZCB0byBhbiBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICBvcmRlci5lbnRpdHlBc3BlY3Quc2V0RGV0YWNoZWQoKTtcclxuICA+ICAgICAgLy8gVGhlICdvcmRlcicgZW50aXR5IHdpbGwgbm93IGJlIGluIGEgJ0RldGFjaGVkJyBzdGF0ZSBhbmQgaXQgd2lsbCBubyBsb25nZXIgaGF2ZSBhbnkgJ3JlbGF0ZWQnIGVudGl0aWVzLlxyXG4gICoqL1xyXG4gIHNldERldGFjaGVkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuc2V0RW50aXR5U3RhdGUoRW50aXR5U3RhdGUuRGV0YWNoZWQpO1xyXG4gIH07XHJcblxyXG4gIC8qKlxyXG4gIFNldHMgdGhlIGVudGl0eSB0byB0aGUgc3BlY2lmaWVkIEVudGl0eVN0YXRlLiBTZWUgYWxzbyAnc2V0VW5jaGFuZ2VkJywgJ3NldE1vZGlmaWVkJywgJ3NldERldGFjaGVkJywgZXRjLlxyXG4gID4gICAgICAvLyBhc3N1bWUgb3JkZXIgaXMgYW4gb3JkZXIgZW50aXR5IGF0dGFjaGVkIHRvIGFuIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgIG9yZGVyLmVudGl0eUFzcGVjdC5zZXRFbnRpdHlTdGF0ZShFbnRpdHlTdGF0ZS5VbmNoYW5nZWQpO1xyXG4gID4gICAgICAvLyBUaGUgJ29yZGVyJyBlbnRpdHkgd2lsbCBub3cgYmUgaW4gYSAnVW5jaGFuZ2VkJyBzdGF0ZS5cclxuICAqKi9cclxuICBzZXRFbnRpdHlTdGF0ZShlbnRpdHlTdGF0ZTogRW50aXR5U3RhdGUpIHtcclxuICAgIGlmICh0aGlzLmVudGl0eVN0YXRlID09PSBlbnRpdHlTdGF0ZSkgcmV0dXJuIGZhbHNlO1xyXG4gICAgdGhpcy5fY2hlY2tPcGVyYXRpb24oXCJzZXRFbnRpdHlTdGF0ZVwiKTtcclxuICAgIGlmICh0aGlzLmVudGl0eVN0YXRlLmlzRGV0YWNoZWQoKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJZb3UgY2Fubm90IHNldCB0aGUgJ2VudGl0eVN0YXRlJyBvZiBhbiBlbnRpdHkgd2hlbiBpdCBpcyBkZXRhY2hlZCAtIGV4Y2VwdCBieSBmaXJzdCBhdHRhY2hpbmcgaXQgdG8gYW4gRW50aXR5TWFuYWdlclwiKTtcclxuICAgIH1cclxuICAgIGxldCBlbnRpdHkgPSB0aGlzLmVudGl0eSE7XHJcbiAgICBsZXQgZW0gPSB0aGlzLmVudGl0eU1hbmFnZXIhO1xyXG4gICAgbGV0IG5lZWRzU2F2ZSA9IHRydWU7XHJcbiAgICBpZiAoZW50aXR5U3RhdGUgPT09IEVudGl0eVN0YXRlLlVuY2hhbmdlZCkge1xyXG4gICAgICBjbGVhck9yaWdpbmFsVmFsdWVzKGVudGl0eSk7XHJcbiAgICAgIGRlbGV0ZSB0aGlzLmhhc1RlbXBLZXk7XHJcbiAgICAgIG5lZWRzU2F2ZSA9IGZhbHNlO1xyXG4gICAgfSBlbHNlIGlmIChlbnRpdHlTdGF0ZSA9PT0gRW50aXR5U3RhdGUuQWRkZWQpIHtcclxuICAgICAgY2xlYXJPcmlnaW5hbFZhbHVlcyhlbnRpdHkpO1xyXG4gICAgICAvLyBUT0RPOiBtb3JlIHRvIGRvIGhlcmUuLi4gbGlrZSByZWdlbmVyYXRpbmcga2V5ID8/P1xyXG4gICAgfSBlbHNlIGlmIChlbnRpdHlTdGF0ZSA9PT0gRW50aXR5U3RhdGUuRGVsZXRlZCkge1xyXG4gICAgICBpZiAodGhpcy5lbnRpdHlTdGF0ZS5pc0FkZGVkKCkpIHtcclxuICAgICAgICAvLyB0dXJuIGl0IGludG8gYSBkZXRhY2ggYW5kIGV4aXQgZWFybHlcclxuICAgICAgICB0aGlzLnNldEVudGl0eVN0YXRlKEVudGl0eVN0YXRlLkRldGFjaGVkKTtcclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBUT0RPOiB0aGluayBhYm91dCBjYXNjYWRlIGRlbGV0ZXNcclxuICAgICAgICAvLyBlbnRpdHlTdGF0ZSBuZWVkcyB0byBiZSBzZXQgaXQgZWFybHkgaW4gdGhpcyBvbmUgY2FzZSB0byBpbnN1cmUgdGhhdCBmaydzIGFyZSBub3QgY2xlYXJlZC5cclxuICAgICAgICB0aGlzLmVudGl0eVN0YXRlID0gRW50aXR5U3RhdGUuRGVsZXRlZDtcclxuICAgICAgICByZW1vdmVGcm9tUmVsYXRpb25zKGVudGl0eSwgRW50aXR5U3RhdGUuRGVsZXRlZCk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSBpZiAoZW50aXR5U3RhdGUgPT09IEVudGl0eVN0YXRlLk1vZGlmaWVkKSB7XHJcbiAgICAgIC8vIG5vdGhpbmcgZXh0cmEgbmVlZGVkXHJcbiAgICB9IGVsc2UgaWYgKGVudGl0eVN0YXRlID09PSBFbnRpdHlTdGF0ZS5EZXRhY2hlZCkge1xyXG4gICAgICBsZXQgZ3JvdXAgPSB0aGlzLmVudGl0eUdyb3VwO1xyXG4gICAgICAvLyBubyBncm91cCA9PT0gYWxyZWFkeSBkZXRhY2hlZC5cclxuICAgICAgaWYgKCFncm91cCkgcmV0dXJuIGZhbHNlO1xyXG4gICAgICBncm91cC5kZXRhY2hFbnRpdHkoZW50aXR5KTtcclxuICAgICAgLy8gbmVlZHMgdG8gb2NjdXIgZWFybHkgaGVyZSAtIHNvIHRoaXMgSVMgZGVsaWJlcmF0ZWx5IHJlZHVuZGVudCB3aXRoIHRoZSBzYW1lIGNvZGUgbGF0ZXIgaW4gdGhpcyBtZXRob2QuXHJcbiAgICAgIHRoaXMuZW50aXR5U3RhdGUgPSBlbnRpdHlTdGF0ZTtcclxuICAgICAgcmVtb3ZlRnJvbVJlbGF0aW9ucyhlbnRpdHksIEVudGl0eVN0YXRlLkRldGFjaGVkKTtcclxuICAgICAgdGhpcy5fZGV0YWNoKCk7XHJcbiAgICAgIGVtLmVudGl0eUNoYW5nZWQucHVibGlzaCh7IGVudGl0eUFjdGlvbjogRW50aXR5QWN0aW9uLkRldGFjaCwgZW50aXR5OiBlbnRpdHkgfSk7XHJcbiAgICAgIG5lZWRzU2F2ZSA9IGZhbHNlO1xyXG4gICAgfVxyXG4gICAgdGhpcy5lbnRpdHlTdGF0ZSA9IGVudGl0eVN0YXRlO1xyXG4gICAgZW0uX25vdGlmeVN0YXRlQ2hhbmdlKGVudGl0eSwgbmVlZHNTYXZlKTtcclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgbG9hZE5hdmlnYXRpb25Qcm9wZXJ0eShuYXZpZ2F0aW9uUHJvcGVydHk6IHN0cmluZywgY2FsbGJhY2s/OiBRdWVyeVN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaz86IFF1ZXJ5RXJyb3JDYWxsYmFjayk6IFByb21pc2U8UXVlcnlSZXN1bHQ+O1xyXG4gIGxvYWROYXZpZ2F0aW9uUHJvcGVydHkobmF2aWdhdGlvblByb3BlcnR5OiBOYXZpZ2F0aW9uUHJvcGVydHksIGNhbGxiYWNrPzogUXVlcnlTdWNjZXNzQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s/OiBRdWVyeUVycm9yQ2FsbGJhY2spOiBQcm9taXNlPFF1ZXJ5UmVzdWx0PjtcclxuICAvKipcclxuICBQZXJmb3JtcyBhIHF1ZXJ5IGZvciB0aGUgdmFsdWUgb2YgYSBzcGVjaWZpZWQgW1tOYXZpZ2F0aW9uUHJvcGVydHldXS4gX19Bc3luY19fXHJcbiAgPiAgICAgIGVtcC5lbnRpdHlBc3BlY3QubG9hZE5hdmlnYXRpb25Qcm9wZXJ0eShcIk9yZGVyc1wiKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7XHJcbiAgPiAgICAgICAgICB2YXIgb3JkZXJzID0gZGF0YS5yZXN1bHRzO1xyXG4gID4gICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXhjZXB0aW9uKSB7XHJcbiAgPiAgICAgICAgICAvLyBoYW5kbGUgZXhjZXB0aW9uIGhlcmU7XHJcbiAgPiAgICAgIH0pO1xyXG4gIEBwYXJhbSBuYXZpZ2F0aW9uUHJvcGVydHkgLSBUaGUgTmF2aWdhdGlvblByb3BlcnR5IG9yIHRoZSBuYW1lIG9mIHRoZSBOYXZpZ2F0aW9uUHJvcGVydHkgdG8gJ2xvYWQnLlxyXG4gIEBwYXJhbSBjYWxsYmFjayAtIEZ1bmN0aW9uIHRvIGNhbGwgb24gc3VjY2Vzcy5cclxuICBAcGFyYW0gZXJyb3JDYWxsYmFjayAtIEZ1bmN0aW9uIHRvIGNhbGwgb24gZmFpbHVyZS5cclxuICBAcmV0dXJuIFByb21pc2Ugd2l0aCBzaGFwZVxyXG4gICAgLSByZXN1bHRzIHtBcnJheSBvZiBFbnRpdHl9XHJcbiAgICAtIHF1ZXJ5IHtFbnRpdHlRdWVyeX0gVGhlIG9yaWdpbmFsIHF1ZXJ5XHJcbiAgICAtIGh0dHBSZXNwb25zZSB7aHR0cFJlc3BvbnNlfSBUaGUgSHR0cFJlc3BvbnNlIHJldHVybmVkIGZyb20gdGhlIHNlcnZlci5cclxuICAqKi9cclxuICBsb2FkTmF2aWdhdGlvblByb3BlcnR5KG5hdmlnYXRpb25Qcm9wZXJ0eTogTmF2aWdhdGlvblByb3BlcnR5IHwgc3RyaW5nLCBjYWxsYmFjazogUXVlcnlTdWNjZXNzQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s6IFF1ZXJ5RXJyb3JDYWxsYmFjaykge1xyXG4gICAgbGV0IGVudGl0eSA9IHRoaXMuZW50aXR5ITtcclxuICAgIGxldCBuYXZQcm9wZXJ0eSA9IGVudGl0eS5lbnRpdHlUeXBlLl9jaGVja05hdlByb3BlcnR5KG5hdmlnYXRpb25Qcm9wZXJ0eSk7XHJcbiAgICBsZXQgcXVlcnkgPSBFbnRpdHlRdWVyeS5mcm9tRW50aXR5TmF2aWdhdGlvbihlbnRpdHksIG5hdlByb3BlcnR5KTtcclxuICAgIC8vIHJldHVybiBlbnRpdHkuZW50aXR5QXNwZWN0LmVudGl0eU1hbmFnZXIuZXhlY3V0ZVF1ZXJ5KHF1ZXJ5LCBjYWxsYmFjaywgZXJyb3JDYWxsYmFjayk7XHJcbiAgICBsZXQgcHJvbWlzZSA9IGVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5TWFuYWdlciEuZXhlY3V0ZVF1ZXJ5KHF1ZXJ5KTtcclxuXHJcbiAgICByZXR1cm4gcHJvbWlzZS50aGVuKChkYXRhKSA9PiB7XHJcbiAgICAgIHRoaXMuX21hcmtBc0xvYWRlZChuYXZQcm9wZXJ0eS5uYW1lKTtcclxuICAgICAgaWYgKGNhbGxiYWNrKSBjYWxsYmFjayhkYXRhKTtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKTtcclxuICAgIH0sIChlcnJvcikgPT4ge1xyXG4gICAgICBpZiAoZXJyb3JDYWxsYmFjaykgZXJyb3JDYWxsYmFjayhlcnJvcik7XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XHJcbiAgICB9KTtcclxuXHJcbiAgfVxyXG5cclxuICAvKipcclxuICBNYXJrcyB0aGlzIG5hdmlnYXRpb25Qcm9wZXJ0eSBvbiB0aGlzIGVudGl0eSBhcyBhbHJlYWR5IGhhdmluZyBiZWVuIGxvYWRlZC5cclxuICA+ICAgICAgZW1wLmVudGl0eUFzcGVjdC5tYXJrTmF2aWdhdGlvblByb3BlcnR5QXNMb2FkZWQoXCJPcmRlcnNcIik7XHJcbiAgQHBhcmFtIG5hdmlnYXRpb25Qcm9wZXJ0eSAtIFRoZSBOYXZpZ2F0aW9uUHJvcGVydHkgb3IgbmFtZSBvZiBOYXZpZ2F0aW9uUHJvcGVydHkgdG8gJ2xvYWQnLlxyXG4gICoqL1xyXG4gIG1hcmtOYXZpZ2F0aW9uUHJvcGVydHlBc0xvYWRlZChuYXZpZ2F0aW9uUHJvcGVydHk6IE5hdmlnYXRpb25Qcm9wZXJ0eSB8IHN0cmluZykge1xyXG4gICAgaWYgKCF0aGlzLmVudGl0eSkgcmV0dXJuO1xyXG4gICAgbGV0IG5hdlByb3BlcnR5ID0gdGhpcy5lbnRpdHkuZW50aXR5VHlwZS5fY2hlY2tOYXZQcm9wZXJ0eShuYXZpZ2F0aW9uUHJvcGVydHkpO1xyXG4gICAgdGhpcy5fbWFya0FzTG9hZGVkKG5hdlByb3BlcnR5Lm5hbWUpO1xyXG4gIH1cclxuXHJcbiAgaXNOYXZpZ2F0aW9uUHJvcGVydHlMb2FkZWQobmF2aWdhdGlvblByb3BlcnR5OiBzdHJpbmcpOiBib29sZWFuO1xyXG4gIGlzTmF2aWdhdGlvblByb3BlcnR5TG9hZGVkKG5hdmlnYXRpb25Qcm9wZXJ0eTogTmF2aWdhdGlvblByb3BlcnR5KTogYm9vbGVhbjtcclxuICAvKipcclxuICBEZXRlcm1pbmVzIHdoZXRoZXIgYSBuYXZpZ2F0aW9uUHJvcGVydHkgb24gdGhpcyBlbnRpdHkgaGFzIGFscmVhZHkgYmVlbiBsb2FkZWQuXHJcblxyXG4gIEEgbmF2aWdhdGlvbiBwcm9wZXJ0eSBpcyBjb25zaWRlcmVkIGxvYWRlZCB3aGVuIGFueSBvZiB0aGUgZm9sbG93aW5nIHRocmVlIGNvbmRpdGlvbnMgYXBwbGllczpcclxuXHJcbiAgICAxLiBJdCB3YXMgZmV0Y2hlZCBmcm9tIHRoZSBiYWNrZW5kIHNlcnZlci5cclxuICAgICAgICA8YnIvPiAgIFRoaXMgY2FuIGJlIHRoZSByZXN1bHQgb2YgYW4gZXhwYW5kIHF1ZXJ5IG9yIGEgY2FsbCB0byB0aGUgW1tFbnRpdHlBc3BlY3QubG9hZE5hdmlnYXRpb25Qcm9wZXJ0eV1dIG1ldGhvZC5cclxuICAgICAgICA8YnIvPiAgIE5vdGUgdGhhdCBldmVuIGlmIHRoZSBmZXRjaCByZXR1cm5zIG5vdGhpbmcgdGhlIHByb3BlcnR5IGlzIHN0aWxsIG1hcmtlZCBhcyBsb2FkZWQgaW4gdGhpcyBjYXNlLlxyXG4gICAgMS4gVGhlIHByb3BlcnR5IGlzIHNjYWxhciBhbmQgaGFzIGJlZW4gc2V0IHRvIGEgbm9ubnVsbCB2YWx1ZS5cclxuICAgIDEuIFRoZSBbW0VudGl0eUFzcGVjdC5tYXJrTmF2aWdhdGlvblByb3BlcnR5QXNMb2FkZWRdXSB3YXMgY2FsbGVkLlxyXG4gIFxyXG4gID4gICAgIHZhciB3YXNMb2FkZWQgPSBlbXAuZW50aXR5QXNwZWN0LmlzTmF2aWdhdGlvblByb3BlcnR5TG9hZGVkKFwiT3JkZXJzXCIpO1xyXG4gIEBwYXJhbSBuYXZpZ2F0aW9uUHJvcGVydHkgLSBUaGUgTmF2aWdhdGlvblByb3BlcnR5IG9yIG5hbWUgb2YgTmF2aWdhdGlvblByb3BlcnR5IHRvICdsb2FkJy5cclxuICAqKi9cclxuICBpc05hdmlnYXRpb25Qcm9wZXJ0eUxvYWRlZChuYXZpZ2F0aW9uUHJvcGVydHk6IE5hdmlnYXRpb25Qcm9wZXJ0eSB8IHN0cmluZykge1xyXG4gICAgaWYgKCF0aGlzLmVudGl0eSkgcmV0dXJuO1xyXG4gICAgbGV0IG5hdlByb3BlcnR5ID0gdGhpcy5lbnRpdHkuZW50aXR5VHlwZS5fY2hlY2tOYXZQcm9wZXJ0eShuYXZpZ2F0aW9uUHJvcGVydHkpO1xyXG4gICAgaWYgKG5hdlByb3BlcnR5LmlzU2NhbGFyICYmIHRoaXMuZW50aXR5LmdldFByb3BlcnR5KG5hdlByb3BlcnR5Lm5hbWUpICE9IG51bGwpIHtcclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5fbG9hZGVkTnBzICYmIHRoaXMuX2xvYWRlZE5wcy5pbmRleE9mKG5hdlByb3BlcnR5Lm5hbWUpID49IDA7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfbWFya0FzTG9hZGVkKG5hdlByb3BOYW1lOiBzdHJpbmcpIHtcclxuICAgIHRoaXMuX2xvYWRlZE5wcyA9IHRoaXMuX2xvYWRlZE5wcyB8fCBbXTtcclxuICAgIGNvcmUuYXJyYXlBZGRJdGVtVW5pcXVlKHRoaXMuX2xvYWRlZE5wcywgbmF2UHJvcE5hbWUpO1xyXG4gIH1cclxuXHJcblxyXG4gIC8qKlxyXG4gIFBlcmZvcm1zIHZhbGlkYXRpb24gb24gdGhlIGVudGl0eSwgYW55IGVycm9ycyBlbmNvdW50ZXJlZCBkdXJpbmcgdGhlIHZhbGlkYXRpb24gYXJlIGF2YWlsYWJsZSB2aWEgdGhlXHJcbiAgW1tFbnRpdHlBc3BlY3QuZ2V0VmFsaWRhdGlvbkVycm9yc11dIG1ldGhvZC4gVmFsaWRhdGluZyBhbiBlbnRpdHkgbWVhbnMgZXhlY3V0aW5nXHJcbiAgYWxsIG9mIHRoZSB2YWxpZGF0b3JzIG9uIGJvdGggdGhlIGVudGl0eSBpdHNlbGYgYXMgd2VsbCBhcyB0aG9zZSBvbiBlYWNoIG9mIGl0cyBwcm9wZXJ0aWVzLlxyXG4gID4gICAgICAvLyBhc3N1bWUgb3JkZXIgaXMgYW4gb3JkZXIgZW50aXR5IGF0dGFjaGVkIHRvIGFuIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgIHZhciBpc09rID0gb3JkZXIuZW50aXR5QXNwZWN0LnZhbGlkYXRlRW50aXR5KCk7XHJcbiAgPiAgICAgIC8vIGlzT2sgd2lsbCBiZSAndHJ1ZScgaWYgdGhlcmUgYXJlIG5vIGVycm9ycyBvbiB0aGUgZW50aXR5LlxyXG4gID4gICAgICBpZiAoIWlzT2spIHtcclxuICA+ICAgICAgICAgIHZhciBlcnJvcnMgPSBvcmRlci5lbnRpdHlBc3BlY3QuZ2V0VmFsaWRhdGlvbkVycm9ycygpO1xyXG4gID4gICAgICB9XHJcbiAgQHJldHVybiBXaGV0aGVyIHRoZSBlbnRpdHkgcGFzc2VkIHZhbGlkYXRpb24uXHJcbiAgKiovXHJcbiAgdmFsaWRhdGVFbnRpdHkoKSB7XHJcbiAgICBsZXQgb2sgPSB0cnVlO1xyXG4gICAgdGhpcy5fcHJvY2Vzc1ZhbGlkYXRpb25PcEFuZFB1Ymxpc2goZnVuY3Rpb24gKHRoYXQ6IGFueSkge1xyXG4gICAgICBvayA9IHZhbGlkYXRlVGFyZ2V0KHRoYXQuZW50aXR5KTtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIG9rO1xyXG4gIH1cclxuXHJcbiAgdmFsaWRhdGVQcm9wZXJ0eShwcm9wZXJ0eTogc3RyaW5nLCBjb250ZXh0PzogYW55KTogYm9vbGVhbjtcclxuICB2YWxpZGF0ZVByb3BlcnR5KHByb3BlcnR5OiBEYXRhUHJvcGVydHksIGNvbnRleHQ/OiBhbnkpOiBib29sZWFuO1xyXG4gIHZhbGlkYXRlUHJvcGVydHkocHJvcGVydHk6IE5hdmlnYXRpb25Qcm9wZXJ0eSwgY29udGV4dD86IGFueSk6IGJvb2xlYW47XHJcbiAgLyoqXHJcbiAgUGVyZm9ybXMgdmFsaWRhdGlvbiBvbiBhIHNwZWNpZmljIHByb3BlcnR5IG9mIHRoaXMgZW50aXR5LCBhbnkgZXJyb3JzIGVuY291bnRlcmVkIGR1cmluZyB0aGUgdmFsaWRhdGlvbiBhcmUgYXZhaWxhYmxlIHZpYSB0aGVcclxuICBbW0VudGl0eUFzcGVjdC5nZXRWYWxpZGF0aW9uRXJyb3JzXV0gbWV0aG9kLiBWYWxpZGF0aW5nIGEgcHJvcGVydHkgbWVhbnMgZXhlY3V0aW5nXHJcbiAgYWxsIG9mIHRoZSB2YWxpZGF0b3JzIG9uIHRoZSBzcGVjaWZpZWQgcHJvcGVydHkuICBUaGlzIGNhbGwgaXMgYWxzbyBtYWRlIGF1dG9tYXRpY2FsbHkgYW55dGltZSBhIHByb3BlcnR5XHJcbiAgb2YgYW4gZW50aXR5IGlzIGNoYW5nZWQuXHJcbiAgPiAgICAgIC8vIGFzc3VtZSBvcmRlciBpcyBhbiBvcmRlciBlbnRpdHkgYXR0YWNoZWQgdG8gYW4gRW50aXR5TWFuYWdlci5cclxuICA+ICAgICAgdmFyIGlzT2sgPSBvcmRlci5lbnRpdHlBc3BlY3QudmFsaWRhdGVQcm9wZXJ0eShcIk9yZGVyXCIpO1xyXG5cclxuICBvclxyXG4gID4gICAgICB2YXIgb3JkZXJEYXRlUHJvcGVydHkgPSBvcmRlci5lbnRpdHlUeXBlLmdldFByb3BlcnR5KFwiT3JkZXJEYXRlXCIpO1xyXG4gID4gICAgICB2YXIgaXNPayA9IG9yZGVyLmVudGl0eUFzcGVjdC52YWxpZGF0ZVByb3BlcnR5KE9yZGVyRGF0ZVByb3BlcnR5KTtcclxuICBAcGFyYW0gcHJvcGVydHkgLSBUaGUgW1tEYXRhUHJvcGVydHldXSBvciBbW05hdmlnYXRpb25Qcm9wZXJ0eV1dIHRvIHZhbGlkYXRlIG9yIGEgc3RyaW5nIFxyXG4gIHdpdGggdGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IG9yIGEgcHJvcGVydHkgcGF0aCB3aXRoIHRoZSBwYXRoIHRvIGEgcHJvcGVydHkgb2YgYSBjb21wbGV4IG9iamVjdC5cclxuICBAcGFyYW0gY29udGV4dCAtICBBIGNvbnRleHQgb2JqZWN0IHVzZWQgdG8gcGFzcyBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIHRvIGVhY2ggW1tWYWxpZGF0b3JdXS5cclxuICBAcmV0dXJuIFdoZXRoZXIgdGhlIGVudGl0eSBwYXNzZWQgdmFsaWRhdGlvbi5cclxuICAqKi9cclxuICB2YWxpZGF0ZVByb3BlcnR5KHByb3BlcnR5OiBFbnRpdHlQcm9wZXJ0eSB8IHN0cmluZywgY29udGV4dDogYW55KSB7XHJcbiAgICBsZXQgdmFsdWUgPSB0aGlzLmdldFByb3BlcnR5VmFsdWUocHJvcGVydHkpOyAvLyBwZXJmb3JtcyB2YWxpZGF0aW9uc1xyXG4gICAgaWYgKHZhbHVlICYmIHZhbHVlLmNvbXBsZXhBc3BlY3QpIHtcclxuICAgICAgcmV0dXJuIHZhbGlkYXRlVGFyZ2V0KHZhbHVlKTtcclxuICAgIH1cclxuICAgIGNvbnRleHQgPSBjb250ZXh0IHx8IHt9O1xyXG4gICAgY29udGV4dC5lbnRpdHkgPSB0aGlzLmVudGl0eTtcclxuICAgIGlmICh0eXBlb2YgcHJvcGVydHkgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgY29udGV4dC5wcm9wZXJ0eSA9IHRoaXMuZW50aXR5IS5lbnRpdHlUeXBlLmdldFByb3BlcnR5KHByb3BlcnR5LCB0cnVlKTtcclxuICAgICAgY29udGV4dC5wcm9wZXJ0eU5hbWUgPSBwcm9wZXJ0eTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnRleHQucHJvcGVydHkgPSBwcm9wZXJ0eTtcclxuICAgICAgY29udGV4dC5wcm9wZXJ0eU5hbWUgPSBwcm9wZXJ0eS5uYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLl92YWxpZGF0ZVByb3BlcnR5KHZhbHVlLCBjb250ZXh0KTtcclxuICB9XHJcblxyXG4gIGdldFZhbGlkYXRpb25FcnJvcnMoKTogVmFsaWRhdGlvbkVycm9yW107XHJcbiAgZ2V0VmFsaWRhdGlvbkVycm9ycyhwcm9wZXJ0eTogc3RyaW5nKTogVmFsaWRhdGlvbkVycm9yW107XHJcbiAgZ2V0VmFsaWRhdGlvbkVycm9ycyhwcm9wZXJ0eTogRW50aXR5UHJvcGVydHkpOiBWYWxpZGF0aW9uRXJyb3JbXTtcclxuICAvKipcclxuICBSZXR1cm5zIHRoZSB2YWxpZGF0aW9uIGVycm9ycyBhc3NvY2lhdGVkIHdpdGggZWl0aGVyIHRoZSBlbnRpcmUgZW50aXR5IG9yIGFueSBzcGVjaWZpZWQgcHJvcGVydHkuXHJcbiAgXHJcbiAgVGhpcyBtZXRob2QgY2FuIHJldHVybiBhbGwgb2YgdGhlIGVycm9ycyBmb3IgYW4gRW50aXR5XHJcbiAgPiAgICAgIC8vIGFzc3VtZSBvcmRlciBpcyBhbiBvcmRlciBlbnRpdHkgYXR0YWNoZWQgdG8gYW4gRW50aXR5TWFuYWdlci5cclxuICA+ICAgICAgdmFyIHZhbEVycm9ycyA9IG9yZGVyLmVudGl0eUFzcGVjdC5nZXRWYWxpZGF0aW9uRXJyb3JzKCk7XHJcblxyXG4gIGFzIHdlbGwgYXMgdGhvc2UgZm9yIGp1c3QgYSBzcGVjaWZpYyBwcm9wZXJ0eS5cclxuICA+ICAgICAgLy8gYXNzdW1lIG9yZGVyIGlzIGFuIG9yZGVyIGVudGl0eSBhdHRhY2hlZCB0byBhbiBFbnRpdHlNYW5hZ2VyLlxyXG4gID4gICAgICB2YXIgb3JkZXJEYXRlRXJyb3JzID0gb3JkZXIuZW50aXR5QXNwZWN0LmdldFZhbGlkYXRpb25FcnJvcnMoXCJPcmRlckRhdGVcIik7XHJcblxyXG4gIHdoaWNoIGNhbiBhbHNvIGJlIGV4cHJlc3NlZCBhc1xyXG4gID4gICAgICAvLyBhc3N1bWUgb3JkZXIgaXMgYW4gb3JkZXIgZW50aXR5IGF0dGFjaGVkIHRvIGFuIEVudGl0eU1hbmFnZXIuXHJcbiAgPiAgICAgIHZhciBvcmRlckRhdGVQcm9wZXJ0eSA9IG9yZGVyLmVudGl0eVR5cGUuZ2V0UHJvcGVydHkoXCJPcmRlckRhdGVcIik7XHJcbiAgPiAgICAgIHZhciBvcmRlckRhdGVFcnJvcnMgPSBvcmRlci5lbnRpdHlBc3BlY3QuZ2V0VmFsaWRhdGlvbkVycm9ycyhvcmRlckRhdGVQcm9wZXJ0eSk7XHJcbiAgQHBhcmFtIHByb3BlcnR5IC0gVGhlIHByb3BlcnR5IGZvciB3aGljaCB2YWxpZGF0aW9uIGVycm9ycyBzaG91bGQgYmUgcmV0cmlldmVkLlxyXG4gIElmIG9taXR0ZWQsIGFsbCBvZiB0aGUgdmFsaWRhdGlvbiBlcnJvcnMgZm9yIHRoaXMgZW50aXR5IHdpbGwgYmUgcmV0dXJuZWQuXHJcbiAgQHJldHVybiBBIGFycmF5IG9mIHZhbGlkYXRpb24gZXJyb3JzLlxyXG4gICoqL1xyXG4gIGdldFZhbGlkYXRpb25FcnJvcnMocHJvcGVydHk/OiBEYXRhUHJvcGVydHkgfCBOYXZpZ2F0aW9uUHJvcGVydHkgfCBzdHJpbmcpIHtcclxuICAgIGFzc2VydFBhcmFtKHByb3BlcnR5LCBcInByb3BlcnR5XCIpLmlzT3B0aW9uYWwoKS5pc0VudGl0eVByb3BlcnR5KCkub3IoKS5pc1N0cmluZygpLmNoZWNrKCk7XHJcbiAgICBsZXQgcmVzdWx0ID0gY29yZS5nZXRPd25Qcm9wZXJ0eVZhbHVlcyh0aGlzLl92YWxpZGF0aW9uRXJyb3JzKTtcclxuICAgIGlmIChwcm9wZXJ0eSkge1xyXG4gICAgICBsZXQgcHJvcGVydHlOYW1lID0gdHlwZW9mIChwcm9wZXJ0eSkgPT09ICdzdHJpbmcnID8gcHJvcGVydHkgOiBwcm9wZXJ0eS5uYW1lO1xyXG4gICAgICByZXN1bHQgPSByZXN1bHQuZmlsdGVyKGZ1bmN0aW9uICh2ZTogVmFsaWRhdGlvbkVycm9yKSB7XHJcbiAgICAgICAgcmV0dXJuIHZlLnByb3BlcnR5ICYmICh2ZS5wcm9wZXJ0eS5uYW1lID09PSBwcm9wZXJ0eU5hbWUgfHwgKHByb3BlcnR5TmFtZS5pbmRleE9mKFwiLlwiKSAhPT0gLTEgJiYgdmUucHJvcGVydHlOYW1lID09PSBwcm9wZXJ0eU5hbWUpKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgQWRkcyBhIHZhbGlkYXRpb24gZXJyb3IuXHJcbiAgKiovXHJcbiAgYWRkVmFsaWRhdGlvbkVycm9yKHZhbGlkYXRpb25FcnJvcjogVmFsaWRhdGlvbkVycm9yKSB7XHJcbiAgICBhc3NlcnRQYXJhbSh2YWxpZGF0aW9uRXJyb3IsIFwidmFsaWRhdGlvbkVycm9yXCIpLmlzSW5zdGFuY2VPZihWYWxpZGF0aW9uRXJyb3IpLmNoZWNrKCk7XHJcbiAgICB0aGlzLl9wcm9jZXNzVmFsaWRhdGlvbk9wQW5kUHVibGlzaChmdW5jdGlvbiAodGhhdDogYW55KSB7XHJcbiAgICAgIHRoYXQuX2FkZFZhbGlkYXRpb25FcnJvcih2YWxpZGF0aW9uRXJyb3IpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICByZW1vdmVWYWxpZGF0aW9uRXJyb3IodmFsaWRhdGlvbkVycm9yOiBWYWxpZGF0aW9uRXJyb3IpOiB2b2lkO1xyXG4gIHJlbW92ZVZhbGlkYXRpb25FcnJvcih2YWxpZGF0aW9uS2V5OiBzdHJpbmcpOiB2b2lkO1xyXG4gIC8qKlxyXG4gIFJlbW92ZXMgYSB2YWxpZGF0aW9uIGVycm9yLlxyXG4gIEBwYXJhbSB2YWxpZGF0aW9uRXJyb3JPcktleSAtIEVpdGhlciBhIFZhbGlkYXRpb25FcnJvciBvciBhIFZhbGlkYXRpb25FcnJvciAna2V5JyB2YWx1ZVxyXG4gICoqL1xyXG4gIHJlbW92ZVZhbGlkYXRpb25FcnJvcih2YWxpZGF0aW9uRXJyb3JPcktleTogVmFsaWRhdGlvbkVycm9yIHwgc3RyaW5nKSB7XHJcbiAgICBhc3NlcnRQYXJhbSh2YWxpZGF0aW9uRXJyb3JPcktleSwgXCJ2YWxpZGF0aW9uRXJyb3JPcktleVwiKS5pc1N0cmluZygpLm9yKCkuaXNJbnN0YW5jZU9mKFZhbGlkYXRpb25FcnJvcikub3IoKS5pc0luc3RhbmNlT2YoVmFsaWRhdG9yKS5jaGVjaygpO1xyXG5cclxuICAgIGxldCBrZXkgPSAodHlwZW9mICh2YWxpZGF0aW9uRXJyb3JPcktleSkgPT09IFwic3RyaW5nXCIpID8gdmFsaWRhdGlvbkVycm9yT3JLZXkgOiB2YWxpZGF0aW9uRXJyb3JPcktleS5rZXk7XHJcbiAgICB0aGlzLl9wcm9jZXNzVmFsaWRhdGlvbk9wQW5kUHVibGlzaChmdW5jdGlvbiAodGhhdDogYW55KSB7XHJcbiAgICAgIHRoYXQuX3JlbW92ZVZhbGlkYXRpb25FcnJvcihrZXkpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICBSZW1vdmVzIGFsbCBvZiB0aGUgdmFsaWRhdGlvbiBlcnJvcnMgZm9yIGEgc3BlY2lmaWVkIGVudGl0eVxyXG4gICoqL1xyXG4gIGNsZWFyVmFsaWRhdGlvbkVycm9ycygpIHtcclxuICAgIHRoaXMuX3Byb2Nlc3NWYWxpZGF0aW9uT3BBbmRQdWJsaXNoKGZ1bmN0aW9uICh0aGF0OiBhbnkpIHtcclxuICAgICAgY29yZS5vYmplY3RGb3JFYWNoKHRoYXQuX3ZhbGlkYXRpb25FcnJvcnMsIGZ1bmN0aW9uIChrZXk6IHN0cmluZywgdmFsRXJyb3I6IFZhbGlkYXRpb25FcnJvcikge1xyXG4gICAgICAgIGlmICh2YWxFcnJvcikge1xyXG4gICAgICAgICAgZGVsZXRlIHRoYXQuX3ZhbGlkYXRpb25FcnJvcnNba2V5XTtcclxuICAgICAgICAgIHRoYXQuX3BlbmRpbmdWYWxpZGF0aW9uUmVzdWx0LnJlbW92ZWQucHVzaCh2YWxFcnJvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgICAgdGhhdC5oYXNWYWxpZGF0aW9uRXJyb3JzID0gIWNvcmUuaXNFbXB0eSh0aGF0Ll92YWxpZGF0aW9uRXJyb3JzKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgUmV0dXJucyBhbiBbW0VudGl0eUtleV1dIGZvciB0aGUgZW50aXR5IHBvaW50ZWQgdG8gYnkgdGhlIHNwZWNpZmllZCBzY2FsYXIgTmF2aWdhdGlvblByb3BlcnR5LlxyXG4gIFRoaXMgb25seSByZXR1cm5zIGFuIEVudGl0eUtleSBpZiB0aGUgY3VycmVudCBlbnRpdHkgaXMgYSAnY2hpbGQnIGVudGl0eSBhbG9uZyB0aGUgc3BlY2lmaWVkIE5hdmlnYXRpb25Qcm9wZXJ0eS4gXHJcbiAgaS5lLiBoYXMgYSBzaW5nbGUgcGFyZW50LlxyXG5cclxuICBAcGFyYW0gbmF2aWdhdGlvblByb3BlcnR5IC0gVGhlIFtbTmF2aWdhdGlvblByb3BlcnR5XV0gKCBwb2ludGluZyB0byBhIHBhcmVudCkuIFxyXG4gIEByZXR1cm5zIEVpdGhlciBhIHBhcmVudCBFbnRpdHlLZXkgaWYgdGhpcyBpcyBhICdjaGlsZCcgZW50aXR5IG9yIG51bGw7ICBcclxuICAqL1xyXG4gIGdldFBhcmVudEtleShuYXZpZ2F0aW9uUHJvcGVydHk6IE5hdmlnYXRpb25Qcm9wZXJ0eSkge1xyXG4gICAgaWYgKCF0aGlzLmVudGl0eSkgcmV0dXJuIG51bGw7XHJcbiAgICAvLyBUT0RPOiByZXZpZXcgdGhpcyAtIG5vdCBzdXJlIGFib3V0IHRoZSBjb21tZW50LlxyXG4gICAgLy8gTmF2aWdhdGlvblByb3BlcnR5IGRvZXNuJ3QgeWV0IGV4aXN0XHJcbiAgICAvLyBhc3NlcnRQYXJhbShuYXZpZ2F0aW9uUHJvcGVydHksIFwibmF2aWdhdGlvblByb3BlcnR5XCIpLmlzSW5zdGFuY2VPZihOYXZpZ2F0aW9uUHJvcGVydHkpLmNoZWNrKCk7XHJcbiAgICBsZXQgZmtOYW1lcyA9IG5hdmlnYXRpb25Qcm9wZXJ0eS5mb3JlaWduS2V5TmFtZXM7XHJcbiAgICBpZiAoZmtOYW1lcy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xyXG4gICAgbGV0IHRoYXQgPSB0aGlzO1xyXG4gICAgbGV0IGZrVmFsdWVzID0gZmtOYW1lcy5tYXAoZnVuY3Rpb24gKGZrbikge1xyXG4gICAgICByZXR1cm4gdGhhdC5lbnRpdHkhLmdldFByb3BlcnR5KGZrbik7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBuZXcgRW50aXR5S2V5KG5hdmlnYXRpb25Qcm9wZXJ0eS5lbnRpdHlUeXBlLCBma1ZhbHVlcyk7XHJcbiAgfVxyXG5cclxuICAvLyBUT0RPOiByZWZhY3RvciB0aGlzIGFuZCB0aGUgc3RhdGljIGdldFByb3BlcnR5UGF0aFZhbHVlLlxyXG4gIC8qKlxyXG4gIFJldHVybnMgdGhlIHZhbHVlIG9mIGEgc3BlY2lmaWVkIERhdGFQcm9wZXJ0eSBvciBOYXZpZ2F0aW9uUHJvcGVydHkgb3IgJ3Byb3BlcnR5IHBhdGgnLiAgXHJcbiAgKiovXHJcbiAgZ2V0UHJvcGVydHlWYWx1ZShwcm9wZXJ0eTogc3RyaW5nIHwgRGF0YVByb3BlcnR5IHwgTmF2aWdhdGlvblByb3BlcnR5KSB7XHJcbiAgICBhc3NlcnRQYXJhbShwcm9wZXJ0eSwgXCJwcm9wZXJ0eVwiKS5pc1N0cmluZygpLm9yKCkuaXNFbnRpdHlQcm9wZXJ0eSgpLmNoZWNrKCk7XHJcbiAgICBsZXQgdmFsdWU6IGFueTtcclxuICAgIGlmICh0eXBlb2YgKHByb3BlcnR5KSA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgbGV0IHByb3BOYW1lcyA9IHByb3BlcnR5LnRyaW0oKS5zcGxpdChcIi5cIik7XHJcbiAgICAgIGxldCBwcm9wTmFtZSA9IHByb3BOYW1lcy5zaGlmdCgpO1xyXG4gICAgICB2YWx1ZSA9IHRoaXMuZW50aXR5O1xyXG4gICAgICB2YWx1ZSA9IHZhbHVlLmdldFByb3BlcnR5KHByb3BOYW1lKTtcclxuICAgICAgd2hpbGUgKHByb3BOYW1lcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgcHJvcE5hbWUgPSBwcm9wTmFtZXMuc2hpZnQoKTtcclxuICAgICAgICB2YWx1ZSA9IHZhbHVlLmdldFByb3BlcnR5KHByb3BOYW1lKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKCEocHJvcGVydHkucGFyZW50VHlwZSBpbnN0YW5jZW9mIEVudGl0eVR5cGUpKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIHZhbGlkYXRlUHJvcGVydHkgbWV0aG9kIGRvZXMgbm90IGFjY2VwdCBhICdwcm9wZXJ0eScgcGFyYW1ldGVyIHdob3NlIHBhcmVudFR5cGUgaXMgYSBDb21wbGV4VHlwZTsgXCIgK1xyXG4gICAgICAgICAgXCJQYXNzIGEgJ3Byb3BlcnR5IHBhdGgnIHN0cmluZyBhcyB0aGUgJ3Byb3BlcnR5JyBwYXJhbWV0ZXIgaW5zdGVhZCBcIik7XHJcbiAgICAgIH1cclxuICAgICAgdmFsdWUgPSB0aGlzLmVudGl0eSEuZ2V0UHJvcGVydHkocHJvcGVydHkubmFtZSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdmFsdWU7XHJcbiAgfVxyXG5cclxuICAvLyBpbnRlcm5hbCBtZXRob2RzXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX2NoZWNrT3BlcmF0aW9uKG9wZXJhdGlvbk5hbWU6IHN0cmluZykge1xyXG4gICAgaWYgKHRoaXMuaXNCZWluZ1NhdmVkKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBwZXJmb3JtIGEgJ1wiICsgb3BlcmF0aW9uTmFtZSArIFwiJyBvbiBhbiBlbnRpdHkgdGhhdCBpcyBpbiB0aGUgcHJvY2VzcyBvZiBiZWluZyBzYXZlZFwiKTtcclxuICAgIH1cclxuICAgIC8vIGFsbG93cyBjaGFpbmluZ1xyXG4gICAgcmV0dXJuIHRoaXM7XHJcbiAgfVxyXG5cclxuICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICBfZGV0YWNoKCkge1xyXG4gICAgdGhpcy5lbnRpdHlHcm91cCA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuZW50aXR5TWFuYWdlciA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuZW50aXR5U3RhdGUgPSBFbnRpdHlTdGF0ZS5EZXRhY2hlZDtcclxuICAgIHRoaXMub3JpZ2luYWxWYWx1ZXMgPSB7fTtcclxuICAgIHRoaXMuX3ZhbGlkYXRpb25FcnJvcnMgPSB7fTtcclxuICAgIHRoaXMuaGFzVmFsaWRhdGlvbkVycm9ycyA9IGZhbHNlO1xyXG4gICAgdGhpcy52YWxpZGF0aW9uRXJyb3JzQ2hhbmdlZC5jbGVhcigpO1xyXG4gICAgdGhpcy5wcm9wZXJ0eUNoYW5nZWQuY2xlYXIoKTtcclxuXHJcbiAgfVxyXG5cclxuXHJcbiAgLy8gY2FsbGVkIGZyb20gZGVmYXVsdEludGVyY2VwdG9yLlxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIF92YWxpZGF0ZVByb3BlcnR5KHZhbHVlOiBhbnksIGNvbnRleHQ6IGFueSkge1xyXG4gICAgbGV0IG9rID0gdHJ1ZTtcclxuICAgIHRoaXMuX3Byb2Nlc3NWYWxpZGF0aW9uT3BBbmRQdWJsaXNoKGZ1bmN0aW9uICh0aGF0OiBhbnkpIHtcclxuICAgICAgY29udGV4dC5wcm9wZXJ0eS5nZXRBbGxWYWxpZGF0b3JzKCkuZm9yRWFjaChmdW5jdGlvbiAodmFsaWRhdG9yOiBWYWxpZGF0b3IpIHtcclxuICAgICAgICBvayA9IHZhbGlkYXRlKHRoYXQsIHZhbGlkYXRvciwgdmFsdWUsIGNvbnRleHQpICYmIG9rO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIG9rO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3Byb2Nlc3NWYWxpZGF0aW9uT3BBbmRQdWJsaXNoKHZhbGlkYXRpb25GbjogYW55KSB7XHJcbiAgICBpZiAodGhpcy5fcGVuZGluZ1ZhbGlkYXRpb25SZXN1bHQpIHtcclxuICAgICAgLy8gb25seSB0b3AgbGV2ZWwgcHJvY2Vzc1ZhbGlkYXRpb25zIGNhbGwgcHVibGlzaGVzXHJcbiAgICAgIHZhbGlkYXRpb25Gbih0aGlzKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgdGhpcy5fcGVuZGluZ1ZhbGlkYXRpb25SZXN1bHQgPSB7IGVudGl0eTogdGhpcy5lbnRpdHksIGFkZGVkOiBbXSwgcmVtb3ZlZDogW10gfTtcclxuICAgICAgICB2YWxpZGF0aW9uRm4odGhpcyk7XHJcbiAgICAgICAgaWYgKHRoaXMuX3BlbmRpbmdWYWxpZGF0aW9uUmVzdWx0LmFkZGVkLmxlbmd0aCA+IDAgfHwgdGhpcy5fcGVuZGluZ1ZhbGlkYXRpb25SZXN1bHQucmVtb3ZlZC5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICB0aGlzLnZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkLnB1Ymxpc2godGhpcy5fcGVuZGluZ1ZhbGlkYXRpb25SZXN1bHQpO1xyXG4gICAgICAgICAgLy8gdGhpcyBtaWdodCBiZSBhIGRldGFjaGVkIGVudGl0eSBoZW5jZSB0aGUgZ3VhcmQgYmVsb3cuXHJcbiAgICAgICAgICB0aGlzLmVudGl0eU1hbmFnZXIgJiYgdGhpcy5lbnRpdHlNYW5hZ2VyLnZhbGlkYXRpb25FcnJvcnNDaGFuZ2VkLnB1Ymxpc2godGhpcy5fcGVuZGluZ1ZhbGlkYXRpb25SZXN1bHQpO1xyXG5cclxuICAgICAgICB9XHJcbiAgICAgIH0gZmluYWxseSB7XHJcbiAgICAgICAgdGhpcy5fcGVuZGluZ1ZhbGlkYXRpb25SZXN1bHQgPSB1bmRlZmluZWQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIC8vIFRPRE86IGFkZC91c2UgYSBWYWxpZGF0aW9uRXJyb3IgdHlwZVxyXG4gIF9hZGRWYWxpZGF0aW9uRXJyb3IodmFsaWRhdGlvbkVycm9yOiBhbnkpIHtcclxuICAgIHRoaXMuX3ZhbGlkYXRpb25FcnJvcnNbdmFsaWRhdGlvbkVycm9yLmtleV0gPSB2YWxpZGF0aW9uRXJyb3I7XHJcbiAgICB0aGlzLmhhc1ZhbGlkYXRpb25FcnJvcnMgPSB0cnVlO1xyXG4gICAgdGhpcy5fcGVuZGluZ1ZhbGlkYXRpb25SZXN1bHQuYWRkZWQucHVzaCh2YWxpZGF0aW9uRXJyb3IpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgX3JlbW92ZVZhbGlkYXRpb25FcnJvcihrZXk6IHN0cmluZykge1xyXG4gICAgbGV0IHZhbEVycm9yID0gdGhpcy5fdmFsaWRhdGlvbkVycm9yc1trZXldO1xyXG4gICAgaWYgKHZhbEVycm9yKSB7XHJcbiAgICAgIGRlbGV0ZSB0aGlzLl92YWxpZGF0aW9uRXJyb3JzW2tleV07XHJcbiAgICAgIHRoaXMuaGFzVmFsaWRhdGlvbkVycm9ycyA9ICFjb3JlLmlzRW1wdHkodGhpcy5fdmFsaWRhdGlvbkVycm9ycyk7XHJcbiAgICAgIHRoaXMuX3BlbmRpbmdWYWxpZGF0aW9uUmVzdWx0LnJlbW92ZWQucHVzaCh2YWxFcnJvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG5cclxuQnJlZXplRXZlbnQuYnViYmxlRXZlbnQoRW50aXR5QXNwZWN0LnByb3RvdHlwZSwgZnVuY3Rpb24gKCkge1xyXG4gIHJldHVybiB0aGlzLmVudGl0eU1hbmFnZXI7XHJcbn0pO1xyXG5cclxuZnVuY3Rpb24gcmVqZWN0Q2hhbmdlc0NvcmUodGFyZ2V0OiBhbnkpIHtcclxuICBsZXQgYXNwZWN0ID0gdGFyZ2V0LmVudGl0eUFzcGVjdCB8fCB0YXJnZXQuY29tcGxleEFzcGVjdDtcclxuICBsZXQgc3R5cGUgPSB0YXJnZXQuZW50aXR5VHlwZSB8fCB0YXJnZXQuY29tcGxleFR5cGU7XHJcbiAgbGV0IG9yaWdpbmFsVmFsdWVzID0gYXNwZWN0Lm9yaWdpbmFsVmFsdWVzO1xyXG4gIGZvciAobGV0IHByb3BOYW1lIGluIG9yaWdpbmFsVmFsdWVzKSB7XHJcbiAgICB0YXJnZXQuc2V0UHJvcGVydHkocHJvcE5hbWUsIG9yaWdpbmFsVmFsdWVzW3Byb3BOYW1lXSk7XHJcbiAgfVxyXG4gIHN0eXBlLmNvbXBsZXhQcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKGNwOiBhbnkpIHtcclxuICAgIGxldCBjb3MgPSB0YXJnZXQuZ2V0UHJvcGVydHkoY3AubmFtZSk7XHJcbiAgICBpZiAoY3AuaXNTY2FsYXIpIHtcclxuICAgICAgcmVqZWN0Q2hhbmdlc0NvcmUoY29zKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvcy5fcmVqZWN0Q2hhbmdlcygpO1xyXG4gICAgICBjb3MuZm9yRWFjaChyZWplY3RDaGFuZ2VzQ29yZSk7XHJcbiAgICB9XHJcbiAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJlbW92ZUZyb21SZWxhdGlvbnMoZW50aXR5OiBFbnRpdHksIGVudGl0eVN0YXRlOiBFbnRpdHlTdGF0ZSkge1xyXG4gIC8vIHJlbW92ZSB0aGlzIGVudGl0eSBmcm9tIGFueSBjb2xsZWN0aW9ucy5cclxuICAvLyBtYXJrIHRoZSBlbnRpdHkgZGVsZXRlZCBvciBkZXRhY2hlZFxyXG5cclxuICBsZXQgaXNEZWxldGVkID0gZW50aXR5U3RhdGUuaXNEZWxldGVkKCk7XHJcbiAgaWYgKGlzRGVsZXRlZCkge1xyXG4gICAgcmVtb3ZlRnJvbVJlbGF0aW9uc0NvcmUoZW50aXR5KTtcclxuICB9IGVsc2Uge1xyXG4gICAgY29yZS51c2luZyhlbnRpdHkuZW50aXR5QXNwZWN0LmVudGl0eU1hbmFnZXIhLCBcImlzTG9hZGluZ1wiLCB0cnVlLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHJlbW92ZUZyb21SZWxhdGlvbnNDb3JlKGVudGl0eSk7XHJcbiAgICB9KTtcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJlbW92ZUZyb21SZWxhdGlvbnNDb3JlKGVudGl0eTogRW50aXR5KSB7XHJcbiAgZW50aXR5LmVudGl0eVR5cGUubmF2aWdhdGlvblByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAobnApIHtcclxuICAgIGxldCBpbnZlcnNlTnAgPSBucC5pbnZlcnNlO1xyXG4gICAgbGV0IG5wVmFsdWUgPSBlbnRpdHkuZ2V0UHJvcGVydHkobnAubmFtZSk7XHJcbiAgICBpZiAobnAuaXNTY2FsYXIpIHtcclxuICAgICAgaWYgKG5wVmFsdWUpIHtcclxuICAgICAgICBpZiAoaW52ZXJzZU5wKSB7XHJcbiAgICAgICAgICBpZiAoaW52ZXJzZU5wLmlzU2NhbGFyKSB7XHJcbiAgICAgICAgICAgIG5wVmFsdWUuc2V0UHJvcGVydHkoaW52ZXJzZU5wLm5hbWUsIG51bGwpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbGV0IGNvbGxlY3Rpb24gPSBucFZhbHVlLmdldFByb3BlcnR5KGludmVyc2VOcC5uYW1lKTtcclxuICAgICAgICAgICAgaWYgKGNvbGxlY3Rpb24ubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgY29yZS5hcnJheVJlbW92ZUl0ZW0oY29sbGVjdGlvbiwgZW50aXR5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBlbnRpdHkuc2V0UHJvcGVydHkobnAubmFtZSwgbnVsbCk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmIChpbnZlcnNlTnAgIT0gbnVsbCkge1xyXG4gICAgICAgIC8vIG5wVmFsdWUgaXMgYSBsaXZlIGxpc3Qgc28gd2UgbmVlZCB0byBjb3B5IGl0IGZpcnN0LlxyXG4gICAgICAgIG5wVmFsdWUuc2xpY2UoMCkuZm9yRWFjaCgodjogYW55KSA9PiB7XHJcbiAgICAgICAgICBpZiAoaW52ZXJzZU5wIS5pc1NjYWxhcikge1xyXG4gICAgICAgICAgICB2LnNldFByb3BlcnR5KGludmVyc2VOcCEubmFtZSwgbnVsbCk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBUT0RPOiBtYW55IHRvIG1hbnkgLSBub3QgeWV0IGhhbmRsZWQuXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgICAgLy8gbm93IGNsZWFyIGl0LlxyXG4gICAgICBucFZhbHVlLmxlbmd0aCA9IDA7XHJcbiAgICB9XHJcbiAgfSk7XHJcblxyXG59XHJcblxyXG4vLyBub3RlIGVudGl0eUFzcGVjdCBvbmx5IC0gKCBubyBjb21wbGV4IGFzcGVjdCBhbGxvd2VkIG9uIHRoZSBjYWxsKS5cclxuZnVuY3Rpb24gdmFsaWRhdGUoZW50aXR5QXNwZWN0OiBFbnRpdHlBc3BlY3QsIHZhbGlkYXRvcjogVmFsaWRhdG9yLCB2YWx1ZTogYW55LCBjb250ZXh0PzogYW55KSB7XHJcbiAgbGV0IHZlID0gdmFsaWRhdG9yLnZhbGlkYXRlKHZhbHVlLCBjb250ZXh0KTtcclxuICBpZiAodmUpIHtcclxuICAgIGVudGl0eUFzcGVjdC5fYWRkVmFsaWRhdGlvbkVycm9yKHZlKTtcclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9IGVsc2Uge1xyXG4gICAgbGV0IGtleSA9IFZhbGlkYXRpb25FcnJvci5nZXRLZXkodmFsaWRhdG9yLCBjb250ZXh0ID8gY29udGV4dC5wcm9wZXJ0eU5hbWUgOiBudWxsKTtcclxuICAgIGVudGl0eUFzcGVjdC5fcmVtb3ZlVmFsaWRhdGlvbkVycm9yKGtleSk7XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcbn1cclxuXHJcbi8vIGNvSW5kZXggaXMgb25seSB1c2VkIHdoZXJlIHRhcmdldCBpcyBhIGNvbXBsZXggb2JqZWN0IHRoYXQgaXMgcGFydCBvZiBhbiBhcnJheSBvZiBjb21wbGV4IG9iamVjdHNcclxuLy8gaW4gd2hpY2ggY2FzZSBjdEluZGV4IGlzIHRoZSBpbmRleCBvZiB0aGUgdGFyZ2V0IHdpdGhpbiB0aGUgYXJyYXkuXHJcbmZ1bmN0aW9uIHZhbGlkYXRlVGFyZ2V0KHRhcmdldDogYW55LCBjb0luZGV4PzogbnVtYmVyKSB7XHJcbiAgbGV0IG9rID0gdHJ1ZTtcclxuICBsZXQgc3R5cGUgPSB0YXJnZXQuZW50aXR5VHlwZSB8fCB0YXJnZXQuY29tcGxleFR5cGU7XHJcbiAgbGV0IGFzcGVjdCA9IHRhcmdldC5lbnRpdHlBc3BlY3QgfHwgdGFyZ2V0LmNvbXBsZXhBc3BlY3Q7XHJcbiAgbGV0IGVudGl0eUFzcGVjdCA9IHRhcmdldC5lbnRpdHlBc3BlY3QgfHwgdGFyZ2V0LmNvbXBsZXhBc3BlY3QuZ2V0RW50aXR5QXNwZWN0KCk7XHJcbiAgbGV0IGNvbnRleHQgPSA8YW55PnsgZW50aXR5OiBlbnRpdHlBc3BlY3QuZW50aXR5IH07XHJcbiAgaWYgKGNvSW5kZXggIT09IHVuZGVmaW5lZCkge1xyXG4gICAgY29udGV4dC5pbmRleCA9IGNvSW5kZXg7XHJcbiAgfVxyXG5cclxuICBzdHlwZS5nZXRQcm9wZXJ0aWVzKCkuZm9yRWFjaChmdW5jdGlvbiAocDogYW55KSB7XHJcbiAgICBsZXQgdmFsdWUgPSB0YXJnZXQuZ2V0UHJvcGVydHkocC5uYW1lKTtcclxuICAgIGxldCB2YWxpZGF0b3JzID0gcC5nZXRBbGxWYWxpZGF0b3JzKCk7XHJcbiAgICBpZiAodmFsaWRhdG9ycy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGNvbnRleHQucHJvcGVydHkgPSBwO1xyXG4gICAgICBjb250ZXh0LnByb3BlcnR5TmFtZSA9IGFzcGVjdC5nZXRQcm9wZXJ0eVBhdGgocC5uYW1lKTtcclxuICAgICAgb2sgPSBlbnRpdHlBc3BlY3QuX3ZhbGlkYXRlUHJvcGVydHkodmFsdWUsIGNvbnRleHQpICYmIG9rO1xyXG4gICAgfVxyXG4gICAgaWYgKHAuaXNDb21wbGV4UHJvcGVydHkpIHtcclxuICAgICAgaWYgKHAuaXNTY2FsYXIpIHtcclxuICAgICAgICBvayA9IHZhbGlkYXRlVGFyZ2V0KHZhbHVlKSAmJiBvaztcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBvayA9IHZhbHVlLnJlZHVjZShmdW5jdGlvbiAocHY6IGFueSwgY3Y6IGFueSwgaXg6IG51bWJlcikge1xyXG4gICAgICAgICAgcmV0dXJuIHZhbGlkYXRlVGFyZ2V0KGN2LCBpeCkgJiYgcHY7XHJcbiAgICAgICAgfSwgb2spO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSk7XHJcblxyXG5cclxuICAvLyB0aGVuIHRhcmdldCBsZXZlbFxyXG4gIHN0eXBlLmdldEFsbFZhbGlkYXRvcnMoKS5mb3JFYWNoKGZ1bmN0aW9uICh2YWxpZGF0b3I6IFZhbGlkYXRvcikge1xyXG4gICAgb2sgPSB2YWxpZGF0ZShlbnRpdHlBc3BlY3QsIHZhbGlkYXRvciwgdGFyZ2V0KSAmJiBvaztcclxuICB9KTtcclxuICByZXR1cm4gb2s7XHJcbn1cclxuXHJcbi8qKlxyXG5BbiBDb21wbGV4QXNwZWN0IGluc3RhbmNlIGlzIGFzc29jaWF0ZWQgd2l0aCBldmVyeSBjb21wbGV4IG9iamVjdCBpbnN0YW5jZSBhbmQgaXMgYWNjZXNzZWQgdmlhIHRoZSBjb21wbGV4IG9iamVjdCdzICdjb21wbGV4QXNwZWN0JyBwcm9wZXJ0eS5cclxuXHJcblRoZSBDb21wbGV4QXNwZWN0IGl0c2VsZiBwcm92aWRlcyBwcm9wZXJ0aWVzIHRvIGRldGVybWluZSB0aGUgcGFyZW50IG9iamVjdCwgcGFyZW50IHByb3BlcnR5IGFuZCBvcmlnaW5hbCB2YWx1ZXMgZm9yIHRoZSBjb21wbGV4IG9iamVjdC5cclxuXHJcbkEgQ29tcGxleEFzcGVjdCB3aWxsIGFsbW9zdCBuZXZlciBuZWVkIHRvIGJlIGNvbnN0cnVjdGVkIGRpcmVjdGx5LiBZb3Ugd2lsbCB1c3VhbGx5IGdldCBhbiBDb21wbGV4QXNwZWN0IGJ5IGFjY2Vzc2luZ1xyXG5hbiBlbnRpdGllcyAnY29tcGxleEFzcGVjdCcgcHJvcGVydHkuICBUaGlzIHByb3BlcnR5IHdpbGwgYmUgYXV0b21hdGljYWxseSBhdHRhY2hlZCB3aGVuIGFuIGNvbXBsZXggb2JqZWN0IGlzIGNyZWF0ZWQgYXMgcGFydCBvZiBhblxyXG5lbnRpdHkgdmlhIGVpdGhlciBhIHF1ZXJ5LCBpbXBvcnQgb3IgRW50aXR5TWFuYWdlci5jcmVhdGVFbnRpdHkgY2FsbC5cclxuPiAgICAgIC8vIGFzc3VtZSBhZGRyZXNzIGlzIGEgY29tcGxleCBwcm9wZXJ0eSBvbiB0aGUgJ0N1c3RvbWVyJyB0eXBlXHJcbj4gICAgICB2YXIgYXNwZWN0ID0gYUN1c3RvbWVyLmFkZHJlc3MuY29tcGxleEFzcGVjdDtcclxuPiAgICAgIC8vIGFDdXN0b21lciA9PT0gYXNwZWN0LnBhcmVudDtcclxuKiovXHJcbmV4cG9ydCBjbGFzcyBDb21wbGV4QXNwZWN0IHtcclxuXHJcbiAgLyoqIFRoZSBjb21wbGV4IG9iamVjdCB0aGF0IHRoaXMgYXNwZWN0IGlzIGFzc29jaWF0ZWQgd2l0aC4gX19SZWFkIE9ubHlfXyAqL1xyXG4gIGNvbXBsZXhPYmplY3Q6IENvbXBsZXhPYmplY3Q7XHJcbiAgLyoqIFRoZSAnb3JpZ2luYWwgdmFsdWVzJyBvZiB0aGlzIGNvbXBsZXggb2JqZWN0IHdoZXJlIHRoZXkgYXJlIGRpZmZlcmVudCBmcm9tIHRoZSAnY3VycmVudCB2YWx1ZXMnLlxyXG4gIFRoaXMgaXMgYSBtYXAgd2hlcmUgdGhlIGtleSBpcyBhIHByb3BlcnR5IG5hbWUgYW5kIHRoZSB2YWx1ZSBpcyB0aGUgJ29yaWdpbmFsIHZhbHVlJyBvZiB0aGUgcHJvcGVydHkuXHJcbiAgX19SZWFkIE9ubHlfXyAqL1xyXG4gIG9yaWdpbmFsVmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xyXG4gIC8qKiBUaGUgcGFyZW50IG9iamVjdCB0aGF0IHRvIHdoaWNoIHRoaXMgYXNwZWN0IGJlbG9uZ3M7IHRoaXMgd2lsbCBlaXRoZXIgYmUgYW4gZW50aXR5IG9yIGFub3RoZXIgY29tcGxleCBvYmplY3QuIF9fUmVhZCBPbmx5X18gKi9cclxuICBwYXJlbnQ/OiBTdHJ1Y3R1cmFsT2JqZWN0O1xyXG4gIC8qKiBUaGUgW1tEYXRhUHJvcGVydHldXSBvbiB0aGUgJ3BhcmVudCcgdGhhdCBjb250YWlucyB0aGlzIGNvbXBsZXggb2JqZWN0LiBfX1JlYWQgT25seV9fICovXHJcbiAgcGFyZW50UHJvcGVydHk/OiBEYXRhUHJvcGVydHk7XHJcbiAgZXh0cmFNZXRhZGF0YT86IGFueTtcclxuXHJcbiAgLyoqIFlvdSB3aWxsIHJhcmVseSwgaWYgZXZlciwgY3JlYXRlIGEgQ29tcGxleEFzcGVjdCBkaXJlY3RseS4gKi9cclxuICBjb25zdHJ1Y3Rvcihjb21wbGV4T2JqZWN0OiBDb21wbGV4T2JqZWN0LCBwYXJlbnQ6IFN0cnVjdHVyYWxPYmplY3QsIHBhcmVudFByb3BlcnR5OiBEYXRhUHJvcGVydHkpIHtcclxuICAgIGlmICghY29tcGxleE9iamVjdCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgIENvbXBsZXhBc3BlY3QgY3RvciByZXF1aXJlcyBhbiBlbnRpdHkgYXMgaXRzIG9ubHkgYXJndW1lbnQuXCIpO1xyXG4gICAgfVxyXG4gICAgaWYgKGNvbXBsZXhPYmplY3QuY29tcGxleEFzcGVjdCkge1xyXG4gICAgICByZXR1cm4gY29tcGxleE9iamVjdC5jb21wbGV4QXNwZWN0O1xyXG4gICAgfVxyXG4gICAgLy8gaWYgY2FsbGVkIHdpdGhvdXQgbmV3XHJcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQ29tcGxleEFzcGVjdCkpIHtcclxuICAgICAgcmV0dXJuIG5ldyBDb21wbGV4QXNwZWN0KGNvbXBsZXhPYmplY3QsIHBhcmVudCwgcGFyZW50UHJvcGVydHkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGVudGl0eVR5cGUgc2hvdWxkIGFscmVhZHkgYmUgb24gdGhlIGVudGl0eSBmcm9tICd3YXRjaCdcclxuICAgIHRoaXMuY29tcGxleE9iamVjdCA9IGNvbXBsZXhPYmplY3Q7XHJcbiAgICBjb21wbGV4T2JqZWN0LmNvbXBsZXhBc3BlY3QgPSB0aGlzO1xyXG5cclxuICAgIC8vIFRPRE86IGtlZXAgcHVibGljIG9yIG5vdD9cclxuICAgIHRoaXMub3JpZ2luYWxWYWx1ZXMgPSB7fTtcclxuXHJcbiAgICAvLyBpZiBhIHN0YW5kYWxvbmUgY29tcGxleE9iamVjdFxyXG4gICAgaWYgKHBhcmVudCAhPSBudWxsKSB7XHJcbiAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50O1xyXG4gICAgICB0aGlzLnBhcmVudFByb3BlcnR5ID0gcGFyZW50UHJvcGVydHk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGNvbXBsZXhUeXBlID0gY29tcGxleE9iamVjdC5jb21wbGV4VHlwZTtcclxuICAgIGlmICghY29tcGxleFR5cGUpIHtcclxuICAgICAgbGV0IHR5cGVOYW1lID0gY29tcGxleE9iamVjdC5wcm90b3R5cGUuXyR0eXBlTmFtZTtcclxuICAgICAgaWYgKCF0eXBlTmFtZSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaXMgZW50aXR5IGlzIG5vdCByZWdpc3RlcmVkIGFzIGEgdmFsaWQgQ29tcGxleFR5cGVcIik7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTWV0YWRhdGEgZm9yIHRoaXMgY29tcGxleFR5cGUgaGFzIG5vdCB5ZXQgYmVlbiByZXNvbHZlZDogXCIgKyB0eXBlTmFtZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGxldCBjb21wbGV4Q3RvciA9IGNvbXBsZXhUeXBlLmdldEN0b3IoKTtcclxuICAgIGNvbmZpZy5pbnRlcmZhY2VSZWdpc3RyeS5tb2RlbExpYnJhcnkuZ2V0RGVmYXVsdEluc3RhbmNlKCkuc3RhcnRUcmFja2luZyhjb21wbGV4T2JqZWN0LCBjb21wbGV4Q3Rvci5wcm90b3R5cGUpO1xyXG5cclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICBSZXR1cm5zIHRoZSBFbnRpdHlBc3BlY3QgZm9yIHRoZSB0b3AgbGV2ZWwgZW50aXR5IHRoYXQgY29udGFpbnMgdGhpcyBjb21wbGV4IG9iamVjdC5cclxuICAqKi9cclxuICBnZXRFbnRpdHlBc3BlY3QoKSB7XHJcbiAgICBsZXQgcGFyZW50ID0gPGFueT50aGlzLnBhcmVudDtcclxuICAgIGlmICghcGFyZW50KSByZXR1cm4gbmV3IEVudGl0eUFzcGVjdCgpO1xyXG4gICAgbGV0IGVudGl0eUFzcGVjdCA9IHBhcmVudC5lbnRpdHlBc3BlY3Q7XHJcbiAgICB3aGlsZSAocGFyZW50ICYmICFlbnRpdHlBc3BlY3QpIHtcclxuICAgICAgcGFyZW50ID0gcGFyZW50LmNvbXBsZXhBc3BlY3QgJiYgcGFyZW50LmNvbXBsZXhBc3BlY3QucGFyZW50O1xyXG4gICAgICBlbnRpdHlBc3BlY3QgPSBwYXJlbnQgJiYgcGFyZW50LmVudGl0eUFzcGVjdDtcclxuICAgIH1cclxuICAgIHJldHVybiBlbnRpdHlBc3BlY3QgfHwgbmV3IEVudGl0eUFzcGVjdCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqICBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gIC8vIFRPRE86IHJlbmFtZSAtIGFuZCB1c2UgJ18nOyB1c2VkIG9uIGJvdGggRW50aXR5QXNwZWN0IGFuZCBDb21wbGV4QXNwZWN0IGZvciBwb2x5bW9ycGhpYyByZWFzb25zLlxyXG4gIGdldFByb3BlcnR5UGF0aChwcm9wTmFtZTogc3RyaW5nKSB7XHJcbiAgICBsZXQgcGFyZW50ID0gPGFueT50aGlzLnBhcmVudDtcclxuICAgIGlmICghcGFyZW50KSByZXR1cm4gbnVsbDtcclxuICAgIGxldCBhc3BlY3QgPSBwYXJlbnQuY29tcGxleEFzcGVjdCB8fCBwYXJlbnQuZW50aXR5QXNwZWN0O1xyXG4gICAgcmV0dXJuIGFzcGVjdC5nZXRQcm9wZXJ0eVBhdGgodGhpcy5wYXJlbnRQcm9wZXJ0eSEubmFtZSArIFwiLlwiICsgcHJvcE5hbWUpO1xyXG4gIH1cclxuXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNsZWFyT3JpZ2luYWxWYWx1ZXModGFyZ2V0OiBhbnkpIHtcclxuICBsZXQgYXNwZWN0ID0gdGFyZ2V0LmVudGl0eUFzcGVjdCB8fCB0YXJnZXQuY29tcGxleEFzcGVjdDtcclxuICBhc3BlY3Qub3JpZ2luYWxWYWx1ZXMgPSB7fTtcclxuICBsZXQgc3R5cGUgPSB0YXJnZXQuZW50aXR5VHlwZSB8fCB0YXJnZXQuY29tcGxleFR5cGU7XHJcbiAgc3R5cGUuY29tcGxleFByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAoY3A6IGFueSkge1xyXG4gICAgbGV0IGNvcyA9IHRhcmdldC5nZXRQcm9wZXJ0eShjcC5uYW1lKTtcclxuICAgIGlmIChjcC5pc1NjYWxhcikge1xyXG4gICAgICBjbGVhck9yaWdpbmFsVmFsdWVzKGNvcyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb3MuX2FjY2VwdENoYW5nZXMoKTtcclxuICAgICAgY29zLmZvckVhY2goY2xlYXJPcmlnaW5hbFZhbHVlcyk7XHJcbiAgICB9XHJcbiAgfSk7XHJcbn1cclxuXHJcblxyXG4iXX0=
|