index.js

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Global Application Object
         * @export
         * @class App
         */
        class App {
            /**
             * Loads a window, or frame into an existing window
             * @param {string} opts.containerName The object name to launch
             * @param {string} opts.pages The initial pages to load, for example, <code>0,1</code>
             * @param {object} opts.target The target object to load the frame into
             * @example
             * // dynamically load a frame into an existing window
             * akioma.swat.loadScreen({
             *
             *     // frame name to load
             *     containerName: "<frame name>",
             *
             *     // into a tabbar's tab frame
             *     target: eventSource.window.getObject("MyTab")
             * });
             * @param {string} opts.view The view name to use for the new repository object (requires target).
             * @param {object} opts.caller The caller object where the container is launched from
             * @param {boolean} opts.dynGuid The dynamic guid.
             * Useful when loading a tab where you could load the same repository object multiple times and the links need to be unique.
             * @param {boolean} opts.autoAdd Automatically add a new record on the resulting screen PrimarySDO datasource.
             * @param {boolean} opts.fetchOnInit If the new repository screen should load its data or not (calls the datasource openQuery).
             * @param {string} opts.repositionTo Positions the PrimarySDO datasource to the SelfHdl given value. Can also be a function call.
             * @param {string} opts.allowMultipleInstances Specifies if allowing multiple screen instances is allowed
             * @param {string|object} opts.customData Information for repositioning the PrimarySDO datasource. Can also be a function call.
             * @param {string} opts.foreignKeyProvider Function call for setting the new record initial values.
             * @param {any} opts.params
             * @param {string} opts.params.typeKey
             * @param {string} opts.params.selfHdl
             * @param {string} opts.params.dataSource
             * @param {string} opts.params.targetId
             * @returns {Promise<LayoutObject>} Returns a promise with the container object
             */
            static loadScreen(opts) {
                opts = opts || {};
                if (typeof opts === 'string')
                    opts = { containerName: opts };
                opts = App.convertLaunchContainerParams(opts);
                // run launchContainer and return promise. jquery promise converted to es6 promise.
                return new Promise((resolve, reject) => {
                    window.app.controller.launchContainer(opts).then((controller) => {
                        resolve(akioma.swat.SwatFactory.createSwatObject(controller));
                    }, (error) => {
                        reject(error);
                    });
                });
            }
            /**
             * Invokes a backend Business Task or Business Entity method
             * @param {string} opts.name The Business Task or Business Entity fully qualified class name
             * @param {string} opts.methodName The method name to invoke
             * @param {object} opts.paramObj The method parameters
             * @param {object} opts.paramObj.plcParameter The method parameter object
             * @param {object} opts.paramObj.* Other optional parameters like datasets
             * @param {boolean} opts.showWaitCursor Displays wait cursor starting from uiContext dynObject
             * @param {dynObject} opts.uiContext The dynObject source of the wait cursor
             * @param {boolean} opts.throwDataError Optional flag to reject promise when dataset contain errors
             * @returns {Promise<Window>} Returns a promise with the output parameter
             */
            static invokeServerTask(opts) {
                return new Promise((resolve, reject) => {
                    window.akioma.invokeServerTask(opts).done(resolve).fail(reject);
                });
            }
            /**
             * Query business entity
             * @param {string} opts.name The Business Entity fully qualified class name
             * @param {object} opts.filter The KendoUI filter
             * @example
             * // query business entity
             * akioma.swat.App.queryBusinessEntity({
             *     name:   'Akioma.Crm.MasterData.System.ParameterEntity',
             *     filter: [{field: 'groupHdl', operator: 'eq', value: 'UserImg'}]
             * }).done((data) => {
             *    console.log(data);
             * }).fail((err) => {
             *    console.log(err.message);
             * });
             * @returns {Promise<any>} Returns a promise with the query data
             */
            static queryBusinessEntity(opts) {
                return new Promise((resolve, reject) => {
                    window.akioma.queryBusinessEntity(opts).done(resolve).fail(reject);
                });
            }
            static getObjectByName(args) {
                return window.akioma.getObjectByName(args);
            }
            /**
             * Converts CLAPI launchContainer options to core launchContainer options
             * @param opts Launch container options
             * @returns LaunchContainer options
             */
            static convertLaunchContainerParams(opts) {
                var _a, _b, _c;
                // convert opts.caller from SwatObject to dynObject
                if ((_a = opts.caller) === null || _a === void 0 ? void 0 : _a._dynObject)
                    opts.caller = opts.caller._dynObject;
                // convert opts.target from SwatObject to controller
                if ((_b = opts.target) === null || _b === void 0 ? void 0 : _b._controller)
                    opts.target = opts.target._controller;
                // convert opts.target from dynObject to controller
                if ((_c = opts.target) === null || _c === void 0 ? void 0 : _c.controller)
                    opts.target = opts.target.controller;
                // if opts.target is set, set dynGuid and containeringuid, if not already set
                if (opts.target) {
                    if (!opts.dynGuid)
                        opts.dynGuid = window.dhtmlx.uid();
                    if (!opts.containerinsguid)
                        opts.containerinsguid = opts.target.opt._ContainerInstanceGuid;
                }
                if (opts.params) {
                    // rename params properties to match launchContainer params
                    // ensures backwards compatibility, do not remove
                    if (opts.params.typeKey) {
                        opts.params.TypeKey = opts.params.typeKey;
                        delete opts.params.typeKey;
                    }
                    if (opts.params.selfHdl) {
                        opts.params.SelfHdl = opts.params.selfHdl;
                        delete opts.params.selfHdl;
                    }
                    if (opts.params.dataSource) {
                        opts.params.Datasource = opts.params.dataSource;
                        delete opts.params.dataSource;
                    }
                    if (opts.params.targetId) {
                        opts.params.TargetId = opts.params.targetId;
                        delete opts.params.targetId;
                    }
                }
                return opts;
            }
            /**
             * Shows the object names in titles for debugging
             * @type {boolean}
             */
            static get objectNamesInTitles() {
                return window.app.sessionData.objectNamesInTitles;
            }
            static set objectNamesInTitles(value) {
                window.app.sessionData.objectNamesInTitles = value;
            }
            static displayValidationError() {
                window.displayValidationError();
            }
        }
        swat.App = App;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        var _a;
        swat.GlobalHooks = {
            OBJECT: { BEFORE_DESTROY: ['Object', 'BeforeDestroy'] },
            LAUNCH: {
                BEFORE_RENDER: ['LaunchContainer', 'BeforeRender'],
                AFTER_LOAD: ['LaunchContainer', 'AfterLoad']
            },
            DATASOURCE: { AFTER_SAVE_CHANGES: ['DataSource', 'AfterSaveChanges'] },
            DESKTOP: { AFTER_TOGGLE: ['Desktop', 'AfterToggle'] },
            WINDOW: {
                CUSTOM_STATE_CHANGED: ['Window', 'CustomStateChanged'],
                HAS_ERRORS: ['Window', 'HasErrors'],
                HAS_CHANGES: ['Window', 'HasChanges'],
                CLOSE: ['Window', 'Close'],
                FOCUS: ['Window', 'Focus']
            },
            DESIGNER: { AFTER_LOAD: ['Designer', 'AfterLoad'] }
        };
        swat.GlobalEmitter = (_a = class {
                static on(eventName, callback) {
                    window.akioma.eventEmitter.on(eventName, callback);
                    return this.events.push({ eventName, callback });
                }
                static once(eventName, callback) {
                    window.akioma.eventEmitter.once(eventName, callback);
                    return this.events.push({ eventName, callback });
                }
                static off(eventName, callback) {
                    const eventEntryIndex = this.events.findIndex(event => event.eventName === eventName && event.callback === callback);
                    if (eventEntryIndex > -1) {
                        this.events.splice(eventEntryIndex, 1);
                        window.akioma.eventEmitter.off(eventName, callback);
                    }
                }
                static offById(eventIndex) {
                    const eventEntry = this.events[eventIndex];
                    if (eventEntry) {
                        this.events.splice(eventIndex, 1);
                        const { eventName, callback } = eventEntry;
                        window.akioma.eventEmitter.off(eventName, callback);
                    }
                }
                static emit(eventName, params) {
                    try {
                        window.akioma.eventEmitter.emit(eventName, params);
                    }
                    catch (e) {
                        window.akioma.log.error(e);
                    }
                }
            },
            _a.events = [],
            _a);
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        const SmartMessageCache = {};
        /**
         * Message Object
         * @export
         * @class Message
         */
        class Message {
            /**
             * Update a vue notification with the given id
             * @static
             * @param {number} opts.id The id of the notification to update
             * @param {string} opts.text The message body
             * @param {number} opts.message The messaga body used for 'link' message type
             * @param {string} opts.type The message type i.e.
             * information, warning, error, success,
             * alert, alert-information, alert-warning, alert-error, alert-question,
             * @param {number} opts.expire The time period to close the message box
             * @param {number} opts.moretext Additional text to be opened in separate window
             * @param {string} opts.title The message title
             * @param {string} opts.linkDesc The link description to be displayed in notification
             * @param {string} opts.linkValue The link value to be called when clicking on the notification
             * @param {string} opts.bottom Additional bottom text used for 'link' message type
             * @param {string} opts.options Additional options used for the link
             * @returns {void}
             */
            static updateVueNotification(opts) {
                window.akioma.NotificationMessage.updateVueNotification(opts);
            }
            /**
             * Removes a vue notification with the given id
             * @static
             * @param {number} id The id of the notification to update
             * @returns {void}
             */
            static removeVueNotification(id) {
                window.akioma.NotificationMessage.removeVueNotification(id);
            }
            /**
             * Displays a message
             * @static
             * @param {string} opts.title The message box title
             * @param {string} opts.text The message box body
             * @param {string} opts.type The message box type i.e.
             * information, warning, error, question, success,
             * alert, alert-information, alert-warning, alert-error, alert-question,
             * confirm, confirm-information, confirm-warning, confirm-error, confirm-question
             * @param {number} opts.expire The time period to close the message box
             * @param {MessageButton} opts.ok The ok button text
             * @param {MessageButton} opts.cancel the cancel button text
             * @param {string} opts.width The css width string
             * @param {string} opts.height The css height string
             * @param {boolean} opts.closeOnEsc  The message box will close when ESC is pressed on keyboard. default is "true"
             * @param {boolean} opts.vue For notification message, specifies if it should use dhxmlx or vue notification (defaults to dhtmlx if not specified)
             * @param {boolean} opts.closeOnClickOutside The message box will close if clicked on overlay or outside of the modal box content. default is "false"
             * @param {boolean} opts.showMessageCode Remove the information message text info group and number, text displayed between parentheses, default is "false"
             * @param {string} opts.modal if it should be a modal or non-modal window
             * @param {string} opts.moretext The text to add inside the resulting window modal as information, will add more button
             * @param {boolean|string[]|MessageButton[]|ButtonList} opts.buttons The modal message buttons to display
             * @param {function} opts.callback The callback function after clicking the ok/cancel buttons with the result
             * @returns {string}
             */
            static message(opts) {
                opts = opts || {};
                if (typeof opts === 'string')
                    opts = { text: opts };
                if (opts.type === undefined)
                    opts.type = 'error';
                if (opts.expire === undefined && opts.lifetime !== undefined)
                    opts.expire = opts.lifetime;
                if (opts.expire === undefined)
                    opts.expire = this.expireDefault || 10000;
                if (opts.expire === 0)
                    opts.expire = -1;
                if (opts.showMessageCode === false)
                    opts.text = opts.text.replace(/ *\([^)]*\) */g, '');
                // if starts with alert automatically set as modal
                if (opts.type.startsWith('alert')) {
                    opts.type = opts.type.replace('alert-', '');
                    opts.modal = true;
                }
                if (opts.type.startsWith('confirm')) {
                    opts.type = opts.type.replace('confirm-', '');
                    opts.modal = true;
                }
                if (opts.type === 'question' || opts.type === 'input')
                    opts.modal = true;
                if (opts.modal)
                    return window.akioma.message(opts);
                else
                    return window.akioma.notification(opts);
            }
            /**
             * Alert message. Same as message({type: 'alert'}).
             * @static
             * @param {string} opts.title The message box title
             * @param {string} opts.text The message box body
             * @param {string} opts.type The message box type i.e.
             * information, warning, error, question, success,
             * alert, alert-information, alert-warning, alert-error, alert-question,
             * confirm, confirm-information, confirm-warning, confirm-error, confirm-question
             * alternatively a custom css class
             * @param {number} opts.expire The time period to close the message box
             * @param {string} opts.ok The ok button text
             * @param {string} opts.cancel the cancel button text
             * @param {string} opts.width The css width string
             * @param {string} opts.height The css height string
             * @param {boolean} opts.closeOnEsc  The message box will close when ESC is pressed on keyboard. default is "true"
             * @param {boolean} opts.closeOnClickOutside The message box will close if clicked on overlay or outside of the modal box content. default is "false"
             * @param {string} opts.moretext The text to add inside the resulting window modal as information, will add more button
             * @param {boolean|string[]|MessageButton[]|ButtonList} opts.buttons The modal message buttons to display
             * @param {function} opts.callback The callback function after clicking the ok/cancel buttons with the result
             */
            static alert(opts) {
                opts = opts || {};
                if (typeof opts === 'string')
                    opts = { text: opts };
                if (!opts.type)
                    opts.type = 'alert';
                return this.message(opts);
            }
            /**
             * Confirm message. Same as message({type: 'confirm'}).
             * @static
             * @param {string} opts.title The message box title
             * @param {string} opts.text The message box body
             * @param {string} opts.type The message box type i.e.
             * information, warning, error, question, success,
             * alert, alert-information, alert-warning, alert-error, alert-question,
             * confirm, confirm-information, confirm-warning, confirm-error, confirm-question
             * alternatively a custom css class
             * @param {number} opts.expire The time period to close the message box
             * @param {string} opts.ok The ok button text
             * @param {string} opts.cancel the cancel button text
             * @param {string} opts.width The css width string
             * @param {string} opts.height The css height string
             * @param {boolean} opts.closeOnEsc  The message box will close when ESC is pressed on keyboard. default is "true"
             * @param {boolean} opts.closeOnClickOutside The message box will close if clicked on overlay or outside of the modal box content. default is "false"
             * @param {string} opts.moretext The text to add inside the resulting window modal as information, will add more button
             * @param {boolean|string[]|MessageButton[]|ButtonList} opts.buttons The modal message buttons to display
             * @param {function} opts.callback The callback function after clicking the ok/cancel buttons with the result
             * @returns {string}
             */
            static confirm(opts) {
                opts = opts || {};
                if (typeof opts === 'string')
                    opts = { text: opts };
                if (!opts.type)
                    opts.type = 'confirm';
                return this.message(opts);
            }
            /**
             * Information message. Same as message({type: 'information'}).
             * @static
             * @param {string} opts.title The message box title
             * @param {string} opts.text The message box body
             * @param {string} opts.type The message box type i.e.
             * information, warning, error, question, success,
             * alert, alert-information, alert-warning, alert-error, alert-question,
             * confirm, confirm-information, confirm-warning, confirm-error, confirm-question
             * alternatively a custom css class
             * @param {number} opts.expire The time period to close the message box
             * @param {string} opts.ok The ok button text
             * @param {string} opts.cancel the cancel button text
             * @param {string} opts.width The css width string
             * @param {string} opts.height The css height string
             * @param {boolean} opts.closeOnEsc  The message box will close when ESC is pressed on keyboard. default is "true"
             * @param {boolean} opts.closeOnClickOutside The message box will close if clicked on overlay or outside of the modal box content. default is "false"
             * @param {string} opts.moretext The text to add inside the resulting window modal as information, will add more button
             * @param {boolean|string[]|MessageButton[]|ButtonList} opts.buttons The modal message buttons to display
             * @param {function} opts.callback The callback function after clicking the ok/cancel buttons with the result
             * @returns {string}
             */
            static informationMessage(opts) {
                opts = opts || {};
                if (typeof opts === 'string')
                    opts = { text: opts };
                if (!opts.type)
                    opts.type = 'information';
                return this.message(opts);
            }
            /**
             * Warning message. Same as message({type: 'warning'}).
             * @static
             * @param {string} opts.title The message box title
             * @param {string} opts.text The message box body
             * @param {string} opts.type The message box type i.e.
             * information, warning, error, question, success,
             * alert, alert-information, alert-warning, alert-error, alert-question,
             * confirm, confirm-information, confirm-warning, confirm-error, confirm-question
             * alternatively a custom css class
             * @param {number} opts.expire The time period to close the message box
             * @param {string} opts.ok The ok button text
             * @param {string} opts.cancel the cancel button text
             * @param {string} opts.width The css width string
             * @param {string} opts.height The css height string
             * @param {boolean} opts.closeOnEsc  The message box will close when ESC is pressed on keyboard. default is "true"
             * @param {boolean} opts.closeOnClickOutside The message box will close if clicked on overlay or outside of the modal box content. default is "false"
             * @param {string} opts.moretext The text to add inside the resulting window modal as information, will add more button
             * @param {boolean|string[]|MessageButton[]|ButtonList} opts.buttons The modal message buttons to display
             * @param {function} opts.callback The callback function after clicking the ok/cancel buttons with the result
             * @returns {string}
             */
            static warningMessage(opts) {
                opts = opts || {};
                if (typeof opts === 'string')
                    opts = { text: opts };
                if (!opts.type)
                    opts.type = 'warning';
                return this.message(opts);
            }
            /**
             * Error message. Same as message({type: 'error'}).
             * @static
             * @param {string} opts.title The message box title
             * @param {string} opts.text The message box body
             * @param {string} opts.type The message box type i.e.
             * information, warning, error, question, success,
             * alert, alert-information, alert-warning, alert-error, alert-question,
             * confirm, confirm-information, confirm-warning, confirm-error, confirm-question
             * alternatively a custom css class
             * @param {number} opts.expire The time period to close the message box
             * @param {string} opts.ok The ok button text
             * @param {string} opts.cancel the cancel button text
             * @param {string} opts.width The css width string
             * @param {string} opts.height The css height string
             * @param {boolean} opts.closeOnEsc  The message box will close when ESC is pressed on keyboard. default is "true"
             * @param {boolean} opts.closeOnClickOutside The message box will close if clicked on overlay or outside of the modal box content. default is "false"
             * @param {string} opts.moretext The text to add inside the resulting window modal as information, will add more button
             * @param {boolean|string[]|MessageButton[]|ButtonList} opts.buttons The modal message buttons to display
             * @param {function} opts.callback The callback function after clicking the ok/cancel buttons with the result
             * @returns {string}
             */
            static errorMessage(opts) {
                opts = opts || {};
                if (typeof opts === 'string')
                    opts = { text: opts };
                if (!opts.type)
                    opts.type = 'error';
                return this.message(opts);
            }
            /**
             * Success message. Same as message({type: 'success'}).
             * @static
             * @param {string} opts.title The message box title
             * @param {string} opts.text The message box body
             * @param {string} opts.type The message box type i.e.
             * information, warning, error, question, success,
             * alert, alert-information, alert-warning, alert-error, alert-question,
             * confirm, confirm-information, confirm-warning, confirm-error, confirm-question
             * alternatively a custom css class
             * @param {number} opts.expire The time period to close the message box
             * @param {string} opts.ok The ok button text
             * @param {string} opts.cancel the cancel button text
             * @param {string} opts.width The css width string
             * @param {string} opts.height The css height string
             * @param {boolean} opts.closeOnEsc  The message box will close when ESC is pressed on keyboard. default is "true"
             * @param {boolean} opts.closeOnClickOutside The message box will close if clicked on overlay or outside of the modal box content. default is "false"
             * @param {string} opts.moretext The text to add inside the resulting window modal as information, will add more button
             * @param {boolean|string[]|MessageButton[]|ButtonList} opts.buttons The modal message buttons to display
             * @param {function} opts.callback The callback function after clicking the ok/cancel buttons with the result
             */
            static successMessage(opts) {
                opts = opts || {};
                if (typeof opts === 'string')
                    opts = { text: opts };
                if (!opts.type)
                    opts.type = 'success';
                return this.message(opts);
            }
            /**
             * Returns a framework message details by group and number
             * @static
             * @param {string} msgGrp The message group (case insensitive)
             * @param {string} msgNum The message number
             * @returns {Promise<any>}
             */
            static getMessageNum(msgGrp, msgNum) {
                if (!SmartMessageCache[msgGrp])
                    SmartMessageCache[msgGrp] = {};
                if (SmartMessageCache[msgGrp][msgNum]) {
                    if (SmartMessageCache[msgGrp][msgNum].then)
                        return SmartMessageCache[msgGrp][msgNum];
                    else
                        return Promise.resolve(SmartMessageCache[msgGrp][msgNum]);
                }
                return SmartMessageCache[msgGrp][msgNum] = fetch(`/web/SmartMessage/${msgGrp}/${msgNum}`, { method: 'GET' })
                    .then(response => {
                    if (!response.ok)
                        throw response;
                    return SmartMessageCache[msgGrp][msgNum] = response.json();
                })
                    .catch(response => {
                    delete SmartMessageCache[msgGrp][msgNum];
                    try {
                        response.json().then((response) => {
                            this.errorMessage(response.message || response.title || response.error || 'Error has occured');
                        });
                    }
                    catch (err) {
                        this.errorMessage('Error has occured');
                    }
                    throw Error();
                });
            }
            /**
             * Returns the MessageType of a SmartMessage either from javascript cache memory or from
             * @static
             * @param   {string}        msgGrp  The message group (case insensitive)
             * @param   {number}        msgNum  The message number
             * @return  {Promise<any>}
             */
            static getMessageType(msgGrp, msgNum) {
                return this.getMessageNum(msgGrp, msgNum).then(message => Promise.resolve(message.MessageType.toLowerCase()));
            }
            /**
             * Displays a framework message by group and number
             * @static
             * @param {string} msgGrp The message group (case insensitive)
             * @param {string} msgNum The message number
             * @param {string} opts.title The message box title
             * @param {string} opts.text The message box body
             * @param {string} opts.type The message box type i.e.
             * information, warning, error, question, success,
             * alert, alert-information, alert-warning, alert-error, alert-question,
             * confirm, confirm-information, confirm-warning, confirm-error, confirm-question
             * alternatively a custom css class
             * @param {number} opts.expire The time period to close the message box
             * @param {string} opts.ok The ok button text
             * @param {string} opts.cancel the cancel button text
             * @param {string} opts.width The css width string
             * @param {string} opts.height The css height string
             * @param {boolean} opts.modal The modal flag for message.
             * @param {boolean} opts.showMessageCode Remove the information message text info group and number, text displayed between parentheses, default is "false"
             * @param {boolean} opts.closeOnEsc  The message box will close when ESC is pressed on keyboard. default is "true"
             * @param {boolean} opts.closeOnClickOutside The message box will close if clicked on overlay or outside of the modal box content. default is "false"
             * @param {string} opts.moretext The text to add inside the resulting window modal as information, will add more button
             * @param {boolean|string[]|MessageButton[]|ButtonList} opts.buttons The modal message buttons to display
             * @param {function} opts.callback The callback function after clicking the ok/cancel buttons with the result
             */
            static displayMessageNum(msgGrp, msgNum, opts) {
                const retVal = this.getMessageNum(msgGrp, msgNum);
                retVal.then(result => {
                    const msg = { text: result.MessageText };
                    msg.text = window.akioma.SmartMessage.replaceEmptyPlaceholders(msg.text);
                    switch (result.MessageType.toLowerCase()) {
                        case 'information':
                            msg.type = 'information';
                            break;
                        case 'error':
                            msg.type = 'error';
                            break;
                        case 'warning':
                            msg.type = 'warning';
                            break;
                        case 'success':
                            msg.type = 'success';
                            break;
                        case 'question':
                            msg.type = 'question';
                            msg.modal = true;
                            break;
                    }
                    // check if MessageBoxStyle is defined and set the modal or nonmodal type
                    if (result.MessageBoxStyle !== undefined)
                        msg.modal = (result.MessageBoxStyle.toLowerCase() === 'modal' ? true : false);
                    if (typeof opts === 'function')
                        msg.callback = opts;
                    else if (opts !== undefined)
                        Object.assign(msg, opts);
                    this.message(msg);
                });
            }
            /**
             * Clears all messages
             * @static
             */
            static clearAll() {
                for (const id in window.dhtmlx.message.pull)
                    window.dhtmlx.message.hide(id);
            }
        }
        /**
         * The default message expire value
         * @static
         */
        Message.expireDefault = 10000;
        swat.Message = Message;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Refresh Emitter
           * @export
           * @class RefreshEmitter
           */
        class RefreshEmitter {
            /**
                 * Refreshes Data
                 * @static
                 * @param {string} entityName The entity name. Accepts wildcard BUT currently only supports begins (see example).
                 * @param {string} opts.lastRowState The 'delete', 'update' or 'add' last row state.
                 * @param {string} opts.lastUpdatedRecord.selfhdl The selfHdl of the last updated record. Required for an add refresh.
                 * @example
                 * // to be called from the invokeServerTask().then() function.
                 *
                 * // delete refresh
                 * akioma.swat.RefreshEmitter.refreshData('eTerm*', {lastRowState: 'delete'}) // This will select the next available record
                 *
                 * // update refresh
                 * akioma.swat.RefreshEmitter.refreshData('eTerm*', {lastRowState: 'update'});
                 *
                 * // add refresh
                 * akioma.swat.RefreshEmitter.refreshData('eTerm*', {lastRowState: 'add', lastUpdatedRecord: {selfhdl: 'A69:111:000008101398'}});
                 */
            static refreshData(entityName, opts) {
                window.akioma.RefreshEmitter.refreshData(entityName, opts);
            }
        }
        swat.RefreshEmitter = RefreshEmitter;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Handles SessionContext
           * @export
           * @class SessionManager
           */
        class SessionManager {
            /**
                 * Gets session property
                 * @static
                 * @param {string}  name      The property name.
                 * @param {string}  [context] Represents the session context where the property will be searched (e.g eSessionContext, eSwatSessionContext).
                 * <br> If not specified, default is eSwatSessionContext
                 * @returns {string | undefined} Returns the session property value
                 */
            static get(name, context = 'eSwatSessionContext') {
                return window.akioma.getSessionProperty(name, context);
            }
            /**
                 * Sets session property
                 * @static
                 * @param {string}                 name       The property name.
                 * @param {string|integer|boolean} value      The property new value.
                 * @param {string}                 [context]  Represents the session context where the property will be set (e.g eSessionContext, eSwatSessionContext).
                 * <br> If not specified, default is eSwatSessionContext
                 */
            static set(name, value, context = 'eSwatSessionContext') {
                window.akioma.setSessionProperty(name, value, context);
            }
        }
        swat.SessionManager = SessionManager;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Handles Keyboard Shorcuts
         * @export
         * @class ShortcutManager
         */
        class ShortcutManager {
            /**
             * Gets keyboard shortcuts
             * @static
             * @param {string} cId The shortcut name.
             * @returns {string | undefined} Returns the shortcut key binding.
             */
            static get(cId) {
                return window.akioma.shortcutManager.get(cId);
            }
            /**
             * Sets keyboard shortcut
             * @static
             * @param {string} cId The Shortcut name.
             * @param {string} cShortcut Represents the new shortcut key binding.
             */
            static set(cId, cShortcut) {
                return window.akioma.shortcutManager.set(cId, cShortcut);
            }
            /**
             * Method for binding global shortcut.
             * @memberof ShortcutManager
             * @static
             * @param {string} keys
             * @param {function} callback
             * @param {any} [action]
             */
            static bindGlobal(keys, callback, action) {
                window.akioma.shortcutManager.bindGlobal(keys, callback, action);
            }
            /**
             * Method for unbinding global shortcut.
             * @memberof ShortcutManager
             * @static
             * @param {string} keys
             */
            static unbind(keys) {
                window.akioma.shortcutManager.unbind(keys);
            }
        }
        swat.ShortcutManager = ShortcutManager;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    /**
       * SocketConnectionHelper Object
       * @export
       * @class SocketConnectionHelper
       */
    class SocketConnectionHelper {
        /**
             * Method for setting up socket event listener
             * @param eventName Name of the event
             * @param callback
             */
        static on(eventName, callback) {
            window.akioma.socketConnection.on(eventName, callback);
        }
        /**
             * Method for emitting an event over websockets
             * @param eventName Name of the event
             * @param data The payload
             */
        static emit(eventName, data) {
            window.akioma.socketConnection.emit(eventName, data);
        }
        /**
             * Method to call after websocket connection is established
             * @param callback
             */
        static onAfterConnected(callback) {
            window.akioma.socketConnection.onAfterConnected(() => {
                callback();
            });
        }
        /**
             * Method to check if connection was established
             */
        static isConnected() {
            return window.akioma.socketConnection.isConnected();
        }
    }
    akioma.SocketConnectionHelper = SocketConnectionHelper;
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Creates a wrapper typescript object for a dynObject
           * @export
           * @class SwatFactory
           */
        class SwatFactory {
            /**
            * Recieves a controller object and creates the equivalent typescript object
            * @static
            * @param {*} controller Excepts both dynObject or controller object
            * @returns {SwatObject}
            */
            static createSwatObject(controller) {
                var _a, _b, _c, _d;
                if (!controller)
                    return null;
                // note that the wrappers are based on controllers and we do not use view or type
                // because there can be cases of controllers without dynObject view or type.
                // for example: the dynselect lookup datasource.
                // if a dynObject was passed instead of a controller then get controller from dynObject
                if (((_a = controller === null || controller === void 0 ? void 0 : controller.controller) === null || _a === void 0 ? void 0 : _a.dynObject) === controller)
                    controller = controller.controller;
                // in some cases use parent controller
                switch (controller.view) {
                    case 'tab':
                        controller = controller.parent;
                        break;
                    case 'ribbonblock':
                    case 'ribbonbutton':
                    case 'ribboncombo':
                    case 'ribboninput':
                    case 'ribbongroup':
                    case 'ribbonselect':
                    case 'ribbonselectoption':
                        controller = controller.parent;
                        while ((controller === null || controller === void 0 ? void 0 : controller.view) !== 'ribbon')
                            controller = controller.parent;
                        break;
                    case 'toolbarbutton':
                    case 'toolbarcombo':
                    case 'toolbarfillin':
                    case 'toolbarselect':
                        controller = controller.parent;
                        while ((controller === null || controller === void 0 ? void 0 : controller.view) !== 'toolbar')
                            controller = controller.parent;
                        break;
                }
                // to avoid creating multiple wrapper objects
                // a reference to the wrapper object is saved
                // and used if it is needed again
                if (controller._akiomaWrapperObject)
                    return controller._akiomaWrapperObject;
                switch (controller.view) {
                    case 'htmlContainer':
                        return new akioma.swat.DataField(controller);
                    case 'block':
                        return new akioma.swat.Block(controller);
                    case 'datasource':
                    case 'businessEntity':
                    case 'businessEntity2':
                        return new akioma.swat.DataSource(controller);
                    case 'form':
                        return new akioma.swat.Form(controller);
                    case 'fieldset':
                        return new akioma.swat.FieldSet(controller);
                    case 'dynselect':
                        return new akioma.swat.DynSelect(controller);
                    case 'combobox':
                    case 'multilist':
                        return new akioma.swat.ComboBox(controller);
                    case 'richtext':
                    case 'ittext':
                    case 'ckEditor':
                    case 'ckRichEditor':
                        return new akioma.swat.RichText(controller);
                    case 'translat':
                        return new akioma.swat.Translatable(controller);
                    case 'input':
                    case 'inputnum':
                    case 'inputtext':
                    case 'fileSelector':
                        if (controller.opt.type === 'checkbox')
                            return new akioma.swat.Toggle(controller);
                        else
                            return new akioma.swat.Input(controller);
                    case 'button':
                        return new akioma.swat.Button(controller);
                    case 'calendar':
                        return new akioma.swat.Calendar(controller);
                    case 'scheduler':
                        return new akioma.swat.Scheduler(controller);
                    case 'tokenselect':
                    case 'image':
                    case 'iconpicker':
                        return new akioma.swat.DataField(controller);
                    case 'datagrid':
                    case 'datagrid2':
                        return new akioma.swat.Grid(controller);
                    case 'propertygrid':
                        return new akioma.swat.PropertyGrid(controller);
                    case 'dataview':
                        return new akioma.swat.DataView(controller);
                    case 'treegrid':
                        return new akioma.swat.TreeGrid(controller);
                    case 'datagridcol':
                    case 'datagridcol2':
                        return new akioma.swat.GridCol(controller);
                    case 'imagebox':
                        return new akioma.swat.Image(controller);
                    case 'tabbar':
                        return new akioma.swat.Tabbar(controller);
                    case 'sidebar':
                        return new akioma.swat.Sidebar(controller);
                    case 'chart':
                        return new akioma.swat.Chart(controller);
                    case 'graphEditor':
                        return new akioma.swat.GraphEditor(controller);
                    case 'panel':
                        return new akioma.swat.Panel(controller);
                    case 'panelSwitcher':
                        return new akioma.swat.PanelSwitcher(controller);
                    case 'frame':
                        // top level frames are treated as windows
                        if ((_d = (_c = (_b = controller === null || controller === void 0 ? void 0 : controller.dynObject) === null || _b === void 0 ? void 0 : _b.parent) === null || _c === void 0 ? void 0 : _c.controller) === null || _d === void 0 ? void 0 : _d.isAutostartObjectsWindow)
                            return new akioma.swat.Window(controller);
                        else
                            return new akioma.swat.Frame(controller);
                    case 'taskbar':
                    case 'grouptaskbar':
                        return new akioma.swat.Taskbar(controller);
                    case 'window':
                    case 'popup':
                        return new akioma.swat.Window(controller);
                    case 'ribbon':
                        return new akioma.swat.Ribbon(controller);
                    case 'toolbar':
                        return new akioma.swat.Toolbar(controller);
                    case 'docviewer':
                        return new akioma.swat.DocViewer(controller);
                    case 'freeHand':
                        return new akioma.swat.FreeHand(controller);
                    case 'upload':
                        return new akioma.swat.Upload(controller);
                    default:
                        return new akioma.swat.SwatObject(controller);
                }
            }
        }
        swat.SwatFactory = SwatFactory;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./SwatFactory.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Base Swat Object
         * @export
         * @class SwatObject
         * @param {*} dynObject The dynObject
         */
        class SwatObject {
            constructor(controller) {
                this._controller = controller;
                // to avoid creating multiple wrapper objects
                // a reference to the wrapper object is saved
                // and used if it is needed again
                controller._akiomaWrapperObject = this;
            }
            get _dynObject() {
                return this._controller.dynObject;
            }
            get className() {
                return this.constructor.name;
            }
            /**
             * The object's legacy API controller.
             * Used for JavaScript calls from TypeScript.
             * @readonly
             * @type {*}
             * @example
             * window.akioma.myFunction(eventSource.controller);
             */
            get controller() {
                return this._controller;
            }
            /**
             * The object's legacy API dynObject.
             * Used for JavaScript calls from TypeScript.
             * @readonly
             * @type {*}
             * @example
             * window.akioma.myFunction(eventSource.dynObject);
             */
            get dynObject() {
                return this._dynObject;
            }
            /**
             * Returns the object attributes
             * @readonly
             * @return {Object}
             */
            get attributes() {
                return (this._controller.opt ? this._controller.opt :
                    null);
            }
            /**
             * The object name
             * @readonly
             * @type {string}
             */
            get name() {
                return (this._dynObject ? this._dynObject.name :
                    this._controller.opt ? this._controller.opt.name :
                        null);
            }
            /**
             * The swat object direct parent
             * @readonly
             * @type {SwatObject}
             */
            get parent() {
                if (!this._parent) {
                    if (this._dynObject)
                        this._parent = akioma.swat.SwatFactory.createSwatObject(this._dynObject.parent);
                    else {
                        let parent = this._controller.parent;
                        while (parent) {
                            if (parent.dynObject && (this._parent = akioma.swat.SwatFactory.createSwatObject(parent)))
                                break;
                            parent = parent.parent;
                        }
                    }
                }
                return this._parent;
            }
            /**
             * The swat object top-level parent, usually a window or dialog object
             * @readonly
             */
            get container() {
                const dynObject = this._dynObject || (this.parent ? this.parent._dynObject : null);
                if (!dynObject)
                    return null;
                if (!this._container)
                    this._container = akioma.swat.SwatFactory.createSwatObject(dynObject.container);
                return this._container;
            }
            /**
             * The swat object top screen (container), usually a window or dialog object
             * @readonly
             */
            get topScreen() {
                const dynObject = this._dynObject || (this.parent ? this.parent._dynObject : null);
                if (!dynObject)
                    return null;
                if (!this._topScreen)
                    this._topScreen = akioma.swat.SwatFactory.createSwatObject(dynObject.topScreen);
                return this._topScreen;
            }
            /**
             * The swat object inner screen (container)
             * @readonly
             */
            get screen() {
                const dynObject = this._dynObject || (this.parent ? this.parent._dynObject : null);
                if (!dynObject)
                    return null;
                if (!this._screen)
                    this._screen = akioma.swat.SwatFactory.createSwatObject(dynObject.screen);
                return this._screen;
            }
            /**
             * Gets a descendant object by name
             * @param {string} name The object name (case-insensitive)
             * @returns {SwatObject}
             */
            getObject(name) {
                if (!this.dynObject)
                    return null;
                const dynObject = this._dynObject.getObject(name);
                if (!dynObject || !dynObject.controller)
                    return null;
                if (dynObject.controller._akiomaWrapperObject)
                    return dynObject.controller._akiomaWrapperObject;
                const swatObject = akioma.swat.SwatFactory.createSwatObject(this._dynObject.getObject(name));
                return swatObject;
            }
            /**
             * Gets the object's link source or target object
             * @param {string} link The link name separated by ":" and SRC/TRG points e.g. "DATA:TRG"
             * @returns {SwatObject}
             * @example myForm.getLink("DISPLAY:SRC")
             */
            getLink(link) {
                if (!this.dynObject)
                    return null;
                const links = this.getLinks(link);
                if (!links || links.length === 0)
                    return null;
                return links[0];
            }
            /**
             * Gets the object's link source or target objects
             * @param {string} link The link name separated by ":" and SRC/TRG points e.g. "DATA:TRG"
             * @returns {SwatObject}[]
             * @example myDataSource.getLinks("DISPLAY:TRG")
             */
            getLinks(link) {
                if (!this.dynObject)
                    return null;
                // the getLink in akioma.object.js accepts :TARGET and anything else for SOURCE
                // so getLink("DISPLAY:TRG") is equal to getLink("DISPLAY:SOURCE")
                if (link.endsWith(':TRG'))
                    link = link.replace(':TRG', ':TARGET');
                // note that links cannot be cached
                // because links can be added dynamically with lazy loading
                // but the wrapper object is never created more than once for every object
                const links = this._dynObject.getLinks(link);
                if (!links || links.length === 0)
                    return null;
                return links.map((link) => akioma.swat.SwatFactory.createSwatObject(link));
            }
            /**
             * The swat object top-level window object.
             * Note: Desktop windows are windows not frames
             * so the window property of a child object in a desktop window will return the desktop window
             * unlike the container property which will return the main desktop window for the application.
             * Note: If the object is a window then it will returns itself.
             * @readonly
             * @type {Window}
             */
            get window() {
                const dynObject = this._dynObject || (this.parent ? this.parent._dynObject : null);
                if (!dynObject)
                    return null;
                if (!this._window) {
                    if (this instanceof akioma.swat.Window)
                        this._window = this;
                    else if (dynObject.container.controller.isAutostartObjectsWindow) {
                        let parent = dynObject.parent;
                        while ((parent === null || parent === void 0 ? void 0 : parent.parent) && !parent.parent.controller.isAutostartObjectsWindow && parent.parent.controller.view !== 'panelSwitcher')
                            parent = parent.parent;
                        this._window = akioma.swat.SwatFactory.createSwatObject(parent);
                    }
                    else
                        this._window = this.container;
                }
                return this._window;
            }
            /**
                 * Returns the first child by type
             * @param {string} type of the object
             * @instance
             * @memberOf Panel
                 */
            getFirstChildByType(type) {
                const firstChild = this.controller.dynObject.getFirstChildByType(type);
                return akioma.swat.SwatFactory.createSwatObject(firstChild);
            }
            /**
                 * Returns the first child by type
             * @param {string} type of the object
             * @instance
             * @memberOf Panel
                 */
            getFirstParentByType(type) {
                const firstParent = this.controller.dynObject.getFirstParentByType(type);
                return akioma.swat.SwatFactory.createSwatObject(firstParent);
            }
            /**
             * Used for retriving the object type
             * @type {string}
             */
            get type() {
                return this._controller.view.toLowerCase();
            }
            /**
             * Returns the state data of an object.
             * @instance
             * @memberof Panel
             * @returns {Object}
             */
            get stateData() {
                return this._controller.stateData;
            }
            //Placeholder function, to be overridden in child types
            /* eslint-disable-next-line @typescript-eslint/no-empty-function */
            destroy() { }
        }
        swat.SwatObject = SwatObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Handles Custom properties in the user profile
         * @export
         * @class UserProfile
         */
        class UserProfile {
            /**
             * Saves custom property/properties in the vuexStore
             * If userProfile AutoStore = 'onChange' it will also save the changes to the database
             * @memberof UserProfile
             * @static
             * @param {Object} oSettings The object containing the new settings (key: value)
             * @returns {void}
             */
            static saveCustomLocalProfileProperty(oSettings) {
                window.UserProfile.saveCustomLocalProfileProperty(oSettings);
            }
            /**
             * Removes custom property by key from the vuexStore
             * If userProfile AutoStore = 'onChange' it will also save the changes to the database
             * @memberof UserProfile
             * @static
             * @param {string} key The custom property key to remove
             * @returns {void}
             */
            static removeCustomLocalProfileProperty(key) {
                window.UserProfile.removeCustomLocalProfileProperty(key);
            }
            /**
             * Removes all custom properties from the vuexStore
             * If userProfile AutoStore = 'onChange' it will also save the changes to the database
             * @memberof UserProfile
             * @static
             * @returns {void}
             */
            static removeCustomLocalProfileProperties() {
                window.UserProfile.removeCustomLocalProfileProperties();
            }
            /**
             * Returns all custom properties of the user profile from the vuexStore
             * @memberof UserProfile
             * @static
             * @returns {Object} The custom properties object with all key/values
             */
            static loadCustomLocalProfileSettings() {
                return window.UserProfile.loadCustomLocalProfileSettings();
            }
            /**
             * Returns custom property object from the user profile vuexStore for given key
             * @memberof UserProfile
             * @static
             * @param {string} key Key for which to return the value
             * @returns {any} Value of given custom property
             */
            static loadCustomLocalProfileSetting(key) {
                return window.UserProfile.loadCustomLocalProfileSetting(key);
            }
            /**
             * Triggers reload of user profile from the server
             * @memberof UserProfile
             * @static
             * @return {Promise<any>}
             */
            static loadFromServer() {
                return window.UserProfile.loadFromServer();
            }
            /**
             * Sets the profileAutoStore strategy to the given value, which handles when savings should occur
             * @memberof UserProfile
             * @param {string} cProfileAutoStore Type of profileAutoStore, can be "onChange" or "onLogout" or "" (empty)
             * @return {void}
             */
            static setProfileAutoStore(cProfileAutoStore) {
                window.UserProfile.setProfileAutoStore(cProfileAutoStore);
            }
            /**
             * Returns the current ProfileAutoStore type
             * @memberof UserProfile
             * @return {string} The profileAutoStore type
             */
            static getProfileAutoStore() {
                return window.UserProfile.getProfileAutoStore();
            }
            /**
             * Method to save the UserProfile settings on the backend side
             * @param  {boolean} bShowSuccessMsg Flag for displaying the success message or not, default will show if not specified
             * @param  {boolean} methodName Name of method to be called on save (setCustomProperty, deleteCustomProperty etc.) default: SaveUserProfile
             * @param  {object} oData      Data to be sent to the backend; contains custom property or whole user profile by default
             * @memberof UserProfile
             * @return {void}
             */
            static saveToServer(bShowSuccessMsg, methodName, oData) {
                window.UserProfile.saveToServer(bShowSuccessMsg, methodName, oData);
            }
        }
        swat.UserProfile = UserProfile;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Wait Cursor
         * @export
         * @class WaitCursor
         */
        class WaitCursor {
            /**
             * Method used for showing the wait state, wait cursor and blocking waiting state on window container
             * @param {SwatObject} uiContext
             * @returns {void}
             */
            static showWaitState(uiContext) {
                window.akioma.WaitCursor.showWaitState(uiContext.dynObject);
            }
            /**
             * Method used for hiding/disabling the wait state, wait cursor and blocking waiting state on window container
             * @param {SwatObject} uiContext
             */
            static hideWaitState(uiContext) {
                window.akioma.WaitCursor.hideWaitState(uiContext.dynObject);
            }
            /**
             * Method used for showing the rotating wait cursor per panel
             * @param {SwatObject} uiContext
             * @param {boolean} bCancellable Indicates if you can cancel the current JSDO request
             */
            static showWaitCursor(uiContext, bCancellable) {
                window.akioma.WaitCursor.showWaitCursor(uiContext.dynObject, bCancellable);
            }
            /**
             * Method for showing External wait state in external screen / linked wait state
             * @param {SwatObject} uiContext
             */
            static showExternalWaitStates(uiContext) {
                window.akioma.WaitCursor.showExternalWaitStates(uiContext.dynObject);
            }
            /**
             * Method for hinding External screen wait state / linked wait state
             * @param {SwatObject} uiContext
             */
            static hideExternalWaitStates(uiContext) {
                window.akioma.WaitCursor.hideExternalWaitStates(uiContext.dynObject);
            }
            /**
             * Method for linking external screen wait state
             * @param {SwatObject} uiContext The control in this screen linked to the external window
             * @param {string} externalWindowId the external window id
             */
            static linkExternalWaitState(uiContext, externalWindowId) {
                window.akioma.WaitCursor.linkExternalWaitState(uiContext.dynObject, externalWindowId);
            }
            /**
             * Method used for hiding the rotating wait cursor per panel
             * @param {SwatObject} uiContext
             */
            static hideWaitCursor(uiContext) {
                window.akioma.WaitCursor.hideWaitCursor(uiContext.dynObject);
            }
            /**
             * Method used for showing/enabling the blocking progress state, user pointer events are blocked in window container
             * @param {SwatObject} uiContext
             */
            static showProgressState(uiContext) {
                window.akioma.WaitCursor.showProgressState(uiContext.dynObject);
            }
            /**
             * Method used for hiding the progress state, user pointer events unblocked in window container
             * @param {SwatObject} uiContext
             */
            static hideProgressState(uiContext) {
                window.akioma.WaitCursor.hideProgressState(uiContext.dynObject);
            }
            /**
             * Method returning current global state of wait cursor
             * @returns {boolean}
             */
            static isGlobalProgressStateActive() {
                return window.akioma.WaitCursor.isGlobalProgressStateActive();
            }
            /**
             * Method used for setting the wait cursor for all link targets of the given businessEntity
             * @param {DataSource} uiContext
             * @param {boolean} inProgress Set the cursor state, true or false
             */
            static setWaitCursorForLinks(uiContext, inProgress) {
                window.akioma.WaitCursor.setWaitCursorForLinks(uiContext.dynObject, inProgress);
            }
            /**
             * Method used for checking if progress state is active
             * @param {SwatObject}   uiContext Swat dynObject
             * @static
             * @memberof WaitCursor
             * @returns {boolean}
             */
            static isProgressStateActive(uiContext) {
                return window.akioma.WaitCursor.isProgressStateActive(uiContext);
            }
            /**
             * Method returning given uiContext dynObject waitCursor visibility
             * @param {SwatObject}   uiContext
             * @static
             * @memberof WaitCursor
             * @returns {boolean}
             */
            static isCursorVisible(uiContext) {
                return window.akioma.WaitCursor.isCursorVisible(uiContext);
            }
            /**
             * Method used for clearing up all the windows that have progress state active
             */
            static clearProgressStateGlobally() {
                window.akioma.WaitCursor.clearProgressStateGlobally();
            }
        }
        swat.WaitCursor = WaitCursor;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../SwatObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * DataSource Object
         * @export
         * @class DataSource
         * @extends {SwatObject}
         */
        class DataSource extends akioma.swat.SwatObject {
            /**
             * Gets the data object field value
             * @param {string} name The field name (case-insensitive)
             * @returns {*}
             */
            getValue(name) {
                name = name.toLowerCase();
                let value = this._controller.getFieldValue(name);
                // copied from getValue() method in akioma.object.js
                // need to check if this part is needed
                if (name === 'selfhdl') {
                    if (value === null || value === undefined) {
                        value = this._controller.getFieldValue('SelfHdl');
                        if (value === null || value === undefined)
                            value = this._controller.getFieldValue('selfHdl');
                    }
                }
                return value;
            }
            /**
             * Sets the data object field value
             * @param {string} name The field name (case-insensitive)
             * @param {value} value The value of the field
             * @param {any} primaryKey The value corresponding to the KeyField attribute; used to uniquely identify the record for which to set the new value; optional
             * @returns {*}
             */
            setValue(name, value, primaryKey) {
                this._controller.setFieldValue({
                    name: name.toLowerCase(),
                    value: value,
                    state: 'updated',
                    primaryKey: primaryKey
                });
            }
            /**
             * Gets the current record with all the record values
             * @returns {*} Returns the current record
             */
            getCurrentRecord() {
                const id = this._controller.getStore(this._controller.entityName).getCursor();
                return Object.assign({}, this._controller.getStore(this._controller.entityName).item(id));
            }
            /**
             * Gets all the loaded records
             * @returns {*} Returns an array with all the loaded records
             */
            getLoadedRecords() {
                const data = this._controller.dhx.data.pull;
                return Object.keys(data).map(key => Object.assign({}, data[key]));
            }
            /**
             * Gets all the updated records
             * @returns {*} Returns an array with all the updated records
             */
            getUpdatedRecords() {
                const data = this._controller.dhx.data.pull;
                return this._controller.dc.updatedRows.map((key) => Object.assign({}, data[key]));
            }
            /**
             * Gets all the locally stored data.
             * @returns {Object} Returns an object containing the locally stored data
             */
            getData() {
                return this._controller.getData();
            }
            /**
             * Clears all filters
             */
            clearFilter() {
                this._controller.query.clearAll();
            }
            /**
             * Add filter (top level AND filter)
             * @param {string}  name     The field name (case-insensitive)
             * @param {string}  operator The filter operator
             * @param {string}  value    The filter value
             * @param {boolean} unique   If true, adds a new unique condition that will overwrite any conditions with the same field name. If false, just adds a new condition
             */
            addFilter(name, operator, value, unique) {
                this.setFilter(name, operator, value, unique);
            }
            /**
             * Sets a filter (top level AND filter)
             * @param {string}  name     The field name (case-insensitive)
             * @param {string}  operator The filter operator
             * @param {string}  value    The filter value
             * @param {boolean} [unique] If true, adds a new unique condition that will overwrite any conditions with the same field name. If false, just adds a new condition
             */
            setFilter(name, operator, value, unique) {
                name = name.toLowerCase();
                if (this.hasFilter(name, operator, value))
                    return;
                if (unique)
                    this._controller.query.addUniqueCondition(name, operator, value);
                else
                    this._controller.query.addCondition(name, operator, value);
            }
            /**
             * Check if there are any filters for a field (top level AND filter)
             * @param {string} name The field name (case-insensitive)
             * @returns {boolean}
             */
            hasFilters(name) {
                name = name.toLowerCase();
                return this._controller.query.hasConditions(name);
            }
            /**
             * Check if specific filter exists (top level AND filter)
             * @param {string}  name     The field name (case-insensitive)
             * @param {string}  operator The filter operator
             * @param {string}  value    The filter value
             * @returns {boolean}
             */
            hasFilter(name, operator, value) {
                name = name.toLowerCase();
                return this._controller.query.hasCondition(name, operator, value);
            }
            /**
             * Returns the filter conditions from a given field name. (top level AND filter)
             * @param {string} name The field name (case-insensitive)
             * @returns {Object[]|null}
             */
            getFilter(name) {
                name = name.toLowerCase();
                return this._controller.query.getFilterByName(name);
            }
            /**
             * Removes an existing filter condition (top level AND filter)
             * @param {string}  name     The field name (case-insensitive)
             * @param {string}  operator The filter operator
             * @param {string}  value    The filter value
             */
            removeFilter(name, operator, value) {
                name = name.toLowerCase();
                this._controller.query.removeCondition(name, operator, value);
            }
            /**
             * Clears sorting
             */
            clearSort() {
                const newfilter = this._controller.query;
                newfilter.clearSort();
                newfilter.buildQuery();
            }
            /**
             * Checks if a field (and optional direction) are in the datasource sorting.
             * Returns true if the field exists at any level not just the first level.
             * @param name The field name (case-insensitive). If no field name is passed, checks if there is any sorting.
             * @param direction "asc" for ascending or "desc" for descending. If no direction is passed, check if only field name exists.
             */
            hasSort(name, direction) {
                const sortList = this.getSort();
                if (!name) {
                    if (sortList && sortList.length > 0)
                        return true;
                    else
                        return false;
                }
                name = name.toLowerCase();
                for (const sort of sortList) {
                    if (sort.field.toLowerCase() === name) {
                        if (direction) {
                            if (sort.direction === direction)
                                return true;
                        }
                        else
                            return true;
                    }
                }
                return false;
            }
            /**
             * Sets the sorting
             * @param {array} [sort]
             * @param {string} sort.field The field name (case-insensitive)
             * @param {string} sort.direction "asc" for ascending or "desc" for descending
             */
            setSort(sort, ...args) {
                if (typeof args[0] === 'string')
                    sort = [{ field: args[0], direction: args[1] || 'asc' }];
                this._controller.query.setSorting(sort);
            }
            /**
             * Returns the current sorting
             */
            getSort() {
                if (!this._controller.query.aSorting)
                    return [];
                return Array.from(this._controller.query.aSorting);
            }
            /**
             * Sets a named query parameter
             * @param {string} query The parameter query name
             * @param {string} name The parameter field name
             * @param {*} value The parameter value
             * @param {string} type The parameter type
             */
            setNamedQueryParam(query, name, value, type) {
                this._controller.setNamedQueryParam(query, name, value, type);
            }
            /**
             * Method used for setting the foreign key fields for the dataSource, that will be sent as request payload in GetInitialValues call
             * @param {array} keys The list of foreign key fields with values
             * @instance
             * @returns {void}
             */
            setForeignKeys(keys) {
                this._controller.setForeignKeys(keys);
            }
            /**
             * Sets the businessEntity to perform queries that include both filters and NamedQuery params
             * @param {boolean} bApply The parameter that sets the apply all filters flag
             */
            setApplyQueryFilters(bApply) {
                this._controller.applyAllQueryFilters(bApply);
            }
            /**
             * Saves current record
             * @returns {Promise<void>}
             */
            saveRecord() {
                return this._controller.updateRecord();
            }
            /**
             * Deletes the current record
             * @param {object} options Delete options
             * @param {boolean} [options.closeWindow=true] Closes the container window after delete. Defaults to true.
             * @returns {Promise<void>}
             */
            deleteRecord(options = { closeWindow: true }) {
                return this.controller.deleteRecord(options);
            }
            /**
             * Adds a new empty record
             */
            addRecord() {
                this.controller.addRecord();
            }
            /**
             * Deprecated method to execute the query
             * @deprecated Use fetch() instead
             * @param {string} opts.repositionTo The handle used to position a record in Grid.
             * Can be a comma-separated list of handles when using a multiselect Grid.
             * @param {function} callback The callback function to be called at the AfterFill event.
             */
            openQuery(opts = {}, callback = null) {
                this._controller.openQuery(opts, callback);
            }
            /**
             * Closes the query and empties the records
             */
            closeQuery() {
                this._controller.dhx.clearAll();
            }
            /**
             * @param {string} opts.repositionTo The handle used to position a record in Grid.
             * Can be a comma-separated list of handles when using a multiselect Grid.
             * @returns {Promise<unknown>} Returns a promise with the reponse
             */
            fetch(opts = {}) {
                return this._controller.fetch(opts);
            }
            /**
             * Returns the current record data before changes
             * @returns {*}
             */
            getBeforeData() {
                const id = this._controller.dhx.getCursor();
                const data = this._controller.jsdo[this._controller.opt.entityName].find((record) => (record.data._id === id)).data;
                const retVal = {};
                for (const key in data)
                    retVal[key] = data[key];
                return retVal;
            }
            /**
             * Returns if there are changes, recusive hasChanges check
             * @returns {boolean}
             */
            hasChanges() {
                return this._controller.hasChanges();
            }
            /**
             * Returns if there are messages from the previous save
             * @readonly
             * @type {boolean}
             */
            get hasMessages() {
                return this._controller.bContainsSmartMessage;
            }
            /**
             * Method used for getting the refresh scheme payload
             * @return {Object|null}
             */
            get refreshSchemePayload() {
                return this._controller.getRefreshSchemePayload();
            }
        }
        swat.DataSource = DataSource;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    /**
     * ExternalScreen Object
     * @export
     * @class ExternalScreen
     */
    class ExternalScreen {
        /**
         * @property {any}  externalData   Data from the external screen.
         */
        static get externalData() {
            return window.akioma.ExternalScreen.externalData;
        }
        /**
         * @property {array}  externalScreens   List of external screens.
         */
        static get externalScreens() {
            return window.akioma.ExternalScreen.externalScreens;
        }
        /**
         * @property {array}  externalScreensNamespaces   List of external screens namespaces.
         */
        static get externalScreensNamespaces() {
            return window.akioma.ExternalScreen.externalScreensNamespaces;
        }
        /**
         * @property {string}  externalScreenContainer   The external screen container.
         */
        static get externalScreenContainer() {
            return window.akioma.ExternalScreen.externalScreenContainer;
        }
        /**
         * @property {string}  UUIDBrowserSession   Browser session id
         */
        static get UUIDBrowserSession() {
            return window.akioma.ExternalScreen.UUIDBrowserSession;
        }
        /**
         * @property {array}  onBeforeScreenOnload   Before screen unload callbacks.
         */
        static get onBeforeScreenOnload() {
            return window.akioma.ExternalScreen.onBeforeScreenOnload;
        }
        /**
         * @property {array}  popups   The windows/popups opened.
         */
        static get popups() {
            return window.akioma.ExternalScreen.popups;
        }
        /**
         * @property {Array<ExternalScreen>} ExternalObjects The list of all External Screen Objects
         */
        static get ExternalObjects() {
            return window.akioma.ExternalScreen.ExternalObjects;
        }
        /**
         * Constructor for creating a new ExternalScreen object
         * @constructor
         * @memberof ExternalScreen
         * @param {string} name Name of the ExternalScreen
         */
        constructor(name) {
            this.externalScreen = new window.akioma.ExternalScreen(name);
        }
        /**
         * Getter for namespace
         * @return {string}
         */
        get namespace() {
            return this.externalScreen.namespace;
        }
        /**
         * Method used for initializing the browser session id
         */
        static initBrowserSessionId() {
            window.akioma.ExternalScreen.initBrowserSessionId();
        }
        /**
         * Method for returning the external screen popup by namespace
         * @param screenNamespace The External Screen namespace used when launching
         */
        static getExternalPopup(screenNamespace) {
            return window.akioma.ExternalScreen.getExternalPopup(screenNamespace);
        }
        /**
         * Method to loop over each external screen popup
         * @param func Function to call for each popup
         */
        static forEachPopup(func) {
            window.akioma.ExternalScreen.forEachPopup(func);
        }
        /**
         * Method for setting screenNamespace from query param screenNamespace
         * @static
         */
        static loadExternalDesignerNamespace() {
            window.akioma.ExternalScreen.loadExternalDesignerNamespace();
        }
        /**
         * Method used for setting the active window foreign key
         * @public
         * @memberof ExternalScreen
         * @param {string} foreignKey
         */
        setActiveWindowForeignKey(foreignKey) {
            this.externalScreen.setActiveWindowForeignKey(foreignKey);
        }
        /**
         * Method used for setting the active window foreign key
         * @public
         * @memberof ExternalScreen
         * @returns {string} activeWindowForeignKey
         */
        getActiveWindowForeignKey() {
            return this.externalScreen.getActiveWindowForeignKey();
        }
        static clearLocalOpened(name) {
            window.akioma.ExternalScreen.clearLocalOpened(name);
        }
        /**
         * Method for getting the ExternalScreen Opened locally from localStorage
         * @param {string} name
         * @instance
         * @memberof ExternalScreen
         * @return  {Object}
         */
        static getLocalOpened(name) {
            return window.akioma.ExternalScreen.getLocalOpened(name);
        }
        /**
         * Method for setting up a refresh listener method
         * @param {function} ln
         * @instance
         * @memberof ExternalScreen
         */
        setRefreshListener(ln) {
            this.externalScreen.setRefreshListener(ln);
        }
        /**
         * Method for setting up a refreshScheme listener method besides the default behaviour
         * @param {function} ln
         * @instance
         * @memberof ExternalScreen
         */
        setRefreshSchemeListener(ln) {
            this.externalScreen.setRefreshSchemeListener(ln);
        }
        /**
         * Method for setting up a launchContainer listener method
         * @param {function} ln Listener method
         * @instance
         * @memberof ExternalScreen
         */
        setLaunchContainerListener(ln) {
            this.externalScreen.setLaunchContainerListener(ln);
        }
        /**
         * Method for setting up an activeWidow listener method
         * @param {function} ln Listener method
         * @instance
         * @memberof ExternalScreen
         */
        setActiveWindowListener(ln) {
            this.externalScreen.setActiveWindowListener(ln);
        }
        /**
         * Method for setting up an closeWindow listener method
         * @param {function} ln Listener method
         * @instance
         * @memberof ExternalScreen
         */
        setCloseWindowListener(ln) {
            this.externalScreen.setCloseWindowListener(ln);
        }
        /**
         * Method for setting up data available listener method
         * @param ln Listener method
         * @instance
         * @memberof ExternalScreen
         */
        setDataAvailListener(ln) {
            this.externalScreen.setDataAvailListener(ln);
        }
        /**
         * Method for listening for events
         * @param {string} eventName The name of the event to listen for
         * @param {function} fn The callback method
         * @instance
         * @memberof ExternalScreen
         */
        on(eventName, fn) {
            this.externalScreen.on(eventName, fn);
        }
        /**
         * Removes the event listeners
         * @param {string} eventName The name of the event
         * @param {function} fn The callback method
         * @memberOf ExternalScreen
         */
        off(eventName, fn) {
            this.externalScreen.off(eventName, fn);
        }
        /**
         * Emits an event
         * @param {string} eventName The name of the event
         * @param {object} payload The payload/data to send
         * @memberOf ExternalScreen
         */
        emit(eventName, payload) {
            this.externalScreen.emit(eventName, payload);
        }
        /**
         * Creates a new event listener
         * @memberof ExternalScreen
         */
        createListener() {
            this.externalScreen.createListener();
        }
        /**
         * Creates a new event listener
         * @memberof ExternalScreen
         */
        createEmitter() {
            this.externalScreen.createEmitter();
        }
        /**
         * Method for setting up the ExternalScreen namespace
         * @memberof ExternalScreen
         * @param {string} namespace
         * @returns {void}
         */
        setNamespace(namespace) {
            this.externalScreen.setNamespace(namespace);
        }
        /**
         * Creates a new event listener
         * @memberof ExternalScreen
         */
        getExternalData(bClear = false) {
            return this.externalScreen.getExternalData(bClear);
        }
        /**
         * Creates a new event listener
         * @memberof ExternalScreen
         */
        static setExternalData(oExternalData) {
            window.akioma.ExternalScreen.setExternalData(oExternalData);
        }
        static setLocalOpened(name, elm) {
            window.akioma.ExternalScreen.setLocalOpened(name, elm);
        }
        /**
         * Sets the external screen container
         * @memberof ExternalScreen
         * @static
         * @param {string} containerName
         */
        static setContainer(containerName) {
            window.akioma.ExternalScreen.externalScreenContainer = containerName;
        }
        /**
         * Creates a new event listener
         * @memberof ExternalScreen
         */
        destroy() {
            delete this.externalScreen;
        }
    }
    akioma.ExternalScreen = ExternalScreen;
    /**
     * Method used for launching an external screen window.
     * @param {object} oOptions
     * @param {object} oOptions.screen Screen settings
     * @param {number} oOptions.screen.width External screen width
     * @param {number} oOptions.screen.height External screen height
     * @param {number} oOptions.screen.top External screen top position
     * @param {number} oOptions.screen.left External screen left position
     * @param {string} oOptions.screen.hostname The hostname, default will be window.location, url
     * @param {string} oOptions.baseLayoutObject The repository object name of the main layout container
     * @param {string} oOptions.autostartObjects The repository object name that will be loaded in the baseLayoutObject
     * @param {string} oOptions.launchContainer Name of screen to launch
     * @param {string} oOptions.name Name of the External Screen to open
     * @param {object} oOptions.custom Custom data object properties to pass to external screen
     * @param {Function} oOptions.onBeforeScreenLoadClosed Callback function to be called before screen loads and closed
     * @param {Function} oOptions.onBeforeScreenUnload Callback function to be called before the screen unloads
     * @returns {Promise<ExternalWindowProxy>}
     *
     */
    function launchExternalScreen(oOptions) {
        return __awaiter(this, void 0, void 0, function* () {
            return window.akioma.launchExternalScreen(oOptions);
        });
    }
    akioma.launchExternalScreen = launchExternalScreen;
})(akioma || (akioma = {}));
/// <reference path="../SwatObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Visual Objects Base Class
         * @export
         * @class VisualObject
         * @extends {SwatObject}
         */
        class VisualObject extends akioma.swat.SwatObject {
            /**
             * Forces the object to show.
             * For example, if the object is in a collapsed panel, the panel is expanded
             * or in an unselected tab, selects the object tab etc.
             */
            forceShow() {
                let controller = this._controller;
                while (controller && controller.view !== 'window') {
                    switch (controller.view) {
                        case 'tab': {
                            const parent = controller.parent;
                            const key = controller.opt.PageKey;
                            if (parent.currentPageKey() !== key)
                                parent.setActivePage(key);
                            break;
                        }
                        case 'panel':
                            if (controller.dhx.isCollapsed())
                                controller.dhx.expand();
                            break;
                    }
                    controller = controller.parent;
                }
            }
            /**
             * Returns if there are changes in the object or its descendents
             * @example Object.hasChanges()
             * @returns {boolean}
             */
            hasChanges() {
                if (this._controller.oVuexState
                    && this._controller.oVuexState.attributes
                    && this._controller.oVuexState.attributes.hasChanges)
                    return true;
                else
                    return false;
            }
            /**
             * Method to clear the hasChanges flag on the object
             * @example Object.clearChanges()
             */
            clearHasChanges() {
                this._controller.clearHasChanges();
            }
            /**
                 * Decrement has changes on a form with 1
                 * @returns {void}
                 * @memberof VisualObject
                 */
            decrementChanges() {
                this._controller._dispatch('decrementHasChanges', 1);
            }
            /**
             * Set a custom state on a controller
             * @param  {string} name
             * @param  {object} [options]
             * @instance
             * @memberOf VisualObject
             * @returns {void}
             */
            setCustomState(name, options) {
                this._controller.setCustomState(name, options);
            }
            /**
             * Remove a custom state from a controller
             * @param  {string} name
             * @instance
             * @memberOf VisualObject
             * @returns {void}
             */
            clearCustomState(name) {
                this._controller.clearCustomState(name);
            }
            /**
             * Returns if there are changes in the object or its descendents
             * @returns {boolean}
             */
            hasErrors() {
                if (this._controller.oVuexState
                    && this._controller.oVuexState.attributes
                    && this._controller.oVuexState.attributes.hasErrors)
                    return true;
                else
                    return false;
            }
            /**
             * Add an panel message and return the index of the message
             * @param  {PanelMessage} msg The panel message
             * @param  {string} msg.text The panel message text
             * @param  {string} msg.type The panel message type i.e.
             * info, warning, error, success
             * @instance
             * @memberOf VisualObject
             * @returns {number}
             */
            addPanelMessage(msg) {
                return this._controller.addPanelMessage(msg);
            }
            /**
             * Remove a panel message from a controller by the given id
             * @param  {number} id
             * @instance
             * @memberOf VisualObject
             * @returns {void}
             */
            removePanelMessage(id) {
                this._controller.removePanelMessage(id);
            }
            /**
             * Remove all panel messages from a controller
             * @instance
             * @memberOf VisualObject
             * @returns {void}
             */
            clearPanelMessages() {
                this._controller.clearPanelMessages();
            }
        }
        swat.VisualObject = VisualObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./VisualObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Accordion Object
           * @export
           * @class Accordion
           * @extends {VisualObject}
           */
        class Accordion extends akioma.swat.VisualObject {
        }
        swat.Accordion = Accordion;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../VisualObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Button Object
           * @export
           * @class Button
           * @extends {VisualObject}
           */
        class FormFieldObject extends akioma.swat.VisualObject {
            get formController() {
                if (!this._formController)
                    this._formController = this._controller.getAncestor('form');
                return this._formController;
            }
            get formDhx() {
                if (!this._formDhx)
                    this._formDhx = this.formController.dhx;
                return this._formDhx;
            }
            /**
             * The form field form object
             * @readonly
             * @type {Form}
             */
            get form() {
                if (!this._form)
                    this._form = (akioma.swat.SwatFactory.createSwatObject(this.formController));
                return this._form;
            }
            /**
             * The form field enabled mode
             * @type {boolean}
             */
            get enabled() {
                return this.formController.getFormFieldEnabled(this.name);
            }
            set enabled(value) {
                if (value)
                    this.formController.enableFormField(this.name);
                else
                    this.formController.disableFormField(this.name);
            }
            /**
             * The form field readonly mode
             * @type {boolean}
             */
            get readonly() {
                return !this.formController.getFormFieldEnabled(this.name);
            }
            set readonly(value) {
                if (value)
                    this.formController.disableFormField(this.name);
                else
                    this.formController.enableFormField(this.name);
            }
            /**
             * The form field hidden mode (opposite of visible)
             * @type {boolean}
             */
            get hidden() {
                return this._controller.isFieldHidden();
            }
            set hidden(value) {
                const formController = this.formController;
                if (value)
                    formController.hideFormField(this.name);
                else
                    formController.showFormField(this.name);
            }
            /**
             * The form field visible mode (opposite of hidden)
             * @type {boolean}
             */
            get visible() {
                return !this.hidden;
            }
            set visible(value) {
                this.hidden = !value;
            }
            /**
             * The form field label
             * @type {string}
             */
            get label() {
                return this.formDhx.getItemLabel(this.name);
            }
            set label(value) {
                this.formDhx.setItemLabel(this.name, value);
            }
            /**
             * Method for checking if form field has changes
             */
            hasChanges() {
                return this.formController.getFieldHasChanges(this.name);
            }
            /**
             * Method for setting the has changes flag on a form field
             * @param state The hasChanges state
             */
            setHasChanges(state) {
                this.formController.setFieldHasChanges(this.name, state);
            }
            /**
             * Method for showing the info button of a form field
             */
            showInfoButton() {
                this._controller.showInfoButton();
            }
            /**
             * Method for hiding the info button of a form field
             */
            hideInfoButton() {
                this._controller.hideInfoButton();
            }
            /**
             * Sets the row of the control.
             * @param {number} row The row number.
             * @memberof FormFieldObject
             */
            setRowStart(row) {
                this._controller.setRowStart(row);
            }
            /**
             * Sets the column start for a form control.
             * @param {number} columnStart The column start.
             * @memberof FormFieldObject
             */
            setColumnStart(columnStart) {
                this._controller.setColumnStart(columnStart);
            }
            /**
             * Sets the width end for a form control.
             * @param {number} width The new control width.
             * @memberof FormFieldObject
             */
            setColumnEnd(width) {
                this._controller.setColumnEnd(width);
            }
        }
        swat.FormFieldObject = FormFieldObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./datafield/FormFieldObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * FormFieldContranierObject Object
         * @export
         * @class FieldSet
         * @extends {VisualObject}
         */
        class FormFieldContainerObject extends akioma.swat.FormFieldObject {
            /**
             * Sets the row of a form control.
             * @param {string} fieldName The form control field name.
             * @param {number} row The row number.
             * @memberof BaseFormDataField
             */
            setFormFieldRowStart(fieldName, row) {
                this._controller.setFormFieldRowStart(fieldName, row);
            }
            /**
             * Sets the column start of a form control.
             * @param {string} fieldName The form control field name.
             * @param {number} columnStart The column start.
             * @memberof BaseFormDataField
             */
            setFormFieldColumnStart(fieldName, columnStart) {
                this._controller.setFormFieldColumnStart(fieldName, columnStart);
            }
            /**
             * Sets the width end of a form control.
             * @param {string} fieldName The form control field name.
             * @param {number} width The new control width.
             * @memberof BaseFormDataField
             */
            setFormFieldColumnEnd(fieldName, width) {
                this._controller.setFormFieldColumnEnd(fieldName, width);
            }
            /**
             * Shifts columns in an active control starting from a given column by a given offset.
             * @param {number} columnStart The column number to start from.
             * @param {number} columnOffset The offset by which to shift.
             * @memberof BaseFormDataField
             */
            shiftColumnsByOffset(columnStart, columnOffset) {
                this._controller.shiftColumnsByOffset(columnStart, columnOffset);
            }
            /**
             * Sets the number of columns in a form field container
             * @param {number} columnNumber The column number.
             * @memberof BaseFormDataField
             */
            setColumns(columnNumber) {
                this._controller.setColumns(columnNumber);
            }
        }
        swat.FormFieldContainerObject = FormFieldContainerObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./FormFieldContainerObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Block Object
         * @export
         * @class FieldSet
         * @extends {FormFieldContainerObject}
         */
        //extended by fieldset, block
        class Block extends akioma.swat.FormFieldContainerObject {
        }
        swat.Block = Block;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./FormFieldContainerObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * FieldSet Object
         * @export
         * @class FieldSet
         * @extends {FormFieldContainerObject}
         */
        class FieldSet extends akioma.swat.FormFieldContainerObject {
            get formDynObject() {
                if (!this._formDynObject)
                    this._setFormObject();
                return this._formDynObject;
            }
            get formController() {
                if (!this._formController)
                    this._setFormObject();
                return this._formController;
            }
            get formDhx() {
                if (!this._formDhx)
                    this._setFormObject();
                return this._formDhx;
            }
            _setFormObject() {
                this._formDynObject = this._dynObject.getParentOfType('form');
                this._formController = this._formDynObject.controller;
                this._formDhx = this._formController.dhx;
            }
            /**
             * The fieldset collapsed mode if it is collapsed or expanded
             * @type {boolean}
             */
            get collapsed() {
                return this._controller.isCollapsed();
            }
            set collapsed(value) {
                this._controller.setCollapsed(value, true);
            }
        }
        swat.FieldSet = FieldSet;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./FormFieldObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Button Object
           * @export
           * @class Button
           * @extends {FormFieldObject}
           */
        class Button extends akioma.swat.FormFieldObject {
        }
        swat.Button = Button;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./FormFieldObject.ts" />
// todo: check if most of the functionality in datafield should be moved to input.
// toggle might need to inherit input in this case.
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Input Data Fields Base Class
         * @export
         * @class DataField
         * @extends {VisualObject}
         */
        class DataField extends akioma.swat.FormFieldObject {
            constructor() {
                super(...arguments);
                /**
                 * Whether the validation should be called on value set, screenValue
                 */
                this.enableLiveValidation = true;
            }
            /**
             * Returns whether should ignore validation event or not.
             * @type {boolean}
             */
            get ignoreValidateEvent() {
                return this._controller.ignoreValidateEvent;
            }
            /**
             * Sets whether should ignore validation event or not.
             * @param {boolean} value New value
             */
            set ignoreValidateEvent(value) {
                this._controller.ignoreValidateEvent = value;
            }
            /**
             * The form field linked datasource
             * @readonly
             * @type {DataSource}
             */
            get dataSource() {
                if (!this._dataSource)
                    this._dataSource = this.form.dataSource;
                return this._dataSource;
            }
            /**
             * The form field screen value
             * @type {*}
             */
            get screenValue() {
                return this._controller.getValue();
            }
            set screenValue(value) {
                this._controller.setValue(value);
                if (this.enableLiveValidation)
                    this.formController.validateField(this.name);
            }
            /**
             * For use in the valuechanged event. The current value.
             * type {*}
             */
            get currentValue() {
                if (!this._dynObject.akEvent)
                    return; // undefined
                return this._dynObject.akEvent.currentValue;
            }
            /**
             * For use in the valuechanged event. The current value native.
             * type {*}
             */
            get currentValueNative() {
                if (!this._dynObject.akEvent)
                    return; // undefined
                return this._dynObject.akEvent.currentValueNative;
            }
            /**
             * For use in the valuechanged event. The last value.
             * type {*}
             */
            get lastValue() {
                if (!this._dynObject.akEvent)
                    return; // undefined
                return this._dynObject.akEvent.lastValue;
            }
            /**
             * The linked datasource field value
             * @type {*}
             */
            get dataValue() {
                return this.dataSource.getValue(this.name);
            }
            set dataValue(value) {
                this.dataSource.setValue(this.name, value);
            }
            /**
             * Returns true if the field value has been changed
             * @readonly
             * @example Field.changed
             * @type {boolean}
             */
            get changed() {
                return this.formController.getFieldHasChanges(this.name);
            }
            /**
             * The form field required mode
             * @type {boolean}
             */
            get required() {
                // there is no *public* dhx function or property for getting the required mode
                return this.formDhx._getItemNode(this.name)._required;
            }
            set required(value) {
                this.formController.setRequired(this.name, value);
            }
            /**
             * Returns the form field validation type rule
             * @returns {*} The validation rule
             */
            getValidationRule(rule) {
                return this.formController.getValidationRule(this.name, rule);
            }
            /**
             * Returns all the form field validation rules
             * @returns {*} The validation rules
             */
            getValidationRules() {
                return this.formController.getValidationRules(this.name);
            }
            /**
             * Set form field validation rule (new or existing)
             * @param {string} opts.rule The rule type i.e. 'required', 'minlength', 'maxlength' or 'notequal'
             * @param {string} opts.smartmessage The smartmessage <group>-<num> e.g. 'valmsg-121'
             * @param {*} opts.value The validation value
             */
            setValidationRule(opts) {
                this.formController.setValidationRule(this.name, {
                    type: opts.type,
                    msg: opts.smartmessage,
                    val: opts.value,
                    triggerValidation: opts.triggerValidation
                });
            }
            /**
             * Delete form field validation rule
             * @param {string} rule The rule type i.e. 'required', 'minlength', 'maxlength' or 'notequal'
             */
            deleteValidationRule(rule) {
                this.formController.deleteValidationRule(this.name, rule);
            }
        }
        swat.DataField = DataField;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./DataField.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Calendar Object
           * @export
           * @class Calendar
           * @extends {DataField}
           */
        class Calendar extends akioma.swat.DataField {
            /**
                 * Formatted value of a date object
                 * type {*}
                 */
            formattedDateValue(value) {
                return this._controller.getFormattedDate(value);
            }
            /**
                 * Unformatted value (date object) of a formatted date string
                 * type {*}
                 */
            unformattedDateValue(value) {
                return this._controller.getUnformattedDate(value);
            }
        }
        swat.Calendar = Calendar;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./DataField.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * ComboBox Object
           * @export
           * @class ComboBox
           * @extends {DataField}
           */
        class ComboBox extends akioma.swat.DataField {
            /**
                 * The combobox field screen value
                 * @type {*}
                 */
            get screenValue() {
                return this._controller.getValue('desc');
            }
            set screenValue(value) {
                return; // do nothing
            }
            /**
                 * The combobox field key value
                 * @type {*}
                 */
            get keyValue() {
                return this._controller.getValue('id');
            }
            set keyValue(value) {
                this._controller.setValue(value);
            }
            /**
                 * The combobox field readonly mode
                 * @type {boolean}
                 */
            get readonly() {
                return !this.enabled;
            }
            set readonly(value) {
                this.enabled = !value;
            }
        }
        swat.ComboBox = ComboBox;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./DataField.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Editor Object
           * @export
           * @class Editor
           * @extends {DataField}
           */
        class Editor extends akioma.swat.DataField {
        }
        swat.Editor = Editor;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./DataField.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Input Object
           * @export
           * @class Input
           * @extends {DataField}
           */
        class Input extends akioma.swat.DataField {
        }
        swat.Input = Input;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./DataField.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Toggle Object
           * @export
           * @class Toggle
           * @extends {DataField}
           */
        class Toggle extends akioma.swat.DataField {
            /**
             * The toggle field screen value
             * @type {boolean}
             */
            get screenValue() {
                return this.checked;
            }
            set screenValue(value) {
                this.checked = value;
            }
            /**
             * The toggle field checked state
             * @type {boolean}
             */
            get checked() {
                return this._controller.getCurrentValueToggleBox();
            }
            set checked(value) {
                this._controller.setValue(value ? 'yes' : 'no');
                if (this.enableLiveValidation)
                    this.formController.validateField(this.name);
            }
            /**
             * The toggle field checked state. This should be the correct getter.
             * Didn't replace get checked() because it would require heavy refactoring
             * on OSIV side. (see CLA-49)
             * @type {boolean}
             */
            get isChecked() {
                return this._controller.getCurrentValueToggleBox();
            }
        }
        swat.Toggle = Toggle;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./DataField.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * TwoState Object
           * @export
           * @class TwoState
           * @extends {DataField}
           */
        class TwoState extends akioma.swat.DataField {
        }
        swat.TwoState = TwoState;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../DataField.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * SmartField Object Base Class
           * @export
           * @class SmartFieldObject
           * @extends {DataField}
           */
        class SmartFieldObject extends akioma.swat.DataField {
        }
        swat.SmartFieldObject = SmartFieldObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./SmartFieldObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * DynSelect Object
         * @export
         * @class DynSelect
         * @extends {SmartFieldObject}
         */
        class DynSelect extends akioma.swat.SmartFieldObject {
            /**
             * The dynselect field screen value.
             * Note that screenValue can only be updated with null, undefined or ""
             * to clear the dynSelect and its keyValue.
             * @type {*}
             */
            get screenValue() {
                return this._controller.getValue('desc');
            }
            /**
             * Set the dynselect field screen value.
             * @type {*}
             */
            set screenValue(value) {
                if (value === null || value === undefined || value === '') {
                    this.clearSelect();
                    return;
                }
                return;
            }
            /**
             * The dynselect key field name
             * @type {*}
             */
            get keyName() {
                const opt = this._controller.opt;
                const name = (opt.lookupKeyValueBinding && opt.lookupKeyValueBinding.toLowerCase() !== '_self' ? opt.lookupKeyValueBinding : this.name);
                return name;
            }
            /**
             * The dynselect field key value
             * @type {*}
             */
            get keyValue() {
                return this._controller.getValue('id');
            }
            set keyValue(value) {
                if (value === null || value === undefined || value === '') {
                    this.clearSelect();
                    return;
                }
                this._controller.dynSelectControl.positionToRecord(value);
            }
            /**
             * Async set key value. Sets the key value and returns a promise that resolves when the key value is set.
             * This method is used for positioning a dynselect on an exact result (or multiple results). The outcome is the same as selecting a result in the dropdown list automatically.
             * @param  {any} value If String or number, it represents the KeyValue value used for filtering using a FetchByUniqueKey NamedQuery. </br>
             * If Array of Objects, it represents the new data that will be set in dynSelect
             * @example
             * async function foo(eventSource: akioma.swat.DynSelect) {
             *   await eventSource.setKeyValue('S');
             *   console.log(eventSource.keyValue);
             * }
             * @type {*}
             */
            setKeyValue(value) {
                if (value === null || value === undefined || value === '') {
                    this.clearSelect();
                    return Promise.resolve(null);
                }
                // return window.akioma.dynSelect.positionToRecord(this._controller, value);
                return this._controller.dynSelectControl.positionToRecord(value);
            }
            /**
             * Clears the dynselect field screen value.
             * Note that the dynselect datasource key value is synchronized with the screen value
             * so clearing the screen will set the datasource key value to null
             */
            clearSelect() {
                return __awaiter(this, void 0, void 0, function* () {
                    // clear screen value
                    try {
                        yield this._controller.setValue('');
                    }
                    catch (error) {
                        window.akioma.log.error(error);
                    }
                    this._controller.val.id = this._controller.defaultEmptyValue;
                    this._controller.val.desc = '';
                    if (!this._controller.bPosRecord)
                        this._controller.oPositionedElement = null;
                    // clear key value
                    // note that there are cases where a form is not linked to a datasource
                    if (this.dataSource)
                        this.dataSource.setValue(this.keyName, null);
                    // clear the lookup datasource
                    if (this.lookupDataSource)
                        this.lookupDataSource.closeQuery();
                    // call akvalidate event
                    if (this._controller.opt.validateEvent && !this._controller.ignoreValidateEvent)
                        window.app.controller.callAkiomaCode(this._controller, this._controller.opt.validateEvent);
                });
            }
            /**
             * Method to clear the select lookup controls
             */
            clearSelectLookupControls() {
                this.controller.clearSelectLookupControls();
            }
            /**
             * The dynselect field readonly mode
             * @type {boolean}
             */
            get readonly() {
                return !this.enabled;
            }
            set readonly(value) {
                this.enabled = !value;
            }
            /**
             * The lookup datasource for this dynselect field
             * @readonly
             * @type {DataSource}
             */
            get lookupDataSource() {
                if (!this._lookupDataSource)
                    this._lookupDataSource = (akioma.swat.SwatFactory.createSwatObject(this._controller.businessEntity));
                return this._lookupDataSource;
            }
            /**
             * Helper method for clearing the lookup datasource filter.
             * Equivalent to dynSelect.lookupDataSource.clearFilter().
             */
            clearFilter() {
                this.lookupDataSource.clearFilter();
            }
            /**
             * Helper method for adding a filter to the lookup datasource filter (top level AND filter).
             * Equivalent to dynSelect.lookupDataSource.addFilter().
             * @param name The field name
             * @param operator The filter operator
             * @param value The filter value
             * @param unique If true, adds a new unique condition that will overwrite any conditions with the same field name. If false, just adds a new condition
             */
            addFilter(name, operator, value, unique) {
                this.lookupDataSource.addFilter(name, operator, value, unique);
            }
            /**
             * Helper method to check if a filter exists in the lookup datasource (top level AND filter).
             * Equivalent to dynSelect.lookupDataSource.hasFilter().
             * @param name The field name
             * @param operator The filter operator
             * @param value The filter value
             * @returns {boolean}
             */
            hasFilter(name, operator, value) {
                return this.lookupDataSource.hasFilter(name, operator, value);
            }
            /**
             * Helper method to clear the lookup datasource sorting.
             * Equivalent to dynSelect.lookupDataSource.clearSort().
             */
            clearSort() {
                this.lookupDataSource.clearSort();
            }
            /**
             * Helper method that returns if a field (and optional direction) are in the lookup datasource sorting.
             * Equivalent to dynSelect.lookupDataSource.hasSort().
             * @param name The field name (case-insensitive). If no field name is passed, checks if there is any sorting.
             * @param direction "asc" for ascending or "desc" for descending. If no direction is passed, check if only field name exists.
             */
            hasSort(name, direction) {
                return this.lookupDataSource.hasSort(name, direction);
            }
            /**
             * Helper method to sets the sorting in the lookup datasource.
             * Equivalent to dynSelect.lookupDataSource.setSort().
             * @param {array} [sort]
             * @param {string} sort.field The field name
             * @param {string} sort.direction "asc" for ascending or "desc" for descending
             */
            setSort(sort) {
                this.lookupDataSource.setSort(sort);
            }
            /**
             * Helper method to get the lookup datasource current sorting.
             * Equivalent to dynSelect.lookupDataSource.getSort().
             */
            getSort() {
                return this.lookupDataSource.getSort();
            }
            /**
             * Helper method to set the lookup datasource named query parameter.
             * Equivalent to dynSelect.lookupDataSource.setNamedQueryParam()
             * @param {string} query The parameter query name
             * @param {string} name The parameter field name
             * @param {*} value The parameter value
             * @param {string} type The parameter type
             */
            setNamedQueryParam(query, name, value, type) {
                this.lookupDataSource.setNamedQueryParam(query, name, value, type);
            }
            /**
             * Helper method for getting a field value in the lookup datasource.
             * Equivalent to dynSelect.lookupDataSource.getValue("myfield").
             * @param {string} name The form field name (case-insensitive)
             * @returns {*}
             */
            getFieldValue(name) {
                return this.lookupDataSource.getValue(name);
            }
            /**
             * Helper method for setting a field value in the lookup datasource.
             * Equivalent to dynSelect.lookupDataSource.setValue("myfield", "value").
             * @param {string} name The form field name (case-insensitive)
             * @param {*} value The value to set
             */
            setFieldValue(name, value) {
                this.lookupDataSource.setValue(name, value);
            }
            /**
             * Gets BusinessEntity data for selected record in dynSelect or the record selected from chooseWindow.
             * @returns {Object} Returns record data
             */
            getSelectedRecord() {
                return this._controller.getSelectedRecord();
            }
            /**
             * Removes values from a multiple dynSelect.
             * @param {string | string[]} values The values to remove from the dynSelect (case-insensitive)
             */
            removeSelection(values) {
                this._controller.removeSelection(values);
            }
            /**
             * Get the typed text inside the dynselect.
             * @instance
             * @memberof DynSelect
             * @returns {string}
             */
            get typedValue() {
                return this._controller.typedValue;
            }
            /**
             * Method used for getting the count of the results from the results list.
             * @instance
             * @memberOf ak_dynselect
             * @returns {number}
             */
            getResultsCount() {
                return this._controller.getResultsCount();
            }
            /**
             * Show a footer item from the dynselect dropdown footer by the item name.
             * @instance
             * @memberOf ak_dynselect
             * @param {string} itemName
             */
            showFooterItem(itemName) {
                this._controller.showFooterItem(itemName);
            }
            /**
             * Hide a footer item from the dynselect dropdown footer by the item name.
             * @instance
             * @memberOf ak_dynselect
             * @param {string} itemName
             */
            hideFooterItem(itemName) {
                this._controller.hideFooterItem(itemName);
            }
            /**
             * Method to enabling preSelectExistingInput option
             */
            enablePreSelectExistingInput() {
                this._controller.enablePreSelectExistingInput();
            }
            /**
             * Method to disabling preSelectExistingInput option
             */
            disablePreSelectExistingInput() {
                this._controller.disablePreSelectExistingInput();
            }
            /**
             * Method to positioning to a certain record
             */
            positionToRecord(recordId) {
                this.controller.dynSelectControl.positionToRecord(recordId);
            }
        }
        swat.DynSelect = DynSelect;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./SmartFieldObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * RichText Object
           * @export
           * @class RichText
           * @extends {SmartFieldObject}
           */
        class RichText extends akioma.swat.SmartFieldObject {
            /**
             * The form field screen value
             * @type {*}
             */
            get screenValue() {
                // for ak_ittext
                if (this._controller.getValueFormatted)
                    return this._controller.getValueFormatted();
                else
                    return this._controller.getValue();
            }
            set screenValue(value) {
                this._controller.setValue(value);
                if (this.enableLiveValidation)
                    this.formController.validateField(this.name);
            }
            /**
             * Returns the plain text value unlike screenValue that returns the formatted HTML value
             * @readonly
             * @type {string}
             */
            get plainValue() {
                return this._controller.getValue('ascii');
            }
        }
        swat.RichText = RichText;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./SmartFieldObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Translatable Object
           * @export
           * @class Translatable
           * @extends {SmartFieldObject}
           */
        class Translatable extends akioma.swat.SmartFieldObject {
        }
        swat.Translatable = Translatable;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../VisualObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Grid Column Base Class
         * @export
         * @class GridCol
         * @extends {VisualObject}
         */
        class GridCol extends akioma.swat.VisualObject {
            get gridController() {
                if (!this._gridController)
                    this._gridController = this._controller.parent;
                return this._gridController;
            }
            get dynObject() {
                return this.grid.dynObject;
            }
            get gridDhx() {
                if (!this._gridDhx)
                    this._gridDhx = this.gridController.dhx;
                return this._gridDhx;
            }
            get colIdx() {
                this._colIdx = this.gridDhx.getColIndexById(this.name.toLowerCase());
                return this._colIdx;
            }
            get rowId() {
                this._rowId = this._controller.rowId;
                return this._rowId;
            }
            /**
             * Returns whether should ignore validation event or not.
             * @type {boolean}
             */
            get ignoreValidateEvent() {
                return this._controller.ignoreValidateEvent;
            }
            /**
             * Sets whether should ignore validation event or not.
             * @param {boolean} value New value
             */
            set ignoreValidateEvent(value) {
                this._controller.ignoreValidateEvent = value;
            }
            /**
             * The grid column grid object
             * @readonly
             * @type {Grid}
             */
            get grid() {
                if (!this._grid)
                    this._grid = (akioma.swat.SwatFactory.createSwatObject(this.gridController));
                return this._grid;
            }
            /**
             * The enabled property for the column
             * @readonly
             * @type {boolean}
             */
            get enabled() {
                return this._controller.isEnabled();
            }
            /**
             * The isEnabled property for the column
             * @readonly
             * @param {boolean}
             */
            set enabled(value) {
                this._controller.setEnabled(value);
            }
            /**
             * The grid column linked datasource
             * @readonly
             * @type {DataSource}
             */
            get dataSource() {
                if (!this._dataSource)
                    this._dataSource = this.grid.dataSource;
                return this._dataSource;
            }
            /**
             * The grid column lookup datasource
             */
            get lookupDataSource() {
                if (!this._lookupDataSource)
                    this._lookupDataSource = (akioma.swat.SwatFactory.createSwatObject(this._controller.businessEntity));
                return this._lookupDataSource;
            }
            /**
             * The grid column screen value
             * @readonly
             * @type {*}
             */
            get screenValue() {
                return this._controller.getValue();
            }
            /**
             * The grid column screen value in filter
             * @returns {string}
             */
            get screenValueFilter() {
                return this._controller.getValueFilter();
            }
            /**
             * The grid column screen value in filter
             * @param {string}
             */
            set screenValueFilter(value) {
                this._controller.setValueFilter(value);
            }
            /**
             * The grid column lookup key value
             * @readonly
             * @type {*}
             */
            get lookupKeyValue() {
                return this._controller.getLookupKey();
            }
            /**
             * The linked datasource field value
             * @readonly
             * @type {*}
             */
            get dataValue() {
                return this.dataSource.getValue(this.name);
            }
            /**
             * The grid column readonly mode
             * @readonly
             * @type {boolean}
             */
            get readonly() {
                return this.gridDhx.getColType(this.colIdx).split(',').includes('ro');
            }
            /**
             * The grid column hidden mode (opposite of visible)
             * @readonly
             * @type {boolean}
             */
            get hidden() {
                return this.gridDhx.isColumnHidden(this.colIdx);
            }
            /**
             * The grid column visible mode (opposite of hidden)
             * @readonly
             * @type {boolean}
             */
            get visible() {
                return !this.hidden;
            }
            /**
             * The grid column label
             * @readonly
             * @type {string}
             */
            get label() {
                return this.gridDhx.getHeaderCol(this.colIdx);
            }
        }
        swat.GridCol = GridCol;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../VisualObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Layout Base Class
           * @export
           * @class LayoutObject
           * @extends {VisualObject}
           */
        class LayoutObject extends akioma.swat.VisualObject {
            /**
                 * Gets a descendent form object by name
                 * @param {string} name The object name (case-insensitive)
                 * @returns {Form}
                 */
            getForm(name) {
                const form = this.getObject(name);
                if (form instanceof akioma.swat.Form)
                    return form;
                else
                    return null;
            }
            /**
                 * Gets a descendent grid object by name
                 * @param {string} name The object name (case-insensitive)
                 * @returns {Grid}
                 */
            getGrid(name) {
                const grid = this.getObject(name);
                if (grid instanceof akioma.swat.Grid)
                    return grid;
                else
                    return null;
            }
            /**
                 * Gets a descendent tabbar object by name
                 * @param {string} name The object name (case-insensitive)
                 * @returns {Tabbar}
                 */
            getTabbar(name) {
                const tabbar = this.getObject(name);
                if (tabbar instanceof akioma.swat.Tabbar)
                    return tabbar;
                else
                    return null;
            }
            /**
                 * Gets a descendent ribbon object by name
                 * @param {string} name The object name (case-insensitive)
                 * @returns {akioma.swat.Ribbon}
                 */
            getRibbon(name) {
                const ribbon = !name
                    ? this.getFirstChildByType('ribbon') : this.getObject(name);
                if (ribbon instanceof akioma.swat.Ribbon)
                    return ribbon;
                else
                    return null;
            }
            /**
                 * Gets a descendent toolbar object by name
                 * @param {string} name The object name (case-insensitive)
                 * @returns {akioma.swat.Toolbar}
                 */
            getToolbar(name) {
                const toolbar = this.getObject(name);
                if (toolbar instanceof akioma.swat.Toolbar)
                    return toolbar;
                else
                    return null;
            }
            /**
                 * Gets a descendent scheduler object by name
                 * @param {string} name The object name (case-insensitive)
                 * @returns {akioma.swat.Scheduler}
                 */
            getScheduler(name) {
                const scheduler = this.getObject(name);
                if (scheduler instanceof akioma.swat.Scheduler)
                    return scheduler;
                else
                    return null;
            }
            /**
                 * Gets a descendent docviewer object by name
                 * @param {string} name The object name (case-insensitive)
                 * @returns {akioma.swat.DocViewer}
                 */
            getDocViewer(name) {
                const docViewer = this.getObject(name);
                if (docViewer instanceof akioma.swat.DocViewer)
                    return docViewer;
                else
                    return null;
            }
            /**
                 * Gets a descendent datasource object by name
                 * @param {string} name The object name (case-insensitive)
                 * @returns {DataSource}
                 */
            getDataSource(name) {
                const dataSource = this.getObject(name);
                if (dataSource instanceof akioma.swat.DataSource)
                    return dataSource;
                else
                    return null;
            }
            /**
                 * Gets a descendent frame object by name
                 * @param {string} name The object name (case-insensitive)
                 * @returns {akioma.swat.Frame}
                 */
            getFrame(name) {
                const frame = this.getObject(name);
                if (frame instanceof akioma.swat.Frame)
                    return frame;
                else
                    return null;
            }
            /**
                 * Clears hasChanges (dirty state)
                 */
            clearHasChanges() {
                const dataSources = [];
                (function fillDataSources(controller) {
                    if (controller.childs) {
                        controller.childs.forEach((child) => {
                            switch (child.view) {
                                case 'businessEntity':
                                case 'businessEntity2':
                                    dataSources.push(child);
                                    break;
                                case 'form':
                                case 'datagrid2':
                                    break;
                                default:
                                    fillDataSources(child);
                            }
                        });
                    }
                })(this._controller);
                dataSources.forEach((dataSource) => {
                    dataSource.clearHasChanges();
                });
            }
        }
        swat.LayoutObject = LayoutObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./LayoutObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * ContainerLayoutObject
         * @export
         * @class ContainerLayoutObject
         * @extends {LayoutObject}
         */
        class ContainerLayoutObject extends akioma.swat.LayoutObject {
            /**
             * The window PRIMARYSDO linked datasource
             * @readonly
             * @type {akioma.swat.DataSource}
             */
            get primaryDataSource() {
                if (!this._primaryDataSource)
                    this._primaryDataSource = this.getLink('PRIMARYSDO:TARGET');
                return this._primaryDataSource;
            }
            /**
             * Retrive customData of a ak_frame object
             * @memberof ContainerLayoutObject
             * @returns {object|string}
             * @instance
             */
            get customData() {
                return this.dynObject.container.controller.customData;
            }
            /**
             * Sets Custom data
             * @memberof ContainerLayoutObject
             * @param {object|string} customData
             * @returns {void}
             * @instance
             */
            setCustomData(customData) {
                this.dynObject.container.controller.customData = customData;
            }
        }
        swat.ContainerLayoutObject = ContainerLayoutObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./ContainerLayoutObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Frame Object
           * @export
           * @class Frame
           * @extends {ContainerLayoutObject}
           */
        class Frame extends akioma.swat.ContainerLayoutObject {
        }
        swat.Frame = Frame;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        let MasterModes;
        (function (MasterModes) {
            MasterModes["TASKBAR_MODE"] = "taskbar-mode";
            MasterModes["DESKTOP_MODE"] = "desktop-mode";
        })(MasterModes || (MasterModes = {}));
        /**
         * MasterLayout Object
         * @export
         * @class MasterLayout
         */
        class MasterLayout {
            static get internalObject() {
                return window.akioma.MasterLayout;
            }
            /*
            * Property used to keep track of the last focused window; used to deactivate focusTrap;
            */
            static get lastActiveWindow() {
                return MasterLayout.internalObject.lastActiveWindow;
            }
            /**
             * Property used for storing base layout object loaded
             */
            static baseLayoutObject() {
                return MasterLayout.internalObject.baseLayoutObject;
            }
            /**
             * Method to toggle between desktop mode and taskbar mode
             * @param isDesktop If Desktop mode should be active MasterModes.DESKTOP_MODE = true
             */
            static toggleDesktop(isDesktop) {
                MasterLayout.internalObject.toggleDesktop(isDesktop);
            }
            /**
             * Method for returning base layout object loaded
             */
            static getBaseLayoutObject() {
                return MasterLayout.internalObject.getBaseLayoutObject();
            }
            /**
             * Method for launching base layout object
             */
            static launchBaseLayoutObject() {
                return __awaiter(this, void 0, void 0, function* () {
                    MasterLayout.internalObject.launchBaseLayoutObject();
                });
            }
            static getBaseLayout() {
                return MasterLayout.internalObject.getBaseLayout();
            }
            /**
             * Method for finding all windows that match a given name
             * @param windowName Instance name of window
             */
            static findWindowsByName(windowName) {
                return MasterLayout.internalObject.findWindowsByName(windowName);
            }
            /**
             * Method for finding all windows in wait state
             * @return {Array}
             */
            static getWindowsInWaitState() {
                return MasterLayout.internalObject.getWindowsInWaitState();
            }
            /**
             * Method to find window by id
             * @param id window id
             */
            static findWindowById(id) {
                return MasterLayout.internalObject.findWindowById(id);
            }
            /**
             * Method to return master state
             * @returns DesktopMode
             */
            static getMasterState() {
                return MasterLayout.internalObject.getMasterState();
            }
            /**
             * Method for checking if User is currently in Desktop mode
             */
            static isDesktopMode() {
                return MasterLayout.internalObject.isDesktopMode();
            }
            /**
             * Method for checking if User is currently in Taskbar mode
             */
            static isTaskbarMode() {
                return MasterLayout.internalObject.isTaskbarMode();
            }
            /**
             * Method for setting the active Master State
             * @param state Type of state from DesktopMode
             */
            static setMasterState(state) {
                MasterLayout.internalObject.setMasterState(state);
            }
            /**
             * Method for setting the Last Active Window
             * @param lastActiveWin Last Active Window Window
             */
            static setLastActiveWindow(lastActiveWin) {
                MasterLayout.internalObject.setLastActiveWindow(lastActiveWin);
            }
            /**
             * Method for setting Activating Last Window Focus-Trap
             */
            static enableLastFocusTrap() {
                MasterLayout.internalObject.enableLastFocusTrap();
            }
            /**
             * Method for setting Deactivating Last Window Focus-Trap
             * @param {Object} deactivateOptions
             */
            static disableLastFocusTrap(deactivateOptions) {
                MasterLayout.internalObject.disableLastFocusTrap(deactivateOptions);
            }
            /**
             * Method for checking if given window is in taskbar mode
             */
            static isWindowInTaskbarMode(windowObject) {
                return MasterLayout.internalObject.isWindowInTaskbarMode(windowObject);
            }
            /**
             * Method for getting top most window
             */
            static getTopMostWindow() {
                return MasterLayout.internalObject.getTopMostWindow();
            }
            /**
             * Method for getting top most window from Taskbar Mode
             */
            static getTaskbarTopMostWindow() {
                return MasterLayout.internalObject.getTaskbarTopMostWindow();
            }
        }
        swat.MasterLayout = MasterLayout;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./LayoutObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * PopOver Object
           * @export
           * @class PopOver
           * @extends {LayoutObject}
           */
        class PopOver extends akioma.swat.LayoutObject {
        }
        swat.PopOver = PopOver;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./ContainerLayoutObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Window Object.
           * Note that the desktop windows are windows not frames.
           * @export
           * @class Window
           * @extends {ContainerLayoutObject}
           */
        class Window extends akioma.swat.ContainerLayoutObject {
            get isMainDesktopWindow() {
                return this._controller.isAutostartObjectsWindow === true;
            }
            get isDesktopWindow() {
                return this._dynObject.parent && this._dynObject.parent.controller.isAutostartObjectsWindow === true;
            }
            /**
                 * The caller object that this window was launched from
                 * @readonly
                 * @type {SwatObject}
                 */
            get caller() {
                if (!this._controller.caller)
                    return null;
                if (!this._caller)
                    this._caller = akioma.swat.SwatFactory.createSwatObject(this._controller.caller);
                return this._caller;
            }
            /**
                 * Gets the window title
                 * @readonly
                 * @type {string}
                 */
            get title() {
                return this._controller.getTitle();
            }
            /**
                 * Sets the window title
                 * @type {string}
                 */
            set title(value) {
                const opt = this._controller.opt;
                if (this.isMainDesktopWindow || this.isDesktopWindow)
                    return;
                this.controller.setTitle(value);
                if (!opt.titleShort)
                    this.shortTitle = value;
            }
            /**
                 * The window short title used in the task bar
                 * @example
                 * MyWindow.shortTitle = 'Angebot {{selfno}}';
                 * @type {string}
                 */
            get shortTitle() {
                return this._controller.opt.titleShort || this._controller.opt.TITLE;
            }
            set shortTitle(value) {
                const opt = this._controller.opt;
                opt.titleShort = value;
            }
            /**
             * Closes the window
             */
            close() {
                if (this.isMainDesktopWindow || this.isDesktopWindow)
                    return;
                this._controller.close();
            }
            /**
             * Method for setting
             * @param closingBehaviour
             */
            setClosingBehaviour(closingBehaviour) {
                this._controller.setClosingBehaviour(closingBehaviour);
            }
            /**
             * Method for getting current window closing behaviour
             * @returns {string}
             */
            getClosingBehaviour() {
                return this._controller.getClosingBehaviour();
            }
            /**
             * Returns the bottommost window
             */
            getBottommostWindow() {
                return this._controller.getBottommostWindow();
            }
            /**
             * Returns the topmost window
             */
            getTopmostWindow() {
                return this._controller.getTopmostWindow();
            }
            /**
             * Method for setting current window active
             */
            setActiveWindow() {
                return this._controller.setActiveWindow();
            }
            /**
             * Sets window as top most window
             */
            bringToTop() {
                return this._controller.bringToTop();
            }
            /**
                 * Returns the customData of the window
                 */
            getCustomData() {
                return this._controller.getCustomData();
            }
            /**
             * Add an window message and return the index of the message
             * @param  {PanelMessage} msg The panel message
             * @param  {string} msg.text The panel message text
             * @param  {string} msg.type The panel message type i.e.
             * info, warning, error, success
             * @instance
             * @memberOf Window
             * @return {number} the index of the message
             */
            addWindowMessage(msg) {
                return this._controller.addWindowMessage(msg);
            }
            /**
             * Remove a window message from a controller by the given id
             * @param  {number} id
             * @instance
             * @memberOf Window
             * @returns {void}
             */
            removeWindowMessage(id) {
                this._controller.removeWindowMessage(id);
            }
            /**
             * Remove all window messages from a controller
             * @instance
             * @memberOf Window
             * @returns {void}
             */
            clearWindowMessages() {
                this._controller.clearWindowMessages();
            }
        }
        swat.Window = Window;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../VisualObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Navigation Object Base Class
           * @export
           * @class NavigationObject
           * @extends {VisualObject}
           */
        class NavigationObject extends akioma.swat.VisualObject {
        }
        swat.NavigationObject = NavigationObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./NavigationObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Ribbon Object
           * @export
           * @class Ribbon
           * @extends {NavigationObject}
           */
        class Ribbon extends akioma.swat.NavigationObject {
            constructor() {
                super(...arguments);
                this._items = [];
            }
            /**
                 * The ribbon item and items block names
                 */
            get items() {
                if (this._items.length === 0)
                    this._setItems();
                return this._items;
            }
            get itemsMap() {
                if (this._items.length === 0)
                    this._setItems();
                return this._itemsMap;
            }
            _setItems() {
                this._items = Object.keys(this._controller.dhx._items);
                this._itemsMap = {};
                this._items.forEach(item => {
                    this._itemsMap[item.toLowerCase()] = item;
                });
            }
            fixNameCasing(name) {
                return this.itemsMap[name.toLowerCase()];
            }
            /**
                 * Returns of the item or items block exists in the ribbon
                 * @param {string} name The name of the item or items block (case-insensitive)
                 */
            hasItem(name) {
                if (this.itemsMap[name.toLowerCase()])
                    return true;
                return false;
            }
            /**
                 * Hides a ribbon item or items block
                 * @param {string} name The name of the item or items block (case-insensitive)
                 */
            hideItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.dhx.hide(name);
            }
            /**
                 * Hides a ribbon subitem
                 * @param {string} itemName The name of the item (case-insensitive)
                 * @param {string} subitemName The name of the subitem (case-insensitive)
                 */
            hideSubitem(itemName, subitemName) {
                if (!itemName || !subitemName)
                    return;
                this._controller.hideSubitem(itemName, subitemName);
            }
            /**
                 * Shows a ribbon item or items block
                 * @param {string} name The name of the item or items block (case-insensitive)
                 */
            showItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.dhx.show(name);
            }
            /**
                 * Shows a ribbon subitem
                 * @param {string} itemName The name of the item (case-insensitive)
                 * @param {string} subitemName The name of the subitem (case-insensitive)
                 */
            showSubitem(itemName, subitemName) {
                if (!itemName || !subitemName)
                    return;
                this._controller.showSubitem(itemName, subitemName);
            }
            /**
                 * Returns true if the ribbon item or items block is visible
                 * @param {string} name The name of the item or items block (case-insensitive)
                 */
            isItemVisible(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                return this._controller.dhx.isVisible(name);
            }
            /**
                 * Enables a ribbon item or items block
                 * @param {string} name The name of the item or items block (case-insensitive)
                 */
            enableItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.enableItem(name);
            }
            /**
                 * Enables a ribbon subitem
                 * @param {string} itemName The name of the item (case-insensitive)
                 * @param {string} subitemName The name of the subitem (case-insensitive)
                 */
            enableSubitem(itemName, subitemName) {
                if (!itemName || !subitemName)
                    return;
                this._controller.enableSubitem(itemName, subitemName);
            }
            /**
                 * Disables a ribbon item or items block
                 * @param {string} name The name of the item or items block (case-insensitive)
                 */
            disableItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.disableItem(name);
            }
            /**
                 * Disables a ribbon subitem
                 * @param {string} itemName The name of the item (case-insensitive)
                 * @param {string} subitemName The name of the subitem (case-insensitive)
                 */
            disableSubitem(itemName, subitemName) {
                if (!itemName || !subitemName)
                    return;
                this._controller.disableSubitem(itemName, subitemName);
            }
            /**
                 * Returns true if the ribbon item or items block is enabled
                 * @param {string} name The name of the item or items block (case-insensitive)
                 */
            isItemEnabled(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                return this._controller.dhx.isEnabled(name);
            }
            /**
                 * Gets the ribbon item or items block label
                 * @param {string} name The name of the item or items block (case-insensitive)
                 */
            getItemLabel(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                return this._controller.getItemText(name);
            }
            /**
                 * Sets the ribbon item or items block label
                 * @param {string} name The name of the item or items block (case-insensitive)
                 * @param {string} label The label to set
                 * @param {boolean} setTooltip Set tooltip with the same value as the label (default is false)
                 */
            setItemLabel(name, label, setTooltip = false) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.setItemText(name, label);
                if (setTooltip)
                    this.setItemTooltip(name, label);
            }
            /**
                 * Gets the ribbon item or items block tooltip
                 * @param {string} name The name of the item or items block (case-insensitive)
                 */
            getItemTooltip(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                return this._controller.getItemToolTip(name);
            }
            /**
                 * Sets the ribbon item or items block tooltip
                 * @param {string} name The name of the item or items block (case-insensitive)
                 * @param {string} tooltip The tooltip to set
                 */
            setItemTooltip(name, tooltip) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.setItemToolTip(name, tooltip);
            }
            /**
                 * Gets the ribbon item by the name
                 * @param {string} name The name of the item or block (case-insensitive)
                 */
            getItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                return this._controller.getItemById(name);
            }
            /**
                 * Gets the selected option from a RibbonCombo
                 * @param {string} name The name of the combo item (case-insensitive)
                 */
            getSelectedOption(name) {
                const combo = this.getItem(name);
                if (combo && combo.controller.view === 'ribboncombo')
                    return combo.controller.getSelectedOption();
                return;
            }
        }
        swat.Ribbon = Ribbon;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./NavigationObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Toolbar Object
           * @export
           * @class Toolbar
           * @extends {NavigationObject}
           */
        class Toolbar extends akioma.swat.NavigationObject {
            constructor() {
                super(...arguments);
                this._items = [];
            }
            /**
             * The toolbar item and items
             */
            get items() {
                if (this._items.length === 0)
                    this._setItems();
                return this._items;
            }
            /**
             * Get the typed text inside the toolbar input.
             * @instance
             * @memberof Toolbar
             * @returns {string}
             */
            get typedValue() {
                return this._controller.typedValue;
            }
            /**
             * Get the input name of the toolbar item that was typed in.
             * @instance
             * @memberof Toolbar
             * @returns {string}
             */
            get inputName() {
                return this._controller.inputName;
            }
            get itemsMap() {
                if (this._items.length === 0)
                    this._setItems();
                return this._itemsMap;
            }
            _setItems() {
                const items = Object.keys(this._controller.dhx.objPull);
                this._itemsMap = {};
                for (const i in items) {
                    const key = items[i].replace(this._controller.dhx.idPrefix, '');
                    this._items.push(key);
                }
                this._items.forEach(item => {
                    this._itemsMap[item.toLowerCase()] = item;
                });
            }
            fixNameCasing(name) {
                return this.itemsMap[name.toLowerCase()];
            }
            /**
             * Enables a toolbar item
             * @param {string} name The name of the item
             */
            enableItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.enableItem(name);
            }
            /**
             * Disables a toolbar item
             * @param {string} name The name of the item
             */
            disableItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.disableItem(name);
            }
            /**
             * Hides a toolbar item
             * @param {string} name The name of the item
             */
            hideItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.hideItem(name);
            }
            /**
             * Shows a toolbar item
             * @param {string} name The name of the item
             */
            showItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                this._controller.showItem(name);
            }
            /**
             * Gets the toolbar item by the name
             * @param {string} name The name of the item (case-insensitive)
             */
            getItem(name) {
                name = this.fixNameCasing(name);
                if (!name)
                    return;
                return this._controller.getItemById(name);
            }
            /**
             * Gets the selected option from a ToolbarCombo
             * @param {string} name The name of the combo item (case-insensitive)
             */
            getSelectedOption(name) {
                const combo = this.getItem(name);
                if (combo && combo.view === 'toolbarcombo')
                    return combo.getSelectedOption();
                return;
            }
        }
        swat.Toolbar = Toolbar;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../NavigationObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Tabbar Object
         * @export
         * @class Tabbar
         * @extends {NavigationObject}
         */
        class Tabbar extends akioma.swat.NavigationObject {
            /**
             * The tabbar current page number
             * @type {number}
             */
            get currentPageNum() {
                return this._controller.currentPageNum();
            }
            set currentPageNum(value) {
                this._controller.setActivePage(value, true);
            }
            /**
             * The tabbar current page key
             * @type {string}
             */
            get currentPageKey() {
                return this._controller.currentPageKey();
            }
            set currentPageKey(value) {
                this._controller.setActivePage(value, true);
            }
            /**
             * Returns a page object
             * @param  {string|integer} pageNum The page key or number
             * @returns {object}
             * @instance
             */
            getPageObject(pageNum) {
                return this._controller.getPage(pageNum);
            }
            /**
             * Sets a page label
             * @param {string|integer} pageNum The page key or number.
             * @param {string} label The label to be set.
             */
            setPageLabel(pageNum, label) {
                this._controller.setPageLabel(pageNum, label);
            }
            /**
             * Gets a page label
             * @param {string|integer} pageNum The page key or number.
             * @returns {string} The label of the page.
             */
            getPageLabel(pageNum) {
                return this._controller.getPageLabel(pageNum);
            }
            /**
             * Enables or disables a page
             * @param pageNum The page key or number
             * @param enabled The enable mode
             */
            setPageEnabled(pageNum, enabled) {
                this._controller.setPageEnabled(pageNum, enabled);
            }
            /**
             * Returns if a page is enabled
             * @param pageNum The page key or number
             */
            isPageEnabled(pageNum) {
                return this._controller.isPageEnabled(pageNum);
            }
            /**
             * Shows or hides a page
             * @param pageNum The page key or number
             * @param visible The visible mode
             */
            setPageVisible(pageNum, visible) {
                this._controller.setPageVisible(pageNum, visible);
            }
            /**
             * Returns if a page is visible
             * @param pageNum The page key or number
             */
            isPageVisible(pageNum) {
                return this._controller.isPageVisible(pageNum);
            }
            /**
             * Sets a page as active
             * @param pageNum The page key or number
             * @param focused The focus mode
             */
            setPageActive(pageNum, focused = true) {
                this._controller.setActivePage(pageNum, focused);
            }
            /**
             * Returns true if there are changes in the page or its descendents
             * @returns {boolean}
             */
            hasPageChanges(pageNum) {
                return this._controller.hasPageChanges(pageNum);
            }
            /**
             * Deprecated method for finding a page by index or pagekey
             * @deprecated
             * @param  {string|integer} value index or PageKey
             * @returns {object}
             * @instance
             */
            fetchPage(value) {
                return this._controller.getPage(value);
            }
        }
        swat.Tabbar = Tabbar;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Tabbar.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Sidebar Object
           * @export
           * @class Sidebar
           * @extends {NavigationObject}
           */
        class Sidebar extends akioma.swat.NavigationObject {
            /**
             * Method for setting the menu id for sidebar items
             * @param {string} menuId Menu structure id
             */
            setMenu(menuId) {
                this.controller.setMenu(menuId);
            }
            /**
             * Method to select sidebar item
             * @param id Index of item
             */
            selectItem(id) {
                return this.controller.selectItem(id);
            }
            /**
             * Method returns true if item is visible on screen
             * @param id Item id
             */
            isItemVisible(id) {
                return this.controller.isItemVisible(id);
            }
            /**
             * Method to collapse item by index
             * @param id Index of item
             */
            collapseItem(id) {
                return this.controller.collapseItem(id);
            }
            /**
             * Method to expand item by index
             * @param id Index of item
             */
            expandItem(id) {
                return this.controller.expandItem(id);
            }
        }
        swat.Sidebar = Sidebar;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../VisualObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Panel Base Class
         * @export
         * @class Panel
         * @extends {VisualObject}
         */
        class PanelSwitcherObject extends akioma.swat.VisualObject {
            /**
             * Method for getting a panel view frame
             * @param {string} viewName The name of the view
             */
            getViewFrame(viewName) {
                const viewFrame = this.controller.getViewFrame(viewName);
                if (!viewFrame)
                    return null;
                return akioma.swat.SwatFactory.createSwatObject(viewFrame);
            }
            /**
             * Returns the active frame view
             * @returns {akioma.swat.Frame | null} The active frame view
             */
            getActiveFrameView() {
                const activeViewFrame = this.controller.getActiveFrameView();
                if (!activeViewFrame)
                    return null;
                return akioma.swat.SwatFactory.createSwatObject(activeViewFrame);
            }
            /**
                 * Switches the view of a panel object to the specified view
             * @param {string} viewName The name of the object
             * @param {akioma.swat.LaunchContainerOptions} [options] The options for the view
             * @instance
             * @memberOf Panel
             * @returns {Promise<akioma.swat.Frame>} The frame object
                 */
            switchView(viewName, options) {
                return __awaiter(this, void 0, void 0, function* () {
                    if (options)
                        options = akioma.swat.App.convertLaunchContainerParams(options);
                    const frame = yield this.controller.switchView(viewName, options);
                    const frameObject = akioma.swat.SwatFactory.createSwatObject(frame);
                    return frameObject;
                });
            }
            /**
             * Determine if provided view name is loaded
             * @param viewName View name
             * @returns {boolean} True if view is loaded
             */
            hasViewLoaded(viewName) {
                return this.controller.hasViewLoaded(viewName);
            }
            /**
             * Returns the current view name
             * @returns {string} The current view name
             */
            getCurrentView() {
                return this.controller.getCurrentView();
            }
        }
        swat.PanelSwitcherObject = PanelSwitcherObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./PanelSwitcherObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Panel Base Class
         * @export
         * @class Panel
         * @extends {VisualObject}
         */
        class Panel extends akioma.swat.PanelSwitcherObject {
            get panelController() {
                if (!this._panelController)
                    this._setPanelObject();
                return this._panelController;
            }
            get panelDhx() {
                if (!this._panelDhx)
                    this._setPanelObject();
                return this._panelDhx;
            }
            _setPanelObject() {
                if (this._controller.view === 'panel') {
                    this._panelController = this._controller;
                    this._panelDhx = this._controller.dhx;
                }
                else {
                    let panel = this._controller.parent;
                    while (panel && panel.view !== 'panel')
                        panel = panel.parent;
                    this._panelController = panel;
                    this._panelDhx = panel.dhx;
                }
            }
            // todo: hiding panel will only work with multiple panels
            /**
             * The panel hidden mode if it is hidden or shown
             * @type {boolean}
             */
            get hidden() {
                const dhx = this.panelDhx;
                return (!dhx.isHeaderVisible() && (dhx.getWidth() === 0 || dhx.getHeight() === 0));
            }
            set hidden(value) {
                if (value === this.hidden)
                    return;
                const dhx = this.panelDhx;
                if (value) {
                    this._lastCollapsed = this.collapsed;
                    this._lastHeaderVisible = dhx.isHeaderVisible();
                    if (dhx.conf.mode === 'h') {
                        this._lastMinHeight = dhx._getMinHeight();
                        this._lastHeight = dhx.getHeight();
                    }
                    else {
                        this._lastMinWidth = dhx._getMinWidth();
                        this._lastWidth = dhx.getWidth();
                    }
                    // the panel must be expanded to hide its header and minimize it
                    if (this._lastCollapsed)
                        this.collapsed = false;
                    if (this._lastHeaderVisible)
                        dhx.hideHeader();
                    if (dhx.conf.mode === 'h') {
                        dhx.setMinHeight(0);
                        dhx.setHeight(0);
                    }
                    else {
                        dhx.setMinWidth(0);
                        dhx.setWidth(0);
                    }
                }
                else {
                    if (dhx.conf.mode === 'h') {
                        dhx.setMinHeight(this._lastMinHeight);
                        dhx.setHeight(this._lastHeight);
                    }
                    else {
                        dhx.setMinWidth(this._lastMinWidth);
                        dhx.setWidth(this._lastWidth);
                    }
                    // the header is shown at the end
                    // because the header cannot be shown if width/height is 0
                    if (this._lastHeaderVisible)
                        dhx.showHeader();
                    // the panel is collapsed at the end
                    // because the panel must be expanded to show its header and maximize it
                    if (this._lastCollapsed)
                        this.collapsed = this._lastCollapsed;
                }
            }
            /**
             * The panel visible mode (opposite of hidden)
             * @type {boolean}
             */
            get visible() {
                return !this.hidden;
            }
            set visible(value) {
                this.hidden = !value;
            }
            /**
             * The panel collapsed mode if it is collapsed or expanded
             * @type {boolean}
             */
            get collapsed() {
                return this.panelDhx.isCollapsed();
            }
            set collapsed(value) {
                if (value)
                    this.panelDhx.collapse();
                else
                    this.panelDhx.expand();
            }
            /**
             * The panel width
             * @type {number}
             */
            get width() {
                return this.panelDhx.getWidth();
            }
            set width(value) {
                if (this.collapsed)
                    this.collapsed = false;
                const dhx = this.panelDhx;
                dhx.showHeader();
                if (value > 0) {
                    dhx.setMinWidth(20);
                    dhx.setWidth(Math.max(value, 20));
                }
                else {
                    dhx.setMinWidth(0);
                    dhx.setWidth(0);
                }
            }
            /**
             * The panel height
             * @type {number}
             */
            get height() {
                return this.panelDhx.getHeight();
            }
            set height(value) {
                if (this.collapsed)
                    this.collapsed = false;
                const dhx = this.panelDhx;
                dhx.showHeader();
                if (value > 0) {
                    dhx.setMinHeight(20);
                    dhx.setHeight(Math.max(value, 20));
                }
                else {
                    dhx.setMinHeight(0);
                    dhx.setHeight(0);
                }
            }
            /**
             * The panel title
             * @type {string}
             */
            get title() {
                return this.panelController.opt.title;
            }
            set title(value) {
                this.panelController.setOption('title', value);
            }
            /**
                 * Method for setting the progress cursor on for this particular object
                 * @param {boolean} bPauseProgressOff A value of true will stop all the future progressOff method calls for this element until reset
                 * @returns {void}
             * @instance
                 * @memberof Panel
                 */
            progressOn(bPauseProgressOff) {
                this.panelController.progressOn(bPauseProgressOff);
            }
            /**
                 * Method for setting the fixed width/height of a panel level object
                 * @param {boolean} fixWidth 'says' to fix the width of the cell (optional)
                 * @param {boolean} fixHeight 'says' to fix the height of the cell (optional)
                 * @returns {void}
             * @instance
                 * @memberof Panel
                 */
            fixSize(fixWidth, fixHeight) {
                this.panelController.fixSize(fixWidth, fixHeight);
            }
            /**
                 * Method for setting the progress cursor off for this particular object
                 * @param {boolean} bPauseProgressOff A value of true will stop all the future progressOff method calls for
                 *  this element until reset
                 * @returns {void}
             * @instance
                 * @memberof Panel
                 */
            progressOff(bPauseProgressOff) {
                this.panelController.progressOff(bPauseProgressOff);
            }
            /**
                 * Hide the header from a panel
                 * @returns {void}
                 * @instance
                 * @memberOf Panel
                 */
            hideHeader() {
                this.panelController.hideHeader();
            }
            /**
                 * Show the header from a panel
                 * @returns {void}
                 * @instance
                 * @memberOf Panel
                 */
            showHeader() {
                this.panelController.showHeader();
            }
            /**
                 * Expand a panel
                 * @returns {void}
                 * @instance
                 * @memberOf Panel
                 */
            expand() {
                this.panelController.expand();
            }
            /**
                 * Collapse a panel
                 * @returns {void}
                 * @instance
                 * @memberOf Panel
                 */
            collapse() {
                this.panelController.collapse();
            }
            /**
                 * Set panel height
             * @param {number}
                 * @returns {void}
                 * @instance
                 * @memberOf Panel
                 */
            setHeight(height) {
                this.panelController.setHeight(height);
            }
            /**
                 * Set panel min height
             * @param {number}
                 * @returns {void}
                 * @instance
                 * @memberOf Panel
                 */
            setMinHeight(height) {
                this.panelController.setMinHeight(height);
            }
            /**
                 * Shows a panelMenu button
             * @param {string} name The button name (SCL menuFunctionCode/menuStructureCode)
             * @instance
             * @memberOf Panel
                 */
            showPanelMenuButton(name) {
                this.panelController.showPanelMenuButton(name);
            }
            /**
                 * Hides a panelMenu button
             * @param {string} name The button name (SCL menuFunctionCode/menuStructureCode)
             * @instance
             * @memberOf Panel
                 */
            hidePanelMenuButton(name) {
                this.panelController.hidePanelMenuButton(name);
            }
        }
        swat.Panel = Panel;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Chart Object
           * @export
           * @class Chart
           * @extends {Panel}
           */
        class Chart extends akioma.swat.Panel {
        }
        swat.Chart = Chart;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Diagram Object
           * @export
           * @class Diagram
           * @extends {Panel}
           */
        class Diagram extends akioma.swat.Panel {
        }
        swat.Diagram = Diagram;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * DocViewer Object
         * @export
         * @class DocViewer
         * @extends {Panel}
         */
        class DocViewer extends akioma.swat.Panel {
            constructor(controller) {
                super(controller);
                this._callbacks = {};
                controller.fireOnCallbackEvent((evt) => {
                    this.processCallbacks(evt);
                });
            }
            get event() {
                var _a;
                return (_a = this.dynObject) === null || _a === void 0 ? void 0 : _a.akEvent;
            }
            /**
             * Calls a docviewer method by messaging the docviewer and returning the response
             * @param {string} methodName The method name
             * @param {*} params The optional parameter array
             * @returns {Promise<any>} Returns a promise with the reponse
             * @example
             * const docViewer = eventSource.window.getDocViewer('MyDocViewer');
             *
             * docViewer.dispatchMethodCall('getPageCount')
             *     .then((numPages) => {
             *         console.log(numPages);
             *     });
             */
            dispatchMethodCall(methodName, params = null) {
                if (params && !(params instanceof Array))
                    params = [params];
                return this.controller.callDocViewerMethod(methodName, params);
            }
            /**
             * Sets a callback function for an event
             * @param {string} eventName The event name. Valid values -
             * "onDocumentLoad", "saveDocument", "saveAnnotation", "saveAsDocument", "uploadDocument", "sendDocument", "switchToTab", "pageChange", "pageCopied", "pagePasted", "pageDeleted", "rotation", "textSelect", "imageLoadFinished", "imageLoadRequested", "annotationCreationCallback";
             * @param {*} callback The callback function
             */
            setCallback(eventName, callback) {
                const name = eventName.toLowerCase();
                if (!this._callbacks[name])
                    this._callbacks[name] = [];
                const callbacks = this._callbacks[name];
                callbacks.push(callback);
            }
            /**
             * Hide toolbar button in docviewer based on given name
             * @param {DocViewerToolbarBtns} name The name of the toolbar button
             * @returns {void}
             */
            hideToolbarButton(name) {
                this.controller.hideToolbarButton(name);
            }
            /**
             * Show toolbar button in docviewer based on given name
             * @param {DocViewerToolbarBtns} name The  name of the toolbar button
             * @returns {void}
             */
            showToolbarButton(name) {
                this.controller.showToolbarButton(name);
            }
            /***
             * Hide Side Toolbar navigation in docviewer
             * @returns {void}
             */
            hideSideToolbar() {
                this.controller.hideSideToolbar();
            }
            /**
             * Shows side Toolbar navigation in docviewer
             * @returns {void}
             */
            showSideToolbar() {
                this.controller.showSideToolbar();
            }
            /**
             * Hides top Toolbar navigation in docviewer
             * @returns {void}
             */
            hideTopToolbar() {
                this.controller.hideTopToolbar();
            }
            /**
             * Shows top Toolbar navigation in docviewer
             * @returns {void}
             */
            showTopToolbar() {
                this.controller.showTopToolbar();
            }
            /**
             * Removes a callback function for an event
             * @param {string} eventName The event name. Valid values -
             * "onDocumentLoad", "saveDocument", "saveAnnotation", "saveAsDocument", "uploadDocument", "sendDocument", "switchToTab", "pageChange", "pageCopied", "pagePasted", "pageDeleted", "rotation", "textSelect", "imageLoadFinished", "imageLoadRequested", "annotationCreationCallback";
             * @param {*} callback The callback function
             */
            unsetCallback(eventName, callback) {
                const name = eventName.toLowerCase();
                if (!this._callbacks[name])
                    return;
                const callbacks = this._callbacks[name];
                const idx = callbacks.indexOf(callback);
                if (idx > -1)
                    callbacks.splice(idx, 1);
            }
            /**
             * Name of the document file to load inside the docviewer control
             * @param {string} value
             */
            setValue(value) {
                return this.controller.setValue(value);
            }
            processCallbacks(evt) {
                const name = evt.eventName.toLowerCase();
                const params = evt.params;
                if (!this._callbacks[name])
                    return;
                const callbacks = this._callbacks[name];
                callbacks.forEach(callback => {
                    callback(params);
                });
            }
        }
        swat.DocViewer = DocViewer;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        const allColors = ['black', 'red', 'yellow', 'blue'];
        class FreeHand extends akioma.swat.Panel {
            save() {
                this.controller.save();
            }
            reset() {
                this.controller.reset();
            }
            undo() {
                this.controller.undo();
            }
            redo() {
                this.controller.redo();
            }
            addText() {
                this.controller.addText();
            }
            selectStrokeColor(value) {
                this.controller.selectStrokeColor(value);
            }
            selectStrokeSize(value) {
                this.controller.selectStrokeSize(value);
            }
            onUploadFileAdd(files) {
                this.controller.onUploadFileAdd(files);
            }
            onUploadComplete(url) {
                this.controller.onUploadComplete(url);
            }
        }
        swat.FreeHand = FreeHand;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Gantt Object
           * @export
           * @class Gantt
           * @extends {Panel}
           */
        class Gantt extends akioma.swat.Panel {
        }
        swat.Gantt = Gantt;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Gauge Object
           * @export
           * @class Gauge
           * @extends {Panel}
           */
        class Gauge extends akioma.swat.Panel {
        }
        swat.Gauge = Gauge;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Graph Editor Object
         * @export
         * @class GraphEditor
         * @extends {Panel}
         */
        class GraphEditor extends akioma.swat.Panel {
        }
        swat.GraphEditor = GraphEditor;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Image Object
           * @export
           * @class Image
           * @extends {Panel}
           */
        class Image extends akioma.swat.Panel {
        }
        swat.Image = Image;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Map Object
           * @export
           * @class Map
           * @extends {Panel}
           */
        class Map extends akioma.swat.Panel {
        }
        swat.Map = Map;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./PanelSwitcherObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Panel Switcher
         * @export
         * @class PanelSwitcher
         * @extends {VisualObject}
         */
        class PanelSwitcher extends akioma.swat.PanelSwitcherObject {
        }
        swat.PanelSwitcher = PanelSwitcher;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Scheduler Object
         * @export
         * @class Scheduler
         * @extends {Panel}
         */
        class Scheduler extends akioma.swat.Panel {
            /**
               * Displays the specified view and date
               * @param {Date} date The date to position the view. null will not change the position.
               * @param {SchedulerView} view The day, week, month or year view. null will not change the view.
               */
            setCurrentView(date, view) {
                this._controller.dhx.setCurrentView(date, view);
            }
            /**
               * Sets the readonly attribute of the scheduler
               * @param {Boolean} readonly True for setting the scheduler as read-only, false for deactivating this setting (default value).
               */
            setReadonly(readonly) {
                this._controller.setReadonly(readonly);
            }
            /**
               * Displays the specified view and date BUT does not fire any events like setCurrentView.
               * You could use updateView to change the scheduler view to week when the screen is displayed before the data has loaded
               * and use setCurrentView to change the date after the data has loaded.
               * @param {Date} date The date to position the view. null will not change the position.
               * @param {SchedulerView} view The day, week, month or year view. null will not change the view.
               */
            updateView(date, view) {
                this._controller.dhx.updateView(date, view);
            }
        }
        swat.Scheduler = Scheduler;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Taskbar Object
         * @export
         * @class Taskbar
        */
        class Taskbar extends akioma.swat.LayoutObject {
            get event() {
                return this._controller.event;
            }
            get events() {
                return this._controller.events;
            }
            /**
             * Method for adding a new taskbar item in Header for External Screens
             * @param options Net taskbar item options, id, icon and title
            */
            addExternalItem(options) {
                this._controller.addExternalItem(options);
            }
            /**
             * Method for removing the External screen taskbar items
             * @param id
            */
            removeExternalItem(id) {
                this._controller.removeExternalItem(id);
            }
            /**
             * Method for clearing up all the external screens
            */
            clearAllExternalScreensOpened() {
                this._controller.clearAllExternalScreensOpened();
            }
            /**
             * Method to remove taskbar item by given id
             * @param id
             */
            removeItem(id) {
                this._controller.removeItem(id);
            }
            /**
             * Method to get taskbar group by id
             * @param id
             */
            getGroupById(id) {
                return this._controller.getGroupById(id);
            }
            /**
             * Method for removing group item by id
             * @param id Group id
             */
            removeGroupById(id) {
                this._controller.removeGroupById(id);
            }
            /**
             * Method to get group has changes state by id
             * @param {string} id
             */
            getGroupHasChangesById(id) {
                return this._controller.getGroupHasChangesById(id);
            }
            /**
             * Method to add taskbar group
             * @param groupData
             */
            addGroup(groupData) {
                this._controller.addGroup(groupData);
            }
            /**
             * Method to add taskbar item
             * @param itemData
             */
            addItem(itemData) {
                this._controller.addItem(itemData);
            }
            /**
             * Method for setting the item hasErrors state
             * @param itemId Item id
             * @param hasErrors Item errors state
             */
            setItemHasErrors(itemId, hasErrors) {
                this._controller.setItemHasErrors(itemId, hasErrors);
            }
            /**
             * Method for setting the item hasErrors state
             * @param itemId Item id
             * @param hasErrors Item errors state
             */
            setItemHasChanges(itemId, hasChanges) {
                this._controller.setItemHasChanges(itemId, hasChanges);
            }
            /**
             * Method for setting a taskbar item title
             * @param itemId
             * @param title
             */
            setItemTitle(itemId, title) {
                this._controller.setItemTitle(itemId, title);
            }
            /**
             * Method for setting a taskbar group item title
             * @param groupId
             * @param title
             */
            setGroupTitle(groupId, title) {
                this._controller.setGroupTitle(groupId, title);
            }
            /**
             * Method for setting custom state on item by id
             * @param id
             * @param customStates
             */
            setItemCustomState(id, customStates) {
                this._controller.setItemCustomState(id, customStates);
            }
            /**
             * Method to get taskbar item by id
             * @param id
             */
            getItemById(id) {
                return this._controller.getItemById(id);
            }
            /**
             * Method to get active taskbar item by group id
             * @param id
             */
            getActiveItemByGroupId(id) {
                return this._controller.getActiveItemByGroupId(id);
            }
            /**
             * Method for selecting taskbar item by given id
             * @param id
             * @param triggerEvent
             */
            selectItem(id, triggerEvent = true) {
                this._controller.selectItem(id, triggerEvent);
            }
            /**
             * Method to get active group id
             */
            getActiveGroupId() {
                return this._controller.getActiveGroupId();
            }
            /**
             * Method to get active item
             */
            getActiveItem() {
                return this._controller.getActiveItem();
            }
            /**
             * Method for updating group with given options
             * @param groupData
             */
            updateGroup(groupData) {
                this._controller.updateGroup(groupData);
            }
            /**
             * Method for enabling Taskbar
             */
            enable() {
                this._controller.enable();
            }
            /**
             * Method for disabling the Taskbar
             */
            disable() {
                this._controller.disable();
            }
            /**
             * Method for getting all taskbar items
             */
            getItems() {
                return this._controller.getItems();
            }
            /**
             * Method for getting all taskbar groups
             */
            getGroups() {
                return this._controller.getGroups();
            }
            /**
             * Method for getting last selected group
             */
            getLastSelectedGroup() {
                return this._controller.getLastSelectedGroup();
            }
            /**
             * Method for attaching event by event name
             * @param eventName
             * @param listener
             */
            attachEvent(eventName, listener) {
                this._controller.attachEvent(eventName, listener);
            }
        }
        swat.Taskbar = Taskbar;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Text Object
           * @export
           * @class Text
           * @extends {Panel}
           */
        class Text extends akioma.swat.Panel {
        }
        swat.Text = Text;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Workflow Object
           * @export
           * @class Workflow
           * @extends {Panel}
           */
        class Workflow extends akioma.swat.Panel {
        }
        swat.Workflow = Workflow;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../Panel.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Field Container Base Class
         * @export
         * @class FieldContainer
         * @extends {Panel}
         */
        class FieldContainer extends akioma.swat.Panel {
        }
        swat.FieldContainer = FieldContainer;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../FieldContainer.ts" />
/// <reference path="../../../datafield/DataField.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Form Object
         * @export
         * @class Form
         * @extends {VisualObject}
         */
        class Form extends akioma.swat.FieldContainer {
            constructor() {
                super(...arguments);
                this._fieldMap = {};
                this._fieldNames = [];
                this._fieldControllers = [];
                this._fieldControllerMap = {};
            }
            /**
             * An array containing the form field names, including nested fieldsets and block fields
             * @readonly
             * @type {Array<string>}
             */
            get fieldNames() {
                if (this._fieldControllers.length === 0)
                    this._fillFields();
                return this._fieldNames;
            }
            get fieldControllers() {
                if (this._fieldControllers.length === 0)
                    this._fillFields();
                return this._fieldControllers;
            }
            get fieldControllerMap() {
                if (this._fieldControllers.length === 0)
                    this._fillFields();
                return this._fieldControllerMap;
            }
            _fillFields(parent) {
                parent = parent || this._dynObject;
                // copied logic from _searchNestedFormElements() in akioma.object.js
                // maybe all objects with childs property should be drilled?
                for (const name in parent.childs) {
                    const child = parent.childs[name];
                    switch (child.type) {
                        case 'fieldset':
                        case 'block':
                            this._fillFields(child);
                            break;
                        case 'htmlcontent':
                        case 'button':
                        case 'menustructure':
                            break;
                        default:
                            this._fieldControllers.push(child.controller);
                            this._fieldControllerMap[child.name.toLowerCase()] = child.controller;
                            if (this._fieldNames.indexOf(child.name) === -1 && child.name)
                                this._fieldNames.push(child.name);
                            break;
                    }
                }
            }
            /**
             * The linked business entity to this form
             * @readonly
             * @type {DataSource}
             */
            get dataSource() {
                if (!this._dataSource) {
                    const dataSource = this._dynObject.getLink('DISPLAY:SRC');
                    if (!dataSource)
                        return null;
                    this._dataSource = (akioma.swat.SwatFactory.createSwatObject(dataSource));
                }
                return this._dataSource;
            }
            get dataSourceController() {
                var _a;
                return ((_a = this._dynObject.getLink('DISPLAY:SRC')) === null || _a === void 0 ? void 0 : _a.controller) || null;
            }
            /**
             * Returns an object containing the form data
             * @returns {object}
             */
            getFormData() {
                return this._controller.getFormData();
            }
            /**
             * Gets a form field object
             * @param {string} name The form field name (case-insensitive)
             * @returns {DataField}
             */
            getField(name) {
                name = name.toLowerCase();
                let field = null;
                if (this.fieldControllerMap[name] && !this._fieldMap[name]) {
                    this._fieldMap[name] = (akioma.swat.SwatFactory.createSwatObject(this.fieldControllerMap[name]));
                    field = this._fieldMap[name];
                }
                else
                    field = (this.getObject(name));
                return field;
            }
            /**
             * Gets a form field dynselect object
             * @param {string} name The form field name (case-insensitive)
             * @returns {DynSelect}
             */
            getDynSelect(name) {
                const dynSelect = this.getField(name);
                if (dynSelect instanceof akioma.swat.DynSelect)
                    return dynSelect;
                else
                    return null;
            }
            /**
             * Gets a form field combobox object
             * @param {string} name The form field name (case-insensitive)
             * @returns {ComboBox}
             */
            getComboBox(name) {
                const comboBox = this.getField(name);
                if (comboBox instanceof akioma.swat.ComboBox)
                    return comboBox;
                else
                    return null;
            }
            /**
             * Gets a form field richtext object
             * @param {string} name The form field name (case-insensitive)
             * @returns {RichText}
             */
            getRichText(name) {
                const richText = this.getField(name);
                if (richText instanceof akioma.swat.RichText)
                    return richText;
                else
                    return null;
            }
            /**
             * Gets a form field toggle object
             * @param {string} name The form field name (case-insensitive)
             * @returns {Toggle}
             */
            getToggle(name) {
                const toggle = this.getField(name);
                if (toggle instanceof akioma.swat.Toggle)
                    return toggle;
                else
                    return null;
            }
            /**
             * Gets a form field set object
             * @param {string} name The fieldset object name (case-insensitive)
             * @returns {FieldSet}
             */
            getFieldSet(name) {
                const fieldSet = this.getObject(name);
                if (fieldSet instanceof akioma.swat.FieldSet)
                    return fieldSet;
                else
                    return null;
            }
            /**
             * Gets a form HTML content object
             * @param {string} name
             * @returns {akioma.swat.HTMLContent}
             */
            getHTMLContent(name) {
                const htmlContent = this.getObject(name);
                if (htmlContent instanceof akioma.swat.HTMLContent)
                    return htmlContent;
                else
                    return null;
            }
            /**
             * Gets a form button object
             * @param {string} name
             * @returns {akioma.swat.Button}
             */
            getButton(name) {
                const btn = this.getObject(name);
                if (btn instanceof akioma.swat.Button)
                    return btn;
                else
                    return null;
            }
            /**
             * Helper method for getting a form field screen value.
             * Equivalent to form.getField('myfield').screenValue.
             * @param {string} name The form field name (case-insensitive)
             * @returns {*}
             */
            getScreenValue(name) {
                return this.getField(name).screenValue;
            }
            /**
             * Helper method for setting a form field screen value.
             * Equivalent to form.getField('myfield').screenValue = 'value'.
             * @param {string} name The form field name (case-insensitive)
             * @param {*} value The value to set
             */
            setScreenValue(name, value) {
                this.getField(name).screenValue = value;
            }
            /**
             * Returns an object with all the form fields screen values, including nested fieldsets and blocks
             * @returns {*}
             */
            getAllScreenValues() {
                const retVal = {};
                this.fieldNames.forEach(name => {
                    const field = this.getField(name);
                    if (field instanceof akioma.swat.DynSelect)
                        retVal[field.keyName] = field.keyValue;
                    else
                        retVal[name] = field.screenValue;
                });
                return retVal;
            }
            /**
             * Returns an object with both the form fields screen and the datasource record fields
             * @returns {*}
             */
            getAllScreenAndDataValues() {
                return Object.assign(this.dataSource.getCurrentRecord(), this.getAllScreenValues());
            }
            /**
             * Helper method for getting a form field linked datasource value.
             * Equivalent to form.dataSource.getValue('myfield').
             * @param {string} name The form field name (case-insensitive)
             * @returns {*}
             */
            getDataValue(name) {
                return this.dataSource.getValue(name.toLowerCase());
            }
            /**
             * Helper method for setting a form field linked datasource value.
             * Equivalent to form.dataSource.setValue('myfield', 'value').
             * @param {string} name The form field name (case-insensitive)
             * @param {*} value The value to set
             */
            setDataValue(name, value) {
                this.dataSource.setValue(name.toLowerCase(), value);
            }
            /**
             * Returns an object with all the linked datasource form field values, including nested fieldsets and blocks
             * @returns {*}
             */
            getAllDataValues() {
                const retVal = {};
                this.fieldNames.forEach(name => {
                    const field = this.getField(name);
                    if (field instanceof akioma.swat.DynSelect)
                        name = field.keyName;
                    retVal[name] = this.dataSource.getValue(name);
                });
                return retVal;
            }
            /**
             * Clears hasChanges (dirty state)
             */
            clearHasChanges() {
                if (this.dataSource)
                    this.dataSource.controller.clearHasChanges();
                else
                    this._controller.clearHasChanges();
            }
            /**
             * Returns an array of field names that their values have been changed
             * @readonly
             * @example Form.changedFields
             * @type {string[]}
             */
            get changedFields() {
                const retVal = [];
                const fields = this.controller.oVuexState.children;
                for (const name in fields) {
                    if (fields[name].hasChanges)
                        retVal.push(fields[name].name);
                }
                return retVal;
            }
            /**
             * Helper method for setting a form field label.
             * Equivalent to form.getField('myfield').label = 'value'.
             * @param {string} name The form field name (case-insensitive)
             * @param {*} value The value to set
             */
            setLabel(name, value) {
                this.getField(name).label = value;
            }
            /**
             * Helper method for getting a form field label.
             * Equivalent to form.getField('myfield').label.
             * @param {string} name The form field name (case-insensitive)
             * @returns {string} value The value to set
             */
            getLabel(name) {
                return this.getField(name).label;
            }
            /**
             * Helper method to enable all the form fields.
             * Equivalent to looping through all the field names, getting the fields and setting enabled = true.
             */
            enableAllFields() {
                this._controller.enableAllFields();
            }
            /**
             * Helper method to disable all the form fields.
             * Equivalent to looping through all the field names, getting the fields and setting enabled = false.
             */
            disableAllFields() {
                this._controller.disableAllFields();
            }
            /**
             * Helper method to set all the form fields readonly property.
             * Equivalent to looping through all the field names, getting the fields and setting readonly property.
             * @param {boolean} readonly
             */
            setAllFieldsReadOnly(readonly) {
                if (readonly)
                    this.disableAllFields();
                else
                    this.enableAllFields();
            }
            /**
             * Returns all the form fields validation rules
             * @returns {*} The validation rules
             */
            getAllValidationRules() {
                return this._controller.validationRules;
            }
            /**
             * Validates the form and highlights invalid form fields
             * @param {boolean} [silent=false] If the validation fails and not silent,
             * forces form to be shown even if the form is in a collapsed panel or unselected tabbar etc.
             * @returns {boolean}
             */
            validate(silent = false) {
                const ok = this._controller.validate();
                if (!ok && !silent)
                    this.forceShow();
                return ok;
            }
            /**
             * Method for validating form field by name
             * @param name Name of form field to validate
             */
            validateField(name) {
                this.controller.validateField(name);
            }
            /**
             * Saves values to the linked datasource.
             * The form is first validated. If the validation fails the save is aborted.
             * @returns {Promise<void>}
             */
            save() {
                return new Promise((resolve, reject) => {
                    // filesave will cause all datasource forms to be saved
                    this._controller.fileSave();
                    this.dataSourceController.addAfterSaveOnceCallback((success) => {
                        if (success)
                            resolve();
                        else
                            reject(); // todo: return error messages
                    });
                });
            }
            /**
             * Saves values to the linked datasource and closes the top-level window.
             * The form is first validated. If the validation fails the save is aborted.
             * Note that if the container is the main dekstop window, the window will not be closed.
             * @returns {Promise<void>}
             */
            saveAndClose() {
                return this.save().then(() => {
                    this.window.close();
                });
            }
            /**
             * Method for returning the enabled state of a form field
             * @param {string} name
             * @instance
             * @memberof Form
             * @returns {boolean}
             */
            getFormFieldEnabled(name) {
                return this._controller.getFormFieldEnabled(name);
            }
            /**
             * Method for setting the focus on a certain form field
             * @param {string} name The form field name
             * @instance
             * @memberof Form
             */
            setFieldFocus(name) {
                this._controller.setFieldFocus(name);
            }
            /**
             * Sets the row of a form control.
             * @param {string} fieldName The form control field name.
             * @param {number} row The row number.
             * @memberof BaseFormDataField
             */
            setFormFieldRowStart(fieldName, row) {
                this._controller.setFormFieldRowStart(fieldName, row);
            }
            /**
             * Sets the column start of a form control.
             * @param {string} fieldName The form control field name.
             * @param {number} columnStart The column start.
             * @memberof BaseFormDataField
             */
            setFormFieldColumnStart(fieldName, columnStart) {
                this._controller.setFormFieldColumnStart(fieldName, columnStart);
            }
            /**
             * Sets the width end of a form control.
             * @param {string} fieldName The form control field name.
             * @param {number} width The new control width.
             * @memberof BaseFormDataField
             */
            setFormFieldColumnEnd(fieldName, width) {
                this._controller.setFormFieldColumnEnd(fieldName, width);
            }
            /**
             * Shifts columns in an active control starting from a given column by a given offset.
             * @param {number} columnStart The column number to start from.
             * @param {number} columnOffset The offset by which to shift.
             * @memberof BaseFormDataField
             */
            shiftColumnsByOffset(columnStart, columnOffset) {
                this._controller.shiftColumnsByOffset(columnStart, columnOffset);
            }
            /**
             * Sets the number of columns in a form field container.
             * @param {number} columnNumber The column number.
             * @memberof BaseFormDataField
             */
            setColumns(columnNumber) {
                this._controller.setColumns(columnNumber);
            }
        }
        swat.Form = Form;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../FieldContainer.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Grid Object
         * @export
         * @class BaseGrid
         * @extends {FieldContainer}
         */
        class BaseGrid extends akioma.swat.FieldContainer {
            constructor() {
                super(...arguments);
                this._gridColMap = {};
                this._gridColNames = [];
                this._gridColControllers = [];
                this._gridColControllerMap = {};
            }
            /**
             * An array containing the grid columns names
             * @readonly
             * @type {Array<string>}
             */
            get gridColNames() {
                if (this._gridColControllers.length === 0)
                    this._fillGridCols();
                return this._gridColNames;
            }
            get gridColControllers() {
                if (this._gridColControllers.length === 0)
                    this._fillGridCols();
                return this._gridColControllers;
            }
            get gridColControllerMap() {
                if (this._gridColControllers.length === 0)
                    this._fillGridCols();
                return this._gridColControllerMap;
            }
            _fillGridCols() {
                this._gridColControllers = this._controller.childs.filter((controller) => controller.view === 'datagridcol2');
                this._gridColControllerMap = this._gridColControllers.reduce((map, controller) => (map[controller.opt.name.toLowerCase()] = controller, map), {});
                this._gridColNames = this._gridColControllers.map((controller) => (controller.opt.name));
            }
            /**
             * The linked business entity to this form
             * @readonly
             * @type {DataSource}
             */
            get dataSource() {
                if (!this._dataSource)
                    this._dataSource = (akioma.swat.SwatFactory.createSwatObject(this._dynObject.getLink('DATA:SRC')));
                return this._dataSource;
            }
            /**
             * The grid enabled mode
             * @type {boolean}
             */
            get enabled() {
                return this._controller.isEnabled();
            }
            set enabled(value) {
                this._controller.setEditable(value);
            }
            /**
             * Promise for waiting on default filter to be loaded in Grid
             * @type {Promise}
             */
            get defaultFilterLoader() {
                return this._controller.FilterManager.oDynSelectPromise;
            }
            /**
             * Promise loader for header menus
             */
            get panelHeaderMenusLoader() {
                return this.controller.FilterManager.panelMenuLoaded;
            }
            /**
             * Event payload
             */
            get event() {
                var _a, _b, _c, _d, _e, _f, _g;
                if (!((_a = this.dynObject) === null || _a === void 0 ? void 0 : _a.akEvent))
                    return undefined;
                const event = Object.assign({}, ((_c = (_b = this.dynObject) === null || _b === void 0 ? void 0 : _b.akEvent) !== null && _c !== void 0 ? _c : {}));
                if ((_e = (_d = this.dynObject) === null || _d === void 0 ? void 0 : _d.akEvent) === null || _e === void 0 ? void 0 : _e.sourceObj)
                    event.sourceObj = akioma.swat.SwatFactory.createSwatObject(this.dynObject.akEvent.sourceObj);
                if ((_g = (_f = this.dynObject) === null || _f === void 0 ? void 0 : _f.akEvent) === null || _g === void 0 ? void 0 : _g.targetObj)
                    event.targetObj = akioma.swat.SwatFactory.createSwatObject(this.dynObject.akEvent.targetObj);
                return event;
            }
            /**
             * Gets a grid column object
             * @param {string} name The grid column name (case-insensitive)
             * @returns {GridCol}
             */
            getGridCol(name) {
                name = name.toLowerCase();
                if (!this._gridColMap[name])
                    this._gridColMap[name] = (akioma.swat.SwatFactory.createSwatObject(this.gridColControllerMap[name]));
                return this._gridColMap[name];
            }
            /**
             * Method to check if panel Menus are loaded
             * @returns {boolean}
             */
            isPanelHeaderMenusLoaded() {
                return this.controller.isPanelHeaderMenusLoaded();
            }
            /**
             * Method for reading filter panel manu states
             * @param {string} name Name of panel menu
             */
            getPanelFilterState(name) {
                return this.controller.FilterManager.getPanelFilterState(name);
            }
            /**
             * Helper method for getting a grid column screen value.
             * Equivalent to grid.getGridCol('mygridCol').screenValue.
             * @param {string} name The grid column name
             * @returns {*}
             */
            getScreenValue(name) {
                return this.getGridCol(name).screenValue;
            }
            /**
             * Helper method for getting a grid column lookup key value.
             * Equivalent to grid.getGridCol('mygridCol').lookupKeyValue.
             * @param {string} name The grid col name
             * @returns {*}
             */
            getLookupKeyValue(name) {
                return this.getGridCol(name).lookupKeyValue;
            }
            /**
             * Helper method for getting a grid column data value.
             * Equivalent to grid.getGridCol('mygridCol').dataValue.
             * @param {string} name The grid column name
             * @returns {*}
             */
            getDataValue(name) {
                return this.getGridCol(name).dataValue;
            }
            /**
             * Helper method for getting a grid column label.
             * Equivalent to grid.getGridCol('mygridcol').label.
             * @param {string} name The grid column name (case-insensitive)
             * @returns {string}
             */
            getLabel(name) {
                return this.getGridCol(name).label;
            }
            /**
             * Helper method for setting a grid column label by the name
             * @param {string} name The grid column name (case-insensitive)
             * @param {string} label The new label
             */
            setLabel(name, label) {
                this._controller.setLabel(name, label);
            }
            /**
             * Clears hasChanges (dirty state)
             */
            clearHasChanges() {
                if (this.dataSource)
                    this.dataSource.controller.clearHasChanges();
                else
                    this._controller.clearHasChanges();
            }
            /**
             * Sets the dirty state for a record identified by the primaryKey
             * @param {boolean} dirtyStateStatus True or False
             * @param {string} primaryKey The value corresponding to the KeyField attribute in the dataSource;
             * used to uniquely identify the record for which to set the new value; Optional
             * @returns {*}
             */
            setHasChanges(dirtyStateStatus, primaryKey) {
                this.controller.setHasChanges(dirtyStateStatus, primaryKey);
            }
            /**
             * Expose the cell of the grid by a given rowID and colIndex
             * @param {string} rowId
             * @param {number} colIndex
             * @returns {*}
             */
            getCellByRowAndCol(rowId, colIndex) {
                return this._controller.getCellByRowAndCol(rowId, colIndex);
            }
            /**
             * Gets the akEvent for a cell. The akEvent contains the currentValue and lastValue of the cell.
             * @param {string} rowId
             * @param {number} colIndex
             * @return {object|null}
             */
            getCellAkEvent(rowId, colIndex) {
                return this._controller.getCellAkEvent(rowId, colIndex);
            }
            /**
             * Enables drag and drop on a grid
             */
            enableDragAndDrop() {
                this._controller.enableDragAndDrop(true);
            }
            /**
             * Disables drag and drop on a grid
             */
            disableDragAndDrop() {
                this._controller.enableDragAndDrop(false);
            }
            /**
             * Checks if drag and drop is enabled on a grid
             * @returns {boolean}
             */
            hasDragAndDropEnabled() {
                return this._controller.hasDragAndDropEnabled();
            }
            /**
             * Sets the drag and drop behaviour on a grid
             * @param dragDropBehaviour 'default' | 'copy' | 'move' Type of drag and drop behaviour
             */
            setDragAndDropBehaviour(dragDropBehaviour) {
                this._controller.setDragAndDropBehaviour(dragDropBehaviour);
            }
            /**
             * Enables autoFocus on a grid after a data refresh
             * @returns {void}
             */
            enableAutoFocus() {
                this._controller.setAutoFocus(true);
            }
            /**
             * Disables autoFocus on a grid after a data refresh
             * @returns {void}
             */
            disableAutoFocus() {
                this._controller.setAutoFocus(false);
            }
            /**
             * Method for getting the column index by id
             * @param {string} name The grid column name
             * @returns {number}
             */
            getColIndexById(name) {
                return this._controller.getColIndexById(name);
            }
            /**
             * Method for handling a class, id or any propertie
             * @param {string} selector
             * @param {*} styles object where the key is property name and value is the value of the propertie.
             * in case where remove is true, property values should be empty string.
             * @param {boolean} remove true for remove, false or undefined for add
             * @returns {void}
             */
            handleProperties(selector, styles, remove) {
                this._controller.handleProperties(selector, styles, remove);
            }
            /**
             * Function used to show a column in the grid.
             * @memberof grid
             * @instance
             * @param {Number | String} identifier
             */
            showColumn(identifier) {
                this._controller.showColumn(identifier);
            }
            /**
             * Function used to enable a column in the grid.
             * @memberof grid
             * @instance
             * @param {Number | String} identifier
             */
            enableColumn(identifier) {
                this._controller.enableColumn(identifier);
            }
            /**
             * Function used to hide a column in the grid.
             * @memberof grid
             * @instance
             * @param {Number | String} identifier
             */
            hideColumn(identifier) {
                this._controller.hideColumn(identifier);
            }
            /**
             * Function used to disable a column in the grid.
             * @memberof grid
             * @instance
             * @param {Number | String} identifier
             */
            disableColumn(identifier) {
                this._controller.disableColumn(identifier);
            }
            /**
             * Adding classes while keeping the old ones
             * @param {string} selector
             * @param {array} classes array of class names
             * @returns {void}
             */
            addClass(selector, classes) {
                this._controller.addClass(selector, classes);
            }
            /**
             * Removing classes while keeping the old ones
             * @param {string} selector
             * @param {array} classes array of class names
             */
            removeClass(selector, classes) {
                this._controller.removeClass(selector, classes);
            }
            /**
             * Method for showing a given context menu item
             * @param itemCode Name of the item to show
             */
            showContextMenuItem(itemCode) {
                this._controller.contextMenuObject.showContextMenuItem(itemCode);
            }
            /**
             * Method for hiding a given context menu item
             * @param itemCode Name of the item to hide
             */
            hideContextMenuItem(itemCode) {
                this._controller.contextMenuObject.hideContextMenuItem(itemCode);
            }
            /**
             * Method for showing all context menu items
             */
            showContextMenuItems() {
                this._controller.contextMenuObject.showContextMenuItems();
            }
            /**
             * Method for hiding all context menu items
             */
            hideContextMenuItems() {
                this._controller.contextMenuObject.hideContextMenuItems();
            }
            /**
             * Method for enabling a given context menu item
             * @param itemCode Name of the item to enable
             */
            enableContextMenuItem(itemCode) {
                this._controller.contextMenuObject.enableContextMenuItem(itemCode);
            }
            /**
             * Method for disabling a given context menu item
             * @param itemCode Name of the item to disable
             */
            disableContextMenuItem(itemCode) {
                this._controller.contextMenuObject.disableContextMenuItem(itemCode);
            }
            /**
             * Method for enabling all context menu items
             */
            enableContextMenuItems() {
                this._controller.contextMenuObject.enableContextMenuItems();
            }
            /**
             * Method for disabling all context menu items
             */
            disableContextMenuItems() {
                this._controller.contextMenuObject.disableContextMenuItems();
            }
            /**
             * Reset filters to default and refresh the grid
             */
            resetAndRefresh() {
                this._controller.resetAndRefresh();
            }
            /**
             * Method for enabling or disabling the grid
             * @param editable True for enabling the grid, false for disabling it
             */
            setEditable(editable) {
                this._controller.setEditable(editable);
            }
            /**
             * Method for checking if the grid is enabled
             * @returns {boolean}
             */
            isEnabled() {
                return this._controller.isEnabled();
            }
            /**
             * Method for enabling the column filters in a grid
             */
            enableColumnFilters() {
                this._controller.enableColumnFilters();
            }
            /**
             * Method for disabling the column filters in a grid
             */
            disableColumnFilters() {
                this._controller.disableColumnFilters();
            }
            /**
             * Method for filtering on Grid
             */
            FilterGo() {
                this._controller.FilterGo();
            }
            /**
             * Method for getting currently selected records of Grid
             */
            getSelectedRecords() {
                return this._controller.getSelectedRecords();
            }
            /**
             * Groups the grid by the given column
             * @instance
             * @param {number | string} identifier Column index|name to group by
             * @param {string[]} mask Optional, array, each value of which is mapped to the related column
             * @memberof ak_datagrid2
             */
            groupBy(identifier, mask) {
                this._controller.groupBy(identifier, mask);
            }
            /**
             * Ungroups the grid to return it into the plain view
             * @instance
             * @memberof ak_datagrid2
             */
            unGroup() {
                this._controller.unGroup();
            }
            /**
             * Expands a group of rows
             * @instance
             * @param {string} groupName Value used to determine what group to expand (a common value for all rows in the group)
             * @memberof ak_datagrid2
             */
            expandGroup(groupName) {
                this._controller.expandGroup(groupName);
            }
            /**
             * Collapses a group of rows
             * @instance
             * @param {string} groupName Value used to determine what group to collapse (a common value for all rows in the group)
             * @memberof ak_datagrid2
             */
            collapseGroup(groupName) {
                this._controller.collapseGroup(groupName);
            }
            /**
             * Expands all groups
             * @instance
             * @memberof ak_datagrid2
             */
            expandAllGroups() {
                this._controller.expandAllGroups();
            }
            /**
             * Collapses all groups
             * @instance
             * @memberof ak_datagrid2
             */
            collapseAllGroups() {
                this._controller.collapseAllGroups();
            }
            /**
             * Sets the customGroupFormat property on the grid to customize the group summary row appearance
             * @param {CustomGroupFormatFunction} customGroupFormat Value used to determine what group to collapse (a common value for all rows in the group)
             * @instance
             * @memberof ak_datagrid2
             */
            setCustomGroupFormat(customGroupFormat) {
                this._controller.setCustomGroupFormat(customGroupFormat);
            }
            /**
             * Iterates through all rows in some group
             * @instance
             * @param {string} name Name of the group
             * @param {RowFunction} rowFunction Function which gets row id as the incoming argument
             * @memberof ak_datagrid2
             */
            forEachRowInGroup(name, rowFunction) {
                this._controller.forEachRowInGroup(name, rowFunction);
            }
        }
        swat.BaseGrid = BaseGrid;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./BaseGrid.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Grid Object
         * @export
         * @class Grid
         * @extends {BaseGrid}
         */
        class Grid extends akioma.swat.BaseGrid {
            /**
             * Counts records from the attached datasource
             * @instance
             * @memberof ak_datagrid2
             */
            countRecords() {
                return this._controller.countRecords();
            }
        }
        swat.Grid = Grid;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Grid.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * DataView Object
           * @export
           * @class DataView
           * @extends {Grid}
           */
        class DataView extends akioma.swat.Grid {
        }
        swat.DataView = DataView;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./BaseGrid.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * PropertyGrid Object
           * @export
           * @class PropertyGrid
           * @extends { BaseGrid }
           */
        class PropertyGrid extends akioma.swat.BaseGrid {
        }
        swat.PropertyGrid = PropertyGrid;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./Grid.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * TreeGrid Object
         * @export
         * @class TreeGrid
         * @extends { Grid }
         */
        class TreeGrid extends akioma.swat.Grid {
            /**
             * Method to expand all tree nodes
             * @param levels Levels of nodes to expand, default -1 expands all nodes
             * @param rowId Optional row identifier, default set to root node id
             */
            expandNodes(levels = -1, rowId) {
                this.controller.expandNodes(levels, rowId);
            }
            /**
             * Method to collapse all tree nodes
             * @param rowId Optional tree row identifier, default set to root node id
             */
            collapseNodes(rowId) {
                this.controller.collapseNodes(rowId);
            }
        }
        swat.TreeGrid = TreeGrid;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="../VisualObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * Primitive Object Base Class
           * @export
           * @class PrimitiveObject
           * @extends {VisualObject}
           */
        class PrimitiveObject extends akioma.swat.VisualObject {
        }
        swat.PrimitiveObject = PrimitiveObject;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./PrimitiveObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
           * HTML Content Object
           * @export
           * @class HTMLContent
           * @extends {PrimitiveObject}
           */
        class HTMLContent extends akioma.swat.PrimitiveObject {
            get formDhx() {
                if (!this._formDhx) {
                    const form = this._dynObject.getParentOfType('form');
                    this._formDhx = form.controller.dhx;
                }
                return this._formDhx;
            }
            get htmlEl() {
                const dhx = this.formDhx;
                return dhx.itemPull[dhx.idPrefix + this.name];
            }
            /**
                 * The HTML content hidden mode (opposite of visible)
                 * @type {boolean}
                 */
            get hidden() {
                const htmlEl = this.htmlEl;
                const displayStyle = htmlEl.style.display.toLowerCase();
                return (displayStyle === 'hidden' || displayStyle === 'none');
            }
            set hidden(value) {
                const htmlEl = this.htmlEl;
                if (value)
                    htmlEl.style.display = 'none';
                else
                    htmlEl.style.display = '';
            }
            /**
                 * The HTML content visible mode (opposite of hidden)
                 * @type {boolean}
                 */
            get visible() {
                return !this.hidden;
            }
            set visible(value) {
                this.hidden = !value;
            }
        }
        swat.HTMLContent = HTMLContent;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
/// <reference path="./PrimitiveObject.ts" />
var akioma;
(function (akioma) {
    var swat;
    (function (swat) {
        /**
         * Upload Object
         * @export
         * @class Upload
         * @extends {PrimitiveObject}
         */
        class Upload extends akioma.swat.PrimitiveObject {
            /**
             * Get dhx response after upload.
             */
            get response() {
                return this._controller.dhx._loader.response;
            }
            /**
             * Call clear method on dhx.
             */
            clear() {
                this._controller.dhx.clear();
            }
        }
        swat.Upload = Upload;
    })(swat = akioma.swat || (akioma.swat = {}));
})(akioma || (akioma = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYWtpb21hL3N3YXQvQXBwLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L0dsb2JhbEhvb2tzLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L01lc3NhZ2UudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvUmVmcmVzaEVtaXR0ZXIudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvU2Vzc2lvbk1hbmFnZXIudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvU2hvcnRjdXRNYW5hZ2VyLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L1NvY2tldENvbm5lY3Rpb25IZWxwZXIudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvU3dhdEZhY3RvcnkudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvU3dhdE9iamVjdC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC9Vc2VyUHJvZmlsZS50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC9XYWl0Q3Vyc29yLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L2RhdGEvRGF0YVNvdXJjZS50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC9leHRlcm5hbC1zY3JlZW4vRXh0ZXJuYWxTY3JlZW4udHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL1Zpc3VhbE9iamVjdC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvQWNjb3JkaW9uLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9kYXRhZmllbGQvRm9ybUZpZWxkT2JqZWN0LnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9Gb3JtRmllbGRDb250YWluZXJPYmplY3QudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL0Jsb2NrLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9GaWVsZFNldC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvZGF0YWZpZWxkL0J1dHRvbi50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvZGF0YWZpZWxkL0RhdGFGaWVsZC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvZGF0YWZpZWxkL0NhbGVuZGFyLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9kYXRhZmllbGQvQ29tYm9Cb3gudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL2RhdGFmaWVsZC9FZGl0b3IudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL2RhdGFmaWVsZC9JbnB1dC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvZGF0YWZpZWxkL1RvZ2dsZS50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvZGF0YWZpZWxkL1R3b1N0YXRlLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9kYXRhZmllbGQvc21hcnRmaWVsZC9TbWFydEZpZWxkT2JqZWN0LnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9kYXRhZmllbGQvc21hcnRmaWVsZC9EeW5TZWxlY3QudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL2RhdGFmaWVsZC9zbWFydGZpZWxkL1JpY2hUZXh0LnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9kYXRhZmllbGQvc21hcnRmaWVsZC9UcmFuc2xhdGFibGUudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL2dyaWRjb2wvR3JpZENvbC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvbGF5b3V0L0xheW91dE9iamVjdC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvbGF5b3V0L0NvbnRhaW5lckxheW91dE9iamVjdC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvbGF5b3V0L0ZyYW1lLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9sYXlvdXQvTWFzdGVyTGF5b3V0LnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9sYXlvdXQvUG9wT3Zlci50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvbGF5b3V0L1dpbmRvdy50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvbmF2aWdhdGlvbi9OYXZpZ2F0aW9uT2JqZWN0LnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9uYXZpZ2F0aW9uL1JpYmJvbi50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvbmF2aWdhdGlvbi9Ub29sYmFyLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9uYXZpZ2F0aW9uL3RhYmJhci9UYWJiYXIudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL25hdmlnYXRpb24vdGFiYmFyL1NpZGViYXIudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL3BhbmVsL1BhbmVsU3dpdGNoZXJPYmplY3QudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL3BhbmVsL1BhbmVsLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9wYW5lbC9DaGFydC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvRGlhZ3JhbS50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvRG9jVmlld2VyLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9wYW5lbC9GcmVlSGFuZC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvR2FudHQudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL3BhbmVsL0dhdWdlLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9wYW5lbC9HcmFwaEVkaXRvci50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvSW1hZ2UudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL3BhbmVsL01hcC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvUGFuZWxTd2l0Y2hlci50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvU2NoZWR1bGVyLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9wYW5lbC9UYXNrYmFyLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9wYW5lbC9UZXh0LnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9wYW5lbC9Xb3JrZmxvdy50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvZmllbGRjb250YWluZXIvRmllbGRDb250YWluZXIudHMiLCIuLi9zcmMvYWtpb21hL3N3YXQvdmlzdWFsL3BhbmVsL2ZpZWxkY29udGFpbmVyL2Zvcm0vRm9ybS50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvZmllbGRjb250YWluZXIvZ3JpZC9CYXNlR3JpZC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvZmllbGRjb250YWluZXIvZ3JpZC9HcmlkLnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9wYW5lbC9maWVsZGNvbnRhaW5lci9ncmlkL0RhdGFWaWV3LnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9wYW5lbC9maWVsZGNvbnRhaW5lci9ncmlkL1Byb3BlcnR5R3JpZC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcGFuZWwvZmllbGRjb250YWluZXIvZ3JpZC9UcmVlR3JpZC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcHJpbWl0aXZlL1ByaW1pdGl2ZU9iamVjdC50cyIsIi4uL3NyYy9ha2lvbWEvc3dhdC92aXN1YWwvcHJpbWl0aXZlL0hUTUxDb250ZW50LnRzIiwiLi4vc3JjL2FraW9tYS9zd2F0L3Zpc3VhbC9wcmltaXRpdmUvVXBsb2FkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLElBQVUsTUFBTSxDQXNTZjtBQXRTRCxXQUFVLE1BQU07SUFBQyxJQUFBLElBQUksQ0FzU3BCO0lBdFNnQixXQUFBLElBQUk7UUFFbkI7Ozs7V0FJRztRQUNILE1BQWEsR0FBRztZQW1DZDs7Ozs7Ozs7Ozs7Ozs7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RTNCLElBQUksS0FBSztvQkFDUCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7O29CQUU5QixNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDOUIsQ0FBQztZQUVEOzs7bUJBR087WUFDUCxJQUFJLE9BQU87Z0JBQ1QsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7WUFDdEIsQ0FBQztZQUVELElBQUksT0FBTyxDQUFDLEtBQWM7Z0JBQ3hCLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUM7WUFDdkIsQ0FBQztTQUNGO1FBcERZLGdCQUFXLGNBb0R2QixDQUFBO0lBQ0gsQ0FBQyxFQTdEZ0IsSUFBSSxHQUFKLFdBQUksS0FBSixXQUFJLFFBNkRwQjtBQUFELENBQUMsRUE3RFMsTUFBTSxLQUFOLE1BQU0sUUE2RGY7QUMvREQsNkNBQTZDO0FBRTdDLElBQVUsTUFBTSxDQXdCZjtBQXhCRCxXQUFVLE1BQU07SUFBQyxJQUFBLElBQUksQ0F3QnBCO0lBeEJnQixXQUFBLElBQUk7UUFFbkI7Ozs7O1dBS0c7UUFDSCxNQUFhLE1BQU8sU0FBUSxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWU7WUFFckQ7O2VBRUc7WUFDSCxJQUFJLFFBQVE7Z0JBQ1YsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDO1lBQy9DLENBQUM7WUFFRDs7ZUFFRztZQUNILEtBQUs7Z0JBQ0gsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDL0IsQ0FBQztTQUNGO1FBZlksV0FBTSxTQWVsQixDQUFBO0lBQ0gsQ0FBQyxFQXhCZ0IsSUFBSSxHQUFKLFdBQUksS0FBSixXQUFJLFFBd0JwQjtBQUFELENBQUMsRUF4QlMsTUFBTSxLQUFOLE1BQU0sUUF3QmYiLCJzb3VyY2VzQ29udGVudCI6WyJuYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBHbG9iYWwgQXBwbGljYXRpb24gT2JqZWN0XG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIEFwcFxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIEFwcCB7XG4gICAgLyoqXG4gICAgICogTG9hZHMgYSB3aW5kb3csIG9yIGZyYW1lIGludG8gYW4gZXhpc3Rpbmcgd2luZG93XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuY29udGFpbmVyTmFtZSBUaGUgb2JqZWN0IG5hbWUgdG8gbGF1bmNoXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMucGFnZXMgVGhlIGluaXRpYWwgcGFnZXMgdG8gbG9hZCwgZm9yIGV4YW1wbGUsIDxjb2RlPjAsMTwvY29kZT5cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0cy50YXJnZXQgVGhlIHRhcmdldCBvYmplY3QgdG8gbG9hZCB0aGUgZnJhbWUgaW50b1xuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gZHluYW1pY2FsbHkgbG9hZCBhIGZyYW1lIGludG8gYW4gZXhpc3Rpbmcgd2luZG93XG4gICAgICogYWtpb21hLnN3YXQubG9hZFNjcmVlbih7XG4gICAgICpcbiAgICAgKiAgICAgLy8gZnJhbWUgbmFtZSB0byBsb2FkXG4gICAgICogICAgIGNvbnRhaW5lck5hbWU6IFwiPGZyYW1lIG5hbWU+XCIsXG4gICAgICpcbiAgICAgKiAgICAgLy8gaW50byBhIHRhYmJhcidzIHRhYiBmcmFtZVxuICAgICAqICAgICB0YXJnZXQ6IGV2ZW50U291cmNlLndpbmRvdy5nZXRPYmplY3QoXCJNeVRhYlwiKVxuICAgICAqIH0pO1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnZpZXcgVGhlIHZpZXcgbmFtZSB0byB1c2UgZm9yIHRoZSBuZXcgcmVwb3NpdG9yeSBvYmplY3QgKHJlcXVpcmVzIHRhcmdldCkuXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdHMuY2FsbGVyIFRoZSBjYWxsZXIgb2JqZWN0IHdoZXJlIHRoZSBjb250YWluZXIgaXMgbGF1bmNoZWQgZnJvbVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5keW5HdWlkIFRoZSBkeW5hbWljIGd1aWQuXG4gICAgICogVXNlZnVsIHdoZW4gbG9hZGluZyBhIHRhYiB3aGVyZSB5b3UgY291bGQgbG9hZCB0aGUgc2FtZSByZXBvc2l0b3J5IG9iamVjdCBtdWx0aXBsZSB0aW1lcyBhbmQgdGhlIGxpbmtzIG5lZWQgdG8gYmUgdW5pcXVlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5hdXRvQWRkIEF1dG9tYXRpY2FsbHkgYWRkIGEgbmV3IHJlY29yZCBvbiB0aGUgcmVzdWx0aW5nIHNjcmVlbiBQcmltYXJ5U0RPIGRhdGFzb3VyY2UuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmZldGNoT25Jbml0IElmIHRoZSBuZXcgcmVwb3NpdG9yeSBzY3JlZW4gc2hvdWxkIGxvYWQgaXRzIGRhdGEgb3Igbm90IChjYWxscyB0aGUgZGF0YXNvdXJjZSBvcGVuUXVlcnkpLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnJlcG9zaXRpb25UbyBQb3NpdGlvbnMgdGhlIFByaW1hcnlTRE8gZGF0YXNvdXJjZSB0byB0aGUgU2VsZkhkbCBnaXZlbiB2YWx1ZS4gQ2FuIGFsc28gYmUgYSBmdW5jdGlvbiBjYWxsLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG9iamVjdH0gb3B0cy5jdXN0b21EYXRhIEluZm9ybWF0aW9uIGZvciByZXBvc2l0aW9uaW5nIHRoZSBQcmltYXJ5U0RPIGRhdGFzb3VyY2UuIENhbiBhbHNvIGJlIGEgZnVuY3Rpb24gY2FsbC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5mb3JlaWduS2V5UHJvdmlkZXIgRnVuY3Rpb24gY2FsbCBmb3Igc2V0dGluZyB0aGUgbmV3IHJlY29yZCBpbml0aWFsIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge2FueX0gb3B0cy5wYXJhbXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5wYXJhbXMuVHlwZUtleVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnBhcmFtcy5TZWxmSGRsXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMucGFyYW1zLkRhdGFzb3VyY2VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5wYXJhbXMuVGFyZ2V0SWRcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxMYXlvdXRPYmplY3Q+fSBSZXR1cm5zIGEgcHJvbWlzZSB3aXRoIHRoZSBjb250YWluZXIgb2JqZWN0XG4gICAgICovXG4gICAgc3RhdGljIGxvYWRTY3JlZW4oY29udGFpbmVyTmFtZTogc3RyaW5nKTogUHJvbWlzZTxha2lvbWEuc3dhdC5XaW5kb3c+O1xuICAgIHN0YXRpYyBsb2FkU2NyZWVuKG9wdHM6IExhdW5jaENvbnRhaW5lck9wdGlvbnMpOiBQcm9taXNlPGFraW9tYS5zd2F0LldpbmRvdz47XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhIHdpbmRvdywgb3IgZnJhbWUgaW50byBhbiBleGlzdGluZyB3aW5kb3dcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5jb250YWluZXJOYW1lIFRoZSBvYmplY3QgbmFtZSB0byBsYXVuY2hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5wYWdlcyBUaGUgaW5pdGlhbCBwYWdlcyB0byBsb2FkLCBmb3IgZXhhbXBsZSwgPGNvZGU+MCwxPC9jb2RlPlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzLnRhcmdldCBUaGUgdGFyZ2V0IG9iamVjdCB0byBsb2FkIHRoZSBmcmFtZSBpbnRvXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiAvLyBkeW5hbWljYWxseSBsb2FkIGEgZnJhbWUgaW50byBhbiBleGlzdGluZyB3aW5kb3dcbiAgICAgKiBha2lvbWEuc3dhdC5sb2FkU2NyZWVuKHtcbiAgICAgKlxuICAgICAqICAgICAvLyBmcmFtZSBuYW1lIHRvIGxvYWRcbiAgICAgKiAgICAgY29udGFpbmVyTmFtZTogXCI8ZnJhbWUgbmFtZT5cIixcbiAgICAgKlxuICAgICAqICAgICAvLyBpbnRvIGEgdGFiYmFyJ3MgdGFiIGZyYW1lXG4gICAgICogICAgIHRhcmdldDogZXZlbnRTb3VyY2Uud2luZG93LmdldE9iamVjdChcIk15VGFiXCIpXG4gICAgICogfSk7XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudmlldyBUaGUgdmlldyBuYW1lIHRvIHVzZSBmb3IgdGhlIG5ldyByZXBvc2l0b3J5IG9iamVjdCAocmVxdWlyZXMgdGFyZ2V0KS5cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0cy5jYWxsZXIgVGhlIGNhbGxlciBvYmplY3Qgd2hlcmUgdGhlIGNvbnRhaW5lciBpcyBsYXVuY2hlZCBmcm9tXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmR5bkd1aWQgVGhlIGR5bmFtaWMgZ3VpZC5cbiAgICAgKiBVc2VmdWwgd2hlbiBsb2FkaW5nIGEgdGFiIHdoZXJlIHlvdSBjb3VsZCBsb2FkIHRoZSBzYW1lIHJlcG9zaXRvcnkgb2JqZWN0IG11bHRpcGxlIHRpbWVzIGFuZCB0aGUgbGlua3MgbmVlZCB0byBiZSB1bmlxdWUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmF1dG9BZGQgQXV0b21hdGljYWxseSBhZGQgYSBuZXcgcmVjb3JkIG9uIHRoZSByZXN1bHRpbmcgc2NyZWVuIFByaW1hcnlTRE8gZGF0YXNvdXJjZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuZmV0Y2hPbkluaXQgSWYgdGhlIG5ldyByZXBvc2l0b3J5IHNjcmVlbiBzaG91bGQgbG9hZCBpdHMgZGF0YSBvciBub3QgKGNhbGxzIHRoZSBkYXRhc291cmNlIG9wZW5RdWVyeSkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMucmVwb3NpdGlvblRvIFBvc2l0aW9ucyB0aGUgUHJpbWFyeVNETyBkYXRhc291cmNlIHRvIHRoZSBTZWxmSGRsIGdpdmVuIHZhbHVlLiBDYW4gYWxzbyBiZSBhIGZ1bmN0aW9uIGNhbGwuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuYWxsb3dNdWx0aXBsZUluc3RhbmNlcyBTcGVjaWZpZXMgaWYgYWxsb3dpbmcgbXVsdGlwbGUgc2NyZWVuIGluc3RhbmNlcyBpcyBhbGxvd2VkXG4gICAgICogQHBhcmFtIHtzdHJpbmd8b2JqZWN0fSBvcHRzLmN1c3RvbURhdGEgSW5mb3JtYXRpb24gZm9yIHJlcG9zaXRpb25pbmcgdGhlIFByaW1hcnlTRE8gZGF0YXNvdXJjZS4gQ2FuIGFsc28gYmUgYSBmdW5jdGlvbiBjYWxsLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmZvcmVpZ25LZXlQcm92aWRlciBGdW5jdGlvbiBjYWxsIGZvciBzZXR0aW5nIHRoZSBuZXcgcmVjb3JkIGluaXRpYWwgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7YW55fSBvcHRzLnBhcmFtc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnBhcmFtcy50eXBlS2V5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMucGFyYW1zLnNlbGZIZGxcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5wYXJhbXMuZGF0YVNvdXJjZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnBhcmFtcy50YXJnZXRJZFxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPExheW91dE9iamVjdD59IFJldHVybnMgYSBwcm9taXNlIHdpdGggdGhlIGNvbnRhaW5lciBvYmplY3RcbiAgICAgKi9cbiAgICBzdGF0aWMgbG9hZFNjcmVlbihvcHRzOiBhbnkpOiBQcm9taXNlPGFraW9tYS5zd2F0LkxheW91dE9iamVjdD4ge1xuICAgICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICAgIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ3N0cmluZycpXG4gICAgICAgIG9wdHMgPSB7IGNvbnRhaW5lck5hbWU6IG9wdHMgfTtcblxuICAgICAgb3B0cyA9IEFwcC5jb252ZXJ0TGF1bmNoQ29udGFpbmVyUGFyYW1zKG9wdHMpO1xuXG4gICAgICAvLyBydW4gbGF1bmNoQ29udGFpbmVyIGFuZCByZXR1cm4gcHJvbWlzZS4ganF1ZXJ5IHByb21pc2UgY29udmVydGVkIHRvIGVzNiBwcm9taXNlLlxuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgd2luZG93LmFwcC5jb250cm9sbGVyLmxhdW5jaENvbnRhaW5lcihvcHRzKS50aGVuKFxuICAgICAgICAgIChjb250cm9sbGVyOiBhbnkpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUoPGFraW9tYS5zd2F0LkxheW91dE9iamVjdD5ha2lvbWEuc3dhdC5Td2F0RmFjdG9yeS5jcmVhdGVTd2F0T2JqZWN0KGNvbnRyb2xsZXIpKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIChlcnJvcjogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludm9rZXMgYSBiYWNrZW5kIEJ1c2luZXNzIFRhc2sgb3IgQnVzaW5lc3MgRW50aXR5IG1ldGhvZFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm5hbWUgVGhlIEJ1c2luZXNzIFRhc2sgb3IgQnVzaW5lc3MgRW50aXR5IGZ1bGx5IHF1YWxpZmllZCBjbGFzcyBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubWV0aG9kTmFtZSBUaGUgbWV0aG9kIG5hbWUgdG8gaW52b2tlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdHMucGFyYW1PYmogVGhlIG1ldGhvZCBwYXJhbWV0ZXJzXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdHMucGFyYW1PYmoucGxjUGFyYW1ldGVyIFRoZSBtZXRob2QgcGFyYW1ldGVyIG9iamVjdFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzLnBhcmFtT2JqLiogT3RoZXIgb3B0aW9uYWwgcGFyYW1ldGVycyBsaWtlIGRhdGFzZXRzXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLnNob3dXYWl0Q3Vyc29yIERpc3BsYXlzIHdhaXQgY3Vyc29yIHN0YXJ0aW5nIGZyb20gdWlDb250ZXh0IGR5bk9iamVjdFxuICAgICAqIEBwYXJhbSB7ZHluT2JqZWN0fSBvcHRzLnVpQ29udGV4dCBUaGUgZHluT2JqZWN0IHNvdXJjZSBvZiB0aGUgd2FpdCBjdXJzb3JcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMudGhyb3dEYXRhRXJyb3IgT3B0aW9uYWwgZmxhZyB0byByZWplY3QgcHJvbWlzZSB3aGVuIGRhdGFzZXQgY29udGFpbiBlcnJvcnNcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxXaW5kb3c+fSBSZXR1cm5zIGEgcHJvbWlzZSB3aXRoIHRoZSBvdXRwdXQgcGFyYW1ldGVyXG4gICAgICovXG4gICAgc3RhdGljIGludm9rZVNlcnZlclRhc2sob3B0czogSW52b2tlU2VydmVyVGFza09wdGlvbnMpOiBQcm9taXNlPGFueT4ge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgd2luZG93LmFraW9tYS5pbnZva2VTZXJ2ZXJUYXNrKG9wdHMpLmRvbmUocmVzb2x2ZSkuZmFpbChyZWplY3QpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUXVlcnkgYnVzaW5lc3MgZW50aXR5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubmFtZSBUaGUgQnVzaW5lc3MgRW50aXR5IGZ1bGx5IHF1YWxpZmllZCBjbGFzcyBuYW1lXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdHMuZmlsdGVyIFRoZSBLZW5kb1VJIGZpbHRlclxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gcXVlcnkgYnVzaW5lc3MgZW50aXR5XG4gICAgICogYWtpb21hLnN3YXQuQXBwLnF1ZXJ5QnVzaW5lc3NFbnRpdHkoe1xuICAgICAqICAgICBuYW1lOiAgICdBa2lvbWEuQ3JtLk1hc3RlckRhdGEuU3lzdGVtLlBhcmFtZXRlckVudGl0eScsXG4gICAgICogICAgIGZpbHRlcjogW3tmaWVsZDogJ2dyb3VwSGRsJywgb3BlcmF0b3I6ICdlcScsIHZhbHVlOiAnVXNlckltZyd9XVxuICAgICAqIH0pLmRvbmUoKGRhdGEpID0+IHtcbiAgICAgKiAgICBjb25zb2xlLmxvZyhkYXRhKTtcbiAgICAgKiB9KS5mYWlsKChlcnIpID0+IHtcbiAgICAgKiAgICBjb25zb2xlLmxvZyhlcnIubWVzc2FnZSk7XG4gICAgICogfSk7XG4gICAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn0gUmV0dXJucyBhIHByb21pc2Ugd2l0aCB0aGUgcXVlcnkgZGF0YVxuICAgICAqL1xuICAgIHN0YXRpYyBxdWVyeUJ1c2luZXNzRW50aXR5KG9wdHM6IHtcbiAgICAgIG5hbWU6IHN0cmluZztcbiAgICAgIHNlcnZpY2VVUkk/OiBzdHJpbmc7XG4gICAgICBmaWx0ZXI/OiBhbnk7XG4gICAgfSk6IFByb21pc2U8YW55PiB7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB3aW5kb3cuYWtpb21hLnF1ZXJ5QnVzaW5lc3NFbnRpdHkob3B0cykuZG9uZShyZXNvbHZlKS5mYWlsKHJlamVjdCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0T2JqZWN0QnlOYW1lKGFyZ3M6IEdldE9iamVjdEJ5TmFtZUFyZ3MpIHtcbiAgICAgIHJldHVybiB3aW5kb3cuYWtpb21hLmdldE9iamVjdEJ5TmFtZShhcmdzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBDTEFQSSBsYXVuY2hDb250YWluZXIgb3B0aW9ucyB0byBjb3JlIGxhdW5jaENvbnRhaW5lciBvcHRpb25zXG4gICAgICogQHBhcmFtIG9wdHMgTGF1bmNoIGNvbnRhaW5lciBvcHRpb25zXG4gICAgICogQHJldHVybnMgTGF1bmNoQ29udGFpbmVyIG9wdGlvbnNcbiAgICAgKi9cbiAgICBzdGF0aWMgY29udmVydExhdW5jaENvbnRhaW5lclBhcmFtcyhvcHRzOiBhbnkpIHtcbiAgICAgIC8vIGNvbnZlcnQgb3B0cy5jYWxsZXIgZnJvbSBTd2F0T2JqZWN0IHRvIGR5bk9iamVjdFxuICAgICAgaWYgKG9wdHMuY2FsbGVyPy5fZHluT2JqZWN0KVxuICAgICAgICBvcHRzLmNhbGxlciA9IG9wdHMuY2FsbGVyLl9keW5PYmplY3Q7XG5cbiAgICAgIC8vIGNvbnZlcnQgb3B0cy50YXJnZXQgZnJvbSBTd2F0T2JqZWN0IHRvIGNvbnRyb2xsZXJcbiAgICAgIGlmIChvcHRzLnRhcmdldD8uX2NvbnRyb2xsZXIpXG4gICAgICAgIG9wdHMudGFyZ2V0ID0gb3B0cy50YXJnZXQuX2NvbnRyb2xsZXI7XG5cbiAgICAgIC8vIGNvbnZlcnQgb3B0cy50YXJnZXQgZnJvbSBkeW5PYmplY3QgdG8gY29udHJvbGxlclxuICAgICAgaWYgKG9wdHMudGFyZ2V0Py5jb250cm9sbGVyKVxuICAgICAgICBvcHRzLnRhcmdldCA9IG9wdHMudGFyZ2V0LmNvbnRyb2xsZXI7XG5cbiAgICAgIC8vIGlmIG9wdHMudGFyZ2V0IGlzIHNldCwgc2V0IGR5bkd1aWQgYW5kIGNvbnRhaW5lcmluZ3VpZCwgaWYgbm90IGFscmVhZHkgc2V0XG4gICAgICBpZiAob3B0cy50YXJnZXQpIHtcbiAgICAgICAgaWYgKCFvcHRzLmR5bkd1aWQpIG9wdHMuZHluR3VpZCA9IHdpbmRvdy5kaHRtbHgudWlkKCk7XG4gICAgICAgIGlmICghb3B0cy5jb250YWluZXJpbnNndWlkKSBvcHRzLmNvbnRhaW5lcmluc2d1aWQgPSBvcHRzLnRhcmdldC5vcHQuX0NvbnRhaW5lckluc3RhbmNlR3VpZDtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdHMucGFyYW1zKSB7XG4gICAgICAgIC8vIHJlbmFtZSBwYXJhbXMgcHJvcGVydGllcyB0byBtYXRjaCBsYXVuY2hDb250YWluZXIgcGFyYW1zXG4gICAgICAgIC8vIGVuc3VyZXMgYmFja3dhcmRzIGNvbXBhdGliaWxpdHksIGRvIG5vdCByZW1vdmVcbiAgICAgICAgaWYgKG9wdHMucGFyYW1zLnR5cGVLZXkpIHtcbiAgICAgICAgICBvcHRzLnBhcmFtcy5UeXBlS2V5ID0gb3B0cy5wYXJhbXMudHlwZUtleTtcbiAgICAgICAgICBkZWxldGUgb3B0cy5wYXJhbXMudHlwZUtleTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRzLnBhcmFtcy5zZWxmSGRsKSB7XG4gICAgICAgICAgb3B0cy5wYXJhbXMuU2VsZkhkbCA9IG9wdHMucGFyYW1zLnNlbGZIZGw7XG4gICAgICAgICAgZGVsZXRlIG9wdHMucGFyYW1zLnNlbGZIZGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0cy5wYXJhbXMuZGF0YVNvdXJjZSkge1xuICAgICAgICAgIG9wdHMucGFyYW1zLkRhdGFzb3VyY2UgPSBvcHRzLnBhcmFtcy5kYXRhU291cmNlO1xuICAgICAgICAgIGRlbGV0ZSBvcHRzLnBhcmFtcy5kYXRhU291cmNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdHMucGFyYW1zLnRhcmdldElkKSB7XG4gICAgICAgICAgb3B0cy5wYXJhbXMuVGFyZ2V0SWQgPSBvcHRzLnBhcmFtcy50YXJnZXRJZDtcbiAgICAgICAgICBkZWxldGUgb3B0cy5wYXJhbXMudGFyZ2V0SWQ7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9wdHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hvd3MgdGhlIG9iamVjdCBuYW1lcyBpbiB0aXRsZXMgZm9yIGRlYnVnZ2luZ1xuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXQgb2JqZWN0TmFtZXNJblRpdGxlcygpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB3aW5kb3cuYXBwLnNlc3Npb25EYXRhLm9iamVjdE5hbWVzSW5UaXRsZXM7XG4gICAgfVxuXG4gICAgc3RhdGljIHNldCBvYmplY3ROYW1lc0luVGl0bGVzKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICB3aW5kb3cuYXBwLnNlc3Npb25EYXRhLm9iamVjdE5hbWVzSW5UaXRsZXMgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZGlzcGxheVZhbGlkYXRpb25FcnJvcigpOiB2b2lkIHtcbiAgICAgICh3aW5kb3cgYXMgYW55KS5kaXNwbGF5VmFsaWRhdGlvbkVycm9yKCk7XG4gICAgfVxuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBMYXVuY2hDb250YWluZXJPcHRpb25zIHtcbiAgICBjb250YWluZXJOYW1lID86IHN0cmluZztcbiAgICBwYWdlcyA/OiBzdHJpbmc7XG4gICAgdmlldz86IHN0cmluZztcbiAgICBmZXRjaE9uSW5pdCA/OiBib29sZWFuO1xuICAgIHBhcmFtcz86IFBhcnRpYWw8e1xuICAgICAgVHlwZUtleT86IHN0cmluZztcbiAgICAgIFNlbGZIZGw/OiBzdHJpbmc7XG4gICAgICBEYXRhc291cmNlPzogc3RyaW5nO1xuICAgICAgVGFyZ2V0SWQ/OiBzdHJpbmc7XG4gICAgICBba2V5OiBzdHJpbmddOiBhbnk7XG4gICAgfT47XG4gICAgZHluR3VpZD86IGJvb2xlYW47XG4gICAgY29udGFpbmVyaW5zZ3VpZD86IHN0cmluZztcbiAgICB0YXJnZXQ/OiBha2lvbWEuc3dhdC5Td2F0T2JqZWN0O1xuICAgIGNhbGxlcj86IGFraW9tYS5zd2F0LlN3YXRPYmplY3Q7XG4gICAgYXV0b0FkZD86IGJvb2xlYW47XG4gICAgYWxsb3dNdWx0aXBsZUluc3RhbmNlcz86IGJvb2xlYW47XG4gICAgZHluYW1pY0xpbmtzPzogRHluYW1pY0xpbmtbXTtcbiAgICBhY3RpdmF0aW9uID86IGJvb2xlYW47XG4gICAgcmVwb3NpdGlvblRvID86IHN0cmluZztcbiAgICBjdXN0b21EYXRhID86IG9iamVjdHxzdHJpbmc7XG4gICAgZm9yZWlnbktleVByb3ZpZGVyID86IHN0cmluZztcbiAgICBzdGFydGluZ1BhZ2UgPzogbnVtYmVyfHN0cmluZztcbiAgfVxuXG4gIGV4cG9ydCB0eXBlIEludm9rZVNlcnZlclRhc2tNZXRob2RUeXBlID0gJ2pzZG8nIHwgJ2F1dG9tYXRpb24nIHwgJ25hbm8nO1xuXG4gIGV4cG9ydCBpbnRlcmZhY2UgSW52b2tlU2VydmVyVGFza09wdGlvbnMge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBtZXRob2ROYW1lOiBzdHJpbmc7XG4gICAgbWV0aG9kVHlwZT86IEludm9rZVNlcnZlclRhc2tNZXRob2RUeXBlO1xuICAgIHNlcnZpY2VVUkk/OiBzdHJpbmc7XG4gICAgc2hvd1dhaXRDdXJzb3I/OiBib29sZWFuO1xuICAgIHVpQ29udGV4dD86IGFraW9tYS5zd2F0LlN3YXRPYmplY3Q7XG4gICAgdGhyb3dEYXRhRXJyb3I/OiBib29sZWFuO1xuICAgIGFyZU5vdGlmaWNhdGlvbnNTaG93bj86IGJvb2xlYW47XG4gICAgcGFyYW1PYmo6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB9XG5cbiAgLyoqXG4gICAqIEludGVyZmFjZSBmb3IgcHJlRXZlbnQgb3B0aW9uc1xuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBFdmVudFByZXZlbnRPcHRpb25zIHtcbiAgICAvKipcbiAgICAqIEBkZXByZWNhdGVkIFVzZSBwcmV2ZW50QWN0aW9uIGluc3RlYWRcbiAgICAqL1xuICAgIHByZXZlbnRMYXVuY2g/OiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIEJvb2xlYW4gdG8gcHJldmVudCBjdXJyZW50IGFjdGlvblxuICAgICAqL1xuICAgIHByZXZlbnRBY3Rpb24/OiBib29sZWFuO1xuICB9XG5cbiAgLyoqXG4gICAqIEludGVyZmFjZSBmb3IgcHJlRXZlbnQgb3B0aW9uc1xuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBFdmVudFByZU9wdGlvbnMgZXh0ZW5kcyBFdmVudFByZXZlbnRPcHRpb25zIHtcbiAgICBuYW1lPzogc3RyaW5nO1xuICAgIG1ldGhvZE5hbWU/OiBzdHJpbmc7XG4gICAgcGFyYW1zPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgb3B0aW9uc0pTT04/OiBQYXJ0aWFsPEludm9rZVNlcnZlclRhc2tPcHRpb25zPjtcbiAgfVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgUGFuZWxNZXNzYWdlIHtcbiAgICB0ZXh0OiBzdHJpbmc7XG4gICAgdHlwZTogc3RyaW5nO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgRHluYW1pY0xpbmsge1xuICAgIHNyYzogTGlua1JlZjtcbiAgICB0cmc6IExpbmtSZWY7XG4gICAgdHlwZTogRHluYW1pY0xpbmtUeXBlO1xuICAgIGFjdGl2ZT86IGJvb2xlYW47XG4gIH1cbiAgZXhwb3J0IHR5cGUgRHluYW1pY0xpbmtUeXBlID0gJ0RBVEEnIHwgJ0RJU1BMQVknIHwgJ1BSSU1BUllEU08nO1xuICBleHBvcnQgdHlwZSBMaW5rUmVmID0gc3RyaW5nIHwgc3RyaW5nW10gfCBha2lvbWEuc3dhdC5Td2F0T2JqZWN0O1xuXG4gIGV4cG9ydCBpbnRlcmZhY2UgR2V0T2JqZWN0QnlOYW1lQXJncyB7XG4gICAgaWQ/OiBzdHJpbmc7XG4gICAgbmFtZT86IHN0cmluZztcbiAgICBzdGFydD86IFJlY29yZDxzdHJpbmcsIGFueT5cbiAgICB2aWV3Pzogc3RyaW5nO1xuICB9XG59XG4iLCJuYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIGV4cG9ydCBjb25zdCBHbG9iYWxIb29rcyA9IHtcbiAgICBPQkpFQ1Q6IHsgQkVGT1JFX0RFU1RST1k6IFsgJ09iamVjdCcsICdCZWZvcmVEZXN0cm95JyBdIH0sXG4gICAgTEFVTkNIOiB7XG4gICAgICBCRUZPUkVfUkVOREVSOiBbICdMYXVuY2hDb250YWluZXInLCAnQmVmb3JlUmVuZGVyJyBdLFxuICAgICAgQUZURVJfTE9BRDogWyAnTGF1bmNoQ29udGFpbmVyJywgJ0FmdGVyTG9hZCcgXVxuICAgIH0sXG4gICAgREFUQVNPVVJDRTogeyBBRlRFUl9TQVZFX0NIQU5HRVM6IFsgJ0RhdGFTb3VyY2UnLCAnQWZ0ZXJTYXZlQ2hhbmdlcycgXSB9LFxuICAgIERFU0tUT1A6IHsgQUZURVJfVE9HR0xFOiBbICdEZXNrdG9wJywgJ0FmdGVyVG9nZ2xlJyBdIH0sXG4gICAgV0lORE9XOiB7XG4gICAgICBDVVNUT01fU1RBVEVfQ0hBTkdFRDogWyAnV2luZG93JywgJ0N1c3RvbVN0YXRlQ2hhbmdlZCcgXSxcbiAgICAgIEhBU19FUlJPUlM6IFsgJ1dpbmRvdycsICdIYXNFcnJvcnMnIF0sXG4gICAgICBIQVNfQ0hBTkdFUzogWyAnV2luZG93JywgJ0hhc0NoYW5nZXMnIF0sXG4gICAgICBDTE9TRTogWyAnV2luZG93JywgJ0Nsb3NlJyBdLFxuICAgICAgRk9DVVM6IFsgJ1dpbmRvdycsICdGb2N1cycgXVxuICAgIH0sXG4gICAgREVTSUdORVI6IHsgQUZURVJfTE9BRDogWyAnRGVzaWduZXInLCAnQWZ0ZXJMb2FkJyBdIH1cbiAgfTtcblxuICBpbnRlcmZhY2UgR2xvYmFsSG9va1BhcmFtcyB7XG4gICAgdmlldz86IHN0cmluZztcbiAgICBuYW1lPzogc3RyaW5nO1xuICAgIGlkPzogc3RyaW5nO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBHbG9iYWxIb29rcyB7XG4gICAgT0JKRUNUOiB7IEJFRk9SRV9ERVNUUk9ZOiBHbG9iYWxIb29rUGFyYW1zIH1cbiAgfVxuXG4gIGV4cG9ydCBjb25zdCBHbG9iYWxFbWl0dGVyID0gY2xhc3Mge1xuICAgIHN0YXRpYyBldmVudHM6IEFycmF5PGFueT4gPSBbXTtcblxuICAgIHN0YXRpYyBvbihldmVudE5hbWU6IHN0cmluZ1tdLCBjYWxsYmFjazogRnVuY3Rpb24pOiBudW1iZXIge1xuICAgICAgd2luZG93LmFraW9tYS5ldmVudEVtaXR0ZXIub24oZXZlbnROYW1lLCBjYWxsYmFjayk7XG4gICAgICByZXR1cm4gdGhpcy5ldmVudHMucHVzaCh7IGV2ZW50TmFtZSwgY2FsbGJhY2sgfSk7XG4gICAgfVxuXG4gICAgc3RhdGljIG9uY2UoZXZlbnROYW1lOiBzdHJpbmdbXSwgY2FsbGJhY2s6IEZ1bmN0aW9uKTogbnVtYmVyIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuZXZlbnRFbWl0dGVyLm9uY2UoZXZlbnROYW1lLCBjYWxsYmFjayk7XG4gICAgICByZXR1cm4gdGhpcy5ldmVudHMucHVzaCh7IGV2ZW50TmFtZSwgY2FsbGJhY2sgfSk7XG4gICAgfVxuXG4gICAgc3RhdGljIG9mZihldmVudE5hbWU6IHN0cmluZ1tdLCBjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgICAgIGNvbnN0IGV2ZW50RW50cnlJbmRleCA9IHRoaXMuZXZlbnRzLmZpbmRJbmRleChldmVudCA9PiBldmVudC5ldmVudE5hbWUgPT09IGV2ZW50TmFtZSAmJiBldmVudC5jYWxsYmFjayA9PT0gY2FsbGJhY2spO1xuICAgICAgaWYgKGV2ZW50RW50cnlJbmRleCA+IC0xKSB7XG4gICAgICAgIHRoaXMuZXZlbnRzLnNwbGljZShldmVudEVudHJ5SW5kZXgsIDEpO1xuICAgICAgICB3aW5kb3cuYWtpb21hLmV2ZW50RW1pdHRlci5vZmYoZXZlbnROYW1lLCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIG9mZkJ5SWQoZXZlbnRJbmRleDogbnVtYmVyKSB7XG4gICAgICBjb25zdCBldmVudEVudHJ5ID0gdGhpcy5ldmVudHNbZXZlbnRJbmRleF07XG4gICAgICBpZiAoZXZlbnRFbnRyeSkge1xuICAgICAgICB0aGlzLmV2ZW50cy5zcGxpY2UoZXZlbnRJbmRleCwgMSk7XG4gICAgICAgIGNvbnN0IHsgZXZlbnROYW1lLCBjYWxsYmFjayB9ID0gZXZlbnRFbnRyeTtcbiAgICAgICAgd2luZG93LmFraW9tYS5ldmVudEVtaXR0ZXIub2ZmKGV2ZW50TmFtZSwgY2FsbGJhY2spO1xuICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyBlbWl0KGV2ZW50TmFtZTogc3RyaW5nW10gfCBzdHJpbmcsIHBhcmFtcz86IGFueSk6IHZvaWQge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93LmFraW9tYS5ldmVudEVtaXR0ZXIuZW1pdChldmVudE5hbWUsIHBhcmFtcyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHdpbmRvdy5ha2lvbWEubG9nLmVycm9yKGUpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbn1cbiIsIm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgaW50ZXJmYWNlIE1lc3NhZ2VCdXR0b24ge1xuICAgIHRleHQ6IHN0cmluZztcbiAgICB2YWx1ZT86IHN0cmluZyB8IG51bWJlcjtcbiAgICB2aXNpYmxlPzogYm9vbGVhbjtcbiAgICBjbGFzc05hbWU/OiBzdHJpbmc7XG4gICAgY2xvc2VNb2RhbD86IGJvb2xlYW47XG4gIH1cblxuICBpbnRlcmZhY2UgQnV0dG9uTGlzdCB7XG4gICAgW2J1dHRvbk5hbWVzcGFjZTogc3RyaW5nXTogTWVzc2FnZUJ1dHRvbiB8IGJvb2xlYW47XG4gIH1cblxuICBpbnRlcmZhY2UgTWVzc2FnZU9wdHMge1xuICAgIGlkPzogc3RyaW5nIHwgbnVtYmVyO1xuICAgIHRpdGxlPzogc3RyaW5nO1xuICAgIHRleHQ/OiBzdHJpbmc7XG4gICAgdHlwZT86IHN0cmluZztcbiAgICBleHBpcmU/OiBudW1iZXI7XG4gICAgb2s/OiBzdHJpbmc7XG4gICAgY2FuY2VsPzogc3RyaW5nO1xuICAgIHdpZHRoPzogc3RyaW5nO1xuICAgIGhlaWdodD86IHN0cmluZztcbiAgICBtb2RhbD86IGJvb2xlYW47XG4gICAgY2xvc2VPbkVzYz86IGJvb2xlYW47XG4gICAgc2hvd01lc3NhZ2VDb2RlPzogYm9vbGVhbjtcbiAgICBjbG9zZU9uQ2xpY2tPdXRzaWRlPzogYm9vbGVhbjtcbiAgICBtb3JldGV4dD86IHN0cmluZztcbiAgICBsaW5rRGVzYz86IHN0cmluZztcbiAgICBsaW5rVmFsdWU/OiBzdHJpbmc7XG4gICAgb3B0aW9ucz86IHN0cmluZztcbiAgICBib3R0b20/OiBzdHJpbmc7XG4gICAgYnV0dG9ucz86IGJvb2xlYW4gfCBzdHJpbmdbXSB8IE1lc3NhZ2VCdXR0b25bXSB8IEJ1dHRvbkxpc3Q7XG4gICAgY2FsbGJhY2s/OiAocmV0VmFsPzogYm9vbGVhbiB8IHN0cmluZykgPT4gdm9pZDtcbiAgfVxuXG4gIGNvbnN0IFNtYXJ0TWVzc2FnZUNhY2hlOiBhbnkgPSB7fTtcblxuICAvKipcbiAgICogTWVzc2FnZSBPYmplY3RcbiAgICogQGV4cG9ydFxuICAgKiBAY2xhc3MgTWVzc2FnZVxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIE1lc3NhZ2Uge1xuXG4gICAgLyoqXG4gICAgICogVGhlIGRlZmF1bHQgbWVzc2FnZSBleHBpcmUgdmFsdWVcbiAgICAgKiBAc3RhdGljXG4gICAgICovXG4gICAgc3RhdGljIGV4cGlyZURlZmF1bHQgPSAxMDAwMDtcblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSBhIHZ1ZSBub3RpZmljYXRpb24gd2l0aCB0aGUgZ2l2ZW4gaWRcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9wdHMuaWQgVGhlIGlkIG9mIHRoZSBub3RpZmljYXRpb24gdG8gdXBkYXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGV4dCBUaGUgbWVzc2FnZSBib2R5XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9wdHMubWVzc2FnZSBUaGUgbWVzc2FnYSBib2R5IHVzZWQgZm9yICdsaW5rJyBtZXNzYWdlIHR5cGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50eXBlIFRoZSBtZXNzYWdlIHR5cGUgaS5lLlxuICAgICAqIGluZm9ybWF0aW9uLCB3YXJuaW5nLCBlcnJvciwgc3VjY2VzcyxcbiAgICAgKiBhbGVydCwgYWxlcnQtaW5mb3JtYXRpb24sIGFsZXJ0LXdhcm5pbmcsIGFsZXJ0LWVycm9yLCBhbGVydC1xdWVzdGlvbixcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb3B0cy5leHBpcmUgVGhlIHRpbWUgcGVyaW9kIHRvIGNsb3NlIHRoZSBtZXNzYWdlIGJveFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcHRzLm1vcmV0ZXh0IEFkZGl0aW9uYWwgdGV4dCB0byBiZSBvcGVuZWQgaW4gc2VwYXJhdGUgd2luZG93XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGl0bGUgVGhlIG1lc3NhZ2UgdGl0bGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5saW5rRGVzYyBUaGUgbGluayBkZXNjcmlwdGlvbiB0byBiZSBkaXNwbGF5ZWQgaW4gbm90aWZpY2F0aW9uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubGlua1ZhbHVlIFRoZSBsaW5rIHZhbHVlIHRvIGJlIGNhbGxlZCB3aGVuIGNsaWNraW5nIG9uIHRoZSBub3RpZmljYXRpb25cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5ib3R0b20gQWRkaXRpb25hbCBib3R0b20gdGV4dCB1c2VkIGZvciAnbGluaycgbWVzc2FnZSB0eXBlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMub3B0aW9ucyBBZGRpdGlvbmFsIG9wdGlvbnMgdXNlZCBmb3IgdGhlIGxpbmtcbiAgICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKi9cbiAgICBzdGF0aWMgdXBkYXRlVnVlTm90aWZpY2F0aW9uKG9wdHM6IE1lc3NhZ2VPcHRzKSA6IHZvaWQge1xuICAgICAgd2luZG93LmFraW9tYS5Ob3RpZmljYXRpb25NZXNzYWdlLnVwZGF0ZVZ1ZU5vdGlmaWNhdGlvbihvcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgdnVlIG5vdGlmaWNhdGlvbiB3aXRoIHRoZSBnaXZlbiBpZFxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gaWQgVGhlIGlkIG9mIHRoZSBub3RpZmljYXRpb24gdG8gdXBkYXRlXG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgc3RhdGljIHJlbW92ZVZ1ZU5vdGlmaWNhdGlvbihpZDogc3RyaW5nKSA6IHZvaWQge1xuICAgICAgd2luZG93LmFraW9tYS5Ob3RpZmljYXRpb25NZXNzYWdlLnJlbW92ZVZ1ZU5vdGlmaWNhdGlvbihpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGlzcGxheXMgYSBtZXNzYWdlXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnRpdGxlIFRoZSBtZXNzYWdlIGJveCB0aXRsZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnRleHQgVGhlIG1lc3NhZ2UgYm94IGJvZHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50eXBlIFRoZSBtZXNzYWdlIGJveCB0eXBlIGkuZS5cbiAgICAgKiBpbmZvcm1hdGlvbiwgd2FybmluZywgZXJyb3IsIHF1ZXN0aW9uLCBzdWNjZXNzLFxuICAgICAqIGFsZXJ0LCBhbGVydC1pbmZvcm1hdGlvbiwgYWxlcnQtd2FybmluZywgYWxlcnQtZXJyb3IsIGFsZXJ0LXF1ZXN0aW9uLFxuICAgICAqIGNvbmZpcm0sIGNvbmZpcm0taW5mb3JtYXRpb24sIGNvbmZpcm0td2FybmluZywgY29uZmlybS1lcnJvciwgY29uZmlybS1xdWVzdGlvblxuICAgICAqIGFsdGVybmF0aXZlbHkgYSBjdXN0b20gY3NzIGNsYXNzXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9wdHMuZXhwaXJlIFRoZSB0aW1lIHBlcmlvZCB0byBjbG9zZSB0aGUgbWVzc2FnZSBib3hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5vayBUaGUgb2sgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5jYW5jZWwgdGhlIGNhbmNlbCBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLndpZHRoIFRoZSBjc3Mgd2lkdGggc3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuaGVpZ2h0IFRoZSBjc3MgaGVpZ2h0IHN0cmluZ1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5jbG9zZU9uRXNjICBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSB3aGVuIEVTQyBpcyBwcmVzc2VkIG9uIGtleWJvYXJkLiBkZWZhdWx0IGlzIFwidHJ1ZVwiXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25DbGlja091dHNpZGUgVGhlIG1lc3NhZ2UgYm94IHdpbGwgY2xvc2UgaWYgY2xpY2tlZCBvbiBvdmVybGF5IG9yIG91dHNpZGUgb2YgdGhlIG1vZGFsIGJveCBjb250ZW50LiBkZWZhdWx0IGlzIFwiZmFsc2VcIlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbnxzdHJpbmdbXXxNZXNzYWdlQnV0dG9uW118QnV0dG9uTGlzdH0gb3B0cy5idXR0b25zIFRoZSBtb2RhbCBtZXNzYWdlIGJ1dHRvbnMgdG8gZGlzcGxheVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IG9wdHMuY2FsbGJhY2sgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGFmdGVyIGNsaWNraW5nIHRoZSBvay9jYW5jZWwgYnV0dG9ucyB3aXRoIHRoZSByZXN1bHRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBtZXNzYWdlKHRleHQ6IHN0cmluZyk6IHN0cmluZztcbiAgICBzdGF0aWMgbWVzc2FnZShvcHRzOiBNZXNzYWdlT3B0cyk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIERpc3BsYXlzIGEgbWVzc2FnZVxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50aXRsZSBUaGUgbWVzc2FnZSBib3ggdGl0bGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50ZXh0IFRoZSBtZXNzYWdlIGJveCBib2R5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudHlwZSBUaGUgbWVzc2FnZSBib3ggdHlwZSBpLmUuXG4gICAgICogaW5mb3JtYXRpb24sIHdhcm5pbmcsIGVycm9yLCBxdWVzdGlvbiwgc3VjY2VzcyxcbiAgICAgKiBhbGVydCwgYWxlcnQtaW5mb3JtYXRpb24sIGFsZXJ0LXdhcm5pbmcsIGFsZXJ0LWVycm9yLCBhbGVydC1xdWVzdGlvbixcbiAgICAgKiBjb25maXJtLCBjb25maXJtLWluZm9ybWF0aW9uLCBjb25maXJtLXdhcm5pbmcsIGNvbmZpcm0tZXJyb3IsIGNvbmZpcm0tcXVlc3Rpb25cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb3B0cy5leHBpcmUgVGhlIHRpbWUgcGVyaW9kIHRvIGNsb3NlIHRoZSBtZXNzYWdlIGJveFxuICAgICAqIEBwYXJhbSB7TWVzc2FnZUJ1dHRvbn0gb3B0cy5vayBUaGUgb2sgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge01lc3NhZ2VCdXR0b259IG9wdHMuY2FuY2VsIHRoZSBjYW5jZWwgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy53aWR0aCBUaGUgY3NzIHdpZHRoIHN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmhlaWdodCBUaGUgY3NzIGhlaWdodCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkVzYyAgVGhlIG1lc3NhZ2UgYm94IHdpbGwgY2xvc2Ugd2hlbiBFU0MgaXMgcHJlc3NlZCBvbiBrZXlib2FyZC4gZGVmYXVsdCBpcyBcInRydWVcIlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy52dWUgRm9yIG5vdGlmaWNhdGlvbiBtZXNzYWdlLCBzcGVjaWZpZXMgaWYgaXQgc2hvdWxkIHVzZSBkaHhtbHggb3IgdnVlIG5vdGlmaWNhdGlvbiAoZGVmYXVsdHMgdG8gZGh0bWx4IGlmIG5vdCBzcGVjaWZpZWQpXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25DbGlja091dHNpZGUgVGhlIG1lc3NhZ2UgYm94IHdpbGwgY2xvc2UgaWYgY2xpY2tlZCBvbiBvdmVybGF5IG9yIG91dHNpZGUgb2YgdGhlIG1vZGFsIGJveCBjb250ZW50LiBkZWZhdWx0IGlzIFwiZmFsc2VcIlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5zaG93TWVzc2FnZUNvZGUgUmVtb3ZlIHRoZSBpbmZvcm1hdGlvbiBtZXNzYWdlIHRleHQgaW5mbyBncm91cCBhbmQgbnVtYmVyLCB0ZXh0IGRpc3BsYXllZCBiZXR3ZWVuIHBhcmVudGhlc2VzLCBkZWZhdWx0IGlzIFwiZmFsc2VcIlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm1vZGFsIGlmIGl0IHNob3VsZCBiZSBhIG1vZGFsIG9yIG5vbi1tb2RhbCB3aW5kb3dcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5tb3JldGV4dCBUaGUgdGV4dCB0byBhZGQgaW5zaWRlIHRoZSByZXN1bHRpbmcgd2luZG93IG1vZGFsIGFzIGluZm9ybWF0aW9uLCB3aWxsIGFkZCBtb3JlIGJ1dHRvblxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbnxzdHJpbmdbXXxNZXNzYWdlQnV0dG9uW118QnV0dG9uTGlzdH0gb3B0cy5idXR0b25zIFRoZSBtb2RhbCBtZXNzYWdlIGJ1dHRvbnMgdG8gZGlzcGxheVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IG9wdHMuY2FsbGJhY2sgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGFmdGVyIGNsaWNraW5nIHRoZSBvay9jYW5jZWwgYnV0dG9ucyB3aXRoIHRoZSByZXN1bHRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBtZXNzYWdlKG9wdHM6IGFueSkgOiBTdHJpbmcge1xuXG4gICAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgICAgaWYgKHR5cGVvZiBvcHRzID09PSAnc3RyaW5nJylcbiAgICAgICAgb3B0cyA9IHsgdGV4dDogb3B0cyB9O1xuXG4gICAgICBpZiAob3B0cy50eXBlID09PSB1bmRlZmluZWQpXG4gICAgICAgIG9wdHMudHlwZSA9ICdlcnJvcic7XG5cbiAgICAgIGlmIChvcHRzLmV4cGlyZSA9PT0gdW5kZWZpbmVkICYmIG9wdHMubGlmZXRpbWUgIT09IHVuZGVmaW5lZClcbiAgICAgICAgb3B0cy5leHBpcmUgPSBvcHRzLmxpZmV0aW1lO1xuXG4gICAgICBpZiAob3B0cy5leHBpcmUgPT09IHVuZGVmaW5lZClcbiAgICAgICAgb3B0cy5leHBpcmUgPSB0aGlzLmV4cGlyZURlZmF1bHQgfHwgMTAwMDA7XG5cbiAgICAgIGlmIChvcHRzLmV4cGlyZSA9PT0gMClcbiAgICAgICAgb3B0cy5leHBpcmUgPSAtMTtcblxuICAgICAgaWYgKG9wdHMuc2hvd01lc3NhZ2VDb2RlID09PSBmYWxzZSlcbiAgICAgICAgb3B0cy50ZXh0ID0gb3B0cy50ZXh0LnJlcGxhY2UoLyAqXFwoW14pXSpcXCkgKi9nLCAnJyk7XG5cbiAgICAgIC8vIGlmIHN0YXJ0cyB3aXRoIGFsZXJ0IGF1dG9tYXRpY2FsbHkgc2V0IGFzIG1vZGFsXG4gICAgICBpZiAob3B0cy50eXBlLnN0YXJ0c1dpdGgoJ2FsZXJ0JykpIHtcbiAgICAgICAgb3B0cy50eXBlID0gb3B0cy50eXBlLnJlcGxhY2UoJ2FsZXJ0LScsICcnKTtcbiAgICAgICAgb3B0cy5tb2RhbCA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRzLnR5cGUuc3RhcnRzV2l0aCgnY29uZmlybScpKSB7XG4gICAgICAgIG9wdHMudHlwZSA9IG9wdHMudHlwZS5yZXBsYWNlKCdjb25maXJtLScsICcnKTtcbiAgICAgICAgb3B0cy5tb2RhbCA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRzLnR5cGUgPT09ICdxdWVzdGlvbicgfHwgb3B0cy50eXBlID09PSAnaW5wdXQnKVxuICAgICAgICBvcHRzLm1vZGFsID0gdHJ1ZTtcblxuICAgICAgaWYgKG9wdHMubW9kYWwpXG4gICAgICAgIHJldHVybiB3aW5kb3cuYWtpb21hLm1lc3NhZ2Uob3B0cyk7XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiB3aW5kb3cuYWtpb21hLm5vdGlmaWNhdGlvbihvcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbGVydCBtZXNzYWdlLiBTYW1lIGFzIG1lc3NhZ2Uoe3R5cGU6ICdhbGVydCd9KS5cbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGl0bGUgVGhlIG1lc3NhZ2UgYm94IHRpdGxlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGV4dCBUaGUgbWVzc2FnZSBib3ggYm9keVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnR5cGUgVGhlIG1lc3NhZ2UgYm94IHR5cGUgaS5lLlxuICAgICAqIGluZm9ybWF0aW9uLCB3YXJuaW5nLCBlcnJvciwgcXVlc3Rpb24sIHN1Y2Nlc3MsXG4gICAgICogYWxlcnQsIGFsZXJ0LWluZm9ybWF0aW9uLCBhbGVydC13YXJuaW5nLCBhbGVydC1lcnJvciwgYWxlcnQtcXVlc3Rpb24sXG4gICAgICogY29uZmlybSwgY29uZmlybS1pbmZvcm1hdGlvbiwgY29uZmlybS13YXJuaW5nLCBjb25maXJtLWVycm9yLCBjb25maXJtLXF1ZXN0aW9uXG4gICAgICogYWx0ZXJuYXRpdmVseSBhIGN1c3RvbSBjc3MgY2xhc3NcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb3B0cy5leHBpcmUgVGhlIHRpbWUgcGVyaW9kIHRvIGNsb3NlIHRoZSBtZXNzYWdlIGJveFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm9rIFRoZSBvayBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmNhbmNlbCB0aGUgY2FuY2VsIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMud2lkdGggVGhlIGNzcyB3aWR0aCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5oZWlnaHQgVGhlIGNzcyBoZWlnaHQgc3RyaW5nXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25Fc2MgIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIHdoZW4gRVNDIGlzIHByZXNzZWQgb24ga2V5Ym9hcmQuIGRlZmF1bHQgaXMgXCJ0cnVlXCJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkNsaWNrT3V0c2lkZSBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSBpZiBjbGlja2VkIG9uIG92ZXJsYXkgb3Igb3V0c2lkZSBvZiB0aGUgbW9kYWwgYm94IGNvbnRlbnQuIGRlZmF1bHQgaXMgXCJmYWxzZVwiXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubW9yZXRleHQgVGhlIHRleHQgdG8gYWRkIGluc2lkZSB0aGUgcmVzdWx0aW5nIHdpbmRvdyBtb2RhbCBhcyBpbmZvcm1hdGlvbiwgd2lsbCBhZGQgbW9yZSBidXR0b25cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW58c3RyaW5nW118TWVzc2FnZUJ1dHRvbltdfEJ1dHRvbkxpc3R9IG9wdHMuYnV0dG9ucyBUaGUgbW9kYWwgbWVzc2FnZSBidXR0b25zIHRvIGRpc3BsYXlcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBvcHRzLmNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvbiBhZnRlciBjbGlja2luZyB0aGUgb2svY2FuY2VsIGJ1dHRvbnMgd2l0aCB0aGUgcmVzdWx0XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgYWxlcnQodGV4dDogc3RyaW5nKTogc3RyaW5nO1xuICAgIHN0YXRpYyBhbGVydChvcHRzOiBNZXNzYWdlT3B0cyk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEFsZXJ0IG1lc3NhZ2UuIFNhbWUgYXMgbWVzc2FnZSh7dHlwZTogJ2FsZXJ0J30pLlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50aXRsZSBUaGUgbWVzc2FnZSBib3ggdGl0bGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50ZXh0IFRoZSBtZXNzYWdlIGJveCBib2R5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudHlwZSBUaGUgbWVzc2FnZSBib3ggdHlwZSBpLmUuXG4gICAgICogaW5mb3JtYXRpb24sIHdhcm5pbmcsIGVycm9yLCBxdWVzdGlvbiwgc3VjY2VzcyxcbiAgICAgKiBhbGVydCwgYWxlcnQtaW5mb3JtYXRpb24sIGFsZXJ0LXdhcm5pbmcsIGFsZXJ0LWVycm9yLCBhbGVydC1xdWVzdGlvbixcbiAgICAgKiBjb25maXJtLCBjb25maXJtLWluZm9ybWF0aW9uLCBjb25maXJtLXdhcm5pbmcsIGNvbmZpcm0tZXJyb3IsIGNvbmZpcm0tcXVlc3Rpb25cbiAgICAgKiBhbHRlcm5hdGl2ZWx5IGEgY3VzdG9tIGNzcyBjbGFzc1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcHRzLmV4cGlyZSBUaGUgdGltZSBwZXJpb2QgdG8gY2xvc2UgdGhlIG1lc3NhZ2UgYm94XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMub2sgVGhlIG9rIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuY2FuY2VsIHRoZSBjYW5jZWwgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy53aWR0aCBUaGUgY3NzIHdpZHRoIHN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmhlaWdodCBUaGUgY3NzIGhlaWdodCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkVzYyAgVGhlIG1lc3NhZ2UgYm94IHdpbGwgY2xvc2Ugd2hlbiBFU0MgaXMgcHJlc3NlZCBvbiBrZXlib2FyZC4gZGVmYXVsdCBpcyBcInRydWVcIlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5jbG9zZU9uQ2xpY2tPdXRzaWRlIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIGlmIGNsaWNrZWQgb24gb3ZlcmxheSBvciBvdXRzaWRlIG9mIHRoZSBtb2RhbCBib3ggY29udGVudC4gZGVmYXVsdCBpcyBcImZhbHNlXCJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5tb3JldGV4dCBUaGUgdGV4dCB0byBhZGQgaW5zaWRlIHRoZSByZXN1bHRpbmcgd2luZG93IG1vZGFsIGFzIGluZm9ybWF0aW9uLCB3aWxsIGFkZCBtb3JlIGJ1dHRvblxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbnxzdHJpbmdbXXxNZXNzYWdlQnV0dG9uW118QnV0dG9uTGlzdH0gb3B0cy5idXR0b25zIFRoZSBtb2RhbCBtZXNzYWdlIGJ1dHRvbnMgdG8gZGlzcGxheVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IG9wdHMuY2FsbGJhY2sgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGFmdGVyIGNsaWNraW5nIHRoZSBvay9jYW5jZWwgYnV0dG9ucyB3aXRoIHRoZSByZXN1bHRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWxlcnQob3B0czogYW55KSA6IHN0cmluZyB7XG5cbiAgICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gICAgICBpZiAodHlwZW9mIG9wdHMgPT09ICdzdHJpbmcnKVxuICAgICAgICBvcHRzID0geyB0ZXh0OiBvcHRzIH07XG5cbiAgICAgIGlmICghb3B0cy50eXBlKVxuICAgICAgICBvcHRzLnR5cGUgPSAnYWxlcnQnO1xuXG4gICAgICByZXR1cm4gdGhpcy5tZXNzYWdlKG9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbmZpcm0gbWVzc2FnZS4gU2FtZSBhcyBtZXNzYWdlKHt0eXBlOiAnY29uZmlybSd9KS5cbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGl0bGUgVGhlIG1lc3NhZ2UgYm94IHRpdGxlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGV4dCBUaGUgbWVzc2FnZSBib3ggYm9keVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnR5cGUgVGhlIG1lc3NhZ2UgYm94IHR5cGUgaS5lLlxuICAgICAqIGluZm9ybWF0aW9uLCB3YXJuaW5nLCBlcnJvciwgcXVlc3Rpb24sIHN1Y2Nlc3MsXG4gICAgICogYWxlcnQsIGFsZXJ0LWluZm9ybWF0aW9uLCBhbGVydC13YXJuaW5nLCBhbGVydC1lcnJvciwgYWxlcnQtcXVlc3Rpb24sXG4gICAgICogY29uZmlybSwgY29uZmlybS1pbmZvcm1hdGlvbiwgY29uZmlybS13YXJuaW5nLCBjb25maXJtLWVycm9yLCBjb25maXJtLXF1ZXN0aW9uXG4gICAgICogYWx0ZXJuYXRpdmVseSBhIGN1c3RvbSBjc3MgY2xhc3NcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb3B0cy5leHBpcmUgVGhlIHRpbWUgcGVyaW9kIHRvIGNsb3NlIHRoZSBtZXNzYWdlIGJveFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm9rIFRoZSBvayBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmNhbmNlbCB0aGUgY2FuY2VsIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMud2lkdGggVGhlIGNzcyB3aWR0aCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5oZWlnaHQgVGhlIGNzcyBoZWlnaHQgc3RyaW5nXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25Fc2MgIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIHdoZW4gRVNDIGlzIHByZXNzZWQgb24ga2V5Ym9hcmQuIGRlZmF1bHQgaXMgXCJ0cnVlXCJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkNsaWNrT3V0c2lkZSBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSBpZiBjbGlja2VkIG9uIG92ZXJsYXkgb3Igb3V0c2lkZSBvZiB0aGUgbW9kYWwgYm94IGNvbnRlbnQuIGRlZmF1bHQgaXMgXCJmYWxzZVwiXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubW9yZXRleHQgVGhlIHRleHQgdG8gYWRkIGluc2lkZSB0aGUgcmVzdWx0aW5nIHdpbmRvdyBtb2RhbCBhcyBpbmZvcm1hdGlvbiwgd2lsbCBhZGQgbW9yZSBidXR0b25cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW58c3RyaW5nW118TWVzc2FnZUJ1dHRvbltdfEJ1dHRvbkxpc3R9IG9wdHMuYnV0dG9ucyBUaGUgbW9kYWwgbWVzc2FnZSBidXR0b25zIHRvIGRpc3BsYXlcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBvcHRzLmNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvbiBhZnRlciBjbGlja2luZyB0aGUgb2svY2FuY2VsIGJ1dHRvbnMgd2l0aCB0aGUgcmVzdWx0XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgY29uZmlybSh0ZXh0OiBzdHJpbmcpOiBzdHJpbmc7XG4gICAgc3RhdGljIGNvbmZpcm0ob3B0czogTWVzc2FnZU9wdHMpOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBDb25maXJtIG1lc3NhZ2UuIFNhbWUgYXMgbWVzc2FnZSh7dHlwZTogJ2NvbmZpcm0nfSkuXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnRpdGxlIFRoZSBtZXNzYWdlIGJveCB0aXRsZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnRleHQgVGhlIG1lc3NhZ2UgYm94IGJvZHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50eXBlIFRoZSBtZXNzYWdlIGJveCB0eXBlIGkuZS5cbiAgICAgKiBpbmZvcm1hdGlvbiwgd2FybmluZywgZXJyb3IsIHF1ZXN0aW9uLCBzdWNjZXNzLFxuICAgICAqIGFsZXJ0LCBhbGVydC1pbmZvcm1hdGlvbiwgYWxlcnQtd2FybmluZywgYWxlcnQtZXJyb3IsIGFsZXJ0LXF1ZXN0aW9uLFxuICAgICAqIGNvbmZpcm0sIGNvbmZpcm0taW5mb3JtYXRpb24sIGNvbmZpcm0td2FybmluZywgY29uZmlybS1lcnJvciwgY29uZmlybS1xdWVzdGlvblxuICAgICAqIGFsdGVybmF0aXZlbHkgYSBjdXN0b20gY3NzIGNsYXNzXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9wdHMuZXhwaXJlIFRoZSB0aW1lIHBlcmlvZCB0byBjbG9zZSB0aGUgbWVzc2FnZSBib3hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5vayBUaGUgb2sgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5jYW5jZWwgdGhlIGNhbmNlbCBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLndpZHRoIFRoZSBjc3Mgd2lkdGggc3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuaGVpZ2h0IFRoZSBjc3MgaGVpZ2h0IHN0cmluZ1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5jbG9zZU9uRXNjICBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSB3aGVuIEVTQyBpcyBwcmVzc2VkIG9uIGtleWJvYXJkLiBkZWZhdWx0IGlzIFwidHJ1ZVwiXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25DbGlja091dHNpZGUgVGhlIG1lc3NhZ2UgYm94IHdpbGwgY2xvc2UgaWYgY2xpY2tlZCBvbiBvdmVybGF5IG9yIG91dHNpZGUgb2YgdGhlIG1vZGFsIGJveCBjb250ZW50LiBkZWZhdWx0IGlzIFwiZmFsc2VcIlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm1vcmV0ZXh0IFRoZSB0ZXh0IHRvIGFkZCBpbnNpZGUgdGhlIHJlc3VsdGluZyB3aW5kb3cgbW9kYWwgYXMgaW5mb3JtYXRpb24sIHdpbGwgYWRkIG1vcmUgYnV0dG9uXG4gICAgICogQHBhcmFtIHtib29sZWFufHN0cmluZ1tdfE1lc3NhZ2VCdXR0b25bXXxCdXR0b25MaXN0fSBvcHRzLmJ1dHRvbnMgVGhlIG1vZGFsIG1lc3NhZ2UgYnV0dG9ucyB0byBkaXNwbGF5XG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gb3B0cy5jYWxsYmFjayBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gYWZ0ZXIgY2xpY2tpbmcgdGhlIG9rL2NhbmNlbCBidXR0b25zIHdpdGggdGhlIHJlc3VsdFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIGNvbmZpcm0ob3B0czogYW55KSA6IHN0cmluZyB7XG5cbiAgICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gICAgICBpZiAodHlwZW9mIG9wdHMgPT09ICdzdHJpbmcnKVxuICAgICAgICBvcHRzID0geyB0ZXh0OiBvcHRzIH07XG5cbiAgICAgIGlmICghb3B0cy50eXBlKVxuICAgICAgICBvcHRzLnR5cGUgPSAnY29uZmlybSc7XG5cbiAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2Uob3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5mb3JtYXRpb24gbWVzc2FnZS4gU2FtZSBhcyBtZXNzYWdlKHt0eXBlOiAnaW5mb3JtYXRpb24nfSkuXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnRpdGxlIFRoZSBtZXNzYWdlIGJveCB0aXRsZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnRleHQgVGhlIG1lc3NhZ2UgYm94IGJvZHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50eXBlIFRoZSBtZXNzYWdlIGJveCB0eXBlIGkuZS5cbiAgICAgKiBpbmZvcm1hdGlvbiwgd2FybmluZywgZXJyb3IsIHF1ZXN0aW9uLCBzdWNjZXNzLFxuICAgICAqIGFsZXJ0LCBhbGVydC1pbmZvcm1hdGlvbiwgYWxlcnQtd2FybmluZywgYWxlcnQtZXJyb3IsIGFsZXJ0LXF1ZXN0aW9uLFxuICAgICAqIGNvbmZpcm0sIGNvbmZpcm0taW5mb3JtYXRpb24sIGNvbmZpcm0td2FybmluZywgY29uZmlybS1lcnJvciwgY29uZmlybS1xdWVzdGlvblxuICAgICAqIGFsdGVybmF0aXZlbHkgYSBjdXN0b20gY3NzIGNsYXNzXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9wdHMuZXhwaXJlIFRoZSB0aW1lIHBlcmlvZCB0byBjbG9zZSB0aGUgbWVzc2FnZSBib3hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5vayBUaGUgb2sgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5jYW5jZWwgdGhlIGNhbmNlbCBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLndpZHRoIFRoZSBjc3Mgd2lkdGggc3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuaGVpZ2h0IFRoZSBjc3MgaGVpZ2h0IHN0cmluZ1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5jbG9zZU9uRXNjICBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSB3aGVuIEVTQyBpcyBwcmVzc2VkIG9uIGtleWJvYXJkLiBkZWZhdWx0IGlzIFwidHJ1ZVwiXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25DbGlja091dHNpZGUgVGhlIG1lc3NhZ2UgYm94IHdpbGwgY2xvc2UgaWYgY2xpY2tlZCBvbiBvdmVybGF5IG9yIG91dHNpZGUgb2YgdGhlIG1vZGFsIGJveCBjb250ZW50LiBkZWZhdWx0IGlzIFwiZmFsc2VcIlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm1vcmV0ZXh0IFRoZSB0ZXh0IHRvIGFkZCBpbnNpZGUgdGhlIHJlc3VsdGluZyB3aW5kb3cgbW9kYWwgYXMgaW5mb3JtYXRpb24sIHdpbGwgYWRkIG1vcmUgYnV0dG9uXG4gICAgICogQHBhcmFtIHtib29sZWFufHN0cmluZ1tdfE1lc3NhZ2VCdXR0b25bXXxCdXR0b25MaXN0fSBvcHRzLmJ1dHRvbnMgVGhlIG1vZGFsIG1lc3NhZ2UgYnV0dG9ucyB0byBkaXNwbGF5XG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gb3B0cy5jYWxsYmFjayBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gYWZ0ZXIgY2xpY2tpbmcgdGhlIG9rL2NhbmNlbCBidXR0b25zIHdpdGggdGhlIHJlc3VsdFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIGluZm9ybWF0aW9uTWVzc2FnZSh0ZXh0OiBzdHJpbmcpOiBzdHJpbmc7XG4gICAgc3RhdGljIGluZm9ybWF0aW9uTWVzc2FnZShvcHRzOiBNZXNzYWdlT3B0cyk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEluZm9ybWF0aW9uIG1lc3NhZ2UuIFNhbWUgYXMgbWVzc2FnZSh7dHlwZTogJ2luZm9ybWF0aW9uJ30pLlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50aXRsZSBUaGUgbWVzc2FnZSBib3ggdGl0bGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50ZXh0IFRoZSBtZXNzYWdlIGJveCBib2R5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudHlwZSBUaGUgbWVzc2FnZSBib3ggdHlwZSBpLmUuXG4gICAgICogaW5mb3JtYXRpb24sIHdhcm5pbmcsIGVycm9yLCBxdWVzdGlvbiwgc3VjY2VzcyxcbiAgICAgKiBhbGVydCwgYWxlcnQtaW5mb3JtYXRpb24sIGFsZXJ0LXdhcm5pbmcsIGFsZXJ0LWVycm9yLCBhbGVydC1xdWVzdGlvbixcbiAgICAgKiBjb25maXJtLCBjb25maXJtLWluZm9ybWF0aW9uLCBjb25maXJtLXdhcm5pbmcsIGNvbmZpcm0tZXJyb3IsIGNvbmZpcm0tcXVlc3Rpb25cbiAgICAgKiBhbHRlcm5hdGl2ZWx5IGEgY3VzdG9tIGNzcyBjbGFzc1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcHRzLmV4cGlyZSBUaGUgdGltZSBwZXJpb2QgdG8gY2xvc2UgdGhlIG1lc3NhZ2UgYm94XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMub2sgVGhlIG9rIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuY2FuY2VsIHRoZSBjYW5jZWwgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy53aWR0aCBUaGUgY3NzIHdpZHRoIHN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmhlaWdodCBUaGUgY3NzIGhlaWdodCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkVzYyAgVGhlIG1lc3NhZ2UgYm94IHdpbGwgY2xvc2Ugd2hlbiBFU0MgaXMgcHJlc3NlZCBvbiBrZXlib2FyZC4gZGVmYXVsdCBpcyBcInRydWVcIlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5jbG9zZU9uQ2xpY2tPdXRzaWRlIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIGlmIGNsaWNrZWQgb24gb3ZlcmxheSBvciBvdXRzaWRlIG9mIHRoZSBtb2RhbCBib3ggY29udGVudC4gZGVmYXVsdCBpcyBcImZhbHNlXCJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5tb3JldGV4dCBUaGUgdGV4dCB0byBhZGQgaW5zaWRlIHRoZSByZXN1bHRpbmcgd2luZG93IG1vZGFsIGFzIGluZm9ybWF0aW9uLCB3aWxsIGFkZCBtb3JlIGJ1dHRvblxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbnxzdHJpbmdbXXxNZXNzYWdlQnV0dG9uW118QnV0dG9uTGlzdH0gb3B0cy5idXR0b25zIFRoZSBtb2RhbCBtZXNzYWdlIGJ1dHRvbnMgdG8gZGlzcGxheVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IG9wdHMuY2FsbGJhY2sgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGFmdGVyIGNsaWNraW5nIHRoZSBvay9jYW5jZWwgYnV0dG9ucyB3aXRoIHRoZSByZXN1bHRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBpbmZvcm1hdGlvbk1lc3NhZ2Uob3B0czogYW55KSA6IHN0cmluZyB7XG5cbiAgICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gICAgICBpZiAodHlwZW9mIG9wdHMgPT09ICdzdHJpbmcnKVxuICAgICAgICBvcHRzID0geyB0ZXh0OiBvcHRzIH07XG5cbiAgICAgIGlmICghb3B0cy50eXBlKVxuICAgICAgICBvcHRzLnR5cGUgPSAnaW5mb3JtYXRpb24nO1xuXG4gICAgICByZXR1cm4gdGhpcy5tZXNzYWdlKG9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdhcm5pbmcgbWVzc2FnZS4gU2FtZSBhcyBtZXNzYWdlKHt0eXBlOiAnd2FybmluZyd9KS5cbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGl0bGUgVGhlIG1lc3NhZ2UgYm94IHRpdGxlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGV4dCBUaGUgbWVzc2FnZSBib3ggYm9keVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnR5cGUgVGhlIG1lc3NhZ2UgYm94IHR5cGUgaS5lLlxuICAgICAqIGluZm9ybWF0aW9uLCB3YXJuaW5nLCBlcnJvciwgcXVlc3Rpb24sIHN1Y2Nlc3MsXG4gICAgICogYWxlcnQsIGFsZXJ0LWluZm9ybWF0aW9uLCBhbGVydC13YXJuaW5nLCBhbGVydC1lcnJvciwgYWxlcnQtcXVlc3Rpb24sXG4gICAgICogY29uZmlybSwgY29uZmlybS1pbmZvcm1hdGlvbiwgY29uZmlybS13YXJuaW5nLCBjb25maXJtLWVycm9yLCBjb25maXJtLXF1ZXN0aW9uXG4gICAgICogYWx0ZXJuYXRpdmVseSBhIGN1c3RvbSBjc3MgY2xhc3NcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb3B0cy5leHBpcmUgVGhlIHRpbWUgcGVyaW9kIHRvIGNsb3NlIHRoZSBtZXNzYWdlIGJveFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm9rIFRoZSBvayBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmNhbmNlbCB0aGUgY2FuY2VsIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMud2lkdGggVGhlIGNzcyB3aWR0aCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5oZWlnaHQgVGhlIGNzcyBoZWlnaHQgc3RyaW5nXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25Fc2MgIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIHdoZW4gRVNDIGlzIHByZXNzZWQgb24ga2V5Ym9hcmQuIGRlZmF1bHQgaXMgXCJ0cnVlXCJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkNsaWNrT3V0c2lkZSBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSBpZiBjbGlja2VkIG9uIG92ZXJsYXkgb3Igb3V0c2lkZSBvZiB0aGUgbW9kYWwgYm94IGNvbnRlbnQuIGRlZmF1bHQgaXMgXCJmYWxzZVwiXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubW9yZXRleHQgVGhlIHRleHQgdG8gYWRkIGluc2lkZSB0aGUgcmVzdWx0aW5nIHdpbmRvdyBtb2RhbCBhcyBpbmZvcm1hdGlvbiwgd2lsbCBhZGQgbW9yZSBidXR0b25cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW58c3RyaW5nW118TWVzc2FnZUJ1dHRvbltdfEJ1dHRvbkxpc3R9IG9wdHMuYnV0dG9ucyBUaGUgbW9kYWwgbWVzc2FnZSBidXR0b25zIHRvIGRpc3BsYXlcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBvcHRzLmNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvbiBhZnRlciBjbGlja2luZyB0aGUgb2svY2FuY2VsIGJ1dHRvbnMgd2l0aCB0aGUgcmVzdWx0XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgd2FybmluZ01lc3NhZ2UodGV4dDogc3RyaW5nKTogc3RyaW5nO1xuICAgIHN0YXRpYyB3YXJuaW5nTWVzc2FnZShvcHRzOiBNZXNzYWdlT3B0cyk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFdhcm5pbmcgbWVzc2FnZS4gU2FtZSBhcyBtZXNzYWdlKHt0eXBlOiAnd2FybmluZyd9KS5cbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGl0bGUgVGhlIG1lc3NhZ2UgYm94IHRpdGxlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGV4dCBUaGUgbWVzc2FnZSBib3ggYm9keVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnR5cGUgVGhlIG1lc3NhZ2UgYm94IHR5cGUgaS5lLlxuICAgICAqIGluZm9ybWF0aW9uLCB3YXJuaW5nLCBlcnJvciwgcXVlc3Rpb24sIHN1Y2Nlc3MsXG4gICAgICogYWxlcnQsIGFsZXJ0LWluZm9ybWF0aW9uLCBhbGVydC13YXJuaW5nLCBhbGVydC1lcnJvciwgYWxlcnQtcXVlc3Rpb24sXG4gICAgICogY29uZmlybSwgY29uZmlybS1pbmZvcm1hdGlvbiwgY29uZmlybS13YXJuaW5nLCBjb25maXJtLWVycm9yLCBjb25maXJtLXF1ZXN0aW9uXG4gICAgICogYWx0ZXJuYXRpdmVseSBhIGN1c3RvbSBjc3MgY2xhc3NcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb3B0cy5leHBpcmUgVGhlIHRpbWUgcGVyaW9kIHRvIGNsb3NlIHRoZSBtZXNzYWdlIGJveFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm9rIFRoZSBvayBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmNhbmNlbCB0aGUgY2FuY2VsIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMud2lkdGggVGhlIGNzcyB3aWR0aCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5oZWlnaHQgVGhlIGNzcyBoZWlnaHQgc3RyaW5nXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25Fc2MgIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIHdoZW4gRVNDIGlzIHByZXNzZWQgb24ga2V5Ym9hcmQuIGRlZmF1bHQgaXMgXCJ0cnVlXCJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkNsaWNrT3V0c2lkZSBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSBpZiBjbGlja2VkIG9uIG92ZXJsYXkgb3Igb3V0c2lkZSBvZiB0aGUgbW9kYWwgYm94IGNvbnRlbnQuIGRlZmF1bHQgaXMgXCJmYWxzZVwiXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubW9yZXRleHQgVGhlIHRleHQgdG8gYWRkIGluc2lkZSB0aGUgcmVzdWx0aW5nIHdpbmRvdyBtb2RhbCBhcyBpbmZvcm1hdGlvbiwgd2lsbCBhZGQgbW9yZSBidXR0b25cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW58c3RyaW5nW118TWVzc2FnZUJ1dHRvbltdfEJ1dHRvbkxpc3R9IG9wdHMuYnV0dG9ucyBUaGUgbW9kYWwgbWVzc2FnZSBidXR0b25zIHRvIGRpc3BsYXlcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBvcHRzLmNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvbiBhZnRlciBjbGlja2luZyB0aGUgb2svY2FuY2VsIGJ1dHRvbnMgd2l0aCB0aGUgcmVzdWx0XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgd2FybmluZ01lc3NhZ2Uob3B0czogYW55KSA6IHN0cmluZyB7XG5cbiAgICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gICAgICBpZiAodHlwZW9mIG9wdHMgPT09ICdzdHJpbmcnKVxuICAgICAgICBvcHRzID0geyB0ZXh0OiBvcHRzIH07XG5cbiAgICAgIGlmICghb3B0cy50eXBlKVxuICAgICAgICBvcHRzLnR5cGUgPSAnd2FybmluZyc7XG5cbiAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2Uob3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXJyb3IgbWVzc2FnZS4gU2FtZSBhcyBtZXNzYWdlKHt0eXBlOiAnZXJyb3InfSkuXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnRpdGxlIFRoZSBtZXNzYWdlIGJveCB0aXRsZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnRleHQgVGhlIG1lc3NhZ2UgYm94IGJvZHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50eXBlIFRoZSBtZXNzYWdlIGJveCB0eXBlIGkuZS5cbiAgICAgKiBpbmZvcm1hdGlvbiwgd2FybmluZywgZXJyb3IsIHF1ZXN0aW9uLCBzdWNjZXNzLFxuICAgICAqIGFsZXJ0LCBhbGVydC1pbmZvcm1hdGlvbiwgYWxlcnQtd2FybmluZywgYWxlcnQtZXJyb3IsIGFsZXJ0LXF1ZXN0aW9uLFxuICAgICAqIGNvbmZpcm0sIGNvbmZpcm0taW5mb3JtYXRpb24sIGNvbmZpcm0td2FybmluZywgY29uZmlybS1lcnJvciwgY29uZmlybS1xdWVzdGlvblxuICAgICAqIGFsdGVybmF0aXZlbHkgYSBjdXN0b20gY3NzIGNsYXNzXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9wdHMuZXhwaXJlIFRoZSB0aW1lIHBlcmlvZCB0byBjbG9zZSB0aGUgbWVzc2FnZSBib3hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5vayBUaGUgb2sgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5jYW5jZWwgdGhlIGNhbmNlbCBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLndpZHRoIFRoZSBjc3Mgd2lkdGggc3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuaGVpZ2h0IFRoZSBjc3MgaGVpZ2h0IHN0cmluZ1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5jbG9zZU9uRXNjICBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSB3aGVuIEVTQyBpcyBwcmVzc2VkIG9uIGtleWJvYXJkLiBkZWZhdWx0IGlzIFwidHJ1ZVwiXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25DbGlja091dHNpZGUgVGhlIG1lc3NhZ2UgYm94IHdpbGwgY2xvc2UgaWYgY2xpY2tlZCBvbiBvdmVybGF5IG9yIG91dHNpZGUgb2YgdGhlIG1vZGFsIGJveCBjb250ZW50LiBkZWZhdWx0IGlzIFwiZmFsc2VcIlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm1vcmV0ZXh0IFRoZSB0ZXh0IHRvIGFkZCBpbnNpZGUgdGhlIHJlc3VsdGluZyB3aW5kb3cgbW9kYWwgYXMgaW5mb3JtYXRpb24sIHdpbGwgYWRkIG1vcmUgYnV0dG9uXG4gICAgICogQHBhcmFtIHtib29sZWFufHN0cmluZ1tdfE1lc3NhZ2VCdXR0b25bXXxCdXR0b25MaXN0fSBvcHRzLmJ1dHRvbnMgVGhlIG1vZGFsIG1lc3NhZ2UgYnV0dG9ucyB0byBkaXNwbGF5XG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gb3B0cy5jYWxsYmFjayBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gYWZ0ZXIgY2xpY2tpbmcgdGhlIG9rL2NhbmNlbCBidXR0b25zIHdpdGggdGhlIHJlc3VsdFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIGVycm9yTWVzc2FnZSh0ZXh0OiBzdHJpbmcpOiBzdHJpbmc7XG4gICAgc3RhdGljIGVycm9yTWVzc2FnZShvcHRzOiBNZXNzYWdlT3B0cyk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEVycm9yIG1lc3NhZ2UuIFNhbWUgYXMgbWVzc2FnZSh7dHlwZTogJ2Vycm9yJ30pLlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50aXRsZSBUaGUgbWVzc2FnZSBib3ggdGl0bGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50ZXh0IFRoZSBtZXNzYWdlIGJveCBib2R5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudHlwZSBUaGUgbWVzc2FnZSBib3ggdHlwZSBpLmUuXG4gICAgICogaW5mb3JtYXRpb24sIHdhcm5pbmcsIGVycm9yLCBxdWVzdGlvbiwgc3VjY2VzcyxcbiAgICAgKiBhbGVydCwgYWxlcnQtaW5mb3JtYXRpb24sIGFsZXJ0LXdhcm5pbmcsIGFsZXJ0LWVycm9yLCBhbGVydC1xdWVzdGlvbixcbiAgICAgKiBjb25maXJtLCBjb25maXJtLWluZm9ybWF0aW9uLCBjb25maXJtLXdhcm5pbmcsIGNvbmZpcm0tZXJyb3IsIGNvbmZpcm0tcXVlc3Rpb25cbiAgICAgKiBhbHRlcm5hdGl2ZWx5IGEgY3VzdG9tIGNzcyBjbGFzc1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcHRzLmV4cGlyZSBUaGUgdGltZSBwZXJpb2QgdG8gY2xvc2UgdGhlIG1lc3NhZ2UgYm94XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMub2sgVGhlIG9rIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuY2FuY2VsIHRoZSBjYW5jZWwgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy53aWR0aCBUaGUgY3NzIHdpZHRoIHN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmhlaWdodCBUaGUgY3NzIGhlaWdodCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkVzYyAgVGhlIG1lc3NhZ2UgYm94IHdpbGwgY2xvc2Ugd2hlbiBFU0MgaXMgcHJlc3NlZCBvbiBrZXlib2FyZC4gZGVmYXVsdCBpcyBcInRydWVcIlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0cy5jbG9zZU9uQ2xpY2tPdXRzaWRlIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIGlmIGNsaWNrZWQgb24gb3ZlcmxheSBvciBvdXRzaWRlIG9mIHRoZSBtb2RhbCBib3ggY29udGVudC4gZGVmYXVsdCBpcyBcImZhbHNlXCJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5tb3JldGV4dCBUaGUgdGV4dCB0byBhZGQgaW5zaWRlIHRoZSByZXN1bHRpbmcgd2luZG93IG1vZGFsIGFzIGluZm9ybWF0aW9uLCB3aWxsIGFkZCBtb3JlIGJ1dHRvblxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbnxzdHJpbmdbXXxNZXNzYWdlQnV0dG9uW118QnV0dG9uTGlzdH0gb3B0cy5idXR0b25zIFRoZSBtb2RhbCBtZXNzYWdlIGJ1dHRvbnMgdG8gZGlzcGxheVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IG9wdHMuY2FsbGJhY2sgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGFmdGVyIGNsaWNraW5nIHRoZSBvay9jYW5jZWwgYnV0dG9ucyB3aXRoIHRoZSByZXN1bHRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBlcnJvck1lc3NhZ2Uob3B0czogYW55KSA6IHN0cmluZyB7XG5cbiAgICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gICAgICBpZiAodHlwZW9mIG9wdHMgPT09ICdzdHJpbmcnKVxuICAgICAgICBvcHRzID0geyB0ZXh0OiBvcHRzIH07XG5cbiAgICAgIGlmICghb3B0cy50eXBlKVxuICAgICAgICBvcHRzLnR5cGUgPSAnZXJyb3InO1xuXG4gICAgICByZXR1cm4gdGhpcy5tZXNzYWdlKG9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1Y2Nlc3MgbWVzc2FnZS4gU2FtZSBhcyBtZXNzYWdlKHt0eXBlOiAnc3VjY2Vzcyd9KS5cbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGl0bGUgVGhlIG1lc3NhZ2UgYm94IHRpdGxlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGV4dCBUaGUgbWVzc2FnZSBib3ggYm9keVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnR5cGUgVGhlIG1lc3NhZ2UgYm94IHR5cGUgaS5lLlxuICAgICAqIGluZm9ybWF0aW9uLCB3YXJuaW5nLCBlcnJvciwgcXVlc3Rpb24sIHN1Y2Nlc3MsXG4gICAgICogYWxlcnQsIGFsZXJ0LWluZm9ybWF0aW9uLCBhbGVydC13YXJuaW5nLCBhbGVydC1lcnJvciwgYWxlcnQtcXVlc3Rpb24sXG4gICAgICogY29uZmlybSwgY29uZmlybS1pbmZvcm1hdGlvbiwgY29uZmlybS13YXJuaW5nLCBjb25maXJtLWVycm9yLCBjb25maXJtLXF1ZXN0aW9uXG4gICAgICogYWx0ZXJuYXRpdmVseSBhIGN1c3RvbSBjc3MgY2xhc3NcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb3B0cy5leHBpcmUgVGhlIHRpbWUgcGVyaW9kIHRvIGNsb3NlIHRoZSBtZXNzYWdlIGJveFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm9rIFRoZSBvayBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmNhbmNlbCB0aGUgY2FuY2VsIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMud2lkdGggVGhlIGNzcyB3aWR0aCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5oZWlnaHQgVGhlIGNzcyBoZWlnaHQgc3RyaW5nXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25Fc2MgIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIHdoZW4gRVNDIGlzIHByZXNzZWQgb24ga2V5Ym9hcmQuIGRlZmF1bHQgaXMgXCJ0cnVlXCJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkNsaWNrT3V0c2lkZSBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSBpZiBjbGlja2VkIG9uIG92ZXJsYXkgb3Igb3V0c2lkZSBvZiB0aGUgbW9kYWwgYm94IGNvbnRlbnQuIGRlZmF1bHQgaXMgXCJmYWxzZVwiXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubW9yZXRleHQgVGhlIHRleHQgdG8gYWRkIGluc2lkZSB0aGUgcmVzdWx0aW5nIHdpbmRvdyBtb2RhbCBhcyBpbmZvcm1hdGlvbiwgd2lsbCBhZGQgbW9yZSBidXR0b25cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW58c3RyaW5nW118TWVzc2FnZUJ1dHRvbltdfEJ1dHRvbkxpc3R9IG9wdHMuYnV0dG9ucyBUaGUgbW9kYWwgbWVzc2FnZSBidXR0b25zIHRvIGRpc3BsYXlcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBvcHRzLmNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvbiBhZnRlciBjbGlja2luZyB0aGUgb2svY2FuY2VsIGJ1dHRvbnMgd2l0aCB0aGUgcmVzdWx0XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgc3VjY2Vzc01lc3NhZ2UodGV4dDogc3RyaW5nKTogc3RyaW5nO1xuICAgIHN0YXRpYyBzdWNjZXNzTWVzc2FnZShvcHRzOiBNZXNzYWdlT3B0cyk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN1Y2Nlc3MgbWVzc2FnZS4gU2FtZSBhcyBtZXNzYWdlKHt0eXBlOiAnc3VjY2Vzcyd9KS5cbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGl0bGUgVGhlIG1lc3NhZ2UgYm94IHRpdGxlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudGV4dCBUaGUgbWVzc2FnZSBib3ggYm9keVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnR5cGUgVGhlIG1lc3NhZ2UgYm94IHR5cGUgaS5lLlxuICAgICAqIGluZm9ybWF0aW9uLCB3YXJuaW5nLCBlcnJvciwgcXVlc3Rpb24sIHN1Y2Nlc3MsXG4gICAgICogYWxlcnQsIGFsZXJ0LWluZm9ybWF0aW9uLCBhbGVydC13YXJuaW5nLCBhbGVydC1lcnJvciwgYWxlcnQtcXVlc3Rpb24sXG4gICAgICogY29uZmlybSwgY29uZmlybS1pbmZvcm1hdGlvbiwgY29uZmlybS13YXJuaW5nLCBjb25maXJtLWVycm9yLCBjb25maXJtLXF1ZXN0aW9uXG4gICAgICogYWx0ZXJuYXRpdmVseSBhIGN1c3RvbSBjc3MgY2xhc3NcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb3B0cy5leHBpcmUgVGhlIHRpbWUgcGVyaW9kIHRvIGNsb3NlIHRoZSBtZXNzYWdlIGJveFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm9rIFRoZSBvayBidXR0b24gdGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmNhbmNlbCB0aGUgY2FuY2VsIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMud2lkdGggVGhlIGNzcyB3aWR0aCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5oZWlnaHQgVGhlIGNzcyBoZWlnaHQgc3RyaW5nXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25Fc2MgIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIHdoZW4gRVNDIGlzIHByZXNzZWQgb24ga2V5Ym9hcmQuIGRlZmF1bHQgaXMgXCJ0cnVlXCJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkNsaWNrT3V0c2lkZSBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSBpZiBjbGlja2VkIG9uIG92ZXJsYXkgb3Igb3V0c2lkZSBvZiB0aGUgbW9kYWwgYm94IGNvbnRlbnQuIGRlZmF1bHQgaXMgXCJmYWxzZVwiXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubW9yZXRleHQgVGhlIHRleHQgdG8gYWRkIGluc2lkZSB0aGUgcmVzdWx0aW5nIHdpbmRvdyBtb2RhbCBhcyBpbmZvcm1hdGlvbiwgd2lsbCBhZGQgbW9yZSBidXR0b25cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW58c3RyaW5nW118TWVzc2FnZUJ1dHRvbltdfEJ1dHRvbkxpc3R9IG9wdHMuYnV0dG9ucyBUaGUgbW9kYWwgbWVzc2FnZSBidXR0b25zIHRvIGRpc3BsYXlcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBvcHRzLmNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvbiBhZnRlciBjbGlja2luZyB0aGUgb2svY2FuY2VsIGJ1dHRvbnMgd2l0aCB0aGUgcmVzdWx0XG4gICAgICovXG4gICAgc3RhdGljIHN1Y2Nlc3NNZXNzYWdlKG9wdHM6IGFueSkgOiBzdHJpbmcge1xuXG4gICAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgICAgaWYgKHR5cGVvZiBvcHRzID09PSAnc3RyaW5nJylcbiAgICAgICAgb3B0cyA9IHsgdGV4dDogb3B0cyB9O1xuXG4gICAgICBpZiAoIW9wdHMudHlwZSlcbiAgICAgICAgb3B0cy50eXBlID0gJ3N1Y2Nlc3MnO1xuXG4gICAgICByZXR1cm4gdGhpcy5tZXNzYWdlKG9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBmcmFtZXdvcmsgbWVzc2FnZSBkZXRhaWxzIGJ5IGdyb3VwIGFuZCBudW1iZXJcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1zZ0dycCBUaGUgbWVzc2FnZSBncm91cCAoY2FzZSBpbnNlbnNpdGl2ZSlcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbXNnTnVtIFRoZSBtZXNzYWdlIG51bWJlclxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gICAgICovXG4gICAgc3RhdGljIGdldE1lc3NhZ2VOdW0obXNnR3JwOiBzdHJpbmcsIG1zZ051bTogbnVtYmVyKTogUHJvbWlzZTxhbnk+IHtcblxuICAgICAgaWYgKCFTbWFydE1lc3NhZ2VDYWNoZVttc2dHcnBdKVxuICAgICAgICBTbWFydE1lc3NhZ2VDYWNoZVttc2dHcnBdID0ge307XG5cbiAgICAgIGlmIChTbWFydE1lc3NhZ2VDYWNoZVttc2dHcnBdW21zZ051bV0pIHtcbiAgICAgICAgaWYgKFNtYXJ0TWVzc2FnZUNhY2hlW21zZ0dycF1bbXNnTnVtXS50aGVuKVxuICAgICAgICAgIHJldHVybiBTbWFydE1lc3NhZ2VDYWNoZVttc2dHcnBdW21zZ051bV07XG4gICAgICAgIGVsc2VcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKFNtYXJ0TWVzc2FnZUNhY2hlW21zZ0dycF1bbXNnTnVtXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBTbWFydE1lc3NhZ2VDYWNoZVttc2dHcnBdW21zZ051bV0gPSBmZXRjaChgL3dlYi9TbWFydE1lc3NhZ2UvJHttc2dHcnB9LyR7bXNnTnVtfWAsIHsgbWV0aG9kOiAnR0VUJyB9KVxuICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgaWYgKCFyZXNwb25zZS5vaylcbiAgICAgICAgICAgIHRocm93IHJlc3BvbnNlO1xuXG4gICAgICAgICAgcmV0dXJuIFNtYXJ0TWVzc2FnZUNhY2hlW21zZ0dycF1bbXNnTnVtXSA9IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICBkZWxldGUgU21hcnRNZXNzYWdlQ2FjaGVbbXNnR3JwXVttc2dOdW1dO1xuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJlc3BvbnNlLmpzb24oKS50aGVuKChyZXNwb25zZTogYW55KSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuZXJyb3JNZXNzYWdlKHJlc3BvbnNlLm1lc3NhZ2UgfHwgcmVzcG9uc2UudGl0bGUgfHwgcmVzcG9uc2UuZXJyb3IgfHwgJ0Vycm9yIGhhcyBvY2N1cmVkJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JNZXNzYWdlKCdFcnJvciBoYXMgb2NjdXJlZCcpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRocm93IEVycm9yKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIE1lc3NhZ2VUeXBlIG9mIGEgU21hcnRNZXNzYWdlIGVpdGhlciBmcm9tIGphdmFzY3JpcHQgY2FjaGUgbWVtb3J5IG9yIGZyb21cbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtICAge3N0cmluZ30gICAgICAgIG1zZ0dycCAgVGhlIG1lc3NhZ2UgZ3JvdXAgKGNhc2UgaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtICAge251bWJlcn0gICAgICAgIG1zZ051bSAgVGhlIG1lc3NhZ2UgbnVtYmVyXG4gICAgICogQHJldHVybiAge1Byb21pc2U8YW55Pn1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0TWVzc2FnZVR5cGUobXNnR3JwOiBzdHJpbmcsIG1zZ051bTogbnVtYmVyKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgIHJldHVybiB0aGlzLmdldE1lc3NhZ2VOdW0obXNnR3JwLCBtc2dOdW0pLnRoZW4obWVzc2FnZSA9PiBQcm9taXNlLnJlc29sdmUobWVzc2FnZS5NZXNzYWdlVHlwZS50b0xvd2VyQ2FzZSgpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGlzcGxheXMgYSBmcmFtZXdvcmsgbWVzc2FnZSBieSBncm91cCBhbmQgbnVtYmVyXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtc2dHcnAgVGhlIG1lc3NhZ2UgZ3JvdXAgKGNhc2UgaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1zZ051bSBUaGUgbWVzc2FnZSBudW1iZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50aXRsZSBUaGUgbWVzc2FnZSBib3ggdGl0bGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50ZXh0IFRoZSBtZXNzYWdlIGJveCBib2R5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudHlwZSBUaGUgbWVzc2FnZSBib3ggdHlwZSBpLmUuXG4gICAgICogaW5mb3JtYXRpb24sIHdhcm5pbmcsIGVycm9yLCBxdWVzdGlvbiwgc3VjY2VzcyxcbiAgICAgKiBhbGVydCwgYWxlcnQtaW5mb3JtYXRpb24sIGFsZXJ0LXdhcm5pbmcsIGFsZXJ0LWVycm9yLCBhbGVydC1xdWVzdGlvbixcbiAgICAgKiBjb25maXJtLCBjb25maXJtLWluZm9ybWF0aW9uLCBjb25maXJtLXdhcm5pbmcsIGNvbmZpcm0tZXJyb3IsIGNvbmZpcm0tcXVlc3Rpb25cbiAgICAgKiBhbHRlcm5hdGl2ZWx5IGEgY3VzdG9tIGNzcyBjbGFzc1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcHRzLmV4cGlyZSBUaGUgdGltZSBwZXJpb2QgdG8gY2xvc2UgdGhlIG1lc3NhZ2UgYm94XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMub2sgVGhlIG9rIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuY2FuY2VsIHRoZSBjYW5jZWwgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy53aWR0aCBUaGUgY3NzIHdpZHRoIHN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmhlaWdodCBUaGUgY3NzIGhlaWdodCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMubW9kYWwgVGhlIG1vZGFsIGZsYWcgZm9yIG1lc3NhZ2UuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25Fc2MgIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIHdoZW4gRVNDIGlzIHByZXNzZWQgb24ga2V5Ym9hcmQuIGRlZmF1bHQgaXMgXCJ0cnVlXCJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkNsaWNrT3V0c2lkZSBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSBpZiBjbGlja2VkIG9uIG92ZXJsYXkgb3Igb3V0c2lkZSBvZiB0aGUgbW9kYWwgYm94IGNvbnRlbnQuIGRlZmF1bHQgaXMgXCJmYWxzZVwiXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubW9yZXRleHQgVGhlIHRleHQgdG8gYWRkIGluc2lkZSB0aGUgcmVzdWx0aW5nIHdpbmRvdyBtb2RhbCBhcyBpbmZvcm1hdGlvbiwgd2lsbCBhZGQgbW9yZSBidXR0b25cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW58c3RyaW5nW118TWVzc2FnZUJ1dHRvbltdfEJ1dHRvbkxpc3R9IG9wdHMuYnV0dG9ucyBUaGUgbW9kYWwgbWVzc2FnZSBidXR0b25zIHRvIGRpc3BsYXlcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBvcHRzLmNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvbiBhZnRlciBjbGlja2luZyB0aGUgb2svY2FuY2VsIGJ1dHRvbnMgd2l0aCB0aGUgcmVzdWx0XG4gICAgICovXG4gICAgc3RhdGljIGRpc3BsYXlNZXNzYWdlTnVtKG1zZ0dycDogc3RyaW5nLCBtc2dOdW06IG51bWJlciwgb3B0cz86IChyZXQ/OiBib29sZWFuKSA9PiB2b2lkKTogdm9pZDtcbiAgICBzdGF0aWMgZGlzcGxheU1lc3NhZ2VOdW0obXNnR3JwOiBzdHJpbmcsIG1zZ051bTogbnVtYmVyLCBvcHRzPzogTWVzc2FnZU9wdHMpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogRGlzcGxheXMgYSBmcmFtZXdvcmsgbWVzc2FnZSBieSBncm91cCBhbmQgbnVtYmVyXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtc2dHcnAgVGhlIG1lc3NhZ2UgZ3JvdXAgKGNhc2UgaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1zZ051bSBUaGUgbWVzc2FnZSBudW1iZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50aXRsZSBUaGUgbWVzc2FnZSBib3ggdGl0bGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy50ZXh0IFRoZSBtZXNzYWdlIGJveCBib2R5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMudHlwZSBUaGUgbWVzc2FnZSBib3ggdHlwZSBpLmUuXG4gICAgICogaW5mb3JtYXRpb24sIHdhcm5pbmcsIGVycm9yLCBxdWVzdGlvbiwgc3VjY2VzcyxcbiAgICAgKiBhbGVydCwgYWxlcnQtaW5mb3JtYXRpb24sIGFsZXJ0LXdhcm5pbmcsIGFsZXJ0LWVycm9yLCBhbGVydC1xdWVzdGlvbixcbiAgICAgKiBjb25maXJtLCBjb25maXJtLWluZm9ybWF0aW9uLCBjb25maXJtLXdhcm5pbmcsIGNvbmZpcm0tZXJyb3IsIGNvbmZpcm0tcXVlc3Rpb25cbiAgICAgKiBhbHRlcm5hdGl2ZWx5IGEgY3VzdG9tIGNzcyBjbGFzc1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcHRzLmV4cGlyZSBUaGUgdGltZSBwZXJpb2QgdG8gY2xvc2UgdGhlIG1lc3NhZ2UgYm94XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMub2sgVGhlIG9rIGJ1dHRvbiB0ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuY2FuY2VsIHRoZSBjYW5jZWwgYnV0dG9uIHRleHRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy53aWR0aCBUaGUgY3NzIHdpZHRoIHN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmhlaWdodCBUaGUgY3NzIGhlaWdodCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMubW9kYWwgVGhlIG1vZGFsIGZsYWcgZm9yIG1lc3NhZ2UuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLnNob3dNZXNzYWdlQ29kZSBSZW1vdmUgdGhlIGluZm9ybWF0aW9uIG1lc3NhZ2UgdGV4dCBpbmZvIGdyb3VwIGFuZCBudW1iZXIsIHRleHQgZGlzcGxheWVkIGJldHdlZW4gcGFyZW50aGVzZXMsIGRlZmF1bHQgaXMgXCJmYWxzZVwiXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcHRzLmNsb3NlT25Fc2MgIFRoZSBtZXNzYWdlIGJveCB3aWxsIGNsb3NlIHdoZW4gRVNDIGlzIHByZXNzZWQgb24ga2V5Ym9hcmQuIGRlZmF1bHQgaXMgXCJ0cnVlXCJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuY2xvc2VPbkNsaWNrT3V0c2lkZSBUaGUgbWVzc2FnZSBib3ggd2lsbCBjbG9zZSBpZiBjbGlja2VkIG9uIG92ZXJsYXkgb3Igb3V0c2lkZSBvZiB0aGUgbW9kYWwgYm94IGNvbnRlbnQuIGRlZmF1bHQgaXMgXCJmYWxzZVwiXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubW9yZXRleHQgVGhlIHRleHQgdG8gYWRkIGluc2lkZSB0aGUgcmVzdWx0aW5nIHdpbmRvdyBtb2RhbCBhcyBpbmZvcm1hdGlvbiwgd2lsbCBhZGQgbW9yZSBidXR0b25cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW58c3RyaW5nW118TWVzc2FnZUJ1dHRvbltdfEJ1dHRvbkxpc3R9IG9wdHMuYnV0dG9ucyBUaGUgbW9kYWwgbWVzc2FnZSBidXR0b25zIHRvIGRpc3BsYXlcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBvcHRzLmNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvbiBhZnRlciBjbGlja2luZyB0aGUgb2svY2FuY2VsIGJ1dHRvbnMgd2l0aCB0aGUgcmVzdWx0XG4gICAgICovXG4gICAgc3RhdGljIGRpc3BsYXlNZXNzYWdlTnVtKG1zZ0dycDogc3RyaW5nLCBtc2dOdW06IG51bWJlciwgb3B0cz86IGFueSk6IHZvaWQge1xuICAgICAgY29uc3QgcmV0VmFsID0gdGhpcy5nZXRNZXNzYWdlTnVtKG1zZ0dycCwgbXNnTnVtKTtcblxuICAgICAgcmV0VmFsLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgY29uc3QgbXNnOiBhbnkgPSB7IHRleHQ6IHJlc3VsdC5NZXNzYWdlVGV4dCB9O1xuXG4gICAgICAgIG1zZy50ZXh0ID0gd2luZG93LmFraW9tYS5TbWFydE1lc3NhZ2UucmVwbGFjZUVtcHR5UGxhY2Vob2xkZXJzKG1zZy50ZXh0KTtcblxuICAgICAgICBzd2l0Y2ggKHJlc3VsdC5NZXNzYWdlVHlwZS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgY2FzZSAnaW5mb3JtYXRpb24nOlxuICAgICAgICAgICAgbXNnLnR5cGUgPSAnaW5mb3JtYXRpb24nO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdlcnJvcic6XG4gICAgICAgICAgICBtc2cudHlwZVx0PSAnZXJyb3InO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICd3YXJuaW5nJzpcbiAgICAgICAgICAgIG1zZy50eXBlXHQ9ICd3YXJuaW5nJztcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAnc3VjY2Vzcyc6XG4gICAgICAgICAgICBtc2cudHlwZVx0PSAnc3VjY2Vzcyc7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGNhc2UgJ3F1ZXN0aW9uJzpcbiAgICAgICAgICAgIG1zZy50eXBlXHQ9ICdxdWVzdGlvbic7XG4gICAgICAgICAgICBtc2cubW9kYWwgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjaGVjayBpZiBNZXNzYWdlQm94U3R5bGUgaXMgZGVmaW5lZCBhbmQgc2V0IHRoZSBtb2RhbCBvciBub25tb2RhbCB0eXBlXG4gICAgICAgIGlmIChyZXN1bHQuTWVzc2FnZUJveFN0eWxlICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgbXNnLm1vZGFsID0gKHJlc3VsdC5NZXNzYWdlQm94U3R5bGUudG9Mb3dlckNhc2UoKSA9PT0gJ21vZGFsJyA/IHRydWUgOiBmYWxzZSk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBvcHRzID09PSAnZnVuY3Rpb24nKVxuICAgICAgICAgIG1zZy5jYWxsYmFjayA9IG9wdHM7XG4gICAgICAgIGVsc2UgaWYgKG9wdHMgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICBPYmplY3QuYXNzaWduKG1zZywgb3B0cyk7XG5cbiAgICAgICAgdGhpcy5tZXNzYWdlKG1zZyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgYWxsIG1lc3NhZ2VzXG4gICAgICogQHN0YXRpY1xuICAgICAqL1xuICAgIHN0YXRpYyBjbGVhckFsbCgpIHtcbiAgICAgIGZvciAoY29uc3QgaWQgaW4gd2luZG93LmRodG1seC5tZXNzYWdlLnB1bGwpXG4gICAgICAgIHdpbmRvdy5kaHRtbHgubWVzc2FnZS5oaWRlKGlkKTtcbiAgICB9XG4gIH1cbn1cbiIsIm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogUmVmcmVzaCBFbWl0dGVyXG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBSZWZyZXNoRW1pdHRlclxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgUmVmcmVzaEVtaXR0ZXIge1xuXG4gICAgLyoqXG4gICAgICAgICAqIFJlZnJlc2hlcyBEYXRhXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGVudGl0eU5hbWUgVGhlIGVudGl0eSBuYW1lLiBBY2NlcHRzIHdpbGRjYXJkIEJVVCBjdXJyZW50bHkgb25seSBzdXBwb3J0cyBiZWdpbnMgKHNlZSBleGFtcGxlKS5cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubGFzdFJvd1N0YXRlIFRoZSAnZGVsZXRlJywgJ3VwZGF0ZScgb3IgJ2FkZCcgbGFzdCByb3cgc3RhdGUuXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmxhc3RVcGRhdGVkUmVjb3JkLnNlbGZoZGwgVGhlIHNlbGZIZGwgb2YgdGhlIGxhc3QgdXBkYXRlZCByZWNvcmQuIFJlcXVpcmVkIGZvciBhbiBhZGQgcmVmcmVzaC5cbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogLy8gdG8gYmUgY2FsbGVkIGZyb20gdGhlIGludm9rZVNlcnZlclRhc2soKS50aGVuKCkgZnVuY3Rpb24uXG4gICAgICAgICAqXG4gICAgICAgICAqIC8vIGRlbGV0ZSByZWZyZXNoXG4gICAgICAgICAqIGFraW9tYS5zd2F0LlJlZnJlc2hFbWl0dGVyLnJlZnJlc2hEYXRhKCdlVGVybSonLCB7bGFzdFJvd1N0YXRlOiAnZGVsZXRlJ30pIC8vIFRoaXMgd2lsbCBzZWxlY3QgdGhlIG5leHQgYXZhaWxhYmxlIHJlY29yZFxuICAgICAgICAgKlxuICAgICAgICAgKiAvLyB1cGRhdGUgcmVmcmVzaFxuICAgICAgICAgKiBha2lvbWEuc3dhdC5SZWZyZXNoRW1pdHRlci5yZWZyZXNoRGF0YSgnZVRlcm0qJywge2xhc3RSb3dTdGF0ZTogJ3VwZGF0ZSd9KTtcbiAgICAgICAgICpcbiAgICAgICAgICogLy8gYWRkIHJlZnJlc2hcbiAgICAgICAgICogYWtpb21hLnN3YXQuUmVmcmVzaEVtaXR0ZXIucmVmcmVzaERhdGEoJ2VUZXJtKicsIHtsYXN0Um93U3RhdGU6ICdhZGQnLCBsYXN0VXBkYXRlZFJlY29yZDoge3NlbGZoZGw6ICdBNjk6MTExOjAwMDAwODEwMTM5OCd9fSk7XG4gICAgICAgICAqL1xuICAgIHN0YXRpYyByZWZyZXNoRGF0YShlbnRpdHlOYW1lOiBzdHJpbmcsIG9wdHM6IHtcbiAgICAgIGxhc3RSb3dTdGF0ZTogJ2RlbGV0ZScgfCAndXBkYXRlJyB8ICdhZGQnO1xuICAgICAgbGFzdFVwZGF0ZWRSZWNvcmQ/OiBSZWNvcmQ8J3NlbGZoZGwnIHwgc3RyaW5nLCBzdHJpbmcgfCBudW1iZXI+O1xuICAgIH0pOiB2b2lkIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuUmVmcmVzaEVtaXR0ZXIucmVmcmVzaERhdGEoZW50aXR5TmFtZSwgb3B0cyk7XG4gICAgfVxuICB9XG59XG4iLCJuYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIEhhbmRsZXMgU2Vzc2lvbkNvbnRleHRcbiAgICAgKiBAZXhwb3J0XG4gICAgICogQGNsYXNzIFNlc3Npb25NYW5hZ2VyXG4gICAgICovXG5cblxuICBleHBvcnQgY2xhc3MgU2Vzc2lvbk1hbmFnZXIge1xuXG4gICAgLyoqXG4gICAgICAgICAqIEdldHMgc2Vzc2lvbiBwcm9wZXJ0eVxuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSAgbmFtZSAgICAgIFRoZSBwcm9wZXJ0eSBuYW1lLlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gIFtjb250ZXh0XSBSZXByZXNlbnRzIHRoZSBzZXNzaW9uIGNvbnRleHQgd2hlcmUgdGhlIHByb3BlcnR5IHdpbGwgYmUgc2VhcmNoZWQgKGUuZyBlU2Vzc2lvbkNvbnRleHQsIGVTd2F0U2Vzc2lvbkNvbnRleHQpLlxuICAgICAgICAgKiA8YnI+IElmIG5vdCBzcGVjaWZpZWQsIGRlZmF1bHQgaXMgZVN3YXRTZXNzaW9uQ29udGV4dFxuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nIHwgdW5kZWZpbmVkfSBSZXR1cm5zIHRoZSBzZXNzaW9uIHByb3BlcnR5IHZhbHVlXG4gICAgICAgICAqL1xuXG4gICAgc3RhdGljIGdldDxUID0gc3RyaW5nPihuYW1lOiBzdHJpbmcsIGNvbnRleHQgPSAnZVN3YXRTZXNzaW9uQ29udGV4dCcpOiBUIHtcbiAgICAgIHJldHVybiB3aW5kb3cuYWtpb21hLmdldFNlc3Npb25Qcm9wZXJ0eShuYW1lLCBjb250ZXh0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogU2V0cyBzZXNzaW9uIHByb3BlcnR5XG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9ICAgICAgICAgICAgICAgICBuYW1lICAgICAgIFRoZSBwcm9wZXJ0eSBuYW1lLlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ3xpbnRlZ2VyfGJvb2xlYW59IHZhbHVlICAgICAgVGhlIHByb3BlcnR5IG5ldyB2YWx1ZS5cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9ICAgICAgICAgICAgICAgICBbY29udGV4dF0gIFJlcHJlc2VudHMgdGhlIHNlc3Npb24gY29udGV4dCB3aGVyZSB0aGUgcHJvcGVydHkgd2lsbCBiZSBzZXQgKGUuZyBlU2Vzc2lvbkNvbnRleHQsIGVTd2F0U2Vzc2lvbkNvbnRleHQpLlxuICAgICAgICAgKiA8YnI+IElmIG5vdCBzcGVjaWZpZWQsIGRlZmF1bHQgaXMgZVN3YXRTZXNzaW9uQ29udGV4dFxuICAgICAgICAgKi9cblxuICAgIHN0YXRpYyBzZXQobmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiwgY29udGV4dCA9ICdlU3dhdFNlc3Npb25Db250ZXh0Jykge1xuICAgICAgd2luZG93LmFraW9tYS5zZXRTZXNzaW9uUHJvcGVydHkobmFtZSwgdmFsdWUsIGNvbnRleHQpO1xuICAgIH1cbiAgfVxuXG59XG4iLCJuYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBIYW5kbGVzIEtleWJvYXJkIFNob3JjdXRzXG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIFNob3J0Y3V0TWFuYWdlclxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIFNob3J0Y3V0TWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGtleWJvYXJkIHNob3J0Y3V0c1xuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY0lkIFRoZSBzaG9ydGN1dCBuYW1lLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmcgfCB1bmRlZmluZWR9IFJldHVybnMgdGhlIHNob3J0Y3V0IGtleSBiaW5kaW5nLlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXQoY0lkOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIHdpbmRvdy5ha2lvbWEuc2hvcnRjdXRNYW5hZ2VyLmdldChjSWQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMga2V5Ym9hcmQgc2hvcnRjdXRcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNJZCBUaGUgU2hvcnRjdXQgbmFtZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY1Nob3J0Y3V0IFJlcHJlc2VudHMgdGhlIG5ldyBzaG9ydGN1dCBrZXkgYmluZGluZy5cbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0KGNJZDogc3RyaW5nLCBjU2hvcnRjdXQ6IHN0cmluZykge1xuICAgICAgcmV0dXJuIHdpbmRvdy5ha2lvbWEuc2hvcnRjdXRNYW5hZ2VyLnNldChjSWQsIGNTaG9ydGN1dCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBiaW5kaW5nIGdsb2JhbCBzaG9ydGN1dC5cbiAgICAgKiBAbWVtYmVyb2YgU2hvcnRjdXRNYW5hZ2VyXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXlzXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge2FueX0gW2FjdGlvbl1cbiAgICAgKi9cbiAgICBzdGF0aWMgYmluZEdsb2JhbChrZXlzOiBzdHJpbmcsIGNhbGxiYWNrOiBGdW5jdGlvbiwgYWN0aW9uPzogYW55KSB7XG4gICAgICB3aW5kb3cuYWtpb21hLnNob3J0Y3V0TWFuYWdlci5iaW5kR2xvYmFsKGtleXMsIGNhbGxiYWNrLCBhY3Rpb24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgdW5iaW5kaW5nIGdsb2JhbCBzaG9ydGN1dC5cbiAgICAgKiBAbWVtYmVyb2YgU2hvcnRjdXRNYW5hZ2VyXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXlzXG4gICAgICovXG4gICAgc3RhdGljIHVuYmluZChrZXlzOiBzdHJpbmcpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuc2hvcnRjdXRNYW5hZ2VyLnVuYmluZChrZXlzKTtcbiAgICB9XG4gIH1cblxufVxuIiwibmFtZXNwYWNlIGFraW9tYSB7XG4gIC8qKlxuICAgICAqIFNvY2tldENvbm5lY3Rpb25IZWxwZXIgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBTb2NrZXRDb25uZWN0aW9uSGVscGVyXG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBTb2NrZXRDb25uZWN0aW9uSGVscGVyIHtcbiAgICAvKipcbiAgICAgICAgICogTWV0aG9kIGZvciBzZXR0aW5nIHVwIHNvY2tldCBldmVudCBsaXN0ZW5lclxuICAgICAgICAgKiBAcGFyYW0gZXZlbnROYW1lIE5hbWUgb2YgdGhlIGV2ZW50XG4gICAgICAgICAqIEBwYXJhbSBjYWxsYmFja1xuICAgICAgICAgKi9cbiAgICBzdGF0aWMgb24oZXZlbnROYW1lOnN0cmluZywgY2FsbGJhY2s6RnVuY3Rpb24pIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuc29ja2V0Q29ubmVjdGlvbi5vbihldmVudE5hbWUsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogTWV0aG9kIGZvciBlbWl0dGluZyBhbiBldmVudCBvdmVyIHdlYnNvY2tldHNcbiAgICAgICAgICogQHBhcmFtIGV2ZW50TmFtZSBOYW1lIG9mIHRoZSBldmVudFxuICAgICAgICAgKiBAcGFyYW0gZGF0YSBUaGUgcGF5bG9hZFxuICAgICAgICAgKi9cbiAgICBzdGF0aWMgZW1pdChldmVudE5hbWU6c3RyaW5nLCBkYXRhOiBhbnkpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuc29ja2V0Q29ubmVjdGlvbi5lbWl0KGV2ZW50TmFtZSwgZGF0YSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIE1ldGhvZCB0byBjYWxsIGFmdGVyIHdlYnNvY2tldCBjb25uZWN0aW9uIGlzIGVzdGFibGlzaGVkXG4gICAgICAgICAqIEBwYXJhbSBjYWxsYmFja1xuICAgICAgICAgKi9cbiAgICBzdGF0aWMgb25BZnRlckNvbm5lY3RlZChjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuc29ja2V0Q29ubmVjdGlvbi5vbkFmdGVyQ29ubmVjdGVkKCgpID0+IHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBNZXRob2QgdG8gY2hlY2sgaWYgY29ubmVjdGlvbiB3YXMgZXN0YWJsaXNoZWRcbiAgICAgICAgICovXG4gICAgc3RhdGljIGlzQ29ubmVjdGVkKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHdpbmRvdy5ha2lvbWEuc29ja2V0Q29ubmVjdGlvbi5pc0Nvbm5lY3RlZCgpO1xuICAgIH1cbiAgfVxufVxuIiwibmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBDcmVhdGVzIGEgd3JhcHBlciB0eXBlc2NyaXB0IG9iamVjdCBmb3IgYSBkeW5PYmplY3RcbiAgICAgKiBAZXhwb3J0XG4gICAgICogQGNsYXNzIFN3YXRGYWN0b3J5XG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBTd2F0RmFjdG9yeSB7XG4gICAgLyoqXG4gICAgKiBSZWNpZXZlcyBhIGNvbnRyb2xsZXIgb2JqZWN0IGFuZCBjcmVhdGVzIHRoZSBlcXVpdmFsZW50IHR5cGVzY3JpcHQgb2JqZWN0XG4gICAgKiBAc3RhdGljXG4gICAgKiBAcGFyYW0geyp9IGNvbnRyb2xsZXIgRXhjZXB0cyBib3RoIGR5bk9iamVjdCBvciBjb250cm9sbGVyIG9iamVjdFxuICAgICogQHJldHVybnMge1N3YXRPYmplY3R9XG4gICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlU3dhdE9iamVjdChjb250cm9sbGVyOiBhbnkpOiBTd2F0T2JqZWN0IHtcbiAgICAgIGlmICghY29udHJvbGxlcilcbiAgICAgICAgcmV0dXJuIG51bGw7XG5cbiAgICAgIC8vIG5vdGUgdGhhdCB0aGUgd3JhcHBlcnMgYXJlIGJhc2VkIG9uIGNvbnRyb2xsZXJzIGFuZCB3ZSBkbyBub3QgdXNlIHZpZXcgb3IgdHlwZVxuICAgICAgLy8gYmVjYXVzZSB0aGVyZSBjYW4gYmUgY2FzZXMgb2YgY29udHJvbGxlcnMgd2l0aG91dCBkeW5PYmplY3QgdmlldyBvciB0eXBlLlxuICAgICAgLy8gZm9yIGV4YW1wbGU6IHRoZSBkeW5zZWxlY3QgbG9va3VwIGRhdGFzb3VyY2UuXG5cbiAgICAgIC8vIGlmIGEgZHluT2JqZWN0IHdhcyBwYXNzZWQgaW5zdGVhZCBvZiBhIGNvbnRyb2xsZXIgdGhlbiBnZXQgY29udHJvbGxlciBmcm9tIGR5bk9iamVjdFxuICAgICAgaWYgKGNvbnRyb2xsZXI/LmNvbnRyb2xsZXI/LmR5bk9iamVjdCA9PT0gY29udHJvbGxlcilcbiAgICAgICAgY29udHJvbGxlciA9IGNvbnRyb2xsZXIuY29udHJvbGxlcjtcblxuICAgICAgLy8gaW4gc29tZSBjYXNlcyB1c2UgcGFyZW50IGNvbnRyb2xsZXJcbiAgICAgIHN3aXRjaCAoY29udHJvbGxlci52aWV3KSB7XG5cbiAgICAgICAgY2FzZSAndGFiJzpcbiAgICAgICAgICBjb250cm9sbGVyID0gY29udHJvbGxlci5wYXJlbnQ7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAncmliYm9uYmxvY2snOlxuICAgICAgICBjYXNlICdyaWJib25idXR0b24nOlxuICAgICAgICBjYXNlICdyaWJib25jb21ibyc6XG4gICAgICAgIGNhc2UgJ3JpYmJvbmlucHV0JzpcbiAgICAgICAgY2FzZSAncmliYm9uZ3JvdXAnOlxuICAgICAgICBjYXNlICdyaWJib25zZWxlY3QnOlxuICAgICAgICBjYXNlICdyaWJib25zZWxlY3RvcHRpb24nOlxuXG4gICAgICAgICAgY29udHJvbGxlciA9IGNvbnRyb2xsZXIucGFyZW50O1xuXG4gICAgICAgICAgd2hpbGUgKGNvbnRyb2xsZXI/LnZpZXcgIT09ICdyaWJib24nKVxuICAgICAgICAgICAgY29udHJvbGxlciA9IGNvbnRyb2xsZXIucGFyZW50O1xuXG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAndG9vbGJhcmJ1dHRvbic6XG4gICAgICAgIGNhc2UgJ3Rvb2xiYXJjb21ibyc6XG4gICAgICAgIGNhc2UgJ3Rvb2xiYXJmaWxsaW4nOlxuICAgICAgICBjYXNlICd0b29sYmFyc2VsZWN0JzpcblxuICAgICAgICAgIGNvbnRyb2xsZXIgPSBjb250cm9sbGVyLnBhcmVudDtcblxuICAgICAgICAgIHdoaWxlIChjb250cm9sbGVyPy52aWV3ICE9PSAndG9vbGJhcicpXG4gICAgICAgICAgICBjb250cm9sbGVyID0gY29udHJvbGxlci5wYXJlbnQ7XG5cbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgLy8gdG8gYXZvaWQgY3JlYXRpbmcgbXVsdGlwbGUgd3JhcHBlciBvYmplY3RzXG4gICAgICAvLyBhIHJlZmVyZW5jZSB0byB0aGUgd3JhcHBlciBvYmplY3QgaXMgc2F2ZWRcbiAgICAgIC8vIGFuZCB1c2VkIGlmIGl0IGlzIG5lZWRlZCBhZ2FpblxuICAgICAgaWYgKGNvbnRyb2xsZXIuX2FraW9tYVdyYXBwZXJPYmplY3QpXG4gICAgICAgIHJldHVybiBjb250cm9sbGVyLl9ha2lvbWFXcmFwcGVyT2JqZWN0O1xuXG4gICAgICBzd2l0Y2ggKGNvbnRyb2xsZXIudmlldykge1xuICAgICAgICBjYXNlICdodG1sQ29udGFpbmVyJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LkRhdGFGaWVsZChjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdibG9jayc6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5CbG9jayhjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdkYXRhc291cmNlJzpcbiAgICAgICAgY2FzZSAnYnVzaW5lc3NFbnRpdHknOlxuICAgICAgICBjYXNlICdidXNpbmVzc0VudGl0eTInOlxuICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuRGF0YVNvdXJjZShjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdmb3JtJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LkZvcm0oY29udHJvbGxlcik7XG5cbiAgICAgICAgY2FzZSAnZmllbGRzZXQnOlxuICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuRmllbGRTZXQoY29udHJvbGxlcik7XG5cbiAgICAgICAgY2FzZSAnZHluc2VsZWN0JzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LkR5blNlbGVjdChjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdjb21ib2JveCc6XG4gICAgICAgIGNhc2UgJ211bHRpbGlzdCc6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5Db21ib0JveChjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdyaWNodGV4dCc6XG4gICAgICAgIGNhc2UgJ2l0dGV4dCc6XG4gICAgICAgIGNhc2UgJ2NrRWRpdG9yJzpcbiAgICAgICAgY2FzZSAnY2tSaWNoRWRpdG9yJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LlJpY2hUZXh0KGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ3RyYW5zbGF0JzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LlRyYW5zbGF0YWJsZShjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdpbnB1dCc6XG4gICAgICAgIGNhc2UgJ2lucHV0bnVtJzpcbiAgICAgICAgY2FzZSAnaW5wdXR0ZXh0JzpcbiAgICAgICAgY2FzZSAnZmlsZVNlbGVjdG9yJzpcblxuICAgICAgICAgIGlmIChjb250cm9sbGVyLm9wdC50eXBlID09PSAnY2hlY2tib3gnKVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5Ub2dnbGUoY29udHJvbGxlcik7XG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5JbnB1dChjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdidXR0b24nOlxuICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuQnV0dG9uKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ2NhbGVuZGFyJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LkNhbGVuZGFyKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ3NjaGVkdWxlcic6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5TY2hlZHVsZXIoY29udHJvbGxlcik7XG5cbiAgICAgICAgY2FzZSAndG9rZW5zZWxlY3QnOlxuICAgICAgICBjYXNlICdpbWFnZSc6XG4gICAgICAgIGNhc2UgJ2ljb25waWNrZXInOlxuICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuRGF0YUZpZWxkKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ2RhdGFncmlkJzpcbiAgICAgICAgY2FzZSAnZGF0YWdyaWQyJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LkdyaWQoY29udHJvbGxlcik7XG5cbiAgICAgICAgY2FzZSAncHJvcGVydHlncmlkJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LlByb3BlcnR5R3JpZChjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdkYXRhdmlldyc6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5EYXRhVmlldyhjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICd0cmVlZ3JpZCc6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5UcmVlR3JpZChjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdkYXRhZ3JpZGNvbCc6XG4gICAgICAgIGNhc2UgJ2RhdGFncmlkY29sMic6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5HcmlkQ29sKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ2ltYWdlYm94JzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LkltYWdlKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ3RhYmJhcic6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5UYWJiYXIoY29udHJvbGxlcik7XG5cbiAgICAgICAgY2FzZSAnc2lkZWJhcic6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5TaWRlYmFyKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ2NoYXJ0JzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LkNoYXJ0KGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ2dyYXBoRWRpdG9yJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LkdyYXBoRWRpdG9yKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ3BhbmVsJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LlBhbmVsKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ3BhbmVsU3dpdGNoZXInOlxuICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuUGFuZWxTd2l0Y2hlcihjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdmcmFtZSc6XG5cbiAgICAgICAgICAvLyB0b3AgbGV2ZWwgZnJhbWVzIGFyZSB0cmVhdGVkIGFzIHdpbmRvd3NcbiAgICAgICAgICBpZiAoY29udHJvbGxlcj8uZHluT2JqZWN0Py5wYXJlbnQ/LmNvbnRyb2xsZXI/LmlzQXV0b3N0YXJ0T2JqZWN0c1dpbmRvdylcbiAgICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuV2luZG93KGNvbnRyb2xsZXIpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuRnJhbWUoY29udHJvbGxlcik7XG5cbiAgICAgICAgY2FzZSAndGFza2Jhcic6XG4gICAgICAgIGNhc2UgJ2dyb3VwdGFza2Jhcic6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5UYXNrYmFyKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ3dpbmRvdyc6XG4gICAgICAgIGNhc2UgJ3BvcHVwJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LldpbmRvdyhjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdyaWJib24nOlxuICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuUmliYm9uKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ3Rvb2xiYXInOlxuICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuVG9vbGJhcihjb250cm9sbGVyKTtcblxuICAgICAgICBjYXNlICdkb2N2aWV3ZXInOlxuICAgICAgICAgIHJldHVybiBuZXcgYWtpb21hLnN3YXQuRG9jVmlld2VyKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ2ZyZWVIYW5kJzpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LkZyZWVIYW5kKGNvbnRyb2xsZXIpO1xuXG4gICAgICAgIGNhc2UgJ3VwbG9hZCc6XG4gICAgICAgICAgcmV0dXJuIG5ldyBha2lvbWEuc3dhdC5VcGxvYWQoY29udHJvbGxlcik7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gbmV3IGFraW9tYS5zd2F0LlN3YXRPYmplY3QoY29udHJvbGxlcik7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9Td2F0RmFjdG9yeS50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAqIEJhc2UgU3dhdCBPYmplY3RcbiAgICogQGV4cG9ydFxuICAgKiBAY2xhc3MgU3dhdE9iamVjdFxuICAgKiBAcGFyYW0geyp9IGR5bk9iamVjdCBUaGUgZHluT2JqZWN0XG4gICAqL1xuICBleHBvcnQgY2xhc3MgU3dhdE9iamVjdCB7XG5cbiAgICBwcm90ZWN0ZWQgX2NvbnRyb2xsZXI6IGFueTtcblxuICAgIHByaXZhdGUgX3BhcmVudDogU3dhdE9iamVjdDtcbiAgICBwcml2YXRlIF93aW5kb3c6IGFraW9tYS5zd2F0LldpbmRvdztcbiAgICBwcml2YXRlIF9jb250YWluZXI6IGFraW9tYS5zd2F0LldpbmRvdztcbiAgICBwcml2YXRlIF9zY3JlZW46IGFraW9tYS5zd2F0LldpbmRvdyB8IGFraW9tYS5zd2F0LkZyYW1lO1xuICAgIHByaXZhdGUgX3RvcFNjcmVlbjogYWtpb21hLnN3YXQuV2luZG93O1xuXG4gICAgY29uc3RydWN0b3IoY29udHJvbGxlcjogYW55KSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyID0gY29udHJvbGxlcjtcblxuICAgICAgLy8gdG8gYXZvaWQgY3JlYXRpbmcgbXVsdGlwbGUgd3JhcHBlciBvYmplY3RzXG4gICAgICAvLyBhIHJlZmVyZW5jZSB0byB0aGUgd3JhcHBlciBvYmplY3QgaXMgc2F2ZWRcbiAgICAgIC8vIGFuZCB1c2VkIGlmIGl0IGlzIG5lZWRlZCBhZ2FpblxuICAgICAgY29udHJvbGxlci5fYWtpb21hV3JhcHBlck9iamVjdCA9IHRoaXM7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGdldCBfZHluT2JqZWN0KCk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5keW5PYmplY3Q7XG4gICAgfVxuXG4gICAgZ2V0IGNsYXNzTmFtZSgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuICh0aGlzLmNvbnN0cnVjdG9yIGFzIGFueSkubmFtZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0J3MgbGVnYWN5IEFQSSBjb250cm9sbGVyLlxuICAgICAqIFVzZWQgZm9yIEphdmFTY3JpcHQgY2FsbHMgZnJvbSBUeXBlU2NyaXB0LlxuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHsqfVxuICAgICAqIEBleGFtcGxlXG4gICAgICogd2luZG93LmFraW9tYS5teUZ1bmN0aW9uKGV2ZW50U291cmNlLmNvbnRyb2xsZXIpO1xuICAgICAqL1xuICAgIGdldCBjb250cm9sbGVyKCk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0J3MgbGVnYWN5IEFQSSBkeW5PYmplY3QuXG4gICAgICogVXNlZCBmb3IgSmF2YVNjcmlwdCBjYWxscyBmcm9tIFR5cGVTY3JpcHQuXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQHR5cGUgeyp9XG4gICAgICogQGV4YW1wbGVcbiAgICAgKiB3aW5kb3cuYWtpb21hLm15RnVuY3Rpb24oZXZlbnRTb3VyY2UuZHluT2JqZWN0KTtcbiAgICAgKi9cbiAgICBnZXQgZHluT2JqZWN0KCk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5fZHluT2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG9iamVjdCBhdHRyaWJ1dGVzXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQHJldHVybiB7T2JqZWN0fVxuICAgICAqL1xuICAgIGdldCBhdHRyaWJ1dGVzKCk6IE9iamVjdCB7XG4gICAgICByZXR1cm4gKFxuICAgICAgICB0aGlzLl9jb250cm9sbGVyLm9wdCA/IHRoaXMuX2NvbnRyb2xsZXIub3B0IDpcbiAgICAgICAgICBudWxsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBvYmplY3QgbmFtZVxuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICovXG4gICAgZ2V0IG5hbWUoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIHRoaXMuX2R5bk9iamVjdCA/IHRoaXMuX2R5bk9iamVjdC5uYW1lIDpcbiAgICAgICAgICB0aGlzLl9jb250cm9sbGVyLm9wdCA/IHRoaXMuX2NvbnRyb2xsZXIub3B0Lm5hbWUgOlxuICAgICAgICAgICAgbnVsbFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgc3dhdCBvYmplY3QgZGlyZWN0IHBhcmVudFxuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHtTd2F0T2JqZWN0fVxuICAgICAqL1xuICAgIGdldCBwYXJlbnQoKTogU3dhdE9iamVjdCB7XG4gICAgICBpZiAoIXRoaXMuX3BhcmVudCkge1xuICAgICAgICBpZiAodGhpcy5fZHluT2JqZWN0KVxuICAgICAgICAgIHRoaXMuX3BhcmVudCA9IGFraW9tYS5zd2F0LlN3YXRGYWN0b3J5LmNyZWF0ZVN3YXRPYmplY3QodGhpcy5fZHluT2JqZWN0LnBhcmVudCk7XG5cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgbGV0IHBhcmVudCA9IHRoaXMuX2NvbnRyb2xsZXIucGFyZW50O1xuXG4gICAgICAgICAgd2hpbGUgKHBhcmVudCkge1xuICAgICAgICAgICAgaWYgKHBhcmVudC5keW5PYmplY3QgJiYgKHRoaXMuX3BhcmVudCA9IGFraW9tYS5zd2F0LlN3YXRGYWN0b3J5LmNyZWF0ZVN3YXRPYmplY3QocGFyZW50KSkpXG4gICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5fcGFyZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBzd2F0IG9iamVjdCB0b3AtbGV2ZWwgcGFyZW50LCB1c3VhbGx5IGEgd2luZG93IG9yIGRpYWxvZyBvYmplY3RcbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKi9cbiAgICBnZXQgY29udGFpbmVyKCk6IGFraW9tYS5zd2F0LldpbmRvdyB8IG51bGwge1xuICAgICAgY29uc3QgZHluT2JqZWN0ID0gdGhpcy5fZHluT2JqZWN0IHx8ICh0aGlzLnBhcmVudCA/IHRoaXMucGFyZW50Ll9keW5PYmplY3QgOiBudWxsKTtcblxuICAgICAgaWYgKCFkeW5PYmplY3QpXG4gICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICBpZiAoIXRoaXMuX2NvbnRhaW5lcilcbiAgICAgICAgdGhpcy5fY29udGFpbmVyID0gPGFraW9tYS5zd2F0LldpbmRvdz5ha2lvbWEuc3dhdC5Td2F0RmFjdG9yeS5jcmVhdGVTd2F0T2JqZWN0KGR5bk9iamVjdC5jb250YWluZXIpO1xuXG4gICAgICByZXR1cm4gdGhpcy5fY29udGFpbmVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBzd2F0IG9iamVjdCB0b3Agc2NyZWVuIChjb250YWluZXIpLCB1c3VhbGx5IGEgd2luZG93IG9yIGRpYWxvZyBvYmplY3RcbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKi9cbiAgICBnZXQgdG9wU2NyZWVuKCk6IGFraW9tYS5zd2F0LldpbmRvdyB8IG51bGwge1xuICAgICAgY29uc3QgZHluT2JqZWN0ID0gdGhpcy5fZHluT2JqZWN0IHx8ICh0aGlzLnBhcmVudCA/IHRoaXMucGFyZW50Ll9keW5PYmplY3QgOiBudWxsKTtcblxuICAgICAgaWYgKCFkeW5PYmplY3QpXG4gICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICBpZiAoIXRoaXMuX3RvcFNjcmVlbilcbiAgICAgICAgdGhpcy5fdG9wU2NyZWVuID0gPGFraW9tYS5zd2F0LldpbmRvdz5ha2lvbWEuc3dhdC5Td2F0RmFjdG9yeS5jcmVhdGVTd2F0T2JqZWN0KGR5bk9iamVjdC50b3BTY3JlZW4pO1xuXG4gICAgICByZXR1cm4gdGhpcy5fdG9wU2NyZWVuO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBzd2F0IG9iamVjdCBpbm5lciBzY3JlZW4gKGNvbnRhaW5lcilcbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKi9cbiAgICBnZXQgc2NyZWVuKCk6IGFraW9tYS5zd2F0LldpbmRvdyB8IGFraW9tYS5zd2F0LkZyYW1lIHwgbnVsbCB7XG4gICAgICBjb25zdCBkeW5PYmplY3QgPSB0aGlzLl9keW5PYmplY3QgfHwgKHRoaXMucGFyZW50ID8gdGhpcy5wYXJlbnQuX2R5bk9iamVjdCA6IG51bGwpO1xuXG4gICAgICBpZiAoIWR5bk9iamVjdClcbiAgICAgICAgcmV0dXJuIG51bGw7XG5cbiAgICAgIGlmICghdGhpcy5fc2NyZWVuKVxuICAgICAgICB0aGlzLl9zY3JlZW4gPSA8YWtpb21hLnN3YXQuV2luZG93IHwgYWtpb21hLnN3YXQuRnJhbWU+YWtpb21hLnN3YXQuU3dhdEZhY3RvcnkuY3JlYXRlU3dhdE9iamVjdChkeW5PYmplY3Quc2NyZWVuKTtcblxuICAgICAgcmV0dXJuIHRoaXMuX3NjcmVlbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgZGVzY2VuZGFudCBvYmplY3QgYnkgbmFtZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBvYmplY3QgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKiBAcmV0dXJucyB7U3dhdE9iamVjdH1cbiAgICAgKi9cbiAgICBnZXRPYmplY3Q8VCBleHRlbmRzIFN3YXRPYmplY3QgPSBTd2F0T2JqZWN0PihuYW1lOiBzdHJpbmcpOiBUIHtcbiAgICAgIGlmICghdGhpcy5keW5PYmplY3QpXG4gICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICBjb25zdCBkeW5PYmplY3QgPSB0aGlzLl9keW5PYmplY3QuZ2V0T2JqZWN0KG5hbWUpO1xuICAgICAgaWYgKCFkeW5PYmplY3QgfHwgIWR5bk9iamVjdC5jb250cm9sbGVyKVxuICAgICAgICByZXR1cm4gbnVsbDtcblxuICAgICAgaWYgKGR5bk9iamVjdC5jb250cm9sbGVyLl9ha2lvbWFXcmFwcGVyT2JqZWN0KVxuICAgICAgICByZXR1cm4gZHluT2JqZWN0LmNvbnRyb2xsZXIuX2FraW9tYVdyYXBwZXJPYmplY3Q7XG5cbiAgICAgIGNvbnN0IHN3YXRPYmplY3Q6IGFueSA9IGFraW9tYS5zd2F0LlN3YXRGYWN0b3J5LmNyZWF0ZVN3YXRPYmplY3QodGhpcy5fZHluT2JqZWN0LmdldE9iamVjdChuYW1lKSk7XG5cbiAgICAgIHJldHVybiBzd2F0T2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIG9iamVjdCdzIGxpbmsgc291cmNlIG9yIHRhcmdldCBvYmplY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGluayBUaGUgbGluayBuYW1lIHNlcGFyYXRlZCBieSBcIjpcIiBhbmQgU1JDL1RSRyBwb2ludHMgZS5nLiBcIkRBVEE6VFJHXCJcbiAgICAgKiBAcmV0dXJucyB7U3dhdE9iamVjdH1cbiAgICAgKiBAZXhhbXBsZSBteUZvcm0uZ2V0TGluayhcIkRJU1BMQVk6U1JDXCIpXG4gICAgICovXG4gICAgZ2V0TGluazxUIGV4dGVuZHMgU3dhdE9iamVjdCA9IFN3YXRPYmplY3Q+KGxpbms6IHN0cmluZyk6IFQge1xuXG4gICAgICBpZiAoIXRoaXMuZHluT2JqZWN0KVxuICAgICAgICByZXR1cm4gbnVsbDtcblxuICAgICAgY29uc3QgbGlua3MgPSB0aGlzLmdldExpbmtzPFQ+KGxpbmspO1xuXG4gICAgICBpZiAoIWxpbmtzIHx8IGxpbmtzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgcmV0dXJuIG51bGw7XG5cbiAgICAgIHJldHVybiBsaW5rc1swXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBvYmplY3QncyBsaW5rIHNvdXJjZSBvciB0YXJnZXQgb2JqZWN0c1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsaW5rIFRoZSBsaW5rIG5hbWUgc2VwYXJhdGVkIGJ5IFwiOlwiIGFuZCBTUkMvVFJHIHBvaW50cyBlLmcuIFwiREFUQTpUUkdcIlxuICAgICAqIEByZXR1cm5zIHtTd2F0T2JqZWN0fVtdXG4gICAgICogQGV4YW1wbGUgbXlEYXRhU291cmNlLmdldExpbmtzKFwiRElTUExBWTpUUkdcIilcbiAgICAgKi9cbiAgICBnZXRMaW5rczxUIGV4dGVuZHMgU3dhdE9iamVjdCA9IFN3YXRPYmplY3Q+KGxpbms6IHN0cmluZyk6IFRbXSB7XG4gICAgICBpZiAoIXRoaXMuZHluT2JqZWN0KVxuICAgICAgICByZXR1cm4gbnVsbDtcblxuICAgICAgLy8gdGhlIGdldExpbmsgaW4gYWtpb21hLm9iamVjdC5qcyBhY2NlcHRzIDpUQVJHRVQgYW5kIGFueXRoaW5nIGVsc2UgZm9yIFNPVVJDRVxuICAgICAgLy8gc28gZ2V0TGluayhcIkRJU1BMQVk6VFJHXCIpIGlzIGVxdWFsIHRvIGdldExpbmsoXCJESVNQTEFZOlNPVVJDRVwiKVxuXG4gICAgICBpZiAobGluay5lbmRzV2l0aCgnOlRSRycpKVxuICAgICAgICBsaW5rID0gbGluay5yZXBsYWNlKCc6VFJHJywgJzpUQVJHRVQnKTtcblxuICAgICAgLy8gbm90ZSB0aGF0IGxpbmtzIGNhbm5vdCBiZSBjYWNoZWRcbiAgICAgIC8vIGJlY2F1c2UgbGlua3MgY2FuIGJlIGFkZGVkIGR5bmFtaWNhbGx5IHdpdGggbGF6eSBsb2FkaW5nXG4gICAgICAvLyBidXQgdGhlIHdyYXBwZXIgb2JqZWN0IGlzIG5ldmVyIGNyZWF0ZWQgbW9yZSB0aGFuIG9uY2UgZm9yIGV2ZXJ5IG9iamVjdFxuXG4gICAgICBjb25zdCBsaW5rcyA9IHRoaXMuX2R5bk9iamVjdC5nZXRMaW5rcyhsaW5rKTtcblxuICAgICAgaWYgKCFsaW5rcyB8fCBsaW5rcy5sZW5ndGggPT09IDApXG4gICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICByZXR1cm4gbGlua3MubWFwKChsaW5rOiBhbnkpID0+IGFraW9tYS5zd2F0LlN3YXRGYWN0b3J5LmNyZWF0ZVN3YXRPYmplY3QobGluaykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBzd2F0IG9iamVjdCB0b3AtbGV2ZWwgd2luZG93IG9iamVjdC5cbiAgICAgKiBOb3RlOiBEZXNrdG9wIHdpbmRvd3MgYXJlIHdpbmRvd3Mgbm90IGZyYW1lc1xuICAgICAqIHNvIHRoZSB3aW5kb3cgcHJvcGVydHkgb2YgYSBjaGlsZCBvYmplY3QgaW4gYSBkZXNrdG9wIHdpbmRvdyB3aWxsIHJldHVybiB0aGUgZGVza3RvcCB3aW5kb3dcbiAgICAgKiB1bmxpa2UgdGhlIGNvbnRhaW5lciBwcm9wZXJ0eSB3aGljaCB3aWxsIHJldHVybiB0aGUgbWFpbiBkZXNrdG9wIHdpbmRvdyBmb3IgdGhlIGFwcGxpY2F0aW9uLlxuICAgICAqIE5vdGU6IElmIHRoZSBvYmplY3QgaXMgYSB3aW5kb3cgdGhlbiBpdCB3aWxsIHJldHVybnMgaXRzZWxmLlxuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHtXaW5kb3d9XG4gICAgICovXG4gICAgZ2V0IHdpbmRvdygpOiBha2lvbWEuc3dhdC5XaW5kb3cge1xuICAgICAgY29uc3QgZHluT2JqZWN0ID0gdGhpcy5fZHluT2JqZWN0IHx8ICh0aGlzLnBhcmVudCA/IHRoaXMucGFyZW50Ll9keW5PYmplY3QgOiBudWxsKTtcblxuICAgICAgaWYgKCFkeW5PYmplY3QpXG4gICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICBpZiAoIXRoaXMuX3dpbmRvdykge1xuXG4gICAgICAgIGlmICh0aGlzIGluc3RhbmNlb2YgYWtpb21hLnN3YXQuV2luZG93KVxuICAgICAgICAgIHRoaXMuX3dpbmRvdyA9IHRoaXM7XG4gICAgICAgIGVsc2UgaWYgKGR5bk9iamVjdC5jb250YWluZXIuY29udHJvbGxlci5pc0F1dG9zdGFydE9iamVjdHNXaW5kb3cpIHtcbiAgICAgICAgICBsZXQgcGFyZW50ID0gZHluT2JqZWN0LnBhcmVudDtcblxuICAgICAgICAgIHdoaWxlIChwYXJlbnQ/LnBhcmVudCAmJiAhcGFyZW50LnBhcmVudC5jb250cm9sbGVyLmlzQXV0b3N0YXJ0T2JqZWN0c1dpbmRvdyAmJiBwYXJlbnQucGFyZW50LmNvbnRyb2xsZXIudmlldyAhPT0gJ3BhbmVsU3dpdGNoZXInKVxuICAgICAgICAgICAgcGFyZW50ID0gcGFyZW50LnBhcmVudDtcblxuICAgICAgICAgIHRoaXMuX3dpbmRvdyA9IDxha2lvbWEuc3dhdC5XaW5kb3c+YWtpb21hLnN3YXQuU3dhdEZhY3RvcnkuY3JlYXRlU3dhdE9iamVjdChwYXJlbnQpO1xuICAgICAgICB9IGVsc2VcbiAgICAgICAgICB0aGlzLl93aW5kb3cgPSA8YWtpb21hLnN3YXQuV2luZG93PiB0aGlzLmNvbnRhaW5lcjtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuX3dpbmRvdztcbiAgICB9XG5cbiAgICAvKipcblx0XHQgKiBSZXR1cm5zIHRoZSBmaXJzdCBjaGlsZCBieSB0eXBlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgb2YgdGhlIG9iamVjdFxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJPZiBQYW5lbFxuXHRcdCAqL1xuICAgIGdldEZpcnN0Q2hpbGRCeVR5cGU8VCBleHRlbmRzIGFraW9tYS5zd2F0LlN3YXRPYmplY3Q+KHR5cGU6IHN0cmluZyk6IFQge1xuICAgICAgY29uc3QgZmlyc3RDaGlsZCA9IHRoaXMuY29udHJvbGxlci5keW5PYmplY3QuZ2V0Rmlyc3RDaGlsZEJ5VHlwZSh0eXBlKTtcbiAgICAgIHJldHVybiBha2lvbWEuc3dhdC5Td2F0RmFjdG9yeS5jcmVhdGVTd2F0T2JqZWN0KGZpcnN0Q2hpbGQpIGFzIFQ7XG4gICAgfVxuXG4gICAgLyoqXG5cdFx0ICogUmV0dXJucyB0aGUgZmlyc3QgY2hpbGQgYnkgdHlwZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIG9mIHRoZSBvYmplY3RcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyT2YgUGFuZWxcblx0XHQgKi9cbiAgICBnZXRGaXJzdFBhcmVudEJ5VHlwZSh0eXBlOiBzdHJpbmcpOiBha2lvbWEuc3dhdC5Td2F0T2JqZWN0IHtcbiAgICAgIGNvbnN0IGZpcnN0UGFyZW50ID0gdGhpcy5jb250cm9sbGVyLmR5bk9iamVjdC5nZXRGaXJzdFBhcmVudEJ5VHlwZSh0eXBlKTtcbiAgICAgIHJldHVybiBha2lvbWEuc3dhdC5Td2F0RmFjdG9yeS5jcmVhdGVTd2F0T2JqZWN0KGZpcnN0UGFyZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGZvciByZXRyaXZpbmcgdGhlIG9iamVjdCB0eXBlXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQgdHlwZSgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIudmlldy50b0xvd2VyQ2FzZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHN0YXRlIGRhdGEgb2YgYW4gb2JqZWN0LlxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJvZiBQYW5lbFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9XG4gICAgICovXG4gICAgZ2V0IHN0YXRlRGF0YSgpOiBPYmplY3Qge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuc3RhdGVEYXRhO1xuICAgIH1cblxuICAgIC8vUGxhY2Vob2xkZXIgZnVuY3Rpb24sIHRvIGJlIG92ZXJyaWRkZW4gaW4gY2hpbGQgdHlwZXNcbiAgICAvKiBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uICovXG4gICAgZGVzdHJveSgpIHt9XG4gIH1cbn1cbiIsIm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgQ3VzdG9tIHByb3BlcnRpZXMgaW4gdGhlIHVzZXIgcHJvZmlsZVxuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBVc2VyUHJvZmlsZVxuICAgKi9cblxuICBleHBvcnQgY2xhc3MgVXNlclByb2ZpbGUge1xuXG4gICAgLyoqXG4gICAgICogU2F2ZXMgY3VzdG9tIHByb3BlcnR5L3Byb3BlcnRpZXMgaW4gdGhlIHZ1ZXhTdG9yZVxuICAgICAqIElmIHVzZXJQcm9maWxlIEF1dG9TdG9yZSA9ICdvbkNoYW5nZScgaXQgd2lsbCBhbHNvIHNhdmUgdGhlIGNoYW5nZXMgdG8gdGhlIGRhdGFiYXNlXG4gICAgICogQG1lbWJlcm9mIFVzZXJQcm9maWxlXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvU2V0dGluZ3MgVGhlIG9iamVjdCBjb250YWluaW5nIHRoZSBuZXcgc2V0dGluZ3MgKGtleTogdmFsdWUpXG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgc3RhdGljIHNhdmVDdXN0b21Mb2NhbFByb2ZpbGVQcm9wZXJ0eShvU2V0dGluZ3M6IE9iamVjdCk6IHZvaWQge1xuICAgICAgd2luZG93LlVzZXJQcm9maWxlLnNhdmVDdXN0b21Mb2NhbFByb2ZpbGVQcm9wZXJ0eShvU2V0dGluZ3MpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgY3VzdG9tIHByb3BlcnR5IGJ5IGtleSBmcm9tIHRoZSB2dWV4U3RvcmVcbiAgICAgKiBJZiB1c2VyUHJvZmlsZSBBdXRvU3RvcmUgPSAnb25DaGFuZ2UnIGl0IHdpbGwgYWxzbyBzYXZlIHRoZSBjaGFuZ2VzIHRvIHRoZSBkYXRhYmFzZVxuICAgICAqIEBtZW1iZXJvZiBVc2VyUHJvZmlsZVxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBjdXN0b20gcHJvcGVydHkga2V5IHRvIHJlbW92ZVxuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqL1xuICAgIHN0YXRpYyByZW1vdmVDdXN0b21Mb2NhbFByb2ZpbGVQcm9wZXJ0eShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgd2luZG93LlVzZXJQcm9maWxlLnJlbW92ZUN1c3RvbUxvY2FsUHJvZmlsZVByb3BlcnR5KGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgY3VzdG9tIHByb3BlcnRpZXMgZnJvbSB0aGUgdnVleFN0b3JlXG4gICAgICogSWYgdXNlclByb2ZpbGUgQXV0b1N0b3JlID0gJ29uQ2hhbmdlJyBpdCB3aWxsIGFsc28gc2F2ZSB0aGUgY2hhbmdlcyB0byB0aGUgZGF0YWJhc2VcbiAgICAgKiBAbWVtYmVyb2YgVXNlclByb2ZpbGVcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgc3RhdGljIHJlbW92ZUN1c3RvbUxvY2FsUHJvZmlsZVByb3BlcnRpZXMoKTogdm9pZCB7XG4gICAgICB3aW5kb3cuVXNlclByb2ZpbGUucmVtb3ZlQ3VzdG9tTG9jYWxQcm9maWxlUHJvcGVydGllcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYWxsIGN1c3RvbSBwcm9wZXJ0aWVzIG9mIHRoZSB1c2VyIHByb2ZpbGUgZnJvbSB0aGUgdnVleFN0b3JlXG4gICAgICogQG1lbWJlcm9mIFVzZXJQcm9maWxlXG4gICAgICogQHN0YXRpY1xuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBjdXN0b20gcHJvcGVydGllcyBvYmplY3Qgd2l0aCBhbGwga2V5L3ZhbHVlc1xuICAgICAqL1xuICAgIHN0YXRpYyBsb2FkQ3VzdG9tTG9jYWxQcm9maWxlU2V0dGluZ3MoKTogT2JqZWN0IHtcbiAgICAgIHJldHVybiB3aW5kb3cuVXNlclByb2ZpbGUubG9hZEN1c3RvbUxvY2FsUHJvZmlsZVNldHRpbmdzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBjdXN0b20gcHJvcGVydHkgb2JqZWN0IGZyb20gdGhlIHVzZXIgcHJvZmlsZSB2dWV4U3RvcmUgZm9yIGdpdmVuIGtleVxuICAgICAqIEBtZW1iZXJvZiBVc2VyUHJvZmlsZVxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IEtleSBmb3Igd2hpY2ggdG8gcmV0dXJuIHRoZSB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHthbnl9IFZhbHVlIG9mIGdpdmVuIGN1c3RvbSBwcm9wZXJ0eVxuICAgICAqL1xuICAgIHN0YXRpYyBsb2FkQ3VzdG9tTG9jYWxQcm9maWxlU2V0dGluZyhrZXk6IHN0cmluZyk6IGFueSB7XG4gICAgICByZXR1cm4gd2luZG93LlVzZXJQcm9maWxlLmxvYWRDdXN0b21Mb2NhbFByb2ZpbGVTZXR0aW5nKGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJpZ2dlcnMgcmVsb2FkIG9mIHVzZXIgcHJvZmlsZSBmcm9tIHRoZSBzZXJ2ZXJcbiAgICAgKiBAbWVtYmVyb2YgVXNlclByb2ZpbGVcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTxhbnk+fVxuICAgICAqL1xuICAgIHN0YXRpYyBsb2FkRnJvbVNlcnZlcigpOiBQcm9taXNlPGFueT4ge1xuICAgICAgcmV0dXJuIHdpbmRvdy5Vc2VyUHJvZmlsZS5sb2FkRnJvbVNlcnZlcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHByb2ZpbGVBdXRvU3RvcmUgc3RyYXRlZ3kgdG8gdGhlIGdpdmVuIHZhbHVlLCB3aGljaCBoYW5kbGVzIHdoZW4gc2F2aW5ncyBzaG91bGQgb2NjdXJcbiAgICAgKiBAbWVtYmVyb2YgVXNlclByb2ZpbGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY1Byb2ZpbGVBdXRvU3RvcmUgVHlwZSBvZiBwcm9maWxlQXV0b1N0b3JlLCBjYW4gYmUgXCJvbkNoYW5nZVwiIG9yIFwib25Mb2dvdXRcIiBvciBcIlwiIChlbXB0eSlcbiAgICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRQcm9maWxlQXV0b1N0b3JlKGNQcm9maWxlQXV0b1N0b3JlOiBTdHJpbmcpOiB2b2lkIHtcbiAgICAgIHdpbmRvdy5Vc2VyUHJvZmlsZS5zZXRQcm9maWxlQXV0b1N0b3JlKGNQcm9maWxlQXV0b1N0b3JlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IFByb2ZpbGVBdXRvU3RvcmUgdHlwZVxuICAgICAqIEBtZW1iZXJvZiBVc2VyUHJvZmlsZVxuICAgICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHByb2ZpbGVBdXRvU3RvcmUgdHlwZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRQcm9maWxlQXV0b1N0b3JlKCk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gd2luZG93LlVzZXJQcm9maWxlLmdldFByb2ZpbGVBdXRvU3RvcmUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdG8gc2F2ZSB0aGUgVXNlclByb2ZpbGUgc2V0dGluZ3Mgb24gdGhlIGJhY2tlbmQgc2lkZVxuICAgICAqIEBwYXJhbSAge2Jvb2xlYW59IGJTaG93U3VjY2Vzc01zZyBGbGFnIGZvciBkaXNwbGF5aW5nIHRoZSBzdWNjZXNzIG1lc3NhZ2Ugb3Igbm90LCBkZWZhdWx0IHdpbGwgc2hvdyBpZiBub3Qgc3BlY2lmaWVkXG4gICAgICogQHBhcmFtICB7Ym9vbGVhbn0gbWV0aG9kTmFtZSBOYW1lIG9mIG1ldGhvZCB0byBiZSBjYWxsZWQgb24gc2F2ZSAoc2V0Q3VzdG9tUHJvcGVydHksIGRlbGV0ZUN1c3RvbVByb3BlcnR5IGV0Yy4pIGRlZmF1bHQ6IFNhdmVVc2VyUHJvZmlsZVxuICAgICAqIEBwYXJhbSAge29iamVjdH0gb0RhdGEgICAgICBEYXRhIHRvIGJlIHNlbnQgdG8gdGhlIGJhY2tlbmQ7IGNvbnRhaW5zIGN1c3RvbSBwcm9wZXJ0eSBvciB3aG9sZSB1c2VyIHByb2ZpbGUgYnkgZGVmYXVsdFxuICAgICAqIEBtZW1iZXJvZiBVc2VyUHJvZmlsZVxuICAgICAqIEByZXR1cm4ge3ZvaWR9XG4gICAgICovXG4gICAgc3RhdGljIHNhdmVUb1NlcnZlcihiU2hvd1N1Y2Nlc3NNc2c/OiBib29sZWFuLCBtZXRob2ROYW1lPzogU3RyaW5nLCBvRGF0YT86IG9iamVjdCk6IHZvaWQge1xuICAgICAgd2luZG93LlVzZXJQcm9maWxlLnNhdmVUb1NlcnZlcihiU2hvd1N1Y2Nlc3NNc2csIG1ldGhvZE5hbWUsIG9EYXRhKTtcbiAgICB9XG4gIH1cbn1cbiIsIm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAqIFdhaXQgQ3Vyc29yXG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIFdhaXRDdXJzb3JcbiAgICovXG4gIGV4cG9ydCBjbGFzcyBXYWl0Q3Vyc29yIHtcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB1c2VkIGZvciBzaG93aW5nIHRoZSB3YWl0IHN0YXRlLCB3YWl0IGN1cnNvciBhbmQgYmxvY2tpbmcgd2FpdGluZyBzdGF0ZSBvbiB3aW5kb3cgY29udGFpbmVyXG4gICAgICogQHBhcmFtIHtTd2F0T2JqZWN0fSB1aUNvbnRleHRcbiAgICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKi9cbiAgICBzdGF0aWMgc2hvd1dhaXRTdGF0ZSh1aUNvbnRleHQ6IGFraW9tYS5zd2F0LlN3YXRPYmplY3QpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuV2FpdEN1cnNvci5zaG93V2FpdFN0YXRlKHVpQ29udGV4dC5keW5PYmplY3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB1c2VkIGZvciBoaWRpbmcvZGlzYWJsaW5nIHRoZSB3YWl0IHN0YXRlLCB3YWl0IGN1cnNvciBhbmQgYmxvY2tpbmcgd2FpdGluZyBzdGF0ZSBvbiB3aW5kb3cgY29udGFpbmVyXG4gICAgICogQHBhcmFtIHtTd2F0T2JqZWN0fSB1aUNvbnRleHRcbiAgICAgKi9cbiAgICBzdGF0aWMgaGlkZVdhaXRTdGF0ZSh1aUNvbnRleHQ6IGFraW9tYS5zd2F0LlN3YXRPYmplY3QpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuV2FpdEN1cnNvci5oaWRlV2FpdFN0YXRlKHVpQ29udGV4dC5keW5PYmplY3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB1c2VkIGZvciBzaG93aW5nIHRoZSByb3RhdGluZyB3YWl0IGN1cnNvciBwZXIgcGFuZWxcbiAgICAgKiBAcGFyYW0ge1N3YXRPYmplY3R9IHVpQ29udGV4dFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gYkNhbmNlbGxhYmxlIEluZGljYXRlcyBpZiB5b3UgY2FuIGNhbmNlbCB0aGUgY3VycmVudCBKU0RPIHJlcXVlc3RcbiAgICAgKi9cbiAgICBzdGF0aWMgc2hvd1dhaXRDdXJzb3IodWlDb250ZXh0OiBha2lvbWEuc3dhdC5Td2F0T2JqZWN0LCBiQ2FuY2VsbGFibGU/OiBib29sZWFuKSB7XG4gICAgICB3aW5kb3cuYWtpb21hLldhaXRDdXJzb3Iuc2hvd1dhaXRDdXJzb3IodWlDb250ZXh0LmR5bk9iamVjdCwgYkNhbmNlbGxhYmxlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHNob3dpbmcgRXh0ZXJuYWwgd2FpdCBzdGF0ZSBpbiBleHRlcm5hbCBzY3JlZW4gLyBsaW5rZWQgd2FpdCBzdGF0ZVxuICAgICAqIEBwYXJhbSB7U3dhdE9iamVjdH0gdWlDb250ZXh0XG4gICAgICovXG4gICAgc3RhdGljIHNob3dFeHRlcm5hbFdhaXRTdGF0ZXModWlDb250ZXh0OiBha2lvbWEuc3dhdC5Td2F0T2JqZWN0KSB7XG4gICAgICB3aW5kb3cuYWtpb21hLldhaXRDdXJzb3Iuc2hvd0V4dGVybmFsV2FpdFN0YXRlcyh1aUNvbnRleHQuZHluT2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIGhpbmRpbmcgRXh0ZXJuYWwgc2NyZWVuIHdhaXQgc3RhdGUgLyBsaW5rZWQgd2FpdCBzdGF0ZVxuICAgICAqIEBwYXJhbSB7U3dhdE9iamVjdH0gdWlDb250ZXh0XG4gICAgICovXG4gICAgc3RhdGljIGhpZGVFeHRlcm5hbFdhaXRTdGF0ZXModWlDb250ZXh0OiBha2lvbWEuc3dhdC5Td2F0T2JqZWN0KSB7XG4gICAgICB3aW5kb3cuYWtpb21hLldhaXRDdXJzb3IuaGlkZUV4dGVybmFsV2FpdFN0YXRlcyh1aUNvbnRleHQuZHluT2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIGxpbmtpbmcgZXh0ZXJuYWwgc2NyZWVuIHdhaXQgc3RhdGVcbiAgICAgKiBAcGFyYW0ge1N3YXRPYmplY3R9IHVpQ29udGV4dCBUaGUgY29udHJvbCBpbiB0aGlzIHNjcmVlbiBsaW5rZWQgdG8gdGhlIGV4dGVybmFsIHdpbmRvd1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBleHRlcm5hbFdpbmRvd0lkIHRoZSBleHRlcm5hbCB3aW5kb3cgaWRcbiAgICAgKi9cbiAgICBzdGF0aWMgbGlua0V4dGVybmFsV2FpdFN0YXRlKHVpQ29udGV4dDpha2lvbWEuc3dhdC5Td2F0T2JqZWN0LCBleHRlcm5hbFdpbmRvd0lkOiBzdHJpbmcpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuV2FpdEN1cnNvci5saW5rRXh0ZXJuYWxXYWl0U3RhdGUodWlDb250ZXh0LmR5bk9iamVjdCwgZXh0ZXJuYWxXaW5kb3dJZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHVzZWQgZm9yIGhpZGluZyB0aGUgcm90YXRpbmcgd2FpdCBjdXJzb3IgcGVyIHBhbmVsXG4gICAgICogQHBhcmFtIHtTd2F0T2JqZWN0fSB1aUNvbnRleHRcbiAgICAgKi9cbiAgICBzdGF0aWMgaGlkZVdhaXRDdXJzb3IodWlDb250ZXh0OiBha2lvbWEuc3dhdC5Td2F0T2JqZWN0KSB7XG4gICAgICB3aW5kb3cuYWtpb21hLldhaXRDdXJzb3IuaGlkZVdhaXRDdXJzb3IodWlDb250ZXh0LmR5bk9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHVzZWQgZm9yIHNob3dpbmcvZW5hYmxpbmcgdGhlIGJsb2NraW5nIHByb2dyZXNzIHN0YXRlLCB1c2VyIHBvaW50ZXIgZXZlbnRzIGFyZSBibG9ja2VkIGluIHdpbmRvdyBjb250YWluZXJcbiAgICAgKiBAcGFyYW0ge1N3YXRPYmplY3R9IHVpQ29udGV4dFxuICAgICAqL1xuICAgIHN0YXRpYyBzaG93UHJvZ3Jlc3NTdGF0ZSh1aUNvbnRleHQ6IGFraW9tYS5zd2F0LlN3YXRPYmplY3QpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuV2FpdEN1cnNvci5zaG93UHJvZ3Jlc3NTdGF0ZSh1aUNvbnRleHQuZHluT2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdXNlZCBmb3IgaGlkaW5nIHRoZSBwcm9ncmVzcyBzdGF0ZSwgdXNlciBwb2ludGVyIGV2ZW50cyB1bmJsb2NrZWQgaW4gd2luZG93IGNvbnRhaW5lclxuICAgICAqIEBwYXJhbSB7U3dhdE9iamVjdH0gdWlDb250ZXh0XG4gICAgICovXG4gICAgc3RhdGljIGhpZGVQcm9ncmVzc1N0YXRlKHVpQ29udGV4dDogYWtpb21hLnN3YXQuU3dhdE9iamVjdCkge1xuICAgICAgd2luZG93LmFraW9tYS5XYWl0Q3Vyc29yLmhpZGVQcm9ncmVzc1N0YXRlKHVpQ29udGV4dC5keW5PYmplY3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCByZXR1cm5pbmcgY3VycmVudCBnbG9iYWwgc3RhdGUgb2Ygd2FpdCBjdXJzb3JcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNHbG9iYWxQcm9ncmVzc1N0YXRlQWN0aXZlKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHdpbmRvdy5ha2lvbWEuV2FpdEN1cnNvci5pc0dsb2JhbFByb2dyZXNzU3RhdGVBY3RpdmUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdXNlZCBmb3Igc2V0dGluZyB0aGUgd2FpdCBjdXJzb3IgZm9yIGFsbCBsaW5rIHRhcmdldHMgb2YgdGhlIGdpdmVuIGJ1c2luZXNzRW50aXR5XG4gICAgICogQHBhcmFtIHtEYXRhU291cmNlfSB1aUNvbnRleHRcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGluUHJvZ3Jlc3MgU2V0IHRoZSBjdXJzb3Igc3RhdGUsIHRydWUgb3IgZmFsc2VcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0V2FpdEN1cnNvckZvckxpbmtzKHVpQ29udGV4dDogYWtpb21hLnN3YXQuRGF0YVNvdXJjZSwgaW5Qcm9ncmVzczogYm9vbGVhbikge1xuICAgICAgd2luZG93LmFraW9tYS5XYWl0Q3Vyc29yLnNldFdhaXRDdXJzb3JGb3JMaW5rcyh1aUNvbnRleHQuZHluT2JqZWN0LCBpblByb2dyZXNzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdXNlZCBmb3IgY2hlY2tpbmcgaWYgcHJvZ3Jlc3Mgc3RhdGUgaXMgYWN0aXZlXG4gICAgICogQHBhcmFtIHtTd2F0T2JqZWN0fSAgIHVpQ29udGV4dCBTd2F0IGR5bk9iamVjdFxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyb2YgV2FpdEN1cnNvclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc1Byb2dyZXNzU3RhdGVBY3RpdmUodWlDb250ZXh0OmFraW9tYS5zd2F0LlN3YXRPYmplY3QpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB3aW5kb3cuYWtpb21hLldhaXRDdXJzb3IuaXNQcm9ncmVzc1N0YXRlQWN0aXZlKHVpQ29udGV4dCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHJldHVybmluZyBnaXZlbiB1aUNvbnRleHQgZHluT2JqZWN0IHdhaXRDdXJzb3IgdmlzaWJpbGl0eVxuICAgICAqIEBwYXJhbSB7U3dhdE9iamVjdH0gICB1aUNvbnRleHRcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlcm9mIFdhaXRDdXJzb3JcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNDdXJzb3JWaXNpYmxlKHVpQ29udGV4dDpha2lvbWEuc3dhdC5Td2F0T2JqZWN0KTogYm9vbGVhbiB7XG4gICAgICByZXR1cm4gd2luZG93LmFraW9tYS5XYWl0Q3Vyc29yLmlzQ3Vyc29yVmlzaWJsZSh1aUNvbnRleHQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB1c2VkIGZvciBjbGVhcmluZyB1cCBhbGwgdGhlIHdpbmRvd3MgdGhhdCBoYXZlIHByb2dyZXNzIHN0YXRlIGFjdGl2ZVxuICAgICAqL1xuICAgIHN0YXRpYyBjbGVhclByb2dyZXNzU3RhdGVHbG9iYWxseSgpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuV2FpdEN1cnNvci5jbGVhclByb2dyZXNzU3RhdGVHbG9iYWxseSgpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uL1N3YXRPYmplY3QudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBGb3JlaWduIEtleXMgVHlwZVxuICAgKiBGb3IgdXNlIGJ5IGdldCBmb3JlaWduIGtleSBwcm92aWRlcnNcbiAgICovXG4gIGV4cG9ydCB0eXBlIEZvcmVpZ25LZXlzID0geyBuYW1lOiBzdHJpbmc7IHZhbHVlOiBudW1iZXIgfCBzdHJpbmcgfCBib29sZWFuIHwgRGF0ZSB9W107XG5cbiAgLyoqXG4gICAqIEV2ZW50QmVmb3JlRmV0Y2ggb2YgRGF0YVNvdXJjZSBvcHRpb25zIGludGVyZmFjZVxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBFdmVudEJlZm9yZUZldGNoT3B0aW9ucyB7XG4gICAgcHJldmVudFF1ZXJ5ID86IGJvb2xlYW47XG4gIH1cblxuICAvKipcbiAgICogRGF0YVNvdXJjZSBPYmplY3RcbiAgICogQGV4cG9ydFxuICAgKiBAY2xhc3MgRGF0YVNvdXJjZVxuICAgKiBAZXh0ZW5kcyB7U3dhdE9iamVjdH1cbiAgICovXG4gIGV4cG9ydCBjbGFzcyBEYXRhU291cmNlIGV4dGVuZHMgYWtpb21hLnN3YXQuU3dhdE9iamVjdCB7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBkYXRhIG9iamVjdCBmaWVsZCB2YWx1ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmaWVsZCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIGdldFZhbHVlKG5hbWU6IHN0cmluZyk6IGFueSB7XG4gICAgICBuYW1lID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICBsZXQgdmFsdWUgPSB0aGlzLl9jb250cm9sbGVyLmdldEZpZWxkVmFsdWUobmFtZSk7XG5cbiAgICAgIC8vIGNvcGllZCBmcm9tIGdldFZhbHVlKCkgbWV0aG9kIGluIGFraW9tYS5vYmplY3QuanNcbiAgICAgIC8vIG5lZWQgdG8gY2hlY2sgaWYgdGhpcyBwYXJ0IGlzIG5lZWRlZFxuICAgICAgaWYgKG5hbWUgPT09ICdzZWxmaGRsJykge1xuICAgICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHZhbHVlID0gdGhpcy5fY29udHJvbGxlci5nZXRGaWVsZFZhbHVlKCdTZWxmSGRsJyk7XG4gICAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMuX2NvbnRyb2xsZXIuZ2V0RmllbGRWYWx1ZSgnc2VsZkhkbCcpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBkYXRhIG9iamVjdCBmaWVsZCB2YWx1ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmaWVsZCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEBwYXJhbSB7dmFsdWV9IHZhbHVlIFRoZSB2YWx1ZSBvZiB0aGUgZmllbGRcbiAgICAgKiBAcGFyYW0ge2FueX0gcHJpbWFyeUtleSBUaGUgdmFsdWUgY29ycmVzcG9uZGluZyB0byB0aGUgS2V5RmllbGQgYXR0cmlidXRlOyB1c2VkIHRvIHVuaXF1ZWx5IGlkZW50aWZ5IHRoZSByZWNvcmQgZm9yIHdoaWNoIHRvIHNldCB0aGUgbmV3IHZhbHVlOyBvcHRpb25hbFxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHNldFZhbHVlKG5hbWU6IHN0cmluZywgdmFsdWU6IGFueSwgcHJpbWFyeUtleT86IHN0cmluZykge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRGaWVsZFZhbHVlKHtcbiAgICAgICAgbmFtZTogbmFtZS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIHN0YXRlOiAndXBkYXRlZCcsXG4gICAgICAgIHByaW1hcnlLZXk6IHByaW1hcnlLZXlcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGN1cnJlbnQgcmVjb3JkIHdpdGggYWxsIHRoZSByZWNvcmQgdmFsdWVzXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGN1cnJlbnQgcmVjb3JkXG4gICAgICovXG4gICAgZ2V0Q3VycmVudFJlY29yZCgpOiBhbnkge1xuICAgICAgY29uc3QgaWQgPSB0aGlzLl9jb250cm9sbGVyLmdldFN0b3JlKHRoaXMuX2NvbnRyb2xsZXIuZW50aXR5TmFtZSkuZ2V0Q3Vyc29yKCk7XG5cbiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCB0aGlzLl9jb250cm9sbGVyLmdldFN0b3JlKHRoaXMuX2NvbnRyb2xsZXIuZW50aXR5TmFtZSkuaXRlbShpZCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYWxsIHRoZSBsb2FkZWQgcmVjb3Jkc1xuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIGFuIGFycmF5IHdpdGggYWxsIHRoZSBsb2FkZWQgcmVjb3Jkc1xuICAgICAqL1xuICAgIGdldExvYWRlZFJlY29yZHMoKTogYW55W10ge1xuICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2NvbnRyb2xsZXIuZGh4LmRhdGEucHVsbDtcblxuICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGRhdGEpLm1hcChrZXkgPT4gT2JqZWN0LmFzc2lnbih7fSwgZGF0YVtrZXldKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhbGwgdGhlIHVwZGF0ZWQgcmVjb3Jkc1xuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIGFuIGFycmF5IHdpdGggYWxsIHRoZSB1cGRhdGVkIHJlY29yZHNcbiAgICAgKi9cbiAgICBnZXRVcGRhdGVkUmVjb3JkcygpOiBhbnlbXSB7XG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5fY29udHJvbGxlci5kaHguZGF0YS5wdWxsO1xuXG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5kYy51cGRhdGVkUm93cy5tYXAoKGtleTogc3RyaW5nIHwgbnVtYmVyKSA9PiBPYmplY3QuYXNzaWduKHt9LCBkYXRhW2tleV0pKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFsbCB0aGUgbG9jYWxseSBzdG9yZWQgZGF0YS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGFuIG9iamVjdCBjb250YWluaW5nIHRoZSBsb2NhbGx5IHN0b3JlZCBkYXRhXG4gICAgICovXG4gICAgZ2V0RGF0YSgpOiBPYmplY3Qge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0RGF0YSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsZWFycyBhbGwgZmlsdGVyc1xuICAgICAqL1xuICAgIGNsZWFyRmlsdGVyKCkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5xdWVyeS5jbGVhckFsbCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBmaWx0ZXIgKHRvcCBsZXZlbCBBTkQgZmlsdGVyKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSAgbmFtZSAgICAgVGhlIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9ICBvcGVyYXRvciBUaGUgZmlsdGVyIG9wZXJhdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9ICB2YWx1ZSAgICBUaGUgZmlsdGVyIHZhbHVlXG4gICAgICogQHBhcmFtIHtib29sZWFufSB1bmlxdWUgICBJZiB0cnVlLCBhZGRzIGEgbmV3IHVuaXF1ZSBjb25kaXRpb24gdGhhdCB3aWxsIG92ZXJ3cml0ZSBhbnkgY29uZGl0aW9ucyB3aXRoIHRoZSBzYW1lIGZpZWxkIG5hbWUuIElmIGZhbHNlLCBqdXN0IGFkZHMgYSBuZXcgY29uZGl0aW9uXG4gICAgICovXG4gICAgYWRkRmlsdGVyKG5hbWU6IHN0cmluZywgb3BlcmF0b3I6IHN0cmluZywgdmFsdWU6IGFueSwgdW5pcXVlPzogYm9vbGVhbikge1xuICAgICAgdGhpcy5zZXRGaWx0ZXIobmFtZSwgb3BlcmF0b3IsIHZhbHVlLCB1bmlxdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBmaWx0ZXIgKHRvcCBsZXZlbCBBTkQgZmlsdGVyKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSAgbmFtZSAgICAgVGhlIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9ICBvcGVyYXRvciBUaGUgZmlsdGVyIG9wZXJhdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9ICB2YWx1ZSAgICBUaGUgZmlsdGVyIHZhbHVlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbdW5pcXVlXSBJZiB0cnVlLCBhZGRzIGEgbmV3IHVuaXF1ZSBjb25kaXRpb24gdGhhdCB3aWxsIG92ZXJ3cml0ZSBhbnkgY29uZGl0aW9ucyB3aXRoIHRoZSBzYW1lIGZpZWxkIG5hbWUuIElmIGZhbHNlLCBqdXN0IGFkZHMgYSBuZXcgY29uZGl0aW9uXG4gICAgICovXG4gICAgc2V0RmlsdGVyKG5hbWU6IHN0cmluZywgb3BlcmF0b3I6IHN0cmluZywgdmFsdWU6IGFueSwgdW5pcXVlPzogYm9vbGVhbikge1xuICAgICAgbmFtZSA9IG5hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgICAgaWYgKHRoaXMuaGFzRmlsdGVyKG5hbWUsIG9wZXJhdG9yLCB2YWx1ZSkpXG4gICAgICAgIHJldHVybjtcblxuICAgICAgaWYgKHVuaXF1ZSlcbiAgICAgICAgdGhpcy5fY29udHJvbGxlci5xdWVyeS5hZGRVbmlxdWVDb25kaXRpb24obmFtZSwgb3BlcmF0b3IsIHZhbHVlKTtcbiAgICAgIGVsc2VcbiAgICAgICAgdGhpcy5fY29udHJvbGxlci5xdWVyeS5hZGRDb25kaXRpb24obmFtZSwgb3BlcmF0b3IsIHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGVyZSBhcmUgYW55IGZpbHRlcnMgZm9yIGEgZmllbGQgKHRvcCBsZXZlbCBBTkQgZmlsdGVyKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmaWVsZCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGhhc0ZpbHRlcnMobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICBuYW1lID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIucXVlcnkuaGFzQ29uZGl0aW9ucyhuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBzcGVjaWZpYyBmaWx0ZXIgZXhpc3RzICh0b3AgbGV2ZWwgQU5EIGZpbHRlcilcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gIG5hbWUgICAgIFRoZSBmaWVsZCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSAgb3BlcmF0b3IgVGhlIGZpbHRlciBvcGVyYXRvclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSAgdmFsdWUgICAgVGhlIGZpbHRlciB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGhhc0ZpbHRlcihuYW1lOiBzdHJpbmcsIG9wZXJhdG9yOiBzdHJpbmcsIHZhbHVlOiBhbnkpOiBib29sZWFuIHtcbiAgICAgIG5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5xdWVyeS5oYXNDb25kaXRpb24obmFtZSwgb3BlcmF0b3IsIHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBmaWx0ZXIgY29uZGl0aW9ucyBmcm9tIGEgZ2l2ZW4gZmllbGQgbmFtZS4gKHRvcCBsZXZlbCBBTkQgZmlsdGVyKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmaWVsZCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEByZXR1cm5zIHtPYmplY3RbXXxudWxsfVxuICAgICAqL1xuICAgIGdldEZpbHRlcihuYW1lOiBzdHJpbmcpOiBvYmplY3QgW10ge1xuICAgICAgbmFtZSA9IG5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLnF1ZXJ5LmdldEZpbHRlckJ5TmFtZShuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFuIGV4aXN0aW5nIGZpbHRlciBjb25kaXRpb24gKHRvcCBsZXZlbCBBTkQgZmlsdGVyKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSAgbmFtZSAgICAgVGhlIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9ICBvcGVyYXRvciBUaGUgZmlsdGVyIG9wZXJhdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9ICB2YWx1ZSAgICBUaGUgZmlsdGVyIHZhbHVlXG4gICAgICovXG4gICAgcmVtb3ZlRmlsdGVyKG5hbWU6IHN0cmluZywgb3BlcmF0b3I6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgICAgbmFtZSA9IG5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIucXVlcnkucmVtb3ZlQ29uZGl0aW9uKG5hbWUsIG9wZXJhdG9yLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xlYXJzIHNvcnRpbmdcbiAgICAgKi9cbiAgICBjbGVhclNvcnQoKSB7XG4gICAgICBjb25zdCBuZXdmaWx0ZXIgPSB0aGlzLl9jb250cm9sbGVyLnF1ZXJ5O1xuXG4gICAgICBuZXdmaWx0ZXIuY2xlYXJTb3J0KCk7XG4gICAgICBuZXdmaWx0ZXIuYnVpbGRRdWVyeSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhIGZpZWxkIChhbmQgb3B0aW9uYWwgZGlyZWN0aW9uKSBhcmUgaW4gdGhlIGRhdGFzb3VyY2Ugc29ydGluZy5cbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIGZpZWxkIGV4aXN0cyBhdCBhbnkgbGV2ZWwgbm90IGp1c3QgdGhlIGZpcnN0IGxldmVsLlxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBmaWVsZCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKS4gSWYgbm8gZmllbGQgbmFtZSBpcyBwYXNzZWQsIGNoZWNrcyBpZiB0aGVyZSBpcyBhbnkgc29ydGluZy5cbiAgICAgKiBAcGFyYW0gZGlyZWN0aW9uIFwiYXNjXCIgZm9yIGFzY2VuZGluZyBvciBcImRlc2NcIiBmb3IgZGVzY2VuZGluZy4gSWYgbm8gZGlyZWN0aW9uIGlzIHBhc3NlZCwgY2hlY2sgaWYgb25seSBmaWVsZCBuYW1lIGV4aXN0cy5cbiAgICAgKi9cbiAgICBoYXNTb3J0KG5hbWU/OiBzdHJpbmcsIGRpcmVjdGlvbj86ICdhc2MnIHwgJ2Rlc2MnKTogYm9vbGVhbiB7XG4gICAgICBjb25zdCBzb3J0TGlzdCA9IHRoaXMuZ2V0U29ydCgpO1xuXG4gICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgaWYgKHNvcnRMaXN0ICYmIHNvcnRMaXN0Lmxlbmd0aCA+IDApXG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIG5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgIGZvciAoY29uc3Qgc29ydCBvZiBzb3J0TGlzdCkge1xuICAgICAgICBpZiAoc29ydC5maWVsZC50b0xvd2VyQ2FzZSgpID09PSBuYW1lKSB7XG4gICAgICAgICAgaWYgKGRpcmVjdGlvbikge1xuICAgICAgICAgICAgaWYgKHNvcnQuZGlyZWN0aW9uID09PSBkaXJlY3Rpb24pXG4gICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc29ydGluZ1xuICAgICAqIEBwYXJhbSB7YXJyYXl9IFtzb3J0XVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzb3J0LmZpZWxkIFRoZSBmaWVsZCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzb3J0LmRpcmVjdGlvbiBcImFzY1wiIGZvciBhc2NlbmRpbmcgb3IgXCJkZXNjXCIgZm9yIGRlc2NlbmRpbmdcbiAgICAgKi9cbiAgICBzZXRTb3J0KG5hbWU6IHN0cmluZyk6IHZvaWQ7XG4gICAgc2V0U29ydChuYW1lOiBzdHJpbmcsIGRpcmVjdGlvbjogJ2FzYycgfCAnZGVzYycpOiB2b2lkO1xuICAgIHNldFNvcnQoc29ydDoge2ZpZWxkOiBzdHJpbmcsIGRpcmVjdGlvbjogJ2FzYycgfCAnZGVzYyd9W10pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc29ydGluZ1xuICAgICAqIEBwYXJhbSB7YXJyYXl9IFtzb3J0XVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzb3J0LmZpZWxkIFRoZSBmaWVsZCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzb3J0LmRpcmVjdGlvbiBcImFzY1wiIGZvciBhc2NlbmRpbmcgb3IgXCJkZXNjXCIgZm9yIGRlc2NlbmRpbmdcbiAgICAgKi9cbiAgICBzZXRTb3J0KHNvcnQ6IGFueSwgLi4uYXJnczogYW55W10pIHtcbiAgICAgIGlmICh0eXBlb2YgYXJnc1swXSA9PT0gJ3N0cmluZycpXG4gICAgICAgIHNvcnQgPSBbeyBmaWVsZDogYXJnc1swXSwgZGlyZWN0aW9uOiBhcmdzWzFdIHx8ICdhc2MnIH1dO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLnF1ZXJ5LnNldFNvcnRpbmcoc29ydCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCBzb3J0aW5nXG4gICAgICovXG4gICAgZ2V0U29ydCgpOiB7ZmllbGQ6IHN0cmluZywgZGlyZWN0aW9uOiAnYXNjJyB8ICdkZXNjJ31bXSB7XG4gICAgICBpZiAoIXRoaXMuX2NvbnRyb2xsZXIucXVlcnkuYVNvcnRpbmcpXG4gICAgICAgIHJldHVybiBbXTtcblxuICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5fY29udHJvbGxlci5xdWVyeS5hU29ydGluZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIG5hbWVkIHF1ZXJ5IHBhcmFtZXRlclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBxdWVyeSBUaGUgcGFyYW1ldGVyIHF1ZXJ5IG5hbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgcGFyYW1ldGVyIGZpZWxkIG5hbWVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBwYXJhbWV0ZXIgdmFsdWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBUaGUgcGFyYW1ldGVyIHR5cGVcbiAgICAgKi9cbiAgICBzZXROYW1lZFF1ZXJ5UGFyYW0ocXVlcnk6IHN0cmluZywgbmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0TmFtZWRRdWVyeVBhcmFtKHF1ZXJ5LCBuYW1lLCB2YWx1ZSwgdHlwZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHVzZWQgZm9yIHNldHRpbmcgdGhlIGZvcmVpZ24ga2V5IGZpZWxkcyBmb3IgdGhlIGRhdGFTb3VyY2UsIHRoYXQgd2lsbCBiZSBzZW50IGFzIHJlcXVlc3QgcGF5bG9hZCBpbiBHZXRJbml0aWFsVmFsdWVzIGNhbGxcbiAgICAgKiBAcGFyYW0ge2FycmF5fSBrZXlzIFRoZSBsaXN0IG9mIGZvcmVpZ24ga2V5IGZpZWxkcyB3aXRoIHZhbHVlc1xuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqL1xuICAgIHNldEZvcmVpZ25LZXlzKGtleXM6IHsgbmFtZTogc3RyaW5nLCB2YWx1ZTogYW55IH1bXSkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRGb3JlaWduS2V5cyhrZXlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBidXNpbmVzc0VudGl0eSB0byBwZXJmb3JtIHF1ZXJpZXMgdGhhdCBpbmNsdWRlIGJvdGggZmlsdGVycyBhbmQgTmFtZWRRdWVyeSBwYXJhbXNcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGJBcHBseSBUaGUgcGFyYW1ldGVyIHRoYXQgc2V0cyB0aGUgYXBwbHkgYWxsIGZpbHRlcnMgZmxhZ1xuICAgICAqL1xuICAgIHNldEFwcGx5UXVlcnlGaWx0ZXJzKGJBcHBseTogYm9vbGVhbikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5hcHBseUFsbFF1ZXJ5RmlsdGVycyhiQXBwbHkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNhdmVzIGN1cnJlbnQgcmVjb3JkXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgc2F2ZVJlY29yZCgpOiBQcm9taXNlPHsganNkbzogYW55LCBzdWNjZXNzOiBib29sZWFuOyByZXF1ZXN0OiBhbnk7IH0+IHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLnVwZGF0ZVJlY29yZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlbGV0ZXMgdGhlIGN1cnJlbnQgcmVjb3JkXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgRGVsZXRlIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmNsb3NlV2luZG93PXRydWVdIENsb3NlcyB0aGUgY29udGFpbmVyIHdpbmRvdyBhZnRlciBkZWxldGUuIERlZmF1bHRzIHRvIHRydWUuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgZGVsZXRlUmVjb3JkKG9wdGlvbnMgPSB7IGNsb3NlV2luZG93OiB0cnVlIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIHJldHVybiB0aGlzLmNvbnRyb2xsZXIuZGVsZXRlUmVjb3JkKG9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBuZXcgZW1wdHkgcmVjb3JkXG4gICAgICovXG4gICAgYWRkUmVjb3JkKCkge1xuICAgICAgdGhpcy5jb250cm9sbGVyLmFkZFJlY29yZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlcHJlY2F0ZWQgbWV0aG9kIHRvIGV4ZWN1dGUgdGhlIHF1ZXJ5XG4gICAgICogQGRlcHJlY2F0ZWQgVXNlIGZldGNoKCkgaW5zdGVhZFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnJlcG9zaXRpb25UbyBUaGUgaGFuZGxlIHVzZWQgdG8gcG9zaXRpb24gYSByZWNvcmQgaW4gR3JpZC5cbiAgICAgKiBDYW4gYmUgYSBjb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBoYW5kbGVzIHdoZW4gdXNpbmcgYSBtdWx0aXNlbGVjdCBHcmlkLlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgYXQgdGhlIEFmdGVyRmlsbCBldmVudC5cbiAgICAgKi9cbiAgICBvcGVuUXVlcnkob3B0czoge1xuICAgICAgcmVwb3NpdGlvblRvPzogc3RyaW5nO1xuICAgIH0gPSB7fSwgY2FsbGJhY2s6ICgpID0+IHZvaWQgPSBudWxsKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLm9wZW5RdWVyeShvcHRzLCBjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xvc2VzIHRoZSBxdWVyeSBhbmQgZW1wdGllcyB0aGUgcmVjb3Jkc1xuICAgICAqL1xuICAgIGNsb3NlUXVlcnkoKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmRoeC5jbGVhckFsbCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnJlcG9zaXRpb25UbyBUaGUgaGFuZGxlIHVzZWQgdG8gcG9zaXRpb24gYSByZWNvcmQgaW4gR3JpZC5cbiAgICAgKiBDYW4gYmUgYSBjb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBoYW5kbGVzIHdoZW4gdXNpbmcgYSBtdWx0aXNlbGVjdCBHcmlkLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHVua25vd24+fSBSZXR1cm5zIGEgcHJvbWlzZSB3aXRoIHRoZSByZXBvbnNlXG4gICAgICovXG4gICAgZmV0Y2gob3B0czoge1xuICAgICAgcmVwb3NpdGlvblRvPzogc3RyaW5nO1xuICAgIH0gPSB7fSk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZmV0Y2gob3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCByZWNvcmQgZGF0YSBiZWZvcmUgY2hhbmdlc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIGdldEJlZm9yZURhdGEoKTogYW55IHtcbiAgICAgIGNvbnN0IGlkID0gdGhpcy5fY29udHJvbGxlci5kaHguZ2V0Q3Vyc29yKCk7XG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5fY29udHJvbGxlci5qc2RvW3RoaXMuX2NvbnRyb2xsZXIub3B0LmVudGl0eU5hbWVdLmZpbmQoKHJlY29yZDogYW55KSA9PiAocmVjb3JkLmRhdGEuX2lkID09PSBpZCkpLmRhdGE7XG4gICAgICBjb25zdCByZXRWYWw6IGFueSA9IHt9O1xuXG4gICAgICBmb3IgKGNvbnN0IGtleSBpbiBkYXRhKVxuICAgICAgICByZXRWYWxba2V5XSA9IGRhdGFba2V5XTtcblxuXG4gICAgICByZXR1cm4gcmV0VmFsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgaWYgdGhlcmUgYXJlIGNoYW5nZXMsIHJlY3VzaXZlIGhhc0NoYW5nZXMgY2hlY2tcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBoYXNDaGFuZ2VzKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuaGFzQ2hhbmdlcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgaWYgdGhlcmUgYXJlIG1lc3NhZ2VzIGZyb20gdGhlIHByZXZpb3VzIHNhdmVcbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQgaGFzTWVzc2FnZXMoKTogYm9vbGVhbiB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5iQ29udGFpbnNTbWFydE1lc3NhZ2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHVzZWQgZm9yIGdldHRpbmcgdGhlIHJlZnJlc2ggc2NoZW1lIHBheWxvYWRcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R8bnVsbH1cbiAgICAgKi9cbiAgICBnZXQgcmVmcmVzaFNjaGVtZVBheWxvYWQoKTogT2JqZWN0fG51bGwge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0UmVmcmVzaFNjaGVtZVBheWxvYWQoKTtcbiAgICB9XG4gIH1cbn1cbiIsIm5hbWVzcGFjZSBha2lvbWEge1xuICBpbnRlcmZhY2UgU2NyZWVuT3B0aW9ucyB7XG4gICAgd2lkdGggPzogbnVtYmVyO1xuICAgIGhlaWdodCA/OiBudW1iZXI7XG4gICAgdG9wID86IG51bWJlcjtcbiAgICBsZWZ0ID86IG51bWJlcjtcbiAgICBob3N0bmFtZSA/OiBzdHJpbmc7XG4gIH1cblxuICB0eXBlIFdpbmRvd1RhcmdldE9wdGlvbnMgPSAnX3NlbGYnIHwgJ19ibGFuaycgfCAnX3BhcmVudCcgfCAnX3RvcCc7XG4gIGludGVyZmFjZSBFeHRlcm5hbFNjcmVlbk9wdGlvbnMge1xuICAgIHNjcmVlbiA/OiBTY3JlZW5PcHRpb25zO1xuICAgIG5hbWUgPzogc3RyaW5nO1xuICAgIGxhdW5jaENvbnRhaW5lciA/OiBzdHJpbmc7XG4gICAgY3VzdG9tID86IGFueTtcbiAgICB0YXJnZXQgPzogV2luZG93VGFyZ2V0T3B0aW9ucztcbiAgICB3aW5kb3dGZWF0dXJlcyA/OiBzdHJpbmc7XG4gICAgb25CZWZvcmVTY3JlZW5Mb2FkQ2xvc2VkID86IEZ1bmN0aW9uO1xuICAgIG9uQmVmb3JlU2NyZWVuVW5sb2FkID86IEZ1bmN0aW9uO1xuICAgIHNjcmVlbk5hbWVzcGFjZSA/OiBzdHJpbmc7XG4gICAgYXV0b3N0YXJ0T2JqZWN0cyA6IHN0cmluZztcbiAgICBiYXNlTGF5b3V0T2JqZWN0ID86IHN0cmluZztcbiAgICBzY3JlZW5TZXR0aW5ncyA/OiBhbnk7XG4gIH1cblxuICBpbnRlcmZhY2UgRXh0ZXJuYWxXaW5kb3dQcm94eSBleHRlbmRzIFdpbmRvd1Byb3h5IHtcbiAgICBFeHRlcm5hbFNjcmVlbkxvYWRDbGVhbnVwPzogRnVuY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogRXh0ZXJuYWxTY3JlZW4gT2JqZWN0XG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIEV4dGVybmFsU2NyZWVuXG4gICAqL1xuICBleHBvcnQgY2xhc3MgRXh0ZXJuYWxTY3JlZW4ge1xuXG4gICAgLyoqXG4gICAgICogQHByb3BlcnR5IHthbnl9ICBleHRlcm5hbERhdGEgICBEYXRhIGZyb20gdGhlIGV4dGVybmFsIHNjcmVlbi5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0IGV4dGVybmFsRGF0YSgpOiBhbnkge1xuICAgICAgcmV0dXJuIHdpbmRvdy5ha2lvbWEuRXh0ZXJuYWxTY3JlZW4uZXh0ZXJuYWxEYXRhO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwcm9wZXJ0eSB7YXJyYXl9ICBleHRlcm5hbFNjcmVlbnMgICBMaXN0IG9mIGV4dGVybmFsIHNjcmVlbnMuXG4gICAgICovXG4gICAgc3RhdGljIGdldCBleHRlcm5hbFNjcmVlbnMoKTogQXJyYXk8YW55PiB7XG4gICAgICByZXR1cm4gd2luZG93LmFraW9tYS5FeHRlcm5hbFNjcmVlbi5leHRlcm5hbFNjcmVlbnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHByb3BlcnR5IHthcnJheX0gIGV4dGVybmFsU2NyZWVuc05hbWVzcGFjZXMgICBMaXN0IG9mIGV4dGVybmFsIHNjcmVlbnMgbmFtZXNwYWNlcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0IGV4dGVybmFsU2NyZWVuc05hbWVzcGFjZXMoKTogQXJyYXk8YW55PiB7XG4gICAgICByZXR1cm4gd2luZG93LmFraW9tYS5FeHRlcm5hbFNjcmVlbi5leHRlcm5hbFNjcmVlbnNOYW1lc3BhY2VzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSAgZXh0ZXJuYWxTY3JlZW5Db250YWluZXIgICBUaGUgZXh0ZXJuYWwgc2NyZWVuIGNvbnRhaW5lci5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0IGV4dGVybmFsU2NyZWVuQ29udGFpbmVyKCk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gd2luZG93LmFraW9tYS5FeHRlcm5hbFNjcmVlbi5leHRlcm5hbFNjcmVlbkNvbnRhaW5lcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcHJvcGVydHkge3N0cmluZ30gIFVVSURCcm93c2VyU2Vzc2lvbiAgIEJyb3dzZXIgc2Vzc2lvbiBpZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXQgVVVJREJyb3dzZXJTZXNzaW9uKCk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gd2luZG93LmFraW9tYS5FeHRlcm5hbFNjcmVlbi5VVUlEQnJvd3NlclNlc3Npb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHByb3BlcnR5IHthcnJheX0gIG9uQmVmb3JlU2NyZWVuT25sb2FkICAgQmVmb3JlIHNjcmVlbiB1bmxvYWQgY2FsbGJhY2tzLlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXQgb25CZWZvcmVTY3JlZW5PbmxvYWQoKTogQXJyYXk8YW55PiB7XG4gICAgICByZXR1cm4gd2luZG93LmFraW9tYS5FeHRlcm5hbFNjcmVlbi5vbkJlZm9yZVNjcmVlbk9ubG9hZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcHJvcGVydHkge2FycmF5fSAgcG9wdXBzICAgVGhlIHdpbmRvd3MvcG9wdXBzIG9wZW5lZC5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0IHBvcHVwcygpOiBBcnJheTxhbnk+IHtcbiAgICAgIHJldHVybiB3aW5kb3cuYWtpb21hLkV4dGVybmFsU2NyZWVuLnBvcHVwcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcHJvcGVydHkge0FycmF5PEV4dGVybmFsU2NyZWVuPn0gRXh0ZXJuYWxPYmplY3RzIFRoZSBsaXN0IG9mIGFsbCBFeHRlcm5hbCBTY3JlZW4gT2JqZWN0c1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXQgRXh0ZXJuYWxPYmplY3RzKCk6IEFycmF5PEV4dGVybmFsU2NyZWVuPiB7XG4gICAgICByZXR1cm4gd2luZG93LmFraW9tYS5FeHRlcm5hbFNjcmVlbi5FeHRlcm5hbE9iamVjdHM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBleHRlcm5hbFNjcmVlbjogRXh0ZXJuYWxTY3JlZW47XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RvciBmb3IgY3JlYXRpbmcgYSBuZXcgRXh0ZXJuYWxTY3JlZW4gb2JqZWN0XG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQG1lbWJlcm9mIEV4dGVybmFsU2NyZWVuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihuYW1lOnN0cmluZykge1xuICAgICAgdGhpcy5leHRlcm5hbFNjcmVlbiA9IG5ldyB3aW5kb3cuYWtpb21hLkV4dGVybmFsU2NyZWVuKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHRlciBmb3IgbmFtZXNwYWNlXG4gICAgICogQHJldHVybiB7c3RyaW5nfVxuICAgICAqL1xuICAgIGdldCBuYW1lc3BhY2UoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiB0aGlzLmV4dGVybmFsU2NyZWVuLm5hbWVzcGFjZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdXNlZCBmb3IgaW5pdGlhbGl6aW5nIHRoZSBicm93c2VyIHNlc3Npb24gaWRcbiAgICAgKi9cbiAgICBzdGF0aWMgaW5pdEJyb3dzZXJTZXNzaW9uSWQoKSB7XG4gICAgICB3aW5kb3cuYWtpb21hLkV4dGVybmFsU2NyZWVuLmluaXRCcm93c2VyU2Vzc2lvbklkKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciByZXR1cm5pbmcgdGhlIGV4dGVybmFsIHNjcmVlbiBwb3B1cCBieSBuYW1lc3BhY2VcbiAgICAgKiBAcGFyYW0gc2NyZWVuTmFtZXNwYWNlIFRoZSBFeHRlcm5hbCBTY3JlZW4gbmFtZXNwYWNlIHVzZWQgd2hlbiBsYXVuY2hpbmdcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0RXh0ZXJuYWxQb3B1cChzY3JlZW5OYW1lc3BhY2U6IHN0cmluZykge1xuICAgICAgcmV0dXJuIHdpbmRvdy5ha2lvbWEuRXh0ZXJuYWxTY3JlZW4uZ2V0RXh0ZXJuYWxQb3B1cChzY3JlZW5OYW1lc3BhY2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBsb29wIG92ZXIgZWFjaCBleHRlcm5hbCBzY3JlZW4gcG9wdXBcbiAgICAgKiBAcGFyYW0gZnVuYyBGdW5jdGlvbiB0byBjYWxsIGZvciBlYWNoIHBvcHVwXG4gICAgICovXG4gICAgc3RhdGljIGZvckVhY2hQb3B1cChmdW5jOkZ1bmN0aW9uKSB7XG4gICAgICB3aW5kb3cuYWtpb21hLkV4dGVybmFsU2NyZWVuLmZvckVhY2hQb3B1cChmdW5jKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHNldHRpbmcgc2NyZWVuTmFtZXNwYWNlIGZyb20gcXVlcnkgcGFyYW0gc2NyZWVuTmFtZXNwYWNlXG4gICAgICogQHN0YXRpY1xuICAgICAqL1xuICAgIHN0YXRpYyBsb2FkRXh0ZXJuYWxEZXNpZ25lck5hbWVzcGFjZSgpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuRXh0ZXJuYWxTY3JlZW4ubG9hZEV4dGVybmFsRGVzaWduZXJOYW1lc3BhY2UoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdXNlZCBmb3Igc2V0dGluZyB0aGUgYWN0aXZlIHdpbmRvdyBmb3JlaWduIGtleVxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAbWVtYmVyb2YgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZm9yZWlnbktleVxuICAgICAqL1xuICAgIHNldEFjdGl2ZVdpbmRvd0ZvcmVpZ25LZXkoZm9yZWlnbktleTpzdHJpbmcpIHtcbiAgICAgIHRoaXMuZXh0ZXJuYWxTY3JlZW4uc2V0QWN0aXZlV2luZG93Rm9yZWlnbktleShmb3JlaWduS2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdXNlZCBmb3Igc2V0dGluZyB0aGUgYWN0aXZlIHdpbmRvdyBmb3JlaWduIGtleVxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAbWVtYmVyb2YgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBhY3RpdmVXaW5kb3dGb3JlaWduS2V5XG4gICAgICovXG4gICAgZ2V0QWN0aXZlV2luZG93Rm9yZWlnbktleSgpOnN0cmluZyB7XG4gICAgICByZXR1cm4gdGhpcy5leHRlcm5hbFNjcmVlbi5nZXRBY3RpdmVXaW5kb3dGb3JlaWduS2V5KCk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNsZWFyTG9jYWxPcGVuZWQobmFtZTpzdHJpbmcpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuRXh0ZXJuYWxTY3JlZW4uY2xlYXJMb2NhbE9wZW5lZChuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIGdldHRpbmcgdGhlIEV4dGVybmFsU2NyZWVuIE9wZW5lZCBsb2NhbGx5IGZyb20gbG9jYWxTdG9yYWdlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKiBAcmV0dXJuICB7T2JqZWN0fVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRMb2NhbE9wZW5lZChuYW1lOnN0cmluZykge1xuICAgICAgcmV0dXJuIHdpbmRvdy5ha2lvbWEuRXh0ZXJuYWxTY3JlZW4uZ2V0TG9jYWxPcGVuZWQobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzZXR0aW5nIHVwIGEgcmVmcmVzaCBsaXN0ZW5lciBtZXRob2RcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBsblxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJvZiBFeHRlcm5hbFNjcmVlblxuICAgICAqL1xuICAgIHNldFJlZnJlc2hMaXN0ZW5lcihsbjpGdW5jdGlvbikge1xuICAgICAgdGhpcy5leHRlcm5hbFNjcmVlbi5zZXRSZWZyZXNoTGlzdGVuZXIobG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3Igc2V0dGluZyB1cCBhIHJlZnJlc2hTY2hlbWUgbGlzdGVuZXIgbWV0aG9kIGJlc2lkZXMgdGhlIGRlZmF1bHQgYmVoYXZpb3VyXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gbG5cbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKi9cbiAgICBzZXRSZWZyZXNoU2NoZW1lTGlzdGVuZXIobG46RnVuY3Rpb24pIHtcbiAgICAgIHRoaXMuZXh0ZXJuYWxTY3JlZW4uc2V0UmVmcmVzaFNjaGVtZUxpc3RlbmVyKGxuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHNldHRpbmcgdXAgYSBsYXVuY2hDb250YWluZXIgbGlzdGVuZXIgbWV0aG9kXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gbG4gTGlzdGVuZXIgbWV0aG9kXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlcm9mIEV4dGVybmFsU2NyZWVuXG4gICAgICovXG4gICAgc2V0TGF1bmNoQ29udGFpbmVyTGlzdGVuZXIobG46RnVuY3Rpb24pIHtcbiAgICAgIHRoaXMuZXh0ZXJuYWxTY3JlZW4uc2V0TGF1bmNoQ29udGFpbmVyTGlzdGVuZXIobG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3Igc2V0dGluZyB1cCBhbiBhY3RpdmVXaWRvdyBsaXN0ZW5lciBtZXRob2RcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBsbiBMaXN0ZW5lciBtZXRob2RcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKi9cbiAgICBzZXRBY3RpdmVXaW5kb3dMaXN0ZW5lcihsbjpGdW5jdGlvbikge1xuICAgICAgdGhpcy5leHRlcm5hbFNjcmVlbi5zZXRBY3RpdmVXaW5kb3dMaXN0ZW5lcihsbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzZXR0aW5nIHVwIGFuIGNsb3NlV2luZG93IGxpc3RlbmVyIG1ldGhvZFxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGxuIExpc3RlbmVyIG1ldGhvZFxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJvZiBFeHRlcm5hbFNjcmVlblxuICAgICAqL1xuICAgIHNldENsb3NlV2luZG93TGlzdGVuZXIobG46RnVuY3Rpb24pIHtcbiAgICAgIHRoaXMuZXh0ZXJuYWxTY3JlZW4uc2V0Q2xvc2VXaW5kb3dMaXN0ZW5lcihsbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzZXR0aW5nIHVwIGRhdGEgYXZhaWxhYmxlIGxpc3RlbmVyIG1ldGhvZFxuICAgICAqIEBwYXJhbSBsbiBMaXN0ZW5lciBtZXRob2RcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKi9cbiAgICBzZXREYXRhQXZhaWxMaXN0ZW5lcihsbjpGdW5jdGlvbikge1xuICAgICAgdGhpcy5leHRlcm5hbFNjcmVlbi5zZXREYXRhQXZhaWxMaXN0ZW5lcihsbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBsaXN0ZW5pbmcgZm9yIGV2ZW50c1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGxpc3RlbiBmb3JcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBmbiBUaGUgY2FsbGJhY2sgbWV0aG9kXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlcm9mIEV4dGVybmFsU2NyZWVuXG4gICAgICovXG4gICAgb24oZXZlbnROYW1lOnN0cmluZywgZm46RnVuY3Rpb24pIHtcbiAgICAgIHRoaXMuZXh0ZXJuYWxTY3JlZW4ub24oZXZlbnROYW1lLCBmbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgZXZlbnQgbGlzdGVuZXJzXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnRcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBmbiBUaGUgY2FsbGJhY2sgbWV0aG9kXG4gICAgICogQG1lbWJlck9mIEV4dGVybmFsU2NyZWVuXG4gICAgICovXG4gICAgb2ZmKGV2ZW50TmFtZTpzdHJpbmcsIGZuOkZ1bmN0aW9uKSB7XG4gICAgICB0aGlzLmV4dGVybmFsU2NyZWVuLm9mZihldmVudE5hbWUsIGZuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50XG4gICAgICogQHBhcmFtIHtvYmplY3R9IHBheWxvYWQgVGhlIHBheWxvYWQvZGF0YSB0byBzZW5kXG4gICAgICogQG1lbWJlck9mIEV4dGVybmFsU2NyZWVuXG4gICAgICovXG4gICAgZW1pdChldmVudE5hbWU6c3RyaW5nLCBwYXlsb2FkOm9iamVjdCkge1xuICAgICAgdGhpcy5leHRlcm5hbFNjcmVlbi5lbWl0KGV2ZW50TmFtZSwgcGF5bG9hZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBldmVudCBsaXN0ZW5lclxuICAgICAqIEBtZW1iZXJvZiBFeHRlcm5hbFNjcmVlblxuICAgICAqL1xuICAgIGNyZWF0ZUxpc3RlbmVyKCkge1xuICAgICAgdGhpcy5leHRlcm5hbFNjcmVlbi5jcmVhdGVMaXN0ZW5lcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgZXZlbnQgbGlzdGVuZXJcbiAgICAgKiBAbWVtYmVyb2YgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKi9cbiAgICBjcmVhdGVFbWl0dGVyKCkge1xuICAgICAgdGhpcy5leHRlcm5hbFNjcmVlbi5jcmVhdGVFbWl0dGVyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzZXR0aW5nIHVwIHRoZSBFeHRlcm5hbFNjcmVlbiBuYW1lc3BhY2VcbiAgICAgKiBAbWVtYmVyb2YgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZXNwYWNlXG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgc2V0TmFtZXNwYWNlKG5hbWVzcGFjZTpzdHJpbmcpIHtcbiAgICAgIHRoaXMuZXh0ZXJuYWxTY3JlZW4uc2V0TmFtZXNwYWNlKG5hbWVzcGFjZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBldmVudCBsaXN0ZW5lclxuICAgICAqIEBtZW1iZXJvZiBFeHRlcm5hbFNjcmVlblxuICAgICAqL1xuICAgIGdldEV4dGVybmFsRGF0YShiQ2xlYXIgPSBmYWxzZSk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5leHRlcm5hbFNjcmVlbi5nZXRFeHRlcm5hbERhdGEoYkNsZWFyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IGV2ZW50IGxpc3RlbmVyXG4gICAgICogQG1lbWJlcm9mIEV4dGVybmFsU2NyZWVuXG4gICAgICovXG4gICAgc3RhdGljIHNldEV4dGVybmFsRGF0YShvRXh0ZXJuYWxEYXRhOmFueSkge1xuICAgICAgd2luZG93LmFraW9tYS5FeHRlcm5hbFNjcmVlbi5zZXRFeHRlcm5hbERhdGEob0V4dGVybmFsRGF0YSk7XG4gICAgfVxuXG4gICAgc3RhdGljIHNldExvY2FsT3BlbmVkKG5hbWU6c3RyaW5nLCBlbG06YW55KSB7XG4gICAgICB3aW5kb3cuYWtpb21hLkV4dGVybmFsU2NyZWVuLnNldExvY2FsT3BlbmVkKG5hbWUsIGVsbSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgZXh0ZXJuYWwgc2NyZWVuIGNvbnRhaW5lclxuICAgICAqIEBtZW1iZXJvZiBFeHRlcm5hbFNjcmVlblxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY29udGFpbmVyTmFtZVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRDb250YWluZXIoY29udGFpbmVyTmFtZTpzdHJpbmcpIHtcbiAgICAgIHdpbmRvdy5ha2lvbWEuRXh0ZXJuYWxTY3JlZW4uZXh0ZXJuYWxTY3JlZW5Db250YWluZXIgPSBjb250YWluZXJOYW1lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgZXZlbnQgbGlzdGVuZXJcbiAgICAgKiBAbWVtYmVyb2YgRXh0ZXJuYWxTY3JlZW5cbiAgICAgKi9cbiAgICBkZXN0cm95KCkge1xuICAgICAgZGVsZXRlIHRoaXMuZXh0ZXJuYWxTY3JlZW47XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB1c2VkIGZvciBsYXVuY2hpbmcgYW4gZXh0ZXJuYWwgc2NyZWVuIHdpbmRvdy5cbiAgICogQHBhcmFtIHtvYmplY3R9IG9PcHRpb25zXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvT3B0aW9ucy5zY3JlZW4gU2NyZWVuIHNldHRpbmdzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvT3B0aW9ucy5zY3JlZW4ud2lkdGggRXh0ZXJuYWwgc2NyZWVuIHdpZHRoXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvT3B0aW9ucy5zY3JlZW4uaGVpZ2h0IEV4dGVybmFsIHNjcmVlbiBoZWlnaHRcbiAgICogQHBhcmFtIHtudW1iZXJ9IG9PcHRpb25zLnNjcmVlbi50b3AgRXh0ZXJuYWwgc2NyZWVuIHRvcCBwb3NpdGlvblxuICAgKiBAcGFyYW0ge251bWJlcn0gb09wdGlvbnMuc2NyZWVuLmxlZnQgRXh0ZXJuYWwgc2NyZWVuIGxlZnQgcG9zaXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IG9PcHRpb25zLnNjcmVlbi5ob3N0bmFtZSBUaGUgaG9zdG5hbWUsIGRlZmF1bHQgd2lsbCBiZSB3aW5kb3cubG9jYXRpb24sIHVybFxuICAgKiBAcGFyYW0ge3N0cmluZ30gb09wdGlvbnMuYmFzZUxheW91dE9iamVjdCBUaGUgcmVwb3NpdG9yeSBvYmplY3QgbmFtZSBvZiB0aGUgbWFpbiBsYXlvdXQgY29udGFpbmVyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvT3B0aW9ucy5hdXRvc3RhcnRPYmplY3RzIFRoZSByZXBvc2l0b3J5IG9iamVjdCBuYW1lIHRoYXQgd2lsbCBiZSBsb2FkZWQgaW4gdGhlIGJhc2VMYXlvdXRPYmplY3RcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9PcHRpb25zLmxhdW5jaENvbnRhaW5lciBOYW1lIG9mIHNjcmVlbiB0byBsYXVuY2hcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9PcHRpb25zLm5hbWUgTmFtZSBvZiB0aGUgRXh0ZXJuYWwgU2NyZWVuIHRvIG9wZW5cbiAgICogQHBhcmFtIHtvYmplY3R9IG9PcHRpb25zLmN1c3RvbSBDdXN0b20gZGF0YSBvYmplY3QgcHJvcGVydGllcyB0byBwYXNzIHRvIGV4dGVybmFsIHNjcmVlblxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvT3B0aW9ucy5vbkJlZm9yZVNjcmVlbkxvYWRDbG9zZWQgQ2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIGJlZm9yZSBzY3JlZW4gbG9hZHMgYW5kIGNsb3NlZFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvT3B0aW9ucy5vbkJlZm9yZVNjcmVlblVubG9hZCBDYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgYmVmb3JlIHRoZSBzY3JlZW4gdW5sb2Fkc1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxFeHRlcm5hbFdpbmRvd1Byb3h5Pn1cbiAgICpcbiAgICovXG4gIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBsYXVuY2hFeHRlcm5hbFNjcmVlbihvT3B0aW9uczpFeHRlcm5hbFNjcmVlbk9wdGlvbnMpOiBQcm9taXNlPEV4dGVybmFsV2luZG93UHJveHk+IHtcbiAgICByZXR1cm4gd2luZG93LmFraW9tYS5sYXVuY2hFeHRlcm5hbFNjcmVlbihvT3B0aW9ucyk7XG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi9Td2F0T2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICBkZWNsYXJlIGludGVyZmFjZSBQYW5lbE1lc3NhZ2VzIHtcbiAgICBbeDogc3RyaW5nXTogbnVtYmVyXG4gIH1cblxuICAvKipcbiAgICogVmlzdWFsIE9iamVjdHMgQmFzZSBDbGFzc1xuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBWaXN1YWxPYmplY3RcbiAgICogQGV4dGVuZHMge1N3YXRPYmplY3R9XG4gICAqL1xuICBleHBvcnQgY2xhc3MgVmlzdWFsT2JqZWN0IGV4dGVuZHMgYWtpb21hLnN3YXQuU3dhdE9iamVjdCB7XG5cbiAgICBwYW5lbE1lc3NhZ2VzOiBQYW5lbE1lc3NhZ2VzO1xuXG4gICAgLyoqXG4gICAgICogRm9yY2VzIHRoZSBvYmplY3QgdG8gc2hvdy5cbiAgICAgKiBGb3IgZXhhbXBsZSwgaWYgdGhlIG9iamVjdCBpcyBpbiBhIGNvbGxhcHNlZCBwYW5lbCwgdGhlIHBhbmVsIGlzIGV4cGFuZGVkXG4gICAgICogb3IgaW4gYW4gdW5zZWxlY3RlZCB0YWIsIHNlbGVjdHMgdGhlIG9iamVjdCB0YWIgZXRjLlxuICAgICAqL1xuICAgIGZvcmNlU2hvdygpIHtcbiAgICAgIGxldCBjb250cm9sbGVyID0gdGhpcy5fY29udHJvbGxlcjtcblxuICAgICAgd2hpbGUgKGNvbnRyb2xsZXIgJiYgY29udHJvbGxlci52aWV3ICE9PSAnd2luZG93Jykge1xuXG4gICAgICAgIHN3aXRjaCAoY29udHJvbGxlci52aWV3KSB7XG4gICAgICAgICAgY2FzZSAndGFiJzoge1xuICAgICAgICAgICAgY29uc3QgcGFyZW50ID0gY29udHJvbGxlci5wYXJlbnQ7XG4gICAgICAgICAgICBjb25zdCBrZXkgPSBjb250cm9sbGVyLm9wdC5QYWdlS2V5O1xuXG4gICAgICAgICAgICBpZiAocGFyZW50LmN1cnJlbnRQYWdlS2V5KCkgIT09IGtleSlcbiAgICAgICAgICAgICAgcGFyZW50LnNldEFjdGl2ZVBhZ2Uoa2V5KTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjYXNlICdwYW5lbCc6XG4gICAgICAgICAgICBpZiAoY29udHJvbGxlci5kaHguaXNDb2xsYXBzZWQoKSlcbiAgICAgICAgICAgICAgY29udHJvbGxlci5kaHguZXhwYW5kKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRyb2xsZXIgPSBjb250cm9sbGVyLnBhcmVudDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGlmIHRoZXJlIGFyZSBjaGFuZ2VzIGluIHRoZSBvYmplY3Qgb3IgaXRzIGRlc2NlbmRlbnRzXG4gICAgICogQGV4YW1wbGUgT2JqZWN0Lmhhc0NoYW5nZXMoKVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGhhc0NoYW5nZXMoKTogYm9vbGVhbiB7XG4gICAgICBpZiAodGhpcy5fY29udHJvbGxlci5vVnVleFN0YXRlXG4gICAgICAgICAgICAgJiYgdGhpcy5fY29udHJvbGxlci5vVnVleFN0YXRlLmF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAmJiB0aGlzLl9jb250cm9sbGVyLm9WdWV4U3RhdGUuYXR0cmlidXRlcy5oYXNDaGFuZ2VzKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBjbGVhciB0aGUgaGFzQ2hhbmdlcyBmbGFnIG9uIHRoZSBvYmplY3RcbiAgICAgKiBAZXhhbXBsZSBPYmplY3QuY2xlYXJDaGFuZ2VzKClcbiAgICAgKi9cbiAgICBjbGVhckhhc0NoYW5nZXMoKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmNsZWFySGFzQ2hhbmdlcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBEZWNyZW1lbnQgaGFzIGNoYW5nZXMgb24gYSBmb3JtIHdpdGggMVxuICAgICAgICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgICAgICogQG1lbWJlcm9mIFZpc3VhbE9iamVjdFxuICAgICAgICAgKi9cbiAgICBkZWNyZW1lbnRDaGFuZ2VzKCk6IHZvaWQge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5fZGlzcGF0Y2goJ2RlY3JlbWVudEhhc0NoYW5nZXMnLCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgYSBjdXN0b20gc3RhdGUgb24gYSBjb250cm9sbGVyXG4gICAgICogQHBhcmFtICB7c3RyaW5nfSBuYW1lXG4gICAgICogQHBhcmFtICB7b2JqZWN0fSBbb3B0aW9uc11cbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyT2YgVmlzdWFsT2JqZWN0XG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgc2V0Q3VzdG9tU3RhdGUobmFtZTogc3RyaW5nLCBvcHRpb25zPzogb2JqZWN0KSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEN1c3RvbVN0YXRlKG5hbWUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBhIGN1c3RvbSBzdGF0ZSBmcm9tIGEgY29udHJvbGxlclxuICAgICAqIEBwYXJhbSAge3N0cmluZ30gbmFtZVxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJPZiBWaXN1YWxPYmplY3RcbiAgICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKi9cbiAgICBjbGVhckN1c3RvbVN0YXRlKG5hbWU6IHN0cmluZykge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5jbGVhckN1c3RvbVN0YXRlKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgaWYgdGhlcmUgYXJlIGNoYW5nZXMgaW4gdGhlIG9iamVjdCBvciBpdHMgZGVzY2VuZGVudHNcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBoYXNFcnJvcnMoKTogYm9vbGVhbiB7XG4gICAgICBpZiAodGhpcy5fY29udHJvbGxlci5vVnVleFN0YXRlXG4gICAgICAgICAgICAgJiYgdGhpcy5fY29udHJvbGxlci5vVnVleFN0YXRlLmF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAmJiB0aGlzLl9jb250cm9sbGVyLm9WdWV4U3RhdGUuYXR0cmlidXRlcy5oYXNFcnJvcnMpXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgZWxzZVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIGFuIHBhbmVsIG1lc3NhZ2UgYW5kIHJldHVybiB0aGUgaW5kZXggb2YgdGhlIG1lc3NhZ2VcbiAgICAgKiBAcGFyYW0gIHtQYW5lbE1lc3NhZ2V9IG1zZyBUaGUgcGFuZWwgbWVzc2FnZVxuICAgICAqIEBwYXJhbSAge3N0cmluZ30gbXNnLnRleHQgVGhlIHBhbmVsIG1lc3NhZ2UgdGV4dFxuICAgICAqIEBwYXJhbSAge3N0cmluZ30gbXNnLnR5cGUgVGhlIHBhbmVsIG1lc3NhZ2UgdHlwZSBpLmUuXG4gICAgICogaW5mbywgd2FybmluZywgZXJyb3IsIHN1Y2Nlc3NcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyT2YgVmlzdWFsT2JqZWN0XG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBhZGRQYW5lbE1lc3NhZ2UobXNnOiBQYW5lbE1lc3NhZ2UpOiBudW1iZXIge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuYWRkUGFuZWxNZXNzYWdlKG1zZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgcGFuZWwgbWVzc2FnZSBmcm9tIGEgY29udHJvbGxlciBieSB0aGUgZ2l2ZW4gaWRcbiAgICAgKiBAcGFyYW0gIHtudW1iZXJ9IGlkXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlck9mIFZpc3VhbE9iamVjdFxuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqL1xuICAgIHJlbW92ZVBhbmVsTWVzc2FnZShpZDogbnVtYmVyKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnJlbW92ZVBhbmVsTWVzc2FnZShpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFsbCBwYW5lbCBtZXNzYWdlcyBmcm9tIGEgY29udHJvbGxlclxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJPZiBWaXN1YWxPYmplY3RcbiAgICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKi9cbiAgICBjbGVhclBhbmVsTWVzc2FnZXMoKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmNsZWFyUGFuZWxNZXNzYWdlcygpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vVmlzdWFsT2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBBY2NvcmRpb24gT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBBY2NvcmRpb25cbiAgICAgKiBAZXh0ZW5kcyB7VmlzdWFsT2JqZWN0fVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgQWNjb3JkaW9uIGV4dGVuZHMgYWtpb21hLnN3YXQuVmlzdWFsT2JqZWN0IHtcblxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vVmlzdWFsT2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBCdXR0b24gT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBCdXR0b25cbiAgICAgKiBAZXh0ZW5kcyB7VmlzdWFsT2JqZWN0fVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgRm9ybUZpZWxkT2JqZWN0IGV4dGVuZHMgYWtpb21hLnN3YXQuVmlzdWFsT2JqZWN0IHtcbiAgICBwcm90ZWN0ZWQgX2Zvcm06IGFraW9tYS5zd2F0LkZvcm07XG4gICAgcHJvdGVjdGVkIF9mb3JtQ29udHJvbGxlcjogYW55O1xuICAgIHByb3RlY3RlZCBfZm9ybURoeDogYW55O1xuXG4gICAgcHJvdGVjdGVkIGdldCBmb3JtQ29udHJvbGxlcigpOiBhbnkge1xuICAgICAgaWYgKCF0aGlzLl9mb3JtQ29udHJvbGxlcilcbiAgICAgICAgdGhpcy5fZm9ybUNvbnRyb2xsZXIgPSB0aGlzLl9jb250cm9sbGVyLmdldEFuY2VzdG9yKCdmb3JtJyk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9mb3JtQ29udHJvbGxlcjtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGZvcm1EaHgoKTogYW55IHtcbiAgICAgIGlmICghdGhpcy5fZm9ybURoeClcbiAgICAgICAgdGhpcy5fZm9ybURoeCA9IHRoaXMuZm9ybUNvbnRyb2xsZXIuZGh4O1xuXG4gICAgICByZXR1cm4gdGhpcy5fZm9ybURoeDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZm9ybSBmaWVsZCBmb3JtIG9iamVjdFxuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHtGb3JtfVxuICAgICAqL1xuICAgIGdldCBmb3JtKCk6IGFraW9tYS5zd2F0LkZvcm0ge1xuICAgICAgaWYgKCF0aGlzLl9mb3JtKVxuICAgICAgICB0aGlzLl9mb3JtID0gPGFraW9tYS5zd2F0LkZvcm0+KGFraW9tYS5zd2F0LlN3YXRGYWN0b3J5LmNyZWF0ZVN3YXRPYmplY3QodGhpcy5mb3JtQ29udHJvbGxlcikpO1xuXG4gICAgICByZXR1cm4gdGhpcy5fZm9ybTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZm9ybSBmaWVsZCBlbmFibGVkIG1vZGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQgZW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLmZvcm1Db250cm9sbGVyLmdldEZvcm1GaWVsZEVuYWJsZWQodGhpcy5uYW1lKTtcbiAgICB9XG5cbiAgICBzZXQgZW5hYmxlZCh2YWx1ZTogYm9vbGVhbikge1xuICAgICAgaWYgKHZhbHVlKVxuICAgICAgICB0aGlzLmZvcm1Db250cm9sbGVyLmVuYWJsZUZvcm1GaWVsZCh0aGlzLm5hbWUpO1xuICAgICAgZWxzZVxuICAgICAgICB0aGlzLmZvcm1Db250cm9sbGVyLmRpc2FibGVGb3JtRmllbGQodGhpcy5uYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZm9ybSBmaWVsZCByZWFkb25seSBtb2RlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgZ2V0IHJlYWRvbmx5KCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuICF0aGlzLmZvcm1Db250cm9sbGVyLmdldEZvcm1GaWVsZEVuYWJsZWQodGhpcy5uYW1lKTtcbiAgICB9XG5cbiAgICBzZXQgcmVhZG9ubHkodmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgIGlmICh2YWx1ZSlcbiAgICAgICAgdGhpcy5mb3JtQ29udHJvbGxlci5kaXNhYmxlRm9ybUZpZWxkKHRoaXMubmFtZSk7XG4gICAgICBlbHNlXG4gICAgICAgIHRoaXMuZm9ybUNvbnRyb2xsZXIuZW5hYmxlRm9ybUZpZWxkKHRoaXMubmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGZvcm0gZmllbGQgaGlkZGVuIG1vZGUgKG9wcG9zaXRlIG9mIHZpc2libGUpXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgZ2V0IGhpZGRlbigpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmlzRmllbGRIaWRkZW4oKTtcbiAgICB9XG5cbiAgICBzZXQgaGlkZGVuKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICBjb25zdCBmb3JtQ29udHJvbGxlciA9IHRoaXMuZm9ybUNvbnRyb2xsZXI7XG4gICAgICBpZiAodmFsdWUpXG4gICAgICAgIGZvcm1Db250cm9sbGVyLmhpZGVGb3JtRmllbGQodGhpcy5uYW1lKTtcbiAgICAgIGVsc2VcbiAgICAgICAgZm9ybUNvbnRyb2xsZXIuc2hvd0Zvcm1GaWVsZCh0aGlzLm5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBmb3JtIGZpZWxkIHZpc2libGUgbW9kZSAob3Bwb3NpdGUgb2YgaGlkZGVuKVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldCB2aXNpYmxlKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuICF0aGlzLmhpZGRlbjtcbiAgICB9XG5cbiAgICBzZXQgdmlzaWJsZSh2YWx1ZTogYm9vbGVhbikge1xuICAgICAgdGhpcy5oaWRkZW4gPSAhdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGZvcm0gZmllbGQgbGFiZWxcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuICAgIGdldCBsYWJlbCgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIHRoaXMuZm9ybURoeC5nZXRJdGVtTGFiZWwodGhpcy5uYW1lKTtcbiAgICB9XG5cbiAgICBzZXQgbGFiZWwodmFsdWU6IHN0cmluZykge1xuICAgICAgdGhpcy5mb3JtRGh4LnNldEl0ZW1MYWJlbCh0aGlzLm5hbWUsIHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIGNoZWNraW5nIGlmIGZvcm0gZmllbGQgaGFzIGNoYW5nZXNcbiAgICAgKi9cbiAgICBoYXNDaGFuZ2VzKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuZm9ybUNvbnRyb2xsZXIuZ2V0RmllbGRIYXNDaGFuZ2VzKHRoaXMubmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzZXR0aW5nIHRoZSBoYXMgY2hhbmdlcyBmbGFnIG9uIGEgZm9ybSBmaWVsZFxuICAgICAqIEBwYXJhbSBzdGF0ZSBUaGUgaGFzQ2hhbmdlcyBzdGF0ZVxuICAgICAqL1xuICAgIHNldEhhc0NoYW5nZXMoc3RhdGU6IGJvb2xlYW4pIHtcbiAgICAgIHRoaXMuZm9ybUNvbnRyb2xsZXIuc2V0RmllbGRIYXNDaGFuZ2VzKHRoaXMubmFtZSwgc3RhdGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3Igc2hvd2luZyB0aGUgaW5mbyBidXR0b24gb2YgYSBmb3JtIGZpZWxkXG4gICAgICovXG4gICAgc2hvd0luZm9CdXR0b24oKTogdm9pZCB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNob3dJbmZvQnV0dG9uKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBoaWRpbmcgdGhlIGluZm8gYnV0dG9uIG9mIGEgZm9ybSBmaWVsZFxuICAgICAqL1xuICAgIGhpZGVJbmZvQnV0dG9uKCk6IHZvaWQge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5oaWRlSW5mb0J1dHRvbigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHJvdyBvZiB0aGUgY29udHJvbC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcm93IFRoZSByb3cgbnVtYmVyLlxuICAgICAqIEBtZW1iZXJvZiBGb3JtRmllbGRPYmplY3RcbiAgICAgKi9cbiAgICBzZXRSb3dTdGFydChyb3c6IG51bWJlcik6IHZvaWQge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRSb3dTdGFydChyb3cpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGNvbHVtbiBzdGFydCBmb3IgYSBmb3JtIGNvbnRyb2wuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGNvbHVtblN0YXJ0IFRoZSBjb2x1bW4gc3RhcnQuXG4gICAgICogQG1lbWJlcm9mIEZvcm1GaWVsZE9iamVjdFxuICAgICAqL1xuICAgIHNldENvbHVtblN0YXJ0KGNvbHVtblN0YXJ0OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0Q29sdW1uU3RhcnQoY29sdW1uU3RhcnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHdpZHRoIGVuZCBmb3IgYSBmb3JtIGNvbnRyb2wuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIFRoZSBuZXcgY29udHJvbCB3aWR0aC5cbiAgICAgKiBAbWVtYmVyb2YgRm9ybUZpZWxkT2JqZWN0XG4gICAgICovXG4gICAgc2V0Q29sdW1uRW5kKHdpZHRoOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0Q29sdW1uRW5kKHdpZHRoKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL2RhdGFmaWVsZC9Gb3JtRmllbGRPYmplY3QudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBGb3JtRmllbGRDb250cmFuaWVyT2JqZWN0IE9iamVjdFxuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBGaWVsZFNldFxuICAgKiBAZXh0ZW5kcyB7VmlzdWFsT2JqZWN0fVxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIEZvcm1GaWVsZENvbnRhaW5lck9iamVjdCBleHRlbmRzIGFraW9tYS5zd2F0LkZvcm1GaWVsZE9iamVjdCB7XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSByb3cgb2YgYSBmb3JtIGNvbnRyb2wuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZpZWxkTmFtZSBUaGUgZm9ybSBjb250cm9sIGZpZWxkIG5hbWUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHJvdyBUaGUgcm93IG51bWJlci5cbiAgICAgKiBAbWVtYmVyb2YgQmFzZUZvcm1EYXRhRmllbGRcbiAgICAgKi9cbiAgICBzZXRGb3JtRmllbGRSb3dTdGFydChmaWVsZE5hbWU6IHN0cmluZywgcm93OiBudW1iZXIpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0Rm9ybUZpZWxkUm93U3RhcnQoZmllbGROYW1lLCByb3cpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGNvbHVtbiBzdGFydCBvZiBhIGZvcm0gY29udHJvbC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZmllbGROYW1lIFRoZSBmb3JtIGNvbnRyb2wgZmllbGQgbmFtZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gY29sdW1uU3RhcnQgVGhlIGNvbHVtbiBzdGFydC5cbiAgICAgKiBAbWVtYmVyb2YgQmFzZUZvcm1EYXRhRmllbGRcbiAgICAgKi9cbiAgICBzZXRGb3JtRmllbGRDb2x1bW5TdGFydChmaWVsZE5hbWU6IHN0cmluZywgY29sdW1uU3RhcnQ6IG51bWJlcikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRGb3JtRmllbGRDb2x1bW5TdGFydChmaWVsZE5hbWUsIGNvbHVtblN0YXJ0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB3aWR0aCBlbmQgb2YgYSBmb3JtIGNvbnRyb2wuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZpZWxkTmFtZSBUaGUgZm9ybSBjb250cm9sIGZpZWxkIG5hbWUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIFRoZSBuZXcgY29udHJvbCB3aWR0aC5cbiAgICAgKiBAbWVtYmVyb2YgQmFzZUZvcm1EYXRhRmllbGRcbiAgICAgKi9cbiAgICBzZXRGb3JtRmllbGRDb2x1bW5FbmQoZmllbGROYW1lOiBzdHJpbmcsIHdpZHRoOiBudW1iZXIpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0Rm9ybUZpZWxkQ29sdW1uRW5kKGZpZWxkTmFtZSwgd2lkdGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNoaWZ0cyBjb2x1bW5zIGluIGFuIGFjdGl2ZSBjb250cm9sIHN0YXJ0aW5nIGZyb20gYSBnaXZlbiBjb2x1bW4gYnkgYSBnaXZlbiBvZmZzZXQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGNvbHVtblN0YXJ0IFRoZSBjb2x1bW4gbnVtYmVyIHRvIHN0YXJ0IGZyb20uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGNvbHVtbk9mZnNldCBUaGUgb2Zmc2V0IGJ5IHdoaWNoIHRvIHNoaWZ0LlxuICAgICAqIEBtZW1iZXJvZiBCYXNlRm9ybURhdGFGaWVsZFxuICAgICAqL1xuICAgIHNoaWZ0Q29sdW1uc0J5T2Zmc2V0KGNvbHVtblN0YXJ0OiBudW1iZXIsIGNvbHVtbk9mZnNldDogbnVtYmVyKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNoaWZ0Q29sdW1uc0J5T2Zmc2V0KGNvbHVtblN0YXJ0LCBjb2x1bW5PZmZzZXQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG51bWJlciBvZiBjb2x1bW5zIGluIGEgZm9ybSBmaWVsZCBjb250YWluZXJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gY29sdW1uTnVtYmVyIFRoZSBjb2x1bW4gbnVtYmVyLlxuICAgICAqIEBtZW1iZXJvZiBCYXNlRm9ybURhdGFGaWVsZFxuICAgICAqL1xuICAgIHNldENvbHVtbnMoY29sdW1uTnVtYmVyOiBudW1iZXIpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0Q29sdW1ucyhjb2x1bW5OdW1iZXIpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vRm9ybUZpZWxkQ29udGFpbmVyT2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICogQmxvY2sgT2JqZWN0XG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIEZpZWxkU2V0XG4gICAqIEBleHRlbmRzIHtGb3JtRmllbGRDb250YWluZXJPYmplY3R9XG4gICAqL1xuICAvL2V4dGVuZGVkIGJ5IGZpZWxkc2V0LCBibG9ja1xuICBleHBvcnQgY2xhc3MgQmxvY2sgZXh0ZW5kcyBha2lvbWEuc3dhdC5Gb3JtRmllbGRDb250YWluZXJPYmplY3Qge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL0Zvcm1GaWVsZENvbnRhaW5lck9iamVjdC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAqIEZpZWxkU2V0IE9iamVjdFxuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBGaWVsZFNldFxuICAgKiBAZXh0ZW5kcyB7Rm9ybUZpZWxkQ29udGFpbmVyT2JqZWN0fVxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIEZpZWxkU2V0IGV4dGVuZHMgYWtpb21hLnN3YXQuRm9ybUZpZWxkQ29udGFpbmVyT2JqZWN0IHtcbiAgICBwcml2YXRlIF9mb3JtRHluT2JqZWN0OiBhbnk7XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGZvcm1EeW5PYmplY3QoKTogYW55IHtcbiAgICAgIGlmICghdGhpcy5fZm9ybUR5bk9iamVjdClcbiAgICAgICAgdGhpcy5fc2V0Rm9ybU9iamVjdCgpO1xuXG4gICAgICByZXR1cm4gdGhpcy5fZm9ybUR5bk9iamVjdDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGZvcm1Db250cm9sbGVyKCk6IGFueSB7XG4gICAgICBpZiAoIXRoaXMuX2Zvcm1Db250cm9sbGVyKVxuICAgICAgICB0aGlzLl9zZXRGb3JtT2JqZWN0KCk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9mb3JtQ29udHJvbGxlcjtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGZvcm1EaHgoKTogYW55IHtcbiAgICAgIGlmICghdGhpcy5fZm9ybURoeClcbiAgICAgICAgdGhpcy5fc2V0Rm9ybU9iamVjdCgpO1xuXG4gICAgICByZXR1cm4gdGhpcy5fZm9ybURoeDtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9zZXRGb3JtT2JqZWN0KCkge1xuICAgICAgdGhpcy5fZm9ybUR5bk9iamVjdCA9IHRoaXMuX2R5bk9iamVjdC5nZXRQYXJlbnRPZlR5cGUoJ2Zvcm0nKTtcbiAgICAgIHRoaXMuX2Zvcm1Db250cm9sbGVyID0gdGhpcy5fZm9ybUR5bk9iamVjdC5jb250cm9sbGVyO1xuICAgICAgdGhpcy5fZm9ybURoeCA9IHRoaXMuX2Zvcm1Db250cm9sbGVyLmRoeDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZmllbGRzZXQgY29sbGFwc2VkIG1vZGUgaWYgaXQgaXMgY29sbGFwc2VkIG9yIGV4cGFuZGVkXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgZ2V0IGNvbGxhcHNlZCgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmlzQ29sbGFwc2VkKCk7XG4gICAgfVxuXG4gICAgc2V0IGNvbGxhcHNlZCh2YWx1ZTogYm9vbGVhbikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRDb2xsYXBzZWQodmFsdWUsIHRydWUpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vRm9ybUZpZWxkT2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBCdXR0b24gT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBCdXR0b25cbiAgICAgKiBAZXh0ZW5kcyB7Rm9ybUZpZWxkT2JqZWN0fVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgQnV0dG9uIGV4dGVuZHMgYWtpb21hLnN3YXQuRm9ybUZpZWxkT2JqZWN0IHtcblxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9Gb3JtRmllbGRPYmplY3QudHNcIiAvPlxuXG4vLyB0b2RvOiBjaGVjayBpZiBtb3N0IG9mIHRoZSBmdW5jdGlvbmFsaXR5IGluIGRhdGFmaWVsZCBzaG91bGQgYmUgbW92ZWQgdG8gaW5wdXQuXG4vLyB0b2dnbGUgbWlnaHQgbmVlZCB0byBpbmhlcml0IGlucHV0IGluIHRoaXMgY2FzZS5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICBleHBvcnQgdHlwZSB2YWxpZGF0aW9uUnVsZVR5cGUgPSAncmVxdWlyZWQnIHwgJ21pbmxlbmd0aCcgfCAnbWF4bGVuZ3RoJyB8ICdub3RlcXVhbCc7XG5cbiAgZXhwb3J0IGludGVyZmFjZSB2YWxpZGF0aW9uUnVsZSB7XG4gICAgc21hcnRtZXNzYWdlOiBzdHJpbmc7XG4gICAgdmFsdWU6IGFueTtcbiAgICB0cmlnZ2VyVmFsaWRhdGlvbj86IGJvb2xlYW47XG4gIH1cblxuICAvKipcbiAgICogSW5wdXQgRGF0YSBGaWVsZHMgQmFzZSBDbGFzc1xuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBEYXRhRmllbGRcbiAgICogQGV4dGVuZHMge1Zpc3VhbE9iamVjdH1cbiAgICovXG4gIGV4cG9ydCBjbGFzcyBEYXRhRmllbGQgZXh0ZW5kcyBha2lvbWEuc3dhdC5Gb3JtRmllbGRPYmplY3Qge1xuXG4gICAgcHJpdmF0ZSBfZGF0YVNvdXJjZTogYWtpb21hLnN3YXQuRGF0YVNvdXJjZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHZhbGlkYXRpb24gc2hvdWxkIGJlIGNhbGxlZCBvbiB2YWx1ZSBzZXQsIHNjcmVlblZhbHVlXG4gICAgICovXG4gICAgZW5hYmxlTGl2ZVZhbGlkYXRpb24gPSB0cnVlO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB3aGV0aGVyIHNob3VsZCBpZ25vcmUgdmFsaWRhdGlvbiBldmVudCBvciBub3QuXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgZ2V0IGlnbm9yZVZhbGlkYXRlRXZlbnQoKTogYm9vbGVhbiB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5pZ25vcmVWYWxpZGF0ZUV2ZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgd2hldGhlciBzaG91bGQgaWdub3JlIHZhbGlkYXRpb24gZXZlbnQgb3Igbm90LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gdmFsdWUgTmV3IHZhbHVlXG4gICAgICovXG4gICAgc2V0IGlnbm9yZVZhbGlkYXRlRXZlbnQodmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuaWdub3JlVmFsaWRhdGVFdmVudCA9IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBmb3JtIGZpZWxkIGxpbmtlZCBkYXRhc291cmNlXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQHR5cGUge0RhdGFTb3VyY2V9XG4gICAgICovXG4gICAgZ2V0IGRhdGFTb3VyY2UoKTogYWtpb21hLnN3YXQuRGF0YVNvdXJjZSB7XG4gICAgICBpZiAoIXRoaXMuX2RhdGFTb3VyY2UpXG4gICAgICAgIHRoaXMuX2RhdGFTb3VyY2UgPSB0aGlzLmZvcm0uZGF0YVNvdXJjZTtcblxuICAgICAgcmV0dXJuIHRoaXMuX2RhdGFTb3VyY2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGZvcm0gZmllbGQgc2NyZWVuIHZhbHVlXG4gICAgICogQHR5cGUgeyp9XG4gICAgICovXG4gICAgZ2V0IHNjcmVlblZhbHVlKCk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRWYWx1ZSgpO1xuICAgIH1cblxuICAgIHNldCBzY3JlZW5WYWx1ZSh2YWx1ZTogYW55KSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldFZhbHVlKHZhbHVlKTtcblxuICAgICAgaWYgKHRoaXMuZW5hYmxlTGl2ZVZhbGlkYXRpb24pXG4gICAgICAgIHRoaXMuZm9ybUNvbnRyb2xsZXIudmFsaWRhdGVGaWVsZCh0aGlzLm5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvciB1c2UgaW4gdGhlIHZhbHVlY2hhbmdlZCBldmVudC4gVGhlIGN1cnJlbnQgdmFsdWUuXG4gICAgICogdHlwZSB7Kn1cbiAgICAgKi9cbiAgICBnZXQgY3VycmVudFZhbHVlKCk6IGFueSB7XG4gICAgICBpZiAoIXRoaXMuX2R5bk9iamVjdC5ha0V2ZW50KVxuICAgICAgICByZXR1cm47IC8vIHVuZGVmaW5lZFxuXG4gICAgICByZXR1cm4gdGhpcy5fZHluT2JqZWN0LmFrRXZlbnQuY3VycmVudFZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvciB1c2UgaW4gdGhlIHZhbHVlY2hhbmdlZCBldmVudC4gVGhlIGN1cnJlbnQgdmFsdWUgbmF0aXZlLlxuICAgICAqIHR5cGUgeyp9XG4gICAgICovXG4gICAgZ2V0IGN1cnJlbnRWYWx1ZU5hdGl2ZSgpOiBhbnkge1xuICAgICAgaWYgKCF0aGlzLl9keW5PYmplY3QuYWtFdmVudClcbiAgICAgICAgcmV0dXJuOyAvLyB1bmRlZmluZWRcblxuICAgICAgcmV0dXJuIHRoaXMuX2R5bk9iamVjdC5ha0V2ZW50LmN1cnJlbnRWYWx1ZU5hdGl2ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3IgdXNlIGluIHRoZSB2YWx1ZWNoYW5nZWQgZXZlbnQuIFRoZSBsYXN0IHZhbHVlLlxuICAgICAqIHR5cGUgeyp9XG4gICAgICovXG4gICAgZ2V0IGxhc3RWYWx1ZSgpOiBhbnkge1xuICAgICAgaWYgKCF0aGlzLl9keW5PYmplY3QuYWtFdmVudClcbiAgICAgICAgcmV0dXJuOyAvLyB1bmRlZmluZWRcblxuICAgICAgcmV0dXJuIHRoaXMuX2R5bk9iamVjdC5ha0V2ZW50Lmxhc3RWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbGlua2VkIGRhdGFzb3VyY2UgZmllbGQgdmFsdWVcbiAgICAgKiBAdHlwZSB7Kn1cbiAgICAgKi9cbiAgICBnZXQgZGF0YVZhbHVlKCk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5kYXRhU291cmNlLmdldFZhbHVlKHRoaXMubmFtZSk7XG4gICAgfVxuXG4gICAgc2V0IGRhdGFWYWx1ZSh2YWx1ZTogYW55KSB7XG4gICAgICB0aGlzLmRhdGFTb3VyY2Uuc2V0VmFsdWUodGhpcy5uYW1lLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSBmaWVsZCB2YWx1ZSBoYXMgYmVlbiBjaGFuZ2VkXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQGV4YW1wbGUgRmllbGQuY2hhbmdlZFxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldCBjaGFuZ2VkKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuZm9ybUNvbnRyb2xsZXIuZ2V0RmllbGRIYXNDaGFuZ2VzKHRoaXMubmFtZSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBUaGUgZm9ybSBmaWVsZCByZXF1aXJlZCBtb2RlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgZ2V0IHJlcXVpcmVkKCk6IGJvb2xlYW4ge1xuICAgICAgLy8gdGhlcmUgaXMgbm8gKnB1YmxpYyogZGh4IGZ1bmN0aW9uIG9yIHByb3BlcnR5IGZvciBnZXR0aW5nIHRoZSByZXF1aXJlZCBtb2RlXG4gICAgICByZXR1cm4gdGhpcy5mb3JtRGh4Ll9nZXRJdGVtTm9kZSh0aGlzLm5hbWUpLl9yZXF1aXJlZDtcbiAgICB9XG5cbiAgICBzZXQgcmVxdWlyZWQodmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgIHRoaXMuZm9ybUNvbnRyb2xsZXIuc2V0UmVxdWlyZWQodGhpcy5uYW1lLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZm9ybSBmaWVsZCB2YWxpZGF0aW9uIHR5cGUgcnVsZVxuICAgICAqIEByZXR1cm5zIHsqfSBUaGUgdmFsaWRhdGlvbiBydWxlXG4gICAgICovXG4gICAgZ2V0VmFsaWRhdGlvblJ1bGUocnVsZTogdmFsaWRhdGlvblJ1bGVUeXBlKTogdmFsaWRhdGlvblJ1bGUge1xuICAgICAgcmV0dXJuIHRoaXMuZm9ybUNvbnRyb2xsZXIuZ2V0VmFsaWRhdGlvblJ1bGUodGhpcy5uYW1lLCBydWxlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFsbCB0aGUgZm9ybSBmaWVsZCB2YWxpZGF0aW9uIHJ1bGVzXG4gICAgICogQHJldHVybnMgeyp9IFRoZSB2YWxpZGF0aW9uIHJ1bGVzXG4gICAgICovXG4gICAgZ2V0VmFsaWRhdGlvblJ1bGVzKCk6IHtcbiAgICAgIFtrZXkgaW4gdmFsaWRhdGlvblJ1bGVUeXBlXTogdmFsaWRhdGlvblJ1bGVcbiAgICB9IHtcbiAgICAgIHJldHVybiB0aGlzLmZvcm1Db250cm9sbGVyLmdldFZhbGlkYXRpb25SdWxlcyh0aGlzLm5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCBmb3JtIGZpZWxkIHZhbGlkYXRpb24gcnVsZSAobmV3IG9yIGV4aXN0aW5nKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnJ1bGUgVGhlIHJ1bGUgdHlwZSBpLmUuICdyZXF1aXJlZCcsICdtaW5sZW5ndGgnLCAnbWF4bGVuZ3RoJyBvciAnbm90ZXF1YWwnXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMuc21hcnRtZXNzYWdlIFRoZSBzbWFydG1lc3NhZ2UgPGdyb3VwPi08bnVtPiBlLmcuICd2YWxtc2ctMTIxJ1xuICAgICAqIEBwYXJhbSB7Kn0gb3B0cy52YWx1ZSBUaGUgdmFsaWRhdGlvbiB2YWx1ZVxuICAgICAqL1xuICAgIHNldFZhbGlkYXRpb25SdWxlKG9wdHM6IHtcbiAgICAgIHR5cGU6IHZhbGlkYXRpb25SdWxlVHlwZVxuICAgIH0gJiB2YWxpZGF0aW9uUnVsZSkge1xuICAgICAgdGhpcy5mb3JtQ29udHJvbGxlci5zZXRWYWxpZGF0aW9uUnVsZSh0aGlzLm5hbWUsIHtcbiAgICAgICAgdHlwZTogb3B0cy50eXBlLFxuICAgICAgICBtc2c6IG9wdHMuc21hcnRtZXNzYWdlLFxuICAgICAgICB2YWw6IG9wdHMudmFsdWUsXG4gICAgICAgIHRyaWdnZXJWYWxpZGF0aW9uOiBvcHRzLnRyaWdnZXJWYWxpZGF0aW9uXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWxldGUgZm9ybSBmaWVsZCB2YWxpZGF0aW9uIHJ1bGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcnVsZSBUaGUgcnVsZSB0eXBlIGkuZS4gJ3JlcXVpcmVkJywgJ21pbmxlbmd0aCcsICdtYXhsZW5ndGgnIG9yICdub3RlcXVhbCdcbiAgICAgKi9cbiAgICBkZWxldGVWYWxpZGF0aW9uUnVsZShydWxlOiB2YWxpZGF0aW9uUnVsZVR5cGUpIHtcbiAgICAgIHRoaXMuZm9ybUNvbnRyb2xsZXIuZGVsZXRlVmFsaWRhdGlvblJ1bGUodGhpcy5uYW1lLCBydWxlKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL0RhdGFGaWVsZC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogQ2FsZW5kYXIgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBDYWxlbmRhclxuICAgICAqIEBleHRlbmRzIHtEYXRhRmllbGR9XG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBDYWxlbmRhciBleHRlbmRzIGFraW9tYS5zd2F0LkRhdGFGaWVsZCB7XG5cbiAgICAvKipcbiAgICAgICAgICogRm9ybWF0dGVkIHZhbHVlIG9mIGEgZGF0ZSBvYmplY3RcbiAgICAgICAgICogdHlwZSB7Kn1cbiAgICAgICAgICovXG4gICAgZm9ybWF0dGVkRGF0ZVZhbHVlKHZhbHVlOiBhbnkpOiBhbnkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0Rm9ybWF0dGVkRGF0ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIFVuZm9ybWF0dGVkIHZhbHVlIChkYXRlIG9iamVjdCkgb2YgYSBmb3JtYXR0ZWQgZGF0ZSBzdHJpbmdcbiAgICAgICAgICogdHlwZSB7Kn1cbiAgICAgICAgICovXG4gICAgdW5mb3JtYXR0ZWREYXRlVmFsdWUodmFsdWU6IGFueSk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRVbmZvcm1hdHRlZERhdGUodmFsdWUpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vRGF0YUZpZWxkLnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBDb21ib0JveCBPYmplY3RcbiAgICAgKiBAZXhwb3J0XG4gICAgICogQGNsYXNzIENvbWJvQm94XG4gICAgICogQGV4dGVuZHMge0RhdGFGaWVsZH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIENvbWJvQm94IGV4dGVuZHMgYWtpb21hLnN3YXQuRGF0YUZpZWxkIHtcblxuICAgIC8qKlxuICAgICAgICAgKiBUaGUgY29tYm9ib3ggZmllbGQgc2NyZWVuIHZhbHVlXG4gICAgICAgICAqIEB0eXBlIHsqfVxuICAgICAgICAgKi9cbiAgICBnZXQgc2NyZWVuVmFsdWUoKTogYW55IHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldFZhbHVlKCdkZXNjJyk7XG4gICAgfVxuXG4gICAgc2V0IHNjcmVlblZhbHVlKHZhbHVlOiBhbnkpIHtcbiAgICAgIHJldHVybjsgLy8gZG8gbm90aGluZ1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBUaGUgY29tYm9ib3ggZmllbGQga2V5IHZhbHVlXG4gICAgICAgICAqIEB0eXBlIHsqfVxuICAgICAgICAgKi9cbiAgICBnZXQga2V5VmFsdWUoKTogYW55IHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldFZhbHVlKCdpZCcpO1xuICAgIH1cblxuICAgIHNldCBrZXlWYWx1ZSh2YWx1ZTogYW55KSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldFZhbHVlKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogVGhlIGNvbWJvYm94IGZpZWxkIHJlYWRvbmx5IG1vZGVcbiAgICAgICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICAgICAqL1xuICAgIGdldCByZWFkb25seSgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiAhdGhpcy5lbmFibGVkO1xuICAgIH1cblxuICAgIHNldCByZWFkb25seSh2YWx1ZTogYm9vbGVhbikge1xuICAgICAgdGhpcy5lbmFibGVkID0gIXZhbHVlO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vRGF0YUZpZWxkLnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBFZGl0b3IgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBFZGl0b3JcbiAgICAgKiBAZXh0ZW5kcyB7RGF0YUZpZWxkfVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgRWRpdG9yIGV4dGVuZHMgYWtpb21hLnN3YXQuRGF0YUZpZWxkIHtcblxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9EYXRhRmllbGQudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIElucHV0IE9iamVjdFxuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgSW5wdXRcbiAgICAgKiBAZXh0ZW5kcyB7RGF0YUZpZWxkfVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgSW5wdXQgZXh0ZW5kcyBha2lvbWEuc3dhdC5EYXRhRmllbGQge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL0RhdGFGaWVsZC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogVG9nZ2xlIE9iamVjdFxuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgVG9nZ2xlXG4gICAgICogQGV4dGVuZHMge0RhdGFGaWVsZH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIFRvZ2dsZSBleHRlbmRzIGFraW9tYS5zd2F0LkRhdGFGaWVsZCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdG9nZ2xlIGZpZWxkIHNjcmVlbiB2YWx1ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldCBzY3JlZW5WYWx1ZSgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLmNoZWNrZWQ7XG4gICAgfVxuXG4gICAgc2V0IHNjcmVlblZhbHVlKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICB0aGlzLmNoZWNrZWQgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdG9nZ2xlIGZpZWxkIGNoZWNrZWQgc3RhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQgY2hlY2tlZCgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldEN1cnJlbnRWYWx1ZVRvZ2dsZUJveCgpO1xuICAgIH1cblxuICAgIHNldCBjaGVja2VkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldFZhbHVlKHZhbHVlID8gJ3llcycgOiAnbm8nKTtcblxuICAgICAgaWYgKHRoaXMuZW5hYmxlTGl2ZVZhbGlkYXRpb24pXG4gICAgICAgIHRoaXMuZm9ybUNvbnRyb2xsZXIudmFsaWRhdGVGaWVsZCh0aGlzLm5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSB0b2dnbGUgZmllbGQgY2hlY2tlZCBzdGF0ZS4gVGhpcyBzaG91bGQgYmUgdGhlIGNvcnJlY3QgZ2V0dGVyLlxuICAgICAqIERpZG4ndCByZXBsYWNlIGdldCBjaGVja2VkKCkgYmVjYXVzZSBpdCB3b3VsZCByZXF1aXJlIGhlYXZ5IHJlZmFjdG9yaW5nXG4gICAgICogb24gT1NJViBzaWRlLiAoc2VlIENMQS00OSlcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQgaXNDaGVja2VkKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0Q3VycmVudFZhbHVlVG9nZ2xlQm94KCk7XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9EYXRhRmllbGQudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIFR3b1N0YXRlIE9iamVjdFxuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgVHdvU3RhdGVcbiAgICAgKiBAZXh0ZW5kcyB7RGF0YUZpZWxkfVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgVHdvU3RhdGUgZXh0ZW5kcyBha2lvbWEuc3dhdC5EYXRhRmllbGQge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi9EYXRhRmllbGQudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIFNtYXJ0RmllbGQgT2JqZWN0IEJhc2UgQ2xhc3NcbiAgICAgKiBAZXhwb3J0XG4gICAgICogQGNsYXNzIFNtYXJ0RmllbGRPYmplY3RcbiAgICAgKiBAZXh0ZW5kcyB7RGF0YUZpZWxkfVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgU21hcnRGaWVsZE9iamVjdCBleHRlbmRzIGFraW9tYS5zd2F0LkRhdGFGaWVsZCB7XG5cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vU21hcnRGaWVsZE9iamVjdC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAqIER5blNlbGVjdCBPYmplY3RcbiAgICogQGV4cG9ydFxuICAgKiBAY2xhc3MgRHluU2VsZWN0XG4gICAqIEBleHRlbmRzIHtTbWFydEZpZWxkT2JqZWN0fVxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIER5blNlbGVjdCBleHRlbmRzIGFraW9tYS5zd2F0LlNtYXJ0RmllbGRPYmplY3Qge1xuXG4gICAgcHJpdmF0ZSBfbG9va3VwRGF0YVNvdXJjZTogYWtpb21hLnN3YXQuRGF0YVNvdXJjZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBkeW5zZWxlY3QgZmllbGQgc2NyZWVuIHZhbHVlLlxuICAgICAqIE5vdGUgdGhhdCBzY3JlZW5WYWx1ZSBjYW4gb25seSBiZSB1cGRhdGVkIHdpdGggbnVsbCwgdW5kZWZpbmVkIG9yIFwiXCJcbiAgICAgKiB0byBjbGVhciB0aGUgZHluU2VsZWN0IGFuZCBpdHMga2V5VmFsdWUuXG4gICAgICogQHR5cGUgeyp9XG4gICAgICovXG4gICAgZ2V0IHNjcmVlblZhbHVlKCk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRWYWx1ZSgnZGVzYycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZHluc2VsZWN0IGZpZWxkIHNjcmVlbiB2YWx1ZS5cbiAgICAgKiBAdHlwZSB7Kn1cbiAgICAgKi9cbiAgICBzZXQgc2NyZWVuVmFsdWUodmFsdWU6IGFueSkge1xuICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICAgIHRoaXMuY2xlYXJTZWxlY3QoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGR5bnNlbGVjdCBrZXkgZmllbGQgbmFtZVxuICAgICAqIEB0eXBlIHsqfVxuICAgICAqL1xuICAgIGdldCBrZXlOYW1lKCk6IGFueSB7XG4gICAgICBjb25zdCBvcHQgPSB0aGlzLl9jb250cm9sbGVyLm9wdDtcbiAgICAgIGNvbnN0IG5hbWUgPSAob3B0Lmxvb2t1cEtleVZhbHVlQmluZGluZyAmJiBvcHQubG9va3VwS2V5VmFsdWVCaW5kaW5nLnRvTG93ZXJDYXNlKCkgIT09ICdfc2VsZicgPyBvcHQubG9va3VwS2V5VmFsdWVCaW5kaW5nIDogdGhpcy5uYW1lKTtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBkeW5zZWxlY3QgZmllbGQga2V5IHZhbHVlXG4gICAgICogQHR5cGUgeyp9XG4gICAgICovXG4gICAgZ2V0IGtleVZhbHVlKCk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRWYWx1ZSgnaWQnKTtcbiAgICB9XG5cbiAgICBzZXQga2V5VmFsdWUodmFsdWU6IGFueSkge1xuICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICAgIHRoaXMuY2xlYXJTZWxlY3QoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5fY29udHJvbGxlci5keW5TZWxlY3RDb250cm9sLnBvc2l0aW9uVG9SZWNvcmQodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFzeW5jIHNldCBrZXkgdmFsdWUuIFNldHMgdGhlIGtleSB2YWx1ZSBhbmQgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBrZXkgdmFsdWUgaXMgc2V0LlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgZm9yIHBvc2l0aW9uaW5nIGEgZHluc2VsZWN0IG9uIGFuIGV4YWN0IHJlc3VsdCAob3IgbXVsdGlwbGUgcmVzdWx0cykuIFRoZSBvdXRjb21lIGlzIHRoZSBzYW1lIGFzIHNlbGVjdGluZyBhIHJlc3VsdCBpbiB0aGUgZHJvcGRvd24gbGlzdCBhdXRvbWF0aWNhbGx5LlxuICAgICAqIEBwYXJhbSAge2FueX0gdmFsdWUgSWYgU3RyaW5nIG9yIG51bWJlciwgaXQgcmVwcmVzZW50cyB0aGUgS2V5VmFsdWUgdmFsdWUgdXNlZCBmb3IgZmlsdGVyaW5nIHVzaW5nIGEgRmV0Y2hCeVVuaXF1ZUtleSBOYW1lZFF1ZXJ5LiA8L2JyPlxuICAgICAqIElmIEFycmF5IG9mIE9iamVjdHMsIGl0IHJlcHJlc2VudHMgdGhlIG5ldyBkYXRhIHRoYXQgd2lsbCBiZSBzZXQgaW4gZHluU2VsZWN0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBmb28oZXZlbnRTb3VyY2U6IGFraW9tYS5zd2F0LkR5blNlbGVjdCkge1xuICAgICAqICAgYXdhaXQgZXZlbnRTb3VyY2Uuc2V0S2V5VmFsdWUoJ1MnKTtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGV2ZW50U291cmNlLmtleVZhbHVlKTtcbiAgICAgKiB9XG4gICAgICogQHR5cGUgeyp9XG4gICAgICovXG4gICAgc2V0S2V5VmFsdWUodmFsdWU6IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgdGhpcy5jbGVhclNlbGVjdCgpO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xuICAgICAgfVxuICAgICAgLy8gcmV0dXJuIHdpbmRvdy5ha2lvbWEuZHluU2VsZWN0LnBvc2l0aW9uVG9SZWNvcmQodGhpcy5fY29udHJvbGxlciwgdmFsdWUpO1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZHluU2VsZWN0Q29udHJvbC5wb3NpdGlvblRvUmVjb3JkKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgdGhlIGR5bnNlbGVjdCBmaWVsZCBzY3JlZW4gdmFsdWUuXG4gICAgICogTm90ZSB0aGF0IHRoZSBkeW5zZWxlY3QgZGF0YXNvdXJjZSBrZXkgdmFsdWUgaXMgc3luY2hyb25pemVkIHdpdGggdGhlIHNjcmVlbiB2YWx1ZVxuICAgICAqIHNvIGNsZWFyaW5nIHRoZSBzY3JlZW4gd2lsbCBzZXQgdGhlIGRhdGFzb3VyY2Uga2V5IHZhbHVlIHRvIG51bGxcbiAgICAgKi9cbiAgICBhc3luYyBjbGVhclNlbGVjdCgpIHtcblxuICAgICAgLy8gY2xlYXIgc2NyZWVuIHZhbHVlXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLl9jb250cm9sbGVyLnNldFZhbHVlKCcnKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHdpbmRvdy5ha2lvbWEubG9nLmVycm9yKGVycm9yKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIudmFsLmlkID0gdGhpcy5fY29udHJvbGxlci5kZWZhdWx0RW1wdHlWYWx1ZTtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIudmFsLmRlc2MgPSAnJztcblxuICAgICAgaWYgKCF0aGlzLl9jb250cm9sbGVyLmJQb3NSZWNvcmQpXG4gICAgICAgIHRoaXMuX2NvbnRyb2xsZXIub1Bvc2l0aW9uZWRFbGVtZW50ID0gbnVsbDtcblxuICAgICAgLy8gY2xlYXIga2V5IHZhbHVlXG4gICAgICAvLyBub3RlIHRoYXQgdGhlcmUgYXJlIGNhc2VzIHdoZXJlIGEgZm9ybSBpcyBub3QgbGlua2VkIHRvIGEgZGF0YXNvdXJjZVxuICAgICAgaWYgKHRoaXMuZGF0YVNvdXJjZSlcbiAgICAgICAgdGhpcy5kYXRhU291cmNlLnNldFZhbHVlKHRoaXMua2V5TmFtZSwgbnVsbCk7XG5cbiAgICAgIC8vIGNsZWFyIHRoZSBsb29rdXAgZGF0YXNvdXJjZVxuICAgICAgaWYgKHRoaXMubG9va3VwRGF0YVNvdXJjZSlcbiAgICAgICAgdGhpcy5sb29rdXBEYXRhU291cmNlLmNsb3NlUXVlcnkoKTtcblxuICAgICAgLy8gY2FsbCBha3ZhbGlkYXRlIGV2ZW50XG4gICAgICBpZiAodGhpcy5fY29udHJvbGxlci5vcHQudmFsaWRhdGVFdmVudCAmJiAhdGhpcy5fY29udHJvbGxlci5pZ25vcmVWYWxpZGF0ZUV2ZW50KVxuICAgICAgICB3aW5kb3cuYXBwLmNvbnRyb2xsZXIuY2FsbEFraW9tYUNvZGUodGhpcy5fY29udHJvbGxlciwgdGhpcy5fY29udHJvbGxlci5vcHQudmFsaWRhdGVFdmVudCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRvIGNsZWFyIHRoZSBzZWxlY3QgbG9va3VwIGNvbnRyb2xzXG4gICAgICovXG4gICAgY2xlYXJTZWxlY3RMb29rdXBDb250cm9scygpIHtcbiAgICAgIHRoaXMuY29udHJvbGxlci5jbGVhclNlbGVjdExvb2t1cENvbnRyb2xzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGR5bnNlbGVjdCBmaWVsZCByZWFkb25seSBtb2RlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgZ2V0IHJlYWRvbmx5KCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuICF0aGlzLmVuYWJsZWQ7XG4gICAgfVxuXG4gICAgc2V0IHJlYWRvbmx5KHZhbHVlOiBib29sZWFuKSB7XG4gICAgICB0aGlzLmVuYWJsZWQgPSAhdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGxvb2t1cCBkYXRhc291cmNlIGZvciB0aGlzIGR5bnNlbGVjdCBmaWVsZFxuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHtEYXRhU291cmNlfVxuICAgICAqL1xuICAgIGdldCBsb29rdXBEYXRhU291cmNlKCk6IGFraW9tYS5zd2F0LkRhdGFTb3VyY2Uge1xuICAgICAgaWYgKCF0aGlzLl9sb29rdXBEYXRhU291cmNlKVxuICAgICAgICB0aGlzLl9sb29rdXBEYXRhU291cmNlID0gPGFraW9tYS5zd2F0LkRhdGFTb3VyY2U+KGFraW9tYS5zd2F0LlN3YXRGYWN0b3J5LmNyZWF0ZVN3YXRPYmplY3QodGhpcy5fY29udHJvbGxlci5idXNpbmVzc0VudGl0eSkpO1xuXG4gICAgICByZXR1cm4gdGhpcy5fbG9va3VwRGF0YVNvdXJjZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgbWV0aG9kIGZvciBjbGVhcmluZyB0aGUgbG9va3VwIGRhdGFzb3VyY2UgZmlsdGVyLlxuICAgICAqIEVxdWl2YWxlbnQgdG8gZHluU2VsZWN0Lmxvb2t1cERhdGFTb3VyY2UuY2xlYXJGaWx0ZXIoKS5cbiAgICAgKi9cbiAgICBjbGVhckZpbHRlcigpIHtcbiAgICAgIHRoaXMubG9va3VwRGF0YVNvdXJjZS5jbGVhckZpbHRlcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBtZXRob2QgZm9yIGFkZGluZyBhIGZpbHRlciB0byB0aGUgbG9va3VwIGRhdGFzb3VyY2UgZmlsdGVyICh0b3AgbGV2ZWwgQU5EIGZpbHRlcikuXG4gICAgICogRXF1aXZhbGVudCB0byBkeW5TZWxlY3QubG9va3VwRGF0YVNvdXJjZS5hZGRGaWx0ZXIoKS5cbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgZmllbGQgbmFtZVxuICAgICAqIEBwYXJhbSBvcGVyYXRvciBUaGUgZmlsdGVyIG9wZXJhdG9yXG4gICAgICogQHBhcmFtIHZhbHVlIFRoZSBmaWx0ZXIgdmFsdWVcbiAgICAgKiBAcGFyYW0gdW5pcXVlIElmIHRydWUsIGFkZHMgYSBuZXcgdW5pcXVlIGNvbmRpdGlvbiB0aGF0IHdpbGwgb3ZlcndyaXRlIGFueSBjb25kaXRpb25zIHdpdGggdGhlIHNhbWUgZmllbGQgbmFtZS4gSWYgZmFsc2UsIGp1c3QgYWRkcyBhIG5ldyBjb25kaXRpb25cbiAgICAgKi9cbiAgICBhZGRGaWx0ZXIobmFtZTogc3RyaW5nLCBvcGVyYXRvcjogc3RyaW5nLCB2YWx1ZTogYW55LCB1bmlxdWU/OiBib29sZWFuKSB7XG4gICAgICB0aGlzLmxvb2t1cERhdGFTb3VyY2UuYWRkRmlsdGVyKG5hbWUsIG9wZXJhdG9yLCB2YWx1ZSwgdW5pcXVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgbWV0aG9kIHRvIGNoZWNrIGlmIGEgZmlsdGVyIGV4aXN0cyBpbiB0aGUgbG9va3VwIGRhdGFzb3VyY2UgKHRvcCBsZXZlbCBBTkQgZmlsdGVyKS5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGR5blNlbGVjdC5sb29rdXBEYXRhU291cmNlLmhhc0ZpbHRlcigpLlxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBmaWVsZCBuYW1lXG4gICAgICogQHBhcmFtIG9wZXJhdG9yIFRoZSBmaWx0ZXIgb3BlcmF0b3JcbiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGZpbHRlciB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGhhc0ZpbHRlcihuYW1lOiBzdHJpbmcsIG9wZXJhdG9yOiBzdHJpbmcsIHZhbHVlOiBhbnkpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLmxvb2t1cERhdGFTb3VyY2UuaGFzRmlsdGVyKG5hbWUsIG9wZXJhdG9yLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCB0byBjbGVhciB0aGUgbG9va3VwIGRhdGFzb3VyY2Ugc29ydGluZy5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGR5blNlbGVjdC5sb29rdXBEYXRhU291cmNlLmNsZWFyU29ydCgpLlxuICAgICAqL1xuICAgIGNsZWFyU29ydCgpIHtcbiAgICAgIHRoaXMubG9va3VwRGF0YVNvdXJjZS5jbGVhclNvcnQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgbWV0aG9kIHRoYXQgcmV0dXJucyBpZiBhIGZpZWxkIChhbmQgb3B0aW9uYWwgZGlyZWN0aW9uKSBhcmUgaW4gdGhlIGxvb2t1cCBkYXRhc291cmNlIHNvcnRpbmcuXG4gICAgICogRXF1aXZhbGVudCB0byBkeW5TZWxlY3QubG9va3VwRGF0YVNvdXJjZS5oYXNTb3J0KCkuXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpLiBJZiBubyBmaWVsZCBuYW1lIGlzIHBhc3NlZCwgY2hlY2tzIGlmIHRoZXJlIGlzIGFueSBzb3J0aW5nLlxuICAgICAqIEBwYXJhbSBkaXJlY3Rpb24gXCJhc2NcIiBmb3IgYXNjZW5kaW5nIG9yIFwiZGVzY1wiIGZvciBkZXNjZW5kaW5nLiBJZiBubyBkaXJlY3Rpb24gaXMgcGFzc2VkLCBjaGVjayBpZiBvbmx5IGZpZWxkIG5hbWUgZXhpc3RzLlxuICAgICAqL1xuICAgIGhhc1NvcnQobmFtZT86IHN0cmluZywgZGlyZWN0aW9uPzogJ2FzYycgfCAnZGVzYycpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLmxvb2t1cERhdGFTb3VyY2UuaGFzU29ydChuYW1lLCBkaXJlY3Rpb24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBtZXRob2QgdG8gc2V0cyB0aGUgc29ydGluZyBpbiB0aGUgbG9va3VwIGRhdGFzb3VyY2UuXG4gICAgICogRXF1aXZhbGVudCB0byBkeW5TZWxlY3QubG9va3VwRGF0YVNvdXJjZS5zZXRTb3J0KCkuXG4gICAgICogQHBhcmFtIHthcnJheX0gW3NvcnRdXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNvcnQuZmllbGQgVGhlIGZpZWxkIG5hbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc29ydC5kaXJlY3Rpb24gXCJhc2NcIiBmb3IgYXNjZW5kaW5nIG9yIFwiZGVzY1wiIGZvciBkZXNjZW5kaW5nXG4gICAgICovXG4gICAgc2V0U29ydChuYW1lOiBzdHJpbmcpOiB2b2lkO1xuICAgIHNldFNvcnQobmFtZTogc3RyaW5nLCBkaXJlY3Rpb246ICdhc2MnIHwgJ2Rlc2MnKTogdm9pZDtcbiAgICBzZXRTb3J0KHNvcnQ6IHtmaWVsZDogc3RyaW5nLCBkaXJlY3Rpb246ICdhc2MnIHwgJ2Rlc2MnfVtdKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBtZXRob2QgdG8gc2V0cyB0aGUgc29ydGluZyBpbiB0aGUgbG9va3VwIGRhdGFzb3VyY2UuXG4gICAgICogRXF1aXZhbGVudCB0byBkeW5TZWxlY3QubG9va3VwRGF0YVNvdXJjZS5zZXRTb3J0KCkuXG4gICAgICogQHBhcmFtIHthcnJheX0gW3NvcnRdXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNvcnQuZmllbGQgVGhlIGZpZWxkIG5hbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc29ydC5kaXJlY3Rpb24gXCJhc2NcIiBmb3IgYXNjZW5kaW5nIG9yIFwiZGVzY1wiIGZvciBkZXNjZW5kaW5nXG4gICAgICovXG4gICAgc2V0U29ydChzb3J0OiBhbnkpIHtcbiAgICAgIHRoaXMubG9va3VwRGF0YVNvdXJjZS5zZXRTb3J0KHNvcnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBtZXRob2QgdG8gZ2V0IHRoZSBsb29rdXAgZGF0YXNvdXJjZSBjdXJyZW50IHNvcnRpbmcuXG4gICAgICogRXF1aXZhbGVudCB0byBkeW5TZWxlY3QubG9va3VwRGF0YVNvdXJjZS5nZXRTb3J0KCkuXG4gICAgICovXG4gICAgZ2V0U29ydCgpOiB7ZmllbGQ6IHN0cmluZywgZGlyZWN0aW9uOiAnYXNjJyB8ICdkZXNjJ31bXSB7XG4gICAgICByZXR1cm4gdGhpcy5sb29rdXBEYXRhU291cmNlLmdldFNvcnQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgbWV0aG9kIHRvIHNldCB0aGUgbG9va3VwIGRhdGFzb3VyY2UgbmFtZWQgcXVlcnkgcGFyYW1ldGVyLlxuICAgICAqIEVxdWl2YWxlbnQgdG8gZHluU2VsZWN0Lmxvb2t1cERhdGFTb3VyY2Uuc2V0TmFtZWRRdWVyeVBhcmFtKClcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcXVlcnkgVGhlIHBhcmFtZXRlciBxdWVyeSBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIHBhcmFtZXRlciBmaWVsZCBuYW1lXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgcGFyYW1ldGVyIHZhbHVlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgVGhlIHBhcmFtZXRlciB0eXBlXG4gICAgICovXG4gICAgc2V0TmFtZWRRdWVyeVBhcmFtKHF1ZXJ5OiBzdHJpbmcsIG5hbWU6IHN0cmluZywgdmFsdWU6IGFueSwgdHlwZTogc3RyaW5nKSB7XG4gICAgICB0aGlzLmxvb2t1cERhdGFTb3VyY2Uuc2V0TmFtZWRRdWVyeVBhcmFtKHF1ZXJ5LCBuYW1lLCB2YWx1ZSwgdHlwZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCBmb3IgZ2V0dGluZyBhIGZpZWxkIHZhbHVlIGluIHRoZSBsb29rdXAgZGF0YXNvdXJjZS5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGR5blNlbGVjdC5sb29rdXBEYXRhU291cmNlLmdldFZhbHVlKFwibXlmaWVsZFwiKS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgZm9ybSBmaWVsZCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIGdldEZpZWxkVmFsdWUobmFtZTogc3RyaW5nKTogYW55IHtcbiAgICAgIHJldHVybiB0aGlzLmxvb2t1cERhdGFTb3VyY2UuZ2V0VmFsdWUobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCBmb3Igc2V0dGluZyBhIGZpZWxkIHZhbHVlIGluIHRoZSBsb29rdXAgZGF0YXNvdXJjZS5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGR5blNlbGVjdC5sb29rdXBEYXRhU291cmNlLnNldFZhbHVlKFwibXlmaWVsZFwiLCBcInZhbHVlXCIpLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmb3JtIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0XG4gICAgICovXG4gICAgc2V0RmllbGRWYWx1ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgICAgIHRoaXMubG9va3VwRGF0YVNvdXJjZS5zZXRWYWx1ZShuYW1lLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBCdXNpbmVzc0VudGl0eSBkYXRhIGZvciBzZWxlY3RlZCByZWNvcmQgaW4gZHluU2VsZWN0IG9yIHRoZSByZWNvcmQgc2VsZWN0ZWQgZnJvbSBjaG9vc2VXaW5kb3cuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyByZWNvcmQgZGF0YVxuICAgICAqL1xuICAgIGdldFNlbGVjdGVkUmVjb3JkKCk6IG9iamVjdCB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRTZWxlY3RlZFJlY29yZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdmFsdWVzIGZyb20gYSBtdWx0aXBsZSBkeW5TZWxlY3QuXG4gICAgICogQHBhcmFtIHtzdHJpbmcgfCBzdHJpbmdbXX0gdmFsdWVzIFRoZSB2YWx1ZXMgdG8gcmVtb3ZlIGZyb20gdGhlIGR5blNlbGVjdCAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKi9cbiAgICByZW1vdmVTZWxlY3Rpb24odmFsdWVzOiBzdHJpbmcgfCBzdHJpbmdbXSkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5yZW1vdmVTZWxlY3Rpb24odmFsdWVzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHR5cGVkIHRleHQgaW5zaWRlIHRoZSBkeW5zZWxlY3QuXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlcm9mIER5blNlbGVjdFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZ2V0IHR5cGVkVmFsdWUoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLnR5cGVkVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHVzZWQgZm9yIGdldHRpbmcgdGhlIGNvdW50IG9mIHRoZSByZXN1bHRzIGZyb20gdGhlIHJlc3VsdHMgbGlzdC5cbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyT2YgYWtfZHluc2VsZWN0XG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBnZXRSZXN1bHRzQ291bnQoKTogbnVtYmVyIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldFJlc3VsdHNDb3VudCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3cgYSBmb290ZXIgaXRlbSBmcm9tIHRoZSBkeW5zZWxlY3QgZHJvcGRvd24gZm9vdGVyIGJ5IHRoZSBpdGVtIG5hbWUuXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlck9mIGFrX2R5bnNlbGVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpdGVtTmFtZVxuICAgICAqL1xuICAgIHNob3dGb290ZXJJdGVtKGl0ZW1OYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2hvd0Zvb3Rlckl0ZW0oaXRlbU5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhpZGUgYSBmb290ZXIgaXRlbSBmcm9tIHRoZSBkeW5zZWxlY3QgZHJvcGRvd24gZm9vdGVyIGJ5IHRoZSBpdGVtIG5hbWUuXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlck9mIGFrX2R5bnNlbGVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpdGVtTmFtZVxuICAgICAqL1xuICAgIGhpZGVGb290ZXJJdGVtKGl0ZW1OYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuaGlkZUZvb3Rlckl0ZW0oaXRlbU5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBlbmFibGluZyBwcmVTZWxlY3RFeGlzdGluZ0lucHV0IG9wdGlvblxuICAgICAqL1xuICAgIGVuYWJsZVByZVNlbGVjdEV4aXN0aW5nSW5wdXQoKTogdm9pZCB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmVuYWJsZVByZVNlbGVjdEV4aXN0aW5nSW5wdXQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdG8gZGlzYWJsaW5nIHByZVNlbGVjdEV4aXN0aW5nSW5wdXQgb3B0aW9uXG4gICAgICovXG4gICAgZGlzYWJsZVByZVNlbGVjdEV4aXN0aW5nSW5wdXQoKTogdm9pZCB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmRpc2FibGVQcmVTZWxlY3RFeGlzdGluZ0lucHV0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRvIHBvc2l0aW9uaW5nIHRvIGEgY2VydGFpbiByZWNvcmRcbiAgICAgKi9cbiAgICBwb3NpdGlvblRvUmVjb3JkKHJlY29yZElkOiBhbnkpIHtcbiAgICAgIHRoaXMuY29udHJvbGxlci5keW5TZWxlY3RDb250cm9sLnBvc2l0aW9uVG9SZWNvcmQocmVjb3JkSWQpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vU21hcnRGaWVsZE9iamVjdC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogUmljaFRleHQgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBSaWNoVGV4dFxuICAgICAqIEBleHRlbmRzIHtTbWFydEZpZWxkT2JqZWN0fVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgUmljaFRleHQgZXh0ZW5kcyBha2lvbWEuc3dhdC5TbWFydEZpZWxkT2JqZWN0IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBmb3JtIGZpZWxkIHNjcmVlbiB2YWx1ZVxuICAgICAqIEB0eXBlIHsqfVxuICAgICAqL1xuICAgIGdldCBzY3JlZW5WYWx1ZSgpOiBhbnkge1xuICAgICAgLy8gZm9yIGFrX2l0dGV4dFxuICAgICAgaWYgKHRoaXMuX2NvbnRyb2xsZXIuZ2V0VmFsdWVGb3JtYXR0ZWQpXG4gICAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldFZhbHVlRm9ybWF0dGVkKCk7XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldFZhbHVlKCk7XG4gICAgfVxuXG4gICAgc2V0IHNjcmVlblZhbHVlKHZhbHVlOiBhbnkpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0VmFsdWUodmFsdWUpO1xuXG4gICAgICBpZiAodGhpcy5lbmFibGVMaXZlVmFsaWRhdGlvbilcbiAgICAgICAgdGhpcy5mb3JtQ29udHJvbGxlci52YWxpZGF0ZUZpZWxkKHRoaXMubmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgcGxhaW4gdGV4dCB2YWx1ZSB1bmxpa2Ugc2NyZWVuVmFsdWUgdGhhdCByZXR1cm5zIHRoZSBmb3JtYXR0ZWQgSFRNTCB2YWx1ZVxuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICovXG4gICAgZ2V0IHBsYWluVmFsdWUoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldFZhbHVlKCdhc2NpaScpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vU21hcnRGaWVsZE9iamVjdC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogVHJhbnNsYXRhYmxlIE9iamVjdFxuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgVHJhbnNsYXRhYmxlXG4gICAgICogQGV4dGVuZHMge1NtYXJ0RmllbGRPYmplY3R9XG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBUcmFuc2xhdGFibGUgZXh0ZW5kcyBha2lvbWEuc3dhdC5TbWFydEZpZWxkT2JqZWN0IHtcblxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vVmlzdWFsT2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICogR3JpZCBDb2x1bW4gQmFzZSBDbGFzc1xuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBHcmlkQ29sXG4gICAqIEBleHRlbmRzIHtWaXN1YWxPYmplY3R9XG4gICAqL1xuICBleHBvcnQgY2xhc3MgR3JpZENvbCBleHRlbmRzIGFraW9tYS5zd2F0LlZpc3VhbE9iamVjdCB7XG5cbiAgICBwcml2YXRlIF9kYXRhU291cmNlOiBha2lvbWEuc3dhdC5EYXRhU291cmNlO1xuICAgIHByaXZhdGUgX2dyaWQ6IGFraW9tYS5zd2F0LkdyaWQ7XG4gICAgcHJpdmF0ZSBfbG9va3VwRGF0YVNvdXJjZTogYWtpb21hLnN3YXQuRGF0YVNvdXJjZTtcbiAgICBwcml2YXRlIF9ncmlkQ29udHJvbGxlcjogYW55O1xuICAgIHByaXZhdGUgX2dyaWREaHg6IGFueTtcbiAgICBwcml2YXRlIF9jb2xJZHg6IG51bWJlcjtcbiAgICBwcml2YXRlIF9yb3dJZDogc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSBnZXQgZ3JpZENvbnRyb2xsZXIoKTogYW55IHtcbiAgICAgIGlmICghdGhpcy5fZ3JpZENvbnRyb2xsZXIpXG4gICAgICAgIHRoaXMuX2dyaWRDb250cm9sbGVyID0gdGhpcy5fY29udHJvbGxlci5wYXJlbnQ7XG5cbiAgICAgIHJldHVybiB0aGlzLl9ncmlkQ29udHJvbGxlcjtcbiAgICB9XG5cbiAgICBnZXQgZHluT2JqZWN0KCk6IGFueSB7XG5cbiAgICAgIHJldHVybiB0aGlzLmdyaWQuZHluT2JqZWN0O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IGdyaWREaHgoKTogYW55IHtcbiAgICAgIGlmICghdGhpcy5fZ3JpZERoeClcbiAgICAgICAgdGhpcy5fZ3JpZERoeCA9IHRoaXMuZ3JpZENvbnRyb2xsZXIuZGh4O1xuXG4gICAgICByZXR1cm4gdGhpcy5fZ3JpZERoeDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldCBjb2xJZHgoKTogbnVtYmVyIHtcbiAgICAgIHRoaXMuX2NvbElkeCA9IHRoaXMuZ3JpZERoeC5nZXRDb2xJbmRleEJ5SWQodGhpcy5uYW1lLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbElkeDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldCByb3dJZCgpOiBzdHJpbmcge1xuICAgICAgdGhpcy5fcm93SWQgPSB0aGlzLl9jb250cm9sbGVyLnJvd0lkO1xuICAgICAgcmV0dXJuIHRoaXMuX3Jvd0lkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgd2hldGhlciBzaG91bGQgaWdub3JlIHZhbGlkYXRpb24gZXZlbnQgb3Igbm90LlxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldCBpZ25vcmVWYWxpZGF0ZUV2ZW50KCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuaWdub3JlVmFsaWRhdGVFdmVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHdoZXRoZXIgc2hvdWxkIGlnbm9yZSB2YWxpZGF0aW9uIGV2ZW50IG9yIG5vdC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHZhbHVlIE5ldyB2YWx1ZVxuICAgICAqL1xuICAgIHNldCBpZ25vcmVWYWxpZGF0ZUV2ZW50KHZhbHVlOiBib29sZWFuKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmlnbm9yZVZhbGlkYXRlRXZlbnQgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZ3JpZCBjb2x1bW4gZ3JpZCBvYmplY3RcbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKiBAdHlwZSB7R3JpZH1cbiAgICAgKi9cbiAgICBnZXQgZ3JpZCgpOiBha2lvbWEuc3dhdC5HcmlkIHtcbiAgICAgIGlmICghdGhpcy5fZ3JpZClcbiAgICAgICAgdGhpcy5fZ3JpZCA9IDxha2lvbWEuc3dhdC5HcmlkPihha2lvbWEuc3dhdC5Td2F0RmFjdG9yeS5jcmVhdGVTd2F0T2JqZWN0KHRoaXMuZ3JpZENvbnRyb2xsZXIpKTtcblxuICAgICAgcmV0dXJuIHRoaXMuX2dyaWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGVuYWJsZWQgcHJvcGVydHkgZm9yIHRoZSBjb2x1bW5cbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQgZW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmlzRW5hYmxlZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBpc0VuYWJsZWQgcHJvcGVydHkgZm9yIHRoZSBjb2x1bW5cbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59XG4gICAgICovXG4gICAgc2V0IGVuYWJsZWQodmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0RW5hYmxlZCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGdyaWQgY29sdW1uIGxpbmtlZCBkYXRhc291cmNlXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQHR5cGUge0RhdGFTb3VyY2V9XG4gICAgICovXG4gICAgZ2V0IGRhdGFTb3VyY2UoKTogYWtpb21hLnN3YXQuRGF0YVNvdXJjZSB7XG4gICAgICBpZiAoIXRoaXMuX2RhdGFTb3VyY2UpXG4gICAgICAgIHRoaXMuX2RhdGFTb3VyY2UgPSB0aGlzLmdyaWQuZGF0YVNvdXJjZTtcblxuICAgICAgcmV0dXJuIHRoaXMuX2RhdGFTb3VyY2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGdyaWQgY29sdW1uIGxvb2t1cCBkYXRhc291cmNlXG4gICAgICovXG4gICAgZ2V0IGxvb2t1cERhdGFTb3VyY2UoKTogYWtpb21hLnN3YXQuRGF0YVNvdXJjZSB7XG4gICAgICBpZiAoIXRoaXMuX2xvb2t1cERhdGFTb3VyY2UpXG4gICAgICAgIHRoaXMuX2xvb2t1cERhdGFTb3VyY2UgPSA8YWtpb21hLnN3YXQuRGF0YVNvdXJjZT4oYWtpb21hLnN3YXQuU3dhdEZhY3RvcnkuY3JlYXRlU3dhdE9iamVjdCh0aGlzLl9jb250cm9sbGVyLmJ1c2luZXNzRW50aXR5KSk7XG4gICAgICByZXR1cm4gdGhpcy5fbG9va3VwRGF0YVNvdXJjZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZ3JpZCBjb2x1bW4gc2NyZWVuIHZhbHVlXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQHR5cGUgeyp9XG4gICAgICovXG4gICAgZ2V0IHNjcmVlblZhbHVlKCk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRWYWx1ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBncmlkIGNvbHVtbiBzY3JlZW4gdmFsdWUgaW4gZmlsdGVyXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQgc2NyZWVuVmFsdWVGaWx0ZXIoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldFZhbHVlRmlsdGVyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGdyaWQgY29sdW1uIHNjcmVlbiB2YWx1ZSBpbiBmaWx0ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ31cbiAgICAgKi9cbiAgICBzZXQgc2NyZWVuVmFsdWVGaWx0ZXIodmFsdWU6IHN0cmluZykge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRWYWx1ZUZpbHRlcih2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGdyaWQgY29sdW1uIGxvb2t1cCBrZXkgdmFsdWVcbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKiBAdHlwZSB7Kn1cbiAgICAgKi9cbiAgICBnZXQgbG9va3VwS2V5VmFsdWUoKTogYW55IHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldExvb2t1cEtleSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBsaW5rZWQgZGF0YXNvdXJjZSBmaWVsZCB2YWx1ZVxuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHsqfVxuICAgICAqL1xuICAgIGdldCBkYXRhVmFsdWUoKTogYW55IHtcbiAgICAgIHJldHVybiB0aGlzLmRhdGFTb3VyY2UuZ2V0VmFsdWUodGhpcy5uYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZ3JpZCBjb2x1bW4gcmVhZG9ubHkgbW9kZVxuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldCByZWFkb25seSgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLmdyaWREaHguZ2V0Q29sVHlwZSh0aGlzLmNvbElkeCkuc3BsaXQoJywnKS5pbmNsdWRlcygncm8nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZ3JpZCBjb2x1bW4gaGlkZGVuIG1vZGUgKG9wcG9zaXRlIG9mIHZpc2libGUpXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgZ2V0IGhpZGRlbigpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLmdyaWREaHguaXNDb2x1bW5IaWRkZW4odGhpcy5jb2xJZHgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBncmlkIGNvbHVtbiB2aXNpYmxlIG1vZGUgKG9wcG9zaXRlIG9mIGhpZGRlbilcbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQgdmlzaWJsZSgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiAhdGhpcy5oaWRkZW47XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGdyaWQgY29sdW1uIGxhYmVsXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQgbGFiZWwoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiB0aGlzLmdyaWREaHguZ2V0SGVhZGVyQ29sKHRoaXMuY29sSWR4KTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi9WaXN1YWxPYmplY3QudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIExheW91dCBCYXNlIENsYXNzXG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBMYXlvdXRPYmplY3RcbiAgICAgKiBAZXh0ZW5kcyB7VmlzdWFsT2JqZWN0fVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgTGF5b3V0T2JqZWN0IGV4dGVuZHMgYWtpb21hLnN3YXQuVmlzdWFsT2JqZWN0IHtcblxuICAgIC8qKlxuICAgICAgICAgKiBHZXRzIGEgZGVzY2VuZGVudCBmb3JtIG9iamVjdCBieSBuYW1lXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBvYmplY3QgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICogQHJldHVybnMge0Zvcm19XG4gICAgICAgICAqL1xuICAgIGdldEZvcm0obmFtZTogc3RyaW5nKTogYWtpb21hLnN3YXQuRm9ybSB7XG4gICAgICBjb25zdCBmb3JtID0gdGhpcy5nZXRPYmplY3QobmFtZSk7XG5cbiAgICAgIGlmIChmb3JtIGluc3RhbmNlb2YgYWtpb21hLnN3YXQuRm9ybSlcbiAgICAgICAgcmV0dXJuIGZvcm07XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBHZXRzIGEgZGVzY2VuZGVudCBncmlkIG9iamVjdCBieSBuYW1lXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBvYmplY3QgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICogQHJldHVybnMge0dyaWR9XG4gICAgICAgICAqL1xuICAgIGdldEdyaWQobmFtZTogc3RyaW5nKTogYWtpb21hLnN3YXQuR3JpZCB7XG4gICAgICBjb25zdCBncmlkID0gdGhpcy5nZXRPYmplY3QobmFtZSk7XG5cbiAgICAgIGlmIChncmlkIGluc3RhbmNlb2YgYWtpb21hLnN3YXQuR3JpZClcbiAgICAgICAgcmV0dXJuIGdyaWQ7XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBHZXRzIGEgZGVzY2VuZGVudCB0YWJiYXIgb2JqZWN0IGJ5IG5hbWVcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG9iamVjdCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAgICAgKiBAcmV0dXJucyB7VGFiYmFyfVxuICAgICAgICAgKi9cbiAgICBnZXRUYWJiYXIobmFtZTogc3RyaW5nKTogYWtpb21hLnN3YXQuVGFiYmFyIHtcbiAgICAgIGNvbnN0IHRhYmJhciA9IHRoaXMuZ2V0T2JqZWN0KG5hbWUpO1xuXG4gICAgICBpZiAodGFiYmFyIGluc3RhbmNlb2YgYWtpb21hLnN3YXQuVGFiYmFyKVxuICAgICAgICByZXR1cm4gdGFiYmFyO1xuICAgICAgZWxzZVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogR2V0cyBhIGRlc2NlbmRlbnQgcmliYm9uIG9iamVjdCBieSBuYW1lXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBvYmplY3QgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICogQHJldHVybnMge2FraW9tYS5zd2F0LlJpYmJvbn1cbiAgICAgICAgICovXG4gICAgZ2V0UmliYm9uKG5hbWU/OiBzdHJpbmcpOiBha2lvbWEuc3dhdC5SaWJib24ge1xuICAgICAgY29uc3QgcmliYm9uID0gIW5hbWVcbiAgICAgICAgPyB0aGlzLmdldEZpcnN0Q2hpbGRCeVR5cGUoJ3JpYmJvbicpIDogdGhpcy5nZXRPYmplY3QobmFtZSk7XG5cbiAgICAgIGlmIChyaWJib24gaW5zdGFuY2VvZiBha2lvbWEuc3dhdC5SaWJib24pXG4gICAgICAgIHJldHVybiByaWJib247XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBHZXRzIGEgZGVzY2VuZGVudCB0b29sYmFyIG9iamVjdCBieSBuYW1lXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBvYmplY3QgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICogQHJldHVybnMge2FraW9tYS5zd2F0LlRvb2xiYXJ9XG4gICAgICAgICAqL1xuICAgIGdldFRvb2xiYXIobmFtZTogc3RyaW5nKTogYWtpb21hLnN3YXQuVG9vbGJhciB7XG4gICAgICBjb25zdCB0b29sYmFyID0gdGhpcy5nZXRPYmplY3QobmFtZSk7XG5cbiAgICAgIGlmICh0b29sYmFyIGluc3RhbmNlb2YgYWtpb21hLnN3YXQuVG9vbGJhcilcbiAgICAgICAgcmV0dXJuIHRvb2xiYXI7XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBHZXRzIGEgZGVzY2VuZGVudCBzY2hlZHVsZXIgb2JqZWN0IGJ5IG5hbWVcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG9iamVjdCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAgICAgKiBAcmV0dXJucyB7YWtpb21hLnN3YXQuU2NoZWR1bGVyfVxuICAgICAgICAgKi9cbiAgICBnZXRTY2hlZHVsZXIobmFtZTogc3RyaW5nKTogYWtpb21hLnN3YXQuU2NoZWR1bGVyIHtcbiAgICAgIGNvbnN0IHNjaGVkdWxlciA9IHRoaXMuZ2V0T2JqZWN0KG5hbWUpO1xuXG4gICAgICBpZiAoc2NoZWR1bGVyIGluc3RhbmNlb2YgYWtpb21hLnN3YXQuU2NoZWR1bGVyKVxuICAgICAgICByZXR1cm4gc2NoZWR1bGVyO1xuICAgICAgZWxzZVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogR2V0cyBhIGRlc2NlbmRlbnQgZG9jdmlld2VyIG9iamVjdCBieSBuYW1lXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBvYmplY3QgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICogQHJldHVybnMge2FraW9tYS5zd2F0LkRvY1ZpZXdlcn1cbiAgICAgICAgICovXG4gICAgZ2V0RG9jVmlld2VyKG5hbWU6IHN0cmluZyk6IGFraW9tYS5zd2F0LkRvY1ZpZXdlciB7XG4gICAgICBjb25zdCBkb2NWaWV3ZXIgPSB0aGlzLmdldE9iamVjdChuYW1lKTtcblxuICAgICAgaWYgKGRvY1ZpZXdlciBpbnN0YW5jZW9mIGFraW9tYS5zd2F0LkRvY1ZpZXdlcilcbiAgICAgICAgcmV0dXJuIGRvY1ZpZXdlcjtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIEdldHMgYSBkZXNjZW5kZW50IGRhdGFzb3VyY2Ugb2JqZWN0IGJ5IG5hbWVcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG9iamVjdCBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAgICAgKiBAcmV0dXJucyB7RGF0YVNvdXJjZX1cbiAgICAgICAgICovXG4gICAgZ2V0RGF0YVNvdXJjZShuYW1lOiBzdHJpbmcpOiBha2lvbWEuc3dhdC5EYXRhU291cmNlIHtcbiAgICAgIGNvbnN0IGRhdGFTb3VyY2UgPSB0aGlzLmdldE9iamVjdChuYW1lKTtcblxuICAgICAgaWYgKGRhdGFTb3VyY2UgaW5zdGFuY2VvZiBha2lvbWEuc3dhdC5EYXRhU291cmNlKVxuICAgICAgICByZXR1cm4gZGF0YVNvdXJjZTtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIEdldHMgYSBkZXNjZW5kZW50IGZyYW1lIG9iamVjdCBieSBuYW1lXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBvYmplY3QgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICogQHJldHVybnMge2FraW9tYS5zd2F0LkZyYW1lfVxuICAgICAgICAgKi9cbiAgICBnZXRGcmFtZShuYW1lOiBzdHJpbmcpOiBha2lvbWEuc3dhdC5GcmFtZSB7XG4gICAgICBjb25zdCBmcmFtZSA9IHRoaXMuZ2V0T2JqZWN0KG5hbWUpO1xuXG4gICAgICBpZiAoZnJhbWUgaW5zdGFuY2VvZiBha2lvbWEuc3dhdC5GcmFtZSlcbiAgICAgICAgcmV0dXJuIGZyYW1lO1xuICAgICAgZWxzZVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogQ2xlYXJzIGhhc0NoYW5nZXMgKGRpcnR5IHN0YXRlKVxuICAgICAgICAgKi9cbiAgICBjbGVhckhhc0NoYW5nZXMoKSB7XG4gICAgICBjb25zdCBkYXRhU291cmNlczogYW55W10gPSBbXTtcbiAgICAgIChmdW5jdGlvbiBmaWxsRGF0YVNvdXJjZXMoY29udHJvbGxlcjogYW55KSB7XG4gICAgICAgIGlmIChjb250cm9sbGVyLmNoaWxkcykge1xuICAgICAgICAgIGNvbnRyb2xsZXIuY2hpbGRzLmZvckVhY2goKGNoaWxkOiBhbnkpID0+IHtcblxuICAgICAgICAgICAgc3dpdGNoIChjaGlsZC52aWV3KSB7XG4gICAgICAgICAgICAgIGNhc2UgJ2J1c2luZXNzRW50aXR5JzpcbiAgICAgICAgICAgICAgY2FzZSAnYnVzaW5lc3NFbnRpdHkyJzpcbiAgICAgICAgICAgICAgICBkYXRhU291cmNlcy5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICBjYXNlICdmb3JtJzpcbiAgICAgICAgICAgICAgY2FzZSAnZGF0YWdyaWQyJzpcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGZpbGxEYXRhU291cmNlcyhjaGlsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pKHRoaXMuX2NvbnRyb2xsZXIpO1xuXG4gICAgICBkYXRhU291cmNlcy5mb3JFYWNoKChkYXRhU291cmNlOiBhbnkpID0+IHtcbiAgICAgICAgZGF0YVNvdXJjZS5jbGVhckhhc0NoYW5nZXMoKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vTGF5b3V0T2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICogQ29udGFpbmVyTGF5b3V0T2JqZWN0XG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIENvbnRhaW5lckxheW91dE9iamVjdFxuICAgKiBAZXh0ZW5kcyB7TGF5b3V0T2JqZWN0fVxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIENvbnRhaW5lckxheW91dE9iamVjdCBleHRlbmRzIGFraW9tYS5zd2F0LkxheW91dE9iamVjdCB7XG4gICAgcHJpdmF0ZSBfcHJpbWFyeURhdGFTb3VyY2U6IGFraW9tYS5zd2F0LkRhdGFTb3VyY2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgd2luZG93IFBSSU1BUllTRE8gbGlua2VkIGRhdGFzb3VyY2VcbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKiBAdHlwZSB7YWtpb21hLnN3YXQuRGF0YVNvdXJjZX1cbiAgICAgKi9cbiAgICBnZXQgcHJpbWFyeURhdGFTb3VyY2UoKTogYWtpb21hLnN3YXQuRGF0YVNvdXJjZSB7XG4gICAgICBpZiAoIXRoaXMuX3ByaW1hcnlEYXRhU291cmNlKVxuICAgICAgICB0aGlzLl9wcmltYXJ5RGF0YVNvdXJjZSA9IDxha2lvbWEuc3dhdC5EYXRhU291cmNlPiB0aGlzLmdldExpbmsoJ1BSSU1BUllTRE86VEFSR0VUJyk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9wcmltYXJ5RGF0YVNvdXJjZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaXZlIGN1c3RvbURhdGEgb2YgYSBha19mcmFtZSBvYmplY3RcbiAgICAgKiBAbWVtYmVyb2YgQ29udGFpbmVyTGF5b3V0T2JqZWN0XG4gICAgICogQHJldHVybnMge29iamVjdHxzdHJpbmd9XG4gICAgICogQGluc3RhbmNlXG4gICAgICovXG4gICAgZ2V0IGN1c3RvbURhdGEoKTogb2JqZWN0fHN0cmluZyB7XG4gICAgICByZXR1cm4gdGhpcy5keW5PYmplY3QuY29udGFpbmVyLmNvbnRyb2xsZXIuY3VzdG9tRGF0YTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIEN1c3RvbSBkYXRhXG4gICAgICogQG1lbWJlcm9mIENvbnRhaW5lckxheW91dE9iamVjdFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fHN0cmluZ30gY3VzdG9tRGF0YVxuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqL1xuICAgIHNldEN1c3RvbURhdGEoY3VzdG9tRGF0YTpvYmplY3R8c3RyaW5nKTogdm9pZCB7XG4gICAgICB0aGlzLmR5bk9iamVjdC5jb250YWluZXIuY29udHJvbGxlci5jdXN0b21EYXRhID0gY3VzdG9tRGF0YTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL0NvbnRhaW5lckxheW91dE9iamVjdC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogRnJhbWUgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBGcmFtZVxuICAgICAqIEBleHRlbmRzIHtDb250YWluZXJMYXlvdXRPYmplY3R9XG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBGcmFtZSBleHRlbmRzIGFraW9tYS5zd2F0LkNvbnRhaW5lckxheW91dE9iamVjdCB7XG5cbiAgfVxufVxuIiwibmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcbiAgZW51bSBNYXN0ZXJNb2RlcyB7XG4gICAgVEFTS0JBUl9NT0RFID0gJ3Rhc2tiYXItbW9kZScsXG4gICAgREVTS1RPUF9NT0RFID0gJ2Rlc2t0b3AtbW9kZSdcbiAgfVxuXG4gIHR5cGUgRGVza3RvcE1vZGUgPSBNYXN0ZXJNb2Rlcy5UQVNLQkFSX01PREUgfCBNYXN0ZXJNb2Rlcy5ERVNLVE9QX01PREU7XG4gIC8qKlxuICAgKiBNYXN0ZXJMYXlvdXQgT2JqZWN0XG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIE1hc3RlckxheW91dFxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIE1hc3RlckxheW91dCB7XG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0IGludGVybmFsT2JqZWN0KCk6IHR5cGVvZiBNYXN0ZXJMYXlvdXQge1xuICAgICAgcmV0dXJuIHdpbmRvdy5ha2lvbWEuTWFzdGVyTGF5b3V0O1xuICAgIH1cblxuICAgIC8qXG4gICAgKiBQcm9wZXJ0eSB1c2VkIHRvIGtlZXAgdHJhY2sgb2YgdGhlIGxhc3QgZm9jdXNlZCB3aW5kb3c7IHVzZWQgdG8gZGVhY3RpdmF0ZSBmb2N1c1RyYXA7XG4gICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIGdldCBsYXN0QWN0aXZlV2luZG93KCk6IGFueSB7XG4gICAgICByZXR1cm4gTWFzdGVyTGF5b3V0LmludGVybmFsT2JqZWN0Lmxhc3RBY3RpdmVXaW5kb3c7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvcGVydHkgdXNlZCBmb3Igc3RvcmluZyBiYXNlIGxheW91dCBvYmplY3QgbG9hZGVkXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBiYXNlTGF5b3V0T2JqZWN0KCk6IGFueSB7XG4gICAgICByZXR1cm4gTWFzdGVyTGF5b3V0LmludGVybmFsT2JqZWN0LmJhc2VMYXlvdXRPYmplY3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRvIHRvZ2dsZSBiZXR3ZWVuIGRlc2t0b3AgbW9kZSBhbmQgdGFza2JhciBtb2RlXG4gICAgICogQHBhcmFtIGlzRGVza3RvcCBJZiBEZXNrdG9wIG1vZGUgc2hvdWxkIGJlIGFjdGl2ZSBNYXN0ZXJNb2Rlcy5ERVNLVE9QX01PREUgPSB0cnVlXG4gICAgICovXG4gICAgc3RhdGljIHRvZ2dsZURlc2t0b3AoaXNEZXNrdG9wOiBib29sZWFuKSB7XG4gICAgICBNYXN0ZXJMYXlvdXQuaW50ZXJuYWxPYmplY3QudG9nZ2xlRGVza3RvcChpc0Rlc2t0b3ApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgcmV0dXJuaW5nIGJhc2UgbGF5b3V0IG9iamVjdCBsb2FkZWRcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0QmFzZUxheW91dE9iamVjdCgpOiBhbnkge1xuICAgICAgcmV0dXJuIE1hc3RlckxheW91dC5pbnRlcm5hbE9iamVjdC5nZXRCYXNlTGF5b3V0T2JqZWN0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBsYXVuY2hpbmcgYmFzZSBsYXlvdXQgb2JqZWN0XG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIGxhdW5jaEJhc2VMYXlvdXRPYmplY3QoKSB7XG4gICAgICBNYXN0ZXJMYXlvdXQuaW50ZXJuYWxPYmplY3QubGF1bmNoQmFzZUxheW91dE9iamVjdCgpO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXRCYXNlTGF5b3V0KCk6IGFueSB7XG4gICAgICByZXR1cm4gTWFzdGVyTGF5b3V0LmludGVybmFsT2JqZWN0LmdldEJhc2VMYXlvdXQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIGZpbmRpbmcgYWxsIHdpbmRvd3MgdGhhdCBtYXRjaCBhIGdpdmVuIG5hbWVcbiAgICAgKiBAcGFyYW0gd2luZG93TmFtZSBJbnN0YW5jZSBuYW1lIG9mIHdpbmRvd1xuICAgICAqL1xuICAgIHN0YXRpYyBmaW5kV2luZG93c0J5TmFtZSh3aW5kb3dOYW1lOiBzdHJpbmcpOiBBcnJheTxha2lvbWEuc3dhdC5XaW5kb3c+IHtcbiAgICAgIHJldHVybiBNYXN0ZXJMYXlvdXQuaW50ZXJuYWxPYmplY3QuZmluZFdpbmRvd3NCeU5hbWUod2luZG93TmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBmaW5kaW5nIGFsbCB3aW5kb3dzIGluIHdhaXQgc3RhdGVcbiAgICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0V2luZG93c0luV2FpdFN0YXRlKCk6IEFycmF5PGFueT4ge1xuICAgICAgcmV0dXJuIE1hc3RlckxheW91dC5pbnRlcm5hbE9iamVjdC5nZXRXaW5kb3dzSW5XYWl0U3RhdGUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdG8gZmluZCB3aW5kb3cgYnkgaWRcbiAgICAgKiBAcGFyYW0gaWQgd2luZG93IGlkXG4gICAgICovXG4gICAgc3RhdGljIGZpbmRXaW5kb3dCeUlkKGlkOiBzdHJpbmcpOiBha2lvbWEuc3dhdC5XaW5kb3cge1xuICAgICAgcmV0dXJuIE1hc3RlckxheW91dC5pbnRlcm5hbE9iamVjdC5maW5kV2luZG93QnlJZChpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRvIHJldHVybiBtYXN0ZXIgc3RhdGVcbiAgICAgKiBAcmV0dXJucyBEZXNrdG9wTW9kZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRNYXN0ZXJTdGF0ZSgpOiBEZXNrdG9wTW9kZSB7XG4gICAgICByZXR1cm4gTWFzdGVyTGF5b3V0LmludGVybmFsT2JqZWN0LmdldE1hc3RlclN0YXRlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBjaGVja2luZyBpZiBVc2VyIGlzIGN1cnJlbnRseSBpbiBEZXNrdG9wIG1vZGVcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNEZXNrdG9wTW9kZSgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiBNYXN0ZXJMYXlvdXQuaW50ZXJuYWxPYmplY3QuaXNEZXNrdG9wTW9kZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgY2hlY2tpbmcgaWYgVXNlciBpcyBjdXJyZW50bHkgaW4gVGFza2JhciBtb2RlXG4gICAgICovXG4gICAgc3RhdGljIGlzVGFza2Jhck1vZGUoKTogYm9vbGVhbiB7XG4gICAgICByZXR1cm4gTWFzdGVyTGF5b3V0LmludGVybmFsT2JqZWN0LmlzVGFza2Jhck1vZGUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHNldHRpbmcgdGhlIGFjdGl2ZSBNYXN0ZXIgU3RhdGVcbiAgICAgKiBAcGFyYW0gc3RhdGUgVHlwZSBvZiBzdGF0ZSBmcm9tIERlc2t0b3BNb2RlXG4gICAgICovXG4gICAgc3RhdGljIHNldE1hc3RlclN0YXRlKHN0YXRlOiBEZXNrdG9wTW9kZSkge1xuICAgICAgTWFzdGVyTGF5b3V0LmludGVybmFsT2JqZWN0LnNldE1hc3RlclN0YXRlKHN0YXRlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHNldHRpbmcgdGhlIExhc3QgQWN0aXZlIFdpbmRvd1xuICAgICAqIEBwYXJhbSBsYXN0QWN0aXZlV2luIExhc3QgQWN0aXZlIFdpbmRvdyBXaW5kb3dcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0TGFzdEFjdGl2ZVdpbmRvdyhsYXN0QWN0aXZlV2luOiBvYmplY3QpIHtcbiAgICAgIE1hc3RlckxheW91dC5pbnRlcm5hbE9iamVjdC5zZXRMYXN0QWN0aXZlV2luZG93KGxhc3RBY3RpdmVXaW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3Igc2V0dGluZyBBY3RpdmF0aW5nIExhc3QgV2luZG93IEZvY3VzLVRyYXBcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5hYmxlTGFzdEZvY3VzVHJhcCgpIHtcbiAgICAgIE1hc3RlckxheW91dC5pbnRlcm5hbE9iamVjdC5lbmFibGVMYXN0Rm9jdXNUcmFwKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzZXR0aW5nIERlYWN0aXZhdGluZyBMYXN0IFdpbmRvdyBGb2N1cy1UcmFwXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRlYWN0aXZhdGVPcHRpb25zXG4gICAgICovXG4gICAgc3RhdGljIGRpc2FibGVMYXN0Rm9jdXNUcmFwKGRlYWN0aXZhdGVPcHRpb25zPzogYW55KSB7XG4gICAgICBNYXN0ZXJMYXlvdXQuaW50ZXJuYWxPYmplY3QuZGlzYWJsZUxhc3RGb2N1c1RyYXAoZGVhY3RpdmF0ZU9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgY2hlY2tpbmcgaWYgZ2l2ZW4gd2luZG93IGlzIGluIHRhc2tiYXIgbW9kZVxuICAgICAqL1xuICAgIHN0YXRpYyBpc1dpbmRvd0luVGFza2Jhck1vZGUod2luZG93T2JqZWN0OiBha2lvbWEuc3dhdC5XaW5kb3cpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiBNYXN0ZXJMYXlvdXQuaW50ZXJuYWxPYmplY3QuaXNXaW5kb3dJblRhc2tiYXJNb2RlKHdpbmRvd09iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBnZXR0aW5nIHRvcCBtb3N0IHdpbmRvd1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXRUb3BNb3N0V2luZG93KCk6IGFraW9tYS5zd2F0LldpbmRvdyB7XG4gICAgICByZXR1cm4gTWFzdGVyTGF5b3V0LmludGVybmFsT2JqZWN0LmdldFRvcE1vc3RXaW5kb3coKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIGdldHRpbmcgdG9wIG1vc3Qgd2luZG93IGZyb20gVGFza2JhciBNb2RlXG4gICAgICovXG4gICAgc3RhdGljIGdldFRhc2tiYXJUb3BNb3N0V2luZG93KCk6IGFraW9tYS5zd2F0LldpbmRvdyB7XG4gICAgICByZXR1cm4gTWFzdGVyTGF5b3V0LmludGVybmFsT2JqZWN0LmdldFRhc2tiYXJUb3BNb3N0V2luZG93KCk7XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9MYXlvdXRPYmplY3QudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIFBvcE92ZXIgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBQb3BPdmVyXG4gICAgICogQGV4dGVuZHMge0xheW91dE9iamVjdH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIFBvcE92ZXIgZXh0ZW5kcyBha2lvbWEuc3dhdC5MYXlvdXRPYmplY3Qge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL0NvbnRhaW5lckxheW91dE9iamVjdC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogV2luZG93IE9iamVjdC5cbiAgICAgKiBOb3RlIHRoYXQgdGhlIGRlc2t0b3Agd2luZG93cyBhcmUgd2luZG93cyBub3QgZnJhbWVzLlxuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgV2luZG93XG4gICAgICogQGV4dGVuZHMge0NvbnRhaW5lckxheW91dE9iamVjdH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIFdpbmRvdyBleHRlbmRzIGFraW9tYS5zd2F0LkNvbnRhaW5lckxheW91dE9iamVjdCB7XG5cbiAgICBwcml2YXRlIF9jYWxsZXI6IGFraW9tYS5zd2F0LlN3YXRPYmplY3Q7XG5cbiAgICBnZXQgaXNNYWluRGVza3RvcFdpbmRvdygpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmlzQXV0b3N0YXJ0T2JqZWN0c1dpbmRvdyA9PT0gdHJ1ZTtcbiAgICB9XG5cbiAgICBnZXQgaXNEZXNrdG9wV2luZG93KCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuX2R5bk9iamVjdC5wYXJlbnQgJiYgdGhpcy5fZHluT2JqZWN0LnBhcmVudC5jb250cm9sbGVyLmlzQXV0b3N0YXJ0T2JqZWN0c1dpbmRvdyA9PT0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogVGhlIGNhbGxlciBvYmplY3QgdGhhdCB0aGlzIHdpbmRvdyB3YXMgbGF1bmNoZWQgZnJvbVxuICAgICAgICAgKiBAcmVhZG9ubHlcbiAgICAgICAgICogQHR5cGUge1N3YXRPYmplY3R9XG4gICAgICAgICAqL1xuICAgIGdldCBjYWxsZXIoKTogYWtpb21hLnN3YXQuU3dhdE9iamVjdCB7XG4gICAgICBpZiAoIXRoaXMuX2NvbnRyb2xsZXIuY2FsbGVyKVxuICAgICAgICByZXR1cm4gbnVsbDtcblxuICAgICAgaWYgKCF0aGlzLl9jYWxsZXIpXG4gICAgICAgIHRoaXMuX2NhbGxlciA9IGFraW9tYS5zd2F0LlN3YXRGYWN0b3J5LmNyZWF0ZVN3YXRPYmplY3QodGhpcy5fY29udHJvbGxlci5jYWxsZXIpO1xuXG4gICAgICByZXR1cm4gdGhpcy5fY2FsbGVyO1xuICAgIH1cblxuICAgIC8qKlxuXHQgICAgICogR2V0cyB0aGUgd2luZG93IHRpdGxlXG4gICAgICAgICAqIEByZWFkb25seVxuICAgICAgICAgKiBAdHlwZSB7c3RyaW5nfVxuXHQgICAgICovXG4gICAgZ2V0IHRpdGxlKCk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRUaXRsZSgpO1xuICAgIH1cblxuICAgIC8qKlxuXHQgICAgICogU2V0cyB0aGUgd2luZG93IHRpdGxlXG5cdCAgICAgKiBAdHlwZSB7c3RyaW5nfVxuXHQgICAgICovXG4gICAgc2V0IHRpdGxlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICAgIGNvbnN0IG9wdCA9IHRoaXMuX2NvbnRyb2xsZXIub3B0O1xuXG4gICAgICBpZiAodGhpcy5pc01haW5EZXNrdG9wV2luZG93IHx8IHRoaXMuaXNEZXNrdG9wV2luZG93KVxuICAgICAgICByZXR1cm47XG5cbiAgICAgIHRoaXMuY29udHJvbGxlci5zZXRUaXRsZSh2YWx1ZSk7XG5cbiAgICAgIGlmICghb3B0LnRpdGxlU2hvcnQpXG4gICAgICAgIHRoaXMuc2hvcnRUaXRsZSA9IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBUaGUgd2luZG93IHNob3J0IHRpdGxlIHVzZWQgaW4gdGhlIHRhc2sgYmFyXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqIE15V2luZG93LnNob3J0VGl0bGUgPSAnQW5nZWJvdCB7e3NlbGZub319JztcbiAgICAgICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgICAgICovXG4gICAgZ2V0IHNob3J0VGl0bGUoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLm9wdC50aXRsZVNob3J0IHx8IHRoaXMuX2NvbnRyb2xsZXIub3B0LlRJVExFO1xuICAgIH1cblxuICAgIHNldCBzaG9ydFRpdGxlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICAgIGNvbnN0IG9wdCA9IHRoaXMuX2NvbnRyb2xsZXIub3B0O1xuXG4gICAgICBvcHQudGl0bGVTaG9ydCA9IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsb3NlcyB0aGUgd2luZG93XG4gICAgICovXG4gICAgY2xvc2UoKSB7XG4gICAgICBpZiAodGhpcy5pc01haW5EZXNrdG9wV2luZG93IHx8IHRoaXMuaXNEZXNrdG9wV2luZG93KVxuICAgICAgICByZXR1cm47XG5cbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuY2xvc2UoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHNldHRpbmdcbiAgICAgKiBAcGFyYW0gY2xvc2luZ0JlaGF2aW91clxuICAgICAqL1xuICAgIHNldENsb3NpbmdCZWhhdmlvdXIoY2xvc2luZ0JlaGF2aW91cjogc3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldENsb3NpbmdCZWhhdmlvdXIoY2xvc2luZ0JlaGF2aW91cik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBnZXR0aW5nIGN1cnJlbnQgd2luZG93IGNsb3NpbmcgYmVoYXZpb3VyXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBnZXRDbG9zaW5nQmVoYXZpb3VyKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0Q2xvc2luZ0JlaGF2aW91cigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGJvdHRvbW1vc3Qgd2luZG93XG4gICAgICovXG4gICAgZ2V0Qm90dG9tbW9zdFdpbmRvdygpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldEJvdHRvbW1vc3RXaW5kb3coKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB0b3Btb3N0IHdpbmRvd1xuICAgICAqL1xuICAgIGdldFRvcG1vc3RXaW5kb3coKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRUb3Btb3N0V2luZG93KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzZXR0aW5nIGN1cnJlbnQgd2luZG93IGFjdGl2ZVxuICAgICAqL1xuICAgIHNldEFjdGl2ZVdpbmRvdygpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLnNldEFjdGl2ZVdpbmRvdygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgd2luZG93IGFzIHRvcCBtb3N0IHdpbmRvd1xuICAgICAqL1xuICAgIGJyaW5nVG9Ub3AoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5icmluZ1RvVG9wKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgdGhlIGN1c3RvbURhdGEgb2YgdGhlIHdpbmRvd1xuICAgICAgICAgKi9cbiAgICBnZXRDdXN0b21EYXRhKCk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRDdXN0b21EYXRhKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIGFuIHdpbmRvdyBtZXNzYWdlIGFuZCByZXR1cm4gdGhlIGluZGV4IG9mIHRoZSBtZXNzYWdlXG4gICAgICogQHBhcmFtICB7UGFuZWxNZXNzYWdlfSBtc2cgVGhlIHBhbmVsIG1lc3NhZ2VcbiAgICAgKiBAcGFyYW0gIHtzdHJpbmd9IG1zZy50ZXh0IFRoZSBwYW5lbCBtZXNzYWdlIHRleHRcbiAgICAgKiBAcGFyYW0gIHtzdHJpbmd9IG1zZy50eXBlIFRoZSBwYW5lbCBtZXNzYWdlIHR5cGUgaS5lLlxuICAgICAqIGluZm8sIHdhcm5pbmcsIGVycm9yLCBzdWNjZXNzXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlck9mIFdpbmRvd1xuICAgICAqIEByZXR1cm4ge251bWJlcn0gdGhlIGluZGV4IG9mIHRoZSBtZXNzYWdlXG4gICAgICovXG4gICAgYWRkV2luZG93TWVzc2FnZShtc2c6IFBhbmVsTWVzc2FnZSk6IG51bWJlciB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5hZGRXaW5kb3dNZXNzYWdlKG1zZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgd2luZG93IG1lc3NhZ2UgZnJvbSBhIGNvbnRyb2xsZXIgYnkgdGhlIGdpdmVuIGlkXG4gICAgICogQHBhcmFtICB7bnVtYmVyfSBpZFxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJPZiBXaW5kb3dcbiAgICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKi9cbiAgICByZW1vdmVXaW5kb3dNZXNzYWdlKGlkOiBudW1iZXIpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIucmVtb3ZlV2luZG93TWVzc2FnZShpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFsbCB3aW5kb3cgbWVzc2FnZXMgZnJvbSBhIGNvbnRyb2xsZXJcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyT2YgV2luZG93XG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgY2xlYXJXaW5kb3dNZXNzYWdlcygpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuY2xlYXJXaW5kb3dNZXNzYWdlcygpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uL1Zpc3VhbE9iamVjdC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogTmF2aWdhdGlvbiBPYmplY3QgQmFzZSBDbGFzc1xuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgTmF2aWdhdGlvbk9iamVjdFxuICAgICAqIEBleHRlbmRzIHtWaXN1YWxPYmplY3R9XG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBOYXZpZ2F0aW9uT2JqZWN0IGV4dGVuZHMgYWtpb21hLnN3YXQuVmlzdWFsT2JqZWN0IHtcblxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9OYXZpZ2F0aW9uT2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBSaWJib24gT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBSaWJib25cbiAgICAgKiBAZXh0ZW5kcyB7TmF2aWdhdGlvbk9iamVjdH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIFJpYmJvbiBleHRlbmRzIGFraW9tYS5zd2F0Lk5hdmlnYXRpb25PYmplY3Qge1xuXG4gICAgcHJpdmF0ZSBfaXRlbXM6IHN0cmluZ1tdID0gW107XG4gICAgcHJpdmF0ZSBfaXRlbXNNYXA6IGFueTtcblxuICAgIC8qKlxuICAgICAgICAgKiBUaGUgcmliYm9uIGl0ZW0gYW5kIGl0ZW1zIGJsb2NrIG5hbWVzXG4gICAgICAgICAqL1xuICAgIGdldCBpdGVtcygpOiBzdHJpbmdbXSB7XG4gICAgICBpZiAodGhpcy5faXRlbXMubGVuZ3RoID09PSAwKVxuICAgICAgICB0aGlzLl9zZXRJdGVtcygpO1xuXG4gICAgICByZXR1cm4gdGhpcy5faXRlbXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgaXRlbXNNYXAoKTogYW55IHtcbiAgICAgIGlmICh0aGlzLl9pdGVtcy5sZW5ndGggPT09IDApXG4gICAgICAgIHRoaXMuX3NldEl0ZW1zKCk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9pdGVtc01hcDtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9zZXRJdGVtcygpIHtcbiAgICAgIHRoaXMuX2l0ZW1zID0gT2JqZWN0LmtleXModGhpcy5fY29udHJvbGxlci5kaHguX2l0ZW1zKTtcbiAgICAgIHRoaXMuX2l0ZW1zTWFwID0ge307XG5cbiAgICAgIHRoaXMuX2l0ZW1zLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICAgIHRoaXMuX2l0ZW1zTWFwW2l0ZW0udG9Mb3dlckNhc2UoKV0gPSBpdGVtO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaXhOYW1lQ2FzaW5nKG5hbWU6IHN0cmluZykge1xuICAgICAgcmV0dXJuIHRoaXMuaXRlbXNNYXBbbmFtZS50b0xvd2VyQ2FzZSgpXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogUmV0dXJucyBvZiB0aGUgaXRlbSBvciBpdGVtcyBibG9jayBleGlzdHMgaW4gdGhlIHJpYmJvblxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbSBvciBpdGVtcyBibG9jayAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICovXG4gICAgaGFzSXRlbShuYW1lOiBzdHJpbmcpIHtcbiAgICAgIGlmICh0aGlzLml0ZW1zTWFwW25hbWUudG9Mb3dlckNhc2UoKV0pXG4gICAgICAgIHJldHVybiB0cnVlO1xuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIEhpZGVzIGEgcmliYm9uIGl0ZW0gb3IgaXRlbXMgYmxvY2tcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGl0ZW0gb3IgaXRlbXMgYmxvY2sgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICAgICAqL1xuICAgIGhpZGVJdGVtKG5hbWU6IHN0cmluZykge1xuICAgICAgbmFtZSA9IHRoaXMuZml4TmFtZUNhc2luZyhuYW1lKTtcbiAgICAgIGlmICghbmFtZSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLmRoeC5oaWRlKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBIaWRlcyBhIHJpYmJvbiBzdWJpdGVtXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpdGVtTmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHN1Yml0ZW1OYW1lIFRoZSBuYW1lIG9mIHRoZSBzdWJpdGVtIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAgICAgKi9cbiAgICBoaWRlU3ViaXRlbShpdGVtTmFtZTogc3RyaW5nLCBzdWJpdGVtTmFtZTogc3RyaW5nKSB7XG4gICAgICBpZiAoIWl0ZW1OYW1lIHx8ICFzdWJpdGVtTmFtZSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLmhpZGVTdWJpdGVtKGl0ZW1OYW1lLCBzdWJpdGVtTmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIFNob3dzIGEgcmliYm9uIGl0ZW0gb3IgaXRlbXMgYmxvY2tcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGl0ZW0gb3IgaXRlbXMgYmxvY2sgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICAgICAqL1xuICAgIHNob3dJdGVtKG5hbWU6IHN0cmluZykge1xuICAgICAgbmFtZSA9IHRoaXMuZml4TmFtZUNhc2luZyhuYW1lKTtcbiAgICAgIGlmICghbmFtZSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLmRoeC5zaG93KG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBTaG93cyBhIHJpYmJvbiBzdWJpdGVtXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpdGVtTmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHN1Yml0ZW1OYW1lIFRoZSBuYW1lIG9mIHRoZSBzdWJpdGVtIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAgICAgKi9cbiAgICBzaG93U3ViaXRlbShpdGVtTmFtZTogc3RyaW5nLCBzdWJpdGVtTmFtZTogc3RyaW5nKSB7XG4gICAgICBpZiAoIWl0ZW1OYW1lIHx8ICFzdWJpdGVtTmFtZSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNob3dTdWJpdGVtKGl0ZW1OYW1lLCBzdWJpdGVtTmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgcmliYm9uIGl0ZW0gb3IgaXRlbXMgYmxvY2sgaXMgdmlzaWJsZVxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbSBvciBpdGVtcyBibG9jayAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICovXG4gICAgaXNJdGVtVmlzaWJsZShuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgIG5hbWUgPSB0aGlzLmZpeE5hbWVDYXNpbmcobmFtZSk7XG4gICAgICBpZiAoIW5hbWUpIHJldHVybjtcblxuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZGh4LmlzVmlzaWJsZShuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogRW5hYmxlcyBhIHJpYmJvbiBpdGVtIG9yIGl0ZW1zIGJsb2NrXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBpdGVtIG9yIGl0ZW1zIGJsb2NrIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAgICAgKi9cbiAgICBlbmFibGVJdGVtKG5hbWU6IHN0cmluZykge1xuICAgICAgbmFtZSA9IHRoaXMuZml4TmFtZUNhc2luZyhuYW1lKTtcbiAgICAgIGlmICghbmFtZSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLmVuYWJsZUl0ZW0obmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIEVuYWJsZXMgYSByaWJib24gc3ViaXRlbVxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gaXRlbU5hbWUgVGhlIG5hbWUgb2YgdGhlIGl0ZW0gKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdWJpdGVtTmFtZSBUaGUgbmFtZSBvZiB0aGUgc3ViaXRlbSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICovXG4gICAgZW5hYmxlU3ViaXRlbShpdGVtTmFtZTogc3RyaW5nLCBzdWJpdGVtTmFtZTogc3RyaW5nKSB7XG4gICAgICBpZiAoIWl0ZW1OYW1lIHx8ICFzdWJpdGVtTmFtZSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLmVuYWJsZVN1Yml0ZW0oaXRlbU5hbWUsIHN1Yml0ZW1OYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogRGlzYWJsZXMgYSByaWJib24gaXRlbSBvciBpdGVtcyBibG9ja1xuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbSBvciBpdGVtcyBibG9jayAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICovXG4gICAgZGlzYWJsZUl0ZW0obmFtZTogc3RyaW5nKSB7XG4gICAgICBuYW1lID0gdGhpcy5maXhOYW1lQ2FzaW5nKG5hbWUpO1xuICAgICAgaWYgKCFuYW1lKSByZXR1cm47XG5cbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuZGlzYWJsZUl0ZW0obmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIERpc2FibGVzIGEgcmliYm9uIHN1Yml0ZW1cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGl0ZW1OYW1lIFRoZSBuYW1lIG9mIHRoZSBpdGVtIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3ViaXRlbU5hbWUgVGhlIG5hbWUgb2YgdGhlIHN1Yml0ZW0gKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICAgICAqL1xuICAgIGRpc2FibGVTdWJpdGVtKGl0ZW1OYW1lOiBzdHJpbmcsIHN1Yml0ZW1OYW1lOiBzdHJpbmcpIHtcbiAgICAgIGlmICghaXRlbU5hbWUgfHwgIXN1Yml0ZW1OYW1lKSByZXR1cm47XG5cbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuZGlzYWJsZVN1Yml0ZW0oaXRlbU5hbWUsIHN1Yml0ZW1OYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSByaWJib24gaXRlbSBvciBpdGVtcyBibG9jayBpcyBlbmFibGVkXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBpdGVtIG9yIGl0ZW1zIGJsb2NrIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAgICAgKi9cbiAgICBpc0l0ZW1FbmFibGVkKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgbmFtZSA9IHRoaXMuZml4TmFtZUNhc2luZyhuYW1lKTtcbiAgICAgIGlmICghbmFtZSkgcmV0dXJuO1xuXG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5kaHguaXNFbmFibGVkKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBHZXRzIHRoZSByaWJib24gaXRlbSBvciBpdGVtcyBibG9jayBsYWJlbFxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbSBvciBpdGVtcyBibG9jayAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICovXG4gICAgZ2V0SXRlbUxhYmVsKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICBuYW1lID0gdGhpcy5maXhOYW1lQ2FzaW5nKG5hbWUpO1xuICAgICAgaWYgKCFuYW1lKSByZXR1cm47XG5cbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldEl0ZW1UZXh0KG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBTZXRzIHRoZSByaWJib24gaXRlbSBvciBpdGVtcyBibG9jayBsYWJlbFxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbSBvciBpdGVtcyBibG9jayAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGxhYmVsIFRoZSBsYWJlbCB0byBzZXRcbiAgICAgICAgICogQHBhcmFtIHtib29sZWFufSBzZXRUb29sdGlwIFNldCB0b29sdGlwIHdpdGggdGhlIHNhbWUgdmFsdWUgYXMgdGhlIGxhYmVsIChkZWZhdWx0IGlzIGZhbHNlKVxuICAgICAgICAgKi9cbiAgICBzZXRJdGVtTGFiZWwobmFtZTogc3RyaW5nLCBsYWJlbDogc3RyaW5nLCBzZXRUb29sdGlwID0gZmFsc2UpIHtcbiAgICAgIG5hbWUgPSB0aGlzLmZpeE5hbWVDYXNpbmcobmFtZSk7XG4gICAgICBpZiAoIW5hbWUpIHJldHVybjtcblxuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRJdGVtVGV4dChuYW1lLCBsYWJlbCk7XG5cbiAgICAgIGlmIChzZXRUb29sdGlwKVxuICAgICAgICB0aGlzLnNldEl0ZW1Ub29sdGlwKG5hbWUsIGxhYmVsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogR2V0cyB0aGUgcmliYm9uIGl0ZW0gb3IgaXRlbXMgYmxvY2sgdG9vbHRpcFxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbSBvciBpdGVtcyBibG9jayAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICovXG4gICAgZ2V0SXRlbVRvb2x0aXAobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgIG5hbWUgPSB0aGlzLmZpeE5hbWVDYXNpbmcobmFtZSk7XG4gICAgICBpZiAoIW5hbWUpIHJldHVybjtcblxuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0SXRlbVRvb2xUaXAobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIFNldHMgdGhlIHJpYmJvbiBpdGVtIG9yIGl0ZW1zIGJsb2NrIHRvb2x0aXBcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGl0ZW0gb3IgaXRlbXMgYmxvY2sgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0b29sdGlwIFRoZSB0b29sdGlwIHRvIHNldFxuICAgICAgICAgKi9cbiAgICBzZXRJdGVtVG9vbHRpcChuYW1lOiBzdHJpbmcsIHRvb2x0aXA6IHN0cmluZykge1xuICAgICAgbmFtZSA9IHRoaXMuZml4TmFtZUNhc2luZyhuYW1lKTtcbiAgICAgIGlmICghbmFtZSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEl0ZW1Ub29sVGlwKG5hbWUsIHRvb2x0aXApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBHZXRzIHRoZSByaWJib24gaXRlbSBieSB0aGUgbmFtZVxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbSBvciBibG9jayAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgICAgICovXG4gICAgZ2V0SXRlbShuYW1lOiBzdHJpbmcpIDogYW55IHtcbiAgICAgIG5hbWUgPSB0aGlzLmZpeE5hbWVDYXNpbmcobmFtZSk7XG4gICAgICBpZiAoIW5hbWUpIHJldHVybjtcblxuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0SXRlbUJ5SWQobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgICAqIEdldHMgdGhlIHNlbGVjdGVkIG9wdGlvbiBmcm9tIGEgUmliYm9uQ29tYm9cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGNvbWJvIGl0ZW0gKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICAgICAqL1xuICAgIGdldFNlbGVjdGVkT3B0aW9uKG5hbWU6IHN0cmluZykgOiBhbnkge1xuICAgICAgY29uc3QgY29tYm8gPSB0aGlzLmdldEl0ZW0obmFtZSk7XG4gICAgICBpZiAoY29tYm8gJiYgY29tYm8uY29udHJvbGxlci52aWV3ID09PSAncmliYm9uY29tYm8nKVxuICAgICAgICByZXR1cm4gY29tYm8uY29udHJvbGxlci5nZXRTZWxlY3RlZE9wdGlvbigpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9OYXZpZ2F0aW9uT2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuXG4gIC8qKlxuICAgICAqIFRvb2xiYXIgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBUb29sYmFyXG4gICAgICogQGV4dGVuZHMge05hdmlnYXRpb25PYmplY3R9XG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBUb29sYmFyIGV4dGVuZHMgYWtpb21hLnN3YXQuTmF2aWdhdGlvbk9iamVjdCB7XG4gICAgcHJpdmF0ZSBfaXRlbXM6IHN0cmluZ1tdID0gW107XG4gICAgcHJpdmF0ZSBfaXRlbXNNYXA6IGFueTtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0b29sYmFyIGl0ZW0gYW5kIGl0ZW1zXG4gICAgICovXG4gICAgZ2V0IGl0ZW1zKCk6IHN0cmluZ1tdIHtcbiAgICAgIGlmICh0aGlzLl9pdGVtcy5sZW5ndGggPT09IDApXG4gICAgICAgIHRoaXMuX3NldEl0ZW1zKCk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9pdGVtcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHR5cGVkIHRleHQgaW5zaWRlIHRoZSB0b29sYmFyIGlucHV0LlxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJvZiBUb29sYmFyXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQgdHlwZWRWYWx1ZSgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIudHlwZWRWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGlucHV0IG5hbWUgb2YgdGhlIHRvb2xiYXIgaXRlbSB0aGF0IHdhcyB0eXBlZCBpbi5cbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgVG9vbGJhclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZ2V0IGlucHV0TmFtZSgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuaW5wdXROYW1lO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IGl0ZW1zTWFwKCk6IGFueSB7XG4gICAgICBpZiAodGhpcy5faXRlbXMubGVuZ3RoID09PSAwKVxuICAgICAgICB0aGlzLl9zZXRJdGVtcygpO1xuXG4gICAgICByZXR1cm4gdGhpcy5faXRlbXNNYXA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfc2V0SXRlbXMoKSB7XG4gICAgICBjb25zdCBpdGVtcyA9IE9iamVjdC5rZXlzKHRoaXMuX2NvbnRyb2xsZXIuZGh4Lm9ialB1bGwpO1xuICAgICAgdGhpcy5faXRlbXNNYXAgPSB7fTtcblxuICAgICAgZm9yIChjb25zdCBpIGluIGl0ZW1zKSB7XG4gICAgICAgIGNvbnN0IGtleTpzdHJpbmcgPSBpdGVtc1tpXS5yZXBsYWNlKHRoaXMuX2NvbnRyb2xsZXIuZGh4LmlkUHJlZml4LCAnJyk7XG5cbiAgICAgICAgdGhpcy5faXRlbXMucHVzaChrZXkpO1xuICAgICAgfVxuXG5cbiAgICAgIHRoaXMuX2l0ZW1zLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICAgIHRoaXMuX2l0ZW1zTWFwW2l0ZW0udG9Mb3dlckNhc2UoKV0gPSBpdGVtO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaXhOYW1lQ2FzaW5nKG5hbWU6IHN0cmluZykge1xuICAgICAgcmV0dXJuIHRoaXMuaXRlbXNNYXBbbmFtZS50b0xvd2VyQ2FzZSgpXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbmFibGVzIGEgdG9vbGJhciBpdGVtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGl0ZW1cbiAgICAgKi9cbiAgICBlbmFibGVJdGVtKG5hbWU6IHN0cmluZykge1xuICAgICAgbmFtZSA9IHRoaXMuZml4TmFtZUNhc2luZyhuYW1lKTtcbiAgICAgIGlmICghbmFtZSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLmVuYWJsZUl0ZW0obmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGlzYWJsZXMgYSB0b29sYmFyIGl0ZW1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaXRlbVxuICAgICAqL1xuICAgIGRpc2FibGVJdGVtKG5hbWU6IHN0cmluZykge1xuICAgICAgbmFtZSA9IHRoaXMuZml4TmFtZUNhc2luZyhuYW1lKTtcbiAgICAgIGlmICghbmFtZSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9jb250cm9sbGVyLmRpc2FibGVJdGVtKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhpZGVzIGEgdG9vbGJhciBpdGVtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGl0ZW1cbiAgICAgKi9cbiAgICBoaWRlSXRlbShuYW1lOiBzdHJpbmcpIHtcbiAgICAgIG5hbWUgPSB0aGlzLmZpeE5hbWVDYXNpbmcobmFtZSk7XG4gICAgICBpZiAoIW5hbWUpIHJldHVybjtcblxuICAgICAgdGhpcy5fY29udHJvbGxlci5oaWRlSXRlbShuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93cyBhIHRvb2xiYXIgaXRlbVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBpdGVtXG4gICAgICovXG4gICAgc2hvd0l0ZW0obmFtZTogc3RyaW5nKSB7XG4gICAgICBuYW1lID0gdGhpcy5maXhOYW1lQ2FzaW5nKG5hbWUpO1xuICAgICAgaWYgKCFuYW1lKSByZXR1cm47XG5cbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2hvd0l0ZW0obmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdG9vbGJhciBpdGVtIGJ5IHRoZSBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGl0ZW0gKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICovXG4gICAgZ2V0SXRlbShuYW1lOiBzdHJpbmcpIDogYW55IHtcbiAgICAgIG5hbWUgPSB0aGlzLmZpeE5hbWVDYXNpbmcobmFtZSk7XG4gICAgICBpZiAoIW5hbWUpIHJldHVybjtcblxuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0SXRlbUJ5SWQobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgc2VsZWN0ZWQgb3B0aW9uIGZyb20gYSBUb29sYmFyQ29tYm9cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgY29tYm8gaXRlbSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZE9wdGlvbihuYW1lOiBzdHJpbmcpIDogYW55IHtcbiAgICAgIGNvbnN0IGNvbWJvID0gdGhpcy5nZXRJdGVtKG5hbWUpO1xuICAgICAgaWYgKGNvbWJvICYmIGNvbWJvLnZpZXcgPT09ICd0b29sYmFyY29tYm8nKVxuICAgICAgICByZXR1cm4gY29tYm8uZ2V0U2VsZWN0ZWRPcHRpb24oKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uL05hdmlnYXRpb25PYmplY3QudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBUYWJiYXIgT2JqZWN0XG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIFRhYmJhclxuICAgKiBAZXh0ZW5kcyB7TmF2aWdhdGlvbk9iamVjdH1cbiAgICovXG4gIGV4cG9ydCBjbGFzcyBUYWJiYXIgZXh0ZW5kcyBha2lvbWEuc3dhdC5OYXZpZ2F0aW9uT2JqZWN0IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0YWJiYXIgY3VycmVudCBwYWdlIG51bWJlclxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0IGN1cnJlbnRQYWdlTnVtKCk6IG51bWJlciB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5jdXJyZW50UGFnZU51bSgpO1xuICAgIH1cblxuICAgIHNldCBjdXJyZW50UGFnZU51bSh2YWx1ZTogbnVtYmVyKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEFjdGl2ZVBhZ2UodmFsdWUsIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSB0YWJiYXIgY3VycmVudCBwYWdlIGtleVxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICovXG4gICAgZ2V0IGN1cnJlbnRQYWdlS2V5KCk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5jdXJyZW50UGFnZUtleSgpO1xuICAgIH1cblxuICAgIHNldCBjdXJyZW50UGFnZUtleSh2YWx1ZTogc3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEFjdGl2ZVBhZ2UodmFsdWUsIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBwYWdlIG9iamVjdFxuICAgICAqIEBwYXJhbSAge3N0cmluZ3xpbnRlZ2VyfSBwYWdlTnVtIFRoZSBwYWdlIGtleSBvciBudW1iZXJcbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fVxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqL1xuICAgIGdldFBhZ2VPYmplY3QocGFnZU51bTogbnVtYmVyIHwgc3RyaW5nKTogYWtpb21hLnN3YXQuVGFiYmFyIHwgYWtpb21hLnN3YXQuU2lkZWJhciB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRQYWdlKHBhZ2VOdW0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBwYWdlIGxhYmVsXG4gICAgICogQHBhcmFtIHtzdHJpbmd8aW50ZWdlcn0gcGFnZU51bSBUaGUgcGFnZSBrZXkgb3IgbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsYWJlbCBUaGUgbGFiZWwgdG8gYmUgc2V0LlxuICAgICAqL1xuICAgIHNldFBhZ2VMYWJlbChwYWdlTnVtOiBudW1iZXIgfCBzdHJpbmcsIGxhYmVsOiBzdHJpbmcpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0UGFnZUxhYmVsKHBhZ2VOdW0sIGxhYmVsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgcGFnZSBsYWJlbFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfGludGVnZXJ9IHBhZ2VOdW0gVGhlIHBhZ2Uga2V5IG9yIG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgbGFiZWwgb2YgdGhlIHBhZ2UuXG4gICAgICovXG4gICAgZ2V0UGFnZUxhYmVsKHBhZ2VOdW06IG51bWJlciB8IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRQYWdlTGFiZWwocGFnZU51bSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyBvciBkaXNhYmxlcyBhIHBhZ2VcbiAgICAgKiBAcGFyYW0gcGFnZU51bSBUaGUgcGFnZSBrZXkgb3IgbnVtYmVyXG4gICAgICogQHBhcmFtIGVuYWJsZWQgVGhlIGVuYWJsZSBtb2RlXG4gICAgICovXG4gICAgc2V0UGFnZUVuYWJsZWQocGFnZU51bTogbnVtYmVyIHwgc3RyaW5nLCBlbmFibGVkOiBib29sZWFuKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldFBhZ2VFbmFibGVkKHBhZ2VOdW0sIGVuYWJsZWQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgaWYgYSBwYWdlIGlzIGVuYWJsZWRcbiAgICAgKiBAcGFyYW0gcGFnZU51bSBUaGUgcGFnZSBrZXkgb3IgbnVtYmVyXG4gICAgICovXG4gICAgaXNQYWdlRW5hYmxlZChwYWdlTnVtOiBudW1iZXIgfCBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmlzUGFnZUVuYWJsZWQocGFnZU51bSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hvd3Mgb3IgaGlkZXMgYSBwYWdlXG4gICAgICogQHBhcmFtIHBhZ2VOdW0gVGhlIHBhZ2Uga2V5IG9yIG51bWJlclxuICAgICAqIEBwYXJhbSB2aXNpYmxlIFRoZSB2aXNpYmxlIG1vZGVcbiAgICAgKi9cbiAgICBzZXRQYWdlVmlzaWJsZShwYWdlTnVtOiBudW1iZXIgfCBzdHJpbmcsIHZpc2libGU6IGJvb2xlYW4pIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0UGFnZVZpc2libGUocGFnZU51bSwgdmlzaWJsZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBpZiBhIHBhZ2UgaXMgdmlzaWJsZVxuICAgICAqIEBwYXJhbSBwYWdlTnVtIFRoZSBwYWdlIGtleSBvciBudW1iZXJcbiAgICAgKi9cbiAgICBpc1BhZ2VWaXNpYmxlKHBhZ2VOdW06IG51bWJlciB8IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuaXNQYWdlVmlzaWJsZShwYWdlTnVtKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGEgcGFnZSBhcyBhY3RpdmVcbiAgICAgKiBAcGFyYW0gcGFnZU51bSBUaGUgcGFnZSBrZXkgb3IgbnVtYmVyXG4gICAgICogQHBhcmFtIGZvY3VzZWQgVGhlIGZvY3VzIG1vZGVcbiAgICAgKi9cbiAgICBzZXRQYWdlQWN0aXZlKHBhZ2VOdW06IG51bWJlciB8IHN0cmluZywgZm9jdXNlZCA9IHRydWUpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0QWN0aXZlUGFnZShwYWdlTnVtLCBmb2N1c2VkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlcmUgYXJlIGNoYW5nZXMgaW4gdGhlIHBhZ2Ugb3IgaXRzIGRlc2NlbmRlbnRzXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaGFzUGFnZUNoYW5nZXMocGFnZU51bTogbnVtYmVyIHwgc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5oYXNQYWdlQ2hhbmdlcyhwYWdlTnVtKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXByZWNhdGVkIG1ldGhvZCBmb3IgZmluZGluZyBhIHBhZ2UgYnkgaW5kZXggb3IgcGFnZWtleVxuICAgICAqIEBkZXByZWNhdGVkXG4gICAgICogQHBhcmFtICB7c3RyaW5nfGludGVnZXJ9IHZhbHVlIGluZGV4IG9yIFBhZ2VLZXlcbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fVxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqL1xuICAgIGZldGNoUGFnZSh2YWx1ZTogc3RyaW5nfG51bWJlcik6IGFraW9tYS5zd2F0LlRhYmJhciB8IGFraW9tYS5zd2F0LlNpZGViYXIge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0UGFnZSh2YWx1ZSk7XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9UYWJiYXIudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIFNpZGViYXIgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBTaWRlYmFyXG4gICAgICogQGV4dGVuZHMge05hdmlnYXRpb25PYmplY3R9XG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBTaWRlYmFyIGV4dGVuZHMgYWtpb21hLnN3YXQuTmF2aWdhdGlvbk9iamVjdCB7XG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzZXR0aW5nIHRoZSBtZW51IGlkIGZvciBzaWRlYmFyIGl0ZW1zXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lbnVJZCBNZW51IHN0cnVjdHVyZSBpZFxuICAgICAqL1xuICAgIHNldE1lbnUobWVudUlkOiBzdHJpbmcpIHtcbiAgICAgIHRoaXMuY29udHJvbGxlci5zZXRNZW51KG1lbnVJZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRvIHNlbGVjdCBzaWRlYmFyIGl0ZW1cbiAgICAgKiBAcGFyYW0gaWQgSW5kZXggb2YgaXRlbVxuICAgICAqL1xuICAgIHNlbGVjdEl0ZW0oaWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgcmV0dXJuIHRoaXMuY29udHJvbGxlci5zZWxlY3RJdGVtKGlkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgcmV0dXJucyB0cnVlIGlmIGl0ZW0gaXMgdmlzaWJsZSBvbiBzY3JlZW5cbiAgICAgKiBAcGFyYW0gaWQgSXRlbSBpZFxuICAgICAqL1xuICAgIGlzSXRlbVZpc2libGUoaWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuY29udHJvbGxlci5pc0l0ZW1WaXNpYmxlKGlkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdG8gY29sbGFwc2UgaXRlbSBieSBpbmRleFxuICAgICAqIEBwYXJhbSBpZCBJbmRleCBvZiBpdGVtXG4gICAgICovXG4gICAgY29sbGFwc2VJdGVtKGlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIHJldHVybiB0aGlzLmNvbnRyb2xsZXIuY29sbGFwc2VJdGVtKGlkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdG8gZXhwYW5kIGl0ZW0gYnkgaW5kZXhcbiAgICAgKiBAcGFyYW0gaWQgSW5kZXggb2YgaXRlbVxuICAgICAqL1xuICAgIGV4cGFuZEl0ZW0oaWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgcmV0dXJuIHRoaXMuY29udHJvbGxlci5leHBhbmRJdGVtKGlkKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi9WaXN1YWxPYmplY3QudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuICAvKipcbiAgICogUGFuZWwgQmFzZSBDbGFzc1xuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBQYW5lbFxuICAgKiBAZXh0ZW5kcyB7VmlzdWFsT2JqZWN0fVxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIFBhbmVsU3dpdGNoZXJPYmplY3QgZXh0ZW5kcyBha2lvbWEuc3dhdC5WaXN1YWxPYmplY3Qge1xuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgZ2V0dGluZyBhIHBhbmVsIHZpZXcgZnJhbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmlld05hbWUgVGhlIG5hbWUgb2YgdGhlIHZpZXdcbiAgICAgKi9cbiAgICBnZXRWaWV3RnJhbWUodmlld05hbWU6IHN0cmluZyk6IGFraW9tYS5zd2F0LkZyYW1lIHwgbnVsbCB7XG4gICAgICBjb25zdCB2aWV3RnJhbWUgPSB0aGlzLmNvbnRyb2xsZXIuZ2V0Vmlld0ZyYW1lKHZpZXdOYW1lKTtcblxuICAgICAgaWYgKCF2aWV3RnJhbWUpXG4gICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICByZXR1cm4gYWtpb21hLnN3YXQuU3dhdEZhY3RvcnkuY3JlYXRlU3dhdE9iamVjdCh2aWV3RnJhbWUpIGFzIGFraW9tYS5zd2F0LkZyYW1lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGFjdGl2ZSBmcmFtZSB2aWV3XG4gICAgICogQHJldHVybnMge2FraW9tYS5zd2F0LkZyYW1lIHwgbnVsbH0gVGhlIGFjdGl2ZSBmcmFtZSB2aWV3XG4gICAgICovXG4gICAgZ2V0QWN0aXZlRnJhbWVWaWV3KCk6IGFraW9tYS5zd2F0LkZyYW1lIHwgbnVsbCB7XG4gICAgICBjb25zdCBhY3RpdmVWaWV3RnJhbWUgPSB0aGlzLmNvbnRyb2xsZXIuZ2V0QWN0aXZlRnJhbWVWaWV3KCk7XG5cbiAgICAgIGlmKCFhY3RpdmVWaWV3RnJhbWUpXG4gICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICByZXR1cm4gYWtpb21hLnN3YXQuU3dhdEZhY3RvcnkuY3JlYXRlU3dhdE9iamVjdChhY3RpdmVWaWV3RnJhbWUpIGFzIGFraW9tYS5zd2F0LkZyYW1lO1xuICAgIH1cblxuICAgIC8qKlxuXHRcdCAqIFN3aXRjaGVzIHRoZSB2aWV3IG9mIGEgcGFuZWwgb2JqZWN0IHRvIHRoZSBzcGVjaWZpZWQgdmlld1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2aWV3TmFtZSBUaGUgbmFtZSBvZiB0aGUgb2JqZWN0XG4gICAgICogQHBhcmFtIHtha2lvbWEuc3dhdC5MYXVuY2hDb250YWluZXJPcHRpb25zfSBbb3B0aW9uc10gVGhlIG9wdGlvbnMgZm9yIHRoZSB2aWV3XG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlck9mIFBhbmVsXG4gICAgICogQHJldHVybnMge1Byb21pc2U8YWtpb21hLnN3YXQuRnJhbWU+fSBUaGUgZnJhbWUgb2JqZWN0XG5cdFx0ICovXG4gICAgYXN5bmMgc3dpdGNoVmlldyh2aWV3TmFtZTogc3RyaW5nLCBvcHRpb25zPzogYWtpb21hLnN3YXQuTGF1bmNoQ29udGFpbmVyT3B0aW9ucyk6IFByb21pc2U8YWtpb21hLnN3YXQuRnJhbWU+IHtcbiAgICAgIGlmIChvcHRpb25zKVxuICAgICAgICBvcHRpb25zID0gYWtpb21hLnN3YXQuQXBwLmNvbnZlcnRMYXVuY2hDb250YWluZXJQYXJhbXMob3B0aW9ucyk7XG5cbiAgICAgIGNvbnN0IGZyYW1lID0gYXdhaXQgdGhpcy5jb250cm9sbGVyLnN3aXRjaFZpZXcodmlld05hbWUsIG9wdGlvbnMpO1xuICAgICAgY29uc3QgZnJhbWVPYmplY3QgPSBha2lvbWEuc3dhdC5Td2F0RmFjdG9yeS5jcmVhdGVTd2F0T2JqZWN0KGZyYW1lKSBhcyBha2lvbWEuc3dhdC5GcmFtZTtcbiAgICAgIHJldHVybiBmcmFtZU9iamVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXRlcm1pbmUgaWYgcHJvdmlkZWQgdmlldyBuYW1lIGlzIGxvYWRlZFxuICAgICAqIEBwYXJhbSB2aWV3TmFtZSBWaWV3IG5hbWVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2aWV3IGlzIGxvYWRlZFxuICAgICAqL1xuICAgIGhhc1ZpZXdMb2FkZWQodmlld05hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuY29udHJvbGxlci5oYXNWaWV3TG9hZGVkKHZpZXdOYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHZpZXcgbmFtZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjdXJyZW50IHZpZXcgbmFtZVxuICAgICAqL1xuICAgIGdldEN1cnJlbnRWaWV3KCk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gdGhpcy5jb250cm9sbGVyLmdldEN1cnJlbnRWaWV3KCk7XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9QYW5lbFN3aXRjaGVyT2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICogUGFuZWwgQmFzZSBDbGFzc1xuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBQYW5lbFxuICAgKiBAZXh0ZW5kcyB7VmlzdWFsT2JqZWN0fVxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIFBhbmVsIGV4dGVuZHMgYWtpb21hLnN3YXQuUGFuZWxTd2l0Y2hlck9iamVjdCB7XG5cbiAgICBwcml2YXRlIF9wYW5lbENvbnRyb2xsZXI6IGFueTtcbiAgICBwcml2YXRlIF9wYW5lbERoeDogYW55O1xuXG4gICAgcHJpdmF0ZSBfbGFzdENvbGxhcHNlZDogYm9vbGVhbjtcbiAgICBwcml2YXRlIF9sYXN0SGVhZGVyVmlzaWJsZTogYm9vbGVhbjtcbiAgICBwcml2YXRlIF9sYXN0V2lkdGg6IG51bWJlcjtcbiAgICBwcml2YXRlIF9sYXN0SGVpZ2h0OiBudW1iZXI7XG4gICAgcHJpdmF0ZSBfbGFzdE1pbldpZHRoOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBfbGFzdE1pbkhlaWdodDogbnVtYmVyO1xuXG4gICAgcHJpdmF0ZSBnZXQgcGFuZWxDb250cm9sbGVyKCk6IGFueSB7XG4gICAgICBpZiAoIXRoaXMuX3BhbmVsQ29udHJvbGxlcilcbiAgICAgICAgdGhpcy5fc2V0UGFuZWxPYmplY3QoKTtcblxuICAgICAgcmV0dXJuIHRoaXMuX3BhbmVsQ29udHJvbGxlcjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldCBwYW5lbERoeCgpOiBhbnkge1xuICAgICAgaWYgKCF0aGlzLl9wYW5lbERoeClcbiAgICAgICAgdGhpcy5fc2V0UGFuZWxPYmplY3QoKTtcblxuICAgICAgcmV0dXJuIHRoaXMuX3BhbmVsRGh4O1xuICAgIH1cblxuICAgIHByaXZhdGUgX3NldFBhbmVsT2JqZWN0KCkge1xuICAgICAgaWYgKHRoaXMuX2NvbnRyb2xsZXIudmlldyA9PT0gJ3BhbmVsJykge1xuICAgICAgICB0aGlzLl9wYW5lbENvbnRyb2xsZXIgPSB0aGlzLl9jb250cm9sbGVyO1xuICAgICAgICB0aGlzLl9wYW5lbERoeCA9IHRoaXMuX2NvbnRyb2xsZXIuZGh4O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGV0IHBhbmVsID0gdGhpcy5fY29udHJvbGxlci5wYXJlbnQ7XG5cbiAgICAgICAgd2hpbGUgKHBhbmVsICYmIHBhbmVsLnZpZXcgIT09ICdwYW5lbCcpXG4gICAgICAgICAgcGFuZWwgPSBwYW5lbC5wYXJlbnQ7XG5cbiAgICAgICAgdGhpcy5fcGFuZWxDb250cm9sbGVyID0gcGFuZWw7XG4gICAgICAgIHRoaXMuX3BhbmVsRGh4ID0gcGFuZWwuZGh4O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRvZG86IGhpZGluZyBwYW5lbCB3aWxsIG9ubHkgd29yayB3aXRoIG11bHRpcGxlIHBhbmVsc1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBhbmVsIGhpZGRlbiBtb2RlIGlmIGl0IGlzIGhpZGRlbiBvciBzaG93blxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldCBoaWRkZW4oKTogYm9vbGVhbiB7XG4gICAgICBjb25zdCBkaHggPSB0aGlzLnBhbmVsRGh4O1xuXG4gICAgICByZXR1cm4gKCFkaHguaXNIZWFkZXJWaXNpYmxlKCkgJiYgKGRoeC5nZXRXaWR0aCgpID09PSAwIHx8IGRoeC5nZXRIZWlnaHQoKSA9PT0gMCkpO1xuICAgIH1cblxuICAgIHNldCBoaWRkZW4odmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgIGlmICh2YWx1ZSA9PT0gdGhpcy5oaWRkZW4pXG4gICAgICAgIHJldHVybjtcblxuICAgICAgY29uc3QgZGh4ID0gdGhpcy5wYW5lbERoeDtcblxuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2xhc3RDb2xsYXBzZWQgPSB0aGlzLmNvbGxhcHNlZDtcbiAgICAgICAgdGhpcy5fbGFzdEhlYWRlclZpc2libGUgPSBkaHguaXNIZWFkZXJWaXNpYmxlKCk7XG5cbiAgICAgICAgaWYgKGRoeC5jb25mLm1vZGUgPT09ICdoJykge1xuICAgICAgICAgIHRoaXMuX2xhc3RNaW5IZWlnaHQgPSBkaHguX2dldE1pbkhlaWdodCgpO1xuICAgICAgICAgIHRoaXMuX2xhc3RIZWlnaHQgPSBkaHguZ2V0SGVpZ2h0KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fbGFzdE1pbldpZHRoID0gZGh4Ll9nZXRNaW5XaWR0aCgpO1xuICAgICAgICAgIHRoaXMuX2xhc3RXaWR0aCA9IGRoeC5nZXRXaWR0aCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhlIHBhbmVsIG11c3QgYmUgZXhwYW5kZWQgdG8gaGlkZSBpdHMgaGVhZGVyIGFuZCBtaW5pbWl6ZSBpdFxuICAgICAgICBpZiAodGhpcy5fbGFzdENvbGxhcHNlZClcbiAgICAgICAgICB0aGlzLmNvbGxhcHNlZCA9IGZhbHNlO1xuXG4gICAgICAgIGlmICh0aGlzLl9sYXN0SGVhZGVyVmlzaWJsZSlcbiAgICAgICAgICBkaHguaGlkZUhlYWRlcigpO1xuXG4gICAgICAgIGlmIChkaHguY29uZi5tb2RlID09PSAnaCcpIHtcbiAgICAgICAgICBkaHguc2V0TWluSGVpZ2h0KDApO1xuICAgICAgICAgIGRoeC5zZXRIZWlnaHQoMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGh4LnNldE1pbldpZHRoKDApO1xuICAgICAgICAgIGRoeC5zZXRXaWR0aCgwKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGRoeC5jb25mLm1vZGUgPT09ICdoJykge1xuICAgICAgICAgIGRoeC5zZXRNaW5IZWlnaHQodGhpcy5fbGFzdE1pbkhlaWdodCk7XG4gICAgICAgICAgZGh4LnNldEhlaWdodCh0aGlzLl9sYXN0SGVpZ2h0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkaHguc2V0TWluV2lkdGgodGhpcy5fbGFzdE1pbldpZHRoKTtcbiAgICAgICAgICBkaHguc2V0V2lkdGgodGhpcy5fbGFzdFdpZHRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRoZSBoZWFkZXIgaXMgc2hvd24gYXQgdGhlIGVuZFxuICAgICAgICAvLyBiZWNhdXNlIHRoZSBoZWFkZXIgY2Fubm90IGJlIHNob3duIGlmIHdpZHRoL2hlaWdodCBpcyAwXG4gICAgICAgIGlmICh0aGlzLl9sYXN0SGVhZGVyVmlzaWJsZSlcbiAgICAgICAgICBkaHguc2hvd0hlYWRlcigpO1xuXG4gICAgICAgIC8vIHRoZSBwYW5lbCBpcyBjb2xsYXBzZWQgYXQgdGhlIGVuZFxuICAgICAgICAvLyBiZWNhdXNlIHRoZSBwYW5lbCBtdXN0IGJlIGV4cGFuZGVkIHRvIHNob3cgaXRzIGhlYWRlciBhbmQgbWF4aW1pemUgaXRcbiAgICAgICAgaWYgKHRoaXMuX2xhc3RDb2xsYXBzZWQpXG4gICAgICAgICAgdGhpcy5jb2xsYXBzZWQgPSB0aGlzLl9sYXN0Q29sbGFwc2VkO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBwYW5lbCB2aXNpYmxlIG1vZGUgKG9wcG9zaXRlIG9mIGhpZGRlbilcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQgdmlzaWJsZSgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiAhdGhpcy5oaWRkZW47XG4gICAgfVxuXG4gICAgc2V0IHZpc2libGUodmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgIHRoaXMuaGlkZGVuID0gIXZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBwYW5lbCBjb2xsYXBzZWQgbW9kZSBpZiBpdCBpcyBjb2xsYXBzZWQgb3IgZXhwYW5kZWRcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQgY29sbGFwc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMucGFuZWxEaHguaXNDb2xsYXBzZWQoKTtcbiAgICB9XG5cbiAgICBzZXQgY29sbGFwc2VkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICBpZiAodmFsdWUpXG4gICAgICAgIHRoaXMucGFuZWxEaHguY29sbGFwc2UoKTtcbiAgICAgIGVsc2VcbiAgICAgICAgdGhpcy5wYW5lbERoeC5leHBhbmQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGFuZWwgd2lkdGhcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuICAgIGdldCB3aWR0aCgpOiBudW1iZXIge1xuICAgICAgcmV0dXJuIHRoaXMucGFuZWxEaHguZ2V0V2lkdGgoKTtcbiAgICB9XG5cbiAgICBzZXQgd2lkdGgodmFsdWU6IG51bWJlcikge1xuICAgICAgaWYgKHRoaXMuY29sbGFwc2VkKVxuICAgICAgICB0aGlzLmNvbGxhcHNlZCA9IGZhbHNlO1xuXG4gICAgICBjb25zdCBkaHggPSB0aGlzLnBhbmVsRGh4O1xuXG4gICAgICBkaHguc2hvd0hlYWRlcigpO1xuXG4gICAgICBpZiAodmFsdWUgPiAwKSB7XG4gICAgICAgIGRoeC5zZXRNaW5XaWR0aCgyMCk7XG4gICAgICAgIGRoeC5zZXRXaWR0aChNYXRoLm1heCh2YWx1ZSwgMjApKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRoeC5zZXRNaW5XaWR0aCgwKTtcbiAgICAgICAgZGh4LnNldFdpZHRoKDApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBwYW5lbCBoZWlnaHRcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuICAgIGdldCBoZWlnaHQoKTogbnVtYmVyIHtcbiAgICAgIHJldHVybiB0aGlzLnBhbmVsRGh4LmdldEhlaWdodCgpO1xuICAgIH1cblxuICAgIHNldCBoZWlnaHQodmFsdWU6IG51bWJlcikge1xuICAgICAgaWYgKHRoaXMuY29sbGFwc2VkKVxuICAgICAgICB0aGlzLmNvbGxhcHNlZCA9IGZhbHNlO1xuXG4gICAgICBjb25zdCBkaHggPSB0aGlzLnBhbmVsRGh4O1xuXG4gICAgICBkaHguc2hvd0hlYWRlcigpO1xuXG4gICAgICBpZiAodmFsdWUgPiAwKSB7XG4gICAgICAgIGRoeC5zZXRNaW5IZWlnaHQoMjApO1xuICAgICAgICBkaHguc2V0SGVpZ2h0KE1hdGgubWF4KHZhbHVlLCAyMCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGh4LnNldE1pbkhlaWdodCgwKTtcbiAgICAgICAgZGh4LnNldEhlaWdodCgwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGFuZWwgdGl0bGVcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuICAgIGdldCB0aXRsZSgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIHRoaXMucGFuZWxDb250cm9sbGVyLm9wdC50aXRsZTtcbiAgICB9XG5cbiAgICBzZXQgdGl0bGUodmFsdWU6IHN0cmluZykge1xuICAgICAgdGhpcy5wYW5lbENvbnRyb2xsZXIuc2V0T3B0aW9uKCd0aXRsZScsIHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcblx0XHQgKiBNZXRob2QgZm9yIHNldHRpbmcgdGhlIHByb2dyZXNzIGN1cnNvciBvbiBmb3IgdGhpcyBwYXJ0aWN1bGFyIG9iamVjdFxuXHRcdCAqIEBwYXJhbSB7Ym9vbGVhbn0gYlBhdXNlUHJvZ3Jlc3NPZmYgQSB2YWx1ZSBvZiB0cnVlIHdpbGwgc3RvcCBhbGwgdGhlIGZ1dHVyZSBwcm9ncmVzc09mZiBtZXRob2QgY2FsbHMgZm9yIHRoaXMgZWxlbWVudCB1bnRpbCByZXNldFxuXHRcdCAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqIEBpbnN0YW5jZVxuXHRcdCAqIEBtZW1iZXJvZiBQYW5lbFxuXHRcdCAqL1xuICAgIHByb2dyZXNzT24oYlBhdXNlUHJvZ3Jlc3NPZmY6IGJvb2xlYW4pIHtcbiAgICAgIHRoaXMucGFuZWxDb250cm9sbGVyLnByb2dyZXNzT24oYlBhdXNlUHJvZ3Jlc3NPZmYpO1xuICAgIH1cblxuICAgIC8qKlxuXHRcdCAqIE1ldGhvZCBmb3Igc2V0dGluZyB0aGUgZml4ZWQgd2lkdGgvaGVpZ2h0IG9mIGEgcGFuZWwgbGV2ZWwgb2JqZWN0XG5cdFx0ICogQHBhcmFtIHtib29sZWFufSBmaXhXaWR0aCAnc2F5cycgdG8gZml4IHRoZSB3aWR0aCBvZiB0aGUgY2VsbCAob3B0aW9uYWwpXG5cdFx0ICogQHBhcmFtIHtib29sZWFufSBmaXhIZWlnaHQgJ3NheXMnIHRvIGZpeCB0aGUgaGVpZ2h0IG9mIHRoZSBjZWxsIChvcHRpb25hbClcblx0XHQgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKiBAaW5zdGFuY2Vcblx0XHQgKiBAbWVtYmVyb2YgUGFuZWxcblx0XHQgKi9cbiAgICBmaXhTaXplKGZpeFdpZHRoPzogYm9vbGVhbiwgZml4SGVpZ2h0PzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgdGhpcy5wYW5lbENvbnRyb2xsZXIuZml4U2l6ZShmaXhXaWR0aCwgZml4SGVpZ2h0KTtcbiAgICB9XG5cbiAgICAvKipcblx0XHQgKiBNZXRob2QgZm9yIHNldHRpbmcgdGhlIHByb2dyZXNzIGN1cnNvciBvZmYgZm9yIHRoaXMgcGFydGljdWxhciBvYmplY3Rcblx0XHQgKiBAcGFyYW0ge2Jvb2xlYW59IGJQYXVzZVByb2dyZXNzT2ZmIEEgdmFsdWUgb2YgdHJ1ZSB3aWxsIHN0b3AgYWxsIHRoZSBmdXR1cmUgcHJvZ3Jlc3NPZmYgbWV0aG9kIGNhbGxzIGZvclxuXHRcdCAqICB0aGlzIGVsZW1lbnQgdW50aWwgcmVzZXRcblx0XHQgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKiBAaW5zdGFuY2Vcblx0XHQgKiBAbWVtYmVyb2YgUGFuZWxcblx0XHQgKi9cbiAgICBwcm9ncmVzc09mZihiUGF1c2VQcm9ncmVzc09mZjogYm9vbGVhbikge1xuICAgICAgdGhpcy5wYW5lbENvbnRyb2xsZXIucHJvZ3Jlc3NPZmYoYlBhdXNlUHJvZ3Jlc3NPZmYpO1xuICAgIH1cblxuICAgIC8qKlxuXHRcdCAqIEhpZGUgdGhlIGhlYWRlciBmcm9tIGEgcGFuZWxcblx0XHQgKiBAcmV0dXJucyB7dm9pZH1cblx0XHQgKiBAaW5zdGFuY2Vcblx0XHQgKiBAbWVtYmVyT2YgUGFuZWxcblx0XHQgKi9cbiAgICBoaWRlSGVhZGVyKCkge1xuICAgICAgdGhpcy5wYW5lbENvbnRyb2xsZXIuaGlkZUhlYWRlcigpO1xuICAgIH1cblxuICAgIC8qKlxuXHRcdCAqIFNob3cgdGhlIGhlYWRlciBmcm9tIGEgcGFuZWxcblx0XHQgKiBAcmV0dXJucyB7dm9pZH1cblx0XHQgKiBAaW5zdGFuY2Vcblx0XHQgKiBAbWVtYmVyT2YgUGFuZWxcblx0XHQgKi9cbiAgICBzaG93SGVhZGVyKCkge1xuICAgICAgdGhpcy5wYW5lbENvbnRyb2xsZXIuc2hvd0hlYWRlcigpO1xuICAgIH1cblxuICAgIC8qKlxuXHRcdCAqIEV4cGFuZCBhIHBhbmVsXG5cdFx0ICogQHJldHVybnMge3ZvaWR9XG5cdFx0ICogQGluc3RhbmNlXG5cdFx0ICogQG1lbWJlck9mIFBhbmVsXG5cdFx0ICovXG4gICAgZXhwYW5kKCkge1xuICAgICAgdGhpcy5wYW5lbENvbnRyb2xsZXIuZXhwYW5kKCk7XG4gICAgfVxuXG4gICAgLyoqXG5cdFx0ICogQ29sbGFwc2UgYSBwYW5lbFxuXHRcdCAqIEByZXR1cm5zIHt2b2lkfVxuXHRcdCAqIEBpbnN0YW5jZVxuXHRcdCAqIEBtZW1iZXJPZiBQYW5lbFxuXHRcdCAqL1xuICAgIGNvbGxhcHNlKCkge1xuICAgICAgdGhpcy5wYW5lbENvbnRyb2xsZXIuY29sbGFwc2UoKTtcbiAgICB9XG5cbiAgICAvKipcblx0XHQgKiBTZXQgcGFuZWwgaGVpZ2h0XG4gICAgICogQHBhcmFtIHtudW1iZXJ9XG5cdFx0ICogQHJldHVybnMge3ZvaWR9XG5cdFx0ICogQGluc3RhbmNlXG5cdFx0ICogQG1lbWJlck9mIFBhbmVsXG5cdFx0ICovXG4gICAgc2V0SGVpZ2h0KGhlaWdodDogbnVtYmVyKSB7XG4gICAgICB0aGlzLnBhbmVsQ29udHJvbGxlci5zZXRIZWlnaHQoaGVpZ2h0KTtcbiAgICB9XG5cbiAgICAvKipcblx0XHQgKiBTZXQgcGFuZWwgbWluIGhlaWdodFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfVxuXHRcdCAqIEByZXR1cm5zIHt2b2lkfVxuXHRcdCAqIEBpbnN0YW5jZVxuXHRcdCAqIEBtZW1iZXJPZiBQYW5lbFxuXHRcdCAqL1xuICAgIHNldE1pbkhlaWdodChoZWlnaHQ6IG51bWJlcikge1xuICAgICAgdGhpcy5wYW5lbENvbnRyb2xsZXIuc2V0TWluSGVpZ2h0KGhlaWdodCk7XG4gICAgfVxuXG4gICAgLyoqXG5cdFx0ICogU2hvd3MgYSBwYW5lbE1lbnUgYnV0dG9uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGJ1dHRvbiBuYW1lIChTQ0wgbWVudUZ1bmN0aW9uQ29kZS9tZW51U3RydWN0dXJlQ29kZSlcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyT2YgUGFuZWxcblx0XHQgKi9cbiAgICBzaG93UGFuZWxNZW51QnV0dG9uKG5hbWU6IHN0cmluZykge1xuICAgICAgdGhpcy5wYW5lbENvbnRyb2xsZXIuc2hvd1BhbmVsTWVudUJ1dHRvbihuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcblx0XHQgKiBIaWRlcyBhIHBhbmVsTWVudSBidXR0b25cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgYnV0dG9uIG5hbWUgKFNDTCBtZW51RnVuY3Rpb25Db2RlL21lbnVTdHJ1Y3R1cmVDb2RlKVxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJPZiBQYW5lbFxuXHRcdCAqL1xuICAgIGhpZGVQYW5lbE1lbnVCdXR0b24obmFtZTogc3RyaW5nKSB7XG4gICAgICB0aGlzLnBhbmVsQ29udHJvbGxlci5oaWRlUGFuZWxNZW51QnV0dG9uKG5hbWUpO1xuICAgIH1cblxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9QYW5lbC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogQ2hhcnQgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBDaGFydFxuICAgICAqIEBleHRlbmRzIHtQYW5lbH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIENoYXJ0IGV4dGVuZHMgYWtpb21hLnN3YXQuUGFuZWwge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL1BhbmVsLnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBEaWFncmFtIE9iamVjdFxuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgRGlhZ3JhbVxuICAgICAqIEBleHRlbmRzIHtQYW5lbH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIERpYWdyYW0gZXh0ZW5kcyBha2lvbWEuc3dhdC5QYW5lbCB7XG5cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vUGFuZWwudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIGV4cG9ydCB0eXBlIERvY1ZpZXdlckV2ZW50VHlwZSA9ICdvbkRvY3VtZW50TG9hZCcgfCAnc2F2ZURvY3VtZW50JyB8ICdzYXZlQW5ub3RhdGlvbicgfCAnc2F2ZUFzRG9jdW1lbnQnIHwgJ3VwbG9hZERvY3VtZW50JyB8ICdzZW5kRG9jdW1lbnQnIHwgJ3N3aXRjaFRvVGFiJyB8ICdwYWdlQ2hhbmdlJyB8ICdwYWdlQ29waWVkJyB8ICdwYWdlUGFzdGVkJyB8ICdwYWdlRGVsZXRlZCcgfCAncm90YXRpb24nIHwgJ3RleHRTZWxlY3QnIHwgJ2ltYWdlTG9hZEZpbmlzaGVkJyB8ICdpbWFnZUxvYWRSZXF1ZXN0ZWQnIHwgJ2Fubm90YXRpb25DcmVhdGlvbkNhbGxiYWNrJztcblxuICBleHBvcnQgaW50ZXJmYWNlIERvY1ZpZXdlckV2ZW50IHtcbiAgICBldmVudE5hbWU6IHN0cmluZztcbiAgICBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgZG9jdmlld2VyaWQ6IHN0cmluZztcbiAgfVxuXG4gIC8qKlxuICAgKiBEb2NWaWV3ZXIgT2JqZWN0XG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIERvY1ZpZXdlclxuICAgKiBAZXh0ZW5kcyB7UGFuZWx9XG4gICAqL1xuICBleHBvcnQgY2xhc3MgRG9jVmlld2VyIGV4dGVuZHMgYWtpb21hLnN3YXQuUGFuZWwge1xuXG4gICAgcHJpdmF0ZSBfY2FsbGJhY2tzOiB7XG4gICAgICBba2V5OiBzdHJpbmddOiAoKHBhcmFtczogYW55KSA9PiB7fSlbXTtcbiAgICB9ID0ge307XG5cbiAgICBjb25zdHJ1Y3Rvcihjb250cm9sbGVyOiBhbnkpIHtcbiAgICAgIHN1cGVyKGNvbnRyb2xsZXIpO1xuXG4gICAgICBjb250cm9sbGVyLmZpcmVPbkNhbGxiYWNrRXZlbnQoKGV2dDogYW55KSA9PiB7IC8vIGluc3RlYWQgb2YgdXNpbmcgLmJpbmQoKVxuICAgICAgICB0aGlzLnByb2Nlc3NDYWxsYmFja3MoZXZ0KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGdldCBldmVudCgpOiBEb2NWaWV3ZXJFdmVudCB8IHVuZGVmaW5lZCB7XG4gICAgICByZXR1cm4gdGhpcy5keW5PYmplY3Q/LmFrRXZlbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FsbHMgYSBkb2N2aWV3ZXIgbWV0aG9kIGJ5IG1lc3NhZ2luZyB0aGUgZG9jdmlld2VyIGFuZCByZXR1cm5pbmcgdGhlIHJlc3BvbnNlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZE5hbWUgVGhlIG1ldGhvZCBuYW1lXG4gICAgICogQHBhcmFtIHsqfSBwYXJhbXMgVGhlIG9wdGlvbmFsIHBhcmFtZXRlciBhcnJheVxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59IFJldHVybnMgYSBwcm9taXNlIHdpdGggdGhlIHJlcG9uc2VcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGNvbnN0IGRvY1ZpZXdlciA9IGV2ZW50U291cmNlLndpbmRvdy5nZXREb2NWaWV3ZXIoJ015RG9jVmlld2VyJyk7XG4gICAgICpcbiAgICAgKiBkb2NWaWV3ZXIuZGlzcGF0Y2hNZXRob2RDYWxsKCdnZXRQYWdlQ291bnQnKVxuICAgICAqICAgICAudGhlbigobnVtUGFnZXMpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKG51bVBhZ2VzKTtcbiAgICAgKiAgICAgfSk7XG4gICAgICovXG4gICAgZGlzcGF0Y2hNZXRob2RDYWxsKG1ldGhvZE5hbWU6IHN0cmluZywgcGFyYW1zOiBhbnkgPSBudWxsKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgIGlmIChwYXJhbXMgJiYgIShwYXJhbXMgaW5zdGFuY2VvZiBBcnJheSkpXG4gICAgICAgIHBhcmFtcyA9IFtwYXJhbXNdO1xuXG4gICAgICByZXR1cm4gdGhpcy5jb250cm9sbGVyLmNhbGxEb2NWaWV3ZXJNZXRob2QobWV0aG9kTmFtZSwgcGFyYW1zKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGEgY2FsbGJhY2sgZnVuY3Rpb24gZm9yIGFuIGV2ZW50XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgZXZlbnQgbmFtZS4gVmFsaWQgdmFsdWVzIC1cbiAgICAgKiBcIm9uRG9jdW1lbnRMb2FkXCIsIFwic2F2ZURvY3VtZW50XCIsIFwic2F2ZUFubm90YXRpb25cIiwgXCJzYXZlQXNEb2N1bWVudFwiLCBcInVwbG9hZERvY3VtZW50XCIsIFwic2VuZERvY3VtZW50XCIsIFwic3dpdGNoVG9UYWJcIiwgXCJwYWdlQ2hhbmdlXCIsIFwicGFnZUNvcGllZFwiLCBcInBhZ2VQYXN0ZWRcIiwgXCJwYWdlRGVsZXRlZFwiLCBcInJvdGF0aW9uXCIsIFwidGV4dFNlbGVjdFwiLCBcImltYWdlTG9hZEZpbmlzaGVkXCIsIFwiaW1hZ2VMb2FkUmVxdWVzdGVkXCIsIFwiYW5ub3RhdGlvbkNyZWF0aW9uQ2FsbGJhY2tcIjtcbiAgICAgKiBAcGFyYW0geyp9IGNhbGxiYWNrIFRoZSBjYWxsYmFjayBmdW5jdGlvblxuICAgICAqL1xuICAgIHNldENhbGxiYWNrKGV2ZW50TmFtZTogRG9jVmlld2VyRXZlbnRUeXBlLCBjYWxsYmFjazogKHBhcmFtczogYW55KSA9PiB7fSkge1xuICAgICAgY29uc3QgbmFtZSA9IGV2ZW50TmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICBpZiAoIXRoaXMuX2NhbGxiYWNrc1tuYW1lXSlcbiAgICAgICAgdGhpcy5fY2FsbGJhY2tzW25hbWVdID0gW107XG5cbiAgICAgIGNvbnN0IGNhbGxiYWNrcyA9IHRoaXMuX2NhbGxiYWNrc1tuYW1lXTtcblxuICAgICAgY2FsbGJhY2tzLnB1c2goY2FsbGJhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhpZGUgdG9vbGJhciBidXR0b24gaW4gZG9jdmlld2VyIGJhc2VkIG9uIGdpdmVuIG5hbWVcbiAgICAgKiBAcGFyYW0ge0RvY1ZpZXdlclRvb2xiYXJCdG5zfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0b29sYmFyIGJ1dHRvblxuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqL1xuICAgIGhpZGVUb29sYmFyQnV0dG9uKG5hbWU6IHN0cmluZykge1xuICAgICAgdGhpcy5jb250cm9sbGVyLmhpZGVUb29sYmFyQnV0dG9uKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3cgdG9vbGJhciBidXR0b24gaW4gZG9jdmlld2VyIGJhc2VkIG9uIGdpdmVuIG5hbWVcbiAgICAgKiBAcGFyYW0ge0RvY1ZpZXdlclRvb2xiYXJCdG5zfSBuYW1lIFRoZSAgbmFtZSBvZiB0aGUgdG9vbGJhciBidXR0b25cbiAgICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKi9cbiAgICBzaG93VG9vbGJhckJ1dHRvbihuYW1lOiBzdHJpbmcpIHtcbiAgICAgIHRoaXMuY29udHJvbGxlci5zaG93VG9vbGJhckJ1dHRvbihuYW1lKTtcbiAgICB9XG5cbiAgICAvKioqXG4gICAgICogSGlkZSBTaWRlIFRvb2xiYXIgbmF2aWdhdGlvbiBpbiBkb2N2aWV3ZXJcbiAgICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKi9cbiAgICBoaWRlU2lkZVRvb2xiYXIoKSB7XG4gICAgICB0aGlzLmNvbnRyb2xsZXIuaGlkZVNpZGVUb29sYmFyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hvd3Mgc2lkZSBUb29sYmFyIG5hdmlnYXRpb24gaW4gZG9jdmlld2VyXG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgc2hvd1NpZGVUb29sYmFyKCkge1xuICAgICAgdGhpcy5jb250cm9sbGVyLnNob3dTaWRlVG9vbGJhcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhpZGVzIHRvcCBUb29sYmFyIG5hdmlnYXRpb24gaW4gZG9jdmlld2VyXG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgaGlkZVRvcFRvb2xiYXIoKSB7XG4gICAgICB0aGlzLmNvbnRyb2xsZXIuaGlkZVRvcFRvb2xiYXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93cyB0b3AgVG9vbGJhciBuYXZpZ2F0aW9uIGluIGRvY3ZpZXdlclxuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqL1xuICAgIHNob3dUb3BUb29sYmFyKCkge1xuICAgICAgdGhpcy5jb250cm9sbGVyLnNob3dUb3BUb29sYmFyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGNhbGxiYWNrIGZ1bmN0aW9uIGZvciBhbiBldmVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIGV2ZW50IG5hbWUuIFZhbGlkIHZhbHVlcyAtXG4gICAgICogXCJvbkRvY3VtZW50TG9hZFwiLCBcInNhdmVEb2N1bWVudFwiLCBcInNhdmVBbm5vdGF0aW9uXCIsIFwic2F2ZUFzRG9jdW1lbnRcIiwgXCJ1cGxvYWREb2N1bWVudFwiLCBcInNlbmREb2N1bWVudFwiLCBcInN3aXRjaFRvVGFiXCIsIFwicGFnZUNoYW5nZVwiLCBcInBhZ2VDb3BpZWRcIiwgXCJwYWdlUGFzdGVkXCIsIFwicGFnZURlbGV0ZWRcIiwgXCJyb3RhdGlvblwiLCBcInRleHRTZWxlY3RcIiwgXCJpbWFnZUxvYWRGaW5pc2hlZFwiLCBcImltYWdlTG9hZFJlcXVlc3RlZFwiLCBcImFubm90YXRpb25DcmVhdGlvbkNhbGxiYWNrXCI7XG4gICAgICogQHBhcmFtIHsqfSBjYWxsYmFjayBUaGUgY2FsbGJhY2sgZnVuY3Rpb25cbiAgICAgKi9cbiAgICB1bnNldENhbGxiYWNrKGV2ZW50TmFtZTogRG9jVmlld2VyRXZlbnRUeXBlLCBjYWxsYmFjazogKHBhcmFtczogYW55KSA9PiB7fSkge1xuICAgICAgY29uc3QgbmFtZSA9IGV2ZW50TmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICBpZiAoIXRoaXMuX2NhbGxiYWNrc1tuYW1lXSlcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgICBjb25zdCBjYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3NbbmFtZV07XG4gICAgICBjb25zdCBpZHggPSBjYWxsYmFja3MuaW5kZXhPZihjYWxsYmFjayk7XG5cbiAgICAgIGlmIChpZHggPiAtMSlcbiAgICAgICAgY2FsbGJhY2tzLnNwbGljZShpZHgsIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE5hbWUgb2YgdGhlIGRvY3VtZW50IGZpbGUgdG8gbG9hZCBpbnNpZGUgdGhlIGRvY3ZpZXdlciBjb250cm9sXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICovXG4gICAgc2V0VmFsdWUodmFsdWU6IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgICByZXR1cm4gdGhpcy5jb250cm9sbGVyLnNldFZhbHVlKHZhbHVlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NDYWxsYmFja3MoZXZ0OiBhbnkpIHtcbiAgICAgIGNvbnN0IG5hbWUgPSBldnQuZXZlbnROYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICBjb25zdCBwYXJhbXMgPSBldnQucGFyYW1zO1xuXG4gICAgICBpZiAoIXRoaXMuX2NhbGxiYWNrc1tuYW1lXSlcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgICBjb25zdCBjYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3NbbmFtZV07XG5cbiAgICAgIGNhbGxiYWNrcy5mb3JFYWNoKGNhbGxiYWNrID0+IHtcbiAgICAgICAgY2FsbGJhY2socGFyYW1zKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vUGFuZWwudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuICBjb25zdCBhbGxDb2xvcnMgPSBbICdibGFjaycsICdyZWQnLCAneWVsbG93JywgJ2JsdWUnIF0gYXMgY29uc3Q7XG4gIGV4cG9ydCB0eXBlIEZyZWVIYW5kQ29sb3IgPSB0eXBlb2YgYWxsQ29sb3JzW251bWJlcl07XG5cbiAgZXhwb3J0IHR5cGUgRnJlZUhhbmRGaWxlID0ge1xuICAgIGZpbGU6IEZpbGU7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHNpemU6IG51bWJlcjtcbiAgICBzdGF0ZTogJ2FkZGVkJztcbiAgfTtcblxuICBleHBvcnQgY2xhc3MgRnJlZUhhbmQgZXh0ZW5kcyBha2lvbWEuc3dhdC5QYW5lbCB7XG4gICAgc2F2ZSgpIHtcbiAgICAgIHRoaXMuY29udHJvbGxlci5zYXZlKCk7XG4gICAgfVxuXG4gICAgcmVzZXQoKSB7XG4gICAgICB0aGlzLmNvbnRyb2xsZXIucmVzZXQoKTtcbiAgICB9XG5cbiAgICB1bmRvKCkge1xuICAgICAgdGhpcy5jb250cm9sbGVyLnVuZG8oKTtcbiAgICB9XG5cbiAgICByZWRvKCkge1xuICAgICAgdGhpcy5jb250cm9sbGVyLnJlZG8oKTtcbiAgICB9XG5cbiAgICBhZGRUZXh0KCkge1xuICAgICAgdGhpcy5jb250cm9sbGVyLmFkZFRleHQoKTtcbiAgICB9XG5cbiAgICBzZWxlY3RTdHJva2VDb2xvcih2YWx1ZTogRnJlZUhhbmRDb2xvcikge1xuICAgICAgdGhpcy5jb250cm9sbGVyLnNlbGVjdFN0cm9rZUNvbG9yKHZhbHVlKTtcbiAgICB9XG5cbiAgICBzZWxlY3RTdHJva2VTaXplKHZhbHVlOiBudW1iZXIpIHtcbiAgICAgIHRoaXMuY29udHJvbGxlci5zZWxlY3RTdHJva2VTaXplKHZhbHVlKTtcbiAgICB9XG5cbiAgICBvblVwbG9hZEZpbGVBZGQoZmlsZXM6IFJlY29yZDxzdHJpbmcsIEZyZWVIYW5kRmlsZT4pIHtcbiAgICAgIHRoaXMuY29udHJvbGxlci5vblVwbG9hZEZpbGVBZGQoZmlsZXMpO1xuICAgIH1cblxuICAgIG9uVXBsb2FkQ29tcGxldGUodXJsOiBzdHJpbmcpIHtcbiAgICAgIHRoaXMuY29udHJvbGxlci5vblVwbG9hZENvbXBsZXRlKHVybCk7XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9QYW5lbC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogR2FudHQgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBHYW50dFxuICAgICAqIEBleHRlbmRzIHtQYW5lbH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIEdhbnR0IGV4dGVuZHMgYWtpb21hLnN3YXQuUGFuZWwge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL1BhbmVsLnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBHYXVnZSBPYmplY3RcbiAgICAgKiBAZXhwb3J0XG4gICAgICogQGNsYXNzIEdhdWdlXG4gICAgICogQGV4dGVuZHMge1BhbmVsfVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgR2F1Z2UgZXh0ZW5kcyBha2lvbWEuc3dhdC5QYW5lbCB7XG5cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vUGFuZWwudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBHcmFwaCBFZGl0b3IgT2JqZWN0XG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIEdyYXBoRWRpdG9yXG4gICAqIEBleHRlbmRzIHtQYW5lbH1cbiAgICovXG4gIGV4cG9ydCBjbGFzcyBHcmFwaEVkaXRvciBleHRlbmRzIGFraW9tYS5zd2F0LlBhbmVsIHtcblxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9QYW5lbC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogSW1hZ2UgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBJbWFnZVxuICAgICAqIEBleHRlbmRzIHtQYW5lbH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIEltYWdlIGV4dGVuZHMgYWtpb21hLnN3YXQuUGFuZWwge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL1BhbmVsLnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBNYXAgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBNYXBcbiAgICAgKiBAZXh0ZW5kcyB7UGFuZWx9XG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBNYXAgZXh0ZW5kcyBha2lvbWEuc3dhdC5QYW5lbCB7XG5cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vUGFuZWxTd2l0Y2hlck9iamVjdC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAqIFBhbmVsIFN3aXRjaGVyXG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIFBhbmVsU3dpdGNoZXJcbiAgICogQGV4dGVuZHMge1Zpc3VhbE9iamVjdH1cbiAgICovXG4gIGV4cG9ydCBjbGFzcyBQYW5lbFN3aXRjaGVyIGV4dGVuZHMgYWtpb21hLnN3YXQuUGFuZWxTd2l0Y2hlck9iamVjdCB7XG5cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vUGFuZWwudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gICAgdHlwZSBTY2hlZHVsZXJWaWV3ID0gJ2RheScgfCAnd2VlaycgfCAnbW9udGgnIHwgJ3llYXInO1xuXG4gICAgLyoqXG4gICAgICogU2NoZWR1bGVyIE9iamVjdFxuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgU2NoZWR1bGVyXG4gICAgICogQGV4dGVuZHMge1BhbmVsfVxuICAgICAqL1xuICAgIGV4cG9ydCBjbGFzcyBTY2hlZHVsZXIgZXh0ZW5kcyBha2lvbWEuc3dhdC5QYW5lbCB7XG5cbiAgICAgIC8qKlxuICAgICAgICAgKiBEaXNwbGF5cyB0aGUgc3BlY2lmaWVkIHZpZXcgYW5kIGRhdGVcbiAgICAgICAgICogQHBhcmFtIHtEYXRlfSBkYXRlIFRoZSBkYXRlIHRvIHBvc2l0aW9uIHRoZSB2aWV3LiBudWxsIHdpbGwgbm90IGNoYW5nZSB0aGUgcG9zaXRpb24uXG4gICAgICAgICAqIEBwYXJhbSB7U2NoZWR1bGVyVmlld30gdmlldyBUaGUgZGF5LCB3ZWVrLCBtb250aCBvciB5ZWFyIHZpZXcuIG51bGwgd2lsbCBub3QgY2hhbmdlIHRoZSB2aWV3LlxuICAgICAgICAgKi9cbiAgICAgIHNldEN1cnJlbnRWaWV3KGRhdGU6IERhdGUsIHZpZXc/OiBTY2hlZHVsZXJWaWV3KSB7XG4gICAgICAgIHRoaXMuX2NvbnRyb2xsZXIuZGh4LnNldEN1cnJlbnRWaWV3KGRhdGUsIHZpZXcpO1xuICAgICAgfVxuXG4gICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgcmVhZG9ubHkgYXR0cmlidXRlIG9mIHRoZSBzY2hlZHVsZXJcbiAgICAgICAgICogQHBhcmFtIHtCb29sZWFufSByZWFkb25seSBUcnVlIGZvciBzZXR0aW5nIHRoZSBzY2hlZHVsZXIgYXMgcmVhZC1vbmx5LCBmYWxzZSBmb3IgZGVhY3RpdmF0aW5nIHRoaXMgc2V0dGluZyAoZGVmYXVsdCB2YWx1ZSkuXG4gICAgICAgICAqL1xuICAgICAgc2V0UmVhZG9ubHkocmVhZG9ubHk6IEJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRSZWFkb25seShyZWFkb25seSk7XG4gICAgICB9XG5cbiAgICAgIC8qKlxuICAgICAgICAgKiBEaXNwbGF5cyB0aGUgc3BlY2lmaWVkIHZpZXcgYW5kIGRhdGUgQlVUIGRvZXMgbm90IGZpcmUgYW55IGV2ZW50cyBsaWtlIHNldEN1cnJlbnRWaWV3LlxuICAgICAgICAgKiBZb3UgY291bGQgdXNlIHVwZGF0ZVZpZXcgdG8gY2hhbmdlIHRoZSBzY2hlZHVsZXIgdmlldyB0byB3ZWVrIHdoZW4gdGhlIHNjcmVlbiBpcyBkaXNwbGF5ZWQgYmVmb3JlIHRoZSBkYXRhIGhhcyBsb2FkZWRcbiAgICAgICAgICogYW5kIHVzZSBzZXRDdXJyZW50VmlldyB0byBjaGFuZ2UgdGhlIGRhdGUgYWZ0ZXIgdGhlIGRhdGEgaGFzIGxvYWRlZC5cbiAgICAgICAgICogQHBhcmFtIHtEYXRlfSBkYXRlIFRoZSBkYXRlIHRvIHBvc2l0aW9uIHRoZSB2aWV3LiBudWxsIHdpbGwgbm90IGNoYW5nZSB0aGUgcG9zaXRpb24uXG4gICAgICAgICAqIEBwYXJhbSB7U2NoZWR1bGVyVmlld30gdmlldyBUaGUgZGF5LCB3ZWVrLCBtb250aCBvciB5ZWFyIHZpZXcuIG51bGwgd2lsbCBub3QgY2hhbmdlIHRoZSB2aWV3LlxuICAgICAgICAgKi9cbiAgICAgIHVwZGF0ZVZpZXcoZGF0ZTogRGF0ZSwgdmlldz86IFNjaGVkdWxlclZpZXcpIHtcbiAgICAgICAgdGhpcy5fY29udHJvbGxlci5kaHgudXBkYXRlVmlldyhkYXRlLCB2aWV3KTtcbiAgICAgIH1cbiAgICB9XG59XG4iLCJuYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIHRoZSB2YWx1ZXMgYXR0YWNoZWQgdG8gYSB0YXNrYmFyIGl0ZW0gKCBkaXNwbGF5ZWQgb24gYm90dG9tIHJvdyBpbiBhcHBsaWNhdGlvbiB0YXNrYmFyIClcbiAgLSBleHRlcm5hbFNjcmVlbj8gOiBib29sZWFuLFxuICAtIGN1c3RvbVN0YXRlcz8gICA6IHN0cmluZyxcbiAgLSBoYXNDaGFuZ2VzICAgICAgOiBib29sZWFuLFxuICAtIGhhc0Vycm9ycz8gICAgICA6IGJvb2xlYW4sXG4gIC0gaWNvbiAgICAgICAgICAgIDogc3RyaW5nLFxuICAtIGlkICAgICAgICAgICAgICA6IHN0cmluZyxcbiAgLSBwYXJlbnRpZCAgICAgICAgOiBzdHJpbmcsXG4gIC0gdGl0bGUgICAgICAgICAgIDogc3RyaW5nLFxuICAtIHR5cGUgICAgICAgICAgICA6IHN0cmluZ1xuICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIFRhc2tiYXJJdGVtIHtcbiAgICBleHRlcm5hbFNjcmVlbj8gOiBib29sZWFuLFxuICAgIGN1c3RvbVN0YXRlcz8gOiBzdHJpbmcsXG4gICAgaGFzQ2hhbmdlcyA6IGJvb2xlYW4sXG4gICAgaGFzRXJyb3JzPyA6IGJvb2xlYW4sXG4gICAgaWNvbiA6IHN0cmluZyxcbiAgICBpZCA6IHN0cmluZyxcbiAgICBwYXJlbnRpZCA6IHN0cmluZyxcbiAgICB0aXRsZSA6IHN0cmluZyxcbiAgICB0eXBlIDogc3RyaW5nXG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyB0aGUgdmFsdWVzIGF0dGFjaGVkIHRvIGEgdGFza2JhciBncm91cCAoIGRpc3BsYXllZCBvbiB0b3Agcm93IGluIGFwcGxpY2F0aW9uIHRhc2tiYXIgKVxuICAgLSBjb2xvciAgICAgICAgICAgOiBzdHJpbmcsXG4gICAtIGljb24gICAgICAgICAgICA6IHN0cmluZyxcbiAgIC0gaWQgICAgICAgICAgICAgIDogc3RyaW5nLFxuICAgLSBpdGVtX2FjdGl2ZSAgICAgOiBzdHJpbmcsXG4gICAtIGl0ZW1fbGFzdEFjdGl2ZSA6IHN0cmluZyxcbiAgIC0gaXRlbXMgICAgICAgICAgIDogVGFza2Jhckl0ZW1bXSxcbiAgIC0gdGl0bGUgICAgICAgICAgIDogc3RyaW5nLFxuICAgLSB0eXBlICAgICAgICAgICAgOiBzdHJpbmdcbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgVGFza2Jhckdyb3VwIHtcbiAgICBjb2xvciA/OiBzdHJpbmcsXG4gICAgaWNvbiA/OiBzdHJpbmcsXG4gICAgaWQgOiBzdHJpbmcsXG4gICAgaXRlbV9hY3RpdmUgPzogc3RyaW5nLFxuICAgIGl0ZW1fbGFzdEFjdGl2ZSA/OiBzdHJpbmcsXG4gICAgaXRlbXMgPzogVGFza2Jhckl0ZW1bXSxcbiAgICB0aXRsZSA/OiBzdHJpbmcsXG4gICAgdHlwZSA/OiBzdHJpbmdcbiAgfVxuXG4gIC8qKlxuICAgKiBUYXNrYmFyIE9iamVjdFxuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBUYXNrYmFyXG4gICovXG4gIGV4cG9ydCBjbGFzcyBUYXNrYmFyIGV4dGVuZHMgYWtpb21hLnN3YXQuTGF5b3V0T2JqZWN0IHtcblxuICAgIGdldCBldmVudCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmV2ZW50O1xuICAgIH1cblxuICAgIGdldCBldmVudHMoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5ldmVudHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBhZGRpbmcgYSBuZXcgdGFza2JhciBpdGVtIGluIEhlYWRlciBmb3IgRXh0ZXJuYWwgU2NyZWVuc1xuICAgICAqIEBwYXJhbSBvcHRpb25zIE5ldCB0YXNrYmFyIGl0ZW0gb3B0aW9ucywgaWQsIGljb24gYW5kIHRpdGxlXG4gICAgKi9cbiAgICBhZGRFeHRlcm5hbEl0ZW0ob3B0aW9uczogeyBpZDogc3RyaW5nLCBpY29uPzpzdHJpbmcsIHRpdGxlPzpzdHJpbmcgfSkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5hZGRFeHRlcm5hbEl0ZW0ob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciByZW1vdmluZyB0aGUgRXh0ZXJuYWwgc2NyZWVuIHRhc2tiYXIgaXRlbXNcbiAgICAgKiBAcGFyYW0gaWRcbiAgICAqL1xuICAgIHJlbW92ZUV4dGVybmFsSXRlbShpZDogc3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnJlbW92ZUV4dGVybmFsSXRlbShpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBjbGVhcmluZyB1cCBhbGwgdGhlIGV4dGVybmFsIHNjcmVlbnNcbiAgICAqL1xuICAgIGNsZWFyQWxsRXh0ZXJuYWxTY3JlZW5zT3BlbmVkKCkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5jbGVhckFsbEV4dGVybmFsU2NyZWVuc09wZW5lZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byByZW1vdmUgdGFza2JhciBpdGVtIGJ5IGdpdmVuIGlkXG4gICAgICogQHBhcmFtIGlkXG4gICAgICovXG4gICAgcmVtb3ZlSXRlbShpZDogc3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnJlbW92ZUl0ZW0oaWQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBnZXQgdGFza2JhciBncm91cCBieSBpZFxuICAgICAqIEBwYXJhbSBpZFxuICAgICAqL1xuICAgIGdldEdyb3VwQnlJZChpZDogc3RyaW5nKTogYWtpb21hLnN3YXQuVGFza2Jhckdyb3VwIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldEdyb3VwQnlJZChpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciByZW1vdmluZyBncm91cCBpdGVtIGJ5IGlkXG4gICAgICogQHBhcmFtIGlkIEdyb3VwIGlkXG4gICAgICovXG4gICAgcmVtb3ZlR3JvdXBCeUlkKGlkOiBzdHJpbmcpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIucmVtb3ZlR3JvdXBCeUlkKGlkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdG8gZ2V0IGdyb3VwIGhhcyBjaGFuZ2VzIHN0YXRlIGJ5IGlkXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGlkXG4gICAgICovXG4gICAgZ2V0R3JvdXBIYXNDaGFuZ2VzQnlJZChpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRHcm91cEhhc0NoYW5nZXNCeUlkKGlkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdG8gYWRkIHRhc2tiYXIgZ3JvdXBcbiAgICAgKiBAcGFyYW0gZ3JvdXBEYXRhXG4gICAgICovXG4gICAgYWRkR3JvdXAoZ3JvdXBEYXRhOiBha2lvbWEuc3dhdC5UYXNrYmFyR3JvdXApIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuYWRkR3JvdXAoZ3JvdXBEYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdG8gYWRkIHRhc2tiYXIgaXRlbVxuICAgICAqIEBwYXJhbSBpdGVtRGF0YVxuICAgICAqL1xuICAgIGFkZEl0ZW0oaXRlbURhdGE6IGFraW9tYS5zd2F0LlRhc2tiYXJJdGVtKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmFkZEl0ZW0oaXRlbURhdGEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3Igc2V0dGluZyB0aGUgaXRlbSBoYXNFcnJvcnMgc3RhdGVcbiAgICAgKiBAcGFyYW0gaXRlbUlkIEl0ZW0gaWRcbiAgICAgKiBAcGFyYW0gaGFzRXJyb3JzIEl0ZW0gZXJyb3JzIHN0YXRlXG4gICAgICovXG4gICAgc2V0SXRlbUhhc0Vycm9ycyhpdGVtSWQ6c3RyaW5nLCBoYXNFcnJvcnM6Ym9vbGVhbikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRJdGVtSGFzRXJyb3JzKGl0ZW1JZCwgaGFzRXJyb3JzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHNldHRpbmcgdGhlIGl0ZW0gaGFzRXJyb3JzIHN0YXRlXG4gICAgICogQHBhcmFtIGl0ZW1JZCBJdGVtIGlkXG4gICAgICogQHBhcmFtIGhhc0Vycm9ycyBJdGVtIGVycm9ycyBzdGF0ZVxuICAgICAqL1xuICAgIHNldEl0ZW1IYXNDaGFuZ2VzKGl0ZW1JZDpzdHJpbmcsIGhhc0NoYW5nZXM6Ym9vbGVhbikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRJdGVtSGFzQ2hhbmdlcyhpdGVtSWQsIGhhc0NoYW5nZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3Igc2V0dGluZyBhIHRhc2tiYXIgaXRlbSB0aXRsZVxuICAgICAqIEBwYXJhbSBpdGVtSWRcbiAgICAgKiBAcGFyYW0gdGl0bGVcbiAgICAgKi9cbiAgICBzZXRJdGVtVGl0bGUoaXRlbUlkOnN0cmluZywgdGl0bGU6c3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEl0ZW1UaXRsZShpdGVtSWQsIHRpdGxlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHNldHRpbmcgYSB0YXNrYmFyIGdyb3VwIGl0ZW0gdGl0bGVcbiAgICAgKiBAcGFyYW0gZ3JvdXBJZFxuICAgICAqIEBwYXJhbSB0aXRsZVxuICAgICAqL1xuICAgIHNldEdyb3VwVGl0bGUoZ3JvdXBJZDpzdHJpbmcsIHRpdGxlOnN0cmluZykge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRHcm91cFRpdGxlKGdyb3VwSWQsIHRpdGxlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHNldHRpbmcgY3VzdG9tIHN0YXRlIG9uIGl0ZW0gYnkgaWRcbiAgICAgKiBAcGFyYW0gaWRcbiAgICAgKiBAcGFyYW0gY3VzdG9tU3RhdGVzXG4gICAgICovXG4gICAgc2V0SXRlbUN1c3RvbVN0YXRlKGlkOiBzdHJpbmcsIGN1c3RvbVN0YXRlczogYW55KSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEl0ZW1DdXN0b21TdGF0ZShpZCwgY3VzdG9tU3RhdGVzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdG8gZ2V0IHRhc2tiYXIgaXRlbSBieSBpZFxuICAgICAqIEBwYXJhbSBpZFxuICAgICAqL1xuICAgIGdldEl0ZW1CeUlkKGlkOiBzdHJpbmcpOiBha2lvbWEuc3dhdC5UYXNrYmFySXRlbSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRJdGVtQnlJZChpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRvIGdldCBhY3RpdmUgdGFza2JhciBpdGVtIGJ5IGdyb3VwIGlkXG4gICAgICogQHBhcmFtIGlkXG4gICAgICovXG4gICAgZ2V0QWN0aXZlSXRlbUJ5R3JvdXBJZChpZDogc3RyaW5nKTogYWtpb21hLnN3YXQuVGFza2Jhckl0ZW0ge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0QWN0aXZlSXRlbUJ5R3JvdXBJZChpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzZWxlY3RpbmcgdGFza2JhciBpdGVtIGJ5IGdpdmVuIGlkXG4gICAgICogQHBhcmFtIGlkXG4gICAgICogQHBhcmFtIHRyaWdnZXJFdmVudFxuICAgICAqL1xuICAgIHNlbGVjdEl0ZW0oaWQ6IHN0cmluZywgdHJpZ2dlckV2ZW50ID0gdHJ1ZSkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZWxlY3RJdGVtKGlkLCB0cmlnZ2VyRXZlbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBnZXQgYWN0aXZlIGdyb3VwIGlkXG4gICAgICovXG4gICAgZ2V0QWN0aXZlR3JvdXBJZCgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0QWN0aXZlR3JvdXBJZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBnZXQgYWN0aXZlIGl0ZW1cbiAgICAgKi9cbiAgICBnZXRBY3RpdmVJdGVtKCk6IGFraW9tYS5zd2F0LlRhc2tiYXJJdGVtIHwgbnVsbCB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRBY3RpdmVJdGVtKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciB1cGRhdGluZyBncm91cCB3aXRoIGdpdmVuIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0gZ3JvdXBEYXRhXG4gICAgICovXG4gICAgdXBkYXRlR3JvdXAoZ3JvdXBEYXRhOiBha2lvbWEuc3dhdC5UYXNrYmFyR3JvdXApIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIudXBkYXRlR3JvdXAoZ3JvdXBEYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIGVuYWJsaW5nIFRhc2tiYXJcbiAgICAgKi9cbiAgICBlbmFibGUoKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmVuYWJsZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgZGlzYWJsaW5nIHRoZSBUYXNrYmFyXG4gICAgICovXG4gICAgZGlzYWJsZSgpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuZGlzYWJsZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgZ2V0dGluZyBhbGwgdGFza2JhciBpdGVtc1xuICAgICAqL1xuICAgIGdldEl0ZW1zKCk6IEFycmF5PGFraW9tYS5zd2F0LlRhc2tiYXJJdGVtPiB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRJdGVtcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgZ2V0dGluZyBhbGwgdGFza2JhciBncm91cHNcbiAgICAgKi9cbiAgICBnZXRHcm91cHMoKTogQXJyYXk8YWtpb21hLnN3YXQuVGFza2Jhckdyb3VwPiB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRHcm91cHMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIGdldHRpbmcgbGFzdCBzZWxlY3RlZCBncm91cFxuICAgICAqL1xuICAgIGdldExhc3RTZWxlY3RlZEdyb3VwKCk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRMYXN0U2VsZWN0ZWRHcm91cCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgYXR0YWNoaW5nIGV2ZW50IGJ5IGV2ZW50IG5hbWVcbiAgICAgKiBAcGFyYW0gZXZlbnROYW1lXG4gICAgICogQHBhcmFtIGxpc3RlbmVyXG4gICAgICovXG4gICAgYXR0YWNoRXZlbnQoZXZlbnROYW1lOiBzdHJpbmcsIGxpc3RlbmVyOiBGdW5jdGlvbikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5hdHRhY2hFdmVudChldmVudE5hbWUsIGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vUGFuZWwudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIFRleHQgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBUZXh0XG4gICAgICogQGV4dGVuZHMge1BhbmVsfVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgVGV4dCBleHRlbmRzIGFraW9tYS5zd2F0LlBhbmVsIHtcblxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9QYW5lbC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogV29ya2Zsb3cgT2JqZWN0XG4gICAgICogQGV4cG9ydFxuICAgICAqIEBjbGFzcyBXb3JrZmxvd1xuICAgICAqIEBleHRlbmRzIHtQYW5lbH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIFdvcmtmbG93IGV4dGVuZHMgYWtpb21hLnN3YXQuUGFuZWwge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi9QYW5lbC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAqIEZpZWxkIENvbnRhaW5lciBCYXNlIENsYXNzXG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIEZpZWxkQ29udGFpbmVyXG4gICAqIEBleHRlbmRzIHtQYW5lbH1cbiAgICovXG4gIGV4cG9ydCBjbGFzcyBGaWVsZENvbnRhaW5lciBleHRlbmRzIGFraW9tYS5zd2F0LlBhbmVsIHtcblxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vRmllbGRDb250YWluZXIudHNcIiAvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uLy4uL2RhdGFmaWVsZC9EYXRhRmllbGQudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBGb3JtIE9iamVjdFxuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBGb3JtXG4gICAqIEBleHRlbmRzIHtWaXN1YWxPYmplY3R9XG4gICAqL1xuICBleHBvcnQgY2xhc3MgRm9ybSBleHRlbmRzIGFraW9tYS5zd2F0LkZpZWxkQ29udGFpbmVyIHtcblxuICAgIHByaXZhdGUgX2RhdGFTb3VyY2U6IGFraW9tYS5zd2F0LkRhdGFTb3VyY2U7XG4gICAgcHJpdmF0ZSBfZmllbGRNYXA6IHsgW2ZpZWxkTmFtZTogc3RyaW5nXTogYWtpb21hLnN3YXQuRGF0YUZpZWxkIH0gPSB7fTtcbiAgICBwcml2YXRlIF9maWVsZE5hbWVzOiBBcnJheTxzdHJpbmc+ID0gW107XG4gICAgcHJpdmF0ZSBfZmllbGRDb250cm9sbGVyczogQXJyYXk8YW55PiA9IFtdO1xuICAgIHByaXZhdGUgX2ZpZWxkQ29udHJvbGxlck1hcDogeyBbZmllbGROYW1lOiBzdHJpbmddOiBhbnkgfSA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogQW4gYXJyYXkgY29udGFpbmluZyB0aGUgZm9ybSBmaWVsZCBuYW1lcywgaW5jbHVkaW5nIG5lc3RlZCBmaWVsZHNldHMgYW5kIGJsb2NrIGZpZWxkc1xuICAgICAqIEByZWFkb25seVxuICAgICAqIEB0eXBlIHtBcnJheTxzdHJpbmc+fVxuICAgICAqL1xuICAgIGdldCBmaWVsZE5hbWVzKCk6IEFycmF5PHN0cmluZz4ge1xuICAgICAgaWYgKHRoaXMuX2ZpZWxkQ29udHJvbGxlcnMubGVuZ3RoID09PSAwKVxuICAgICAgICB0aGlzLl9maWxsRmllbGRzKCk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9maWVsZE5hbWVzO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IGZpZWxkQ29udHJvbGxlcnMoKTogQXJyYXk8YW55PiB7XG4gICAgICBpZiAodGhpcy5fZmllbGRDb250cm9sbGVycy5sZW5ndGggPT09IDApXG4gICAgICAgIHRoaXMuX2ZpbGxGaWVsZHMoKTtcblxuICAgICAgcmV0dXJuIHRoaXMuX2ZpZWxkQ29udHJvbGxlcnM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgZmllbGRDb250cm9sbGVyTWFwKCk6IHsgW2ZpZWxkTmFtZTogc3RyaW5nXTogYW55IH0ge1xuICAgICAgaWYgKHRoaXMuX2ZpZWxkQ29udHJvbGxlcnMubGVuZ3RoID09PSAwKVxuICAgICAgICB0aGlzLl9maWxsRmllbGRzKCk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9maWVsZENvbnRyb2xsZXJNYXA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZmlsbEZpZWxkcyhwYXJlbnQ/OiBhbnkpIHtcbiAgICAgIHBhcmVudCA9IHBhcmVudCB8fCB0aGlzLl9keW5PYmplY3Q7XG5cbiAgICAgIC8vIGNvcGllZCBsb2dpYyBmcm9tIF9zZWFyY2hOZXN0ZWRGb3JtRWxlbWVudHMoKSBpbiBha2lvbWEub2JqZWN0LmpzXG4gICAgICAvLyBtYXliZSBhbGwgb2JqZWN0cyB3aXRoIGNoaWxkcyBwcm9wZXJ0eSBzaG91bGQgYmUgZHJpbGxlZD9cbiAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBwYXJlbnQuY2hpbGRzKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkID0gcGFyZW50LmNoaWxkc1tuYW1lXTtcblxuICAgICAgICBzd2l0Y2ggKGNoaWxkLnR5cGUpIHtcbiAgICAgICAgICBjYXNlICdmaWVsZHNldCc6XG4gICAgICAgICAgY2FzZSAnYmxvY2snOlxuICAgICAgICAgICAgdGhpcy5fZmlsbEZpZWxkcyhjaGlsZCk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGNhc2UgJ2h0bWxjb250ZW50JzpcbiAgICAgICAgICBjYXNlICdidXR0b24nOlxuICAgICAgICAgIGNhc2UgJ21lbnVzdHJ1Y3R1cmUnOlxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhpcy5fZmllbGRDb250cm9sbGVycy5wdXNoKGNoaWxkLmNvbnRyb2xsZXIpO1xuICAgICAgICAgICAgdGhpcy5fZmllbGRDb250cm9sbGVyTWFwW2NoaWxkLm5hbWUudG9Mb3dlckNhc2UoKV0gPSBjaGlsZC5jb250cm9sbGVyO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fZmllbGROYW1lcy5pbmRleE9mKGNoaWxkLm5hbWUpID09PSAtMSAmJiBjaGlsZC5uYW1lKVxuICAgICAgICAgICAgICB0aGlzLl9maWVsZE5hbWVzLnB1c2goY2hpbGQubmFtZSk7XG5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGxpbmtlZCBidXNpbmVzcyBlbnRpdHkgdG8gdGhpcyBmb3JtXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQHR5cGUge0RhdGFTb3VyY2V9XG4gICAgICovXG4gICAgZ2V0IGRhdGFTb3VyY2UoKTogYWtpb21hLnN3YXQuRGF0YVNvdXJjZSB7XG4gICAgICBpZiAoIXRoaXMuX2RhdGFTb3VyY2UpIHtcbiAgICAgICAgY29uc3QgZGF0YVNvdXJjZSA9IHRoaXMuX2R5bk9iamVjdC5nZXRMaW5rKCdESVNQTEFZOlNSQycpO1xuICAgICAgICBpZiAoIWRhdGFTb3VyY2UpXG4gICAgICAgICAgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgdGhpcy5fZGF0YVNvdXJjZSA9IDxha2lvbWEuc3dhdC5EYXRhU291cmNlPihha2lvbWEuc3dhdC5Td2F0RmFjdG9yeS5jcmVhdGVTd2F0T2JqZWN0KGRhdGFTb3VyY2UpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuX2RhdGFTb3VyY2U7XG4gICAgfVxuXG4gICAgZ2V0IGRhdGFTb3VyY2VDb250cm9sbGVyKCk6IGFueSB8IG51bGwge1xuICAgICAgcmV0dXJuIHRoaXMuX2R5bk9iamVjdC5nZXRMaW5rKCdESVNQTEFZOlNSQycpPy5jb250cm9sbGVyIHx8IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgZm9ybSBkYXRhXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKi9cbiAgICBnZXRGb3JtRGF0YSgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldEZvcm1EYXRhKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIGZvcm0gZmllbGQgb2JqZWN0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGZvcm0gZmllbGQgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKiBAcmV0dXJucyB7RGF0YUZpZWxkfVxuICAgICAqL1xuICAgIGdldEZpZWxkKG5hbWU6IHN0cmluZyk6IGFraW9tYS5zd2F0LkRhdGFGaWVsZCB7XG4gICAgICBuYW1lID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICBsZXQgZmllbGQgPSBudWxsO1xuXG4gICAgICBpZiAodGhpcy5maWVsZENvbnRyb2xsZXJNYXBbbmFtZV0gJiYgIXRoaXMuX2ZpZWxkTWFwW25hbWVdKSB7XG4gICAgICAgIHRoaXMuX2ZpZWxkTWFwW25hbWVdID0gPGFraW9tYS5zd2F0LkRhdGFGaWVsZD4oYWtpb21hLnN3YXQuU3dhdEZhY3RvcnkuY3JlYXRlU3dhdE9iamVjdCh0aGlzLmZpZWxkQ29udHJvbGxlck1hcFtuYW1lXSkpO1xuICAgICAgICBmaWVsZCA9IHRoaXMuX2ZpZWxkTWFwW25hbWVdO1xuICAgICAgfSBlbHNlXG4gICAgICAgIGZpZWxkID0gPGFraW9tYS5zd2F0LkRhdGFGaWVsZD4odGhpcy5nZXRPYmplY3QobmFtZSkpO1xuXG4gICAgICByZXR1cm4gZmllbGQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIGZvcm0gZmllbGQgZHluc2VsZWN0IG9iamVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmb3JtIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHJldHVybnMge0R5blNlbGVjdH1cbiAgICAgKi9cbiAgICBnZXREeW5TZWxlY3QobmFtZTogc3RyaW5nKTogYWtpb21hLnN3YXQuRHluU2VsZWN0IHtcbiAgICAgIGNvbnN0IGR5blNlbGVjdCA9IHRoaXMuZ2V0RmllbGQobmFtZSk7XG5cbiAgICAgIGlmIChkeW5TZWxlY3QgaW5zdGFuY2VvZiBha2lvbWEuc3dhdC5EeW5TZWxlY3QpXG4gICAgICAgIHJldHVybiBkeW5TZWxlY3Q7XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYSBmb3JtIGZpZWxkIGNvbWJvYm94IG9iamVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmb3JtIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHJldHVybnMge0NvbWJvQm94fVxuICAgICAqL1xuICAgIGdldENvbWJvQm94KG5hbWU6IHN0cmluZyk6IGFraW9tYS5zd2F0LkNvbWJvQm94IHtcbiAgICAgIGNvbnN0IGNvbWJvQm94ID0gdGhpcy5nZXRGaWVsZChuYW1lKTtcblxuICAgICAgaWYgKGNvbWJvQm94IGluc3RhbmNlb2YgYWtpb21hLnN3YXQuQ29tYm9Cb3gpXG4gICAgICAgIHJldHVybiBjb21ib0JveDtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIGZvcm0gZmllbGQgcmljaHRleHQgb2JqZWN0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGZvcm0gZmllbGQgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKiBAcmV0dXJucyB7UmljaFRleHR9XG4gICAgICovXG4gICAgZ2V0UmljaFRleHQobmFtZTogc3RyaW5nKTogYWtpb21hLnN3YXQuUmljaFRleHQge1xuICAgICAgY29uc3QgcmljaFRleHQgPSB0aGlzLmdldEZpZWxkKG5hbWUpO1xuXG4gICAgICBpZiAocmljaFRleHQgaW5zdGFuY2VvZiBha2lvbWEuc3dhdC5SaWNoVGV4dClcbiAgICAgICAgcmV0dXJuIHJpY2hUZXh0O1xuICAgICAgZWxzZVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgZm9ybSBmaWVsZCB0b2dnbGUgb2JqZWN0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGZvcm0gZmllbGQgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKiBAcmV0dXJucyB7VG9nZ2xlfVxuICAgICAqL1xuICAgIGdldFRvZ2dsZShuYW1lOiBzdHJpbmcpOiBha2lvbWEuc3dhdC5Ub2dnbGUge1xuICAgICAgY29uc3QgdG9nZ2xlID0gdGhpcy5nZXRGaWVsZChuYW1lKTtcblxuICAgICAgaWYgKHRvZ2dsZSBpbnN0YW5jZW9mIGFraW9tYS5zd2F0LlRvZ2dsZSlcbiAgICAgICAgcmV0dXJuIHRvZ2dsZTtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIGZvcm0gZmllbGQgc2V0IG9iamVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmaWVsZHNldCBvYmplY3QgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKiBAcmV0dXJucyB7RmllbGRTZXR9XG4gICAgICovXG4gICAgZ2V0RmllbGRTZXQobmFtZTogc3RyaW5nKTogYWtpb21hLnN3YXQuRmllbGRTZXQge1xuICAgICAgY29uc3QgZmllbGRTZXQgPSB0aGlzLmdldE9iamVjdChuYW1lKTtcblxuICAgICAgaWYgKGZpZWxkU2V0IGluc3RhbmNlb2YgYWtpb21hLnN3YXQuRmllbGRTZXQpXG4gICAgICAgIHJldHVybiBmaWVsZFNldDtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIGZvcm0gSFRNTCBjb250ZW50IG9iamVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAgICogQHJldHVybnMge2FraW9tYS5zd2F0LkhUTUxDb250ZW50fVxuICAgICAqL1xuICAgIGdldEhUTUxDb250ZW50KG5hbWU6IHN0cmluZyk6IGFraW9tYS5zd2F0LkhUTUxDb250ZW50IHtcbiAgICAgIGNvbnN0IGh0bWxDb250ZW50ID0gdGhpcy5nZXRPYmplY3QobmFtZSk7XG5cbiAgICAgIGlmIChodG1sQ29udGVudCBpbnN0YW5jZW9mIGFraW9tYS5zd2F0LkhUTUxDb250ZW50KVxuICAgICAgICByZXR1cm4gaHRtbENvbnRlbnQ7XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYSBmb3JtIGJ1dHRvbiBvYmplY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgICAqIEByZXR1cm5zIHtha2lvbWEuc3dhdC5CdXR0b259XG4gICAgICovXG4gICAgZ2V0QnV0dG9uKG5hbWU6IHN0cmluZyk6IGFraW9tYS5zd2F0LkJ1dHRvbiB7XG4gICAgICBjb25zdCBidG4gPSB0aGlzLmdldE9iamVjdChuYW1lKTtcblxuICAgICAgaWYgKGJ0biBpbnN0YW5jZW9mIGFraW9tYS5zd2F0LkJ1dHRvbilcbiAgICAgICAgcmV0dXJuIGJ0bjtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCBmb3IgZ2V0dGluZyBhIGZvcm0gZmllbGQgc2NyZWVuIHZhbHVlLlxuICAgICAqIEVxdWl2YWxlbnQgdG8gZm9ybS5nZXRGaWVsZCgnbXlmaWVsZCcpLnNjcmVlblZhbHVlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmb3JtIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgZ2V0U2NyZWVuVmFsdWUobmFtZTogc3RyaW5nKTogYW55IHtcbiAgICAgIHJldHVybiB0aGlzLmdldEZpZWxkKG5hbWUpLnNjcmVlblZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBtZXRob2QgZm9yIHNldHRpbmcgYSBmb3JtIGZpZWxkIHNjcmVlbiB2YWx1ZS5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGZvcm0uZ2V0RmllbGQoJ215ZmllbGQnKS5zY3JlZW5WYWx1ZSA9ICd2YWx1ZScuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGZvcm0gZmllbGQgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXRcbiAgICAgKi9cbiAgICBzZXRTY3JlZW5WYWx1ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgICAgIHRoaXMuZ2V0RmllbGQobmFtZSkuc2NyZWVuVmFsdWUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIG9iamVjdCB3aXRoIGFsbCB0aGUgZm9ybSBmaWVsZHMgc2NyZWVuIHZhbHVlcywgaW5jbHVkaW5nIG5lc3RlZCBmaWVsZHNldHMgYW5kIGJsb2Nrc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIGdldEFsbFNjcmVlblZhbHVlcygpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICAgIGNvbnN0IHJldFZhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuXG4gICAgICB0aGlzLmZpZWxkTmFtZXMuZm9yRWFjaChuYW1lID0+IHtcbiAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmdldEZpZWxkKG5hbWUpO1xuXG4gICAgICAgIGlmIChmaWVsZCBpbnN0YW5jZW9mIGFraW9tYS5zd2F0LkR5blNlbGVjdClcbiAgICAgICAgICByZXRWYWxbZmllbGQua2V5TmFtZV0gPSBmaWVsZC5rZXlWYWx1ZTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHJldFZhbFtuYW1lXSA9IGZpZWxkLnNjcmVlblZhbHVlO1xuXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHJldFZhbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIG9iamVjdCB3aXRoIGJvdGggdGhlIGZvcm0gZmllbGRzIHNjcmVlbiBhbmQgdGhlIGRhdGFzb3VyY2UgcmVjb3JkIGZpZWxkc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIGdldEFsbFNjcmVlbkFuZERhdGFWYWx1ZXMoKTogYW55IHtcbiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHRoaXMuZGF0YVNvdXJjZS5nZXRDdXJyZW50UmVjb3JkKCksIHRoaXMuZ2V0QWxsU2NyZWVuVmFsdWVzKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBtZXRob2QgZm9yIGdldHRpbmcgYSBmb3JtIGZpZWxkIGxpbmtlZCBkYXRhc291cmNlIHZhbHVlLlxuICAgICAqIEVxdWl2YWxlbnQgdG8gZm9ybS5kYXRhU291cmNlLmdldFZhbHVlKCdteWZpZWxkJykuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGZvcm0gZmllbGQgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBnZXREYXRhVmFsdWUobmFtZTogc3RyaW5nKTogYW55IHtcbiAgICAgIHJldHVybiB0aGlzLmRhdGFTb3VyY2UuZ2V0VmFsdWUobmFtZS50b0xvd2VyQ2FzZSgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgbWV0aG9kIGZvciBzZXR0aW5nIGEgZm9ybSBmaWVsZCBsaW5rZWQgZGF0YXNvdXJjZSB2YWx1ZS5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGZvcm0uZGF0YVNvdXJjZS5zZXRWYWx1ZSgnbXlmaWVsZCcsICd2YWx1ZScpLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmb3JtIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0XG4gICAgICovXG4gICAgc2V0RGF0YVZhbHVlKG5hbWU6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgICAgdGhpcy5kYXRhU291cmNlLnNldFZhbHVlKG5hbWUudG9Mb3dlckNhc2UoKSwgdmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYW4gb2JqZWN0IHdpdGggYWxsIHRoZSBsaW5rZWQgZGF0YXNvdXJjZSBmb3JtIGZpZWxkIHZhbHVlcywgaW5jbHVkaW5nIG5lc3RlZCBmaWVsZHNldHMgYW5kIGJsb2Nrc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIGdldEFsbERhdGFWYWx1ZXMoKTogYW55IHtcbiAgICAgIGNvbnN0IHJldFZhbDogYW55ID0ge307XG5cbiAgICAgIHRoaXMuZmllbGROYW1lcy5mb3JFYWNoKG5hbWUgPT4ge1xuICAgICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZ2V0RmllbGQobmFtZSk7XG5cbiAgICAgICAgaWYgKGZpZWxkIGluc3RhbmNlb2YgYWtpb21hLnN3YXQuRHluU2VsZWN0KVxuICAgICAgICAgIG5hbWUgPSBmaWVsZC5rZXlOYW1lO1xuXG4gICAgICAgIHJldFZhbFtuYW1lXSA9IHRoaXMuZGF0YVNvdXJjZS5nZXRWYWx1ZShuYW1lKTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gcmV0VmFsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsZWFycyBoYXNDaGFuZ2VzIChkaXJ0eSBzdGF0ZSlcbiAgICAgKi9cbiAgICBjbGVhckhhc0NoYW5nZXMoKSB7XG4gICAgICBpZiAodGhpcy5kYXRhU291cmNlKVxuICAgICAgICB0aGlzLmRhdGFTb3VyY2UuY29udHJvbGxlci5jbGVhckhhc0NoYW5nZXMoKTtcbiAgICAgIGVsc2VcbiAgICAgICAgdGhpcy5fY29udHJvbGxlci5jbGVhckhhc0NoYW5nZXMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIGFycmF5IG9mIGZpZWxkIG5hbWVzIHRoYXQgdGhlaXIgdmFsdWVzIGhhdmUgYmVlbiBjaGFuZ2VkXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQGV4YW1wbGUgRm9ybS5jaGFuZ2VkRmllbGRzXG4gICAgICogQHR5cGUge3N0cmluZ1tdfVxuICAgICAqL1xuICAgIGdldCBjaGFuZ2VkRmllbGRzKCk6IHN0cmluZ1tdIHtcbiAgICAgIGNvbnN0IHJldFZhbDogc3RyaW5nW10gPSBbXTtcblxuICAgICAgY29uc3QgZmllbGRzID0gdGhpcy5jb250cm9sbGVyLm9WdWV4U3RhdGUuY2hpbGRyZW47XG4gICAgICBmb3IgKGNvbnN0IG5hbWUgaW4gZmllbGRzKSB7XG4gICAgICAgIGlmIChmaWVsZHNbbmFtZV0uaGFzQ2hhbmdlcylcbiAgICAgICAgICByZXRWYWwucHVzaChmaWVsZHNbbmFtZV0ubmFtZSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXRWYWw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCBmb3Igc2V0dGluZyBhIGZvcm0gZmllbGQgbGFiZWwuXG4gICAgICogRXF1aXZhbGVudCB0byBmb3JtLmdldEZpZWxkKCdteWZpZWxkJykubGFiZWwgPSAndmFsdWUnLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmb3JtIGZpZWxkIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0XG4gICAgICovXG4gICAgc2V0TGFiZWwobmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XG4gICAgICB0aGlzLmdldEZpZWxkKG5hbWUpLmxhYmVsID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCBmb3IgZ2V0dGluZyBhIGZvcm0gZmllbGQgbGFiZWwuXG4gICAgICogRXF1aXZhbGVudCB0byBmb3JtLmdldEZpZWxkKCdteWZpZWxkJykubGFiZWwuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGZvcm0gZmllbGQgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSlcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0XG4gICAgICovXG4gICAgZ2V0TGFiZWwobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEZpZWxkKG5hbWUpLmxhYmVsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBtZXRob2QgdG8gZW5hYmxlIGFsbCB0aGUgZm9ybSBmaWVsZHMuXG4gICAgICogRXF1aXZhbGVudCB0byBsb29waW5nIHRocm91Z2ggYWxsIHRoZSBmaWVsZCBuYW1lcywgZ2V0dGluZyB0aGUgZmllbGRzIGFuZCBzZXR0aW5nIGVuYWJsZWQgPSB0cnVlLlxuICAgICAqL1xuICAgIGVuYWJsZUFsbEZpZWxkcygpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuZW5hYmxlQWxsRmllbGRzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCB0byBkaXNhYmxlIGFsbCB0aGUgZm9ybSBmaWVsZHMuXG4gICAgICogRXF1aXZhbGVudCB0byBsb29waW5nIHRocm91Z2ggYWxsIHRoZSBmaWVsZCBuYW1lcywgZ2V0dGluZyB0aGUgZmllbGRzIGFuZCBzZXR0aW5nIGVuYWJsZWQgPSBmYWxzZS5cbiAgICAgKi9cbiAgICBkaXNhYmxlQWxsRmllbGRzKCkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5kaXNhYmxlQWxsRmllbGRzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCB0byBzZXQgYWxsIHRoZSBmb3JtIGZpZWxkcyByZWFkb25seSBwcm9wZXJ0eS5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGxvb3BpbmcgdGhyb3VnaCBhbGwgdGhlIGZpZWxkIG5hbWVzLCBnZXR0aW5nIHRoZSBmaWVsZHMgYW5kIHNldHRpbmcgcmVhZG9ubHkgcHJvcGVydHkuXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZWFkb25seVxuICAgICAqL1xuICAgIHNldEFsbEZpZWxkc1JlYWRPbmx5KHJlYWRvbmx5OiBib29sZWFuKSB7XG4gICAgICBpZiAocmVhZG9ubHkpXG4gICAgICAgIHRoaXMuZGlzYWJsZUFsbEZpZWxkcygpO1xuICAgICAgZWxzZVxuICAgICAgICB0aGlzLmVuYWJsZUFsbEZpZWxkcygpO1xuXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbGwgdGhlIGZvcm0gZmllbGRzIHZhbGlkYXRpb24gcnVsZXNcbiAgICAgKiBAcmV0dXJucyB7Kn0gVGhlIHZhbGlkYXRpb24gcnVsZXNcbiAgICAgKi9cbiAgICBnZXRBbGxWYWxpZGF0aW9uUnVsZXMoKToge1xuICAgICAgW2ZpZWxkOiBzdHJpbmddOiB7XG4gICAgICAgIFtydWxlIGluIHZhbGlkYXRpb25SdWxlVHlwZV06IHZhbGlkYXRpb25SdWxlO1xuICAgICAgfVxuICAgIH0ge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIudmFsaWRhdGlvblJ1bGVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFZhbGlkYXRlcyB0aGUgZm9ybSBhbmQgaGlnaGxpZ2h0cyBpbnZhbGlkIGZvcm0gZmllbGRzXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbc2lsZW50PWZhbHNlXSBJZiB0aGUgdmFsaWRhdGlvbiBmYWlscyBhbmQgbm90IHNpbGVudCxcbiAgICAgKiBmb3JjZXMgZm9ybSB0byBiZSBzaG93biBldmVuIGlmIHRoZSBmb3JtIGlzIGluIGEgY29sbGFwc2VkIHBhbmVsIG9yIHVuc2VsZWN0ZWQgdGFiYmFyIGV0Yy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICB2YWxpZGF0ZShzaWxlbnQgPSBmYWxzZSk6IGJvb2xlYW4ge1xuICAgICAgY29uc3Qgb2sgPSB0aGlzLl9jb250cm9sbGVyLnZhbGlkYXRlKCk7XG5cbiAgICAgIGlmICghb2sgJiYgIXNpbGVudClcbiAgICAgICAgdGhpcy5mb3JjZVNob3coKTtcblxuICAgICAgcmV0dXJuIG9rO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgdmFsaWRhdGluZyBmb3JtIGZpZWxkIGJ5IG5hbWVcbiAgICAgKiBAcGFyYW0gbmFtZSBOYW1lIG9mIGZvcm0gZmllbGQgdG8gdmFsaWRhdGVcbiAgICAgKi9cbiAgICB2YWxpZGF0ZUZpZWxkKG5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgICAgdGhpcy5jb250cm9sbGVyLnZhbGlkYXRlRmllbGQobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZXMgdmFsdWVzIHRvIHRoZSBsaW5rZWQgZGF0YXNvdXJjZS5cbiAgICAgKiBUaGUgZm9ybSBpcyBmaXJzdCB2YWxpZGF0ZWQuIElmIHRoZSB2YWxpZGF0aW9uIGZhaWxzIHRoZSBzYXZlIGlzIGFib3J0ZWQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgc2F2ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgLy8gZmlsZXNhdmUgd2lsbCBjYXVzZSBhbGwgZGF0YXNvdXJjZSBmb3JtcyB0byBiZSBzYXZlZFxuICAgICAgICB0aGlzLl9jb250cm9sbGVyLmZpbGVTYXZlKCk7XG5cbiAgICAgICAgdGhpcy5kYXRhU291cmNlQ29udHJvbGxlci5hZGRBZnRlclNhdmVPbmNlQ2FsbGJhY2soKHN1Y2Nlc3M6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgICBpZiAoc3VjY2VzcylcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICByZWplY3QoKTsgLy8gdG9kbzogcmV0dXJuIGVycm9yIG1lc3NhZ2VzXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZXMgdmFsdWVzIHRvIHRoZSBsaW5rZWQgZGF0YXNvdXJjZSBhbmQgY2xvc2VzIHRoZSB0b3AtbGV2ZWwgd2luZG93LlxuICAgICAqIFRoZSBmb3JtIGlzIGZpcnN0IHZhbGlkYXRlZC4gSWYgdGhlIHZhbGlkYXRpb24gZmFpbHMgdGhlIHNhdmUgaXMgYWJvcnRlZC5cbiAgICAgKiBOb3RlIHRoYXQgaWYgdGhlIGNvbnRhaW5lciBpcyB0aGUgbWFpbiBkZWtzdG9wIHdpbmRvdywgdGhlIHdpbmRvdyB3aWxsIG5vdCBiZSBjbG9zZWQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgc2F2ZUFuZENsb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgcmV0dXJuIHRoaXMuc2F2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLndpbmRvdy5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciByZXR1cm5pbmcgdGhlIGVuYWJsZWQgc3RhdGUgb2YgYSBmb3JtIGZpZWxkXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgRm9ybVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldEZvcm1GaWVsZEVuYWJsZWQobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRGb3JtRmllbGRFbmFibGVkKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3Igc2V0dGluZyB0aGUgZm9jdXMgb24gYSBjZXJ0YWluIGZvcm0gZmllbGRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgZm9ybSBmaWVsZCBuYW1lXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlcm9mIEZvcm1cbiAgICAgKi9cbiAgICBzZXRGaWVsZEZvY3VzKG5hbWU6IHN0cmluZykge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRGaWVsZEZvY3VzKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHJvdyBvZiBhIGZvcm0gY29udHJvbC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZmllbGROYW1lIFRoZSBmb3JtIGNvbnRyb2wgZmllbGQgbmFtZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcm93IFRoZSByb3cgbnVtYmVyLlxuICAgICAqIEBtZW1iZXJvZiBCYXNlRm9ybURhdGFGaWVsZFxuICAgICAqL1xuICAgIHNldEZvcm1GaWVsZFJvd1N0YXJ0KGZpZWxkTmFtZTogc3RyaW5nLCByb3c6IG51bWJlcikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRGb3JtRmllbGRSb3dTdGFydChmaWVsZE5hbWUsIHJvdyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY29sdW1uIHN0YXJ0IG9mIGEgZm9ybSBjb250cm9sLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmaWVsZE5hbWUgVGhlIGZvcm0gY29udHJvbCBmaWVsZCBuYW1lLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBjb2x1bW5TdGFydCBUaGUgY29sdW1uIHN0YXJ0LlxuICAgICAqIEBtZW1iZXJvZiBCYXNlRm9ybURhdGFGaWVsZFxuICAgICAqL1xuICAgIHNldEZvcm1GaWVsZENvbHVtblN0YXJ0KGZpZWxkTmFtZTogc3RyaW5nLCBjb2x1bW5TdGFydDogbnVtYmVyKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEZvcm1GaWVsZENvbHVtblN0YXJ0KGZpZWxkTmFtZSwgY29sdW1uU3RhcnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHdpZHRoIGVuZCBvZiBhIGZvcm0gY29udHJvbC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZmllbGROYW1lIFRoZSBmb3JtIGNvbnRyb2wgZmllbGQgbmFtZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gd2lkdGggVGhlIG5ldyBjb250cm9sIHdpZHRoLlxuICAgICAqIEBtZW1iZXJvZiBCYXNlRm9ybURhdGFGaWVsZFxuICAgICAqL1xuICAgIHNldEZvcm1GaWVsZENvbHVtbkVuZChmaWVsZE5hbWU6IHN0cmluZywgd2lkdGg6IG51bWJlcikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRGb3JtRmllbGRDb2x1bW5FbmQoZmllbGROYW1lLCB3aWR0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hpZnRzIGNvbHVtbnMgaW4gYW4gYWN0aXZlIGNvbnRyb2wgc3RhcnRpbmcgZnJvbSBhIGdpdmVuIGNvbHVtbiBieSBhIGdpdmVuIG9mZnNldC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gY29sdW1uU3RhcnQgVGhlIGNvbHVtbiBudW1iZXIgdG8gc3RhcnQgZnJvbS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gY29sdW1uT2Zmc2V0IFRoZSBvZmZzZXQgYnkgd2hpY2ggdG8gc2hpZnQuXG4gICAgICogQG1lbWJlcm9mIEJhc2VGb3JtRGF0YUZpZWxkXG4gICAgICovXG4gICAgc2hpZnRDb2x1bW5zQnlPZmZzZXQoY29sdW1uU3RhcnQ6IG51bWJlciwgY29sdW1uT2Zmc2V0OiBudW1iZXIpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2hpZnRDb2x1bW5zQnlPZmZzZXQoY29sdW1uU3RhcnQsIGNvbHVtbk9mZnNldCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gYSBmb3JtIGZpZWxkIGNvbnRhaW5lci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gY29sdW1uTnVtYmVyIFRoZSBjb2x1bW4gbnVtYmVyLlxuICAgICAqIEBtZW1iZXJvZiBCYXNlRm9ybURhdGFGaWVsZFxuICAgICAqL1xuICAgIHNldENvbHVtbnMoY29sdW1uTnVtYmVyOiBudW1iZXIpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0Q29sdW1ucyhjb2x1bW5OdW1iZXIpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uL0ZpZWxkQ29udGFpbmVyLnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcbiAgdHlwZSBDdXN0b21Hcm91cEZvcm1hdEZ1bmN0aW9uID0gKG5hbWU6IHN0cmluZywgY291bnQ6IG51bWJlcikgPT4gc3RyaW5nO1xuICB0eXBlIFJvd0Z1bmN0aW9uID0gKGlkOiBzdHJpbmcpID0+IHZvaWQ7XG5cbiAgaW50ZXJmYWNlIERyb3BFdmVudENvbnRleHQge1xuICAgIHNvdXJjZUlkOiBzdHJpbmcgfCBudW1iZXI7XG4gICAgdGFyZ2V0SWQ6IHN0cmluZyB8IG51bWJlcjtcbiAgICBkcm9wSWQ6IHN0cmluZyB8IG51bWJlcjtcbiAgICBzb3VyY2VPYmo6IGFraW9tYS5zd2F0LkJhc2VHcmlkO1xuICAgIHRhcmdldE9iajogYWtpb21hLnN3YXQuQmFzZUdyaWQ7XG4gICAgc291cmNlQ29sOiBudW1iZXI7XG4gICAgdGFyZ2V0Q29sOiBudW1iZXI7XG4gIH1cblxuICAvKipcbiAgICogR3JpZCBPYmplY3RcbiAgICogQGV4cG9ydFxuICAgKiBAY2xhc3MgQmFzZUdyaWRcbiAgICogQGV4dGVuZHMge0ZpZWxkQ29udGFpbmVyfVxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIEJhc2VHcmlkIGV4dGVuZHMgYWtpb21hLnN3YXQuRmllbGRDb250YWluZXIge1xuICAgIHByaXZhdGUgX2RhdGFTb3VyY2U6IGFraW9tYS5zd2F0LkRhdGFTb3VyY2U7XG4gICAgcHJpdmF0ZSBfZ3JpZENvbE1hcDogeyBbbmFtZTogc3RyaW5nXTogYWtpb21hLnN3YXQuR3JpZENvbCB9ID0ge307XG4gICAgcHJpdmF0ZSBfZ3JpZENvbE5hbWVzOiBBcnJheTxzdHJpbmc+ID0gW107XG4gICAgcHJpdmF0ZSBfZ3JpZENvbENvbnRyb2xsZXJzOiBBcnJheTxhbnk+ID0gW107XG4gICAgcHJpdmF0ZSBfZ3JpZENvbENvbnRyb2xsZXJNYXA6IHsgW25hbWU6IHN0cmluZ106IGFueSB9ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBBbiBhcnJheSBjb250YWluaW5nIHRoZSBncmlkIGNvbHVtbnMgbmFtZXNcbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKiBAdHlwZSB7QXJyYXk8c3RyaW5nPn1cbiAgICAgKi9cbiAgICBnZXQgZ3JpZENvbE5hbWVzKCk6IEFycmF5PHN0cmluZz4ge1xuICAgICAgaWYgKHRoaXMuX2dyaWRDb2xDb250cm9sbGVycy5sZW5ndGggPT09IDApXG4gICAgICAgIHRoaXMuX2ZpbGxHcmlkQ29scygpO1xuXG4gICAgICByZXR1cm4gdGhpcy5fZ3JpZENvbE5hbWVzO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IGdyaWRDb2xDb250cm9sbGVycygpOiBBcnJheTxhbnk+IHtcbiAgICAgIGlmICh0aGlzLl9ncmlkQ29sQ29udHJvbGxlcnMubGVuZ3RoID09PSAwKVxuICAgICAgICB0aGlzLl9maWxsR3JpZENvbHMoKTtcblxuICAgICAgcmV0dXJuIHRoaXMuX2dyaWRDb2xDb250cm9sbGVycztcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldCBncmlkQ29sQ29udHJvbGxlck1hcCgpOiB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSB7XG4gICAgICBpZiAodGhpcy5fZ3JpZENvbENvbnRyb2xsZXJzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgdGhpcy5fZmlsbEdyaWRDb2xzKCk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9ncmlkQ29sQ29udHJvbGxlck1hcDtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9maWxsR3JpZENvbHMoKSB7XG4gICAgICB0aGlzLl9ncmlkQ29sQ29udHJvbGxlcnMgPSB0aGlzLl9jb250cm9sbGVyLmNoaWxkcy5maWx0ZXIoKGNvbnRyb2xsZXI6IGFueSkgPT5cbiAgICAgICAgY29udHJvbGxlci52aWV3ID09PSAnZGF0YWdyaWRjb2wyJyk7XG5cbiAgICAgIHRoaXMuX2dyaWRDb2xDb250cm9sbGVyTWFwID0gdGhpcy5fZ3JpZENvbENvbnRyb2xsZXJzLnJlZHVjZSgobWFwOiBhbnksIGNvbnRyb2xsZXI6IGFueSkgPT4gKFxuICAgICAgICBtYXBbY29udHJvbGxlci5vcHQubmFtZS50b0xvd2VyQ2FzZSgpXSA9IGNvbnRyb2xsZXIsIG1hcFxuICAgICAgKSwge30pO1xuXG4gICAgICB0aGlzLl9ncmlkQ29sTmFtZXMgPSB0aGlzLl9ncmlkQ29sQ29udHJvbGxlcnMubWFwKChjb250cm9sbGVyOiBhbnkpID0+IChcbiAgICAgICAgY29udHJvbGxlci5vcHQubmFtZVxuICAgICAgKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGxpbmtlZCBidXNpbmVzcyBlbnRpdHkgdG8gdGhpcyBmb3JtXG4gICAgICogQHJlYWRvbmx5XG4gICAgICogQHR5cGUge0RhdGFTb3VyY2V9XG4gICAgICovXG4gICAgZ2V0IGRhdGFTb3VyY2UoKTogYWtpb21hLnN3YXQuRGF0YVNvdXJjZSB7XG4gICAgICBpZiAoIXRoaXMuX2RhdGFTb3VyY2UpXG4gICAgICAgIHRoaXMuX2RhdGFTb3VyY2UgPSA8YWtpb21hLnN3YXQuRGF0YVNvdXJjZT4oYWtpb21hLnN3YXQuU3dhdEZhY3RvcnkuY3JlYXRlU3dhdE9iamVjdCh0aGlzLl9keW5PYmplY3QuZ2V0TGluaygnREFUQTpTUkMnKSkpO1xuXG4gICAgICByZXR1cm4gdGhpcy5fZGF0YVNvdXJjZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZ3JpZCBlbmFibGVkIG1vZGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQgZW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmlzRW5hYmxlZCgpO1xuICAgIH1cblxuICAgIHNldCBlbmFibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEVkaXRhYmxlKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9taXNlIGZvciB3YWl0aW5nIG9uIGRlZmF1bHQgZmlsdGVyIHRvIGJlIGxvYWRlZCBpbiBHcmlkXG4gICAgICogQHR5cGUge1Byb21pc2V9XG4gICAgICovXG4gICAgZ2V0IGRlZmF1bHRGaWx0ZXJMb2FkZXIoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLkZpbHRlck1hbmFnZXIub0R5blNlbGVjdFByb21pc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvbWlzZSBsb2FkZXIgZm9yIGhlYWRlciBtZW51c1xuICAgICAqL1xuICAgIGdldCBwYW5lbEhlYWRlck1lbnVzTG9hZGVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgcmV0dXJuIHRoaXMuY29udHJvbGxlci5GaWx0ZXJNYW5hZ2VyLnBhbmVsTWVudUxvYWRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFdmVudCBwYXlsb2FkXG4gICAgICovXG4gICAgZ2V0IGV2ZW50KCk6IERyb3BFdmVudENvbnRleHQgfCB1bmRlZmluZWQge1xuICAgICAgaWYoIXRoaXMuZHluT2JqZWN0Py5ha0V2ZW50KVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICBjb25zdCBldmVudDogRHJvcEV2ZW50Q29udGV4dCA9IHsgLi4uKHRoaXMuZHluT2JqZWN0Py5ha0V2ZW50ID8/IHt9KSB9O1xuXG4gICAgICBpZih0aGlzLmR5bk9iamVjdD8uYWtFdmVudD8uc291cmNlT2JqKVxuICAgICAgICBldmVudC5zb3VyY2VPYmogPSBha2lvbWEuc3dhdC5Td2F0RmFjdG9yeS5jcmVhdGVTd2F0T2JqZWN0KHRoaXMuZHluT2JqZWN0LmFrRXZlbnQuc291cmNlT2JqKSBhcyBha2lvbWEuc3dhdC5CYXNlR3JpZDtcbiAgICAgIGlmKHRoaXMuZHluT2JqZWN0Py5ha0V2ZW50Py50YXJnZXRPYmopXG4gICAgICAgIGV2ZW50LnRhcmdldE9iaiA9IGFraW9tYS5zd2F0LlN3YXRGYWN0b3J5LmNyZWF0ZVN3YXRPYmplY3QodGhpcy5keW5PYmplY3QuYWtFdmVudC50YXJnZXRPYmopIGFzIGFraW9tYS5zd2F0LkJhc2VHcmlkO1xuXG4gICAgICByZXR1cm4gZXZlbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIGdyaWQgY29sdW1uIG9iamVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBncmlkIGNvbHVtbiBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEByZXR1cm5zIHtHcmlkQ29sfVxuICAgICAqL1xuICAgIGdldEdyaWRDb2wobmFtZTogc3RyaW5nKTogYWtpb21hLnN3YXQuR3JpZENvbCB7XG4gICAgICBuYW1lID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICBpZiAoIXRoaXMuX2dyaWRDb2xNYXBbbmFtZV0pXG4gICAgICAgIHRoaXMuX2dyaWRDb2xNYXBbbmFtZV0gPSA8YWtpb21hLnN3YXQuR3JpZENvbD4oYWtpb21hLnN3YXQuU3dhdEZhY3RvcnkuY3JlYXRlU3dhdE9iamVjdCh0aGlzLmdyaWRDb2xDb250cm9sbGVyTWFwW25hbWVdKSk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9ncmlkQ29sTWFwW25hbWVdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBjaGVjayBpZiBwYW5lbCBNZW51cyBhcmUgbG9hZGVkXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaXNQYW5lbEhlYWRlck1lbnVzTG9hZGVkKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuY29udHJvbGxlci5pc1BhbmVsSGVhZGVyTWVudXNMb2FkZWQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIHJlYWRpbmcgZmlsdGVyIHBhbmVsIG1hbnUgc3RhdGVzXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgTmFtZSBvZiBwYW5lbCBtZW51XG4gICAgICovXG4gICAgZ2V0UGFuZWxGaWx0ZXJTdGF0ZShuYW1lOiBzdHJpbmcpOiBhbnkge1xuICAgICAgcmV0dXJuIHRoaXMuY29udHJvbGxlci5GaWx0ZXJNYW5hZ2VyLmdldFBhbmVsRmlsdGVyU3RhdGUobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCBmb3IgZ2V0dGluZyBhIGdyaWQgY29sdW1uIHNjcmVlbiB2YWx1ZS5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGdyaWQuZ2V0R3JpZENvbCgnbXlncmlkQ29sJykuc2NyZWVuVmFsdWUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGdyaWQgY29sdW1uIG5hbWVcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBnZXRTY3JlZW5WYWx1ZShuYW1lOiBzdHJpbmcpOiBhbnkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0R3JpZENvbChuYW1lKS5zY3JlZW5WYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgbWV0aG9kIGZvciBnZXR0aW5nIGEgZ3JpZCBjb2x1bW4gbG9va3VwIGtleSB2YWx1ZS5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGdyaWQuZ2V0R3JpZENvbCgnbXlncmlkQ29sJykubG9va3VwS2V5VmFsdWUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGdyaWQgY29sIG5hbWVcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBnZXRMb29rdXBLZXlWYWx1ZShuYW1lOiBzdHJpbmcpOiBhbnkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0R3JpZENvbChuYW1lKS5sb29rdXBLZXlWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgbWV0aG9kIGZvciBnZXR0aW5nIGEgZ3JpZCBjb2x1bW4gZGF0YSB2YWx1ZS5cbiAgICAgKiBFcXVpdmFsZW50IHRvIGdyaWQuZ2V0R3JpZENvbCgnbXlncmlkQ29sJykuZGF0YVZhbHVlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBncmlkIGNvbHVtbiBuYW1lXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgZ2V0RGF0YVZhbHVlKG5hbWU6IHN0cmluZyk6IGFueSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRHcmlkQ29sKG5hbWUpLmRhdGFWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgbWV0aG9kIGZvciBnZXR0aW5nIGEgZ3JpZCBjb2x1bW4gbGFiZWwuXG4gICAgICogRXF1aXZhbGVudCB0byBncmlkLmdldEdyaWRDb2woJ215Z3JpZGNvbCcpLmxhYmVsLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBncmlkIGNvbHVtbiBuYW1lIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZ2V0TGFiZWwobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEdyaWRDb2wobmFtZSkubGFiZWw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCBmb3Igc2V0dGluZyBhIGdyaWQgY29sdW1uIGxhYmVsIGJ5IHRoZSBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGdyaWQgY29sdW1uIG5hbWUgKGNhc2UtaW5zZW5zaXRpdmUpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxhYmVsIFRoZSBuZXcgbGFiZWxcbiAgICAgKi9cbiAgICBzZXRMYWJlbChuYW1lOiBzdHJpbmcsIGxhYmVsOiBzdHJpbmcpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0TGFiZWwobmFtZSwgbGFiZWwpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsZWFycyBoYXNDaGFuZ2VzIChkaXJ0eSBzdGF0ZSlcbiAgICAgKi9cbiAgICBjbGVhckhhc0NoYW5nZXMoKSB7XG4gICAgICBpZiAodGhpcy5kYXRhU291cmNlKVxuICAgICAgICB0aGlzLmRhdGFTb3VyY2UuY29udHJvbGxlci5jbGVhckhhc0NoYW5nZXMoKTtcbiAgICAgIGVsc2VcbiAgICAgICAgdGhpcy5fY29udHJvbGxlci5jbGVhckhhc0NoYW5nZXMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBkaXJ0eSBzdGF0ZSBmb3IgYSByZWNvcmQgaWRlbnRpZmllZCBieSB0aGUgcHJpbWFyeUtleVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZGlydHlTdGF0ZVN0YXR1cyBUcnVlIG9yIEZhbHNlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHByaW1hcnlLZXkgVGhlIHZhbHVlIGNvcnJlc3BvbmRpbmcgdG8gdGhlIEtleUZpZWxkIGF0dHJpYnV0ZSBpbiB0aGUgZGF0YVNvdXJjZTtcbiAgICAgKiB1c2VkIHRvIHVuaXF1ZWx5IGlkZW50aWZ5IHRoZSByZWNvcmQgZm9yIHdoaWNoIHRvIHNldCB0aGUgbmV3IHZhbHVlOyBPcHRpb25hbFxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHNldEhhc0NoYW5nZXMoZGlydHlTdGF0ZVN0YXR1czogYm9vbGVhbiwgcHJpbWFyeUtleT86IGFueSk6IHZvaWQge1xuICAgICAgdGhpcy5jb250cm9sbGVyLnNldEhhc0NoYW5nZXMoZGlydHlTdGF0ZVN0YXR1cywgcHJpbWFyeUtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhwb3NlIHRoZSBjZWxsIG9mIHRoZSBncmlkIGJ5IGEgZ2l2ZW4gcm93SUQgYW5kIGNvbEluZGV4XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHJvd0lkXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGNvbEluZGV4XG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgZ2V0Q2VsbEJ5Um93QW5kQ29sKHJvd0lkOiBzdHJpbmcsIGNvbEluZGV4OiBudW1iZXIpOiBhbnkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuZ2V0Q2VsbEJ5Um93QW5kQ29sKHJvd0lkLCBjb2xJbmRleCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYWtFdmVudCBmb3IgYSBjZWxsLiBUaGUgYWtFdmVudCBjb250YWlucyB0aGUgY3VycmVudFZhbHVlIGFuZCBsYXN0VmFsdWUgb2YgdGhlIGNlbGwuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHJvd0lkXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGNvbEluZGV4XG4gICAgICogQHJldHVybiB7b2JqZWN0fG51bGx9XG4gICAgICovXG4gICAgZ2V0Q2VsbEFrRXZlbnQocm93SWQ6IHN0cmluZywgY29sSW5kZXg6IG51bWJlcik6IG9iamVjdHxudWxsIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldENlbGxBa0V2ZW50KHJvd0lkLCBjb2xJbmRleCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyBkcmFnIGFuZCBkcm9wIG9uIGEgZ3JpZFxuICAgICAqL1xuICAgIGVuYWJsZURyYWdBbmREcm9wKCkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5lbmFibGVEcmFnQW5kRHJvcCh0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEaXNhYmxlcyBkcmFnIGFuZCBkcm9wIG9uIGEgZ3JpZFxuICAgICAqL1xuICAgIGRpc2FibGVEcmFnQW5kRHJvcCgpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuZW5hYmxlRHJhZ0FuZERyb3AoZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBkcmFnIGFuZCBkcm9wIGlzIGVuYWJsZWQgb24gYSBncmlkXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaGFzRHJhZ0FuZERyb3BFbmFibGVkKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRyb2xsZXIuaGFzRHJhZ0FuZERyb3BFbmFibGVkKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgZHJhZyBhbmQgZHJvcCBiZWhhdmlvdXIgb24gYSBncmlkXG4gICAgICogQHBhcmFtIGRyYWdEcm9wQmVoYXZpb3VyICdkZWZhdWx0JyB8ICdjb3B5JyB8ICdtb3ZlJyBUeXBlIG9mIGRyYWcgYW5kIGRyb3AgYmVoYXZpb3VyXG4gICAgICovXG4gICAgc2V0RHJhZ0FuZERyb3BCZWhhdmlvdXIoZHJhZ0Ryb3BCZWhhdmlvdXI6ICdkZWZhdWx0JyB8ICdjb3B5JyB8ICdtb3ZlJykge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXREcmFnQW5kRHJvcEJlaGF2aW91cihkcmFnRHJvcEJlaGF2aW91cik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyBhdXRvRm9jdXMgb24gYSBncmlkIGFmdGVyIGEgZGF0YSByZWZyZXNoXG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgZW5hYmxlQXV0b0ZvY3VzKCk6IHZvaWQge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zZXRBdXRvRm9jdXModHJ1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGlzYWJsZXMgYXV0b0ZvY3VzIG9uIGEgZ3JpZCBhZnRlciBhIGRhdGEgcmVmcmVzaFxuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqL1xuICAgIGRpc2FibGVBdXRvRm9jdXMoKTogdm9pZCB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEF1dG9Gb2N1cyhmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBnZXR0aW5nIHRoZSBjb2x1bW4gaW5kZXggYnkgaWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgZ3JpZCBjb2x1bW4gbmFtZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0Q29sSW5kZXhCeUlkKG5hbWU6IHN0cmluZyk6IG51bWJlciB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5nZXRDb2xJbmRleEJ5SWQobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBoYW5kbGluZyBhIGNsYXNzLCBpZCBvciBhbnkgcHJvcGVydGllXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gICAgICogQHBhcmFtIHsqfSBzdHlsZXMgb2JqZWN0IHdoZXJlIHRoZSBrZXkgaXMgcHJvcGVydHkgbmFtZSBhbmQgdmFsdWUgaXMgdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0aWUuXG4gICAgICogaW4gY2FzZSB3aGVyZSByZW1vdmUgaXMgdHJ1ZSwgcHJvcGVydHkgdmFsdWVzIHNob3VsZCBiZSBlbXB0eSBzdHJpbmcuXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZW1vdmUgdHJ1ZSBmb3IgcmVtb3ZlLCBmYWxzZSBvciB1bmRlZmluZWQgZm9yIGFkZFxuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqL1xuICAgIGhhbmRsZVByb3BlcnRpZXMoc2VsZWN0b3I6IHN0cmluZywgc3R5bGVzOiBhbnksIHJlbW92ZTogYm9vbGVhbikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5oYW5kbGVQcm9wZXJ0aWVzKHNlbGVjdG9yLCBzdHlsZXMsIHJlbW92ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdXNlZCB0byBzaG93IGEgY29sdW1uIGluIHRoZSBncmlkLlxuICAgICAqIEBtZW1iZXJvZiBncmlkXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQHBhcmFtIHtOdW1iZXIgfCBTdHJpbmd9IGlkZW50aWZpZXJcbiAgICAgKi9cbiAgICBzaG93Q29sdW1uKGlkZW50aWZpZXI6IE51bWJlciB8IFN0cmluZykge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5zaG93Q29sdW1uKGlkZW50aWZpZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZ1bmN0aW9uIHVzZWQgdG8gZW5hYmxlIGEgY29sdW1uIGluIHRoZSBncmlkLlxuICAgICAqIEBtZW1iZXJvZiBncmlkXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQHBhcmFtIHtOdW1iZXIgfCBTdHJpbmd9IGlkZW50aWZpZXJcbiAgICAgKi9cbiAgICBlbmFibGVDb2x1bW4oaWRlbnRpZmllcjogTnVtYmVyIHwgU3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmVuYWJsZUNvbHVtbihpZGVudGlmaWVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB1c2VkIHRvIGhpZGUgYSBjb2x1bW4gaW4gdGhlIGdyaWQuXG4gICAgICogQG1lbWJlcm9mIGdyaWRcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAcGFyYW0ge051bWJlciB8IFN0cmluZ30gaWRlbnRpZmllclxuICAgICAqL1xuICAgIGhpZGVDb2x1bW4oaWRlbnRpZmllcjogTnVtYmVyIHwgU3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmhpZGVDb2x1bW4oaWRlbnRpZmllcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdXNlZCB0byBkaXNhYmxlIGEgY29sdW1uIGluIHRoZSBncmlkLlxuICAgICAqIEBtZW1iZXJvZiBncmlkXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQHBhcmFtIHtOdW1iZXIgfCBTdHJpbmd9IGlkZW50aWZpZXJcbiAgICAgKi9cbiAgICBkaXNhYmxlQ29sdW1uKGlkZW50aWZpZXI6IE51bWJlciB8IFN0cmluZykge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5kaXNhYmxlQ29sdW1uKGlkZW50aWZpZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZGluZyBjbGFzc2VzIHdoaWxlIGtlZXBpbmcgdGhlIG9sZCBvbmVzXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gICAgICogQHBhcmFtIHthcnJheX0gY2xhc3NlcyBhcnJheSBvZiBjbGFzcyBuYW1lc1xuICAgICAqIEByZXR1cm5zIHt2b2lkfVxuICAgICAqL1xuICAgIGFkZENsYXNzKHNlbGVjdG9yOiBzdHJpbmcsIGNsYXNzZXM6IEFycmF5PHN0cmluZz4pIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuYWRkQ2xhc3Moc2VsZWN0b3IsIGNsYXNzZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92aW5nIGNsYXNzZXMgd2hpbGUga2VlcGluZyB0aGUgb2xkIG9uZXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JcbiAgICAgKiBAcGFyYW0ge2FycmF5fSBjbGFzc2VzIGFycmF5IG9mIGNsYXNzIG5hbWVzXG4gICAgICovXG4gICAgcmVtb3ZlQ2xhc3Moc2VsZWN0b3I6IHN0cmluZywgY2xhc3NlczogQXJyYXk8c3RyaW5nPikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5yZW1vdmVDbGFzcyhzZWxlY3RvciwgY2xhc3Nlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBzaG93aW5nIGEgZ2l2ZW4gY29udGV4dCBtZW51IGl0ZW1cbiAgICAgKiBAcGFyYW0gaXRlbUNvZGUgTmFtZSBvZiB0aGUgaXRlbSB0byBzaG93XG4gICAgICovXG4gICAgc2hvd0NvbnRleHRNZW51SXRlbShpdGVtQ29kZTogc3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmNvbnRleHRNZW51T2JqZWN0LnNob3dDb250ZXh0TWVudUl0ZW0oaXRlbUNvZGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgaGlkaW5nIGEgZ2l2ZW4gY29udGV4dCBtZW51IGl0ZW1cbiAgICAgKiBAcGFyYW0gaXRlbUNvZGUgTmFtZSBvZiB0aGUgaXRlbSB0byBoaWRlXG4gICAgICovXG4gICAgaGlkZUNvbnRleHRNZW51SXRlbShpdGVtQ29kZTogc3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmNvbnRleHRNZW51T2JqZWN0LmhpZGVDb250ZXh0TWVudUl0ZW0oaXRlbUNvZGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3Igc2hvd2luZyBhbGwgY29udGV4dCBtZW51IGl0ZW1zXG4gICAgICovXG4gICAgc2hvd0NvbnRleHRNZW51SXRlbXMoKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmNvbnRleHRNZW51T2JqZWN0LnNob3dDb250ZXh0TWVudUl0ZW1zKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBoaWRpbmcgYWxsIGNvbnRleHQgbWVudSBpdGVtc1xuICAgICAqL1xuICAgIGhpZGVDb250ZXh0TWVudUl0ZW1zKCkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5jb250ZXh0TWVudU9iamVjdC5oaWRlQ29udGV4dE1lbnVJdGVtcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgZW5hYmxpbmcgYSBnaXZlbiBjb250ZXh0IG1lbnUgaXRlbVxuICAgICAqIEBwYXJhbSBpdGVtQ29kZSBOYW1lIG9mIHRoZSBpdGVtIHRvIGVuYWJsZVxuICAgICAqL1xuICAgIGVuYWJsZUNvbnRleHRNZW51SXRlbShpdGVtQ29kZTogc3RyaW5nKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmNvbnRleHRNZW51T2JqZWN0LmVuYWJsZUNvbnRleHRNZW51SXRlbShpdGVtQ29kZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBkaXNhYmxpbmcgYSBnaXZlbiBjb250ZXh0IG1lbnUgaXRlbVxuICAgICAqIEBwYXJhbSBpdGVtQ29kZSBOYW1lIG9mIHRoZSBpdGVtIHRvIGRpc2FibGVcbiAgICAgKi9cbiAgICBkaXNhYmxlQ29udGV4dE1lbnVJdGVtKGl0ZW1Db2RlOiBzdHJpbmcpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuY29udGV4dE1lbnVPYmplY3QuZGlzYWJsZUNvbnRleHRNZW51SXRlbShpdGVtQ29kZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBlbmFibGluZyBhbGwgY29udGV4dCBtZW51IGl0ZW1zXG4gICAgICovXG4gICAgZW5hYmxlQ29udGV4dE1lbnVJdGVtcygpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuY29udGV4dE1lbnVPYmplY3QuZW5hYmxlQ29udGV4dE1lbnVJdGVtcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgZGlzYWJsaW5nIGFsbCBjb250ZXh0IG1lbnUgaXRlbXNcbiAgICAgKi9cbiAgICBkaXNhYmxlQ29udGV4dE1lbnVJdGVtcygpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuY29udGV4dE1lbnVPYmplY3QuZGlzYWJsZUNvbnRleHRNZW51SXRlbXMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNldCBmaWx0ZXJzIHRvIGRlZmF1bHQgYW5kIHJlZnJlc2ggdGhlIGdyaWRcbiAgICAgKi9cbiAgICByZXNldEFuZFJlZnJlc2goKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnJlc2V0QW5kUmVmcmVzaCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgZW5hYmxpbmcgb3IgZGlzYWJsaW5nIHRoZSBncmlkXG4gICAgICogQHBhcmFtIGVkaXRhYmxlIFRydWUgZm9yIGVuYWJsaW5nIHRoZSBncmlkLCBmYWxzZSBmb3IgZGlzYWJsaW5nIGl0XG4gICAgICovXG4gICAgc2V0RWRpdGFibGUoZWRpdGFibGU6IGJvb2xlYW4pIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuc2V0RWRpdGFibGUoZWRpdGFibGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgY2hlY2tpbmcgaWYgdGhlIGdyaWQgaXMgZW5hYmxlZFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmlzRW5hYmxlZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgZW5hYmxpbmcgdGhlIGNvbHVtbiBmaWx0ZXJzIGluIGEgZ3JpZFxuICAgICAqL1xuICAgIGVuYWJsZUNvbHVtbkZpbHRlcnMoKTogdm9pZCB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmVuYWJsZUNvbHVtbkZpbHRlcnMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgZm9yIGRpc2FibGluZyB0aGUgY29sdW1uIGZpbHRlcnMgaW4gYSBncmlkXG4gICAgICovXG4gICAgZGlzYWJsZUNvbHVtbkZpbHRlcnMoKTogdm9pZCB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmRpc2FibGVDb2x1bW5GaWx0ZXJzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIGZvciBmaWx0ZXJpbmcgb24gR3JpZFxuICAgICAqL1xuICAgIEZpbHRlckdvKCk6IHZvaWQge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5GaWx0ZXJHbygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBmb3IgZ2V0dGluZyBjdXJyZW50bHkgc2VsZWN0ZWQgcmVjb3JkcyBvZiBHcmlkXG4gICAgICovXG4gICAgZ2V0U2VsZWN0ZWRSZWNvcmRzKCk6IGFueVtdIHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmdldFNlbGVjdGVkUmVjb3JkcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdyb3VwcyB0aGUgZ3JpZCBieSB0aGUgZ2l2ZW4gY29sdW1uXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQHBhcmFtIHtudW1iZXIgfCBzdHJpbmd9IGlkZW50aWZpZXIgQ29sdW1uIGluZGV4fG5hbWUgdG8gZ3JvdXAgYnlcbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBtYXNrIE9wdGlvbmFsLCBhcnJheSwgZWFjaCB2YWx1ZSBvZiB3aGljaCBpcyBtYXBwZWQgdG8gdGhlIHJlbGF0ZWQgY29sdW1uXG4gICAgICogQG1lbWJlcm9mIGFrX2RhdGFncmlkMlxuICAgICAqL1xuICAgIGdyb3VwQnkoaWRlbnRpZmllcjogbnVtYmVyIHwgc3RyaW5nLCBtYXNrPzogc3RyaW5nW10pOiB2b2lkIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuZ3JvdXBCeShpZGVudGlmaWVyLCBtYXNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmdyb3VwcyB0aGUgZ3JpZCB0byByZXR1cm4gaXQgaW50byB0aGUgcGxhaW4gdmlld1xuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJvZiBha19kYXRhZ3JpZDJcbiAgICAgKi9cbiAgICB1bkdyb3VwKCk6IHZvaWQge1xuICAgICAgdGhpcy5fY29udHJvbGxlci51bkdyb3VwKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhwYW5kcyBhIGdyb3VwIG9mIHJvd3NcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZ3JvdXBOYW1lIFZhbHVlIHVzZWQgdG8gZGV0ZXJtaW5lIHdoYXQgZ3JvdXAgdG8gZXhwYW5kIChhIGNvbW1vbiB2YWx1ZSBmb3IgYWxsIHJvd3MgaW4gdGhlIGdyb3VwKVxuICAgICAqIEBtZW1iZXJvZiBha19kYXRhZ3JpZDJcbiAgICAgKi9cbiAgICBleHBhbmRHcm91cChncm91cE5hbWU6IHN0cmluZykge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5leHBhbmRHcm91cChncm91cE5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbGxhcHNlcyBhIGdyb3VwIG9mIHJvd3NcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZ3JvdXBOYW1lIFZhbHVlIHVzZWQgdG8gZGV0ZXJtaW5lIHdoYXQgZ3JvdXAgdG8gY29sbGFwc2UgKGEgY29tbW9uIHZhbHVlIGZvciBhbGwgcm93cyBpbiB0aGUgZ3JvdXApXG4gICAgICogQG1lbWJlcm9mIGFrX2RhdGFncmlkMlxuICAgICAqL1xuICAgIGNvbGxhcHNlR3JvdXAoZ3JvdXBOYW1lOiBzdHJpbmcpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuY29sbGFwc2VHcm91cChncm91cE5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4cGFuZHMgYWxsIGdyb3Vwc1xuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJvZiBha19kYXRhZ3JpZDJcbiAgICAgKi9cbiAgICBleHBhbmRBbGxHcm91cHMoKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLmV4cGFuZEFsbEdyb3VwcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbGxhcHNlcyBhbGwgZ3JvdXBzXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlcm9mIGFrX2RhdGFncmlkMlxuICAgICAqL1xuICAgIGNvbGxhcHNlQWxsR3JvdXBzKCkge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5jb2xsYXBzZUFsbEdyb3VwcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGN1c3RvbUdyb3VwRm9ybWF0IHByb3BlcnR5IG9uIHRoZSBncmlkIHRvIGN1c3RvbWl6ZSB0aGUgZ3JvdXAgc3VtbWFyeSByb3cgYXBwZWFyYW5jZVxuICAgICAqIEBwYXJhbSB7Q3VzdG9tR3JvdXBGb3JtYXRGdW5jdGlvbn0gY3VzdG9tR3JvdXBGb3JtYXQgVmFsdWUgdXNlZCB0byBkZXRlcm1pbmUgd2hhdCBncm91cCB0byBjb2xsYXBzZSAoYSBjb21tb24gdmFsdWUgZm9yIGFsbCByb3dzIGluIHRoZSBncm91cClcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgYWtfZGF0YWdyaWQyXG4gICAgICovXG4gICAgc2V0Q3VzdG9tR3JvdXBGb3JtYXQoY3VzdG9tR3JvdXBGb3JtYXQgOiBDdXN0b21Hcm91cEZvcm1hdEZ1bmN0aW9uKSB7XG4gICAgICB0aGlzLl9jb250cm9sbGVyLnNldEN1c3RvbUdyb3VwRm9ybWF0KGN1c3RvbUdyb3VwRm9ybWF0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyB0aHJvdWdoIGFsbCByb3dzIGluIHNvbWUgZ3JvdXBcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBOYW1lIG9mIHRoZSBncm91cFxuICAgICAqIEBwYXJhbSB7Um93RnVuY3Rpb259IHJvd0Z1bmN0aW9uIEZ1bmN0aW9uIHdoaWNoIGdldHMgcm93IGlkIGFzIHRoZSBpbmNvbWluZyBhcmd1bWVudFxuICAgICAqIEBtZW1iZXJvZiBha19kYXRhZ3JpZDJcbiAgICAgKi9cbiAgICBmb3JFYWNoUm93SW5Hcm91cChuYW1lOiBzdHJpbmcsIHJvd0Z1bmN0aW9uOiBSb3dGdW5jdGlvbikge1xuICAgICAgdGhpcy5fY29udHJvbGxlci5mb3JFYWNoUm93SW5Hcm91cChuYW1lLCByb3dGdW5jdGlvbik7XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9CYXNlR3JpZC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG4gIC8qKlxuICAgKiBHcmlkIE9iamVjdFxuICAgKiBAZXhwb3J0XG4gICAqIEBjbGFzcyBHcmlkXG4gICAqIEBleHRlbmRzIHtCYXNlR3JpZH1cbiAgICovXG4gIGV4cG9ydCBjbGFzcyBHcmlkIGV4dGVuZHMgYWtpb21hLnN3YXQuQmFzZUdyaWQge1xuICAgIC8qKlxuICAgICAqIENvdW50cyByZWNvcmRzIGZyb20gdGhlIGF0dGFjaGVkIGRhdGFzb3VyY2VcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgYWtfZGF0YWdyaWQyXG4gICAgICovXG4gICAgY291bnRSZWNvcmRzKCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udHJvbGxlci5jb3VudFJlY29yZHMoKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL0dyaWQudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIERhdGFWaWV3IE9iamVjdFxuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgRGF0YVZpZXdcbiAgICAgKiBAZXh0ZW5kcyB7R3JpZH1cbiAgICAgKi9cbiAgZXhwb3J0IGNsYXNzIERhdGFWaWV3IGV4dGVuZHMgYWtpb21hLnN3YXQuR3JpZCB7XG5cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4vQmFzZUdyaWQudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgICAqIFByb3BlcnR5R3JpZCBPYmplY3RcbiAgICAgKiBAZXhwb3J0XG4gICAgICogQGNsYXNzIFByb3BlcnR5R3JpZFxuICAgICAqIEBleHRlbmRzIHsgQmFzZUdyaWQgfVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgUHJvcGVydHlHcmlkIGV4dGVuZHMgYWtpb21hLnN3YXQuQmFzZUdyaWQge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL0dyaWQudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBUcmVlR3JpZCBPYmplY3RcbiAgICogQGV4cG9ydFxuICAgKiBAY2xhc3MgVHJlZUdyaWRcbiAgICogQGV4dGVuZHMgeyBHcmlkIH1cbiAgICovXG4gIGV4cG9ydCBjbGFzcyBUcmVlR3JpZCBleHRlbmRzIGFraW9tYS5zd2F0LkdyaWQge1xuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBleHBhbmQgYWxsIHRyZWUgbm9kZXNcbiAgICAgKiBAcGFyYW0gbGV2ZWxzIExldmVscyBvZiBub2RlcyB0byBleHBhbmQsIGRlZmF1bHQgLTEgZXhwYW5kcyBhbGwgbm9kZXNcbiAgICAgKiBAcGFyYW0gcm93SWQgT3B0aW9uYWwgcm93IGlkZW50aWZpZXIsIGRlZmF1bHQgc2V0IHRvIHJvb3Qgbm9kZSBpZFxuICAgICAqL1xuICAgIGV4cGFuZE5vZGVzKGxldmVscyA9IC0xLCByb3dJZD86IHN0cmluZykge1xuICAgICAgdGhpcy5jb250cm9sbGVyLmV4cGFuZE5vZGVzKGxldmVscywgcm93SWQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBjb2xsYXBzZSBhbGwgdHJlZSBub2Rlc1xuICAgICAqIEBwYXJhbSByb3dJZCBPcHRpb25hbCB0cmVlIHJvdyBpZGVudGlmaWVyLCBkZWZhdWx0IHNldCB0byByb290IG5vZGUgaWRcbiAgICAgKi9cbiAgICBjb2xsYXBzZU5vZGVzKHJvd0lkPzogc3RyaW5nKSB7XG4gICAgICB0aGlzLmNvbnRyb2xsZXIuY29sbGFwc2VOb2Rlcyhyb3dJZCk7XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vVmlzdWFsT2JqZWN0LnRzXCIgLz5cblxubmFtZXNwYWNlIGFraW9tYS5zd2F0IHtcblxuICAvKipcbiAgICAgKiBQcmltaXRpdmUgT2JqZWN0IEJhc2UgQ2xhc3NcbiAgICAgKiBAZXhwb3J0XG4gICAgICogQGNsYXNzIFByaW1pdGl2ZU9iamVjdFxuICAgICAqIEBleHRlbmRzIHtWaXN1YWxPYmplY3R9XG4gICAgICovXG4gIGV4cG9ydCBjbGFzcyBQcmltaXRpdmVPYmplY3QgZXh0ZW5kcyBha2lvbWEuc3dhdC5WaXN1YWxPYmplY3Qge1xuXG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuL1ByaW1pdGl2ZU9iamVjdC50c1wiIC8+XG5cbm5hbWVzcGFjZSBha2lvbWEuc3dhdCB7XG5cbiAgLyoqXG4gICAgICogSFRNTCBDb250ZW50IE9iamVjdFxuICAgICAqIEBleHBvcnRcbiAgICAgKiBAY2xhc3MgSFRNTENvbnRlbnRcbiAgICAgKiBAZXh0ZW5kcyB7UHJpbWl0aXZlT2JqZWN0fVxuICAgICAqL1xuICBleHBvcnQgY2xhc3MgSFRNTENvbnRlbnQgZXh0ZW5kcyBha2lvbWEuc3dhdC5QcmltaXRpdmVPYmplY3Qge1xuXG4gICAgcHJpdmF0ZSBfZm9ybURoeDogYW55O1xuICAgIHByaXZhdGUgX2h0bWxFbDogYW55O1xuXG4gICAgcHJpdmF0ZSBnZXQgZm9ybURoeCgpOiBhbnkge1xuICAgICAgaWYgKCF0aGlzLl9mb3JtRGh4KSB7XG4gICAgICAgIGNvbnN0IGZvcm0gPSB0aGlzLl9keW5PYmplY3QuZ2V0UGFyZW50T2ZUeXBlKCdmb3JtJyk7XG5cbiAgICAgICAgdGhpcy5fZm9ybURoeCA9IGZvcm0uY29udHJvbGxlci5kaHg7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLl9mb3JtRGh4O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IGh0bWxFbCgpIHtcbiAgICAgIGNvbnN0IGRoeCA9IHRoaXMuZm9ybURoeDtcblxuICAgICAgcmV0dXJuIGRoeC5pdGVtUHVsbFtkaHguaWRQcmVmaXggKyB0aGlzLm5hbWVdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAgICAgKiBUaGUgSFRNTCBjb250ZW50IGhpZGRlbiBtb2RlIChvcHBvc2l0ZSBvZiB2aXNpYmxlKVxuICAgICAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgICAgICovXG4gICAgZ2V0IGhpZGRlbigpOiBib29sZWFuIHtcbiAgICAgIGNvbnN0IGh0bWxFbCA9IHRoaXMuaHRtbEVsO1xuICAgICAgY29uc3QgZGlzcGxheVN0eWxlID0gaHRtbEVsLnN0eWxlLmRpc3BsYXkudG9Mb3dlckNhc2UoKTtcblxuICAgICAgcmV0dXJuIChkaXNwbGF5U3R5bGUgPT09ICdoaWRkZW4nIHx8IGRpc3BsYXlTdHlsZSA9PT0gJ25vbmUnKTtcbiAgICB9XG5cbiAgICBzZXQgaGlkZGVuKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICBjb25zdCBodG1sRWwgPSB0aGlzLmh0bWxFbDtcblxuICAgICAgaWYgKHZhbHVlKVxuICAgICAgICBodG1sRWwuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgIGVsc2VcbiAgICAgICAgaHRtbEVsLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgICAgICogVGhlIEhUTUwgY29udGVudCB2aXNpYmxlIG1vZGUgKG9wcG9zaXRlIG9mIGhpZGRlbilcbiAgICAgICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICAgICAqL1xuICAgIGdldCB2aXNpYmxlKCk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuICF0aGlzLmhpZGRlbjtcbiAgICB9XG5cbiAgICBzZXQgdmlzaWJsZSh2YWx1ZTogYm9vbGVhbikge1xuICAgICAgdGhpcy5oaWRkZW4gPSAhdmFsdWU7XG4gICAgfVxuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9QcmltaXRpdmVPYmplY3QudHNcIiAvPlxuXG5uYW1lc3BhY2UgYWtpb21hLnN3YXQge1xuXG4gIC8qKlxuICAgKiBVcGxvYWQgT2JqZWN0XG4gICAqIEBleHBvcnRcbiAgICogQGNsYXNzIFVwbG9hZFxuICAgKiBAZXh0ZW5kcyB7UHJpbWl0aXZlT2JqZWN0fVxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIFVwbG9hZCBleHRlbmRzIGFraW9tYS5zd2F0LlByaW1pdGl2ZU9iamVjdCB7XG5cbiAgICAvKipcbiAgICAgKiBHZXQgZGh4IHJlc3BvbnNlIGFmdGVyIHVwbG9hZC5cbiAgICAgKi9cbiAgICBnZXQgcmVzcG9uc2UoKTogYW55IHtcbiAgICAgIHJldHVybiB0aGlzLl9jb250cm9sbGVyLmRoeC5fbG9hZGVyLnJlc3BvbnNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGwgY2xlYXIgbWV0aG9kIG9uIGRoeC5cbiAgICAgKi9cbiAgICBjbGVhcigpOiB2b2lkIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xsZXIuZGh4LmNsZWFyKCk7XG4gICAgfVxuICB9XG59XG4iXX0=