com.phloxui
Version:
PhloxUI Ng2+ Framework
455 lines (454 loc) • 51.8 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import { Component, ViewChild } from '@angular/core';
import { DialogModel, ConfirmDialogModel } from './model/models';
import { PhloxAppInfoService } from '../service/PhloxAppInfoService.service';
import { NeedFocusService } from '../service/NeedFocusService.service';
import { ConfirmDialog } from './dialog.internal/ConfirmDialog.component';
import { MessageDialog } from './dialog.internal/MessageDialog.component';
import { ComponentDialog } from './dialog.internal/ComponentDialog.component';
const /** @type {?} */ TYPE_NAME = "phx-dialog";
const /** @type {?} */ CONFIRM_DIALOG = 'confirm';
const /** @type {?} */ MESSAGE_DIALOG = 'message';
const /** @type {?} */ COMPONENT_DIALOG = 'component';
/**
* <p style="text-indent: 2em;">
* A <code>singleton</code> UI component controlling <code>application</code> pop-up dialog logic. This dialog is a <code>modal</code> dialog, saying that,
* when it is displayed, all user's UI actions will be blocked and the user will be forced to focus on this dialog. When the user completes the interaction
* with this dialog, for example, clicking on "OK" button, this dialog will be hidden and the user can resume normal UI operations. Normally, you <b>should
* NOT</b> directly access this component instance but you could control it via <b>[[DialogService]]</b>.
* </p>
* <p style="text-indent: 2em;">
* Please note that there is a dialog <code>display queue</code> operating behind the scenes. This <code>display queue</code> is a <code>FIFO</code> queue
* keeping all dialog models ([[DialogModel]]) --which are automatically generated and kept in the queue when <code><i>show...Dialog</i></code> methods are called--
* but those dialog models cannot be displayed suddenly. For example, if there already is a dialog being displayed currently, but, there is also someone else
* calling <code><i>show...Dialog</i></code> method simultaneously, the dialog model generated from the later <code><i>show...Dialog</i></code> method will
* not be showed suddenly. Nevertheless, it'll be showed immediately when the first dialog is closed. For this mechanism, the dialog model can be firstly kept
* in the queue, then, it will be showed and removed from the queue when its preceding dialog is closed.
* </p>
* <p style="text-indent: 2em;">
* If you want to implement your own <b>custom dialog</b>, you should do it using <code>component dialog</code> rather than building it all up from scratches. The only thing
* which you need to do is just implementing the component being displayed inside the dialog body. All other mechanisms, such as dialog <code>display queue</code>
* listed above, should be left to be handled by the framework or by this class. For more information about building custom dialog, please see [[showComponentDialog]].
* </p>
*
* @author shiorin, tee4cute
* @see [[DialogService]]
*/
export class PhloxDialog {
/**
* @param {?} phloxAppService
* @param {?} needFocusService
*/
constructor(phloxAppService, needFocusService) {
this.show = false;
this.dialogQueue = [];
this.dialogResolverQueue = [];
this.needFocusService = needFocusService;
if (phloxAppService != null) {
phloxAppService.getAppInfo().then((result) => {
this.phloxAppInfo = result;
});
}
if (window.history && window.history.pushState) {
$(window).on('popstate', (event) => {
this.hideDialog();
});
}
}
/**
* @param {?} show
* @return {?}
*/
set show(show) {
this._show = show;
if (this._show) {
// if true add class to body
$("body").addClass("phx-dialog-fixed");
}
else {
// if false remove class from body
$("body").removeClass("phx-dialog-fixed");
}
}
/**
* @return {?}
*/
get show() {
return this._show;
}
/**
* @return {?}
*/
showNextDialog() {
this.currentModel = null;
if (this.dialogQueue.length > 0) {
this.currentModel = this.dialogQueue[0];
this.dialogQueue.splice(0, 1);
if (this.dialogResolverQueue.length > 0) {
this.currentResolver = this.dialogResolverQueue[0];
this.dialogResolverQueue.splice(0, 1);
}
if (this.currentModel !== null && typeof this.currentModel !== 'undefined') {
this.showDialog();
return true;
}
else {
this.currentResolver = null;
this.hideDialog();
return false;
}
}
return false;
}
/**
* @param {?} key
* @return {?}
*/
getI18NMessage(key) {
if (this.phloxAppInfo != null && this.phloxAppInfo.i18n != null) {
if (this.phloxAppInfo.i18n[key] !== null && typeof this.phloxAppInfo.i18n[key] !== 'undefined') {
return this.phloxAppInfo.i18n[key];
}
}
return key;
}
/**
* @param {?} model
* @param {?} resolve
* @param {?} reject
* @return {?}
*/
getResolverWrapper(model, resolve, reject) {
let /** @type {?} */ result = {
model: model,
resolve: resolve,
reject: reject
};
return result;
}
/**
* @return {?}
*/
getDialogWidth() {
if (this.currentModel !== null && typeof this.currentModel !== 'undefined') {
if (this.currentModel.width !== null && typeof this.currentModel.width === 'string') {
return this.currentModel.width;
}
}
return "";
}
/**
* @return {?}
*/
getDialogHeight() {
if (this.currentModel !== null && typeof this.currentModel !== 'undefined') {
if (this.currentModel.height !== null && typeof this.currentModel.height === 'string') {
return this.currentModel.height;
}
}
return "";
}
/**
* @param {?} dialogType
* @return {?}
*/
getDialogResult(dialogType) {
if (dialogType === null || typeof dialogType === 'undefined') {
return null;
}
if (dialogType === CONFIRM_DIALOG) {
if (this.confirmDialog !== null && typeof this.confirmDialog !== 'undefined') {
return this.confirmDialog.getDialogResult();
}
}
else if (dialogType === MESSAGE_DIALOG) {
if (this.messageDialog !== null && typeof this.messageDialog !== 'undefined') {
return this.messageDialog.getDialogResult();
}
}
else if (dialogType === COMPONENT_DIALOG) {
if (this.componentDialog !== null && typeof this.componentDialog !== 'undefined') {
return this.componentDialog.getDialogResult();
}
}
return null;
}
/**
* @return {?}
*/
_showDialog() {
this.show = true;
}
/**
* <p style="text-indent: 1em;">
* Show current dialog described by the <code><b>[[currentModel]]</b></code>. This usually be the last model generated by
* the last <code><i>show...Dialog</i></code> method call.
* </p>
* @return {?}
*/
showDialog() {
if (this.currentModel !== null && typeof this.currentModel !== 'undefined') {
let /** @type {?} */ dialogType = this.currentModel.type;
if (typeof dialogType === 'string') {
if (dialogType === CONFIRM_DIALOG) {
if (this.confirmDialog !== null && typeof this.confirmDialog !== 'undefined') {
this.confirmDialog.showDialog();
this._showDialog();
}
}
else if (dialogType === MESSAGE_DIALOG) {
if (this.messageDialog !== null && typeof this.messageDialog !== 'undefined') {
this.messageDialog.showDialog();
this._showDialog();
}
}
else if (dialogType === COMPONENT_DIALOG) {
if (this.componentDialog !== null && typeof this.componentDialog !== 'undefined') {
this.componentDialog.showDialog();
this._showDialog();
}
}
}
}
}
/**
* <p style="text-indent: 1em;">
* Hide the current showing dialog and show the next dialog in the queue (if any).
* </p>
* @return {?}
*/
hideDialog() {
// hide all dialog
if (this.confirmDialog !== null && typeof this.confirmDialog !== 'undefined') {
this.confirmDialog.hideDialog();
}
if (this.messageDialog !== null && typeof this.messageDialog !== 'undefined') {
this.messageDialog.hideDialog();
}
if (this.componentDialog !== null && typeof this.componentDialog !== 'undefined') {
this.componentDialog.hideDialog();
}
// resolve
if (this.currentResolver !== null && typeof this.currentResolver !== 'undefined') {
if (this.currentModel !== null && typeof this.currentModel !== 'undefined') {
this.currentResolver.resolve(this.getDialogResult(this.currentModel.type));
}
else {
this.currentResolver.resolve(null);
}
}
this.currentModel = null;
this.currentResolver = null;
if (this.showNextDialog()) {
return;
}
this.show = false;
}
/**
* <p style="text-indent: 1em;">
* Display a confirmation dialog on the screen.
* </p>
*
* @see [[ConfirmDialog]]
* @param {?} title The dialog title text.
* @param {?} message The dialog message which will be displayed in the dialog body.
* @param {?} showCancelBtn To display the <code>CANCEL</code> button or not. By default, the confirmation dialog will contain only
* <code>YES</code> and <code>NO</code> button.
* @param {?=} width The css <code>"width"</code> style value governing dialog width e.g. <code>100px</code>, <code>50pt</code>.
* @param {?=} height The css <code>"height"</code> style value governing dialog height e.g. <code>100px</code>, <code>50pt</code>.
*
* @return {?} The <code>promise</code> which will be resolved when this dialog is closed. The resolving result will be the value
* returned from [[ConfirmDialog.getDialogResult]] method.
*
*/
showConfirmDialog(title, message, showCancelBtn, width, height) {
return new Promise((resolve, reject) => {
let /** @type {?} */ confirmDialog = new ConfirmDialogModel(title, message, CONFIRM_DIALOG, showCancelBtn, width, height);
let /** @type {?} */ resolver = this.getResolverWrapper(confirmDialog, resolve, reject);
this.currentResolver = resolver;
if (this.currentModel == null) {
this.currentModel = confirmDialog;
if (this.confirmDialog != null) {
this.confirmDialog.showDialog();
this._showDialog();
}
}
else {
// stack in
this.dialogQueue.push(confirmDialog);
this.dialogResolverQueue.push(resolver);
}
});
}
/**
* <p style="text-indent: 1em;">
* Display a message dialog on the screen.
* </p>
*
* @see [[MessageDialog]]
* @param {?} title The dialog title text.
* @param {?} message The dialog message which will be displayed in the dialog body.
* @param {?=} width The css <code>"width"</code> style value governing dialog width e.g. <code>100px</code>, <code>50pt</code>.
* @param {?=} height The css <code>"height"</code> style value governing dialog height e.g. <code>100px</code>, <code>50pt</code>.
*
* @return {?} The <code>promise</code> which will be resolved when this dialog is closed. The resolving result will be the value
* returned from [[MessageDialog.getDialogResult]] method (which always returns <code>true</code>).
*
*/
showMessageDialog(title, message, width, height) {
return new Promise((resolve, reject) => {
let /** @type {?} */ messageDialog = new DialogModel(title, message, MESSAGE_DIALOG, width, height);
let /** @type {?} */ resolver = this.getResolverWrapper(messageDialog, resolve, reject);
this.currentResolver = resolver;
if (this.currentModel == null) {
this.currentModel = messageDialog;
if (this.messageDialog != null) {
this.messageDialog.showDialog();
this._showDialog();
}
}
else {
// stack in
this.dialogQueue.push(messageDialog);
this.dialogResolverQueue.push(resolver);
}
});
}
/**
* <p style="text-indent: 1em;">
* Display a component dialog on the screen. A component dialog is a dialog allowing you to display your own custom dialog by specifying
* a <code>component type</code> being displayed as its body. That <code>component type</code> must be a class which is an instance of
* [[IDialogController]].
* </p>
*
* @see [[ComponentDialog]]
* @param {?} componentDialogModel A dialog model being displayed.
*
* @return {?} The <code>promise</code> which will be resolved when this dialog is closed. The resolving result will be the value returned
* from [[IDialogController.getDialogResult]] method.
*
*/
showComponentDialog(componentDialogModel) {
if (componentDialogModel === null || typeof componentDialogModel === 'undefined') {
return Promise.resolve(null);
}
return new Promise((resolve, reject) => {
let /** @type {?} */ componentDialog = componentDialogModel;
componentDialog.type = COMPONENT_DIALOG;
let /** @type {?} */ resolver = this.getResolverWrapper(componentDialog, resolve, reject);
this.currentResolver = resolver;
if (componentDialogModel.dialogStyleClass !== undefined && componentDialogModel.dialogStyleClass !== null) {
this.dialogClass = componentDialogModel.dialogStyleClass;
}
else {
this.dialogClass = [];
}
if (this.currentModel == null) {
this.currentModel = componentDialog;
if (this.componentDialog != null) {
this.componentDialog.showDialog();
this._showDialog();
}
}
else {
// stack in
this.dialogQueue.push(componentDialog);
this.dialogResolverQueue.push(resolver);
}
});
}
/**
* @return {?}
*/
isShow() {
return this.show;
}
/**
* @return {?}
*/
getCurrentModel() {
return this.currentModel;
}
/**
* @return {?}
*/
getDialogClass() {
return this.dialogClass;
}
}
PhloxDialog.TYPE_NAME = TYPE_NAME;
PhloxDialog.CONFIRM_DIALOG = CONFIRM_DIALOG;
PhloxDialog.MESSAGE_DIALOG = MESSAGE_DIALOG;
PhloxDialog.COMPONENT_DIALOG = COMPONENT_DIALOG;
PhloxDialog.decorators = [
{ type: Component, args: [{
moduleId: module.id,
selector: TYPE_NAME,
template: `<div class="phx-dialog-background" [class.show]="isShow()">
<div class="phx-dialog" [ngClass]="getDialogClass()" [class.show]="isShow()" [style.width]="getDialogWidth()" [style.height]="getDialogHeight()">
<phx-confirm-dialog #confirmdialog [model]="getCurrentModel()" [dialog]="this"></phx-confirm-dialog>
<phx-message-dialog #messagedialog [model]="getCurrentModel()" [dialog]="this"></phx-message-dialog>
<phx-component-dialog #componentdialog [model]="getCurrentModel()" [dialog]="this"></phx-component-dialog>
</div>
</div>
`
},] },
];
/** @nocollapse */
PhloxDialog.ctorParameters = () => [
{ type: PhloxAppInfoService, },
{ type: NeedFocusService, },
];
PhloxDialog.propDecorators = {
"confirmDialog": [{ type: ViewChild, args: ['confirmdialog',] },],
"messageDialog": [{ type: ViewChild, args: ['messagedialog',] },],
"componentDialog": [{ type: ViewChild, args: ['componentdialog',] },],
};
function PhloxDialog_tsickle_Closure_declarations() {
/** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
PhloxDialog.decorators;
/**
* @nocollapse
* @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
*/
PhloxDialog.ctorParameters;
/** @type {!Object<string,!Array<{type: !Function, args: (undefined|!Array<?>)}>>} */
PhloxDialog.propDecorators;
/** @type {?} */
PhloxDialog.TYPE_NAME;
/** @type {?} */
PhloxDialog.CONFIRM_DIALOG;
/** @type {?} */
PhloxDialog.MESSAGE_DIALOG;
/** @type {?} */
PhloxDialog.COMPONENT_DIALOG;
/** @type {?} */
PhloxDialog.prototype.dialogQueue;
/** @type {?} */
PhloxDialog.prototype.dialogClass;
/** @type {?} */
PhloxDialog.prototype.dialogResolverQueue;
/** @type {?} */
PhloxDialog.prototype.confirmDialog;
/** @type {?} */
PhloxDialog.prototype.messageDialog;
/** @type {?} */
PhloxDialog.prototype.componentDialog;
/** @type {?} */
PhloxDialog.prototype.currentModel;
/** @type {?} */
PhloxDialog.prototype.currentResolver;
/** @type {?} */
PhloxDialog.prototype.phloxAppInfo;
/** @type {?} */
PhloxDialog.prototype.needFocusService;
/** @type {?} */
PhloxDialog.prototype._show;
}
export { YES, NO, CANCEL, ConfirmDialog } from './dialog.internal/ConfirmDialog.component';
export { MessageDialog } from './dialog.internal/MessageDialog.component';
export { ComponentDialog } from './dialog.internal/ComponentDialog.component';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGhsb3hEaWFsb2cuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vY29tLnBobG94dWkvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50L1BobG94RGlhbG9nLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDckQsT0FBTyxFQUFFLFdBQVcsRUFBc0Msa0JBQWtCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyRyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUM3RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUN2RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFDMUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDJDQUEyQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQztBQUU5RSx1QkFBTSxTQUFTLEdBQVcsWUFBWSxDQUFDO0FBRXZDLHVCQUFNLGNBQWMsR0FBVyxTQUFTLENBQUM7QUFDekMsdUJBQU0sY0FBYyxHQUFXLFNBQVMsQ0FBQztBQUN6Qyx1QkFBTSxnQkFBZ0IsR0FBVyxXQUFXLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFzQzdDLE1BQU07Ozs7O0lBd0NKLFlBQVksZUFBb0MsRUFBRSxnQkFBa0M7UUFDbEYsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUM7UUFDbEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUM7UUFFekMsRUFBRSxDQUFDLENBQUMsZUFBZSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDNUIsZUFBZSxDQUFD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UUFBUSxFQUFFLE1BQU0sQ0FBQyxFQUFFO2dCQUNuQixRQUFRLEVBQUUsU0FBUztnQkFDbkIsUUFBUSxFQUFFOzs7Ozs7O0NBT1g7YUFDQTs7OztZQS9DUSxtQkFBbUI7WUFDbkIsZ0JBQWdCOzs7OEJBMER0QixTQUFTLFNBQUMsZUFBZTs4QkFFekIsU0FBUyxTQUFDLGVBQWU7Z0NBRXpCLFNBQVMsU0FBQyxpQkFBaUI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUEyVTlCLCtDQUFjLDJDQUEyQyxDQUFDO0FBQzFELDhCQUFjLDJDQUEyQyxDQUFDO0FBQzFELGdDQUFjLDZDQUE2QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERpYWxvZ01vZGVsLCBQaGxveEFwcEluZm8sIENvbXBvbmVudERpYWxvZ01vZGVsLCBDb25maXJtRGlhbG9nTW9kZWwgfSBmcm9tICcuL21vZGVsL21vZGVscyc7XG5pbXBvcnQgeyBQaGxveEFwcEluZm9TZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZS9QaGxveEFwcEluZm9TZXJ2aWNlLnNlcnZpY2UnO1xuaW1wb3J0IHsgTmVlZEZvY3VzU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2UvTmVlZEZvY3VzU2VydmljZS5zZXJ2aWNlJztcbmltcG9ydCB7IENvbmZpcm1EaWFsb2cgfSBmcm9tICcuL2RpYWxvZy5pbnRlcm5hbC9Db25maXJtRGlhbG9nLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBNZXNzYWdlRGlhbG9nIH0gZnJvbSAnLi9kaWFsb2cuaW50ZXJuYWwvTWVzc2FnZURpYWxvZy5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ29tcG9uZW50RGlhbG9nIH0gZnJvbSAnLi9kaWFsb2cuaW50ZXJuYWwvQ29tcG9uZW50RGlhbG9nLmNvbXBvbmVudCc7XG5cbmNvbnN0IFRZUEVfTkFNRTogc3RyaW5nID0gXCJwaHgtZGlhbG9nXCI7XG5cbmNvbnN0IENPTkZJUk1fRElBTE9HOiBzdHJpbmcgPSAnY29uZmlybSc7XG5jb25zdCBNRVNTQUdFX0RJQUxPRzogc3RyaW5nID0gJ21lc3NhZ2UnO1xuY29uc3QgQ09NUE9ORU5UX0RJQUxPRzogc3RyaW5nID0gJ2NvbXBvbmVudCc7XG5cbi8qKlxuICogPHAgc3R5bGU9XCJ0ZXh0LWluZGVudDogMmVtO1wiPlxuICogQSA8Y29kZT5zaW5nbGV0b248L2NvZGU+IFVJIGNvbXBvbmVudCBjb250cm9sbGluZyA8Y29kZT5hcHBsaWNhdGlvbjwvY29kZT4gcG9wLXVwIGRpYWxvZyBsb2dpYy4gVGhpcyBkaWFsb2cgaXMgYSA8Y29kZT5tb2RhbDwvY29kZT4gZGlhbG9nLCBzYXlpbmcgdGhhdCxcbiAqIHdoZW4gaXQgaXMgZGlzcGxheWVkLCBhbGwgdXNlcidzIFVJIGFjdGlvbnMgd2lsbCBiZSBibG9ja2VkIGFuZCB0aGUgdXNlciB3aWxsIGJlIGZvcmNlZCB0byBmb2N1cyBvbiB0aGlzIGRpYWxvZy4gV2hlbiB0aGUgdXNlciBjb21wbGV0ZXMgdGhlIGludGVyYWN0aW9uXG4gKiB3aXRoIHRoaXMgZGlhbG9nLCBmb3IgZXhhbXBsZSwgY2xpY2tpbmcgb24gXCJPS1wiIGJ1dHRvbiwgdGhpcyBkaWFsb2cgd2lsbCBiZSBoaWRkZW4gYW5kIHRoZSB1c2VyIGNhbiByZXN1bWUgbm9ybWFsIFVJIG9wZXJhdGlvbnMuIE5vcm1hbGx5LCB5b3UgPGI+c2hvdWxkXG4gKiBOT1Q8L2I+IGRpcmVjdGx5IGFjY2VzcyB0aGlzIGNvbXBvbmVudCBpbnN0YW5jZSBidXQgeW91IGNvdWxkIGNvbnRyb2wgaXQgdmlhIDxiPltbRGlhbG9nU2VydmljZV1dPC9iPi5cbiAqIDwvcD5cbiAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDJlbTtcIj5cbiAqIFBsZWFzZSBub3RlIHRoYXQgdGhlcmUgaXMgYSBkaWFsb2cgPGNvZGU+ZGlzcGxheSBxdWV1ZTwvY29kZT4gb3BlcmF0aW5nIGJlaGluZCB0aGUgc2NlbmVzLiBUaGlzIDxjb2RlPmRpc3BsYXkgcXVldWU8L2NvZGU+IGlzIGEgPGNvZGU+RklGTzwvY29kZT4gcXVldWVcbiAqIGtlZXBpbmcgYWxsIGRpYWxvZyBtb2RlbHMgKFtbRGlhbG9nTW9kZWxdXSkgLS13aGljaCBhcmUgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgYW5kIGtlcHQgaW4gdGhlIHF1ZXVlIHdoZW4gPGNvZGU+PGk+c2hvdy4uLkRpYWxvZzwvaT48L2NvZGU+IG1ldGhvZHMgYXJlIGNhbGxlZC0tXG4gKiBidXQgdGhvc2UgZGlhbG9nIG1vZGVscyBjYW5ub3QgYmUgZGlzcGxheWVkIHN1ZGRlbmx5LiBGb3IgZXhhbXBsZSwgaWYgdGhlcmUgYWxyZWFkeSBpcyBhIGRpYWxvZyBiZWluZyBkaXNwbGF5ZWQgY3VycmVudGx5LCBidXQsIHRoZXJlIGlzIGFsc28gc29tZW9uZSBlbHNlXG4gKiBjYWxsaW5nIDxjb2RlPjxpPnNob3cuLi5EaWFsb2c8L2k+PC9jb2RlPiBtZXRob2Qgc2ltdWx0YW5lb3VzbHksIHRoZSBkaWFsb2cgbW9kZWwgZ2VuZXJhdGVkIGZyb20gdGhlIGxhdGVyIDxjb2RlPjxpPnNob3cuLi5EaWFsb2c8L2k+PC9jb2RlPiBtZXRob2Qgd2lsbFxuICogbm90IGJlIHNob3dlZCBzdWRkZW5seS4gTmV2ZXJ0aGVsZXNzLCBpdCdsbCBiZSBzaG93ZWQgaW1tZWRpYXRlbHkgd2hlbiB0aGUgZmlyc3QgZGlhbG9nIGlzIGNsb3NlZC4gRm9yIHRoaXMgbWVjaGFuaXNtLCB0aGUgZGlhbG9nIG1vZGVsIGNhbiBiZSBmaXJzdGx5IGtlcHRcbiAqIGluIHRoZSBxdWV1ZSwgdGhlbiwgaXQgd2lsbCBiZSBzaG93ZWQgYW5kIHJlbW92ZWQgZnJvbSB0aGUgcXVldWUgd2hlbiBpdHMgcHJlY2VkaW5nIGRpYWxvZyBpcyBjbG9zZWQuXG4gKiA8L3A+XG4gKiA8cCBzdHlsZT1cInRleHQtaW5kZW50OiAyZW07XCI+XG4gKiBJZiB5b3Ugd2FudCB0byBpbXBsZW1lbnQgeW91ciBvd24gPGI+Y3VzdG9tIGRpYWxvZzwvYj4sIHlvdSBzaG91bGQgZG8gaXQgdXNpbmcgPGNvZGU+Y29tcG9uZW50IGRpYWxvZzwvY29kZT4gcmF0aGVyIHRoYW4gYnVpbGRpbmcgaXQgYWxsIHVwIGZyb20gc2NyYXRjaGVzLiBUaGUgb25seSB0aGluZ1xuICogd2hpY2ggeW91IG5lZWQgdG8gZG8gaXMganVzdCBpbXBsZW1lbnRpbmcgdGhlIGNvbXBvbmVudCBiZWluZyBkaXNwbGF5ZWQgaW5zaWRlIHRoZSBkaWFsb2cgYm9keS4gQWxsIG90aGVyIG1lY2hhbmlzbXMsIHN1Y2ggYXMgZGlhbG9nIDxjb2RlPmRpc3BsYXkgcXVldWU8L2NvZGU+XG4gKiBsaXN0ZWQgYWJvdmUsIHNob3VsZCBiZSBsZWZ0IHRvIGJlIGhhbmRsZWQgYnkgdGhlIGZyYW1ld29yayBvciBieSB0aGlzIGNsYXNzLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBidWlsZGluZyBjdXN0b20gZGlhbG9nLCBwbGVhc2Ugc2VlIFtbc2hvd0NvbXBvbmVudERpYWxvZ11dLlxuICogPC9wPlxuICpcbiAqIEBhdXRob3Igc2hpb3JpbiwgdGVlNGN1dGVcbiAqIEBzZWUgW1tEaWFsb2dTZXJ2aWNlXV1cbiAqL1xuQENvbXBvbmVudCh7XG4gIG1vZHVsZUlkOiBtb2R1bGUuaWQsXG4gIHNlbGVjdG9yOiBUWVBFX05BTUUsXG4gIHRlbXBsYXRlOiBgPGRpdiBjbGFzcz1cInBoeC1kaWFsb2ctYmFja2dyb3VuZFwiIFtjbGFzcy5zaG93XT1cImlzU2hvdygpXCI+XG5cdDxkaXYgY2xhc3M9XCJwaHgtZGlhbG9nXCIgW25nQ2xhc3NdPVwiZ2V0RGlhbG9nQ2xhc3MoKVwiIFtjbGFzcy5zaG93XT1cImlzU2hvdygpXCIgW3N0eWxlLndpZHRoXT1cImdldERpYWxvZ1dpZHRoKClcIiBbc3R5bGUuaGVpZ2h0XT1cImdldERpYWxvZ0hlaWdodCgpXCI+XG5cdFx0PHBoeC1jb25maXJtLWRpYWxvZyAjY29uZmlybWRpYWxvZyBbbW9kZWxdPVwiZ2V0Q3VycmVudE1vZGVsKClcIiBbZGlhbG9nXT1cInRoaXNcIj48L3BoeC1jb25maXJtLWRpYWxvZz5cblx0XHQ8cGh4LW1lc3NhZ2UtZGlhbG9nICNtZXNzYWdlZGlhbG9nIFttb2RlbF09XCJnZXRDdXJyZW50TW9kZWwoKVwiIFtkaWFsb2ddPVwidGhpc1wiPjwvcGh4LW1lc3NhZ2UtZGlhbG9nPlxuXHRcdDxwaHgtY29tcG9uZW50LWRpYWxvZyAjY29tcG9uZW50ZGlhbG9nIFttb2RlbF09XCJnZXRDdXJyZW50TW9kZWwoKVwiIFtkaWFsb2ddPVwidGhpc1wiPjwvcGh4LWNvbXBvbmVudC1kaWFsb2c+XG5cdDwvZGl2PlxuPC9kaXY+XG5gXG59KVxuZXhwb3J0IGNsYXNzIFBobG94RGlhbG9nIHtcblxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFRZUEVfTkFNRTogc3RyaW5nID0gVFlQRV9OQU1FO1xuXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgQ09ORklSTV9ESUFMT0c6IHN0cmluZyA9IENPTkZJUk1fRElBTE9HO1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE1FU1NBR0VfRElBTE9HOiBzdHJpbmcgPSBNRVNTQUdFX0RJQUxPRztcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBDT01QT05FTlRfRElBTE9HOiBzdHJpbmcgPSBDT01QT05FTlRfRElBTE9HO1xuXG4gIHByaXZhdGUgZGlhbG9nUXVldWU6IERpYWxvZ01vZGVsW107XG4gIHByaXZhdGUgZGlhbG9nQ2xhc3M6IHN0cmluZ1tdO1xuICBwcml2YXRlIGRpYWxvZ1Jlc29sdmVyUXVldWU6IGFueVtdO1xuICBAVmlld0NoaWxkKCdjb25maXJtZGlhbG9nJylcbiAgcHJpdmF0ZSBjb25maXJtRGlhbG9nOiBDb25maXJtRGlhbG9nO1xuICBAVmlld0NoaWxkKCdtZXNzYWdlZGlhbG9nJylcbiAgcHJpdmF0ZSBtZXNzYWdlRGlhbG9nOiBNZXNzYWdlRGlhbG9nO1xuICBAVmlld0NoaWxkKCdjb21wb25lbnRkaWFsb2cnKVxuICBwcml2YXRlIGNvbXBvbmVudERpYWxvZzogQ29tcG9uZW50RGlhbG9nO1xuICBwcml2YXRlIGN1cnJlbnRNb2RlbDogRGlhbG9nTW9kZWw7XG4gIHByaXZhdGUgY3VycmVudFJlc29sdmVyOiBhbnk7XG4gIHByaXZhdGUgcGhsb3hBcHBJbmZvOiBQaGxveEFwcEluZm87XG4gIHByaXZhdGUgbmVlZEZvY3VzU2VydmljZTogTmVlZEZvY3VzU2VydmljZTtcbiAgcHJpdmF0ZSBfc2hvdzogYm9vbGVhbjtcblxuICBwcml2YXRlIHNldCBzaG93KHNob3c6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9zaG93ID0gc2hvdztcblxuXG4gICAgaWYgKHRoaXMuX3Nob3cpIHtcbiAgICAgIC8vIGlmIHRydWUgYWRkIGNsYXNzIHRvIGJvZHlcbiAgICAgICQoXCJib2R5XCIpLmFkZENsYXNzKFwicGh4LWRpYWxvZy1maXhlZFwiKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgZmFsc2UgcmVtb3ZlIGNsYXNzIGZyb20gYm9keVxuICAgICAgJChcImJvZHlcIikucmVtb3ZlQ2xhc3MoXCJwaHgtZGlhbG9nLWZpeGVkXCIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0IHNob3coKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Nob3c7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihwaGxveEFwcFNlcnZpY2U6IFBobG94QXBwSW5mb1NlcnZpY2UsIG5lZWRGb2N1c1NlcnZpY2U6IE5lZWRGb2N1c1NlcnZpY2UpIHtcbiAgICB0aGlzLnNob3cgPSBmYWxzZTtcbiAgICB0aGlzLmRpYWxvZ1F1ZXVlID0gW107XG4gICAgdGhpcy5kaWFsb2dSZXNvbHZlclF1ZXVlID0gW107XG4gICAgdGhpcy5uZWVkRm9jdXNTZXJ2aWNlID0gbmVlZEZvY3VzU2VydmljZTtcblxuICAgIGlmIChwaGxveEFwcFNlcnZpY2UgIT0gbnVsbCkge1xuICAgICAgcGhsb3hBcHBTZXJ2aWNlLmdldEFwcEluZm8oKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgdGhpcy5waGxveEFwcEluZm8gPSByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAod2luZG93Lmhpc3RvcnkgJiYgd2luZG93Lmhpc3RvcnkucHVzaFN0YXRlKSB7XG4gICAgICAkKHdpbmRvdykub24oJ3BvcHN0YXRlJywgKGV2ZW50KSA9PiB7XG4gICAgICAgIHRoaXMuaGlkZURpYWxvZygpO1xuICAgICAgfSlcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNob3dOZXh0RGlhbG9nKCk6IGJvb2xlYW4ge1xuICAgIHRoaXMuY3VycmVudE1vZGVsID0gbnVsbDtcbiAgICBpZiAodGhpcy5kaWFsb2dRdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmN1cnJlbnRNb2RlbCA9IHRoaXMuZGlhbG9nUXVldWVbMF07XG4gICAgICB0aGlzLmRpYWxvZ1F1ZXVlLnNwbGljZSgwLCAxKTtcblxuICAgICAgaWYgKHRoaXMuZGlhbG9nUmVzb2x2ZXJRdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFJlc29sdmVyID0gdGhpcy5kaWFsb2dSZXNvbHZlclF1ZXVlWzBdO1xuICAgICAgICB0aGlzLmRpYWxvZ1Jlc29sdmVyUXVldWUuc3BsaWNlKDAsIDEpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5jdXJyZW50TW9kZWwgIT09IG51bGwgJiYgdHlwZW9mIHRoaXMuY3VycmVudE1vZGVsICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aGlzLnNob3dEaWFsb2coKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmN1cnJlbnRSZXNvbHZlciA9IG51bGw7XG4gICAgICAgIHRoaXMuaGlkZURpYWxvZygpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRJMThOTWVzc2FnZShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMucGhsb3hBcHBJbmZvICE9IG51bGwgJiYgdGhpcy5waGxveEFwcEluZm8uaTE4biAhPSBudWxsKSB7XG4gICAgICBpZiAodGhpcy5waGxveEFwcEluZm8uaTE4bltrZXldICE9PSBudWxsICYmIHR5cGVvZiB0aGlzLnBobG94QXBwSW5mby5pMThuW2tleV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBobG94QXBwSW5mby5pMThuW2tleV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBrZXk7XG4gIH1cblxuICBwcml2YXRlIGdldFJlc29sdmVyV3JhcHBlcihtb2RlbDogYW55LCByZXNvbHZlOiBhbnksIHJlamVjdDogYW55KTogYW55IHtcbiAgICBsZXQgcmVzdWx0ID0ge1xuICAgICAgbW9kZWw6IG1vZGVsLFxuICAgICAgcmVzb2x2ZTogcmVzb2x2ZSxcbiAgICAgIHJlamVjdDogcmVqZWN0XG4gICAgfTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0RGlhbG9nV2lkdGgoKTogc3RyaW5nIHtcbiAgICBpZiAodGhpcy5jdXJyZW50TW9kZWwgIT09IG51bGwgJiYgdHlwZW9mIHRoaXMuY3VycmVudE1vZGVsICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgaWYgKHRoaXMuY3VycmVudE1vZGVsLndpZHRoICE9PSBudWxsICYmIHR5cGVvZiB0aGlzLmN1cnJlbnRNb2RlbC53aWR0aCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudE1vZGVsLndpZHRoO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBcIlwiO1xuICB9XG5cbiAgcHVibGljIGdldERpYWxvZ0hlaWdodCgpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLmN1cnJlbnRNb2RlbCAhPT0gbnVsbCAmJiB0eXBlb2YgdGhpcy5jdXJyZW50TW9kZWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBpZiAodGhpcy5jdXJyZW50TW9kZWwuaGVpZ2h0ICE9PSBudWxsICYmIHR5cGVvZiB0aGlzLmN1cnJlbnRNb2RlbC5oZWlnaHQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRNb2RlbC5oZWlnaHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiXCI7XG4gIH1cblxuICBwcml2YXRlIGdldERpYWxvZ1Jlc3VsdChkaWFsb2dUeXBlOiBzdHJpbmcpOiBhbnkge1xuICAgIGlmIChkaWFsb2dUeXBlID09PSBudWxsIHx8IHR5cGVvZiBkaWFsb2dUeXBlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKGRpYWxvZ1R5cGUgPT09IENPTkZJUk1fRElBTE9HKSB7XG4gICAgICBpZiAodGhpcy5jb25maXJtRGlhbG9nICE9PSBudWxsICYmIHR5cGVvZiB0aGlzLmNvbmZpcm1EaWFsb2cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpcm1EaWFsb2cuZ2V0RGlhbG9nUmVzdWx0KCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChkaWFsb2dUeXBlID09PSBNRVNTQUdFX0RJQUxPRykge1xuICAgICAgaWYgKHRoaXMubWVzc2FnZURpYWxvZyAhPT0gbnVsbCAmJiB0eXBlb2YgdGhpcy5tZXNzYWdlRGlhbG9nICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlRGlhbG9nLmdldERpYWxvZ1Jlc3VsdCgpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZGlhbG9nVHlwZSA9PT0gQ09NUE9ORU5UX0RJQUxPRykge1xuICAgICAgaWYgKHRoaXMuY29tcG9uZW50RGlhbG9nICE9PSBudWxsICYmIHR5cGVvZiB0aGlzLmNvbXBvbmVudERpYWxvZyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcG9uZW50RGlhbG9nLmdldERpYWxvZ1Jlc3VsdCgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2hvd0RpYWxvZygpOiB2b2lkIHtcbiAgICB0aGlzLnNob3cgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDFlbTtcIj5cbiAgICogU2hvdyBjdXJyZW50IGRpYWxvZyBkZXNjcmliZWQgYnkgdGhlIDxjb2RlPjxiPltbY3VycmVudE1vZGVsXV08L2I+PC9jb2RlPi4gVGhpcyB1c3VhbGx5IGJlIHRoZSBsYXN0IG1vZGVsIGdlbmVyYXRlZCBieVxuICAgKiB0aGUgbGFzdCA8Y29kZT48aT5zaG93Li4uRGlhbG9nPC9pPjwvY29kZT4gbWV0aG9kIGNhbGwuXG4gICAqIDwvcD5cbiAgICovXG4gIHB1YmxpYyBzaG93RGlhbG9nKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmN1cnJlbnRNb2RlbCAhPT0gbnVsbCAmJiB0eXBlb2YgdGhpcy5jdXJyZW50TW9kZWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBsZXQgZGlhbG9nVHlwZSA9IHRoaXMuY3VycmVudE1vZGVsLnR5cGU7XG4gICAgICBpZiAodHlwZW9mIGRpYWxvZ1R5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGlmIChkaWFsb2dUeXBlID09PSBDT05GSVJNX0RJQUxPRykge1xuICAgICAgICAgIGlmICh0aGlzLmNvbmZpcm1EaWFsb2cgIT09IG51bGwgJiYgdHlwZW9mIHRoaXMuY29uZmlybURpYWxvZyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRoaXMuY29uZmlybURpYWxvZy5zaG93RGlhbG9nKCk7XG4gICAgICAgICAgICB0aGlzLl9zaG93RGlhbG9nKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGRpYWxvZ1R5cGUgPT09IE1FU1NBR0VfRElBTE9HKSB7XG4gICAgICAgICAgaWYgKHRoaXMubWVzc2FnZURpYWxvZyAhPT0gbnVsbCAmJiB0eXBlb2YgdGhpcy5tZXNzYWdlRGlhbG9nICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhpcy5tZXNzYWdlRGlhbG9nLnNob3dEaWFsb2coKTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3dEaWFsb2coKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZGlhbG9nVHlwZSA9PT0gQ09NUE9ORU5UX0RJQUxPRykge1xuICAgICAgICAgIGlmICh0aGlzLmNvbXBvbmVudERpYWxvZyAhPT0gbnVsbCAmJiB0eXBlb2YgdGhpcy5jb21wb25lbnREaWFsb2cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aGlzLmNvbXBvbmVudERpYWxvZy5zaG93RGlhbG9nKCk7XG4gICAgICAgICAgICB0aGlzLl9zaG93RGlhbG9nKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDFlbTtcIj5cbiAgICogSGlkZSB0aGUgY3VycmVudCBzaG93aW5nIGRpYWxvZyBhbmQgc2hvdyB0aGUgbmV4dCBkaWFsb2cgaW4gdGhlIHF1ZXVlIChpZiBhbnkpLlxuICAgKiA8L3A+XG4gICAqL1xuICBwdWJsaWMgaGlkZURpYWxvZygpOiB2b2lkIHtcbiAgICAvLyBoaWRlIGFsbCBkaWFsb2dcbiAgICBpZiAodGhpcy5jb25maXJtRGlhbG9nICE9PSBudWxsICYmIHR5cGVvZiB0aGlzLmNvbmZpcm1EaWFsb2cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLmNvbmZpcm1EaWFsb2cuaGlkZURpYWxvZygpO1xuICAgIH1cbiAgICBpZiAodGhpcy5tZXNzYWdlRGlhbG9nICE9PSBudWxsICYmIHR5cGVvZiB0aGlzLm1lc3NhZ2VEaWFsb2cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2VEaWFsb2cuaGlkZURpYWxvZygpO1xuICAgIH1cbiAgICBpZiAodGhpcy5jb21wb25lbnREaWFsb2cgIT09IG51bGwgJiYgdHlwZW9mIHRoaXMuY29tcG9uZW50RGlhbG9nICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5jb21wb25lbnREaWFsb2cuaGlkZURpYWxvZygpO1xuICAgIH1cblxuICAgIC8vIHJlc29sdmVcbiAgICBpZiAodGhpcy5jdXJyZW50UmVzb2x2ZXIgIT09IG51bGwgJiYgdHlwZW9mIHRoaXMuY3VycmVudFJlc29sdmVyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgaWYgKHRoaXMuY3VycmVudE1vZGVsICE9PSBudWxsICYmIHR5cGVvZiB0aGlzLmN1cnJlbnRNb2RlbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50UmVzb2x2ZXIucmVzb2x2ZSh0aGlzLmdldERpYWxvZ1Jlc3VsdCh0aGlzLmN1cnJlbnRNb2RlbC50eXBlKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmN1cnJlbnRSZXNvbHZlci5yZXNvbHZlKG51bGwpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuY3VycmVudE1vZGVsID0gbnVsbDtcbiAgICB0aGlzLmN1cnJlbnRSZXNvbHZlciA9IG51bGw7XG4gICAgaWYgKHRoaXMuc2hvd05leHREaWFsb2coKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnNob3cgPSBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiA8cCBzdHlsZT1cInRleHQtaW5kZW50OiAxZW07XCI+XG4gICAqIERpc3BsYXkgYSBjb25maXJtYXRpb24gZGlhbG9nIG9uIHRoZSBzY3JlZW4uXG4gICAqIDwvcD5cbiAgICpcbiAgICogQHBhcmFtIHRpdGxlIFRoZSBkaWFsb2cgdGl0bGUgdGV4dC5cbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIGRpYWxvZyBtZXNzYWdlIHdoaWNoIHdpbGwgYmUgZGlzcGxheWVkIGluIHRoZSBkaWFsb2cgYm9keS5cbiAgICogQHBhcmFtIHNob3dDYW5jZWxCdG4gVG8gZGlzcGxheSB0aGUgPGNvZGU+Q0FOQ0VMPC9jb2RlPiBidXR0b24gb3Igbm90LiBCeSBkZWZhdWx0LCB0aGUgY29uZmlybWF0aW9uIGRpYWxvZyB3aWxsIGNvbnRhaW4gb25seVxuICAgKiA8Y29kZT5ZRVM8L2NvZGU+IGFuZCA8Y29kZT5OTzwvY29kZT4gYnV0dG9uLlxuICAgKiBAcGFyYW0gd2lkdGggVGhlIGNzcyA8Y29kZT5cIndpZHRoXCI8L2NvZGU+IHN0eWxlIHZhbHVlIGdvdmVybmluZyBkaWFsb2cgd2lkdGggZS5nLiA8Y29kZT4xMDBweDwvY29kZT4sIDxjb2RlPjUwcHQ8L2NvZGU+LlxuICAgKiBAcGFyYW0gaGVpZ2h0IFRoZSBjc3MgPGNvZGU+XCJoZWlnaHRcIjwvY29kZT4gc3R5bGUgdmFsdWUgZ292ZXJuaW5nIGRpYWxvZyBoZWlnaHQgZS5nLiA8Y29kZT4xMDBweDwvY29kZT4sIDxjb2RlPjUwcHQ8L2NvZGU+LlxuICAgKlxuICAgKiBAcmV0dXJuIFRoZSA8Y29kZT5wcm9taXNlPC9jb2RlPiB3aGljaCB3aWxsIGJlIHJlc29sdmVkIHdoZW4gdGhpcyBkaWFsb2cgaXMgY2xvc2VkLiBUaGUgcmVzb2x2aW5nIHJlc3VsdCB3aWxsIGJlIHRoZSB2YWx1ZVxuICAgKiByZXR1cm5lZCBmcm9tIFtbQ29uZmlybURpYWxvZy5nZXREaWFsb2dSZXN1bHRdXSBtZXRob2QuXG4gICAqXG4gICAqIEBzZWUgW1tDb25maXJtRGlhbG9nXV1cbiAgICovXG4gIHB1YmxpYyBzaG93Q29uZmlybURpYWxvZyh0aXRsZTogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcsIHNob3dDYW5jZWxCdG46IGJvb2xlYW4sIHdpZHRoPzogc3RyaW5nLCBoZWlnaHQ/OiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgY29uZmlybURpYWxvZyA9IG5ldyBDb25maXJtRGlhbG9nTW9kZWwodGl0bGUsIG1lc3NhZ2UsIENPTkZJUk1fRElBTE9HLCBzaG93Q2FuY2VsQnRuLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgIGxldCByZXNvbHZlciA9IHRoaXMuZ2V0UmVzb2x2ZXJXcmFwcGVyKGNvbmZpcm1EaWFsb2csIHJlc29sdmUsIHJlamVjdCk7XG4gICAgICB0aGlzLmN1cnJlbnRSZXNvbHZlciA9IHJlc29sdmVyO1xuXG4gICAgICBpZiAodGhpcy5jdXJyZW50TW9kZWwgPT0gbnVsbCkge1xuICAgICAgICB0aGlzLmN1cnJlbnRNb2RlbCA9IGNvbmZpcm1EaWFsb2c7XG5cbiAgICAgICAgaWYgKHRoaXMuY29uZmlybURpYWxvZyAhPSBudWxsKSB7XG4gICAgICAgICAgdGhpcy5jb25maXJtRGlhbG9nLnNob3dEaWFsb2coKTtcbiAgICAgICAgICB0aGlzLl9zaG93RGlhbG9nKCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHN0YWNrIGluXG4gICAgICAgIHRoaXMuZGlhbG9nUXVldWUucHVzaChjb25maXJtRGlhbG9nKTtcbiAgICAgICAgdGhpcy5kaWFsb2dSZXNvbHZlclF1ZXVlLnB1c2gocmVzb2x2ZXIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDFlbTtcIj5cbiAgICogRGlzcGxheSBhIG1lc3NhZ2UgZGlhbG9nIG9uIHRoZSBzY3JlZW4uXG4gICAqIDwvcD5cbiAgICpcbiAgICogQHBhcmFtIHRpdGxlIFRoZSBkaWFsb2cgdGl0bGUgdGV4dC5cbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIGRpYWxvZyBtZXNzYWdlIHdoaWNoIHdpbGwgYmUgZGlzcGxheWVkIGluIHRoZSBkaWFsb2cgYm9keS5cbiAgICogQHBhcmFtIHdpZHRoIFRoZSBjc3MgPGNvZGU+XCJ3aWR0aFwiPC9jb2RlPiBzdHlsZSB2YWx1ZSBnb3Zlcm5pbmcgZGlhbG9nIHdpZHRoIGUuZy4gPGNvZGU+MTAwcHg8L2NvZGU+LCA8Y29kZT41MHB0PC9jb2RlPi5cbiAgICogQHBhcmFtIGhlaWdodCBUaGUgY3NzIDxjb2RlPlwiaGVpZ2h0XCI8L2NvZGU+IHN0eWxlIHZhbHVlIGdvdmVybmluZyBkaWFsb2cgaGVpZ2h0IGUuZy4gPGNvZGU+MTAwcHg8L2NvZGU+LCA8Y29kZT41MHB0PC9jb2RlPi5cbiAgICpcbiAgICogQHJldHVybiBUaGUgPGNvZGU+cHJvbWlzZTwvY29kZT4gd2hpY2ggd2lsbCBiZSByZXNvbHZlZCB3aGVuIHRoaXMgZGlhbG9nIGlzIGNsb3NlZC4gVGhlIHJlc29sdmluZyByZXN1bHQgd2lsbCBiZSB0aGUgdmFsdWVcbiAgICogcmV0dXJuZWQgZnJvbSBbW01lc3NhZ2VEaWFsb2cuZ2V0RGlhbG9nUmVzdWx0XV0gbWV0aG9kICh3aGljaCBhbHdheXMgcmV0dXJucyA8Y29kZT50cnVlPC9jb2RlPikuXG4gICAqXG4gICAqIEBzZWUgW1tNZXNzYWdlRGlhbG9nXV1cbiAgICovXG4gIHB1YmxpYyBzaG93TWVzc2FnZURpYWxvZyh0aXRsZTogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcsIHdpZHRoPzogc3RyaW5nLCBoZWlnaHQ/OiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgbWVzc2FnZURpYWxvZyA9IG5ldyBEaWFsb2dNb2RlbCh0aXRsZSwgbWVzc2FnZSwgTUVTU0FHRV9ESUFMT0csIHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgICBsZXQgcmVzb2x2ZXIgPSB0aGlzLmdldFJlc29sdmVyV3JhcHBlcihtZXNzYWdlRGlhbG9nLCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgdGhpcy5jdXJyZW50UmVzb2x2ZXIgPSByZXNvbHZlcjtcblxuICAgICAgaWYgKHRoaXMuY3VycmVudE1vZGVsID09IG51bGwpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50TW9kZWwgPSBtZXNzYWdlRGlhbG9nO1xuXG4gICAgICAgIGlmICh0aGlzLm1lc3NhZ2VEaWFsb2cgIT0gbnVsbCkge1xuICAgICAgICAgIHRoaXMubWVzc2FnZURpYWxvZy5zaG93RGlhbG9nKCk7XG4gICAgICAgICAgdGhpcy5fc2hvd0RpYWxvZygpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBzdGFjayBpblxuICAgICAgICB0aGlzLmRpYWxvZ1F1ZXVlLnB1c2gobWVzc2FnZURpYWxvZyk7XG4gICAgICAgIHRoaXMuZGlhbG9nUmVzb2x2ZXJRdWV1ZS5wdXNoKHJlc29sdmVyKTtcbiAgICAgIH1cblxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIDxwIHN0eWxlPVwidGV4dC1pbmRlbnQ6IDFlbTtcIj5cbiAgICogRGlzcGxheSBhIGNvbXBvbmVudCBkaWFsb2cgb24gdGhlIHNjcmVlbi4gQSBjb21wb25lbnQgZGlhbG9nIGlzIGEgZGlhbG9nIGFsbG93aW5nIHlvdSB0byBkaXNwbGF5IHlvdXIgb3duIGN1c3RvbSBkaWFsb2cgYnkgc3BlY2lmeWluZ1xuICAgKiBhIDxjb2RlPmNvbXBvbmVudCB0eXBlPC9jb2RlPiBiZWluZyBkaXNwbGF5ZWQgYXMgaXRzIGJvZHkuIFRoYXQgPGNvZGU+Y29tcG9uZW50IHR5cGU8L2NvZGU+IG11c3QgYmUgYSBjbGFzcyB3aGljaCBpcyBhbiBpbnN0YW5jZSBvZlxuICAgKiBbW0lEaWFsb2dDb250cm9sbGVyXV0uXG4gICAqIDwvcD5cbiAgICpcbiAgICogQHBhcmFtIGNvbXBvbmVudERpYWxvZ01vZGVsIEEgZGlhbG9nIG1vZGVsIGJlaW5nIGRpc3BsYXllZC5cbiAgICpcbiAgICogQHJldHVybiBUaGUgPGNvZGU+cHJvbWlzZTwvY29kZT4gd2hpY2ggd2lsbCBiZSByZXNvbHZlZCB3aGVuIHRoaXMgZGlhbG9nIGlzIGNsb3NlZC4gVGhlIHJlc29sdmluZyByZXN1bHQgd2lsbCBiZSB0aGUgdmFsdWUgcmV0dXJuZWRcbiAgICogZnJvbSBbW0lEaWFsb2dDb250cm9sbGVyLmdldERpYWxvZ1Jlc3VsdF1dIG1ldGhvZC5cbiAgICpcbiAgICogQHNlZSBbW0NvbXBvbmVudERpYWxvZ11dXG4gICAqL1xuICBwdWJsaWMgc2hvd0NvbXBvbmVudERpYWxvZyhjb21wb25lbnREaWFsb2dNb2RlbDogQ29tcG9uZW50RGlhbG9nTW9kZWwpOiBQcm9taXNlPGFueT4ge1xuICAgIGlmIChjb21wb25lbnREaWFsb2dNb2RlbCA9PT0gbnVsbCB8fCB0eXBlb2YgY29tcG9uZW50RGlhbG9nTW9kZWwgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4g