angular-archwizard
Version:
An Angular 9+ module containing a wizard component and its supporting components and directives
164 lines • 22.3 kB
JavaScript
import { MovingDirection } from '../util/moving-direction.enum';
/**
* Base implementation of [[NavigationMode]]
*
* Note: Built-in [[NavigationMode]] classes should be stateless, allowing the library user to easily create
* an instance of a particular [[NavigationMode]] class and pass it to `<aw-wizard [navigationMode]="...">`.
*
* @author Marc Arndt
*/
export class BaseNavigationMode {
/**
* 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]].
*
* In this implementation, a destination wizard step can be entered if:
* - it exists
* - the current step can be exited in the direction of the destination step
* - the destination step can be entered in the direction from the current step
*
* Subclasses can impose additional restrictions, see [[canTransitionToStep]].
*
* @param wizard The wizard component to operate on
* @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(wizard, destinationIndex) {
const hasStep = wizard.hasStep(destinationIndex);
const movingDirection = wizard.getMovingDirection(destinationIndex);
const canExitCurrentStep = (previous) => {
return previous && wizard.currentStep.canExitStep(movingDirection);
};
const canEnterDestinationStep = (previous) => {
return previous && wizard.getStepAtIndex(destinationIndex).canEnterStep(movingDirection);
};
const canTransitionToStep = (previous) => {
return previous && this.canTransitionToStep(wizard, destinationIndex);
};
return Promise.resolve(hasStep)
.then(canTransitionToStep)
// Apply user-defined checks at the end. They can involve user interaction
// which is better to be avoided if navigation mode does not actually allow the transition
// (`canTransitionToStep` returns `false`).
.then(canExitCurrentStep)
.then(canEnterDestinationStep);
}
/**
* Imposes additional restrictions for `canGoToStep` in current navigation mode.
*
* The base implementation allows transition iff the given step is navigable from the navigation bar (see `isNavigable`).
* However, in some navigation modes `canTransitionToStep` can be more relaxed to allow navigation to certain steps
* by previous/next buttons, but not using the navigation bar.
*
* @param wizard The wizard component to operate on
* @param destinationIndex The index of the destination step
* @returns `true`, if the destination step can be transitioned to and `false` otherwise
*/
canTransitionToStep(wizard, destinationIndex) {
return this.isNavigable(wizard, destinationIndex);
}
/**
* Tries to transition to the wizard step, as denoted by the given destination index.
*
* When entering the destination step, the following actions are done:
* - the old current step is set as completed
* - the old current step is set as unselected
* - the old current step is exited
* - the destination step is set as selected
* - the destination step is entered
*
* When the destination step couldn't be entered, the following actions are done:
* - the current step is exited and entered in the direction `MovingDirection.Stay`
*
* @param wizard The wizard component to operate on
* @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(wizard, destinationIndex, preFinalize, postFinalize) {
this.canGoToStep(wizard, destinationIndex).then(navigationAllowed => {
if (navigationAllowed) {
// the current step can be exited in the given direction
const movingDirection = wizard.getMovingDirection(destinationIndex);
/* istanbul ignore if */
if (preFinalize) {
preFinalize.emit();
}
// leave current step
wizard.currentStep.completed = true;
wizard.currentStep.exit(movingDirection);
wizard.currentStep.editing = false;
wizard.currentStep.selected = false;
this.transition(wizard, destinationIndex);
// remember if the next step is already completed before entering it to properly set `editing` flag
const wasCompleted = wizard.completed || wizard.currentStep.completed;
// go to next step
wizard.currentStep.enter(movingDirection);
wizard.currentStep.selected = true;
if (wasCompleted) {
wizard.currentStep.editing = true;
}
/* istanbul ignore if */
if (postFinalize) {
postFinalize.emit();
}
}
else {
// if the current step can't be left, reenter the current step
wizard.currentStep.exit(MovingDirection.Stay);
wizard.currentStep.enter(MovingDirection.Stay);
}
});
}
/**
* Transitions the wizard to the given step index.
*
* Can perform additional actions in particular navigation mode implementations.
*
* @param wizard The wizard component to operate on
* @param destinationIndex The index of the destination wizard step
*/
transition(wizard, destinationIndex) {
wizard.currentStepIndex = destinationIndex;
}
/**
* Resets the state of this wizard.
*
* A reset transitions the wizard automatically to the first step and sets all steps as incomplete.
* In addition the whole wizard is set as incomplete.
*
* @param wizard The wizard component to operate on
*/
reset(wizard) {
this.ensureCanReset(wizard);
// reset the step internal state
wizard.wizardSteps.forEach(step => {
step.completed = step.initiallyCompleted;
step.selected = false;
step.editing = false;
});
// set the first step as the current step
wizard.currentStepIndex = wizard.defaultStepIndex;
wizard.currentStep.selected = true;
wizard.currentStep.enter(MovingDirection.Forwards);
}
/**
* Checks if wizard configuration allows to perform reset.
*
* A check failure is indicated by throwing an `Error` with the message discribing the discovered misconfiguration issue.
*
* Can include additional checks in particular navigation mode implementations.
*
* @param wizard The wizard component to operate on
* @throws An `Error` is thrown, if a micconfiguration issue is discovered.
*/
ensureCanReset(wizard) {
// the wizard doesn't contain a step with the default step index
if (!wizard.hasStep(wizard.defaultStepIndex)) {
throw new Error(`The wizard doesn't contain a step with index ${wizard.defaultStepIndex}`);
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1uYXZpZ2F0aW9uLW1vZGUuaW50ZXJmYWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vYW5ndWxhci1hcmNod2l6YXJkLyIsInNvdXJjZXMiOlsibGliL25hdmlnYXRpb24vYmFzZS1uYXZpZ2F0aW9uLW1vZGUuaW50ZXJmYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQztBQUk5RDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxPQUFnQixrQkFBa0I7SUFFdEM7Ozs7Ozs7Ozs7Ozs7Ozs7T0FnQkc7SUFDSSxXQUFXLENBQUMsTUFBdUIsRUFBRSxnQkFBd0I7UUFDbEUsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRWpELE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXBFLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxRQUFpQixFQUFFLEVBQUU7WUFDL0MsT0FBTyxRQUFRLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDckUsQ0FBQyxDQUFDO1FBRUYsTUFBTSx1QkFBdUIsR0FBRyxDQUFDLFFBQWlCLEVBQUUsRUFBRTtZQUNwRCxPQUFPLFFBQVEsSUFBSSxNQUFNLENBQUMsY0FBYyxDQUFDLGdCQUFnQixDQUFDLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzNGLENBQUMsQ0FBQztRQUVGLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxRQUFpQixFQUFFLEVBQUU7WUFDaEQsT0FBTyxRQUFRLElBQUksSUFBSSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3hFLENBQUMsQ0FBQztRQUVGLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7YUFDNUIsSUFBSSxDQUFDLG1CQUFt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Q0FBQyxnQkFBZ0IsQ0FBQztRQUNsRCxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDbkMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDTyxjQUFjLENBQUMsTUFBdUI7UUFDOUMsZ0VBQWdFO1FBQ2hFLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFO1lBQzVDLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7U0FDNUY7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0V2ZW50RW1pdHRlcn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge01vdmluZ0RpcmVjdGlvbn0gZnJvbSAnLi4vdXRpbC9tb3ZpbmctZGlyZWN0aW9uLmVudW0nO1xuaW1wb3J0IHtOYXZpZ2F0aW9uTW9kZX0gZnJvbSAnLi9uYXZpZ2F0aW9uLW1vZGUuaW50ZXJmYWNlJztcbmltcG9ydCB7V2l6YXJkQ29tcG9uZW50fSBmcm9tICcuLi9jb21wb25lbnRzL3dpemFyZC5jb21wb25lbnQnO1xuXG4vKipcbiAqIEJhc2UgaW1wbGVtZW50YXRpb24gb2YgW1tOYXZpZ2F0aW9uTW9kZV1dXG4gKlxuICogTm90ZTogQnVpbHQtaW4gW1tOYXZpZ2F0aW9uTW9kZV1dIGNsYXNzZXMgc2hvdWxkIGJlIHN0YXRlbGVzcywgYWxsb3dpbmcgdGhlIGxpYnJhcnkgdXNlciB0byBlYXNpbHkgY3JlYXRlXG4gKiBhbiBpbnN0YW5jZSBvZiBhIHBhcnRpY3VsYXIgW1tOYXZpZ2F0aW9uTW9kZV1dIGNsYXNzIGFuZCBwYXNzIGl0IHRvIGA8YXctd2l6YXJkIFtuYXZpZ2F0aW9uTW9kZV09XCIuLi5cIj5gLlxuICpcbiAqIEBhdXRob3IgTWFyYyBBcm5kdFxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZU5hdmlnYXRpb25Nb2RlIGltcGxlbWVudHMgTmF2aWdhdGlvbk1vZGUge1xuXG4gIC8qKlxuICAgKiBDaGVja3MsIHdoZXRoZXIgYSB3aXphcmQgc3RlcCwgYXMgZGVmaW5lZCBieSB0aGUgZ2l2ZW4gZGVzdGluYXRpb24gaW5kZXgsIGNhbiBiZSB0cmFuc2l0aW9uZWQgdG8uXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGNvbnRyb2xzIG5hdmlnYXRpb24gYnkgW1tnb1RvU3RlcF1dLCBbW2dvVG9QcmV2aW91c1N0ZXBdXSwgYW5kIFtbZ29Ub05leHRTdGVwXV0gZGlyZWN0aXZlcy5cbiAgICogTmF2aWdhdGlvbiBieSBuYXZpZ2F0aW9uIGJhciBpcyBnb3Zlcm5lZCBieSBbW2lzTmF2aWdhYmxlXV0uXG4gICAqXG4gICAqIEluIHRoaXMgaW1wbGVtZW50YXRpb24sIGEgZGVzdGluYXRpb24gd2l6YXJkIHN0ZXAgY2FuIGJlIGVudGVyZWQgaWY6XG4gICAqIC0gaXQgZXhpc3RzXG4gICAqIC0gdGhlIGN1cnJlbnQgc3RlcCBjYW4gYmUgZXhpdGVkIGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIGRlc3RpbmF0aW9uIHN0ZXBcbiAgICogLSB0aGUgZGVzdGluYXRpb24gc3RlcCBjYW4gYmUgZW50ZXJlZCBpbiB0aGUgZGlyZWN0aW9uIGZyb20gdGhlIGN1cnJlbnQgc3RlcFxuICAgKlxuICAgKiBTdWJjbGFzc2VzIGNhbiBpbXBvc2UgYWRkaXRpb25hbCByZXN0cmljdGlvbnMsIHNlZSBbW2NhblRyYW5zaXRpb25Ub1N0ZXBdXS5cbiAgICpcbiAgICogQHBhcmFtIHdpemFyZCBUaGUgd2l6YXJkIGNvbXBvbmVudCB0byBvcGVyYXRlIG9uXG4gICAqIEBwYXJhbSBkZXN0aW5hdGlvbkluZGV4IFRoZSBpbmRleCBvZiB0aGUgZGVzdGluYXRpb24gc3RlcFxuICAgKiBAcmV0dXJucyBBIFtbUHJvbWlzZV1dIGNvbnRhaW5pbmcgYHRydWVgLCBpZiB0aGUgZGVzdGluYXRpb24gc3RlcCBjYW4gYmUgdHJhbnNpdGlvbmVkIHRvIGFuZCBgZmFsc2VgIG90aGVyd2lzZVxuICAgKi9cbiAgcHVibGljIGNhbkdvVG9TdGVwKHdpemFyZDogV2l6YXJkQ29tcG9uZW50LCBkZXN0aW5hdGlvbkluZGV4OiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBoYXNTdGVwID0gd2l6YXJkLmhhc1N0ZXAoZGVzdGluYXRpb25JbmRleCk7XG5cbiAgICBjb25zdCBtb3ZpbmdEaXJlY3Rpb24gPSB3aXphcmQuZ2V0TW92aW5nRGlyZWN0aW9uKGRlc3RpbmF0aW9uSW5kZXgpO1xuXG4gICAgY29uc3QgY2FuRXhpdEN1cnJlbnRTdGVwID0gKHByZXZpb3VzOiBib29sZWFuKSA9PiB7XG4gICAgICByZXR1cm4gcHJldmlvdXMgJiYgd2l6YXJkLmN1cnJlbnRTdGVwLmNhbkV4aXRTdGVwKG1vdmluZ0RpcmVjdGlvbik7XG4gICAgfTtcblxuICAgIGNvbnN0IGNhbkVudGVyRGVzdGluYXRpb25TdGVwID0gKHByZXZpb3VzOiBib29sZWFuKSA9PiB7XG4gICAgICByZXR1cm4gcHJldmlvdXMgJiYgd2l6YXJkLmdldFN0ZXBBdEluZGV4KGRlc3RpbmF0aW9uSW5kZXgpLmNhbkVudGVyU3RlcChtb3ZpbmdEaXJlY3Rpb24pO1xuICAgIH07XG5cbiAgICBjb25zdCBjYW5UcmFuc2l0aW9uVG9TdGVwID0gKHByZXZpb3VzOiBib29sZWFuKSA9PiB7XG4gICAgICByZXR1cm4gcHJldmlvdXMgJiYgdGhpcy5jYW5UcmFuc2l0aW9uVG9TdGVwKHdpemFyZCwgZGVzdGluYXRpb25JbmRleCk7XG4gICAgfTtcblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoaGFzU3RlcClcbiAgICAgIC50aGVuKGNhblRyYW5zaXRpb25Ub1N0ZXApXG4gICAgICAvLyBBcHBseSB1c2VyLWRlZmluZWQgY2hlY2tzIGF0IHRoZSBlbmQuICBUaGV5IGNhbiBpbnZvbHZlIHVzZXIgaW50ZXJhY3Rpb25cbiAgICAgIC8vIHdoaWNoIGlzIGJldHRlciB0byBiZSBhdm9pZGVkIGlmIG5hdmlnYXRpb24gbW9kZSBkb2VzIG5vdCBhY3R1YWxseSBhbGxvdyB0aGUgdHJhbnNpdGlvblxuICAgICAgLy8gKGBjYW5UcmFuc2l0aW9uVG9TdGVwYCByZXR1cm5zIGBmYWxzZWApLlxuICAgICAgLnRoZW4oY2FuRXhpdEN1cnJlbnRTdGVwKVxuICAgICAgLnRoZW4oY2FuRW50ZXJEZXN0aW5hdGlvblN0ZXApO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcG9zZXMgYWRkaXRpb25hbCByZXN0cmljdGlvbnMgZm9yIGBjYW5Hb1RvU3RlcGAgaW4gY3VycmVudCBuYXZpZ2F0aW9uIG1vZGUuXG4gICAqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIGFsbG93cyB0cmFuc2l0aW9uIGlmZiB0aGUgZ2l2ZW4gc3RlcCBpcyBuYXZpZ2FibGUgZnJvbSB0aGUgbmF2aWdhdGlvbiBiYXIgKHNlZSBgaXNOYXZpZ2FibGVgKS5cbiAgICogSG93ZXZlciwgaW4gc29tZSBuYXZpZ2F0aW9uIG1vZGVzIGBjYW5UcmFuc2l0aW9uVG9TdGVwYCBjYW4gYmUgbW9yZSByZWxheGVkIHRvIGFsbG93IG5hdmlnYXRpb24gdG8gY2VydGFpbiBzdGVwc1xuICAgKiBieSBwcmV2aW91cy9uZXh0IGJ1dHRvbnMsIGJ1dCBub3QgdXNpbmcgdGhlIG5hdmlnYXRpb24gYmFyLlxuICAgKlxuICAgKiBAcGFyYW0gd2l6YXJkIFRoZSB3aXphcmQgY29tcG9uZW50IHRvIG9wZXJhdGUgb25cbiAgICogQHBhcmFtIGRlc3RpbmF0aW9uSW5kZXggVGhlIGluZGV4IG9mIHRoZSBkZXN0aW5hdGlvbiBzdGVwXG4gICAqIEByZXR1cm5zIGB0cnVlYCwgaWYgdGhlIGRlc3RpbmF0aW9uIHN0ZXAgY2FuIGJlIHRyYW5zaXRpb25lZCB0byBhbmQgYGZhbHNlYCBvdGhlcndpc2VcbiAgICovXG4gIHByb3RlY3RlZCBjYW5UcmFuc2l0aW9uVG9TdGVwKHdpemFyZDogV2l6YXJkQ29tcG9uZW50LCBkZXN0aW5hdGlvbkluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pc05hdmlnYWJsZSh3aXphcmQsIGRlc3RpbmF0aW9uSW5kZXgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyaWVzIHRvIHRyYW5zaXRpb24gdG8gdGhlIHdpemFyZCBzdGVwLCBhcyBkZW5vdGVkIGJ5IHRoZSBnaXZlbiBkZXN0aW5hdGlvbiBpbmRleC5cbiAgICpcbiAgICogV2hlbiBlbnRlcmluZyB0aGUgZGVzdGluYXRpb24gc3RlcCwgdGhlIGZvbGxvd2luZyBhY3Rpb25zIGFyZSBkb25lOlxuICAgKiAtIHRoZSBvbGQgY3VycmVudCBzdGVwIGlzIHNldCBhcyBjb21wbGV0ZWRcbiAgICogLSB0aGUgb2xkIGN1cnJlbnQgc3RlcCBpcyBzZXQgYXMgdW5zZWxlY3RlZFxuICAgKiAtIHRoZSBvbGQgY3VycmVudCBzdGVwIGlzIGV4aXRlZFxuICAgKiAtIHRoZSBkZXN0aW5hdGlvbiBzdGVwIGlzIHNldCBhcyBzZWxlY3RlZFxuICAgKiAtIHRoZSBkZXN0aW5hdGlvbiBzdGVwIGlzIGVudGVyZWRcbiAgICpcbiAgICogV2hlbiB0aGUgZGVzdGluYXRpb24gc3RlcCBjb3VsZG4ndCBiZSBlbnRlcmVkLCB0aGUgZm9sbG93aW5nIGFjdGlvbnMgYXJlIGRvbmU6XG4gICAqIC0gdGhlIGN1cnJlbnQgc3RlcCBpcyBleGl0ZWQgYW5kIGVudGVyZWQgaW4gdGhlIGRpcmVjdGlvbiBgTW92aW5nRGlyZWN0aW9uLlN0YXlgXG4gICAqXG4gICAqIEBwYXJhbSB3aXphcmQgVGhlIHdpemFyZCBjb21wb25lbnQgdG8gb3BlcmF0ZSBvblxuICAgKiBAcGFyYW0gZGVzdGluYXRpb25JbmRleCBUaGUgaW5kZXggb2YgdGhlIGRlc3RpbmF0aW9uIHdpemFyZCBzdGVwLCB3aGljaCBzaG91bGQgYmUgZW50ZXJlZFxuICAgKiBAcGFyYW0gcHJlRmluYWxpemUgQW4gZXZlbnQgZW1pdHRlciwgdG8gYmUgY2FsbGVkIGJlZm9yZSB0aGUgc3RlcCBoYXMgYmVlbiB0cmFuc2l0aW9uZWRcbiAgICogQHBhcmFtIHBvc3RGaW5hbGl6ZSBBbiBldmVudCBlbWl0dGVyLCB0byBiZSBjYWxsZWQgYWZ0ZXIgdGhlIHN0ZXAgaGFzIGJlZW4gdHJhbnNpdGlvbmVkXG4gICAqL1xuICBwdWJsaWMgZ29Ub1N0ZXAoXG4gICAgd2l6YXJkOiBXaXphcmRDb21wb25lbnQsXG4gICAgZGVzdGluYXRpb25JbmRleDogbnVtYmVyLFxuICAgIHByZUZpbmFsaXplPzogRXZlbnRFbWl0dGVyPHZvaWQ+LFxuICAgIHBvc3RGaW5hbGl6ZT86IEV2ZW50RW1pdHRlcjx2b2lkPik6IHZvaWQge1xuXG4gICAgdGhpcy5jYW5Hb1RvU3RlcCh3aXphcmQsIGRlc3RpbmF0aW9uSW5kZXgpLnRoZW4obmF2aWdhdGlvbkFsbG93ZWQgPT4ge1xuICAgICAgaWYgKG5hdmlnYXRpb25BbGxvd2VkKSB7XG4gICAgICAgIC8vIHRoZSBjdXJyZW50IHN0ZXAgY2FuIGJlIGV4aXRlZCBpbiB0aGUgZ2l2ZW4gZGlyZWN0aW9uXG4gICAgICAgIGNvbnN0IG1vdmluZ0RpcmVjdGlvbjogTW92aW5nRGlyZWN0aW9uID0gd2l6YXJkLmdldE1vdmluZ0RpcmVjdGlvbihkZXN0aW5hdGlvbkluZGV4KTtcblxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgICAgaWYgKHByZUZpbmFsaXplKSB7XG4gICAgICAgICAgcHJlRmluYWxpemUuZW1pdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbGVhdmUgY3VycmVudCBzdGVwXG4gICAgICAgIHdpemFyZC5jdXJyZW50U3RlcC5jb21wbGV0ZWQgPSB0cnVlO1xuICAgICAgICB3aXphcmQuY3VycmVudFN0ZXAuZXhpdChtb3ZpbmdEaXJlY3Rpb24pO1xuICAgICAgICB3aXphcmQuY3VycmVudFN0ZXAuZWRpdGluZyA9IGZhbHNlO1xuICAgICAgICB3aXphcmQuY3VycmVudFN0ZXAuc2VsZWN0ZWQgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLnRyYW5zaXRpb24od2l6YXJkLCBkZXN0aW5hdGlvbkluZGV4KTtcblxuICAgICAgICAvLyByZW1lbWJlciBpZiB0aGUgbmV4dCBzdGVwIGlzIGFscmVhZHkgY29tcGxldGVkIGJlZm9yZSBlbnRlcmluZyBpdCB0byBwcm9wZXJseSBzZXQgYGVkaXRpbmdgIGZsYWdcbiAgICAgICAgY29uc3Qgd2FzQ29tcGxldGVkID0gd2l6YXJkLmNvbXBsZXRlZCB8fCB3aXphcmQuY3VycmVudFN0ZXAuY29tcGxldGVkO1xuXG4gICAgICAgIC8vIGdvIHRvIG5leHQgc3RlcFxuICAgICAgICB3aXphcmQuY3VycmVudFN0ZXAuZW50ZXIobW92aW5nRGlyZWN0aW9uKTtcbiAgICAgICAgd2l6YXJkLmN1cnJlbnRTdGVwLnNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgaWYgKHdhc0NvbXBsZXRlZCkge1xuICAgICAgICAgIHdpemFyZC5jdXJyZW50U3RlcC5lZGl0aW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgICBpZiAocG9zdEZpbmFsaXplKSB7XG4gICAgICAgICAgcG9zdEZpbmFsaXplLmVtaXQoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaWYgdGhlIGN1cnJlbnQgc3RlcCBjYW4ndCBiZSBsZWZ0LCByZWVudGVyIHRoZSBjdXJyZW50IHN0ZXBcbiAgICAgICAgd2l6YXJkLmN1cnJlbnRTdGVwLmV4aXQoTW92aW5nRGlyZWN0aW9uLlN0YXkpO1xuICAgICAgICB3aXphcmQuY3VycmVudFN0ZXAuZW50ZXIoTW92aW5nRGlyZWN0aW9uLlN0YXkpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zaXRpb25zIHRoZSB3aXphcmQgdG8gdGhlIGdpdmVuIHN0ZXAgaW5kZXguXG4gICAqXG4gICAqIENhbiBwZXJmb3JtIGFkZGl0aW9uYWwgYWN0aW9ucyBpbiBwYXJ0aWN1bGFyIG5hdmlnYXRpb24gbW9kZSBpbXBsZW1lbnRhdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB3aXphcmQgVGhlIHdpemFyZCBjb21wb25lbnQgdG8gb3BlcmF0ZSBvblxuICAgKiBAcGFyYW0gZGVzdGluYXRpb25JbmRleCBUaGUgaW5kZXggb2YgdGhlIGRlc3RpbmF0aW9uIHdpemFyZCBzdGVwXG4gICAqL1xuICBwcm90ZWN0ZWQgdHJhbnNpdGlvbih3aXphcmQ6IFdpemFyZENvbXBvbmVudCwgZGVzdGluYXRpb25JbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgd2l6YXJkLmN1cnJlbnRTdGVwSW5kZXggPSBkZXN0aW5hdGlvbkluZGV4O1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbmhlcml0RG9jXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgaXNOYXZpZ2FibGUoV2l6YXJkQ29tcG9uZW50OiBXaXphcmRDb21wb25lbnQsIGRlc3RpbmF0aW9uSW5kZXg6IG51bWJlcik6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFJlc2V0cyB0aGUgc3RhdGUgb2YgdGhpcyB3aXphcmQuXG4gICAqXG4gICAqIEEgcmVzZXQgdHJhbnNpdGlvbnMgdGhlIHdpemFyZCBhdXRvbWF0aWNhbGx5IHRvIHRoZSBmaXJzdCBzdGVwIGFuZCBzZXRzIGFsbCBzdGVwcyBhcyBpbmNvbXBsZXRlLlxuICAgKiBJbiBhZGRpdGlvbiB0aGUgd2hvbGUgd2l6YXJkIGlzIHNldCBhcyBpbmNvbXBsZXRlLlxuICAgKlxuICAgKiBAcGFyYW0gd2l6YXJkIFRoZSB3aXphcmQgY29tcG9uZW50IHRvIG9wZXJhdGUgb25cbiAgICovXG4gIHB1YmxpYyByZXNldCh3aXphcmQ6IFdpemFyZENvbXBvbmVudCk6IHZvaWQge1xuICAgIHRoaXMuZW5zdXJlQ2FuUmVzZXQod2l6YXJkKTtcblxuICAgIC8vIHJlc2V0IHRoZSBzdGVwIGludGVybmFsIHN0YXRlXG4gICAgd2l6YXJkLndpemFyZFN0ZXBzLmZvckVhY2goc3RlcCA9PiB7XG4gICAgICBzdGVwLmNvbXBsZXRlZCA9IHN0ZXAuaW5pdGlhbGx5Q29tcGxldGVkO1xuICAgICAgc3RlcC5zZWxlY3RlZCA9IGZhbHNlO1xuICAgICAgc3RlcC5lZGl0aW5nID0gZmFsc2U7XG4gICAgfSk7XG5cbiAgICAvLyBzZXQgdGhlIGZpcnN0IHN0ZXAgYXMgdGhlIGN1cnJlbnQgc3RlcFxuICAgIHdpemFyZC5jdXJyZW50U3RlcEluZGV4ID0gd2l6YXJkLmRlZmF1bHRTdGVwSW5kZXg7XG4gICAgd2l6YXJkLmN1cnJlbnRTdGVwLnNlbGVjdGVkID0gdHJ1ZTtcbiAgICB3aXphcmQuY3VycmVudFN0ZXAuZW50ZXIoTW92aW5nRGlyZWN0aW9uLkZvcndhcmRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgd2l6YXJkIGNvbmZpZ3VyYXRpb24gYWxsb3dzIHRvIHBlcmZvcm0gcmVzZXQuXG4gICAqXG4gICAqIEEgY2hlY2sgZmFpbHVyZSBpcyBpbmRpY2F0ZWQgYnkgdGhyb3dpbmcgYW4gYEVycm9yYCB3aXRoIHRoZSBtZXNzYWdlIGRpc2NyaWJpbmcgdGhlIGRpc2NvdmVyZWQgbWlzY29uZmlndXJhdGlvbiBpc3N1ZS5cbiAgICpcbiAgICogQ2FuIGluY2x1ZGUgYWRkaXRpb25hbCBjaGVja3MgaW4gcGFydGljdWxhciBuYXZpZ2F0aW9uIG1vZGUgaW1wbGVtZW50YXRpb25zLlxuICAgKlxuICAgKiBAcGFyYW0gd2l6YXJkIFRoZSB3aXphcmQgY29tcG9uZW50IHRvIG9wZXJhdGUgb25cbiAgICogQHRocm93cyBBbiBgRXJyb3JgIGlzIHRocm93biwgaWYgYSBtaWNjb25maWd1cmF0aW9uIGlzc3VlIGlzIGRpc2NvdmVyZWQuXG4gICAqL1xuICBwcm90ZWN0ZWQgZW5zdXJlQ2FuUmVzZXQod2l6YXJkOiBXaXphcmRDb21wb25lbnQpOiB2b2lkIHtcbiAgICAvLyB0aGUgd2l6YXJkIGRvZXNuJ3QgY29udGFpbiBhIHN0ZXAgd2l0aCB0aGUgZGVmYXVsdCBzdGVwIGluZGV4XG4gICAgaWYgKCF3aXphcmQuaGFzU3RlcCh3aXphcmQuZGVmYXVsdFN0ZXBJbmRleCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlIHdpemFyZCBkb2Vzbid0IGNvbnRhaW4gYSBzdGVwIHdpdGggaW5kZXggJHt3aXphcmQuZGVmYXVsdFN0ZXBJbmRleH1gKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==