@rg-software/angular-archwizard
Version:
A fork of the Angular Arch Wizard adapted for angular versions 17+.
369 lines • 45 kB
JavaScript
import { Component, ContentChildren, HostBinding, Input } from '@angular/core';
import { WizardStep } from '../util/wizard-step.interface';
import { MovingDirection } from '../util/moving-direction.enum';
import { ConfigurableNavigationMode } from '../navigation/configurable-navigation-mode';
import { WizardBase } from '../util/wizard.interface';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "./wizard-navigation-bar.component";
/**
* The `aw-wizard` component defines the root component of a wizard.
* Through the setting of input parameters for the `aw-wizard` component it's possible to change the location and size
* of its navigation bar.
*
* ### Syntax
* ```html
* <aw-wizard [navBarLocation]="location of navigation bar" [navBarLayout]="layout of navigation bar">
* ...
* </aw-wizard>
* ```
*
* ### Example
*
* Without completion step:
*
* ```html
* <aw-wizard navBarLocation="top" navBarLayout="small">
* <aw-wizard-step>...</aw-wizard-step>
* <aw-wizard-step>...</aw-wizard-step>
* </aw-wizard>
* ```
*
* With completion step:
*
* ```html
* <aw-wizard navBarLocation="top" navBarLayout="small">
* <aw-wizard-step>...</aw-wizard-step>
* <aw-wizard-step>...</aw-wizard-step>
* <aw-wizard-completion-step>...</aw-wizard-completion-step>
* </aw-wizard>
* ```
*
* @author Marc Arndt
*/
export class WizardComponent {
/**
* The initially selected step, represented by its index
* Beware: This initial default is only used if no wizard step has been enhanced with the `selected` directive
*/
get defaultStepIndex() {
// This value can be either:
// - the index of a wizard step with a `selected` directive, or
// - the default step index, set in the [[WizardComponent]]
const foundDefaultStep = this.wizardSteps.find(step => step.defaultSelected);
if (foundDefaultStep) {
return this.getIndexOfStep(foundDefaultStep);
}
else {
return this._defaultStepIndex;
}
}
set defaultStepIndex(defaultStepIndex) {
this._defaultStepIndex = defaultStepIndex;
}
/**
* Constructor
*/
constructor() {
/**
* The location of the navigation bar inside the wizard.
* This location can be either top, bottom, left or right
*/
this.navBarLocation = 'top';
/**
* The layout of the navigation bar inside the wizard.
* The layout can be either small, large-filled, large-empty or large-symbols
*/
this.navBarLayout = 'small';
/**
* The direction in which the steps inside the navigation bar should be shown.
* The direction can be either `left-to-right` or `right-to-left`
*/
this.navBarDirection = 'left-to-right';
this._defaultStepIndex = 0;
/**
* True, if the navigation bar shouldn't be used for navigating
*/
this.disableNavigationBar = false;
/**
* The navigation mode used to navigate inside the wizard
*
* For outside access, use the [[navigation]] getter.
*/
this._navigation = new ConfigurableNavigationMode();
/**
* An array representation of all wizard steps belonging to this model
*
* For outside access, use the [[wizardSteps]] getter.
*/
this._wizardSteps = [];
/**
* The index of the currently visible and selected step inside the wizardSteps QueryList.
* If this wizard contains no steps, currentStepIndex is -1
*
* Note: Do not modify this field directly. Instead, use navigation methods:
* [[goToStep]], [[goToPreviousStep]], [[goToNextStep]].
*/
this.currentStepIndex = -1;
}
/**
* Returns true if this wizard uses a horizontal orientation.
* The wizard uses a horizontal orientation, iff the navigation bar is shown at the top or bottom of this wizard
*
* @returns True if this wizard uses a horizontal orientation
*/
get horizontalOrientation() {
return this.navBarLocation === 'top' || this.navBarLocation === 'bottom';
}
/**
* Returns true if this wizard uses a vertical orientation.
* The wizard uses a vertical orientation, iff the navigation bar is shown at the left or right of this wizard
*
* @returns True if this wizard uses a vertical orientation
*/
get verticalOrientation() {
return this.navBarLocation === 'left' || this.navBarLocation === 'right';
}
/**
* Initialization work
*/
ngAfterContentInit() {
// add a subscriber to the wizard steps QueryList to listen to changes in the DOM
this.wizardStepsQueryList.changes.subscribe(changedWizardSteps => {
this.updateWizardSteps(changedWizardSteps.toArray());
});
// initialize the model
this.updateWizardSteps(this.wizardStepsQueryList.toArray());
// finally reset the whole wizard component
setTimeout(() => this.reset());
}
/**
* The WizardStep object belonging to the currently visible and selected step.
* The currentStep is always the currently selected wizard step.
* The currentStep can be either completed, if it was visited earlier,
* or not completed, if it is visited for the first time or its state is currently out of date.
*
* If this wizard contains no steps, currentStep is null
*/
get currentStep() {
if (this.hasStep(this.currentStepIndex)) {
return this.wizardSteps[this.currentStepIndex];
}
else {
return null;
}
}
/**
* The completeness of the wizard.
* If the wizard has been completed, i.e. all steps are either completed or optional, this value is true, otherwise it is false
*/
get completed() {
return this.wizardSteps.every(step => step.completed || step.optional);
}
/**
* An array representation of all wizard steps belonging to this model
*/
get wizardSteps() {
return this._wizardSteps;
}
/**
* Updates the wizard steps to the new array
*
* @param wizardSteps The updated wizard steps
*/
updateWizardSteps(wizardSteps) {
// the wizard is currently not in the initialization phase
if (this.wizardSteps.length > 0 && this.currentStepIndex > -1) {
this.currentStepIndex = wizardSteps.indexOf(this.wizardSteps[this.currentStepIndex]);
}
this._wizardSteps = wizardSteps;
}
/**
* The navigation mode used to navigate inside the wizard
*/
get navigation() {
return this._navigation;
}
/**
* Updates the navigation mode for this wizard component
*
* @param navigation The updated navigation mode
*/
set navigation(navigation) {
this._navigation = navigation;
}
/**
* Checks if a given index `stepIndex` is inside the range of possible wizard steps inside this wizard
*
* @param stepIndex The to be checked index of a step inside this wizard
* @returns True if the given `stepIndex` is contained inside this wizard, false otherwise
*/
hasStep(stepIndex) {
return this.wizardSteps.length > 0 && 0 <= stepIndex && stepIndex < this.wizardSteps.length;
}
/**
* Checks if this wizard has a previous step, compared to the current step
*
* @returns True if this wizard has a previous step before the current step
*/
hasPreviousStep() {
return this.hasStep(this.currentStepIndex - 1);
}
/**
* Checks if this wizard has a next step, compared to the current step
*
* @returns True if this wizard has a next step after the current step
*/
hasNextStep() {
return this.hasStep(this.currentStepIndex + 1);
}
/**
* Checks if this wizard is currently inside its last step
*
* @returns True if the wizard is currently inside its last step
*/
isLastStep() {
return this.wizardSteps.length > 0 && this.currentStepIndex === this.wizardSteps.length - 1;
}
/**
* Finds the [[WizardStep]] at the given index `stepIndex`.
* If no [[WizardStep]] exists at the given index an Error is thrown
*
* @param stepIndex The given index
* @returns The found [[WizardStep]] at the given index `stepIndex`
* @throws An `Error` is thrown, if the given index `stepIndex` doesn't exist
*/
getStepAtIndex(stepIndex) {
if (!this.hasStep(stepIndex)) {
throw new Error(`Expected a known step, but got stepIndex: ${stepIndex}.`);
}
return this.wizardSteps[stepIndex];
}
/**
* Finds the index of the step with the given `stepId`.
* If no step with the given `stepId` exists, `-1` is returned
*
* @param stepId The given step id
* @returns The found index of a step with the given step id, or `-1` if no step with the given id is included in the wizard
*/
getIndexOfStepWithId(stepId) {
return this.wizardSteps.findIndex(step => step.stepId === stepId);
}
/**
* Finds the index of the given [[WizardStep]] `step`.
* If the given [[WizardStep]] is not contained inside this wizard, `-1` is returned
*
* @param step The given [[WizardStep]]
* @returns The found index of `step` or `-1` if the step is not included in the wizard
*/
getIndexOfStep(step) {
return this.wizardSteps.indexOf(step);
}
/**
* Calculates the correct [[MovingDirection]] value for a given `destinationStep` compared to the `currentStepIndex`.
*
* @param destinationStep The given destination step
* @returns The calculated [[MovingDirection]]
*/
getMovingDirection(destinationStep) {
let movingDirection;
if (destinationStep > this.currentStepIndex) {
movingDirection = MovingDirection.Forwards;
}
else if (destinationStep < this.currentStepIndex) {
movingDirection = MovingDirection.Backwards;
}
else {
movingDirection = MovingDirection.Stay;
}
return movingDirection;
}
/**
* Checks, whether a wizard step, as defined by the given destination index, can be transitioned to.
*
* This method controls navigation by [[goToStep]], [[goToPreviousStep]], and [[goToNextStep]] directives.
* Navigation by navigation bar is governed by [[isNavigable]].
*
* @param destinationIndex The index of the destination step
* @returns A [[Promise]] containing `true`, if the destination step can be transitioned to and false otherwise
*/
canGoToStep(destinationIndex) {
return this.navigation.canGoToStep(this, destinationIndex);
}
/**
* Tries to transition to the wizard step, as denoted by the given destination index.
*
* Note: You do not have to call [[canGoToStep]] before calling [[goToStep]].
* The [[canGoToStep]] method will be called automatically.
*
* @param destinationIndex The index of the destination wizard step, which should be entered
* @param preFinalize An event emitter, to be called before the step has been transitioned
* @param postFinalize An event emitter, to be called after the step has been transitioned
*/
goToStep(destinationIndex, preFinalize, postFinalize) {
return this.navigation.goToStep(this, destinationIndex, preFinalize, postFinalize);
}
/**
* Tries to transition the wizard to the previous step
*
* @param preFinalize An event emitter, to be called before the step has been transitioned
* @param postFinalize An event emitter, to be called after the step has been transitioned
*/
goToPreviousStep(preFinalize, postFinalize) {
return this.navigation.goToStep(this, this.currentStepIndex - 1, preFinalize, postFinalize);
}
/**
* Tries to transition the wizard to the next step
*
* @param preFinalize An event emitter, to be called before the step has been transitioned
* @param postFinalize An event emitter, to be called after the step has been transitioned
*/
goToNextStep(preFinalize, postFinalize) {
return this.navigation.goToStep(this, this.currentStepIndex + 1, preFinalize, postFinalize);
}
/**
* Checks, whether the wizard step, located at the given index, can be navigated to using the navigation bar.
*
* @param destinationIndex The index of the destination step
* @returns True if the step can be navigated to, false otherwise
*/
isNavigable(destinationIndex) {
return this.navigation.isNavigable(this, destinationIndex);
}
/**
* Resets the state of this wizard.
*/
reset() {
this.navigation.reset(this);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.0", ngImport: i0, type: WizardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.0", type: WizardComponent, selector: "aw-wizard", inputs: { navBarLocation: "navBarLocation", navBarLayout: "navBarLayout", navBarDirection: "navBarDirection", defaultStepIndex: "defaultStepIndex", disableNavigationBar: "disableNavigationBar" }, host: { properties: { "class.horizontal": "this.horizontalOrientation", "class.vertical": "this.verticalOrientation" } }, providers: [
{ provide: WizardBase, useExisting: WizardComponent }
], queries: [{ propertyName: "wizardStepsQueryList", predicate: WizardStep, descendants: true }], ngImport: i0, template: "<aw-wizard-navigation-bar\n *ngIf=\"navBarLocation === 'top' || navBarLocation === 'left'\"\n [ngClass]=\"{\n 'vertical': navBarLocation === 'left',\n 'horizontal': navBarLocation === 'top',\n 'small': navBarLayout === 'small',\n 'large-filled': navBarLayout === 'large-filled',\n 'large-filled-symbols': navBarLayout === 'large-filled-symbols',\n 'large-empty': navBarLayout === 'large-empty',\n 'large-empty-symbols': navBarLayout === 'large-empty-symbols'\n }\">\n</aw-wizard-navigation-bar>\n\n<div [ngClass]=\"{\n 'wizard-steps': true,\n 'vertical': navBarLocation === 'left' || navBarLocation === 'right',\n 'horizontal': navBarLocation === 'top' || navBarLocation === 'bottom'\n}\">\n <ng-content></ng-content>\n</div>\n\n<aw-wizard-navigation-bar\n *ngIf=\"navBarLocation === 'bottom' || navBarLocation === 'right'\"\n [ngClass]=\"{\n 'vertical': navBarLocation === 'right',\n 'horizontal': navBarLocation === 'bottom',\n 'small': navBarLayout === 'small',\n 'large-filled': navBarLayout === 'large-filled',\n 'large-filled-symbols': navBarLayout === 'large-filled-symbols',\n 'large-empty': navBarLayout === 'large-empty',\n 'large-empty-symbols': navBarLayout === 'large-empty-symbols'\n }\">\n</aw-wizard-navigation-bar>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.WizardNavigationBarComponent, selector: "aw-wizard-navigation-bar" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.0", ngImport: i0, type: WizardComponent, decorators: [{
type: Component,
args: [{ selector: 'aw-wizard', providers: [
{ provide: WizardBase, useExisting: WizardComponent }
], template: "<aw-wizard-navigation-bar\n *ngIf=\"navBarLocation === 'top' || navBarLocation === 'left'\"\n [ngClass]=\"{\n 'vertical': navBarLocation === 'left',\n 'horizontal': navBarLocation === 'top',\n 'small': navBarLayout === 'small',\n 'large-filled': navBarLayout === 'large-filled',\n 'large-filled-symbols': navBarLayout === 'large-filled-symbols',\n 'large-empty': navBarLayout === 'large-empty',\n 'large-empty-symbols': navBarLayout === 'large-empty-symbols'\n }\">\n</aw-wizard-navigation-bar>\n\n<div [ngClass]=\"{\n 'wizard-steps': true,\n 'vertical': navBarLocation === 'left' || navBarLocation === 'right',\n 'horizontal': navBarLocation === 'top' || navBarLocation === 'bottom'\n}\">\n <ng-content></ng-content>\n</div>\n\n<aw-wizard-navigation-bar\n *ngIf=\"navBarLocation === 'bottom' || navBarLocation === 'right'\"\n [ngClass]=\"{\n 'vertical': navBarLocation === 'right',\n 'horizontal': navBarLocation === 'bottom',\n 'small': navBarLayout === 'small',\n 'large-filled': navBarLayout === 'large-filled',\n 'large-filled-symbols': navBarLayout === 'large-filled-symbols',\n 'large-empty': navBarLayout === 'large-empty',\n 'large-empty-symbols': navBarLayout === 'large-empty-symbols'\n }\">\n</aw-wizard-navigation-bar>\n" }]
}], ctorParameters: () => [], propDecorators: { wizardStepsQueryList: [{
type: ContentChildren,
args: [WizardStep, { descendants: true }]
}], navBarLocation: [{
type: Input
}], navBarLayout: [{
type: Input
}], navBarDirection: [{
type: Input
}], defaultStepIndex: [{
type: Input
}], disableNavigationBar: [{
type: Input
}], horizontalOrientation: [{
type: HostBinding,
args: ['class.horizontal']
}], verticalOrientation: [{
type: HostBinding,
args: ['class.vertical']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2l6YXJkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy93aXphcmQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL3dpemFyZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsU0FBUyxFQUNULGVBQWUsRUFDZixXQUFXLEVBQ1gsS0FBSyxFQUdOLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQztBQUN6RCxPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0sK0JBQStCLENBQUM7QUFDOUQsT0FBTyxFQUFDLDBCQUEwQixFQUFDLE1BQU0sNENBQTRDLENBQUM7QUFDdEYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDOzs7O0FBRXREOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0NHO0FBUUgsTUFBTSxPQUFPLGVBQWU7SUE0QjFCOzs7T0FHRztJQUNILElBQ1csZ0JBQWdCO1FBQ3pCLDRCQUE0QjtRQUM1QiwrREFBK0Q7UUFDL0QsMkRBQTJEO1FBRTNELE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFN0UsSUFBSSxnQkFBZ0IsRUFBRTtZQUNwQixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztTQUM5QzthQUFNO1lBQ0wsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUM7U0FDL0I7SUFDSCxDQUFDO0lBQ0QsSUFBVyxnQkFBZ0IsQ0FBQyxnQkFBd0I7UUFDbEQsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGdCQUFnQixDQUFDO0lBQzVDLENBQUM7SUFn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RyxDQUFDLEVBQUUsV0FBVyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzlGLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLFdBQVcsQ0FBQyxnQkFBd0I7UUFDekMsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUM3RCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLO1FBQ1YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUIsQ0FBQzs4R0F0VlUsZUFBZTtrR0FBZixlQUFlLGtXQUpmO1lBQ1QsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUU7U0FDdEQsK0RBTWdCLFVBQVUsZ0RDN0Q3Qix1d0NBaUNBOzsyRkR3QmEsZUFBZTtrQkFQM0IsU0FBUzsrQkFDRSxXQUFXLGFBRVY7d0JBQ1QsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsaUJBQWlCLEVBQUU7cUJBQ3REO3dEQU9NLG9CQUFvQjtzQkFEMUIsZUFBZTt1QkFBQyxVQUFVLEVBQUUsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFO2dCQVEzQyxjQUFjO3NCQURwQixLQUFLO2dCQVFDLFlBQVk7c0JBRGxCLEtBQUs7Z0JBUUMsZUFBZTtzQkFEckIsS0FBSztnQkFRSyxnQkFBZ0I7c0JBRDFCLEtBQUs7Z0JBdUJDLG9CQUFvQjtzQkFEMUIsS0FBSztnQkF1Q0sscUJBQXFCO3NCQUQvQixXQUFXO3VCQUFDLGtCQUFrQjtnQkFZcEIsbUJBQW1CO3NCQUQ3QixXQUFXO3VCQUFDLGdCQUFnQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkcmVuLFxuICBIb3N0QmluZGluZyxcbiAgSW5wdXQsXG4gIFF1ZXJ5TGlzdCxcbiAgRXZlbnRFbWl0dGVyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtOYXZpZ2F0aW9uTW9kZX0gZnJvbSAnLi4vbmF2aWdhdGlvbi9uYXZpZ2F0aW9uLW1vZGUuaW50ZXJmYWNlJztcbmltcG9ydCB7V2l6YXJkU3RlcH0gZnJvbSAnLi4vdXRpbC93aXphcmQtc3RlcC5pbnRlcmZhY2UnO1xuaW1wb3J0IHtNb3ZpbmdEaXJlY3Rpb259IGZyb20gJy4uL3V0aWwvbW92aW5nLWRpcmVjdGlvbi5lbnVtJztcbmltcG9ydCB7Q29uZmlndXJhYmxlTmF2aWdhdGlvbk1vZGV9IGZyb20gJy4uL25hdmlnYXRpb24vY29uZmlndXJhYmxlLW5hdmlnYXRpb24tbW9kZSc7XG5pbXBvcnQgeyBXaXphcmRCYXNlIH0gZnJvbSAnLi4vdXRpbC93aXphcmQuaW50ZXJmYWNlJztcblxuLyoqXG4gKiBUaGUgYGF3LXdpemFyZGAgY29tcG9uZW50IGRlZmluZXMgdGhlIHJvb3QgY29tcG9uZW50IG9mIGEgd2l6YXJkLlxuICogVGhyb3VnaCB0aGUgc2V0dGluZyBvZiBpbnB1dCBwYXJhbWV0ZXJzIGZvciB0aGUgYGF3LXdpemFyZGAgY29tcG9uZW50IGl0J3MgcG9zc2libGUgdG8gY2hhbmdlIHRoZSBsb2NhdGlvbiBhbmQgc2l6ZVxuICogb2YgaXRzIG5hdmlnYXRpb24gYmFyLlxuICpcbiAqICMjIyBTeW50YXhcbiAqIGBgYGh0bWxcbiAqIDxhdy13aXphcmQgW25hdkJhckxvY2F0aW9uXT1cImxvY2F0aW9uIG9mIG5hdmlnYXRpb24gYmFyXCIgW25hdkJhckxheW91dF09XCJsYXlvdXQgb2YgbmF2aWdhdGlvbiBiYXJcIj5cbiAqICAgICAuLi5cbiAqIDwvYXctd2l6YXJkPlxuICogYGBgXG4gKlxuICogIyMjIEV4YW1wbGVcbiAqXG4gKiBXaXRob3V0IGNvbXBsZXRpb24gc3RlcDpcbiAqXG4gKiBgYGBodG1sXG4gKiA8YXctd2l6YXJkIG5hdkJhckxvY2F0aW9uPVwidG9wXCIgbmF2QmFyTGF5b3V0PVwic21hbGxcIj5cbiAqICAgICA8YXctd2l6YXJkLXN0ZXA+Li4uPC9hdy13aXphcmQtc3RlcD5cbiAqICAgICA8YXctd2l6YXJkLXN0ZXA+Li4uPC9hdy13aXphcmQtc3RlcD5cbiAqIDwvYXctd2l6YXJkPlxuICogYGBgXG4gKlxuICogV2l0aCBjb21wbGV0aW9uIHN0ZXA6XG4gKlxuICogYGBgaHRtbFxuICogPGF3LXdpemFyZCBuYXZCYXJMb2NhdGlvbj1cInRvcFwiIG5hdkJhckxheW91dD1cInNtYWxsXCI+XG4gKiAgICAgPGF3LXdpemFyZC1zdGVwPi4uLjwvYXctd2l6YXJkLXN0ZXA+XG4gKiAgICAgPGF3LXdpemFyZC1zdGVwPi4uLjwvYXctd2l6YXJkLXN0ZXA+XG4gKiAgICAgPGF3LXdpemFyZC1jb21wbGV0aW9uLXN0ZXA+Li4uPC9hdy13aXphcmQtY29tcGxldGlvbi1zdGVwPlxuICogPC9hdy13aXphcmQ+XG4gKiBgYGBcbiAqXG4gKiBAYXV0aG9yIE1hcmMgQXJuZHRcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXctd2l6YXJkJyxcbiAgdGVtcGxhdGVVcmw6ICd3aXphcmQuY29tcG9uZW50Lmh0bWwnLFxuICBwcm92aWRlcnM6IFtcbiAgICB7IHByb3ZpZGU6IFdpemFyZEJhc2UsIHVzZUV4aXN0aW5nOiBXaXphcmRDb21wb25lbnQgfVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIFdpemFyZENvbXBvbmVudCBpbXBsZW1lbnRzIFdpemFyZEJhc2UsIEFmdGVyQ29udGVudEluaXQge1xuICAvKipcbiAgICogQSBRdWVyeUxpc3QgY29udGFpbmluZyBhbGwgW1tXaXphcmRTdGVwXV1zIGluc2lkZSB0aGlzIHdpemFyZFxuICAgKi9cbiAgQENvbnRlbnRDaGlsZHJlbihXaXphcmRTdGVwLCB7IGRlc2NlbmRhbnRzOiB0cnVlIH0pXG4gIHB1YmxpYyB3aXphcmRTdGVwc1F1ZXJ5TGlzdDogUXVlcnlMaXN0PFdpemFyZFN0ZXA+O1xuXG4gIC8qKlxuICAgKiBUaGUgbG9jYXRpb24gb2YgdGhlIG5hdmlnYXRpb24gYmFyIGluc2lkZSB0aGUgd2l6YXJkLlxuICAgKiBUaGlzIGxvY2F0aW9uIGNhbiBiZSBlaXRoZXIgdG9wLCBib3R0b20sIGxlZnQgb3IgcmlnaHRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBuYXZCYXJMb2NhdGlvbiA9ICd0b3AnO1xuXG4gIC8qKlxuICAgKiBUaGUgbGF5b3V0IG9mIHRoZSBuYXZpZ2F0aW9uIGJhciBpbnNpZGUgdGhlIHdpemFyZC5cbiAgICogVGhlIGxheW91dCBjYW4gYmUgZWl0aGVyIHNtYWxsLCBsYXJnZS1maWxsZWQsIGxhcmdlLWVtcHR5IG9yIGxhcmdlLXN5bWJvbHNcbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBuYXZCYXJMYXlvdXQgPSAnc21hbGwnO1xuXG4gIC8qKlxuICAgKiBUaGUgZGlyZWN0aW9uIGluIHdoaWNoIHRoZSBzdGVwcyBpbnNpZGUgdGhlIG5hdmlnYXRpb24gYmFyIHNob3VsZCBiZSBzaG93bi5cbiAgICogVGhlIGRpcmVjdGlvbiBjYW4gYmUgZWl0aGVyIGBsZWZ0LXRvLXJpZ2h0YCBvciBgcmlnaHQtdG8tbGVmdGBcbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBuYXZCYXJEaXJlY3Rpb24gPSAnbGVmdC10by1yaWdodCc7XG5cbiAgLyoqXG4gICAqIFRoZSBpbml0aWFsbHkgc2VsZWN0ZWQgc3RlcCwgcmVwcmVzZW50ZWQgYnkgaXRzIGluZGV4XG4gICAqIEJld2FyZTogVGhpcyBpbml0aWFsIGRlZmF1bHQgaXMgb25seSB1c2VkIGlmIG5vIHdpemFyZCBzdGVwIGhhcyBiZWVuIGVuaGFuY2VkIHdpdGggdGhlIGBzZWxlY3RlZGAgZGlyZWN0aXZlXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgZ2V0IGRlZmF1bHRTdGVwSW5kZXgoKTogbnVtYmVyIHtcbiAgICAvLyBUaGlzIHZhbHVlIGNhbiBiZSBlaXRoZXI6XG4gICAgLy8gLSB0aGUgaW5kZXggb2YgYSB3aXphcmQgc3RlcCB3aXRoIGEgYHNlbGVjdGVkYCBkaXJlY3RpdmUsIG9yXG4gICAgLy8gLSB0aGUgZGVmYXVsdCBzdGVwIGluZGV4LCBzZXQgaW4gdGhlIFtbV2l6YXJkQ29tcG9uZW50XV1cblxuICAgIGNvbnN0IGZvdW5kRGVmYXVsdFN0ZXAgPSB0aGlzLndpemFyZFN0ZXBzLmZpbmQoc3RlcCA9PiBzdGVwLmRlZmF1bHRTZWxlY3RlZCk7XG5cbiAgICBpZiAoZm91bmREZWZhdWx0U3RlcCkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0SW5kZXhPZlN0ZXAoZm91bmREZWZhdWx0U3RlcCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLl9kZWZhdWx0U3RlcEluZGV4O1xuICAgIH1cbiAgfVxuICBwdWJsaWMgc2V0IGRlZmF1bHRTdGVwSW5kZXgoZGVmYXVsdFN0ZXBJbmRleDogbnVtYmVyKSB7XG4gICAgdGhpcy5fZGVmYXVsdFN0ZXBJbmRleCA9IGRlZmF1bHRTdGVwSW5kZXg7XG4gIH1cbiAgcHJpdmF0ZSBfZGVmYXVsdFN0ZXBJbmRleCA9IDA7XG5cbiAgLyoqXG4gICAqIFRydWUsIGlmIHRoZSBuYXZpZ2F0aW9uIGJhciBzaG91bGRuJ3QgYmUgdXNlZCBmb3IgbmF2aWdhdGluZ1xuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIGRpc2FibGVOYXZpZ2F0aW9uQmFyID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIFRoZSBuYXZpZ2F0aW9uIG1vZGUgdXNlZCB0byBuYXZpZ2F0ZSBpbnNpZGUgdGhlIHdpemFyZFxuICAgKlxuICAgKiBGb3Igb3V0c2lkZSBhY2Nlc3MsIHVzZSB0aGUgW1tuYXZpZ2F0aW9uXV0gZ2V0dGVyLlxuICAgKi9cbiAgcHJpdmF0ZSBfbmF2aWdhdGlvbjogTmF2aWdhdGlvbk1vZGUgPSBuZXcgQ29uZmlndXJhYmxlTmF2aWdhdGlvbk1vZGUoKTtcblxuICAvKipcbiAgICogQW4gYXJyYXkgcmVwcmVzZW50YXRpb24gb2YgYWxsIHdpemFyZCBzdGVwcyBiZWxvbmdpbmcgdG8gdGhpcyBtb2RlbFxuICAgKlxuICAgKiBGb3Igb3V0c2lkZSBhY2Nlc3MsIHVzZSB0aGUgW1t3aXphcmRTdGVwc11dIGdldHRlci5cbiAgICovXG4gIHByaXZhdGUgX3dpemFyZFN0ZXBzOiBXaXphcmRTdGVwW10gPSBbXTtcblxuICAvKipcbiAgICogVGhlIGluZGV4IG9mIHRoZSBjdXJyZW50bHkgdmlzaWJsZSBhbmQgc2VsZWN0ZWQgc3RlcCBpbnNpZGUgdGhlIHdpemFyZFN0ZXBzIFF1ZXJ5TGlzdC5cbiAgICogSWYgdGhpcyB3aXphcmQgY29udGFpbnMgbm8gc3RlcHMsIGN1cnJlbnRTdGVwSW5kZXggaXMgLTFcbiAgICpcbiAgICogTm90ZTogRG8gbm90IG1vZGlmeSB0aGlzIGZpZWxkIGRpcmVjdGx5LiAgSW5zdGVhZCwgdXNlIG5hdmlnYXRpb24gbWV0aG9kczpcbiAgICogW1tnb1RvU3RlcF1dLCBbW2dvVG9QcmV2aW91c1N0ZXBdXSwgW1tnb1RvTmV4dFN0ZXBdXS5cbiAgICovXG4gIHB1YmxpYyBjdXJyZW50U3RlcEluZGV4ID0gLTE7XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yXG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyB3aXphcmQgdXNlcyBhIGhvcml6b250YWwgb3JpZW50YXRpb24uXG4gICAqIFRoZSB3aXphcmQgdXNlcyBhIGhvcml6b250YWwgb3JpZW50YXRpb24sIGlmZiB0aGUgbmF2aWdhdGlvbiBiYXIgaXMgc2hvd24gYXQgdGhlIHRvcCBvciBib3R0b20gb2YgdGhpcyB3aXphcmRcbiAgICpcbiAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGlzIHdpemFyZCB1c2VzIGEgaG9yaXpvbnRhbCBvcmllbnRhdGlvblxuICAgKi9cbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5ob3Jpem9udGFsJylcbiAgcHVibGljIGdldCBob3Jpem9udGFsT3JpZW50YXRpb24oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubmF2QmFyTG9jYXRpb24gPT09ICd0b3AnIHx8IHRoaXMubmF2QmFyTG9jYXRpb24gPT09ICdib3R0b20nO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIHdpemFyZCB1c2VzIGEgdmVydGljYWwgb3JpZW50YXRpb24uXG4gICAqIFRoZSB3aXphcmQgdXNlcyBhIHZlcnRpY2FsIG9yaWVudGF0aW9uLCBpZmYgdGhlIG5hdmlnYXRpb24gYmFyIGlzIHNob3duIGF0IHRoZSBsZWZ0IG9yIHJpZ2h0IG9mIHRoaXMgd2l6YXJkXG4gICAqXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhpcyB3aXphcmQgdXNlcyBhIHZlcnRpY2FsIG9yaWVudGF0aW9uXG4gICAqL1xuICBASG9zdEJpbmRpbmcoJ2NsYXNzLnZlcnRpY2FsJylcbiAgcHVibGljIGdldCB2ZXJ0aWNhbE9yaWVudGF0aW9uKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm5hdkJhckxvY2F0aW9uID09PSAnbGVmdCcgfHwgdGhpcy5uYXZCYXJMb2NhdGlvbiA9PT0gJ3JpZ2h0JztcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXphdGlvbiB3b3JrXG4gICAqL1xuICBwdWJsaWMgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIC8vIGFkZCBhIHN1YnNjcmliZXIgdG8gdGhlIHdpemFyZCBzdGVwcyBRdWVyeUxpc3QgdG8gbGlzdGVuIHRvIGNoYW5nZXMgaW4gdGhlIERPTVxuICAgIHRoaXMud2l6YXJkU3RlcHNRdWVyeUxpc3QuY2hhbmdlcy5zdWJzY3JpYmUoY2hhbmdlZFdpemFyZFN0ZXBzID0+IHtcbiAgICAgIHRoaXMudXBkYXRlV2l6YXJkU3RlcHMoY2hhbmdlZFdpemFyZFN0ZXBzLnRvQXJyYXkoKSk7XG4gICAgfSk7XG5cbiAgICAvLyBpbml0aWFsaXplIHRoZSBtb2RlbFxuICAgIHRoaXMudXBkYXRlV2l6YXJkU3RlcHModGhpcy53aXphcmRTdGVwc1F1ZXJ5TGlzdC50b0FycmF5KCkpO1xuXG4gICAgLy8gZmluYWxseSByZXNldCB0aGUgd2hvbGUgd2l6YXJkIGNvbXBvbmVudFxuICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5yZXNldCgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgV2l6YXJkU3RlcCBvYmplY3QgYmVsb25naW5nIHRvIHRoZSBjdXJyZW50bHkgdmlzaWJsZSBhbmQgc2VsZWN0ZWQgc3RlcC5cbiAgICogVGhlIGN1cnJlbnRTdGVwIGlzIGFsd2F5cyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHdpemFyZCBzdGVwLlxuICAgKiBUaGUgY3VycmVudFN0ZXAgY2FuIGJlIGVpdGhlciBjb21wbGV0ZWQsIGlmIGl0IHdhcyB2aXNpdGVkIGVhcmxpZXIsXG4gICAqIG9yIG5vdCBjb21wbGV0ZWQsIGlmIGl0IGlzIHZpc2l0ZWQgZm9yIHRoZSBmaXJzdCB0aW1lIG9yIGl0cyBzdGF0ZSBpcyBjdXJyZW50bHkgb3V0IG9mIGRhdGUuXG4gICAqXG4gICAqIElmIHRoaXMgd2l6YXJkIGNvbnRhaW5zIG5vIHN0ZXBzLCBjdXJyZW50U3RlcCBpcyBudWxsXG4gICAqL1xuICBwdWJsaWMgZ2V0IGN1cnJlbnRTdGVwKCk6IFdpemFyZFN0ZXAge1xuICAgIGlmICh0aGlzLmhhc1N0ZXAodGhpcy5jdXJyZW50U3RlcEluZGV4KSkge1xuICAgICAgcmV0dXJuIHRoaXMud2l6YXJkU3RlcHNbdGhpcy5jdXJyZW50U3RlcEluZGV4XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjb21wbGV0ZW5lc3Mgb2YgdGhlIHdpemFyZC5cbiAgICogSWYgdGhlIHdpemFyZCBoYXMgYmVlbiBjb21wbGV0ZWQsIGkuZS4gYWxsIHN0ZXBzIGFyZSBlaXRoZXIgY29tcGxldGVkIG9yIG9wdGlvbmFsLCB0aGlzIHZhbHVlIGlzIHRydWUsIG90aGVyd2lzZSBpdCBpcyBmYWxzZVxuICAgKi9cbiAgcHVibGljIGdldCBjb21wbGV0ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMud2l6YXJkU3RlcHMuZXZlcnkoc3RlcCA9PiBzdGVwLmNvbXBsZXRlZCB8fCBzdGVwLm9wdGlvbmFsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBhcnJheSByZXByZXNlbnRhdGlvbiBvZiBhbGwgd2l6YXJkIHN0ZXBzIGJlbG9uZ2luZyB0byB0aGlzIG1vZGVsXG4gICAqL1xuICBwdWJsaWMgZ2V0IHdpemFyZFN0ZXBzKCk6IFdpemFyZFN0ZXBbXSB7XG4gICAgcmV0dXJuIHRoaXMuX3dpemFyZFN0ZXBzO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIHdpemFyZCBzdGVwcyB0byB0aGUgbmV3IGFycmF5XG4gICAqXG4gICAqIEBwYXJhbSB3aXphcmRTdGVwcyBUaGUgdXBkYXRlZCB3aXphcmQgc3RlcHNcbiAgICovXG4gIHByaXZhdGUgdXBkYXRlV2l6YXJkU3RlcHMod2l6YXJkU3RlcHM6IFdpemFyZFN0ZXBbXSk6IHZvaWQge1xuICAgIC8vIHRoZSB3aXphcmQgaXMgY3VycmVudGx5IG5vdCBpbiB0aGUgaW5pdGlhbGl6YXRpb24gcGhhc2VcbiAgICBpZiAodGhpcy53aXphcmRTdGVwcy5sZW5ndGggPiAwICYmIHRoaXMuY3VycmVudFN0ZXBJbmRleCA+IC0xKSB7XG4gICAgICB0aGlzLmN1cnJlbnRTdGVwSW5kZXggPSB3aXphcmRTdGVwcy5pbmRleE9mKHRoaXMud2l6YXJkU3RlcHNbdGhpcy5jdXJyZW50U3RlcEluZGV4XSk7XG4gICAgfVxuXG4gICAgdGhpcy5fd2l6YXJkU3RlcHMgPSB3aXphcmRTdGVwcztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgbmF2aWdhdGlvbiBtb2RlIHVzZWQgdG8gbmF2aWdhdGUgaW5zaWRlIHRoZSB3aXphcmRcbiAgICovXG4gIHB1YmxpYyBnZXQgbmF2aWdhdGlvbigpOiBOYXZpZ2F0aW9uTW9kZSB7XG4gICAgcmV0dXJuIHRoaXMuX25hdmlnYXRpb247XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgbmF2aWdhdGlvbiBtb2RlIGZvciB0aGlzIHdpemFyZCBjb21wb25lbnRcbiAgICpcbiAgICogQHBhcmFtIG5hdmlnYXRpb24gVGhlIHVwZGF0ZWQgbmF2aWdhdGlvbiBtb2RlXG4gICAqL1xuICBwdWJsaWMgc2V0IG5hdmlnYXRpb24obmF2aWdhdGlvbjogTmF2aWdhdGlvbk1vZGUpIHtcbiAgICB0aGlzLl9uYXZpZ2F0aW9uID0gbmF2aWdhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYSBnaXZlbiBpbmRleCBgc3RlcEluZGV4YCBpcyBpbnNpZGUgdGhlIHJhbmdlIG9mIHBvc3NpYmxlIHdpemFyZCBzdGVwcyBpbnNpZGUgdGhpcyB3aXphcmRcbiAgICpcbiAgICogQHBhcmFtIHN0ZXBJbmRleCBUaGUgdG8gYmUgY2hlY2tlZCBpbmRleCBvZiBhIHN0ZXAgaW5zaWRlIHRoaXMgd2l6YXJkXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGdpdmVuIGBzdGVwSW5kZXhgIGlzIGNvbnRhaW5lZCBpbnNpZGUgdGhpcyB3aXphcmQsIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgcHVibGljIGhhc1N0ZXAoc3RlcEluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy53aXphcmRTdGVwcy5sZW5ndGggPiAwICYmIDAgPD0gc3RlcEluZGV4ICYmIHN0ZXBJbmRleCA8IHRoaXMud2l6YXJkU3RlcHMubGVuZ3RoO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGlzIHdpemFyZCBoYXMgYSBwcmV2aW91cyBzdGVwLCBjb21wYXJlZCB0byB0aGUgY3VycmVudCBzdGVwXG4gICAqXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhpcyB3aXphcmQgaGFzIGEgcHJldmlvdXMgc3RlcCBiZWZvcmUgdGhlIGN1cnJlbnQgc3RlcFxuICAgKi9cbiAgcHVibGljIGhhc1ByZXZpb3VzU3RlcCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5oYXNTdGVwKHRoaXMuY3VycmVudFN0ZXBJbmRleCAtIDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGlzIHdpemFyZCBoYXMgYSBuZXh0IHN0ZXAsIGNvbXBhcmVkIHRvIHRoZSBjdXJyZW50IHN0ZXBcbiAgICpcbiAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGlzIHdpemFyZCBoYXMgYSBuZXh0IHN0ZXAgYWZ0ZXIgdGhlIGN1cnJlbnQgc3RlcFxuICAgKi9cbiAgcHVibGljIGhhc05leHRTdGVwKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmhhc1N0ZXAodGhpcy5jdXJyZW50U3RlcEluZGV4ICsgMSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoaXMgd2l6YXJkIGlzIGN1cnJlbnRseSBpbnNpZGUgaXRzIGxhc3Qgc3RlcFxuICAgKlxuICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSB3aXphcmQgaXMgY3VycmVudGx5IGluc2lkZSBpdHMgbGFzdCBzdGVwXG4gICAqL1xuICBwdWJsaWMgaXNMYXN0U3RlcCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy53aXphcmRTdGVwcy5sZW5ndGggPiAwICYmIHRoaXMuY3VycmVudFN0ZXBJbmRleCA9PT0gdGhpcy53aXphcmRTdGVwcy5sZW5ndGggLSAxO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIHRoZSBbW1dpemFyZFN0ZXBdXSBhdCB0aGUgZ2l2ZW4gaW5kZXggYHN0ZXBJbmRleGAuXG4gICAqIElmIG5vIFtbV2l6YXJkU3RlcF1dIGV4aXN0cyBhdCB0aGUgZ2l2ZW4gaW5kZXggYW4gRXJyb3IgaXMgdGhyb3duXG4gICAqXG4gICAqIEBwYXJhbSBzdGVwSW5kZXggVGhlIGdpdmVuIGluZGV4XG4gICAqIEByZXR1cm5zIFRoZSBmb3VuZCBbW1dpemFyZFN0ZXBdXSBhdCB0aGUgZ2l2ZW4gaW5kZXggYHN0ZXBJbmRleGBcbiAgICogQHRocm93cyBBbiBgRXJyb3JgIGlzIHRocm93biwgaWYgdGhlIGdpdmVuIGluZGV4IGBzdGVwSW5kZXhgIGRvZXNuJ3QgZXhpc3RcbiAgICovXG4gIHB1YmxpYyBnZXRTdGVwQXRJbmRleChzdGVwSW5kZXg6IG51bWJlcik6IFdpemFyZFN0ZXAge1xuICAgIGlmICghdGhpcy5oYXNTdGVwKHN0ZXBJbmRleCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgYSBrbm93biBzdGVwLCBidXQgZ290IHN0ZXBJbmRleDogJHtzdGVwSW5kZXh9LmApO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLndpemFyZFN0ZXBzW3N0ZXBJbmRleF07XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgdGhlIGluZGV4IG9mIHRoZSBzdGVwIHdpdGggdGhlIGdpdmVuIGBzdGVwSWRgLlxuICAgKiBJZiBubyBzdGVwIHdpdGggdGhlIGdpdmVuIGBzdGVwSWRgIGV4aXN0cywgYC0xYCBpcyByZXR1cm5lZFxuICAgKlxuICAgKiBAcGFyYW0gc3RlcElkIFRoZSBnaXZlbiBzdGVwIGlkXG4gICAqIEByZXR1cm5zIFRoZSBmb3VuZCBpbmRleCBvZiBhIHN0ZXAgd2l0aCB0aGUgZ2l2ZW4gc3RlcCBpZCwgb3IgYC0xYCBpZiBubyBzdGVwIHdpdGggdGhlIGdpdmVuIGlkIGlzIGluY2x1ZGVkIGluIHRoZSB3aXphcmRcbiAgICovXG4gIHB1YmxpYyBnZXRJbmRleE9mU3RlcFdpdGhJZChzdGVwSWQ6IHN0cmluZyk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMud2l6YXJkU3RlcHMuZmluZEluZGV4KHN0ZXAgPT4gc3RlcC5zdGVwSWQgPT09IHN0ZXBJZCk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgdGhlIGluZGV4IG9mIHRoZSBnaXZlbiBbW1dpemFyZFN0ZXBdXSBgc3RlcGAuXG4gICAqIElmIHRoZSBnaXZlbiBbW1dpemFyZFN0ZXBdXSBpcyBub3QgY29udGFpbmVkIGluc2lkZSB0aGlzIHdpemFyZCwgYC0xYCBpcyByZXR1cm5lZFxuICAgKlxuICAgKiBAcGFyYW0gc3RlcCBUaGUgZ2l2ZW4gW1tXaXphcmRTdGVwXV1cbiAgICogQHJldHVybnMgVGhlIGZvdW5kIGluZGV4IG9mIGBzdGVwYCBvciBgLTFgIGlmIHRoZSBzdGVwIGlzIG5vdCBpbmNsdWRlZCBpbiB0aGUgd2l6YXJkXG4gICAqL1xuICBwdWJsaWMgZ2V0SW5kZXhPZlN0ZXAoc3RlcDogV2l6YXJkU3RlcCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMud2l6YXJkU3RlcHMuaW5kZXhPZihzdGVwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGVzIHRoZSBjb3JyZWN0IFtbTW92aW5nRGlyZWN0aW9uXV0gdmFsdWUgZm9yIGEgZ2l2ZW4gYGRlc3RpbmF0aW9uU3RlcGAgY29tcGFyZWQgdG8gdGhlIGBjdXJyZW50U3RlcEluZGV4YC5cbiAgICpcbiAgICogQHBhcmFtIGRlc3RpbmF0aW9uU3RlcCBUaGUgZ2l2ZW4gZGVzdGluYXRpb24gc3RlcFxuICAgKiBAcmV0dXJucyBUaGUgY2FsY3VsYXRlZCBbW01vdmluZ0RpcmVjdGlvbl1dXG4gICAqL1xuICBwdWJsaWMgZ2V0TW92aW5nRGlyZWN0aW9uKGRlc3RpbmF0aW9uU3RlcDogbnVtYmVyKTogTW92aW5nRGlyZWN0aW9uIHtcbiAgICBsZXQgbW92aW5nRGlyZWN0aW9uOiBNb3ZpbmdEaXJlY3Rpb247XG5cbiAgICBpZiAoZGVzdGluYXRpb25TdGVwID4gdGhpcy5jdXJyZW50U3RlcEluZGV4KSB7XG4gICAgICBtb3ZpbmdEaXJlY3Rpb24gPSBNb3ZpbmdEaXJlY3Rpb24uRm9yd2FyZHM7XG4gICAgfSBlbHNlIGlmIChkZXN0aW5hdGlvblN0ZXAgPCB0aGlzLmN1cnJlbnRTdGVwSW5kZXgpIHtcbiAgICAgIG1vdmluZ0RpcmVjdGlvbiA9IE1vdmluZ0RpcmVjdGlvbi5CYWNrd2FyZHM7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1vdmluZ0RpcmVjdGlvbiA9IE1vdmluZ0RpcmVjdGlvbi5TdGF5O1xuICAgIH1cblxuICAgIHJldHVybiBtb3ZpbmdEaXJlY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzLCB3aGV0aGVyIGEgd2l6YXJkIHN0ZXAsIGFzIGRlZmluZWQgYnkgdGhlIGdpdmVuIGRlc3RpbmF0aW9uIGluZGV4LCBjYW4gYmUgdHJhbnNpdGlvbmVkIHRvLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjb250cm9scyBuYXZpZ2F0aW9uIGJ5IFtbZ29Ub1N0ZXBdXSwgW1tnb1RvUHJldmlvdXNTdGVwXV0sIGFuZCBbW2dvVG9OZXh0U3RlcF1dIGRpcmVjdGl2ZXMuXG4gICAqIE5hdmlnYXRpb24gYnkgbmF2aWdhdGlvbiBiYXIgaXMgZ292ZXJuZWQgYnkgW1tpc05hdmlnYWJsZV1dLlxuICAgKlxuICAgKiBAcGFyYW0gZGVzdGluYXRpb25JbmRleCBUaGUgaW5kZXggb2YgdGhlIGRlc3RpbmF0aW9uIHN0ZXBcbiAgICogQHJldHVybnMgQSBbW1Byb21pc2VdXSBjb250YWluaW5nIGB0cnVlYCwgaWYgdGhlIGRlc3RpbmF0aW9uIHN0ZXAgY2FuIGJlIHRyYW5zaXRpb25lZCB0byBhbmQgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBwdWJsaWMgY2FuR29Ub1N0ZXAoZGVzdGluYXRpb25JbmRleDogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMubmF2aWdhdGlvbi5jYW5Hb1RvU3RlcCh0aGlzLCBkZXN0aW5hdGlvbkluZGV4KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmllcyB0byB0cmFuc2l0aW9uIHRvIHRoZSB3aXphcmQgc3RlcCwgYXMgZGVub3RlZCBieSB0aGUgZ2l2ZW4gZGVzdGluYXRpb24gaW5kZXguXG4gICAqXG4gICAqIE5vdGU6IFlvdSBkbyBub3QgaGF2ZSB0byBjYWxsIFtbY2FuR29Ub1N0ZXBdXSBiZWZvcmUgY2FsbGluZyBbW2dvVG9TdGVwXV0uXG4gICAqIFRoZSBbW2NhbkdvVG9TdGVwXV0gbWV0aG9kIHdpbGwgYmUgY2FsbGVkIGF1dG9tYXRpY2FsbHkuXG4gICAqXG4gICAqIEBwYXJhbSBkZXN0aW5hdGlvbkluZGV4IFRoZSBpbmRleCBvZiB0aGUgZGVzdGluYXRpb24gd2l6YXJkIHN0ZXAsIHdoaWNoIHNob3VsZCBiZSBlbnRlcmVkXG4gICAqIEBwYXJhbSBwcmVGaW5hbGl6ZSBBbiBldmVudCBlbWl0dGVyLCB0byBiZSBjYWxsZWQgYmVmb3JlIHRoZSBzdGVwIGhhcyBiZWVuIHRyYW5zaXRpb25lZFxuICAgKiBAcGFyYW0gcG9zdEZpbmFsaXplIEFuIGV2ZW50IGVtaXR0ZXIsIHRvIGJlIGNhbGxlZCBhZnRlciB0aGUgc3RlcCBoYXMgYmVlbiB0cmFuc2l0aW9uZWRcbiAgICovXG4gIHB1YmxpYyBnb1RvU3RlcChkZXN0aW5hdGlvbkluZGV4OiBudW1iZXIsIHByZUZpbmFsaXplPzogRXZlbnRFbWl0dGVyPHZvaWQ+LCBwb3N0RmluYWxpemU/OiBFdmVudEVtaXR0ZXI8dm9pZD4pOiB2b2lkIHtcbiAgICByZXR1cm4gdGhpcy5uYXZpZ2F0aW9uLmdvVG9TdGVwKHRoaXMsIGRlc3RpbmF0aW9uSW5kZXgsIHByZUZpbmFsaXplLCBwb3N0RmluYWxpemUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyaWVzIHRvIHRyYW5zaXRpb24gdGhlIHdpemFyZCB0byB0aGUgcHJldmlvdXMgc3RlcFxuICAgKlxuICAgKiBAcGFyYW0gcHJlRmluYWxpemUgQW4gZXZlbnQgZW1pdHRlciwgdG8gYmUgY2FsbGVkIGJlZm9yZSB0aGUgc3RlcCBoYXMgYmVlbiB0cmFuc2l0aW9uZWRcbiAgICogQHBhcmFtIHBvc3RGaW5hbGl6ZSBBbiBldmVudCBlbWl0dGVyLCB0byBiZSBjYWxsZWQgYWZ0ZXIgdGhlIHN0ZXAgaGFzIGJlZW4gdHJhbnNpdGlvbmVkXG4gICAqL1xuICBwdWJsaWMgZ29Ub1ByZXZpb3VzU3RlcChwcmVGaW5hbGl6ZT86IEV2ZW50RW1pdHRlcjx2b2lkPiwgcG9zdEZpbmFsaXplPzogRXZlbnRFbWl0dGVyPHZvaWQ+KTogdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMubmF2aWdhdGlvbi5nb1RvU3RlcCh0aGlzLCB0aGlzLmN1cnJlbnRTdGVwSW5kZXggLSAxLCBwcmVGaW5hbGl6ZSwgcG9zdEZpbmFsaXplKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmllcyB0byB0cmFuc2l0aW9uIHRoZSB3aXphcmQgdG8gdGhlIG5leHQgc3RlcFxuICAgKlxuICAgKiBAcGFyYW0gcHJlRmluYWxpemUgQW4gZXZlbnQgZW1pdHRlciwgdG8gYmUgY2FsbGVkIGJlZm9yZSB0aGUgc3RlcCBoYXMgYmVlbiB0cmFuc2l0aW9uZWRcbiAgICogQHBhcmFtIHBvc3RGaW5hbGl6ZSBBbiBldmVudCBlbWl0dGVyLCB0byBiZSBjYWxsZWQgYWZ0ZXIgdGhlIHN0ZXAgaGFzIGJlZW4gdHJhbnNpdGlvbmVkXG4gICAqL1xuICBwdWJsaWMgZ29Ub05leHRTdGVwKHByZUZpbmFsaXplPzogRXZlbnRFbWl0dGVyPHZvaWQ+LCBwb3N0RmluYWxpemU/OiBFdmVudEVtaXR0ZXI8dm9pZD4pOiB2b2lkIHtcbiAgICByZXR1cm4gdGhpcy5uYXZpZ2F0aW9uLmdvVG9TdGVwKHRoaXMsIHRoaXMuY3VycmVudFN0ZXBJbmRleCArIDEsIHByZUZpbmFsaXplLCBwb3N0RmluYWxpemUpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcywgd2hldGhlciB0aGUgd2l6YXJkIHN0ZXAsIGxvY2F0ZWQgYXQgdGhlIGdpdmVuIGluZGV4LCBjYW4gYmUgbmF2aWdhdGVkIHRvIHVzaW5nIHRoZSBuYXZpZ2F0aW9uIGJhci5cbiAgICpcbiAgICogQHBhcmFtIGRlc3RpbmF0aW9uSW5kZXggVGhlIGluZGV4IG9mIHRoZSBkZXN0aW5hdGlvbiBzdGVwXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHN0ZXAgY2FuIGJlIG5hdmlnYXRlZCB0bywgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBwdWJsaWMgaXNOYXZpZ2FibGUoZGVzdGluYXRpb25JbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubmF2aWdhdGlvbi5pc05hdmlnYWJsZSh0aGlzLCBkZXN0aW5hdGlvbkluZGV4KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldHMgdGhlIHN0YXRlIG9mIHRoaXMgd2l6YXJkLlxuICAgKi9cbiAgcHVibGljIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMubmF2aWdhdGlvbi5yZXNldCh0aGlzKTtcbiAgfVxufVxuIiwiPGF3LXdpemFyZC1uYXZpZ2F0aW9uLWJhclxuICAqbmdJZj1cIm5hdkJhckxvY2F0aW9uID09PSAndG9wJyB8fCBuYXZCYXJMb2NhdGlvbiA9PT0gJ2xlZnQnXCJcbiAgW25nQ2xhc3NdPVwie1xuICAgICd2ZXJ0aWNhbCc6IG5hdkJhckxvY2F0aW9uID09PSAnbGVmdCcsXG4gICAgJ2hvcml6b250YWwnOiBuYXZCYXJMb2NhdGlvbiA9PT0gJ3RvcCcsXG4gICAgJ3NtYWxsJzogbmF2QmFyTGF5b3V0ID09PSAnc21hbGwnLFxuICAgICdsYXJnZS1maWxsZWQnOiBuYXZCYXJMYXlvdXQgPT09ICdsYXJnZS1maWxsZWQnLFxuICAgICdsYXJnZS1maWxsZWQtc3ltYm9scyc6IG5hdkJhckxheW91dCA9PT0gJ2xhcmdlLWZpbGxlZC1zeW1ib2xzJyxcbiAgICAnbGFyZ2UtZW1wdHknOiBuYXZCYXJMYXlvdXQgPT09ICdsYXJnZS1lbXB0eScsXG4gICAgJ2xhcmdlLWVtcHR5LXN5bWJvbHMnOiBuYXZCYXJMYXlvdXQgPT09ICdsYXJnZS1lbXB0eS1zeW1ib2xzJ1xuICB9XCI+XG48L2F3LXdpemFyZC1uYXZpZ2F0aW9uLWJhcj5cblxuPGRpdiBbbmdDbGFzc109XCJ7XG4gICd3aXphcmQtc3RlcHMnOiB0cnVlLFxuICAndmVydGljYWwnOiBuYXZCYXJMb2NhdGlvbiA9PT0gJ2xlZnQnIHx8IG5hdkJhckxvY2F0aW9uID09PSAncmlnaHQnLFxuICAnaG9yaXpvbnRhbCc6IG5hdkJhckxvY2F0aW9uID09PSAndG9wJyB8fCBuYXZCYXJMb2NhdGlvbiA9PT0gJ2JvdHRvbSdcbn1cIj5cbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuPC9kaXY+XG5cbjxhdy13aXphcmQtbmF2aWdhdGlvbi1iYXJcbiAgKm5nSWY9XCJuYXZCYXJMb2NhdGlvbiA9PT0gJ2JvdHRvbScgfHwgbmF2QmFyTG9jYXRpb24gPT09ICdyaWdodCdcIlxuICBbbmdDbGFzc109XCJ7XG4gICAgJ3ZlcnRpY2FsJzogbmF2QmFyTG9jYXRpb24gPT09ICdyaWdodCcsXG4gICAgJ2hvcml6b250YWwnOiBuYXZCYXJMb2NhdGlvbiA9PT0gJ2JvdHRvbScsXG4gICAgJ3NtYWxsJzogbmF2QmFyTGF5b3V0ID09PSAnc21hbGwnLFxuICAgICdsYXJnZS1maWxsZWQnOiBuYXZCYXJMYXlvdXQgPT09ICdsYXJnZS1maWxsZWQnLFxuICAgICdsYXJnZS1maWxsZWQtc3ltYm9scyc6IG5hdkJhckxheW91dCA9PT0gJ2xhcmdlLWZpbGxlZC1zeW1ib2xzJyxcbiAgICAnbGFyZ2UtZW1wdHknOiBuYXZCYXJMYXlvdXQgPT09ICdsYXJnZS1lbXB0eScsXG4gICAgJ2xhcmdlLWVtcHR5LXN5bWJvbHMnOiBuYXZCYXJMYXlvdXQgPT09ICdsYXJnZS1lbXB0eS1zeW1ib2xzJ1xuICB9XCI+XG48L2F3LXdpemFyZC1uYXZpZ2F0aW9uLWJhcj5cbiJdfQ==