@ionic/angular
Version:
Angular specific wrappers for @ionic/core
349 lines • 50.1 kB
JavaScript
import { ViewContainerRef, inject, Attribute, Directive, EventEmitter, Optional, Output, SkipSelf, EnvironmentInjector, } from '@angular/core';
import { ActivatedRoute, ChildrenOutletContexts, PRIMARY_OUTLET } from '@angular/router';
import { componentOnReady } from '@ionic/core';
import { BehaviorSubject } from 'rxjs';
import { distinctUntilChanged, filter, switchMap } from 'rxjs/operators';
import { Config } from '../../providers/config';
import { NavController } from '../../providers/nav-controller';
import { StackController } from './stack-controller';
import { getUrl } from './stack-utils';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/router";
// TODO(FW-2827): types
// eslint-disable-next-line @angular-eslint/directive-class-suffix
export class IonRouterOutlet {
constructor(name, tabs, commonLocation, elementRef, router, zone, activatedRoute, parentOutlet) {
this.parentOutlet = parentOutlet;
this.activated = null;
this.activatedView = null;
this._activatedRoute = null;
// Maintain map of activated route proxies for each component instance
this.proxyMap = new WeakMap();
// Keep the latest activated route in a subject for the proxy routes to switch map to
this.currentActivatedRoute$ = new BehaviorSubject(null);
this.stackEvents = new EventEmitter();
// eslint-disable-next-line @angular-eslint/no-output-rename
this.activateEvents = new EventEmitter();
// eslint-disable-next-line @angular-eslint/no-output-rename
this.deactivateEvents = new EventEmitter();
this.parentContexts = inject(ChildrenOutletContexts);
this.location = inject(ViewContainerRef);
this.environmentInjector = inject(EnvironmentInjector);
// Ionic providers
this.config = inject(Config);
this.navCtrl = inject(NavController);
this.nativeEl = elementRef.nativeElement;
this.name = name || PRIMARY_OUTLET;
this.tabsPrefix = tabs === 'true' ? getUrl(router, activatedRoute) : undefined;
this.stackCtrl = new StackController(this.tabsPrefix, this.nativeEl, router, this.navCtrl, zone, commonLocation);
this.parentContexts.onChildOutletCreated(this.name, this);
}
set animation(animation) {
this.nativeEl.animation = animation;
}
set animated(animated) {
this.nativeEl.animated = animated;
}
set swipeGesture(swipe) {
this._swipeGesture = swipe;
this.nativeEl.swipeHandler = swipe
? {
canStart: () => this.stackCtrl.canGoBack(1) && !this.stackCtrl.hasRunningTask(),
onStart: () => this.stackCtrl.startBackTransition(),
onEnd: (shouldContinue) => this.stackCtrl.endBackTransition(shouldContinue),
}
: undefined;
}
ngOnDestroy() {
this.stackCtrl.destroy();
}
getContext() {
return this.parentContexts.getContext(this.name);
}
ngOnInit() {
this.initializeOutletWithName();
}
// Note: Ionic deviates from the Angular Router implementation here
initializeOutletWithName() {
if (!this.activated) {
// If the outlet was not instantiated at the time the route got activated we need to populate
// the outlet when it is initialized (ie inside a NgIf)
const context = this.getContext();
if (context?.route) {
this.activateWith(context.route, context.injector);
}
}
new Promise((resolve) => componentOnReady(this.nativeEl, resolve)).then(() => {
if (this._swipeGesture === undefined) {
this.swipeGesture = this.config.getBoolean('swipeBackEnabled', this.nativeEl.mode === 'ios');
}
});
}
get isActivated() {
return !!this.activated;
}
get component() {
if (!this.activated) {
throw new Error('Outlet is not activated');
}
return this.activated.instance;
}
get activatedRoute() {
if (!this.activated) {
throw new Error('Outlet is not activated');
}
return this._activatedRoute;
}
get activatedRouteData() {
if (this._activatedRoute) {
return this._activatedRoute.snapshot.data;
}
return {};
}
/**
* Called when the `RouteReuseStrategy` instructs to detach the subtree
*/
detach() {
throw new Error('incompatible reuse strategy');
}
/**
* Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
attach(_ref, _activatedRoute) {
throw new Error('incompatible reuse strategy');
}
deactivate() {
if (this.activated) {
if (this.activatedView) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const context = this.getContext();
this.activatedView.savedData = new Map(context.children['contexts']);
/**
* Angular v11.2.10 introduced a change
* where this route context is cleared out when
* a router-outlet is deactivated, However,
* we need this route information in order to
* return a user back to the correct tab when
* leaving and then going back to the tab context.
*/
const primaryOutlet = this.activatedView.savedData.get('primary');
if (primaryOutlet && context.route) {
primaryOutlet.route = { ...context.route };
}
/**
* Ensure we are saving the NavigationExtras
* data otherwise it will be lost
*/
this.activatedView.savedExtras = {};
if (context.route) {
const contextSnapshot = context.route.snapshot;
this.activatedView.savedExtras.queryParams = contextSnapshot.queryParams;
this.activatedView.savedExtras.fragment = contextSnapshot.fragment;
}
}
const c = this.component;
this.activatedView = null;
this.activated = null;
this._activatedRoute = null;
this.deactivateEvents.emit(c);
}
}
activateWith(activatedRoute, environmentInjector) {
if (this.isActivated) {
throw new Error('Cannot activate an already activated outlet');
}
this._activatedRoute = activatedRoute;
let cmpRef;
let enteringView = this.stackCtrl.getExistingView(activatedRoute);
if (enteringView) {
cmpRef = this.activated = enteringView.ref;
const saved = enteringView.savedData;
if (saved) {
// self-restore
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const context = this.getContext();
context.children['contexts'] = saved;
}
// Updated activated route proxy for this component
this.updateActivatedRouteProxy(cmpRef.instance, activatedRoute);
}
else {
const snapshot = activatedRoute._futureSnapshot;
/**
* Angular 14 introduces a new `loadComponent` property to the route config.
* This function will assign a `component` property to the route snapshot.
* We check for the presence of this property to determine if the route is
* using standalone components.
*/
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
// We create an activated route proxy object that will maintain future updates for this component
// over its lifecycle in the stack.
const component$ = new BehaviorSubject(null);
const activatedRouteProxy = this.createActivatedRouteProxy(component$, activatedRoute);
const injector = new OutletInjector(activatedRouteProxy, childContexts, this.location.injector);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const component = snapshot.routeConfig.component ?? snapshot.component;
cmpRef = this.activated = this.location.createComponent(component, {
index: this.location.length,
injector,
environmentInjector: environmentInjector ?? this.environmentInjector,
});
// Once the component is created we can push it to our local subject supplied to the proxy
component$.next(cmpRef.instance);
// Calling `markForCheck` to make sure we will run the change detection when the
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
enteringView = this.stackCtrl.createView(this.activated, activatedRoute);
// Store references to the proxy by component
this.proxyMap.set(cmpRef.instance, activatedRouteProxy);
this.currentActivatedRoute$.next({ component: cmpRef.instance, activatedRoute });
}
this.activatedView = enteringView;
/**
* The top outlet is set prior to the entering view's transition completing,
* so that when we have nested outlets (e.g. ion-tabs inside an ion-router-outlet),
* the tabs outlet will be assigned as the top outlet when a view inside tabs is
* activated.
*
* In this scenario, activeWith is called for both the tabs and the root router outlet.
* To avoid a race condition, we assign the top outlet synchronously.
*/
this.navCtrl.setTopOutlet(this);
this.stackCtrl.setActive(enteringView).then((data) => {
this.activateEvents.emit(cmpRef.instance);
this.stackEvents.emit(data);
});
}
/**
* Returns `true` if there are pages in the stack to go back.
*/
canGoBack(deep = 1, stackId) {
return this.stackCtrl.canGoBack(deep, stackId);
}
/**
* Resolves to `true` if it the outlet was able to sucessfully pop the last N pages.
*/
pop(deep = 1, stackId) {
return this.stackCtrl.pop(deep, stackId);
}
/**
* Returns the URL of the active page of each stack.
*/
getLastUrl(stackId) {
const active = this.stackCtrl.getLastUrl(stackId);
return active ? active.url : undefined;
}
/**
* Returns the RouteView of the active page of each stack.
* @internal
*/
getLastRouteView(stackId) {
return this.stackCtrl.getLastUrl(stackId);
}
/**
* Returns the root view in the tab stack.
* @internal
*/
getRootView(stackId) {
return this.stackCtrl.getRootUrl(stackId);
}
/**
* Returns the active stack ID. In the context of ion-tabs, it means the active tab.
*/
getActiveStackId() {
return this.stackCtrl.getActiveStackId();
}
/**
* Since the activated route can change over the life time of a component in an ion router outlet, we create
* a proxy so that we can update the values over time as a user navigates back to components already in the stack.
*/
createActivatedRouteProxy(component$, activatedRoute) {
const proxy = new ActivatedRoute();
proxy._futureSnapshot = activatedRoute._futureSnapshot;
proxy._routerState = activatedRoute._routerState;
proxy.snapshot = activatedRoute.snapshot;
proxy.outlet = activatedRoute.outlet;
proxy.component = activatedRoute.component;
// Setup wrappers for the observables so consumers don't have to worry about switching to new observables as the state updates
proxy._paramMap = this.proxyObservable(component$, 'paramMap');
proxy._queryParamMap = this.proxyObservable(component$, 'queryParamMap');
proxy.url = this.proxyObservable(component$, 'url');
proxy.params = this.proxyObservable(component$, 'params');
proxy.queryParams = this.proxyObservable(component$, 'queryParams');
proxy.fragment = this.proxyObservable(component$, 'fragment');
proxy.data = this.proxyObservable(component$, 'data');
return proxy;
}
/**
* Create a wrapped observable that will switch to the latest activated route matched by the given component
*/
proxyObservable(component$, path) {
return component$.pipe(
// First wait until the component instance is pushed
filter((component) => !!component), switchMap((component) => this.currentActivatedRoute$.pipe(filter((current) => current !== null && current.component === component), switchMap((current) => current && current.activatedRoute[path]), distinctUntilChanged())));
}
/**
* Updates the activated route proxy for the given component to the new incoming router state
*/
updateActivatedRouteProxy(component, activatedRoute) {
const proxy = this.proxyMap.get(component);
if (!proxy) {
throw new Error(`Could not find activated route proxy for view`);
}
proxy._futureSnapshot = activatedRoute._futureSnapshot;
proxy._routerState = activatedRoute._routerState;
proxy.snapshot = activatedRoute.snapshot;
proxy.outlet = activatedRoute.outlet;
proxy.component = activatedRoute.component;
this.currentActivatedRoute$.next({ component, activatedRoute });
}
}
/** @nocollapse */ IonRouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonRouterOutlet, deps: [{ token: 'name', attribute: true }, { token: 'tabs', attribute: true, optional: true }, { token: i1.Location }, { token: i0.ElementRef }, { token: i2.Router }, { token: i0.NgZone }, { token: i2.ActivatedRoute }, { token: IonRouterOutlet, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Directive });
/** @nocollapse */ IonRouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: IonRouterOutlet, selector: "ion-router-outlet", inputs: { animated: "animated", animation: "animation", mode: "mode", swipeGesture: "swipeGesture" }, outputs: { stackEvents: "stackEvents", activateEvents: "activate", deactivateEvents: "deactivate" }, exportAs: ["outlet"], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonRouterOutlet, decorators: [{
type: Directive,
args: [{
selector: 'ion-router-outlet',
exportAs: 'outlet',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['animated', 'animation', 'mode', 'swipeGesture'],
}]
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Attribute,
args: ['name']
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Attribute,
args: ['tabs']
}] }, { type: i1.Location }, { type: i0.ElementRef }, { type: i2.Router }, { type: i0.NgZone }, { type: i2.ActivatedRoute }, { type: IonRouterOutlet, decorators: [{
type: SkipSelf
}, {
type: Optional
}] }]; }, propDecorators: { stackEvents: [{
type: Output
}], activateEvents: [{
type: Output,
args: ['activate']
}], deactivateEvents: [{
type: Output,
args: ['deactivate']
}] } });
class OutletInjector {
constructor(route, childContexts, parent) {
this.route = route;
this.childContexts = childContexts;
this.parent = parent;
}
get(token, notFoundValue) {
if (token === ActivatedRoute) {
return this.route;
}
if (token === ChildrenOutletContexts) {
return this.childContexts;
}
return this.parent.get(token, notFoundValue);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW9uLXJvdXRlci1vdXRsZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZGlyZWN0aXZlcy9uYXZpZ2F0aW9uL2lvbi1yb3V0ZXItb3V0bGV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFPTCxnQkFBZ0IsRUFDaEIsTUFBTSxFQUNOLFNBQVMsRUFDVCxTQUFTLEVBQ1QsWUFBWSxFQUNaLFFBQVEsRUFDUixNQUFNLEVBQ04sUUFBUSxFQUNSLG1CQUFtQixHQUNwQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXlCLGNBQWMsRUFBRSxzQkFBc0IsRUFBRSxjQUFjLEVBQVEsTUFBTSxpQkFBaUIsQ0FBQztBQUN0SCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDL0MsT0FBTyxFQUFjLGVBQWUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNuRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBR3pFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFL0QsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3JELE9BQU8sRUFBYSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7Ozs7QUFFbEQsdUJBQXVCO0FBUXZCLGtFQUFrRTtBQUNsRSxNQUFNLE9BQU8sZUFBZTtJQXFEMUIsWUFDcUIsSUFBWSxFQUNBLElBQVksRUFDM0MsY0FBd0IsRUFDeEIsVUFBc0IsRUFDdEIsTUFBYyxFQUNkLElBQVksRUFDWixjQUE4QixFQUNHLFlBQThCO1FBQTlCLGlCQUFZLEdBQVosWUFBWSxDQUFrQjtRQTFEekQsY0FBUyxHQUE2QixJQUFJLENBQUM7UUFDbkQsa0JBQWEsR0FBcUIsSUFBSSxDQUFDO1FBRS9C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QyxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7U0FDM0I7UUFFRCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztJQUMvQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMb2NhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBDb21wb25lbnRSZWYsXG4gIEVsZW1lbnRSZWYsXG4gIEluamVjdG9yLFxuICBOZ1pvbmUsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBWaWV3Q29udGFpbmVyUmVmLFxuICBpbmplY3QsXG4gIEF0dHJpYnV0ZSxcbiAgRGlyZWN0aXZlLFxuICBFdmVudEVtaXR0ZXIsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFNraXBTZWxmLFxuICBFbnZpcm9ubWVudEluamVjdG9yLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE91dGxldENvbnRleHQsIFJvdXRlciwgQWN0aXZhdGVkUm91dGUsIENoaWxkcmVuT3V0bGV0Q29udGV4dHMsIFBSSU1BUllfT1VUTEVULCBEYXRhIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGNvbXBvbmVudE9uUmVhZHkgfSBmcm9tICdAaW9uaWMvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBmaWx0ZXIsIHN3aXRjaE1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgQW5pbWF0aW9uQnVpbGRlciB9IGZyb20gJy4uLy4uL2lvbmljLWNvcmUnO1xuaW1wb3J0IHsgQ29uZmlnIH0gZnJvbSAnLi4vLi4vcHJvdmlkZXJzL2NvbmZpZyc7XG5pbXBvcnQgeyBOYXZDb250cm9sbGVyIH0gZnJvbSAnLi4vLi4vcHJvdmlkZXJzL25hdi1jb250cm9sbGVyJztcblxuaW1wb3J0IHsgU3RhY2tDb250cm9sbGVyIH0gZnJvbSAnLi9zdGFjay1jb250cm9sbGVyJztcbmltcG9ydCB7IFJvdXRlVmlldywgZ2V0VXJsIH0gZnJvbSAnLi9zdGFjay11dGlscyc7XG5cbi8vIFRPRE8oRlctMjgyNyk6IHR5cGVzXG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ2lvbi1yb3V0ZXItb3V0bGV0JyxcbiAgZXhwb3J0QXM6ICdvdXRsZXQnLFxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGFuZ3VsYXItZXNsaW50L25vLWlucHV0cy1tZXRhZGF0YS1wcm9wZXJ0eVxuICBpbnB1dHM6IFsnYW5pbWF0ZWQnLCAnYW5pbWF0aW9uJywgJ21vZGUnLCAnc3dpcGVHZXN0dXJlJ10sXG59KVxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9kaXJlY3RpdmUtY2xhc3Mtc3VmZml4XG5leHBvcnQgY2xhc3MgSW9uUm91dGVyT3V0bGV0IGltcGxlbWVudHMgT25EZXN0cm95LCBPbkluaXQge1xuICBuYXRpdmVFbDogSFRNTElvblJvdXRlck91dGxldEVsZW1lbnQ7XG5cbiAgcHJpdmF0ZSBhY3RpdmF0ZWQ6IENvbXBvbmVudFJlZjxhbnk+IHwgbnVsbCA9IG51bGw7XG4gIGFjdGl2YXRlZFZpZXc6IFJvdXRlVmlldyB8IG51bGwgPSBudWxsO1xuXG4gIHByaXZhdGUgX2FjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9zd2lwZUdlc3R1cmU/OiBib29sZWFuO1xuICBwcml2YXRlIG5hbWU6IHN0cmluZztcbiAgcHJpdmF0ZSBzdGFja0N0cmw6IFN0YWNrQ29udHJvbGxlcjtcblxuICAvLyBNYWludGFpbiBtYXAgb2YgYWN0aXZhdGVkIHJvdXRlIHByb3hpZXMgZm9yIGVhY2ggY29tcG9uZW50IGluc3RhbmNlXG4gIHByaXZhdGUgcHJveHlNYXAgPSBuZXcgV2Vha01hcDxhbnksIEFjdGl2YXRlZFJvdXRlPigpO1xuXG4gIC8vIEtlZXAgdGhlIGxhdGVzdCBhY3RpdmF0ZWQgcm91dGUgaW4gYSBzdWJqZWN0IGZvciB0aGUgcHJveHkgcm91dGVzIHRvIHN3aXRjaCBtYXAgdG9cbiAgcHJpdmF0ZSBjdXJyZW50QWN0aXZhdGVkUm91dGUkID0gbmV3IEJlaGF2aW9yU3ViamVjdDx7IGNvbXBvbmVudDogYW55OyBhY3RpdmF0ZWRSb3V0ZTogQWN0aXZhdGVkUm91dGUgfSB8IG51bGw+KG51bGwpO1xuXG4gIHRhYnNQcmVmaXg6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBAT3V0cHV0KCkgc3RhY2tFdmVudHMgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9uby1vdXRwdXQtcmVuYW1lXG4gIEBPdXRwdXQoJ2FjdGl2YXRlJykgYWN0aXZhdGVFdmVudHMgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9uby1vdXRwdXQtcmVuYW1lXG4gIEBPdXRwdXQoJ2RlYWN0aXZhdGUnKSBkZWFjdGl2YXRlRXZlbnRzID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgcHJpdmF0ZSBwYXJlbnRDb250ZXh0cyA9IGluamVjdChDaGlsZHJlbk91dGxldENvbnRleHRzKTtcbiAgcHJpdmF0ZSBsb2NhdGlvbiA9IGluamVjdChWaWV3Q29udGFpbmVyUmVmKTtcbiAgcHJpdmF0ZSBlbnZpcm9ubWVudEluamVjdG9yID0gaW5qZWN0KEVudmlyb25tZW50SW5qZWN0b3IpO1xuXG4gIC8vIElvbmljIHByb3ZpZGVyc1xuICBwcml2YXRlIGNvbmZpZyA9IGluamVjdChDb25maWcpO1xuICBwcml2YXRlIG5hdkN0cmwgPSBpbmplY3QoTmF2Q29udHJvbGxlcik7XG5cbiAgc2V0IGFuaW1hdGlvbihhbmltYXRpb246IEFuaW1hdGlvbkJ1aWxkZXIpIHtcbiAgICB0aGlzLm5hdGl2ZUVsLmFuaW1hdGlvbiA9IGFuaW1hdGlvbjtcbiAgfVxuXG4gIHNldCBhbmltYXRlZChhbmltYXRlZDogYm9vbGVhbikge1xuICAgIHRoaXMubmF0aXZlRWwuYW5pbWF0ZWQgPSBhbmltYXRlZDtcbiAgfVxuXG4gIHNldCBzd2lwZUdlc3R1cmUoc3dpcGU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9zd2lwZUdlc3R1cmUgPSBzd2lwZTtcblxuICAgIHRoaXMubmF0aXZlRWwuc3dpcGVIYW5kbGVyID0gc3dpcGVcbiAgICAgID8ge1xuICAgICAgICAgIGNhblN0YXJ0OiAoKSA9PiB0aGlzLnN0YWNrQ3RybC5jYW5Hb0JhY2soMSkgJiYgIXRoaXMuc3RhY2tDdHJsLmhhc1J1bm5pbmdUYXNrKCksXG4gICAgICAgICAgb25TdGFydDogKCkgPT4gdGhpcy5zdGFja0N0cmwuc3RhcnRCYWNrVHJhbnNpdGlvbigpLFxuICAgICAgICAgIG9uRW5kOiAoc2hvdWxkQ29udGludWUpID0+IHRoaXMuc3RhY2tDdHJsLmVuZEJhY2tUcmFuc2l0aW9uKHNob3VsZENvbnRpbnVlKSxcbiAgICAgICAgfVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBAQXR0cmlidXRlKCduYW1lJykgbmFtZTogc3RyaW5nLFxuICAgIEBPcHRpb25hbCgpIEBBdHRyaWJ1dGUoJ3RhYnMnKSB0YWJzOiBzdHJpbmcsXG4gICAgY29tbW9uTG9jYXRpb246IExvY2F0aW9uLFxuICAgIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgcm91dGVyOiBSb3V0ZXIsXG4gICAgem9uZTogTmdab25lLFxuICAgIGFjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBAU2tpcFNlbGYoKSBAT3B0aW9uYWwoKSByZWFkb25seSBwYXJlbnRPdXRsZXQ/OiBJb25Sb3V0ZXJPdXRsZXRcbiAgKSB7XG4gICAgdGhpcy5uYXRpdmVFbCA9IGVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICB0aGlzLm5hbWUgPSBuYW1lIHx8IFBSSU1BUllfT1VUTEVUO1xuICAgIHRoaXMudGFic1ByZWZpeCA9IHRhYnMgPT09ICd0cnVlJyA/IGdldFVybChyb3V0ZXIsIGFjdGl2YXRlZFJvdXRlKSA6IHVuZGVmaW5lZDtcbiAgICB0aGlzLnN0YWNrQ3RybCA9IG5ldyBTdGFja0NvbnRyb2xsZXIodGhpcy50YWJzUHJlZml4LCB0aGlzLm5hdGl2ZUVsLCByb3V0ZXIsIHRoaXMubmF2Q3RybCwgem9uZSwgY29tbW9uTG9jYXRpb24pO1xuICAgIHRoaXMucGFyZW50Q29udGV4dHMub25DaGlsZE91dGxldENyZWF0ZWQodGhpcy5uYW1lLCB0aGlzIGFzIGFueSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnN0YWNrQ3RybC5kZXN0cm95KCk7XG4gIH1cblxuICBnZXRDb250ZXh0KCk6IE91dGxldENvbnRleHQgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5wYXJlbnRDb250ZXh0cy5nZXRDb250ZXh0KHRoaXMubmFtZSk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmluaXRpYWxpemVPdXRsZXRXaXRoTmFtZSgpO1xuICB9XG5cbiAgLy8gTm90ZTogSW9uaWMgZGV2aWF0ZXMgZnJvbSB0aGUgQW5ndWxhciBSb3V0ZXIgaW1wbGVtZW50YXRpb24gaGVyZVxuICBwcml2YXRlIGluaXRpYWxpemVPdXRsZXRXaXRoTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMuYWN0aXZhdGVkKSB7XG4gICAgICAvLyBJZiB0aGUgb3V0bGV0IHdhcyBub3QgaW5zdGFudGlhdGVkIGF0IHRoZSB0aW1lIHRoZSByb3V0ZSBnb3QgYWN0aXZhdGVkIHdlIG5lZWQgdG8gcG9wdWxhdGVcbiAgICAgIC8vIHRoZSBvdXRsZXQgd2hlbiBpdCBpcyBpbml0aWFsaXplZCAoaWUgaW5zaWRlIGEgTmdJZilcbiAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmdldENvbnRleHQoKTtcbiAgICAgIGlmIChjb250ZXh0Py5yb3V0ZSkge1xuICAgICAgICB0aGlzLmFjdGl2YXRlV2l0aChjb250ZXh0LnJvdXRlLCBjb250ZXh0LmluamVjdG9yKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gY29tcG9uZW50T25SZWFkeSh0aGlzLm5hdGl2ZUVsLCByZXNvbHZlKSkudGhlbigoKSA9PiB7XG4gICAgICBpZiAodGhpcy5fc3dpcGVHZXN0dXJlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5zd2lwZUdlc3R1cmUgPSB0aGlzLmNvbmZpZy5nZXRCb29sZWFuKCdzd2lwZUJhY2tFbmFibGVkJywgKHRoaXMubmF0aXZlRWwgYXMgYW55KS5tb2RlID09PSAnaW9zJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBnZXQgaXNBY3RpdmF0ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5hY3RpdmF0ZWQ7XG4gIH1cblxuICBnZXQgY29tcG9uZW50KCk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgICBpZiAoIXRoaXMuYWN0aXZhdGVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ091dGxldCBpcyBub3QgYWN0aXZhdGVkJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFjdGl2YXRlZC5pbnN0YW5jZTtcbiAgfVxuXG4gIGdldCBhY3RpdmF0ZWRSb3V0ZSgpOiBBY3RpdmF0ZWRSb3V0ZSB7XG4gICAgaWYgKCF0aGlzLmFjdGl2YXRlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdPdXRsZXQgaXMgbm90IGFjdGl2YXRlZCcpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYWN0aXZhdGVkUm91dGUgYXMgQWN0aXZhdGVkUm91dGU7XG4gIH1cblxuICBnZXQgYWN0aXZhdGVkUm91dGVEYXRhKCk6IERhdGEge1xuICAgIGlmICh0aGlzLl9hY3RpdmF0ZWRSb3V0ZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2FjdGl2YXRlZFJvdXRlLnNuYXBzaG90LmRhdGE7XG4gICAgfVxuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiB0aGUgYFJvdXRlUmV1c2VTdHJhdGVneWAgaW5zdHJ1Y3RzIHRvIGRldGFjaCB0aGUgc3VidHJlZVxuICAgKi9cbiAgZGV0YWNoKCk6IENvbXBvbmVudFJlZjxhbnk+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2luY29tcGF0aWJsZSByZXVzZSBzdHJhdGVneScpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIHRoZSBgUm91dGVSZXVzZVN0cmF0ZWd5YCBpbnN0cnVjdHMgdG8gcmUtYXR0YWNoIGEgcHJldmlvdXNseSBkZXRhY2hlZCBzdWJ0cmVlXG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGF0dGFjaChfcmVmOiBDb21wb25lbnRSZWY8YW55PiwgX2FjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSk6IHZvaWQge1xuICAgIHRocm93IG5ldyBFcnJvcignaW5jb21wYXRpYmxlIHJldXNlIHN0cmF0ZWd5Jyk7XG4gIH1cblxuICBkZWFjdGl2YXRlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmFjdGl2YXRlZCkge1xuICAgICAgaWYgKHRoaXMuYWN0aXZhdGVkVmlldykge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5nZXRDb250ZXh0KCkhO1xuICAgICAgICB0aGlzLmFjdGl2YXRlZFZpZXcuc2F2ZWREYXRhID0gbmV3IE1hcChjb250ZXh0LmNoaWxkcmVuWydjb250ZXh0cyddKTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQW5ndWxhciB2MTEuMi4xMCBpbnRyb2R1Y2VkIGEgY2hhbmdlXG4gICAgICAgICAqIHdoZXJlIHRoaXMgcm91dGUgY29udGV4dCBpcyBjbGVhcmVkIG91dCB3aGVuXG4gICAgICAgICAqIGEgcm91dGVyLW91dGxldCBpcyBkZWFjdGl2YXRlZCwgSG93ZXZlcixcbiAgICAgICAgICogd2UgbmVlZCB0aGlzIHJvdXRlIGluZm9ybWF0aW9uIGluIG9yZGVyIHRvXG4gICAgICAgICAqIHJldHVybiBhIHVzZXIgYmFjayB0byB0aGUgY29ycmVjdCB0YWIgd2hlblxuICAgICAgICAgKiBsZWF2aW5nIGFuZCB0aGVuIGdvaW5nIGJhY2sgdG8gdGhlIHRhYiBjb250ZXh0LlxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3QgcHJpbWFyeU91dGxldCA9IHRoaXMuYWN0aXZhdGVkVmlldy5zYXZlZERhdGEuZ2V0KCdwcmltYXJ5Jyk7XG4gICAgICAgIGlmIChwcmltYXJ5T3V0bGV0ICYmIGNvbnRleHQucm91dGUpIHtcbiAgICAgICAgICBwcmltYXJ5T3V0bGV0LnJvdXRlID0geyAuLi5jb250ZXh0LnJvdXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5zdXJlIHdlIGFyZSBzYXZpbmcgdGhlIE5hdmlnYXRpb25FeHRyYXNcbiAgICAgICAgICogZGF0YSBvdGhlcndpc2UgaXQgd2lsbCBiZSBsb3N0XG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmFjdGl2YXRlZFZpZXcuc2F2ZWRFeHRyYXMgPSB7fTtcbiAgICAgICAgaWYgKGNvbnRleHQucm91dGUpIHtcbiAgICAgICAgICBjb25zdCBjb250ZXh0U25hcHNob3QgPSBjb250ZXh0LnJvdXRlLnNuYXBzaG90O1xuXG4gICAgICAgICAgdGhpcy5hY3RpdmF0ZWRWaWV3LnNhdmVkRXh0cmFzLnF1ZXJ5UGFyYW1zID0gY29udGV4dFNuYXBzaG90LnF1ZXJ5UGFyYW1zO1xuICAgICAgICAgICh0aGlzLmFjdGl2YXRlZFZpZXcuc2F2ZWRFeHRyYXMuZnJhZ21lbnQgYXMgc3RyaW5nIHwgbnVsbCkgPSBjb250ZXh0U25hcHNob3QuZnJhZ21lbnQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IGMgPSB0aGlzLmNvbXBvbmVudDtcbiAgICAgIHRoaXMuYWN0aXZhdGVkVmlldyA9IG51bGw7XG4gICAgICB0aGlzLmFjdGl2YXRlZCA9IG51bGw7XG4gICAgICB0aGlzLl9hY3RpdmF0ZWRSb3V0ZSA9IG51bGw7XG4gICAgICB0aGlzLmRlYWN0aXZhdGVFdmVudHMuZW1pdChjKTtcbiAgICB9XG4gIH1cblxuICBhY3RpdmF0ZVdpdGgoYWN0aXZhdGVkUm91dGU6IEFjdGl2YXRlZFJvdXRlLCBlbnZpcm9ubWVudEluamVjdG9yOiBFbnZpcm9ubWVudEluamVjdG9yIHwgbnVsbCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzQWN0aXZhdGVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhY3RpdmF0ZSBhbiBhbHJlYWR5IGFjdGl2YXRlZCBvdXRsZXQnKTtcbiAgICB9XG4gICAgdGhpcy5fYWN0aXZhdGVkUm91dGUgPSBhY3RpdmF0ZWRSb3V0ZTtcblxuICAgIGxldCBjbXBSZWY6IGFueTtcbiAgICBsZXQgZW50ZXJpbmdWaWV3ID0gdGhpcy5zdGFja0N0cmwuZ2V0RXhpc3RpbmdWaWV3KGFjdGl2YXRlZFJvdXRlKTtcbiAgICBpZiAoZW50ZXJpbmdWaWV3KSB7XG4gICAgICBjbXBSZWYgPSB0aGlzLmFjdGl2YXRlZCA9IGVudGVyaW5nVmlldy5yZWY7XG4gICAgICBjb25zdCBzYXZlZCA9IGVudGVyaW5nVmlldy5zYXZlZERhdGE7XG4gICAgICBpZiAoc2F2ZWQpIHtcbiAgICAgICAgLy8gc2VsZi1yZXN0b3JlXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmdldENvbnRleHQoKSE7XG4gICAgICAgIGNvbnRleHQuY2hpbGRyZW5bJ2NvbnRleHRzJ10gPSBzYXZlZDtcbiAgICAgIH1cbiAgICAgIC8vIFVwZGF0ZWQgYWN0aXZhdGVkIHJvdXRlIHByb3h5IGZvciB0aGlzIGNvbXBvbmVudFxuICAgICAgdGhpcy51cGRhdGVBY3RpdmF0ZWRSb3V0ZVByb3h5KGNtcFJlZi5pbnN0YW5jZSwgYWN0aXZhdGVkUm91dGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzbmFwc2hvdCA9IChhY3RpdmF0ZWRSb3V0ZSBhcyBhbnkpLl9mdXR1cmVTbmFwc2hvdDtcblxuICAgICAgLyoqXG4gICAgICAgKiBBbmd1bGFyIDE0IGludHJvZHVjZXMgYSBuZXcgYGxvYWRDb21wb25lbnRgIHByb3BlcnR5IHRvIHRoZSByb3V0ZSBjb25maWcuXG4gICAgICAgKiBUaGlzIGZ1bmN0aW9uIHdpbGwgYXNzaWduIGEgYGNvbXBvbmVudGAgcHJvcGVydHkgdG8gdGhlIHJvdXRlIHNuYXBzaG90LlxuICAgICAgICogV2UgY2hlY2sgZm9yIHRoZSBwcmVzZW5jZSBvZiB0aGlzIHByb3BlcnR5IHRvIGRldGVybWluZSBpZiB0aGUgcm91dGUgaXNcbiAgICAgICAqIHVzaW5nIHN0YW5kYWxvbmUgY29tcG9uZW50cy5cbiAgICAgICAqL1xuICAgICAgY29uc3QgY2hpbGRDb250ZXh0cyA9IHRoaXMucGFyZW50Q29udGV4dHMuZ2V0T3JDcmVhdGVDb250ZXh0KHRoaXMubmFtZSkuY2hpbGRyZW47XG5cbiAgICAgIC8vIFdlIGNyZWF0ZSBhbiBhY3RpdmF0ZWQgcm91dGUgcHJveHkgb2JqZWN0IHRoYXQgd2lsbCBtYWludGFpbiBmdXR1cmUgdXBkYXRlcyBmb3IgdGhpcyBjb21wb25lbnRcbiAgICAgIC8vIG92ZXIgaXRzIGxpZmVjeWNsZSBpbiB0aGUgc3RhY2suXG4gICAgICBjb25zdCBjb21wb25lbnQkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxhbnk+KG51bGwpO1xuICAgICAgY29uc3QgYWN0aXZhdGVkUm91dGVQcm94eSA9IHRoaXMuY3JlYXRlQWN0aXZhdGVkUm91dGVQcm94eShjb21wb25lbnQkLCBhY3RpdmF0ZWRSb3V0ZSk7XG5cbiAgICAgIGNvbnN0IGluamVjdG9yID0gbmV3IE91dGxldEluamVjdG9yKGFjdGl2YXRlZFJvdXRlUHJveHksIGNoaWxkQ29udGV4dHMsIHRoaXMubG9jYXRpb24uaW5qZWN0b3IpO1xuXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgY29uc3QgY29tcG9uZW50ID0gc25hcHNob3Qucm91dGVDb25maWchLmNvbXBvbmVudCA/PyBzbmFwc2hvdC5jb21wb25lbnQ7XG5cbiAgICAgIGNtcFJlZiA9IHRoaXMuYWN0aXZhdGVkID0gdGhpcy5sb2NhdGlvbi5jcmVhdGVDb21wb25lbnQoY29tcG9uZW50LCB7XG4gICAgICAgIGluZGV4OiB0aGlzLmxvY2F0aW9uLmxlbmd0aCxcbiAgICAgICAgaW5qZWN0b3IsXG4gICAgICAgIGVudmlyb25tZW50SW5qZWN0b3I6IGVudmlyb25tZW50SW5qZWN0b3IgPz8gdGhpcy5lbnZpcm9ubWVudEluamVjdG9yLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIE9uY2UgdGhlIGNvbXBvbmVudCBpcyBjcmVhdGVkIHdlIGNhbiBwdXNoIGl0IHRvIG91ciBsb2NhbCBzdWJqZWN0IHN1cHBsaWVkIHRvIHRoZSBwcm94eVxuICAgICAgY29tcG9uZW50JC5uZXh0KGNtcFJlZi5pbnN0YW5jZSk7XG5cbiAgICAgIC8vIENhbGxpbmcgYG1hcmtGb3JDaGVja2AgdG8gbWFrZSBzdXJlIHdlIHdpbGwgcnVuIHRoZSBjaGFuZ2UgZGV0ZWN0aW9uIHdoZW4gdGhlXG4gICAgICAvLyBgUm91dGVyT3V0bGV0YCBpcyBpbnNpZGUgYSBgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoYCBjb21wb25lbnQuXG4gICAgICBlbnRlcmluZ1ZpZXcgPSB0aGlzLnN0YWNrQ3RybC5jcmVhdGVWaWV3KHRoaXMuYWN0aXZhdGVkLCBhY3RpdmF0ZWRSb3V0ZSk7XG5cbiAgICAgIC8vIFN0b3JlIHJlZmVyZW5jZXMgdG8gdGhlIHByb3h5IGJ5IGNvbXBvbmVudFxuICAgICAgdGhpcy5wcm94eU1hcC5zZXQoY21wUmVmLmluc3RhbmNlLCBhY3RpdmF0ZWRSb3V0ZVByb3h5KTtcbiAgICAgIHRoaXMuY3VycmVudEFjdGl2YXRlZFJvdXRlJC5uZXh0KHsgY29tcG9uZW50OiBjbXBSZWYuaW5zdGFuY2UsIGFjdGl2YXRlZFJvdXRlIH0pO1xuICAgIH1cblxuICAgIHRoaXMuYWN0aXZhdGVkVmlldyA9IGVudGVyaW5nVmlldztcblxuICAgIC8qKlxuICAgICAqIFRoZSB0b3Agb3V0bGV0IGlzIHNldCBwcmlvciB0byB0aGUgZW50ZXJpbmcgdmlldydzIHRyYW5zaXRpb24gY29tcGxldGluZyxcbiAgICAgKiBzbyB0aGF0IHdoZW4gd2UgaGF2ZSBuZXN0ZWQgb3V0bGV0cyAoZS5nLiBpb24tdGFicyBpbnNpZGUgYW4gaW9uLXJvdXRlci1vdXRsZXQpLFxuICAgICAqIHRoZSB0YWJzIG91dGxldCB3aWxsIGJlIGFzc2lnbmVkIGFzIHRoZSB0b3Agb3V0bGV0IHdoZW4gYSB2aWV3IGluc2lkZSB0YWJzIGlzXG4gICAgICogYWN0aXZhdGVkLlxuICAgICAqXG4gICAgICogSW4gdGhpcyBzY2VuYXJpbywgYWN0aXZlV2l0aCBpcyBjYWxsZWQgZm9yIGJvdGggdGhlIHRhYnMgYW5kIHRoZSByb290IHJvdXRlciBvdXRsZXQuXG4gICAgICogVG8gYXZvaWQgYSByYWNlIGNvbmRpdGlvbiwgd2UgYXNzaWduIHRoZSB0b3Agb3V0bGV0IHN5bmNocm9ub3VzbHkuXG4gICAgICovXG4gICAgdGhpcy5uYXZDdHJsLnNldFRvcE91dGxldCh0aGlzKTtcblxuICAgIHRoaXMuc3RhY2tDdHJsLnNldEFjdGl2ZShlbnRlcmluZ1ZpZXcpLnRoZW4oKGRhdGEpID0+IHtcbiAgICAgIHRoaXMuYWN0aXZhdGVFdmVudHMuZW1pdChjbXBSZWYuaW5zdGFuY2UpO1xuICAgICAgdGhpcy5zdGFja0V2ZW50cy5lbWl0KGRhdGEpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYHRydWVgIGlmIHRoZXJlIGFyZSBwYWdlcyBpbiB0aGUgc3RhY2sgdG8gZ28gYmFjay5cbiAgICovXG4gIGNhbkdvQmFjayhkZWVwID0gMSwgc3RhY2tJZD86IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN0YWNrQ3RybC5jYW5Hb0JhY2soZGVlcCwgc3RhY2tJZCk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdG8gYHRydWVgIGlmIGl0IHRoZSBvdXRsZXQgd2FzIGFibGUgdG8gc3VjZXNzZnVsbHkgcG9wIHRoZSBsYXN0IE4gcGFnZXMuXG4gICAqL1xuICBwb3AoZGVlcCA9IDEsIHN0YWNrSWQ/OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5zdGFja0N0cmwucG9wKGRlZXAsIHN0YWNrSWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIFVSTCBvZiB0aGUgYWN0aXZlIHBhZ2Ugb2YgZWFjaCBzdGFjay5cbiAgICovXG4gIGdldExhc3RVcmwoc3RhY2tJZD86IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgYWN0aXZlID0gdGhpcy5zdGFja0N0cmwuZ2V0TGFzdFVybChzdGFja0lkKTtcbiAgICByZXR1cm4gYWN0aXZlID8gYWN0aXZlLnVybCA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBSb3V0ZVZpZXcgb2YgdGhlIGFjdGl2ZSBwYWdlIG9mIGVhY2ggc3RhY2suXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgZ2V0TGFzdFJvdXRlVmlldyhzdGFja0lkPzogc3RyaW5nKTogUm91dGVWaWV3IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5zdGFja0N0cmwuZ2V0TGFzdFVybChzdGFja0lkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSByb290IHZpZXcgaW4gdGhlIHRhYiBzdGFjay5cbiAgICogQGludGVybmFsXG4gICAqL1xuICBnZXRSb290VmlldyhzdGFja0lkPzogc3RyaW5nKTogUm91dGVWaWV3IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5zdGFja0N0cmwuZ2V0Um9vdFVybChzdGFja0lkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhY3RpdmUgc3RhY2sgSUQuIEluIHRoZSBjb250ZXh0IG9mIGlvbi10YWJzLCBpdCBtZWFucyB0aGUgYWN0aXZlIHRhYi5cbiAgICovXG4gIGdldEFjdGl2ZVN0YWNrSWQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5zdGFja0N0cmwuZ2V0QWN0aXZlU3RhY2tJZCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNpbmNlIHRoZSBhY3RpdmF0ZWQgcm91dGUgY2FuIGNoYW5nZSBvdmVyIHRoZSBsaWZlIHRpbWUgb2YgYSBjb21wb25lbnQgaW4gYW4gaW9uIHJvdXRlciBvdXRsZXQsIHdlIGNyZWF0ZVxuICAgKiBhIHByb3h5IHNvIHRoYXQgd2UgY2FuIHVwZGF0ZSB0aGUgdmFsdWVzIG92ZXIgdGltZSBhcyBhIHVzZXIgbmF2aWdhdGVzIGJhY2sgdG8gY29tcG9uZW50cyBhbHJlYWR5IGluIHRoZSBzdGFjay5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlQWN0aXZhdGVkUm91dGVQcm94eShjb21wb25lbnQkOiBPYnNlcnZhYmxlPGFueT4sIGFjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSk6IEFjdGl2YXRlZFJvdXRlIHtcbiAgICBjb25zdCBwcm94eTogYW55ID0gbmV3IEFjdGl2YXRlZFJvdXRlKCk7XG5cbiAgICBwcm94eS5fZnV0dXJlU25hcHNob3QgPSAoYWN0aXZhdGVkUm91dGUgYXMgYW55KS5fZnV0dXJlU25hcHNob3Q7XG4gICAgcHJveHkuX3JvdXRlclN0YXRlID0gKGFjdGl2YXRlZFJvdXRlIGFzIGFueSkuX3JvdXRlclN0YXRlO1xuICAgIHByb3h5LnNuYXBzaG90ID0gYWN0aXZhdGVkUm91dGUuc25hcHNob3Q7XG4gICAgcHJveHkub3V0bGV0ID0gYWN0aXZhdGVkUm91dGUub3V0bGV0O1xuICAgIHByb3h5LmNvbXBvbmVudCA9IGFjdGl2YXRlZFJvdXRlLmNvbXBvbmVudDtcblxuICAgIC8vIFNldHVwIHdyYXBwZXJzIGZvciB0aGUgb2JzZXJ2YWJsZXMgc28gY29uc3VtZXJzIGRvbid0IGhhdmUgdG8gd29ycnkgYWJvdXQgc3dpdGNoaW5nIHRvIG5ldyBvYnNlcnZhYmxlcyBhcyB0aGUgc3RhdGUgdXBkYXRlc1xuICAgIChwcm94eSBhcyBhbnkpLl9wYXJhbU1hcCA9IHRoaXMucHJveHlPYnNlcnZhYmxlKGNvbXBvbmVudCQsICdwYXJhbU1hcCcpO1xuICAgIChwcm94eSBhcyBhbnkpLl9xdWVyeVBhcmFtTWFwID0gdGhpcy5wcm94eU9ic2VydmFibGUoY29tcG9uZW50JCwgJ3F1ZXJ5UGFyYW1NYXAnKTtcbiAgICBwcm94eS51cmwgPSB0aGlzLnByb3h5T2JzZXJ2YWJsZShjb21wb25lbnQkLCAndXJsJyk7XG4gICAgcHJveHkucGFyYW1zID0gdGhpcy5wcm94eU9ic2VydmFibGUoY29tcG9uZW50JCwgJ3BhcmFtcycpO1xuICAgIHByb3h5LnF1ZXJ5UGFyYW1zID0gdGhpcy5wcm94eU9ic2VydmFibGUoY29tcG9uZW50JCwgJ3F1ZXJ5UGFyYW1zJyk7XG4gICAgcHJveHkuZnJhZ21lbnQgPSB0aGlzLnByb3h5T2JzZXJ2YWJsZShjb21wb25lbnQkLCAnZnJhZ21lbnQnKTtcbiAgICBwcm94eS5kYXRhID0gdGhpcy5wcm94eU9ic2VydmFibGUoY29tcG9uZW50JCwgJ2RhdGEnKTtcblxuICAgIHJldHVybiBwcm94eSBhcyBBY3RpdmF0ZWRSb3V0ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSB3cmFwcGVkIG9ic2VydmFibGUgdGhhdCB3aWxsIHN3aXRjaCB0byB0aGUgbGF0ZXN0IGFjdGl2YXRlZCByb3V0ZSBtYXRjaGVkIGJ5IHRoZSBnaXZlbiBjb21wb25lbnRcbiAgICovXG4gIHByaXZhdGUgcHJveHlPYnNlcnZhYmxlKGNvbXBvbmVudCQ6IE9ic2VydmFibGU8YW55PiwgcGF0aDogc3RyaW5nKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICByZXR1cm4gY29tcG9uZW50JC5waXBlKFxuICAgICAgLy8gRmlyc3Qgd2FpdCB1bnRpbCB0aGUgY29tcG9uZW50IGluc3RhbmNlIGlzIHB1c2hlZFxuICAgICAgZmlsdGVyKChjb21wb25lbnQpID0+ICEhY29tcG9uZW50KSxcbiAgICAgIHN3aXRjaE1hcCgoY29tcG9uZW50KSA9PlxuICAgICAgICB0aGlzLmN1cnJlbnRBY3RpdmF0ZWRSb3V0ZSQucGlwZShcbiAgICAgICAgICBmaWx0ZXIoKGN1cnJlbnQpID0+IGN1cnJlbnQgIT09IG51bGwgJiYgY3VycmVudC5jb21wb25lbnQgPT09IGNvbXBvbmVudCksXG4gICAgICAgICAgc3dpdGNoTWFwKChjdXJyZW50KSA9PiBjdXJyZW50ICYmIChjdXJyZW50LmFjdGl2YXRlZFJvdXRlIGFzIGFueSlbcGF0aF0pLFxuICAgICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKClcbiAgICAgICAgKVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgYWN0aXZhdGVkIHJvdXRlIHByb3h5IGZvciB0aGUgZ2l2ZW4gY29tcG9uZW50IHRvIHRoZSBuZXcgaW5jb21pbmcgcm91dGVyIHN0YXRlXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZUFjdGl2YXRlZFJvdXRlUHJveHkoY29tcG9uZW50OiBhbnksIGFjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSk6IHZvaWQge1xuICAgIGNvbnN0IHByb3h5ID0gdGhpcy5wcm94eU1hcC5nZXQoY29tcG9uZW50KTtcbiAgICBpZiAoIXByb3h5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmaW5kIGFjdGl2YXRlZCByb3V0ZSBwcm94eSBmb3Igdmlld2ApO1xuICAgIH1cblxuICAgIChwcm94eSBhcyBhbnkpLl9mdXR1cmVTbmFwc2hvdCA9IChhY3RpdmF0ZWRSb3V0ZSBhcyBhbnkpLl9mdXR1cmVTbmFwc2hvdDtcbiAgICAocHJveHkgYXMgYW55KS5fcm91dGVyU3RhdGUgPSAoYWN0aXZhdGVkUm91dGUgYXMgYW55KS5fcm91dGVyU3RhdGU7XG4gICAgcHJveHkuc25hcHNob3QgPSBhY3RpdmF0ZWRSb3V0ZS5zbmFwc2hvdDtcbiAgICBwcm94eS5vdXRsZXQgPSBhY3RpdmF0ZWRSb3V0ZS5vdXRsZXQ7XG4gICAgcHJveHkuY29tcG9uZW50ID0gYWN0aXZhdGVkUm91dGUuY29tcG9uZW50O1xuXG4gICAgdGhpcy5jdXJyZW50QWN0aXZhdGVkUm91dGUkLm5leHQoeyBjb21wb25lbnQsIGFjdGl2YXRlZFJvdXRlIH0pO1xuICB9XG59XG5cbmNsYXNzIE91dGxldEluamVjdG9yIGltcGxlbWVudHMgSW5qZWN0b3Ige1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSwgcHJpdmF0ZSBjaGlsZENvbnRleHRzOiBDaGlsZHJlbk91dGxldENvbnRleHRzLCBwcml2YXRlIHBhcmVudDogSW5qZWN0b3IpIHt9XG5cbiAgZ2V0KHRva2VuOiBhbnksIG5vdEZvdW5kVmFsdWU/OiBhbnkpOiBhbnkge1xuICAgIGlmICh0b2tlbiA9PT0gQWN0aXZhdGVkUm91dGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnJvdXRlO1xuICAgIH1cblxuICAgIGlmICh0b2tlbiA9PT0gQ2hpbGRyZW5PdXRsZXRDb250ZXh0cykge1xuICAgICAgcmV0dXJuIHRoaXMuY2hpbGRDb25