UNPKG

@versatiledatakit/shared

Version:

Versatile Data Kit Shared library enables reusability of shared features like: NgRx Redux, Error Handlers, Utils, Generic Components, etc.

297 lines 39.2 kB
/* * Copyright 2023-2025 Broadcom * SPDX-License-Identifier: Apache-2.0 */ /* eslint-disable @angular-eslint/directive-class-suffix */ import { Directive } from '@angular/core'; import { CollectionsUtil } from '../../../../utils'; import { RouteStateFactory } from '../../../router/factory'; import { ComponentModel, FAILED } from '../../model'; import { TaurusErrorBaseComponent } from '../error-base'; import * as i0 from "@angular/core"; import * as i1 from "../../services"; import * as i2 from "../../../navigation"; import * as i3 from "@angular/router"; /** * ** Superclass Component for all other Components that want to use NgRx Store and all lifecycle hooks from Taurus. */ export class TaurusBaseComponent extends TaurusErrorBaseComponent { /** * ** Constructor. */ constructor(componentService, navigationService, activatedRoute, className = null) { super(className ?? TaurusBaseComponent.CLASS_NAME); this.componentService = componentService; this.navigationService = navigationService; this.activatedRoute = activatedRoute; /** * ** Feature flag to enforce Route reuse in native way provided from Taurus NgRx. * * - Introduced for backward compatibility. * - Default value is false, and continues to operate like previous major version. * - If set to true will enforce Route reuse strategy and will re-initialize Component with new Model for the new params. */ this.enforceRouteReuse = false; } /** * ** Navigate to page using {@link NavigationService.navigateTo}. */ navigateTo(replaceValues) { return this.navigationService.navigateTo(replaceValues); } /** * ** Navigate back to previous page using {@link NavigationService.navigateBack}. */ navigateBack(replaceValues) { return this.navigationService.navigateBack(replaceValues); } /** * @inheritDoc */ ngOnInit() { this.bindModel(); this.initializeRouteReuse(); } /** * @inheritDoc */ ngOnDestroy() { this.setStateIdle(); super.ngOnDestroy(); } /** * ** Invoking method register subscriber for Taurus NgRx Redux Store mutation in context of {@link ComponentState.routePathSegments}, * which binds {@link ComponentModel} to {@link TaurusBaseComponent.model} * and start invocation of Taurus NgRx Redux Component lifecycle hooks. * * <b>Invocation order:</b> * * 1. {@link OnTaurusModelInit} * 2. {@link OnTaurusModelInitialLoad} or {@link OnTaurusModelFirstLoad} - only one could be invoke, * where deprecated shouldn't be implemented anymore. * 3. {@link OnTaurusModelLoad} * 4. {@link OnTaurusModelChange} when status is {@link LOADED} * 5. {@link OnTaurusModelError} or {@link OnTaurusModelFail} when status is {@link FAILED} - only one could be invoke, * where deprecated shouldn't be implemented anymore. * * <p> * <br> * Override it if you want to change default behavior. * </p> * * @protected */ bindModel() { let isOnModelInitialLoadExecuted = false; if (!TaurusBaseComponent._routeStateFactory) { TaurusBaseComponent._routeStateFactory = new RouteStateFactory(); } const routeState = TaurusBaseComponent._routeStateFactory.create(this.activatedRoute.snapshot, null); this.componentService.init(this.uuid, routeState).subscribe((model) => { this.model = model; TaurusBaseComponent._executeTaurusComponentHook(this, 'onModelInit', model); }); this._modelSubscription = this.componentService.getModel(this.uuid, routeState.routePathSegments).subscribe((model) => { if (!isOnModelInitialLoadExecuted) { isOnModelInitialLoadExecuted = true; if (!TaurusBaseComponent._executeTaurusComponentHook(this, 'onModelInitialLoad', model)) { TaurusBaseComponent._executeTaurusComponentHook(this, 'onModelFirstLoad', model); } } this.evaluateTaurusComponentLifecycleHooks(model); }); this.subscriptions.push(this._modelSubscription); } /** * ** Evaluates Taurus NgRx Redux Component lifecycle hooks * ({@link OnTaurusModelLoad} and {@link OnTaurusModelChange} and ({@link OnTaurusModelFail} or {@link OnTaurusModelError})). * * - Override it if you want to change default behavior. * * @protected */ evaluateTaurusComponentLifecycleHooks(model) { TaurusBaseComponent._executeTaurusComponentHook(this, 'onModelLoad', model); if (!this.isModelModified(model)) { return; } const previousModel = this.model; this.refreshModel(model); if (model.status === FAILED) { const previousErrorRecords = previousModel instanceof ComponentModel ? previousModel.getComponentState().errors.records : []; const distinctErrorRecordsFromPreviousCycle = model.getComponentState().errors.distinctErrorRecords(previousErrorRecords); if (!TaurusBaseComponent._executeTaurusComponentHook(this, 'onModelError', model, distinctErrorRecordsFromPreviousCycle)) { TaurusBaseComponent._executeTaurusComponentHook(this, 'onModelFail', model); } } else { TaurusBaseComponent._executeTaurusComponentHook(this, 'onModelChange', model); } try { this.normalizeModelState(model); } catch (e) { console.error(`Taurus NgRx Redux failed to normalize ComponentModel!`, e); } } /** * ** Refresh model field {@link TaurusBaseComponent.model} with new one, * and assigns previous model reference to field {@link ComponentModel.previousModel} in the new model, * to the max depth 3. * * - All assignments are by reference. * - Override it if you want to change default behavior. * - <b>Be cautious about your changes and intents!</b> It could affect features thar depend on this method Impl. * * @protected */ refreshModel(model) { // purge component ErrorStore with data from ComponentModel ErrorStore this.errors.purge(model.getComponentState().errors); // assign current model as previous to the new one // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore model['previousModel'] = this.model; // eslint-disable-line @typescript-eslint/dot-notation // clean previous models that exceed max depth 3 try { let depthLevel = 1; let previousModel = model.previousModel; while (previousModel instanceof ComponentModel) { if (++depthLevel <= 3) { previousModel = previousModel.previousModel; } else { if (previousModel.previousModel) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore delete previousModel['previousModel']; // eslint-disable-line @typescript-eslint/dot-notation } break; } } } catch (e) { console.error('Failed to clean previous ComponentModel', e); } // assign model as current this.model = model; } /** * ** Normalize Model state, by default it clear Task field in {@link ComponentState.task} and update model in Taurus NgRx Redux Store. * * - It is invoked only if {@link ComponentModel} is modified and after invocation of all Taurus components lifecycle hooks. * - Override it if you want to change default behavior. * * @protected */ normalizeModelState(model) { this.componentService.update(model.clearTask().getComponentState()); } /** * ** Set Model state in IDLE to stop listening on Events from Store. * * - It is invoked by default before Component is destroyed, in Angular lifecycle hook {@link OnDestroy}. * - Override it if you want to change default behavior. * * @protected */ setStateIdle() { this.componentService.idle(this.model.prepareForDestroy().getComponentState()); } /** * ** Evaluation of this method acknowledge that new {@link ComponentModel} is modified or not. * * - Comparison is evaluated between provided Model and assigned Component's Model {@link TaurusBaseComponent.model}. * - Default implementation use {@link ComponentModel.isModified} for deep Comparison of specific fields. * - Override it if you want to change default behavior. * * <p> * <b>Be cautious about your changes and intents!</b> * Examples what can wrong comparison do? * </p> * * 1. Infinite lifecycle hooks invocation, where consequences are: performance deterioration or application freeze. * 2. Prevent lifecycle hooks invocation, where consequences are: your Data never arrive to your Component fields. * * @protected */ isModelModified(model) { return model.isModified(this.model); } /** * ** Initialize Route reuse strategy for Component in context of Taurus NgRx. * - Turns on listener for Activated params change and if detects mutation * sets current model in current RoutePathSegment to idle, * and bind for new model stream to the new RoutePathSegment. * - New feature this is completely backward compatible, * and it can be turned on with feature flag per Component Class. * * @protected */ initializeRouteReuse() { if (!this.enforceRouteReuse) { return; } let previousParams; this.subscriptions.push(this.activatedRoute.params.subscribe((params) => { if (CollectionsUtil.isNil(previousParams)) { previousParams = params; return; } if (!CollectionsUtil.isEqual(previousParams, params)) { previousParams = params; const isRemoveSuccessful = this.removeSubscriptionRef(this._modelSubscription); if (isRemoveSuccessful) { // set current RoutePathSegment model state to idle this.setStateIdle(); // bind new model stream to new RoutePathSegment this.bindModel(); } } })); } /** * ** Invoke Taurus NgRx Redux Component lifecycle hook. * * - Lifecycle hooks are invoked only if implementation they are found as implemented in subclasses. * - Returns true if method is found and executed, otherwise false. * * @private */ // eslint-disable-next-line @typescript-eslint/member-ordering static _executeTaurusComponentHook(instance, method, model, ...additionalParams) { // eslint-disable-line @typescript-eslint/no-explicit-any if (CollectionsUtil.isFunction(instance[method])) { const currentTask = model.getTask(); try { if (CollectionsUtil.isString(currentTask)) { // eslint-disable-next-line @typescript-eslint/no-unsafe-call instance[method](model, currentTask, ...additionalParams); } else { // eslint-disable-next-line @typescript-eslint/no-unsafe-call instance[method](model, undefined, ...additionalParams); } } catch (e) { console.error(`Taurus NgRx Redux failed to execute lifecycle hook "${method}"!`, e); } return true; } return false; } } /** * @inheritDoc */ TaurusBaseComponent.CLASS_NAME = 'TaurusBaseComponent'; /** * @inheritDoc */ TaurusBaseComponent.PUBLIC_NAME = 'Taurus-Base-Component'; TaurusBaseComponent.ɵfac = function TaurusBaseComponent_Factory(t) { i0.ɵɵinvalidFactory(); }; TaurusBaseComponent.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: TaurusBaseComponent, features: [i0.ɵɵInheritDefinitionFeature] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TaurusBaseComponent, [{ type: Directive }], function () { return [{ type: i1.ComponentService }, { type: i2.NavigationService }, { type: i3.ActivatedRoute }, { type: undefined }]; }, null); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGF1cnVzLWJhc2UuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc2hhcmVkL3NyYy9saWIvY29yZS9jb21wb25lbnQvY29tcG9uZW50cy9yZWR1eC1iYXNlL3RhdXJ1cy1iYXNlLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCwyREFBMkQ7QUFFM0QsT0FBTyxFQUFFLFNBQVMsRUFBcUIsTUFBTSxlQUFlLENBQUM7QUFLN0QsT0FBTyxFQUFnQixlQUFlLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUtsRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUU1RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUdyRCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxlQUFlLENBQUM7Ozs7O0FBSXpEOztHQUVHO0FBRUgsTUFBTSxPQUFnQixtQkFBb0IsU0FBUSx3QkFBd0I7SUFzQ3RFOztPQUVHO0lBQ0gsWUFDdUIsZ0JBQWtDLEVBQ2xDLGlCQUFvQyxFQUNwQyxjQUE4QixFQUNqRCxZQUFvQixJQUFJO1FBRXhCLEtBQUssQ0FBQyxTQUFTLElBQUksbUJBQW1CLENBQUMsVUFBVSxDQUFDLENBQUM7UUFMaEMscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNsQyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBQ3BDLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQXJCckQ7Ozs7OztXQU1HO1FBQ0gsc0JBQWlCLEdBQUcsS0FBSyxDQUFDO0lBa0IxQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxVQUFVLENBQUMsYUFBa0c7UUFDekcsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRDs7T0FFRztJQUNI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RztBQUNzQiw4QkFBVSxHQUFXLHFCQUFzQixDQUFBO0FBRXBFOztHQUVHO0FBQ3NCLCtCQUFXLEdBQVcsdUJBQXdCLENBQUE7O3NFQVRyRCxtQkFBbUI7dUZBQW5CLG1CQUFtQjtjQUR4QyxTQUFTIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAyMDIzLTIwMjUgQnJvYWRjb21cbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cblxuLyogZXNsaW50LWRpc2FibGUgQGFuZ3VsYXItZXNsaW50L2RpcmVjdGl2ZS1jbGFzcy1zdWZmaXggKi9cblxuaW1wb3J0IHsgRGlyZWN0aXZlLCBPbkRlc3Ryb3ksIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIFBhcmFtcyB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5cbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBBcnJheUVsZW1lbnQsIENvbGxlY3Rpb25zVXRpbCB9IGZyb20gJy4uLy4uLy4uLy4uL3V0aWxzJztcblxuaW1wb3J0IHsgRXJyb3JSZWNvcmQsIFRhdXJ1c05hdmlnYXRlQWN0aW9uIH0gZnJvbSAnLi4vLi4vLi4vLi4vY29tbW9uJztcblxuaW1wb3J0IHsgTmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9uYXZpZ2F0aW9uJztcbmltcG9ydCB7IFJvdXRlU3RhdGVGYWN0b3J5IH0gZnJvbSAnLi4vLi4vLi4vcm91dGVyL2ZhY3RvcnknO1xuXG5pbXBvcnQgeyBDb21wb25lbnRNb2RlbCwgRkFJTEVEIH0gZnJvbSAnLi4vLi4vbW9kZWwnO1xuaW1wb3J0IHsgQ29tcG9uZW50U2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzJztcblxuaW1wb3J0IHsgVGF1cnVzRXJyb3JCYXNlQ29tcG9uZW50IH0gZnJvbSAnLi4vZXJyb3ItYmFzZSc7XG5cbmltcG9ydCB7IFRhdXJ1c0NvbXBvbmVudEhvb2tzIH0gZnJvbSAnLi9pbnRlcmZhY2VzJztcblxuLyoqXG4gKiAqKiBTdXBlcmNsYXNzIENvbXBvbmVudCBmb3IgYWxsIG90aGVyIENvbXBvbmVudHMgdGhhdCB3YW50IHRvIHVzZSBOZ1J4IFN0b3JlIGFuZCBhbGwgbGlmZWN5Y2xlIGhvb2tzIGZyb20gVGF1cnVzLlxuICovXG5ARGlyZWN0aXZlKClcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBUYXVydXNCYXNlQ29tcG9uZW50IGV4dGVuZHMgVGF1cnVzRXJyb3JCYXNlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICAgIC8qKlxuICAgICAqIEBpbmhlcml0RG9jXG4gICAgICovXG4gICAgc3RhdGljIG92ZXJyaWRlIHJlYWRvbmx5IENMQVNTX05BTUU6IHN0cmluZyA9ICdUYXVydXNCYXNlQ29tcG9uZW50JztcblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0RG9jXG4gICAgICovXG4gICAgc3RhdGljIG92ZXJyaWRlIHJlYWRvbmx5IFBVQkxJQ19OQU1FOiBzdHJpbmcgPSAnVGF1cnVzLUJhc2UtQ29tcG9uZW50JztcblxuICAgIHByaXZhdGUgc3RhdGljIF9yb3V0ZVN0YXRlRmFjdG9yeTogUm91dGVTdGF0ZUZhY3Rvcnk7XG5cbiAgICAvKipcbiAgICAgKiAqKiBGaWVsZCB0aGF0IGhvbGQgQ29tcG9uZW50IE1vZGVsLlxuICAgICAqL1xuICAgIG1vZGVsOiBDb21wb25lbnRNb2RlbDtcblxuICAgIC8qKlxuICAgICAqICoqIFVVSUQgaXMgaWRlbnRpZmllciBmb3IgZXZlcnkgU3ViY2xhc3MgaW4gQ29tcG9uZW50cyBzdGF0ZSBTdG9yZS5cbiAgICAgKi9cbiAgICBhYnN0cmFjdCByZWFkb25seSB1dWlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiAqKiBGZWF0dXJlIGZsYWcgdG8gZW5mb3JjZSBSb3V0ZSByZXVzZSBpbiBuYXRpdmUgd2F5IHByb3ZpZGVkIGZyb20gVGF1cnVzIE5nUnguXG4gICAgICpcbiAgICAgKiAgICAgIC0gSW50cm9kdWNlZCBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eS5cbiAgICAgKiAgICAgIC0gRGVmYXVsdCB2YWx1ZSBpcyBmYWxzZSwgYW5kIGNvbnRpbnVlcyB0byBvcGVyYXRlIGxpa2UgcHJldmlvdXMgbWFqb3IgdmVyc2lvbi5cbiAgICAgKiAgICAgIC0gSWYgc2V0IHRvIHRydWUgd2lsbCBlbmZvcmNlIFJvdXRlIHJldXNlIHN0cmF0ZWd5IGFuZCB3aWxsIHJlLWluaXRpYWxpemUgQ29tcG9uZW50IHdpdGggbmV3IE1vZGVsIGZvciB0aGUgbmV3IHBhcmFtcy5cbiAgICAgKi9cbiAgICBlbmZvcmNlUm91dGVSZXVzZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogKiogTW9kZWwgc3Vic2NyaXB0aW9uIHJlZi5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHByaXZhdGUgX21vZGVsU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgICAvKipcbiAgICAgKiAqKiBDb25zdHJ1Y3Rvci5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgICAgIHByb3RlY3RlZCByZWFkb25seSBjb21wb25lbnRTZXJ2aWNlOiBDb21wb25lbnRTZXJ2aWNlLFxuICAgICAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgbmF2aWdhdGlvblNlcnZpY2U6IE5hdmlnYXRpb25TZXJ2aWNlLFxuICAgICAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgYWN0aXZhdGVkUm91dGU6IEFjdGl2YXRlZFJvdXRlLFxuICAgICAgICBjbGFzc05hbWU6IHN0cmluZyA9IG51bGxcbiAgICApIHtcbiAgICAgICAgc3VwZXIoY2xhc3NOYW1lID8/IFRhdXJ1c0Jhc2VDb21wb25lbnQuQ0xBU1NfTkFNRSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogKiogTmF2aWdhdGUgdG8gcGFnZSB1c2luZyB7QGxpbmsgTmF2aWdhdGlvblNlcnZpY2UubmF2aWdhdGVUb30uXG4gICAgICovXG4gICAgbmF2aWdhdGVUbyhyZXBsYWNlVmFsdWVzPzogeyBba2V5OiBzdHJpbmddOiBBcnJheUVsZW1lbnQ8VGF1cnVzTmF2aWdhdGVBY3Rpb25bJ3JlcGxhY2VycyddPlsncmVwbGFjZVZhbHVlJ10gfSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5uYXZpZ2F0aW9uU2VydmljZS5uYXZpZ2F0ZVRvKHJlcGxhY2VWYWx1ZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICoqIE5hdmlnYXRlIGJhY2sgdG8gcHJldmlvdXMgcGFnZSB1c2luZyB7QGxpbmsgTmF2aWdhdGlvblNlcnZpY2UubmF2aWdhdGVCYWNrfS5cbiAgICAgKi9cbiAgICBuYXZpZ2F0ZUJhY2socmVwbGFjZVZhbHVlcz86IHsgW2tleTogc3RyaW5nXTogQXJyYXlFbGVtZW50PFRhdXJ1c05hdmlnYXRlQWN0aW9uWydyZXBsYWNlcnMnXT5bJ3JlcGxhY2VWYWx1ZSddIH0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMubmF2aWdhdGlvblNlcnZpY2UubmF2aWdhdGVCYWNrKHJlcGxhY2VWYWx1ZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0RG9jXG4gICAgICovXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIHRoaXMuYmluZE1vZGVsKCk7XG5cbiAgICAgICAgdGhpcy5pbml0aWFsaXplUm91dGVSZXVzZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0RG9jXG4gICAgICovXG4gICAgb3ZlcnJpZGUgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGVJZGxlKCk7XG5cbiAgICAgICAgc3VwZXIubmdPbkRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAqKiBJbnZva2luZyBtZXRob2QgcmVnaXN0ZXIgc3Vic2NyaWJlciBmb3IgVGF1cnVzIE5nUnggUmVkdXggU3RvcmUgbXV0YXRpb24gaW4gY29udGV4dCBvZiB7QGxpbmsgQ29tcG9uZW50U3RhdGUucm91dGVQYXRoU2VnbWVudHN9LFxuICAgICAqICAgICAgd2hpY2ggYmluZHMge0BsaW5rIENvbXBvbmVudE1vZGVsfSB0byB7QGxpbmsgVGF1cnVzQmFzZUNvbXBvbmVudC5tb2RlbH1cbiAgICAgKiAgICAgIGFuZCBzdGFydCBpbnZvY2F0aW9uIG9mIFRhdXJ1cyBOZ1J4IFJlZHV4IENvbXBvbmVudCBsaWZlY3ljbGUgaG9va3MuXG4gICAgICpcbiAgICAgKiAgICAgIDxiPkludm9jYXRpb24gb3JkZXI6PC9iPlxuICAgICAqXG4gICAgICogICAgICAxLiB7QGxpbmsgT25UYXVydXNNb2RlbEluaXR9XG4gICAgICogICAgICAyLiB7QGxpbmsgT25UYXVydXNNb2RlbEluaXRpYWxMb2FkfSBvciB7QGxpbmsgT25UYXVydXNNb2RlbEZpcnN0TG9hZH0gLSBvbmx5IG9uZSBjb3VsZCBiZSBpbnZva2UsXG4gICAgICogICAgICAgICAgICAgIHdoZXJlIGRlcHJlY2F0ZWQgc2hvdWxkbid0IGJlIGltcGxlbWVudGVkIGFueW1vcmUuXG4gICAgICogICAgICAzLiB7QGxpbmsgT25UYXVydXNNb2RlbExvYWR9XG4gICAgICogICAgICA0LiB7QGxpbmsgT25UYXVydXNNb2RlbENoYW5nZX0gd2hlbiBzdGF0dXMgaXMge0BsaW5rIExPQURFRH1cbiAgICAgKiAgICAgIDUuIHtAbGluayBPblRhdXJ1c01vZGVsRXJyb3J9IG9yIHtAbGluayBPblRhdXJ1c01vZGVsRmFpbH0gd2hlbiBzdGF0dXMgaXMge0BsaW5rIEZBSUxFRH0gLSBvbmx5IG9uZSBjb3VsZCBiZSBpbnZva2UsXG4gICAgICogICAgICAgICAgICAgIHdoZXJlIGRlcHJlY2F0ZWQgc2hvdWxkbid0IGJlIGltcGxlbWVudGVkIGFueW1vcmUuXG4gICAgICpcbiAgICAgKiAgICAgIDxwPlxuICAgICAqICAgICAgICAgIDxicj5cbiAgICAgKiAgICAgICAgICBPdmVycmlkZSBpdCBpZiB5b3Ugd2FudCB0byBjaGFuZ2UgZGVmYXVsdCBiZWhhdmlvci5cbiAgICAgKiAgICAgIDwvcD5cbiAgICAgKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYmluZE1vZGVsKCk6IHZvaWQge1xuICAgICAgICBsZXQgaXNPbk1vZGVsSW5pdGlhbExvYWRFeGVjdXRlZCA9IGZhbHNlO1xuXG4gICAgICAgIGlmICghVGF1cnVzQmFzZUNvbXBvbmVudC5fcm91dGVTdGF0ZUZhY3RvcnkpIHtcbiAgICAgICAgICAgIFRhdXJ1c0Jhc2VDb21wb25lbnQuX3JvdXRlU3RhdGVGYWN0b3J5ID0gbmV3IFJvdXRlU3RhdGVGYWN0b3J5KCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByb3V0ZVN0YXRlID0gVGF1cnVzQmFzZUNvbXBvbmVudC5fcm91dGVTdGF0ZUZhY3RvcnkuY3JlYXRlKHRoaXMuYWN0aXZhdGVkUm91dGUuc25hcHNob3QsIG51bGwpO1xuXG4gICAgICAgIHRoaXMuY29tcG9uZW50U2VydmljZS5pbml0KHRoaXMudXVpZCwgcm91dGVTdGF0ZSkuc3Vic2NyaWJlKChtb2RlbCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5tb2RlbCA9IG1vZGVsO1xuXG4gICAgICAgICAgICBUYXVydXNCYXNlQ29tcG9uZW50Ll9leGVjdXRlVGF1cnVzQ29tcG9uZW50SG9vayh0aGlzLCAnb25Nb2RlbEluaXQnLCBtb2RlbCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuX21vZGVsU3Vic2NyaXB0aW9uID0gdGhpcy5jb21wb25lbnRTZXJ2aWNlLmdldE1vZGVsKHRoaXMudXVpZCwgcm91dGVTdGF0ZS5yb3V0ZVBhdGhTZWdtZW50cykuc3Vic2NyaWJlKChtb2RlbCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFpc09uTW9kZWxJbml0aWFsTG9hZEV4ZWN1dGVkKSB7XG4gICAgICAgICAgICAgICAgaXNPbk1vZGVsSW5pdGlhbExvYWRFeGVjdXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKCFUYXVydXNCYXNlQ29tcG9uZW50Ll9leGVjdXRlVGF1cnVzQ29tcG9uZW50SG9vayh0aGlzLCAnb25Nb2RlbEluaXRpYWxMb2FkJywgbW9kZWwpKSB7XG4gICAgICAgICAgICAgICAgICAgIFRhdXJ1c0Jhc2VDb21wb25lbnQuX2V4ZWN1dGVUYXVydXNDb21wb25lbnRIb29rKHRoaXMsICdvbk1vZGVsRmlyc3RMb2FkJywgbW9kZWwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5ldmFsdWF0ZVRhdXJ1c0NvbXBvbmVudExpZmVjeWNsZUhvb2tzKG1vZGVsKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2godGhpcy5fbW9kZWxTdWJzY3JpcHRpb24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICoqIEV2YWx1YXRlcyBUYXVydXMgTmdSeCBSZWR1eCBDb21wb25lbnQgbGlmZWN5Y2xlIGhvb2tzXG4gICAgICogICAgICAoe0BsaW5rIE9uVGF1cnVzTW9kZWxMb2FkfSBhbmQge0BsaW5rIE9uVGF1cnVzTW9kZWxDaGFuZ2V9IGFuZCAoe0BsaW5rIE9uVGF1cnVzTW9kZWxGYWlsfSBvciB7QGxpbmsgT25UYXVydXNNb2RlbEVycm9yfSkpLlxuICAgICAqXG4gICAgICogICAgICAtIE92ZXJyaWRlIGl0IGlmIHlvdSB3YW50IHRvIGNoYW5nZSBkZWZhdWx0IGJlaGF2aW9yLlxuICAgICAqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIHByb3RlY3RlZCBldmFsdWF0ZVRhdXJ1c0NvbXBvbmVudExpZmVjeWNsZUhvb2tzKG1vZGVsOiBDb21wb25lbnRNb2RlbCk6IHZvaWQge1xuICAgICAgICBUYXVydXNCYXNlQ29tcG9uZW50Ll9leGVjdXRlVGF1cnVzQ29tcG9uZW50SG9vayh0aGlzLCAnb25Nb2RlbExvYWQnLCBtb2RlbCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmlzTW9kZWxNb2RpZmllZChtb2RlbCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHByZXZpb3VzTW9kZWwgPSB0aGlzLm1vZGVsO1xuXG4gICAgICAgIHRoaXMucmVmcmVzaE1vZGVsKG1vZGVsKTtcblxuICAgICAgICBpZiAobW9kZWwuc3RhdHVzID09PSBGQUlMRUQpIHtcbiAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzRXJyb3JSZWNvcmRzOiBFcnJvclJlY29yZFtdID1cbiAgICAgICAgICAgICAgICBwcmV2aW91c01vZGVsIGluc3RhbmNlb2YgQ29tcG9uZW50TW9kZWwgPyBwcmV2aW91c01vZGVsLmdldENvbXBvbmVudFN0YXRlKCkuZXJyb3JzLnJlY29yZHMgOiBbXTtcbiAgICAgICAgICAgIGNvbnN0IGRpc3RpbmN0RXJyb3JSZWNvcmRzRnJvbVByZXZpb3VzQ3ljbGUgPSBtb2RlbC5nZXRDb21wb25lbnRTdGF0ZSgpLmVycm9ycy5kaXN0aW5jdEVycm9yUmVjb3JkcyhwcmV2aW91c0Vycm9yUmVjb3Jkcyk7XG5cbiAgICAgICAgICAgIGlmICghVGF1cnVzQmFzZUNvbXBvbmVudC5fZXhlY3V0ZVRhdXJ1c0NvbXBvbmVudEhvb2sodGhpcywgJ29uTW9kZWxFcnJvcicsIG1vZGVsLCBkaXN0aW5jdEVycm9yUmVjb3Jkc0Zyb21QcmV2aW91c0N5Y2xlKSkge1xuICAgICAgICAgICAgICAgIFRhdXJ1c0Jhc2VDb21wb25lbnQuX2V4ZWN1dGVUYXVydXNDb21wb25lbnRIb29rKHRoaXMsICdvbk1vZGVsRmFpbCcsIG1vZGVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFRhdXJ1c0Jhc2VDb21wb25lbnQuX2V4ZWN1dGVUYXVydXNDb21wb25lbnRIb29rKHRoaXMsICdvbk1vZGVsQ2hhbmdlJywgbW9kZWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplTW9kZWxTdGF0ZShtb2RlbCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFRhdXJ1cyBOZ1J4IFJlZHV4IGZhaWxlZCB0byBub3JtYWxpemUgQ29tcG9uZW50TW9kZWwhYCwgZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAqKiBSZWZyZXNoIG1vZGVsIGZpZWxkIHtAbGluayBUYXVydXNCYXNlQ29tcG9uZW50Lm1vZGVsfSB3aXRoIG5ldyBvbmUsXG4gICAgICogICAgICBhbmQgYXNzaWducyBwcmV2aW91cyBtb2RlbCByZWZlcmVuY2UgdG8gZmllbGQge0BsaW5rIENvbXBvbmVudE1vZGVsLnByZXZpb3VzTW9kZWx9IGluIHRoZSBuZXcgbW9kZWwsXG4gICAgICogICAgICB0byB0aGUgbWF4IGRlcHRoIDMuXG4gICAgICpcbiAgICAgKiAgICAgIC0gQWxsIGFzc2lnbm1lbnRzIGFyZSBieSByZWZlcmVuY2UuXG4gICAgICogICAgICAtIE92ZXJyaWRlIGl0IGlmIHlvdSB3YW50IHRvIGNoYW5nZSBkZWZhdWx0IGJlaGF2aW9yLlxuICAgICAqICAgICAgLSA8Yj5CZSBjYXV0aW91cyBhYm91dCB5b3VyIGNoYW5nZXMgYW5kIGludGVudHMhPC9iPiBJdCBjb3VsZCBhZmZlY3QgZmVhdHVyZXMgdGhhciBkZXBlbmQgb24gdGhpcyBtZXRob2QgSW1wbC5cbiAgICAgKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVmcmVzaE1vZGVsKG1vZGVsOiBDb21wb25lbnRNb2RlbCk6IHZvaWQge1xuICAgICAgICAvLyBwdXJnZSBjb21wb25lbnQgRXJyb3JTdG9yZSB3aXRoIGRhdGEgZnJvbSBDb21wb25lbnRNb2RlbCBFcnJvclN0b3JlXG4gICAgICAgIHRoaXMuZXJyb3JzLnB1cmdlKG1vZGVsLmdldENvbXBvbmVudFN0YXRlKCkuZXJyb3JzKTtcblxuICAgICAgICAvLyBhc3NpZ24gY3VycmVudCBtb2RlbCBhcyBwcmV2aW91cyB0byB0aGUgbmV3IG9uZVxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgbW9kZWxbJ3ByZXZpb3VzTW9kZWwnXSA9IHRoaXMubW9kZWw7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2RvdC1ub3RhdGlvblxuXG4gICAgICAgIC8vIGNsZWFuIHByZXZpb3VzIG1vZGVscyB0aGF0IGV4Y2VlZCBtYXggZGVwdGggM1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbGV0IGRlcHRoTGV2ZWwgPSAxO1xuICAgICAgICAgICAgbGV0IHByZXZpb3VzTW9kZWwgPSBtb2RlbC5wcmV2aW91c01vZGVsO1xuXG4gICAgICAgICAgICB3aGlsZSAocHJldmlvdXNNb2RlbCBpbnN0YW5jZW9mIENvbXBvbmVudE1vZGVsKSB7XG4gICAgICAgICAgICAgICAgaWYgKCsrZGVwdGhMZXZlbCA8PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzTW9kZWwgPSBwcmV2aW91c01vZGVsLnByZXZpb3VzTW9kZWw7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzTW9kZWwucHJldmlvdXNNb2RlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHByZXZpb3VzTW9kZWxbJ3ByZXZpb3VzTW9kZWwnXTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvZG90LW5vdGF0aW9uXG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBjbGVhbiBwcmV2aW91cyBDb21wb25lbnRNb2RlbCcsIGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gYXNzaWduIG1vZGVsIGFzIGN1cnJlbnRcbiAgICAgICAgdGhpcy5tb2RlbCA9IG1vZGVsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICoqIE5vcm1hbGl6ZSBNb2RlbCBzdGF0ZSwgYnkgZGVmYXVsdCBpdCBjbGVhciBUYXNrIGZpZWxkIGluIHtAbGluayBDb21wb25lbnRTdGF0ZS50YXNrfSBhbmQgdXBkYXRlIG1vZGVsIGluIFRhdXJ1cyBOZ1J4IFJlZHV4IFN0b3JlLlxuICAgICAqXG4gICAgICogICAgICAtIEl0IGlzIGludm9rZWQgb25seSBpZiB7QGxpbmsgQ29tcG9uZW50TW9kZWx9IGlzIG1vZGlmaWVkIGFuZCBhZnRlciBpbnZvY2F0aW9uIG9mIGFsbCBUYXVydXMgY29tcG9uZW50cyBsaWZlY3ljbGUgaG9va3MuXG4gICAgICogICAgICAtIE92ZXJyaWRlIGl0IGlmIHlvdSB3YW50IHRvIGNoYW5nZSBkZWZhdWx0IGJlaGF2aW9yLlxuICAgICAqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIHByb3RlY3RlZCBub3JtYWxpemVNb2RlbFN0YXRlKG1vZGVsOiBDb21wb25lbnRNb2RlbCk6IHZvaWQge1xuICAgICAgICB0aGlzLmNvbXBvbmVudFNlcnZpY2UudXBkYXRlKG1vZGVsLmNsZWFyVGFzaygpLmdldENvbXBvbmVudFN0YXRlKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICoqIFNldCBNb2RlbCBzdGF0ZSBpbiBJRExFIHRvIHN0b3AgbGlzdGVuaW5nIG9uIEV2ZW50cyBmcm9tIFN0b3JlLlxuICAgICAqXG4gICAgICogICAgICAtIEl0IGlzIGludm9rZWQgYnkgZGVmYXVsdCBiZWZvcmUgQ29tcG9uZW50IGlzIGRlc3Ryb3llZCwgaW4gQW5ndWxhciBsaWZlY3ljbGUgaG9vayB7QGxpbmsgT25EZXN0cm95fS5cbiAgICAgKiAgICAgIC0gT3ZlcnJpZGUgaXQgaWYgeW91IHdhbnQgdG8gY2hhbmdlIGRlZmF1bHQgYmVoYXZpb3IuXG4gICAgICpcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHNldFN0YXRlSWRsZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jb21wb25lbnRTZXJ2aWNlLmlkbGUodGhpcy5tb2RlbC5wcmVwYXJlRm9yRGVzdHJveSgpLmdldENvbXBvbmVudFN0YXRlKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICoqIEV2YWx1YXRpb24gb2YgdGhpcyBtZXRob2QgYWNrbm93bGVkZ2UgdGhhdCBuZXcge0BsaW5rIENvbXBvbmVudE1vZGVsfSBpcyBtb2RpZmllZCBvciBub3QuXG4gICAgICpcbiAgICAgKiAgICAgIC0gQ29tcGFyaXNvbiBpcyBldmFsdWF0ZWQgYmV0d2VlbiBwcm92aWRlZCBNb2RlbCBhbmQgYXNzaWduZWQgQ29tcG9uZW50J3MgTW9kZWwge0BsaW5rIFRhdXJ1c0Jhc2VDb21wb25lbnQubW9kZWx9LlxuICAgICAqICAgICAgLSBEZWZhdWx0IGltcGxlbWVudGF0aW9uIHVzZSB7QGxpbmsgQ29tcG9uZW50TW9kZWwuaXNNb2RpZmllZH0gZm9yIGRlZXAgQ29tcGFyaXNvbiBvZiBzcGVjaWZpYyBmaWVsZHMuXG4gICAgICogICAgICAtIE92ZXJyaWRlIGl0IGlmIHlvdSB3YW50IHRvIGNoYW5nZSBkZWZhdWx0IGJlaGF2aW9yLlxuICAgICAqXG4gICAgICogPHA+XG4gICAgICogICAgICA8Yj5CZSBjYXV0aW91cyBhYm91dCB5b3VyIGNoYW5nZXMgYW5kIGludGVudHMhPC9iPlxuICAgICAqICAgICAgRXhhbXBsZXMgd2hhdCBjYW4gd3JvbmcgY29tcGFyaXNvbiBkbz9cbiAgICAgKiA8L3A+XG4gICAgICpcbiAgICAgKiAgICAgIDEuIEluZmluaXRlIGxpZmVjeWNsZSBob29rcyBpbnZvY2F0aW9uLCB3aGVyZSBjb25zZXF1ZW5jZXMgYXJlOiBwZXJmb3JtYW5jZSBkZXRlcmlvcmF0aW9uIG9yIGFwcGxpY2F0aW9uIGZyZWV6ZS5cbiAgICAgKiAgICAgIDIuIFByZXZlbnQgbGlmZWN5Y2xlIGhvb2tzIGludm9jYXRpb24sIHdoZXJlIGNvbnNlcXVlbmNlcyBhcmU6IHlvdXIgRGF0YSBuZXZlciBhcnJpdmUgdG8geW91ciBDb21wb25lbnQgZmllbGRzLlxuICAgICAqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIHByb3RlY3RlZCBpc01vZGVsTW9kaWZpZWQobW9kZWw6IENvbXBvbmVudE1vZGVsKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBtb2RlbC5pc01vZGlmaWVkKHRoaXMubW9kZWwpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICoqIEluaXRpYWxpemUgUm91dGUgcmV1c2Ugc3RyYXRlZ3kgZm9yIENvbXBvbmVudCBpbiBjb250ZXh0IG9mIFRhdXJ1cyBOZ1J4LlxuICAgICAqICAgICAgLSBUdXJucyBvbiBsaXN0ZW5lciBmb3IgQWN0aXZhdGVkIHBhcmFtcyBjaGFuZ2UgYW5kIGlmIGRldGVjdHMgbXV0YXRpb25cbiAgICAgKiAgICAgICAgICAgICAgc2V0cyBjdXJyZW50IG1vZGVsIGluIGN1cnJlbnQgUm91dGVQYXRoU2VnbWVudCB0byBpZGxlLFxuICAgICAqICAgICAgICAgICAgICBhbmQgYmluZCBmb3IgbmV3IG1vZGVsIHN0cmVhbSB0byB0aGUgbmV3IFJvdXRlUGF0aFNlZ21lbnQuXG4gICAgICogICAgICAtIE5ldyBmZWF0dXJlIHRoaXMgaXMgY29tcGxldGVseSBiYWNrd2FyZCBjb21wYXRpYmxlLFxuICAgICAqICAgICAgICAgICAgICBhbmQgaXQgY2FuIGJlIHR1cm5lZCBvbiB3aXRoIGZlYXR1cmUgZmxhZyBwZXIgQ29tcG9uZW50IENsYXNzLlxuICAgICAqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIHByb3RlY3RlZCBpbml0aWFsaXplUm91dGVSZXVzZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLmVuZm9yY2VSb3V0ZVJldXNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcHJldmlvdXNQYXJhbXM6IFBhcmFtcztcblxuICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgICAgICAgIHRoaXMuYWN0aXZhdGVkUm91dGUucGFyYW1zLnN1YnNjcmliZSgocGFyYW1zKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKENvbGxlY3Rpb25zVXRpbC5pc05pbChwcmV2aW91c1BhcmFtcykpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNQYXJhbXMgPSBwYXJhbXM7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghQ29sbGVjdGlvbnNVdGlsLmlzRXF1YWwocHJldmlvdXNQYXJhbXMsIHBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNQYXJhbXMgPSBwYXJhbXM7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNSZW1vdmVTdWNjZXNzZnVsID0gdGhpcy5yZW1vdmVTdWJzY3JpcHRpb25SZWYodGhpcy5fbW9kZWxTdWJzY3JpcHRpb24pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNSZW1vdmVTdWNjZXNzZnVsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzZXQgY3VycmVudCBSb3V0ZVBhdGhTZWdtZW50IG1vZGVsIHN0YXRlIHRvIGlkbGVcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGVJZGxlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBiaW5kIG5ldyBtb2RlbCBzdHJlYW0gdG8gbmV3IFJvdXRlUGF0aFNlZ21lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmluZE1vZGVsKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICoqIEludm9rZSBUYXVydXMgTmdSeCBSZWR1eCBDb21wb25lbnQgbGlmZWN5Y2xlIGhvb2suXG4gICAgICpcbiAgICAgKiAgICAgIC0gTGlmZWN5Y2xlIGhvb2tzIGFyZSBpbnZva2VkIG9ubHkgaWYgaW1wbGVtZW50YXRpb24gdGhleSBhcmUgZm91bmQgYXMgaW1wbGVtZW50ZWQgaW4gc3ViY2xhc3Nlcy5cbiAgICAgKiAgICAgIC0gUmV0dXJucyB0cnVlIGlmIG1ldGhvZCBpcyBmb3VuZCBhbmQgZXhlY3V0ZWQsIG90aGVyd2lzZSBmYWxzZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9tZW1iZXItb3JkZXJpbmdcbiAgICBwcml2YXRlIHN0YXRpYyBfZXhlY3V0ZVRhdXJ1c0NvbXBvbmVudEhvb2soXG4gICAgICAgIGluc3RhbmNlOiBUYXVydXNCYXNlQ29tcG9uZW50LFxuICAgICAgICBtZXRob2Q6IGtleW9mIFRhdXJ1c0NvbXBvbmVudEhvb2tzLFxuICAgICAgICBtb2RlbDogQ29tcG9uZW50TW9kZWwsXG4gICAgICAgIC4uLmFkZGl0aW9uYWxQYXJhbXM6IGFueVtdXG4gICAgKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuXG4gICAgICAgIGlmIChDb2xsZWN0aW9uc1V0aWwuaXNGdW5jdGlvbihpbnN0YW5jZVttZXRob2RdKSkge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudFRhc2sgPSBtb2RlbC5nZXRUYXNrKCk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKENvbGxlY3Rpb25zVXRpbC5pc1N0cmluZyhjdXJyZW50VGFzaykpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtY2FsbFxuICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZVttZXRob2RdKG1vZGVsLCBjdXJyZW50VGFzaywgLi4uYWRkaXRpb25hbFBhcmFtcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtY2FsbFxuICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZVttZXRob2RdKG1vZGVsLCB1bmRlZmluZWQsIC4uLmFkZGl0aW9uYWxQYXJhbXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBUYXVydXMgTmdSeCBSZWR1eCBmYWlsZWQgdG8gZXhlY3V0ZSBsaWZlY3ljbGUgaG9vayBcIiR7bWV0aG9kfVwiIWAsIGUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG4iXX0=