UNPKG

com.phloxui

Version:

PhloxUI Ng2+ Framework

643 lines (642 loc) 59.8 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ import { Component, ViewChild } from '@angular/core'; import { Router } from '@angular/router'; import { PhloxAppInfoService } from '../service/PhloxAppInfoService.service'; import { PhloxAppService } from '../service/PhloxAppService.service'; import { ObservableManager } from '../service/ObservableManager.service'; import { NeedFocusService } from '../service/NeedFocusService.service'; import { DialogService } from '../service/DialogService.service'; import { BackgroundProcessManager } from '../service/BackgroundProcessManager.service'; import { AbstractNavLeftLayout } from './AbstractNavLeftLayout'; import { MaterialBarLoader } from '../theme/material/component/MaterialBarLoader.component'; const /** @type {?} */ TYPE_NAME = "phx-app"; /** * <p style="text-indent: 2em;"> * A main bootstrap component class for <code>PhloxUI</code> application. This class implements the [[INavigator]] interface having pages ([[AbstractPage]]) * as <code>navigatee</code> items ([[INavigatee]]). An <code>application</code> may consist of various pages, for example, it may have a login page to allow the user to * login, once the user is logged on, it will navigate the user to the main page, etc. * </p> * * @author shiorin, tee4cute */ export class PhloxApp { /** * @param {?} router * @param {?} appInfoService * @param {?} appSvc * @param {?} observableMgr * @param {?} needFocusService * @param {?} dialogService * @param {?} bgProcessMgr */ constructor(router, appInfoService, appSvc, observableMgr, needFocusService, dialogService, bgProcessMgr) { this.curRouterLoading = { "path": null, "resolve": null, "reject": null }; this.pages = []; this.router = router; this.appInfoService = appInfoService; this.observableMgr = observableMgr; this.needFocusService = needFocusService; this.reloadAppInfo(); this.dialogService = dialogService; this.bgProcessMgr = bgProcessMgr; this._showLoader = false; // Set app instance to PhloxAppService to allow others to access this instance. appSvc.setInstance(this); // init dialog service this.dialogService.init(this); this.observableMgr.subscribe(BackgroundProcessManager.PROCESS_START_TOPIC_NAME, (startBGProcess) => { if (startBGProcess.type === 'connection.page') { this.runPageLoader(); } }); this.observableMgr.subscribe(BackgroundProcessManager.PROCESS_END_TOPIC_NAME, (endBGProcess) => { if (endBGProcess.type === 'connection.page') { if (this.bgProcessMgr.getRunningProcessesCount('connection.page', null) <= 0) { this.stopPageLoader(); } } }); this.observableMgr.subscribe(BackgroundProcessManager.PROCESS_ERROR_TOPIC_NAME, (errorBGProcess) => { if (errorBGProcess.type === 'connection.page') { if (this.bgProcessMgr.getRunningProcessesCount('connection.page', null) <= 0) { this.stopPageLoader(); } } }); } /** * @return {?} */ ngOnInit() { this.observableMgr.subscribe(AbstractNavLeftLayout.FIXED_CHANGE_TOPIC_NAME, (layout) => { console.log('Nav left "' + layout.getSubTopicName() + '" fixed: ' + layout.fixed); }); this.observableMgr.subscribe(AbstractNavLeftLayout.TOGGLED_CHANGE_TOPIC_NAME, (layout) => { console.log('Nav left "' + layout.getSubTopicName() + '" toggled: ' + layout.toggled); }); // fixed=false, toggled=true setTimeout(() => { this.observableMgr.publish(AbstractNavLeftLayout.TOGGLED_CMD_TOPIC_NAME, true); }, 1500); // fixed=false, toggled=false setTimeout(() => { this.observableMgr.publish(AbstractNavLeftLayout.TOGGLED_CMD_TOPIC_NAME, false); }, 3000); // fixed=true, toggled=false setTimeout(() => { this.observableMgr.publish(AbstractNavLeftLayout.FIXED_CMD_TOPIC_NAME, true); }, 3500); // fixed=true, toggled=true setTimeout(() => { this.observableMgr.publish(AbstractNavLeftLayout.TOGGLED_CMD_TOPIC_NAME, true); }, 4500); // fixed=true, toggled=false setTimeout(() => { this.observableMgr.publish(AbstractNavLeftLayout.TOGGLED_CMD_TOPIC_NAME, false); }, 6000); // fixed=false, toggled=false setTimeout(() => { this.observableMgr.publish(AbstractNavLeftLayout.FIXED_CMD_TOPIC_NAME, false); }, 6500); } /** * @return {?} */ isShowLoader() { return this._showLoader; } /** * <p style="text-indent: 1em;"> * Get app info of currently opened <code>application</code>. * </p> * @return {?} */ getAppInfo() { return this.appInfo; } /** * <p style="text-indent: 1em;"> * Reload the app info from <code>PhloxAppInfoService</code>. * </p> * @return {?} */ reloadAppInfo() { return this.appInfoService.reload().then((result) => { this.appInfo = result; return Promise.resolve(this.appInfo); }); } /** * @return {?} */ getRouter() { return this.router; } /** * <p style="text-indent: 1em;"> * Get all available <code>pages</code> ([[AbstractPage]]) in this <code>application</code>. * </p> * * @see [[INavigator.getItems]] * @return {?} */ getItems() { return this.pages; } /** * <p style="text-indent: 1em;"> * Get all available <code>page</code> count ([[AbstractPage]]) in this <code>application</code>. * </p> * * @see [[INavigator.getItemCount]] * @return {?} */ getItemCount() { return this.pages.length; } /** * <p style="text-indent: 1em;"> * Get current active <code>page</code> ([[AbstractPage]]) index in the array returned from [[getItems]] method. * </p> * * @see [[INavigator.getActiveIndex]] * @return {?} Returns <code>-1</code> if there is no current active <code>page</code>. */ getActiveIndex() { for (let /** @type {?} */ i = 0; i < this.pages.length; i++) { if (this.pages[i].isActive()) { return i; } } return -1; } /** * <p style="text-indent: 1em;"> * Get current active <code>page</code> ([[AbstractPage]]) object instance. * </p> * * @see [[INavigator.getActiveItem]] * @return {?} Returns <code>null</code> if there is no current active <code>page</code>. */ getActiveItem() { let /** @type {?} */ idx = this.getActiveIndex(); if (idx < 0) { return null; } return this.pages[idx]; } /** * <p style="text-indent: 1em;"> * An implementation of [[INavigator.setItems]] method. Please see the documentation of super class or super interface for more details. * </p> * * @see [[INavigator.setItems]] * @param {?} items * @return {?} */ setItems(items) { this.pages = items; } /** * <p style="text-indent: 1em;"> * Add a new <code>page</code> ([[AbstractPage]]) into this <code>application</code>. If the <code>page</code> (<code><b>item</b></code>) being added is the * first <code>page</code> of this <code>application</code>, this method will automatically show the given <code>page</code> and set its <code>active</code> * flag to <code>true</code>. * </p> * * @see [[INavigator.addItem]] * @param {?} item * @return {?} */ addItem(item) { if (this.containsItem(item)) { return false; } this.pages.push(item); if (this.pages.length === 1) { // This is the first one. So, it should be active! item.active = true; } return true; } /** * <p style="text-indent: 1em;"> * Remove the given <code>page</code> ([[AbstractPage]]) from this <code>application</code>. If the <code>page</code> (<code><b>item</b></code>) being removed is * currently active, this method will automatically unset its <code>active</code> flag and show the first <code>page</code> (if available) in the array returned from * [[getItems]] method instead. * </p> * * @see [[INavigator.removeItem]] * @param {?} item * @return {?} */ removeItem(item) { let /** @type {?} */ idx = this.pages.indexOf(item); if (idx < 0) { return false; } this.pages = this.pages.slice(idx, 1); if (item.active) { // Set page active to false. item.active = false; // If it is currently active page, we've to navigate to another one. this.navigateToIndex(0); } return true; } /** * <p style="text-indent: 1em;"> * An implementation of [[INavigator.containsItem]] method. Please see the documentation of super class or super interface for more details. * </p> * * @see [[INavigator.containsItem]] * @param {?} item * @return {?} */ containsItem(item) { return this.pages.indexOf(item) >= 0; } /** * <p style="text-indent: 1em;"> * An implementation of [[INavigator.getItemByIndex]] method. Please see the documentation of super class or super interface for more details. * </p> * * @see [[INavigator.getItemByIndex]] * @param {?} idx * @return {?} */ getItemByIndex(idx) { if (idx < 0 || idx >= this.pages.length) { return null; } return this.pages[idx]; } /** * <p style="text-indent: 1em;"> * An implementation of [[INavigator.getItemByName]] method. Please see the documentation of super class or super interface for more details. * </p> * * @see [[INavigator.getItemByName]] * @param {?} name * @return {?} */ getItemByName(name) { let /** @type {?} */ idx = this.getItemIndexByName(name); if (idx < 0) { return null; } return this.pages[idx]; } /** * <p style="text-indent: 1em;"> * An implementation of [[INavigator.getItemIndex]] method. Please see the documentation of super class or super interface for more details. * </p> * * @see [[INavigator.getItemIndex]] * @param {?} item * @return {?} */ getItemIndex(item) { return this.pages.indexOf(item); } /** * <p style="text-indent: 1em;"> * An implementation of [[INavigator.getItemIndexByName]] method. Please see the documentation of super class or super interface for more details. * </p> * * @see [[INavigator.getItemIndexByName]] * @param {?} name * @return {?} */ getItemIndexByName(name) { for (let /** @type {?} */ i = 0; i < this.pages.length; i++) { if (this.pages[i].getName() === name) { return i; } } return -1; } /** * <p style="text-indent: 1em;"> * An alias method of [[navigateToName]] passing <code>page</code>'s name ([[AbstractPage.getName]]) as a parameter. * </p> * * @see [[INavigator.navigateTo]] * @see [[navigateToName]] * @param {?} item * @param {?=} options * @return {?} */ navigateTo(item, options) { return this.navigateToName(item.getName(), options); } /** * <p style="text-indent: 1em;"> * An alias method of [[navigateTo]] passing <code>page</code> instance at the given index (<code><b>idx</b></code>) as a parameter. * </p> * * @see [[INavigator.navigateToIndex]] * @see [[navigateTo]] * @param {?} idx * @param {?=} options * @return {?} */ navigateToIndex(idx, options) { let /** @type {?} */ page = this.getItemByIndex(idx); if (page === null) { return Promise.resolve(false); } return this.navigateTo(page, options); } /** * <p style="text-indent: 1em;"> * Navigate this <code>application</code> to the given <code>page</code> <code><b>name</b></code>. The <code>page</code> name is also a * <code>router</code>'s uri path specified in [[PHLOX_ROUTES]]. * </p> * * @see [[INavigator.navigateToName]] * @see [[PHLOX_ROUTES]] * @param {?} name * @param {?=} options * @return {?} */ navigateToName(name, options) { let /** @type {?} */ link = name; if (link === null || typeof link !== 'string') { return Promise.resolve(false); } if (link.length <= 0) { return Promise.resolve(false); } if (link.charAt(0) !== '/') { link = '/' + link; } if (this.router.url === link) { // Currently active return Promise.resolve(false); } let /** @type {?} */ nav = [link]; if (options !== null && options !== undefined) { nav.push(options); } // Navigate to specified link return this.router.navigate(nav).then((success) => { if (success) { let /** @type {?} */ curActive = this.getActiveItem(); if (curActive !== null) { // Set current page active to false curActive.active = false; } let /** @type {?} */ newPage = this.getItemByName(link.substring(1)); if (newPage !== null) { newPage.active = true; } } else { console.warn('Could not navigate to "' + name + '".'); } return Promise.resolve(success); }); } /** * <p style="text-indent: 1em;"> * Try to navigate this <code>application</code> back to the first <code>page</code>. * </p> * * @see [[INavigator.reset]] * @return {?} */ reset() { this.navigateToIndex(0); } /** * <p style="text-indent: 1em;"> * A delegator method passing method call to <code>[[needFocusService]].setFocusingComponent()</code>. * </p> * * @see [[NeedFocusService.setFocusingComponent]] * @param {?} component * @param {?=} event * @return {?} */ setFocusingComponent(component, event) { this.needFocusService.setFocusingComponent(component, event); } /** * <p style="text-indent: 1em;"> * A delegator method passing method call to <code>[[needFocusService]].getFocusingComponent()</code>. * </p> * * @see [[NeedFocusService.getFocusingComponent]] * @return {?} */ getFocusingComponent() { return this.needFocusService.getFocusingComponent(); } /** * <p style="text-indent: 1em;"> * A delegator method passing method call to <code>[[needFocusService]].resetFocusingComponent()</code>. * </p> * * @see [[NeedFocusService.resetFocusingComponent]] * @param {?=} event * @return {?} */ resetFocusingComponent(event) { this.needFocusService.resetFocusingComponent(event); } /** * <p style="text-indent: 1em;"> * A delegator method passing method call to <code>[[phloxDialog]].hideDialog()</code>. * </p> * * @see [[PhloxDialog.hideDialog]] * @return {?} */ hideDialog() { if (this.phloxDialog != null) { return this.phloxDialog.hideDialog(); } } /** * <p style="text-indent: 1em;"> * A delegator method passing method call to <code>[[phloxDialog]].showConfirmDialog()</code>. * </p> * * @see [[PhloxDialog.showConfirmDialog]] * @param {?} title * @param {?} message * @param {?} showCancelBtn * @param {?=} width * @param {?=} height * @return {?} */ showConfirmDialog(title, message, showCancelBtn, width, height) { if (this.phloxDialog != null) { return this.phloxDialog.showConfirmDialog(title, message, showCancelBtn, width, height); } return new Promise((resolve, reject) => { reject('Could not find PhloxDialog instance.'); }); } /** * <p style="text-indent: 1em;"> * A delegator method passing method call to <code>[[phloxDialog]].showMessageDialog()</code>. * </p> * * @see [[PhloxDialog.showMessageDialog]] * @param {?} title * @param {?} message * @param {?=} width * @param {?=} height * @return {?} */ showMessageDialog(title, message, width, height) { if (this.phloxDialog != null) { return this.phloxDialog.showMessageDialog(title, message, width, height); } return new Promise((resolve, reject) => { reject('Could not find PhloxDialog instance.'); }); } /** * <p style="text-indent: 1em;"> * A delegator method passing method call to <code>[[phloxDialog]].showComponentDialog()</code>. * </p> * * @see [[PhloxDialog.showComponentDialog]] * @param {?} componentDialogModel * @return {?} */ showComponentDialog(componentDialogModel) { if (this.phloxDialog != null) { return this.phloxDialog.showComponentDialog(componentDialogModel); } return new Promise((resolve, reject) => { reject('Could not find PhloxDialog instance.'); }); } /** * @return {?} */ runPageLoader() { if (this.barloader === null || typeof this.barloader === 'undefined') { return; } this._showLoader = true; if (!this.barloader.isRunning()) { this.barloader.start(); } } /** * @return {?} */ stopPageLoader() { if (this.barloader === null || typeof this.barloader === 'undefined') { return; } this._showLoader = false; if (this.barloader.isRunning()) { this.barloader.stop(); } } } PhloxApp.TYPE_NAME = TYPE_NAME; PhloxApp.decorators = [ { type: Component, args: [{ moduleId: module.id, selector: 'phx-app', template: `<div class="phlox-app-bar-container" [class.show]="isShowLoader()"> <material-bar-loader #barloader></material-bar-loader> </div> <router-outlet></router-outlet> <phx-dialog #dialog></phx-dialog> ` },] }, ]; /** @nocollapse */ PhloxApp.ctorParameters = () => [ { type: Router, }, { type: PhloxAppInfoService, }, { type: PhloxAppService, }, { type: ObservableManager, }, { type: NeedFocusService, }, { type: DialogService, }, { type: BackgroundProcessManager, }, ]; PhloxApp.propDecorators = { "phloxDialog": [{ type: ViewChild, args: ['dialog',] },], "barloader": [{ type: ViewChild, args: ["barloader",] },], }; function PhloxApp_tsickle_Closure_declarations() { /** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */ PhloxApp.decorators; /** * @nocollapse * @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>} */ PhloxApp.ctorParameters; /** @type {!Object<string,!Array<{type: !Function, args: (undefined|!Array<?>)}>>} */ PhloxApp.propDecorators; /** @type {?} */ PhloxApp.TYPE_NAME; /** * This field will be automatically injected by <code>ng</code>. * @type {?} */ PhloxApp.prototype.appInfoService; /** * This field will be automatically injected by <code>ng</code>. * @type {?} */ PhloxApp.prototype.observableMgr; /** * This field will be automatically injected by <code>ng</code>. * @type {?} */ PhloxApp.prototype.needFocusService; /** * A field keeping cache for the last successfully loaded [[PhloxAppInfo]] from method [[reloadAppInfo]]. * @type {?} */ PhloxApp.prototype.appInfo; /** * An array keeping all <code>page</code>s of this <code>application</code>. * @type {?} */ PhloxApp.prototype.pages; /** * This field will be automatically injected by <code>ng</code>. * @type {?} */ PhloxApp.prototype.router; /** * This field will be automatically injected by <code>ng</code>. * @type {?} */ PhloxApp.prototype.dialogService; /** * This field will be automatically injected by <code>ng</code>. * @type {?} */ PhloxApp.prototype.bgProcessMgr; /** * A [[PhloxDialog]] child component instance of this component. * @type {?} */ PhloxApp.prototype.phloxDialog; /** @type {?} */ PhloxApp.prototype.barloader; /** @type {?} */ PhloxApp.prototype._showLoader; /** @type {?} */ PhloxApp.prototype.curRouterLoading; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGhsb3hBcHAuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vY29tLnBobG94dWkvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50L1BobG94QXBwLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0QsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXpDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQzdFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUNyRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUN6RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUN2RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDakUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFJdkYsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seURBQXlELENBQUM7QUFFNUYsdUJBQU0sU0FBUyxHQUFXLFNBQVMsQ0FBQzs7Ozs7Ozs7OztBQXFCcEMsTUFBTTs7Ozs7Ozs7OztJQWtESixZQUFZLE1BQWMsRUFBRSxjQUFtQyxFQUFFLE1BQXVCLEVBQUUsYUFBZ0MsRUFBRSxnQkFBa0MsRUFDNUosYUFBNEIsRUFBRSxZQUFzQztnQ0FQdEM7WUFDOUIsTUFBTSxFQUFFLElBQUk7WUFDWixTQUFTLEVBQUUsSUFBSTtZQUNmLFFBQVEsRUFBRSxJQUFJO1NBQ2Y7UUFJQyxJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNoQixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJ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T25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBQaGxveEFwcEluZm8sIENvbXBvbmVudERpYWxvZ01vZGVsIH0gZnJvbSAnLi9tb2RlbC9tb2RlbHMnO1xuaW1wb3J0IHsgUGhsb3hBcHBJbmZvU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2UvUGhsb3hBcHBJbmZvU2VydmljZS5zZXJ2aWNlJztcbmltcG9ydCB7IFBobG94QXBwU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2UvUGhsb3hBcHBTZXJ2aWNlLnNlcnZpY2UnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZU1hbmFnZXIgfSBmcm9tICcuLi9zZXJ2aWNlL09ic2VydmFibGVNYW5hZ2VyLnNlcnZpY2UnO1xuaW1wb3J0IHsgTmVlZEZvY3VzU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2UvTmVlZEZvY3VzU2VydmljZS5zZXJ2aWNlJztcbmltcG9ydCB7IERpYWxvZ1NlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlL0RpYWxvZ1NlcnZpY2Uuc2VydmljZSc7XG5pbXBvcnQgeyBCYWNrZ3JvdW5kUHJvY2Vzc01hbmFnZXIgfSBmcm9tICcuLi9zZXJ2aWNlL0JhY2tncm91bmRQcm9jZXNzTWFuYWdlci5zZXJ2aWNlJztcbmltcG9ydCB7IElOYXZpZ2F0b3IgfSBmcm9tICcuL0lOYXZpZ2F0b3InO1xuaW1wb3J0IHsgSU5lZWRGb2N1cyB9IGZyb20gJy4vSU5lZWRGb2N1cyc7XG5pbXBvcnQgeyBBYnN0cmFjdFBhZ2UgfSBmcm9tICcuL0Fic3RyYWN0UGFnZSc7XG5pbXBvcnQgeyBBYnN0cmFjdE5hdkxlZnRMYXlvdXQgfSBmcm9tICcuL0Fic3RyYWN0TmF2TGVmdExheW91dCc7XG5pbXBvcnQgeyBNYXRlcmlhbEJhckxvYWRlciB9IGZyb20gJy4uL3RoZW1lL21hdGVyaWFsL2NvbXBvbmVudC9NYXRlcmlhbEJhckxvYWRlci5jb21wb25lbnQnO1xuXG5jb25zdCBUWVBFX05BTUU6IHN0cmluZyA9IFwicGh4LWFwcFwiO1xuXG4vKipcbiAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDJlbTtcIj5cbiAqIEEgbWFpbiBib290c3RyYXAgY29tcG9uZW50IGNsYXNzIGZvciA8Y29kZT5QaGxveFVJPC9jb2RlPiBhcHBsaWNhdGlvbi4gVGhpcyBjbGFzcyBpbXBsZW1lbnRzIHRoZSBbW0lOYXZpZ2F0b3JdXSBpbnRlcmZhY2UgaGF2aW5nIHBhZ2VzIChbW0Fic3RyYWN0UGFnZV1dKVxuICogYXMgPGNvZGU+bmF2aWdhdGVlPC9jb2RlPiBpdGVtcyAoW1tJTmF2aWdhdGVlXV0pLiBBbiA8Y29kZT5hcHBsaWNhdGlvbjwvY29kZT4gbWF5IGNvbnNpc3Qgb2YgdmFyaW91cyBwYWdlcywgZm9yIGV4YW1wbGUsIGl0IG1heSBoYXZlIGEgbG9naW4gcGFnZSB0byBhbGxvdyB0aGUgdXNlciB0b1xuICogbG9naW4sIG9uY2UgdGhlIHVzZXIgaXMgbG9nZ2VkIG9uLCBpdCB3aWxsIG5hdmlnYXRlIHRoZSB1c2VyIHRvIHRoZSBtYWluIHBhZ2UsIGV0Yy5cbiAqIDwvcD5cbiAqXG4gKiBAYXV0aG9yIHNoaW9yaW4sIHRlZTRjdXRlXG4gKi9cbkBDb21wb25lbnQoe1xuICBtb2R1bGVJZDogbW9kdWxlLmlkLFxuICBzZWxlY3RvcjogJ3BoeC1hcHAnLFxuICB0ZW1wbGF0ZTogYDxkaXYgY2xhc3M9XCJwaGxveC1hcHAtYmFyLWNvbnRhaW5lclwiIFtjbGFzcy5zaG93XT1cImlzU2hvd0xvYWRlcigpXCI+XG4gIDxtYXRlcmlhbC1iYXItbG9hZGVyICNiYXJsb2FkZXI+PC9tYXRlcmlhbC1iYXItbG9hZGVyPlxuPC9kaXY+XG48cm91dGVyLW91dGxldD48L3JvdXRlci1vdXRsZXQ+XG48cGh4LWRpYWxvZyAjZGlhbG9nPjwvcGh4LWRpYWxvZz5cbmBcbn0pXG5leHBvcnQgY2xhc3MgUGhsb3hBcHAgaW1wbGVtZW50cyBJTmF2aWdhdG9yPEFic3RyYWN0UGFnZT4sIE9uSW5pdCB7XG5cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBUWVBFX05BTUU6IHN0cmluZyA9IFRZUEVfTkFNRTtcblxuICAvKipcbiAgICogVGhpcyBmaWVsZCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgaW5qZWN0ZWQgYnkgPGNvZGU+bmc8L2NvZGU+LlxuICAgKi9cbiAgcHJpdmF0ZSBhcHBJbmZvU2VydmljZTogUGhsb3hBcHBJbmZvU2VydmljZTtcbiAgLyoqXG4gICAqIFRoaXMgZmllbGQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGluamVjdGVkIGJ5IDxjb2RlPm5nPC9jb2RlPi5cbiAgICovXG4gIHByaXZhdGUgb2JzZXJ2YWJsZU1ncjogT2JzZXJ2YWJsZU1hbmFnZXI7XG4gIC8qKlxuICAgKiBUaGlzIGZpZWxkIHdpbGwgYmUgYXV0b21hdGljYWxseSBpbmplY3RlZCBieSA8Y29kZT5uZzwvY29kZT4uXG4gICAqL1xuICBwcml2YXRlIG5lZWRGb2N1c1NlcnZpY2U6IE5lZWRGb2N1c1NlcnZpY2U7XG4gIC8qKlxuICAgKiBBIGZpZWxkIGtlZXBpbmcgY2FjaGUgZm9yIHRoZSBsYXN0IHN1Y2Nlc3NmdWxseSBsb2FkZWQgW1tQaGxveEFwcEluZm9dXSBmcm9tIG1ldGhvZCBbW3JlbG9hZEFwcEluZm9dXS5cbiAgICovXG4gIHByaXZhdGUgYXBwSW5mbzogUGhsb3hBcHBJbmZvO1xuICAvKipcbiAgICogQW4gYXJyYXkga2VlcGluZyBhbGwgPGNvZGU+cGFnZTwvY29kZT5zIG9mIHRoaXMgPGNvZGU+YXBwbGljYXRpb248L2NvZGU+LlxuICAgKi9cbiAgcHJpdmF0ZSBwYWdlczogQWJzdHJhY3RQYWdlW107XG4gIC8qKlxuICAgKiBUaGlzIGZpZWxkIHdpbGwgYmUgYXV0b21hdGljYWxseSBpbmplY3RlZCBieSA8Y29kZT5uZzwvY29kZT4uXG4gICAqL1xuICBwcml2YXRlIHJvdXRlcjogUm91dGVyO1xuICAvKipcbiAgICogVGhpcyBmaWVsZCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgaW5qZWN0ZWQgYnkgPGNvZGU+bmc8L2NvZGU+LlxuICAgKi9cbiAgcHJpdmF0ZSBkaWFsb2dTZXJ2aWNlOiBEaWFsb2dTZXJ2aWNlO1xuICAvKipcbiAgICogVGhpcyBmaWVsZCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgaW5qZWN0ZWQgYnkgPGNvZGU+bmc8L2NvZGU+LlxuICAgKi9cbiAgcHJpdmF0ZSBiZ1Byb2Nlc3NNZ3I6IEJhY2tncm91bmRQcm9jZXNzTWFuYWdlcjtcbiAgLyoqXG4gICAqIEEgW1tQaGxveERpYWxvZ11dIGNoaWxkIGNvbXBvbmVudCBpbnN0YW5jZSBvZiB0aGlzIGNvbXBvbmVudC5cbiAgICovXG4gIEBWaWV3Q2hpbGQoJ2RpYWxvZycpXG4gIHByaXZhdGUgcGhsb3hEaWFsb2c6IGFueTtcbiAgQFZpZXdDaGlsZChcImJhcmxvYWRlclwiKVxuICBwcml2YXRlIGJhcmxvYWRlcjogTWF0ZXJpYWxCYXJMb2FkZXI7XG4gIHByaXZhdGUgX3Nob3dMb2FkZXI6IGJvb2xlYW47XG4gIHByaXZhdGUgY3VyUm91dGVyTG9hZGluZzogYW55ID0ge1xuICAgIFwicGF0aFwiOiBudWxsLFxuICAgIFwicmVzb2x2ZVwiOiBudWxsLFxuICAgIFwicmVqZWN0XCI6IG51bGxcbiAgfTtcblxuICBjb25zdHJ1Y3Rvcihyb3V0ZXI6IFJvdXRlciwgYXBwSW5mb1NlcnZpY2U6IFBobG94QXBwSW5mb1NlcnZpY2UsIGFwcFN2YzogUGhsb3hBcHBTZXJ2aWNlLCBvYnNlcnZhYmxlTWdyOiBPYnNlcnZhYmxlTWFuYWdlciwgbmVlZEZvY3VzU2VydmljZTogTmVlZEZvY3VzU2VydmljZSxcbiAgICBkaWFsb2dTZXJ2aWNlOiBEaWFsb2dTZXJ2aWNlLCBiZ1Byb2Nlc3NNZ3I6IEJhY2tncm91bmRQcm9jZXNzTWFuYWdlcikge1xuICAgIHRoaXMucGFnZXMgPSBbXTtcbiAgICB0aGlzLnJvdXRlciA9IHJvdXRlcjtcbiAgICB0aGlzLmFwcEluZm9TZXJ2aWNlID0gYXBwSW5mb1NlcnZpY2U7XG4gICAgdGhpcy5vYnNlcnZhYmxlTWdyID0gb2JzZXJ2YWJsZU1ncjtcbiAgICB0aGlzLm5lZWRGb2N1c1NlcnZpY2UgPSBuZWVkRm9jdXNTZXJ2aWNlO1xuICAgIHRoaXMucmVsb2FkQXBwSW5mbygpO1xuICAgIHRoaXMuZGlhbG9nU2VydmljZSA9IGRpYWxvZ1NlcnZpY2U7XG4gICAgdGhpcy5iZ1Byb2Nlc3NNZ3IgPSBiZ1Byb2Nlc3NNZ3I7XG4gICAgdGhpcy5fc2hvd0xvYWRlciA9IGZhbHNlO1xuXG4gICAgLy8gU2V0IGFwcCBpbnN0YW5jZSB0byBQaGxveEFwcFNlcnZpY2UgdG8gYWxsb3cgb3RoZXJzIHRvIGFjY2VzcyB0aGlzIGluc3RhbmNlLlxuICAgIGFwcFN2Yy5zZXRJbnN0YW5jZSh0aGlzKTtcblxuICAgIC8vIGluaXQgZGlhbG9nIHNlcnZpY2VcbiAgICB0aGlzLmRpYWxvZ1NlcnZpY2UuaW5pdCh0aGlzKTtcblxuICAgIHRoaXMub2JzZXJ2YWJsZU1nci5zdWJzY3JpYmUoQmFja2dyb3VuZFByb2Nlc3NNYW5hZ2VyLlBST0NFU1NfU1RBUlRfVE9QSUNfTkFNRSwgKHN0YXJ0QkdQcm9jZXNzOiBhbnkpID0+IHtcbiAgICAgIGlmIChzdGFydEJHUHJvY2Vzcy50eXBlID09PSAnY29ubmVjdGlvbi5wYWdlJykge1xuICAgICAgICB0aGlzLnJ1blBhZ2VMb2FkZXIoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLm9ic2VydmFibGVNZ3Iuc3Vic2NyaWJlKEJhY2tncm91bmRQcm9jZXNzTWFuYWdlci5QUk9DRVNTX0VORF9UT1BJQ19OQU1FLCAoZW5kQkdQcm9jZXNzOiBhbnkpID0+IHtcbiAgICAgIGlmIChlbmRCR1Byb2Nlc3MudHlwZSA9PT0gJ2Nvbm5lY3Rpb24ucGFnZScpIHtcbiAgICAgICAgaWYgKHRoaXMuYmdQcm9jZXNzTWdyLmdldFJ1bm5pbmdQcm9jZXNzZXNDb3VudCgnY29ubmVjdGlvbi5wYWdlJywgbnVsbCkgPD0gMCkge1xuICAgICAgICAgIHRoaXMuc3RvcFBhZ2VMb2FkZXIoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMub2JzZXJ2YWJsZU1nci5zdWJzY3JpYmUoQmFja2dyb3VuZFByb2Nlc3NNYW5hZ2VyLlBST0NFU1NfRVJST1JfVE9QSUNfTkFNRSwgKGVycm9yQkdQcm9jZXNzOiBhbnkpID0+IHtcbiAgICAgIGlmIChlcnJvckJHUHJvY2Vzcy50eXBlID09PSAnY29ubmVjdGlvbi5wYWdlJykge1xuICAgICAgICBpZiAodGhpcy5iZ1Byb2Nlc3NNZ3IuZ2V0UnVubmluZ1Byb2Nlc3Nlc0NvdW50KCdjb25uZWN0aW9uLnBhZ2UnLCBudWxsKSA8PSAwKSB7XG4gICAgICAgICAgdGhpcy5zdG9wUGFnZUxvYWRlcigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5vYnNlcnZhYmxlTWdyLnN1YnNjcmliZShBYnN0cmFjdE5hdkxlZnRMYXlvdXQuRklYRURfQ0hBTkdFX1RPUElDX05BTUUsIChsYXlvdXQ6IGFueSkgPT4ge1xuICAgICAgY29uc29sZS5sb2coJ05hdiBsZWZ0IFwiJyArIGxheW91dC5nZXRTdWJUb3BpY05hbWUoKSArICdcIiBmaXhlZDogJyArIGxheW91dC5maXhlZCk7XG4gICAgfSk7XG4gICAgdGhpcy5vYnNlcnZhYmxlTWdyLnN1YnNjcmliZShBYnN0cmFjdE5hdkxlZnRMYXlvdXQuVE9HR0xFRF9DSEFOR0VfVE9QSUNfTkFNRSwgKGxheW91dDogYW55KSA9PiB7XG4gICAgICBjb25zb2xlLmxvZygnTmF2IGxlZnQgXCInICsgbGF5b3V0LmdldFN1YlRvcGljTmFtZSgpICsgJ1wiIHRvZ2dsZWQ6ICcgKyBsYXlvdXQudG9nZ2xlZCk7XG4gICAgfSk7XG5cbiAgICAvLyBmaXhlZD1mYWxzZSwgdG9nZ2xlZD10cnVlXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLm9ic2VydmFibGVNZ3IucHVibGlzaChBYnN0cmFjdE5hdkxlZnRMYXlvdXQuVE9HR0xFRF9DTURfVE9QSUNfTkFNRSwgdHJ1ZSk7XG4gICAgfSwgMTUwMCk7XG4gICAgLy8gZml4ZWQ9ZmFsc2UsIHRvZ2dsZWQ9ZmFsc2VcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMub2JzZXJ2YWJsZU1nci5wdWJsaXNoKEFic3RyYWN0TmF2TGVmdExheW91dC5UT0dHTEVEX0NNRF9UT1BJQ19OQU1FLCBmYWxzZSk7XG4gICAgfSwgMzAwMCk7XG4gICAgLy8gZml4ZWQ9dHJ1ZSwgdG9nZ2xlZD1mYWxzZVxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5vYnNlcnZhYmxlTWdyLnB1Ymxpc2goQWJzdHJhY3ROYXZMZWZ0TGF5b3V0LkZJWEVEX0NNRF9UT1BJQ19OQU1FLCB0cnVlKTtcbiAgICB9LCAzNTAwKTtcbiAgICAvLyBmaXhlZD10cnVlLCB0b2dnbGVkPXRydWVcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMub2JzZXJ2YWJsZU1nci5wdWJsaXNoKEFic3RyYWN0TmF2TGVmdExheW91dC5UT0dHTEVEX0NNRF9UT1BJQ19OQU1FLCB0cnVlKTtcbiAgICB9LCA0NTAwKTtcbiAgICAvLyBmaXhlZD10cnVlLCB0b2dnbGVkPWZhbHNlXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLm9ic2VydmFibGVNZ3IucHVibGlzaChBYnN0cmFjdE5hdkxlZnRMYXlvdXQuVE9HR0xFRF9DTURfVE9QSUNfTkFNRSwgZmFsc2UpO1xuICAgIH0sIDYwMDApO1xuICAgIC8vIGZpeGVkPWZhbHNlLCB0b2dnbGVkPWZhbHNlXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLm9ic2VydmFibGVNZ3IucHVibGlzaChBYnN0cmFjdE5hdkxlZnRMYXlvdXQuRklYRURfQ01EX1RPUElDX05BTUUsIGZhbHNlKTtcbiAgICB9LCA2NTAwKTtcbiAgfVxuXG4gIHB1YmxpYyBpc1Nob3dMb2FkZXIoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX3Nob3dMb2FkZXI7XG4gIH1cblxuICAvKipcbiAgICogPHAgc3R5bGU9XCJ0ZXh0LWluZGVudDogMWVtO1wiPlxuICAgKiBHZXQgYXBwIGluZm8gb2YgY3VycmVudGx5IG9wZW5lZCA8Y29kZT5hcHBsaWNhdGlvbjwvY29kZT4uXG4gICAqIDwvcD5cbiAgICovXG4gIHB1YmxpYyBnZXRBcHBJbmZvKCk6IFBobG94QXBwSW5mbyB7XG4gICAgcmV0dXJuIHRoaXMuYXBwSW5mbztcbiAgfVxuXG4gIC8qKlxuICAgKiA8cCBzdHlsZT1cInRleHQtaW5kZW50OiAxZW07XCI+XG4gICAqIFJlbG9hZCB0aGUgYXBwIGluZm8gZnJvbSA8Y29kZT5QaGxveEFwcEluZm9TZXJ2aWNlPC9jb2RlPi5cbiAgICogPC9wPlxuICAgKi9cbiAgcHVibGljIHJlbG9hZEFwcEluZm8oKTogUHJvbWlzZTxQaGxveEFwcEluZm8+IHtcbiAgICByZXR1cm4gdGhpcy5hcHBJbmZvU2VydmljZS5yZWxvYWQoKS50aGVuKChyZXN1bHQ6IFBobG94QXBwSW5mbykgPT4ge1xuICAgICAgdGhpcy5hcHBJbmZvID0gcmVzdWx0O1xuXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuYXBwSW5mbyk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0Um91dGVyKCk6IFJvdXRlciB7XG4gICAgcmV0dXJuIHRoaXMucm91dGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDFlbTtcIj5cbiAgICogR2V0IGFsbCBhdmFpbGFibGUgPGNvZGU+cGFnZXM8L2NvZGU+IChbW0Fic3RyYWN0UGFnZV1dKSBpbiB0aGlzIDxjb2RlPmFwcGxpY2F0aW9uPC9jb2RlPi5cbiAgICogPC9wPlxuICAgKlxuICAgKiBAc2VlIFtbSU5hdmlnYXRvci5nZXRJdGVtc11dXG4gICAqL1xuICBwdWJsaWMgZ2V0SXRlbXMoKTogQWJzdHJhY3RQYWdlW10ge1xuICAgIHJldHVybiB0aGlzLnBhZ2VzO1xuICB9XG5cbiAgLyoqXG4gICAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDFlbTtcIj5cbiAgICogR2V0IGFsbCBhdmFpbGFibGUgPGNvZGU+cGFnZTwvY29kZT4gY291bnQgKFtbQWJzdHJhY3RQYWdlXV0pIGluIHRoaXMgPGNvZGU+YXBwbGljYXRpb248L2NvZGU+LlxuICAgKiA8L3A+XG4gICAqXG4gICAqIEBzZWUgW1tJTmF2aWdhdG9yLmdldEl0ZW1Db3VudF1dXG4gICAqL1xuICBwdWJsaWMgZ2V0SXRlbUNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucGFnZXMubGVuZ3RoO1xuICB9XG5cbiAgLyoqXG4gICAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDFlbTtcIj5cbiAgICogR2V0IGN1cnJlbnQgYWN0aXZlIDxjb2RlPnBhZ2U8L2NvZGU+IChbW0Fic3RyYWN0UGFnZV1dKSBpbmRleCBpbiB0aGUgYXJyYXkgcmV0dXJuZWQgZnJvbSBbW2dldEl0ZW1zXV0gbWV0aG9kLlxuICAgKiA8L3A+XG4gICAqXG4gICAqIEBzZWUgW1tJTmF2aWdhdG9yLmdldEFjdGl2ZUluZGV4XV1cbiAgICogQHJldHVybnMgUmV0dXJucyA8Y29kZT4tMTwvY29kZT4gaWYgdGhlcmUgaXMgbm8gY3VycmVudCBhY3RpdmUgPGNvZGU+cGFnZTwvY29kZT4uXG4gICAqL1xuICBwdWJsaWMgZ2V0QWN0aXZlSW5kZXgoKTogbnVtYmVyIHtcbiAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgdGhpcy5wYWdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHRoaXMucGFnZXNbaV0uaXNBY3RpdmUoKSkge1xuICAgICAgICByZXR1cm4gaTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICAvKipcbiAgICogPHAgc3R5bGU9XCJ0ZXh0LWluZGVudDogMWVtO1wiPlxuICAgKiBHZXQgY3VycmVudCBhY3RpdmUgPGNvZGU+cGFnZTwvY29kZT4gKFtbQWJzdHJhY3RQYWdlXV0pIG9iamVjdCBpbnN0YW5jZS5cbiAgICogPC9wPlxuICAgKlxuICAgKiBAc2VlIFtbSU5hdmlnYXRvci5nZXRBY3RpdmVJdGVtXV1cbiAgICogQHJldHVybnMgUmV0dXJucyA8Y29kZT5udWxsPC9jb2RlPiBpZiB0aGVyZSBpcyBubyBjdXJyZW50IGFjdGl2ZSA8Y29kZT5wYWdlPC9jb2RlPi5cbiAgICovXG4gIHB1YmxpYyBnZXRBY3RpdmVJdGVtKCk6IEFic3RyYWN0UGFnZSB7XG4gICAgbGV0IGlkeDogbnVtYmVyID0gdGhpcy5nZXRBY3RpdmVJbmRleCgpO1xuXG4gICAgaWYgKGlkeCA8IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnBhZ2VzW2lkeF07XG4gIH1cblxuICAvKipcbiAgICogPHAgc3R5bGU9XCJ0ZXh0LWluZGVudDogMWVtO1wiPlxuICAgKiBBbiBpbXBsZW1lbnRhdGlvbiBvZiBbW0lOYXZpZ2F0b3Iuc2V0SXRlbXNdXSBtZXRob2QuIFBsZWFzZSBzZWUgdGhlIGRvY3VtZW50YXRpb24gb2Ygc3VwZXIgY2xhc3Mgb3Igc3VwZXIgaW50ZXJmYWNlIGZvciBtb3JlIGRldGFpbHMuXG4gICAqIDwvcD5cbiAgICpcbiAgICogQHNlZSBbW0lOYXZpZ2F0b3Iuc2V0SXRlbXNdXVxuICAgKi9cbiAgcHVibGljIHNldEl0ZW1zKGl0ZW1zOiBBYnN0cmFjdFBhZ2VbXSk6IHZvaWQge1xuICAgIHRoaXMucGFnZXMgPSBpdGVtcztcbiAgfVxuXG4gIC8qKlxuICAgKiA8cCBzdHlsZT1cInRleHQtaW5kZW50OiAxZW07XCI+XG4gICAqIEFkZCBhIG5ldyA8Y29kZT5wYWdlPC9jb2RlPiAoW1tBYnN0cmFjdFBhZ2VdXSkgaW50byB0aGlzIDxjb2RlPmFwcGxpY2F0aW9uPC9jb2RlPi4gSWYgdGhlIDxjb2RlPnBhZ2U8L2NvZGU+ICg8Y29kZT48Yj5pdGVtPC9iPjwvY29kZT4pIGJlaW5nIGFkZGVkIGlzIHRoZVxuICAgKiBmaXJzdCA8Y29kZT5wYWdlPC9jb2RlPiBvZiB0aGlzIDxjb2RlPmFwcGxpY2F0aW9uPC9jb2RlPiwgdGhpcyBtZXRob2Qgd2lsbCBhdXRvbWF0aWNhbGx5IHNob3cgdGhlIGdpdmVuIDxjb2RlPnBhZ2U8L2NvZGU+IGFuZCBzZXQgaXRzIDxjb2RlPmFjdGl2ZTwvY29kZT5cbiAgICogZmxhZyB0byA8Y29kZT50cnVlPC9jb2RlPi5cbiAgICogPC9wPlxuICAgKlxuICAgKiBAc2VlIFtbSU5hdmlnYXRvci5hZGRJdGVtXV1cbiAgICovXG4gIHB1YmxpYyBhZGRJdGVtKGl0ZW06IEFic3RyYWN0UGFnZSk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmNvbnRhaW5zSXRlbShpdGVtKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHRoaXMucGFnZXMucHVzaChpdGVtKTtcblxuICAgIGlmICh0aGlzLnBhZ2VzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgLy8gVGhpcyBpcyB0aGUgZmlyc3Qgb25lLiBTbywgaXQgc2hvdWxkIGJlIGFjdGl2ZSFcbiAgICAgIGl0ZW0uYWN0aXZlID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiA8cCBzdHlsZT1cInRleHQtaW5kZW50OiAxZW07XCI+XG4gICAqIFJlbW92ZSB0aGUgZ2l2ZW4gPGNvZGU+cGFnZTwvY29kZT4gKFtbQWJzdHJhY3RQYWdlXV0pIGZyb20gdGhpcyA8Y29kZT5hcHBsaWNhdGlvbjwvY29kZT4uIElmIHRoZSA8Y29kZT5wYWdlPC9jb2RlPiAoPGNvZGU+PGI+aXRlbTwvYj48L2NvZGU+KSBiZWluZyByZW1vdmVkIGlzXG4gICAqIGN1cnJlbnRseSBhY3RpdmUsIHRoaXMgbWV0aG9kIHdpbGwgYXV0b21hdGljYWxseSB1bnNldCBpdHMgPGNvZGU+YWN0aXZlPC9jb2RlPiBmbGFnIGFuZCBzaG93IHRoZSBmaXJzdCA8Y29kZT5wYWdlPC9jb2RlPiAoaWYgYXZhaWxhYmxlKSBpbiB0aGUgYXJyYXkgcmV0dXJuZWQgZnJvbVxuICAgKiBbW2dldEl0ZW1zXV0gbWV0aG9kIGluc3RlYWQuXG4gICAqIDwvcD5cbiAgICpcbiAgICogQHNlZSBbW0lOYXZpZ2F0b3IucmVtb3ZlSXRlbV1dXG4gICAqL1xuICBwdWJsaWMgcmVtb3ZlSXRlbShpdGVtOiBBYnN0cmFjdFBhZ2UpOiBib29sZWFuIHtcbiAgICBsZXQgaWR4OiBudW1iZXIgPSB0aGlzLnBhZ2VzLmluZGV4T2YoaXRlbSk7XG5cbiAgICBpZiAoaWR4IDwgMCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHRoaXMucGFnZXMgPSB0aGlzLnBhZ2VzLnNsaWNlKGlkeCwgMSk7XG5cbiAgICBpZiAoaXRlbS5hY3RpdmUpIHtcbiAgICAgIC8vIFNldCBwYWdlIGFjdGl2ZSB0byBmYWxzZS5cbiAgICAgIGl0ZW0uYWN0aXZlID0gZmFsc2U7XG5cbiAgICAgIC8vIElmIGl0IGlzIGN1cnJlbnRseSBhY3RpdmUgcGFnZSwgd2UndmUgdG8gbmF2aWdhdGUgdG8gYW5vdGhlciBvbmUuXG4gICAgICB0aGlzLm5hdmlnYXRlVG9JbmRleCgwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiA8cCBzdHlsZT1cInRleHQtaW5kZW50OiAxZW07XCI+XG4gICAqIEFuIGltcGxlbWVudGF0aW9uIG9mIFtbSU5hdmlnYXRvci5jb250YWluc0l0ZW1dXSBtZXRob2QuIFBsZWFzZSBzZWUgdGhlIGRvY3VtZW50YXRpb24gb2Ygc3VwZXIgY2xhc3Mgb3Igc3VwZXIgaW50ZXJmYWNlIGZvciBtb3JlIGRldGFpbHMuXG4gICAqIDwvcD5cbiAgICpcbiAgICogQHNlZSBbW0lOYXZpZ2F0b3IuY29udGFpbnNJdGVtXV1cbiAgICovXG4gIHB1YmxpYyBjb250YWluc0l0ZW0oaXRlbTogQWJzdHJhY3RQYWdlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucGFnZXMuaW5kZXhPZihpdGVtKSA+PSAwO1xuICB9XG5cbiAgLyoqXG4gICAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDFlbTtcIj5cbiAgICogQW4gaW1wbGVtZW50YXRpb24gb2YgW1tJTmF2aWdhdG9yLmdldEl0ZW1CeUluZGV4XV0gbWV0aG9kLiBQbGVhc2Ugc2VlIHRoZSBkb2N1bWVudGF0aW9uIG9mIHN1cGVyIGNsYXNzIG9yIHN1cGVyIGludGVyZmFjZSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgKiA8L3A+XG4gICAqXG4gICAqIEBzZWUgW1tJTmF2aWdhdG9yLmdldEl0ZW1CeUluZGV4XV1cbiAgICovXG4gIHB1YmxpYyBnZXRJdGVtQnlJbmRleChpZHg6IG51bWJlcik6IEFic3RyYWN0UGFnZSB7XG4gICAgaWYgKGlkeCA8IDAgfHwgaWR4ID49IHRoaXMucGFnZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5wYWdlc1tpZHhdO1xuICB9XG5cbiAgLyoqXG4gICAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDFlbTtcIj5cbiAgICogQW4gaW1wbGVtZW50YXRpb24gb2YgW1tJTmF2aWdhdG9yLmdldEl0ZW1CeU5hbWVdXSBtZXRob2QuIFBsZWFzZSBzZWUgdGhlIGRvY3VtZW50YXRpb24gb2Ygc3VwZXIgY2xhc3Mgb3Igc3VwZXIgaW50ZXJmYWNlIGZvciBtb3JlIGRldGFpbHMuXG4gICAqIDwvcD5cbiAgICpcbiAgICogQHNlZSBbW0lOYXZpZ2F0b3IuZ2V0SXRlbUJ5TmFtZV1dXG4gICAqL1xuICBwdWJsaWMgZ2V0SXRlbUJ5TmFtZShuYW1lOiBzdHJpbmcpO