yy-menu
Version:
A traditional menu system for web apps inspired by Electron
397 lines (372 loc) • 47.4 kB
JavaScript
const Config = require('./config');
const MenuItem = require('./menuItem');
const LocalAccelerator = require('./localAccelerator');
const html = require('./html');
let _application;
class Menu {
/**
* creates a menu bar
* @param {object} [options]
* @param {object} [options.styles] additional CSS styles for menu
*/
constructor(options) {
options = options || {};
this.div = document.createElement('div');
this.styles = options.styles;
this.children = [];
this.applyConfig(Config.MenuStyle);
this.div.tabIndex = -1;
}
/**
* append a MenuItem to the Menu
* @param {MenuItem} menuItem
*/
append(menuItem) {
if (menuItem.submenu) {
menuItem.submenu.menu = this;
}
menuItem.menu = this;
this.div.appendChild(menuItem.div);
if (menuItem.type !== 'separator') {
this.children.push(menuItem);
}
}
/**
* inserts a MenuItem into the Menu
* @param {number} pos
* @param {MenuItem} menuItem
*/
insert(pos, menuItem) {
if (pos >= this.div.childNodes.length) {
this.append(menuItem);
} else {
if (menuItem.submenu) {
menuItem.submenu.menu = this;
}
menuItem.menu = this;
this.div.insertBefore(menuItem.div, this.div.childNodes[pos]);
if (menuItem.type !== 'separator') {
this.children.splice(pos, 0, menuItem);
}
}
}
hide() {
let current = this.menu.showing;
while (current && current.submenu) {
current.div.style.backgroundColor = 'transparent';
current.submenu.div.remove();
let next = current.submenu.showing;
if (next) {
current.submenu.showing.div.style.backgroundColor = 'transparent';
current.submenu.showing = null;
}
current = next;
}
}
show(menuItem) {
Menu.LocalAccelerator.unregisterMenuShortcuts();
if (this.menu && this.menu.showing === menuItem) {
this.hide();
this.menu.showing = null;
this.div.remove();
this.menu.showAccelerators();
} else {
if (this.menu) {
if (this.menu.showing && this.menu.children.indexOf(menuItem) !== -1) {
this.hide();
}
this.menu.showing = menuItem;
this.menu.hideAccelerators();
}
const div = menuItem.div;
const parent = this.menu.div;
if (this.menu.applicationMenu) {
this.div.style.left = div.offsetLeft + 'px';
this.div.style.top = div.offsetTop + div.offsetHeight + 'px';
} else {
this.div.style.left = parent.offsetLeft + parent.offsetWidth - Config.Overlap + 'px';
this.div.style.top = parent.offsetTop + div.offsetTop - Config.Overlap + 'px';
}
this.attached = menuItem;
this.showAccelerators();
this.getApplicationDiv().appendChild(this.div);
let label = 0,
accelerator = 0,
arrow = 0,
checked = 0;
for (let child of this.children) {
child.check.style.width = 'auto';
child.label.style.width = 'auto';
child.accelerator.style.width = 'auto';
child.arrow.style.width = 'auto';
if (child.type === 'checkbox') {
checked = Config.MinimumColumnWidth;
}
if (child.submenu) {
arrow = Config.MinimumColumnWidth;
}
}
for (let child of this.children) {
const childLabel = child.label.offsetWidth * 2;
label = childLabel > label ? childLabel : label;
const childAccelerator = child.accelerator.offsetWidth;
accelerator = childAccelerator > accelerator ? childAccelerator : accelerator;
if (child.submenu) {
arrow = child.arrow.offsetWidth;
}
}
for (let child of this.children) {
child.check.style.width = checked + 'px';
child.label.style.width = label + 'px';
child.accelerator.style.width = accelerator + 'px';
child.arrow.style.width = arrow + 'px';
}
if (this.div.offsetLeft + this.div.offsetWidth > window.innerWidth) {
this.div.style.left = window.innerWidth - this.div.offsetWidth + 'px';
}
if (this.div.offsetTop + this.div.offsetHeight > window.innerHeight) {
this.div.style.top = window.innerHeight - this.div.offsetHeight + 'px';
}
_application.menu.div.focus();
}
}
applyConfig(base) {
const styles = {};
for (let style in base) {
styles[style] = base[style];
}
if (this.styles) {
for (let style in this.styles) {
styles[style] = this.styles[style];
}
}
for (let style in styles) {
this.div.style[style] = styles[style];
}
}
showAccelerators() {
for (let child of this.children) {
child.showShortcut();
if (child.type !== 'separator') {
const index = child.text.indexOf('&');
if (index !== -1) {
Menu.LocalAccelerator.registerMenuShortcut(child.text[index + 1], child);
}
}
}
if (!this.applicationMenu) {
Menu.LocalAccelerator.registerMenuSpecial(this);
}
}
hideAccelerators() {
for (let child of this.children) {
child.hideShortcut();
}
}
closeAll() {
Menu.LocalAccelerator.unregisterMenuShortcuts();
let application = _application.menu;
if (application.showing) {
let menu = application;
while (menu.showing) {
menu = menu.showing.submenu;
}
while (menu && !menu.applicationMenu) {
if (menu.showing) {
menu.showing.div.style.backgroundColor = 'transparent';
menu.showing = null;
}
menu.div.remove();
menu = menu.menu;
}
if (menu) {
menu.showing.div.style.background = 'transparent';
menu.showing = null;
menu.hideAccelerators();
}
}
}
getApplicationDiv() {
return _application;
}
/**
* move selector to the next child pane
* @param {string} direction (left or right)
* @private
*/
moveChild(direction) {
let index;
if (direction === 'left') {
const parent = this.selector.menu.menu;
index = parent.children.indexOf(parent.showing);
index--;
index = index < 0 ? parent.children.length - 1 : index;
parent.children[index].handleClick();
} else {
let parent = this.selector.menu.menu;
let selector = parent.showing;
while (!parent.applicationMenu) {
selector.handleClick();
selector.div.style.backgroundColor = 'transparent';
parent = parent.menu;
selector = parent.showing;
}
index = parent.children.indexOf(selector);
index++;
index = index === parent.children.length ? 0 : index;
parent.children[index].handleClick();
}
this.selector = null;
}
/**
* move selector right and left
* @param {MouseEvent} e
* @param {string} direction
* @private
*/
horizontalSelector(e, direction) {
if (direction === 'right') {
if (this.selector.submenu) {
this.selector.handleClick(e);
this.selector.submenu.selector = this.selector.submenu.children[0];
this.selector.submenu.selector.div.style.backgroundColor = Config.SelectedBackgroundStyle;
this.selector = null;
} else {
this.moveChild(direction);
}
} else if (direction === 'left') {
if (!this.selector.menu.menu.applicationMenu) {
this.selector.menu.attached.handleClick(e);
this.selector.menu.menu.selector = this.selector.menu.attached;
this.selector = null;
} else {
this.moveChild(direction);
}
}
e.stopPropagation();
e.preventDefault();
}
/**
* move the selector in the menu
* @param {KeyboardEvent} e
* @param {string} direction (left, right, up, down)
* @private
*/
move(e, direction) {
if (this.selector) {
this.selector.div.style.backgroundColor = 'transparent';
let index = this.children.indexOf(this.selector);
if (direction === 'down') {
index++;
index = index === this.children.length ? 0 : index;
} else if (direction === 'up') {
index--;
index = index < 0 ? this.children.length - 1 : index;
} else {
return this.horizontalSelector(e, direction);
}
this.selector = this.children[index];
} else {
if (direction === 'up') {
this.selector = this.children[this.children.length - 1];
} else {
this.selector = this.children[0];
}
}
this.selector.div.style.backgroundColor = Config.SelectedBackgroundStyle;
e.preventDefault();
e.stopPropagation();
}
/**
* click the selector with keyboard
* @private
*/
enter(e) {
if (this.selector) {
this.selector.handleClick(e);
e.preventDefault();
e.stopPropagation();
}
}
/**
* array containing the menu's items
* @property {MenuItems[]} items
* @readonly
*/
get items() {
return this.children;
}
/**
* show application menu accelerators when alt is pressed
* @private
*/
showApplicationAccelerators() {
this.hideAccelerators();
LocalAccelerator.registerAlt(() => {
if (!this.showing) {
this.showAccelerators();
}
}, () => {
this.hideAccelerators();
});
}
/**
* sets active application Menu (and removes any existing application menus)
* @param {Menu} menu
*/
static setApplicationMenu(menu) {
LocalAccelerator.init();
if (_application) {
_application.remove();
}
_application = html({ parent: document.body, styles: Config.ApplicationContainerStyle });
_application.menu = menu;
menu.applyConfig(Config.ApplicationMenuStyle);
for (let child of menu.children) {
child.applyConfig(Config.ApplicationMenuRowStyle);
if (child.arrow) {
child.arrow.style.display = 'none';
}
menu.div.appendChild(child.div);
}
_application.appendChild(menu.div);
menu.applicationMenu = true;
menu.div.tabIndex = -1;
// don't let menu bar focus unless windows are open (this fixes a focus bug)
menu.div.addEventListener('focus', () => {
if (!menu.showing) {
menu.div.blur();
}
});
// close all windows if menu is no longer the focus
menu.div.addEventListener('blur', () => {
if (menu.showing) {
menu.closeAll();
}
});
menu.showApplicationAccelerators();
}
/**
* localAccelerator definition
* @type {Accelerator}
*/
static get LocalAccelerator() {
return LocalAccelerator;
}
/**
* use this to change the default Config settings across all menus
* @type {Config}
*/
static get Config() {
return Config;
}
/**
* MenuItem definition
* @type {MenuItem}
*/
static get MenuItem() {
return MenuItem;
}
}
module.exports = Menu;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9tZW51LmpzIl0sIm5hbWVzIjpbIkNvbmZpZyIsInJlcXVpcmUiLCJNZW51SXRlbSIsIkxvY2FsQWNjZWxlcmF0b3IiLCJodG1sIiwiX2FwcGxpY2F0aW9uIiwiTWVudSIsImNvbnN0cnVjdG9yIiwib3B0aW9ucyIsImRpdiIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudCIsInN0eWxlcyIsImNoaWxkcmVuIiwiYXBwbHlDb25maWciLCJNZW51U3R5bGUiLCJ0YWJJbmRleCIsImFwcGVuZCIsIm1lbnVJdGVtIiwic3VibWVudSIsIm1lbnUiLCJhcHBlbmRDaGlsZCIsInR5cGUiLCJwdXNoIiwiaW5zZXJ0IiwicG9zIiwiY2hpbGROb2RlcyIsImxlbmd0aCIsImluc2VydEJlZm9yZSIsInNwbGljZSIsImhpZGUiLCJjdXJyZW50Iiwic2hvd2luZyIsInN0eWxlIiwiYmFja2dyb3VuZENvbG9yIiwicmVtb3ZlIiwibmV4dCIsInNob3ciLCJ1bnJlZ2lzdGVyTWVudVNob3J0Y3V0cyIsInNob3dBY2NlbGVyYXRvcnMiLCJpbmRleE9mIiwiaGlkZUFjY2VsZXJhdG9ycyIsInBhcmVudCIsImFwcGxpY2F0aW9uTWVudSIsImxlZnQiLCJvZmZzZXRMZWZ0IiwidG9wIiwib2Zmc2V0VG9wIiwib2Zmc2V0SGVpZ2h0Iiwib2Zmc2V0V2lkdGgiLCJPdmVybGFwIiwiYXR0YWNoZWQiLCJnZXRBcHBsaWNhdGlvbkRpdiIsImxhYmVsIiwiYWNjZWxlcmF0b3IiLCJhcnJvdyIsImNoZWNrZWQiLCJjaGlsZCIsImNoZWNrIiwid2lkdGgiLCJNaW5pbXVtQ29sdW1uV2lkdGgiLCJjaGlsZExhYmVsIiwiY2hpbGRBY2NlbGVyYXRvciIsIndpbmRvdyIsImlubmVyV2lkdGgiLCJpbm5lckhlaWdodCIsImZvY3VzIiwiYmFzZSIsInNob3dTaG9ydGN1dCIsImluZGV4IiwidGV4dCIsInJlZ2lzdGVyTWVudVNob3J0Y3V0IiwicmVnaXN0ZXJNZW51U3BlY2lhbCIsImhpZGVTaG9ydGN1dCIsImNsb3NlQWxsIiwiYXBwbGljYXRpb24iLCJiYWNrZ3JvdW5kIiwibW92ZUNoaWxkIiwiZGlyZWN0aW9uIiwic2VsZWN0b3IiLCJoYW5kbGVDbGljayIsImhvcml6b250YWxTZWxlY3RvciIsImUiLCJTZWxlY3RlZEJhY2tncm91bmRTdHlsZSIsInN0b3BQcm9wYWdhdGlvbiIsInByZXZlbnREZWZhdWx0IiwibW92ZSIsImVudGVyIiwiaXRlbXMiLCJzaG93QXBwbGljYXRpb25BY2NlbGVyYXRvcnMiLCJyZWdpc3RlckFsdCIsInNldEFwcGxpY2F0aW9uTWVudSIsImluaXQiLCJib2R5IiwiQXBwbGljYXRpb25Db250YWluZXJTdHlsZSIsIkFwcGxpY2F0aW9uTWVudVN0eWxlIiwiQXBwbGljYXRpb25NZW51Um93U3R5bGUiLCJkaXNwbGF5IiwiYWRkRXZlbnRMaXN0ZW5lciIsImJsdXIiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiQUFBQSxNQUFNQSxTQUFXQyxRQUFRLFVBQVIsQ0FBakI7QUFDQSxNQUFNQyxXQUFXRCxRQUFRLFlBQVIsQ0FBakI7QUFDQSxNQUFNRSxtQkFBbUJGLFFBQVEsb0JBQVIsQ0FBekI7QUFDQSxNQUFNRyxPQUFPSCxRQUFRLFFBQVIsQ0FBYjs7QUFFQSxJQUFJSSxZQUFKOztBQUVBLE1BQU1DLElBQU4sQ0FDQTtBQUNJOzs7OztBQUtBQyxnQkFBWUMsT0FBWixFQUNBO0FBQ0lBLGtCQUFVQSxXQUFXLEVBQXJCO0FBQ0EsYUFBS0MsR0FBTCxHQUFXQyxTQUFTQyxhQUFULENBQXVCLEtBQXZCLENBQVg7QUFDQSxhQUFLQyxNQUFMLEdBQWNKLFFBQVFJLE1BQXRCO0FBQ0EsYUFBS0MsUUFBTCxHQUFnQixFQUFoQjtBQUNBLGFBQUtDLFdBQUwsQ0FBaUJkLE9BQU9lLFNBQXhCO0FBQ0EsYUFBS04sR0FBTCxDQUFTTyxRQUFULEdBQW9CLENBQUMsQ0FBckI7QUFDSDs7QUFFRDs7OztBQUlBQyxXQUFPQyxRQUFQLEVBQ0E7QUFDSSxZQUFJQSxT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O0FBQ0EvRSxhQUFLWCxHQUFMLENBQVN5RixnQkFBVCxDQUEwQixNQUExQixFQUFrQyxNQUNsQztBQUNJLGdCQUFJOUUsS0FBS1ksT0FBVCxFQUNBO0FBQ0laLHFCQUFLc0QsUUFBTDtBQUNIO0FBQ0osU0FORDtBQU9BdEQsYUFBS3FFLDJCQUFMO0FBQ0g7O0FBRUQ7Ozs7QUFJQSxlQUFXdEYsZ0JBQVgsR0FDQTtBQUNJLGVBQU9BLGdCQUFQO0FBQ0g7O0FBRUQ7Ozs7QUFJQSxlQUFXSCxNQUFYLEdBQ0E7QUFDSSxlQUFPQSxNQUFQO0FBQ0g7O0FBRUQ7Ozs7QUFJQSxlQUFXRSxRQUFYLEdBQ0E7QUFDSSxlQUFPQSxRQUFQO0FBQ0g7QUE1ZEw7O0FBK2RBa0csT0FBT0MsT0FBUCxHQUFpQi9GLElBQWpCIiwiZmlsZSI6Im1lbnUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBDb25maWcgPSAgIHJlcXVpcmUoJy4vY29uZmlnJylcclxuY29uc3QgTWVudUl0ZW0gPSByZXF1aXJlKCcuL21lbnVJdGVtJylcclxuY29uc3QgTG9jYWxBY2NlbGVyYXRvciA9IHJlcXVpcmUoJy4vbG9jYWxBY2NlbGVyYXRvcicpXHJcbmNvbnN0IGh0bWwgPSByZXF1aXJlKCcuL2h0bWwnKVxyXG5cclxubGV0IF9hcHBsaWNhdGlvblxyXG5cclxuY2xhc3MgTWVudVxyXG57XHJcbiAgICAvKipcclxuICAgICAqIGNyZWF0ZXMgYSBtZW51IGJhclxyXG4gICAgICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXVxyXG4gICAgICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zLnN0eWxlc10gYWRkaXRpb25hbCBDU1Mgc3R5bGVzIGZvciBtZW51XHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMpXHJcbiAgICB7XHJcbiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cclxuICAgICAgICB0aGlzLmRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpXHJcbiAgICAgICAgdGhpcy5zdHlsZXMgPSBvcHRpb25zLnN0eWxlc1xyXG4gICAgICAgIHRoaXMuY2hpbGRyZW4gPSBbXVxyXG4gICAgICAgIHRoaXMuYXBwbHlDb25maWcoQ29uZmlnLk1lbnVTdHlsZSlcclxuICAgICAgICB0aGlzLmRpdi50YWJJbmRleCA9IC0xXHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhcHBlbmQgYSBNZW51SXRlbSB0byB0aGUgTWVudVxyXG4gICAgICogQHBhcmFtIHtNZW51SXRlbX0gbWVudUl0ZW1cclxuICAgICAqL1xyXG4gICAgYXBwZW5kKG1lbnVJdGVtKVxyXG4gICAge1xyXG4gICAgICAgIGlmIChtZW51SXRlbS5zdWJtZW51KVxyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgbWVudUl0ZW0uc3VibWVudS5tZW51ID0gdGhpc1xyXG4gICAgICAgIH1cclxuICAgICAgICBtZW51SXRlbS5tZW51ID0gdGhpc1xyXG4gICAgICAgIHRoaXMuZGl2LmFwcGVuZENoaWxkKG1lbnVJdGVtLmRpdilcclxuICAgICAgICBpZiAobWVudUl0ZW0udHlwZSAhPT0gJ3NlcGFyYXRvcicpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICB0aGlzLmNoaWxkcmVuLnB1c2gobWVudUl0ZW0pXHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogaW5zZXJ0cyBhIE1lbnVJdGVtIGludG8gdGhlIE1lbnVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwb3NcclxuICAgICAqIEBwYXJhbSB7TWVudUl0ZW19IG1lbnVJdGVtXHJcbiAgICAgKi9cclxuICAgIGluc2VydChwb3MsIG1lbnVJdGVtKVxyXG4gICAge1xyXG4gICAgICAgIGlmIChwb3MgPj0gdGhpcy5kaXYuY2hpbGROb2Rlcy5sZW5ndGgpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICB0aGlzLmFwcGVuZChtZW51SXRlbSlcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgaWYgKG1lbnVJdGVtLnN1Ym1lbnUpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIG1lbnVJdGVtLnN1Ym1lbnUubWVudSA9IHRoaXNcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBtZW51SXRlbS5tZW51ID0gdGhpc1xyXG4gICAgICAgICAgICB0aGlzLmRpdi5pbnNlcnRCZWZvcmUobWVudUl0ZW0uZGl2LCB0aGlzLmRpdi5jaGlsZE5vZGVzW3Bvc10pXHJcbiAgICAgICAgICAgIGlmIChtZW51SXRlbS50eXBlICE9PSAnc2VwYXJhdG9yJylcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbi5zcGxpY2UocG9zLCAwLCBtZW51SXRlbSlcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBoaWRlKClcclxuICAgIHtcclxuICAgICAgICBsZXQgY3VycmVudCA9IHRoaXMubWVudS5zaG93aW5nXHJcbiAgICAgICAgd2hpbGUgKGN1cnJlbnQgJiYgY3VycmVudC5zdWJtZW51KVxyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgY3VycmVudC5kaXYuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gJ3RyYW5zcGFyZW50J1xyXG4gICAgICAgICAgICBjdXJyZW50LnN1Ym1lbnUuZGl2LnJlbW92ZSgpXHJcbiAgICAgICAgICAgIGxldCBuZXh0ID0gY3VycmVudC5zdWJtZW51LnNob3dpbmdcclxuICAgICAgICAgICAgaWYgKG5leHQpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIGN1cnJlbnQuc3VibWVudS5zaG93aW5nLmRpdi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAndHJhbnNwYXJlbnQnXHJcbiAgICAgICAgICAgICAgICBjdXJyZW50LnN1Ym1lbnUuc2hvd2luZyA9IG51bGxcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjdXJyZW50ID0gbmV4dFxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBzaG93KG1lbnVJdGVtKVxyXG4gICAge1xyXG4gICAgICAgIE1lbnUuTG9jYWxBY2NlbGVyYXRvci51bnJlZ2lzdGVyTWVudVNob3J0Y3V0cygpXHJcbiAgICAgICAgaWYgKHRoaXMubWVudSAmJiB0aGlzLm1lbnUuc2hvd2luZyA9PT0gbWVudUl0ZW0pXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICB0aGlzLmhpZGUoKVxyXG4gICAgICAgICAgICB0aGlzLm1lbnUuc2hvd2luZyA9IG51bGxcclxuICAgICAgICAgICAgdGhpcy5kaXYucmVtb3ZlKClcclxuICAgICAgICAgICAgdGhpcy5tZW51LnNob3dBY2NlbGVyYXRvcnMoKVxyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5tZW51KVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5tZW51LnNob3dpbmcgJiYgdGhpcy5tZW51LmNoaWxkcmVuLmluZGV4T2YobWVudUl0ZW0pICE9PSAtMSlcclxuICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhpcy5tZW51LnNob3dpbmcgPSBtZW51SXRlbVxyXG4gICAgICAgICAgICAgICAgdGhpcy5tZW51LmhpZGVBY2NlbGVyYXRvcnMoKVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNvbnN0IGRpdiA9IG1lbnVJdGVtLmRpdlxyXG4gICAgICAgICAgICBjb25zdCBwYXJlbnQgPSB0aGlzLm1lbnUuZGl2XHJcbiAgICAgICAgICAgIGlmICh0aGlzLm1lbnUuYXBwbGljYXRpb25NZW51KVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmRpdi5zdHlsZS5sZWZ0ID0gZGl2Lm9mZnNldExlZnQgKyAncHgnXHJcbiAgICAgICAgICAgICAgICB0aGlzLmRpdi5zdHlsZS50b3AgPSBkaXYub2Zmc2V0VG9wICsgZGl2Lm9mZnNldEhlaWdodCArICdweCdcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZGl2LnN0eWxlLmxlZnQgPSBwYXJlbnQub2Zmc2V0TGVmdCArIHBhcmVudC5vZmZzZXRXaWR0aCAtIENvbmZpZy5PdmVybGFwICsgJ3B4J1xyXG4gICAgICAgICAgICAgICAgdGhpcy5kaXYuc3R5bGUudG9wID0gcGFyZW50Lm9mZnNldFRvcCArIGRpdi5vZmZzZXRUb3AgLSBDb25maWcuT3ZlcmxhcCArICdweCdcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0aGlzLmF0dGFjaGVkID0gbWVudUl0ZW1cclxuICAgICAgICAgICAgdGhpcy5zaG93QWNjZWxlcmF0b3JzKClcclxuICAgICAgICAgICAgdGhpcy5nZXRBcHBsaWNhdGlvbkRpdigpLmFwcGVuZENoaWxkKHRoaXMuZGl2KVxyXG4gICAgICAgICAgICBsZXQgbGFiZWwgPSAwLCBhY2NlbGVyYXRvciA9IDAsIGFycm93ID0gMCwgY2hlY2tlZCA9IDBcclxuICAgICAgICAgICAgZm9yIChsZXQgY2hpbGQgb2YgdGhpcy5jaGlsZHJlbilcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgY2hpbGQuY2hlY2suc3R5bGUud2lkdGggPSAnYXV0bydcclxuICAgICAgICAgICAgICAgIGNoaWxkLmxhYmVsLnN0eWxlLndpZHRoID0gJ2F1dG8nXHJcbiAgICAgICAgICAgICAgICBjaGlsZC5hY2NlbGVyYXRvci5zdHlsZS53aWR0aCA9ICdhdXRvJ1xyXG4gICAgICAgICAgICAgICAgY2hpbGQuYXJyb3cuc3R5bGUud2lkdGggPSAnYXV0bydcclxuICAgICAgICAgICAgICAgIGlmIChjaGlsZC50eXBlID09PSAnY2hlY2tib3gnKVxyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICAgIGNoZWNrZWQgPSBDb25maWcuTWluaW11bUNvbHVtbldpZHRoXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQuc3VibWVudSlcclxuICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICBhcnJvdyA9IENvbmZpZy5NaW5pbXVtQ29sdW1uV2lkdGhcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBmb3IgKGxldCBjaGlsZCBvZiB0aGlzLmNoaWxkcmVuKVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBjaGlsZExhYmVsID0gY2hpbGQubGFiZWwub2Zmc2V0V2lkdGggKiAyXHJcbiAgICAgICAgICAgICAgICBsYWJlbCA9IGNoaWxkTGFiZWwgPiBsYWJlbCA/IGNoaWxkTGFiZWwgOiBsYWJlbFxyXG4gICAgICAgICAgICAgICAgY29uc3QgY2hpbGRBY2NlbGVyYXRvciA9IGNoaWxkLmFjY2VsZXJhdG9yLm9mZnNldFdpZHRoXHJcbiAgICAgICAgICAgICAgICBhY2NlbGVyYXRvciA9IGNoaWxkQWNjZWxlcmF0b3IgPiBhY2NlbGVyYXRvciA/IGNoaWxkQWNjZWxlcmF0b3IgOiBhY2NlbGVyYXRvclxyXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkLnN1Ym1lbnUpXHJcbiAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgYXJyb3cgPSBjaGlsZC5hcnJvdy5vZmZzZXRXaWR0aFxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGZvciAobGV0IGNoaWxkIG9mIHRoaXMuY2hpbGRyZW4pXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIGNoaWxkLmNoZWNrLnN0eWxlLndpZHRoID0gY2hlY2tlZCArICdweCdcclxuICAgICAgICAgICAgICAgIGNoaWxkLmxhYmVsLnN0eWxlLndpZHRoID0gbGFiZWwgKyAncHgnXHJcbiAgICAgICAgICAgICAgICBjaGlsZC5hY2NlbGVyYXRvci5zdHlsZS53aWR0aCA9IGFjY2VsZXJhdG9yICsgJ3B4J1xyXG4gICAgICAgICAgICAgICAgY2hpbGQuYXJyb3cuc3R5bGUud2lkdGggPSBhcnJvdyArICdweCdcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAodGhpcy5kaXYub2Zmc2V0TGVmdCArIHRoaXMuZGl2Lm9mZnNldFdpZHRoID4gd2luZG93LmlubmVyV2lkdGgpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZGl2LnN0eWxlLmxlZnQgPSB3aW5kb3cuaW5uZXJXaWR0aCAtIHRoaXMuZGl2Lm9mZnNldFdpZHRoICsgJ3B4J1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmRpdi5vZmZzZXRUb3AgKyB0aGlzLmRpdi5vZmZzZXRIZWlnaHQgPiB3aW5kb3cuaW5uZXJIZWlnaHQpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZGl2LnN0eWxlLnRvcCA9IHdpbmRvdy5pbm5lckhlaWdodCAtIHRoaXMuZGl2Lm9mZnNldEhlaWdodCArICdweCdcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBfYXBwbGljYXRpb24ubWVudS5kaXYuZm9jdXMoKVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBhcHBseUNvbmZpZyhiYXNlKVxyXG4gICAge1xyXG4gICAgICAgIGNvbnN0IHN0eWxlcyA9IHt9XHJcbiAgICAgICAgZm9yIChsZXQgc3R5bGUgaW4gYmFzZSlcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIHN0eWxlc1tzdHlsZV0gPSBiYXNlW3N0eWxlXVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodGhpcy5zdHlsZXMpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBmb3IgKGxldCBzdHlsZSBpbiB0aGlzLnN0eWxlcylcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgc3R5bGVzW3N0eWxlXSA9IHRoaXMuc3R5bGVzW3N0eWxlXVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZvciAobGV0IHN0eWxlIGluIHN0eWxlcylcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIHRoaXMuZGl2LnN0eWxlW3N0eWxlXSA9IHN0eWxlc1tzdHlsZV1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgc2hvd0FjY2VsZXJhdG9ycygpXHJcbiAgICB7XHJcbiAgICAgICAgZm9yIChsZXQgY2hpbGQgb2YgdGhpcy5jaGlsZHJlbilcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIGNoaWxkLnNob3dTaG9ydGN1dCgpXHJcbiAgICAgICAgICAgIGlmIChjaGlsZC50eXBlICE9PSAnc2VwYXJhdG9yJylcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSBjaGlsZC50ZXh0LmluZGV4T2YoJyYnKVxyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSlcclxuICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICBNZW51LkxvY2FsQWNjZWxlcmF0b3IucmVnaXN0ZXJNZW51U2hvcnRjdXQoY2hpbGQudGV4dFtpbmRleCArIDFdLCBjaGlsZClcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIXRoaXMuYXBwbGljYXRpb25NZW51KVxyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgTWVudS5Mb2NhbEFjY2VsZXJhdG9yLnJlZ2lzdGVyTWVudVNwZWNpYWwodGhpcylcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaGlkZUFjY2VsZXJhdG9ycygpXHJcbiAgICB7XHJcbiAgICAgICAgZm9yIChsZXQgY2hpbGQgb2YgdGhpcy5jaGlsZHJlbilcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIGNoaWxkLmhpZGVTaG9ydGN1dCgpXHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNsb3NlQWxsKClcclxuICAgIHtcclxuICAgICAgICBNZW51LkxvY2FsQWNjZWxlcmF0b3IudW5yZWdpc3Rlck1lbnVTaG9ydGN1dHMoKVxyXG4gICAgICAgIGxldCBhcHBsaWNhdGlvbiA9IF9hcHBsaWNhdGlvbi5tZW51XHJcbiAgICAgICAgaWYgKGFwcGxpY2F0aW9uLnNob3dpbmcpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBsZXQgbWVudSA9IGFwcGxpY2F0aW9uXHJcbiAgICAgICAgICAgIHdoaWxlIChtZW51LnNob3dpbmcpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIG1lbnUgPSBtZW51LnNob3dpbmcuc3VibWVudVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHdoaWxlIChtZW51ICYmICFtZW51LmFwcGxpY2F0aW9uTWVudSlcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgaWYgKG1lbnUuc2hvd2luZylcclxuICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICBtZW51LnNob3dpbmcuZGl2LnN0eWxlLmJhY2tncm91bmRDb2xvciA9ICd0cmFuc3BhcmVudCdcclxuICAgICAgICAgICAgICAgICAgICBtZW51LnNob3dpbmcgPSBudWxsXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBtZW51LmRpdi5yZW1vdmUoKVxyXG4gICAgICAgICAgICAgICAgbWVudSA9IG1lbnUubWVudVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChtZW51KVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBtZW51LnNob3dpbmcuZGl2LnN0eWxlLmJhY2tncm91bmQgPSAndHJhbnNwYXJlbnQnXHJcbiAgICAgICAgICAgICAgICBtZW51LnNob3dpbmcgPSBudWxsXHJcbiAgICAgICAgICAgICAgICBtZW51LmhpZGVBY2NlbGVyYXRvcnMoKVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGdldEFwcGxpY2F0aW9uRGl2KClcclxuICAgIHtcclxuICAgICAgICByZXR1cm4gX2FwcGxpY2F0aW9uXHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBtb3ZlIHNlbGVjdG9yIHRvIHRoZSBuZXh0IGNoaWxkIHBhbmVcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBkaXJlY3Rpb24gKGxlZnQgb3IgcmlnaHQpXHJcbiAgICAgKiBAcHJpdmF0ZVxyXG4gICAgICovXHJcbiAgICBtb3ZlQ2hpbGQoZGlyZWN0aW9uKVxyXG4gICAge1xyXG4gICAgICAgIGxldCBpbmRleFxyXG4gICAgICAgIGlmIChkaXJlY3Rpb24gPT09ICdsZWZ0JylcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBhcmVudCA9IHRoaXMuc2VsZWN0b3IubWVudS5tZW51XHJcbiAgICAgICAgICAgIGluZGV4ID0gcGFyZW50LmNoaWxkcmVuLmluZGV4T2YocGFyZW50LnNob3dpbmcpXHJcbiAgICAgICAgICAgIGluZGV4LS1cclxuICAgICAgICAgICAgaW5kZXggPSAoaW5kZXggPCAwKSA/IHBhcmVudC5jaGlsZHJlbi5sZW5ndGggLSAxIDogaW5kZXhcclxuICAgICAgICAgICAgcGFyZW50LmNoaWxkcmVuW2luZGV4XS5oYW5kbGVDbGljaygpXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIGxldCBwYXJlbnQgPSB0aGlzLnNlbGVjdG9yLm1lbnUubWVudVxyXG4gICAgICAgICAgICBsZXQgc2VsZWN0b3IgPSBwYXJlbnQuc2hvd2luZ1xyXG4gICAgICAgICAgICB3aGlsZSAoIXBhcmVudC5hcHBsaWNhdGlvbk1lbnUpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHNlbGVjdG9yLmhhbmRsZUNsaWNrKClcclxuICAgICAgICAgICAgICAgIHNlbGVjdG9yLmRpdi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAndHJhbnNwYXJlbnQnXHJcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQubWVudVxyXG4gICAgICAgICAgICAgICAgc2VsZWN0b3IgPSBwYXJlbnQuc2hvd2luZ1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGluZGV4ID0gcGFyZW50LmNoaWxkcmVuLmluZGV4T2Yoc2VsZWN0b3IpXHJcbiAgICAgICAgICAgIGluZGV4KytcclxuICAgICAgICAgICAgaW5kZXggPSAoaW5kZXggPT09IHBhcmVudC5jaGlsZHJlbi5sZW5ndGgpID8gMCA6IGluZGV4XHJcbiAgICAgICAgICAgIHBhcmVudC5jaGlsZHJlbltpbmRleF0uaGFuZGxlQ2xpY2soKVxyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnNlbGVjdG9yID0gbnVsbFxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogbW92ZSBzZWxlY3RvciByaWdodCBhbmQgbGVmdFxyXG4gICAgICogQHBhcmFtIHtNb3VzZUV2ZW50fSBlXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZGlyZWN0aW9uXHJcbiAgICAgKiBAcHJpdmF0ZVxyXG4gICAgICovXHJcbiAgICBob3Jpem9udGFsU2VsZWN0b3IoZSwgZGlyZWN0aW9uKVxyXG4gICAge1xyXG4gICAgICAgIGlmIChkaXJlY3Rpb24gPT09ICdyaWdodCcpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5zZWxlY3Rvci5zdWJtZW51KVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdG9yLmhhbmRsZUNsaWNrKGUpXHJcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdG9yLnN1Ym1lbnUuc2VsZWN0b3IgPSB0aGlzLnNlbGVjdG9yLnN1Ym1lbnUuY2hpbGRyZW5bMF1cclxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0b3Iuc3VibWVudS5zZWxlY3Rvci5kaXYuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gQ29uZmlnLlNlbGVjdGVkQmFja2dyb3VuZFN0eWxlXHJcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdG9yID0gbnVsbFxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5tb3ZlQ2hpbGQoZGlyZWN0aW9uKVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ2xlZnQnKVxyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLnNlbGVjdG9yLm1lbnUubWVudS5hcHBsaWNhdGlvbk1lbnUpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0b3IubWVudS5hdHRhY2hlZC5oYW5kbGVDbGljayhlKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3Rvci5tZW51Lm1lbnUuc2VsZWN0b3IgPSB0aGlzLnNlbGVjdG9yLm1lbnUuYXR0YWNoZWRcclxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0b3IgPSBudWxsXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm1vdmVDaGlsZChkaXJlY3Rpb24pXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKVxyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogbW92ZSB0aGUgc2VsZWN0b3IgaW4gdGhlIG1lbnVcclxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZVxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGRpcmVjdGlvbiAobGVmdCwgcmlnaHQsIHVwLCBkb3duKVxyXG4gICAgICogQHByaXZhdGVcclxuICAgICAqL1xyXG4gICAgbW92ZShlLCBkaXJlY3Rpb24pXHJcbiAgICB7XHJcbiAgICAgICAgaWYgKHRoaXMuc2VsZWN0b3IpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICB0aGlzLnNlbGVjdG9yLmRpdi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAndHJhbnNwYXJlbnQnXHJcbiAgICAgICAgICAgIGxldCBpbmRleCA9IHRoaXMuY2hpbGRyZW4uaW5kZXhPZih0aGlzLnNlbGVjdG9yKVxyXG4gICAgICAgICAgICBpZiAoZGlyZWN0aW9uID09PSAnZG93bicpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIGluZGV4KytcclxuICAgICAgICAgICAgICAgIGluZGV4ID0gKGluZGV4ID09PSB0aGlzLmNoaWxkcmVuLmxlbmd0aCkgPyAwIDogaW5kZXhcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmIChkaXJlY3Rpb24gPT09ICd1cCcpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIGluZGV4LS1cclxuICAgICAgICAgICAgICAgIGluZGV4ID0gKGluZGV4IDwgMCkgPyB0aGlzLmNoaWxkcmVuLmxlbmd0aCAtIDEgOiBpbmRleFxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaG9yaXpvbnRhbFNlbGVjdG9yKGUsIGRpcmVjdGlvbilcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0aGlzLnNlbGVjdG9yID0gdGhpcy5jaGlsZHJlbltpbmRleF1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ3VwJylcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RvciA9IHRoaXMuY2hpbGRyZW5bdGhpcy5jaGlsZHJlbi5sZW5ndGggLSAxXVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RvciA9IHRoaXMuY2hpbGRyZW5bMF1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnNlbGVjdG9yLmRpdi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBDb25maWcuU2VsZWN0ZWRCYWNrZ3JvdW5kU3R5bGVcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpXHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBjbGljayB0aGUgc2VsZWN0b3Igd2l0aCBrZXlib2FyZFxyXG4gICAgICogQHByaXZhdGVcclxuICAgICAqL1xyXG4gICAgZW50ZXIoZSlcclxuICAgIHtcclxuICAgICAgICBpZiAodGhpcy5zZWxlY3RvcilcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0b3IuaGFuZGxlQ2xpY2soZSlcclxuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpXHJcbiAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKClcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhcnJheSBjb250YWluaW5nIHRoZSBtZW51J3MgaXRlbXNcclxuICAgICAqIEBwcm9wZXJ0eSB7TWVudUl0ZW1zW119IGl0ZW1zXHJcbiAgICAgKiBAcmVhZG9ubHlcclxuICAgICAqL1xyXG4gICAgZ2V0IGl0ZW1zKClcclxuICAgIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5jaGlsZHJlblxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogc2hvdyBhcHBsaWNhdGlvbiBtZW51IGFjY2VsZXJhdG9ycyB3aGVuIGFsdCBpcyBwcmVzc2VkXHJcbiAgICAgKiBAcHJpdmF0ZVxyXG4gICAgICovXHJcbiAgICBzaG93QXBwbGljYXRpb25BY2NlbGVyYXRvcnMoKVxyXG4gICAge1xyXG4gICAgICAgIHRoaXMuaGlkZUFjY2VsZXJhdG9ycygpXHJcbiAgICAgICAgTG9jYWxBY2NlbGVyYXRvci5yZWdpc3RlckFsdCgoKSA9PlxyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLnNob3dpbmcpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2hvd0FjY2VsZXJhdG9ycygpXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LCAoKSA9PlxyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgdGhpcy5oaWRlQWNjZWxlcmF0b3JzKClcclxuICAgICAgICB9KVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogc2V0cyBhY3RpdmUgYXBwbGljYXRpb24gTWVudSAoYW5kIHJlbW92ZXMgYW55IGV4aXN0aW5nIGFwcGxpY2F0aW9uIG1lbnVzKVxyXG4gICAgICogQHBhcmFtIHtNZW51fSBtZW51XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBzZXRBcHBsaWNhdGlvbk1lbnUobWVudSlcclxuICAgIHtcclxuICAgICAgICBMb2NhbEFjY2VsZXJhdG9yLmluaXQoKVxyXG4gICAgICAgIGlmIChfYXBwbGljYXRpb24pXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBfYXBwbGljYXRpb24ucmVtb3ZlKClcclxuICAgICAgICB9XHJcbiAgICAgICAgX2FwcGxpY2F0aW9uID0gaHRtbCh7IHBhcmVudDogZG9jdW1lbnQuYm9keSwgc3R5bGVzOiBDb25maWcuQXBwbGljYXRpb25Db250YWluZXJTdHlsZSB9KVxyXG4gICAgICAgIF9hcHBsaWNhdGlvbi5tZW51ID0gbWVudVxyXG4gICAgICAgIG1lbnUuYXBwbHlDb25maWcoQ29uZmlnLkFwcGxpY2F0aW9uTWVudVN0eWxlKVxyXG4gICAgICAgIGZvciAobGV0IGNoaWxkIG9mIG1lbnUuY2hpbGRyZW4pXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBjaGlsZC5hcHBseUNvbmZpZyhDb25maWcuQXBwbGljYXRpb25NZW51Um93U3R5bGUpXHJcbiAgICAgICAgICAgIGlmIChjaGlsZC5hcnJvdylcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgY2hpbGQuYXJyb3cuc3R5bGUuZGlzcGxheSA9ICdub25lJ1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG1lbnUuZGl2LmFwcGVuZENoaWxkKGNoaWxkLmRpdilcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIF9hcHBsaWNhdGlvbi5hcHBlbmRDaGlsZChtZW51LmRpdilcclxuICAgICAgICBtZW51LmFwcGxpY2F0aW9uTWVudSA9IHRydWVcclxuICAgICAgICBtZW51LmRpdi50YWJJbmRleCA9IC0xXHJcblxyXG4gICAgICAgIC8vIGRvbid0IGxldCBtZW51IGJhciBmb2N1cyB1bmxlc3Mgd2luZG93cyBhcmUgb3BlbiAodGhpcyBmaXhlcyBhIGZvY3VzIGJ1ZylcclxuICAgICAgICBtZW51LmRpdi5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsICgpID0+XHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBpZiAoIW1lbnUuc2hvd2luZylcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgbWVudS5kaXYuYmx1cigpXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KVxyXG5cclxuICAgICAgICAvLyBjbG9zZSBhbGwgd2luZG93cyBpZiBtZW51IGlzIG5vIGxvbmdlciB0aGUgZm9jdXNcclxuICAgICAgICBtZW51LmRpdi5hZGRFdmVudExpc3RlbmVyKCdibHVyJywgKCkgPT5cclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIGlmIChtZW51LnNob3dpbmcpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIG1lbnUuY2xvc2VBbGwoKVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSlcclxuICAgICAgICBtZW51LnNob3dBcHBsaWNhdGlvbkFjY2VsZXJhdG9ycygpXHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBsb2NhbEFjY2VsZXJhdG9yIGRlZmluaXRpb25cclxuICAgICAqIEB0eXBlIHtBY2NlbGVyYXRvcn1cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGdldCBMb2NhbEFjY2VsZXJhdG9yKClcclxuICAgIHtcclxuICAgICAgICByZXR1cm4gTG9jYWxBY2NlbGVyYXRvclxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogdXNlIHRoaXMgdG8gY2hhbmdlIHRoZSBkZWZhdWx0IENvbmZpZyBzZXR0aW5ncyBhY3Jvc3MgYWxsIG1lbnVzXHJcbiAgICAgKiBAdHlwZSB7Q29uZmlnfVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgZ2V0IENvbmZpZygpXHJcbiAgICB7XHJcbiAgICAgICAgcmV0dXJuIENvbmZpZ1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWVudUl0ZW0gZGVmaW5pdGlvblxyXG4gICAgICogQHR5cGUge01lbnVJdGVtfVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgZ2V0IE1lbnVJdGVtKClcclxuICAgIHtcclxuICAgICAgICByZXR1cm4gTWVudUl0ZW1cclxuICAgIH1cclxufVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBNZW51Il19