UNPKG

angular-xml-editor

Version:
4,039 lines 439 kB
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('rxjs'), require('@angular/core'), require('@angular/common'), require('@angular/forms')) :
    typeof define === 'function' && define.amd ? define('angular-xml-editor', ['exports', 'rxjs', '@angular/core', '@angular/common', '@angular/forms'], factory) :
    (factory((global['angular-xml-editor'] = {}),global.rxjs,global.ng.core,global.ng.common,global.ng.forms));
}(this, (function (exports,rxjs,i0,i1,forms) { 'use strict';

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditorDebugger = /** @class */ (function () {
        function XmlEditorDebugger() {
            this.actualCursorPosChanged$ = new rxjs.Subject();
            this.inputSelectionChanged$ = new rxjs.Subject();
        }
        /**
         * @param {?} pos
         * @return {?}
         */
        XmlEditorDebugger.prototype.setActualCursorPos = /**
         * @param {?} pos
         * @return {?}
         */
            function (pos) {
                this.actualCursorPosChanged$.next(pos);
            };
        /**
         * @param {?} info
         * @return {?}
         */
        XmlEditorDebugger.prototype.setInputSelection = /**
         * @param {?} info
         * @return {?}
         */
            function (info) {
                this.inputSelectionChanged$.next(info);
            };
        /**
         * @return {?}
         */
        XmlEditorDebugger.prototype.ngOnDestroy = /**
         * @return {?}
         */
            function () {
                this.actualCursorPosChanged$.complete();
                this.inputSelectionChanged$.complete();
            };
        return XmlEditorDebugger;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlToolbox = /** @class */ (function () {
        function XmlToolbox() {
        }
        /**
         * @param {?} node
         * @return {?}
         */
        XmlToolbox.IsTextOrCommentNode = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                switch (node.nodeType) {
                    case Node.TEXT_NODE: // text node
                    case Node.COMMENT_NODE:
                        return true;
                    default:
                        return false;
                }
                // return ((node.nodeType === System.Xml.XmlText) || (node.nodeType === System.Xml.XmlComment));
            };
        /**
         * @param {?} node
         * @return {?}
         */
        XmlToolbox.GetNodeDebugContext = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                if (node === null || node === undefined) {
                    return 'NULL';
                }
                if (node.nodeType === Node.TEXT_NODE) {
                    if (node.textContent === ' ' || node.textContent === String.fromCharCode(160)) {
                        return "TextContent!Parent=" + XmlToolbox.GetNodeDebugContext(node.parentNode);
                    }
                    else {
                        return "TextContent='" + node.textContent + "'";
                    }
                }
                /** @type {?} */
                var asElem = /** @type {?} */ (node);
                if (asElem === undefined) {
                    return "localName: " + node.nodeName + ", nodeType:" + node.nodeType;
                }
                else {
                    return asElem.outerHTML;
                }
            };
        return XmlToolbox;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var Xml2htmlAttributeWorker = /** @class */ (function () {
        function Xml2htmlAttributeWorker(rules) {
            this.rules = rules;
        }
        /** writes the given attributes to the html node in data-attribute-syntax **/
        /**
         * writes the given attributes to the html node in data-attribute-syntax *
         * @param {?} xmlElement
         * @param {?} htmlElement
         * @return {?}
         */
        Xml2htmlAttributeWorker.prototype.writeAllXmlAttributesToHtml = /**
         * writes the given attributes to the html node in data-attribute-syntax *
         * @param {?} xmlElement
         * @param {?} htmlElement
         * @return {?}
         */
            function (xmlElement, htmlElement) {
                /** @type {?} */
                var attributes = xmlElement.attributes;
                for (var i = 0; i < attributes.length; ++i) {
                    /** @type {?} */
                    var attr = attributes[i];
                    this.writeAttributeToHtml(htmlElement, attr.name, attr.value);
                }
            };
        /** writes the given attribute value to the html node in data-attribute-syntax **/
        /**
         * writes the given attribute value to the html node in data-attribute-syntax *
         * @param {?} htmlElement
         * @param {?} key
         * @param {?} value
         * @return {?}
         */
        Xml2htmlAttributeWorker.prototype.writeAttributeToHtml = /**
         * writes the given attribute value to the html node in data-attribute-syntax *
         * @param {?} htmlElement
         * @param {?} key
         * @param {?} value
         * @return {?}
         */
            function (htmlElement, key, value) {
                /** @type {?} */
                var name = "" + Xml2htmlAttributeWorker.DataAttribPraefix + key;
                if (value && value.length > 0) {
                    htmlElement.setAttribute(name, value);
                }
                else {
                    htmlElement.removeAttribute(name);
                }
                this.updateAttributesDescriptionInHtmlElement(htmlElement);
            };
        /** writes the given attribute value from the html node data-attribute-syntax **/
        /**
         * writes the given attribute value from the html node data-attribute-syntax *
         * @param {?} htmlElement
         * @param {?} key
         * @return {?}
         */
        Xml2htmlAttributeWorker.prototype.getAttributeValueFromHtml = /**
         * writes the given attribute value from the html node data-attribute-syntax *
         * @param {?} htmlElement
         * @param {?} key
         * @return {?}
         */
            function (htmlElement, key) {
                /** @type {?} */
                var attributes = htmlElement.attributes;
                for (var i = 0; i < attributes.length; ++i) {
                    if (attributes[i].name === "" + Xml2htmlAttributeWorker.DataAttribPraefix + key) {
                        return attributes[i].value;
                    }
                }
                return undefined;
            };
        /** writes the given attribute value to the xml node (and gets it from the html node from data-attribute-syntax) **/
        /**
         * writes the given attribute value to the xml node (and gets it from the html node from data-attribute-syntax) *
         * @param {?} htmlElement
         * @param {?} xmlElement
         * @return {?}
         */
        Xml2htmlAttributeWorker.prototype.writeAllHtmlAttributesToXml = /**
         * writes the given attribute value to the xml node (and gets it from the html node from data-attribute-syntax) *
         * @param {?} htmlElement
         * @param {?} xmlElement
         * @return {?}
         */
            function (htmlElement, xmlElement) {
                /** @type {?} */
                var attributes = htmlElement.attributes;
                for (var i = 0; i < attributes.length; ++i) {
                    /** @type {?} */
                    var attr = attributes[i];
                    if (attr.name.startsWith(Xml2htmlAttributeWorker.DataAttribPraefix)) {
                        xmlElement.setAttribute(attr.name.substr(Xml2htmlAttributeWorker.DataAttribPraefix.length), attr.value);
                    }
                }
            };
        /**
         * updates the 'for human eyes' only description of the attributes inside a html node *
         * @param {?} htmlElement
         * @return {?}
         */
        Xml2htmlAttributeWorker.prototype.updateAttributesDescriptionInHtmlElement = /**
         * updates the 'for human eyes' only description of the attributes inside a html node *
         * @param {?} htmlElement
         * @return {?}
         */
            function (htmlElement) {
                /** @type {?} */
                var attributes = htmlElement.attributes;
                /** @type {?} */
                var allAttributes = '';
                for (var i = 0; i < attributes.length; ++i) {
                    /** @type {?} */
                    var attr = attributes[i];
                    if (attr.name.startsWith(Xml2htmlAttributeWorker.DataAttribPraefix)) {
                        allAttributes = allAttributes + " " + attr.name.substr(Xml2htmlAttributeWorker.DataAttribPraefix.length) + "=\"" + attr.value + "\"";
                    }
                }
                if (allAttributes.length > 0) {
                    htmlElement.setAttribute('data-attributes', allAttributes);
                }
                else {
                    htmlElement.removeAttribute('data-attributes');
                }
            };
        Xml2htmlAttributeWorker.DataAttribPraefix = 'data-attribute-';
        return Xml2htmlAttributeWorker;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var Xml2html = /** @class */ (function () {
        function Xml2html(rules) {
            this.rules = rules;
            this.attributeWorker = new Xml2htmlAttributeWorker(rules);
        }
        /**
         * @param {?} node
         * @return {?}
         */
        Xml2html.getTagNameFromNode = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                /** @type {?} */
                var elem = /** @type {?} */ (node);
                /** @type {?} */
                var name = '';
                if (elem) {
                    name = elem.getAttribute(Xml2html.DataTagName);
                }
                if (name === undefined || name === null || name === '') {
                    throw new Error("node has no DataTagName attribute " + XmlToolbox.GetNodeDebugContext(node));
                }
                return name;
            };
        /**
         * @param {?} node
         * @return {?}
         */
        Xml2html.isFloatingElement = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                /** @type {?} */
                var elem = /** @type {?} */ (node);
                if (elem && elem.classList) {
                    return elem.classList.contains(Xml2html.FloatingTagClassName);
                }
                return false;
            };
        /**
         * @param {?} node
         * @return {?}
         */
        Xml2html.isNoClosingElement = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                /** @type {?} */
                var elem = /** @type {?} */ (node);
                if (elem && elem.classList) {
                    return elem.classList.contains(Xml2html.NoClosingTagClassName);
                }
                return false;
            };
        /**
         * @param {?} xml
         * @return {?}
         */
        Xml2html.prototype.ToHtml = /**
         * @param {?} xml
         * @return {?}
         */
            function (xml) {
                if (xml === '' || xml === undefined || xml === null) {
                    return '';
                }
                // alert(xml);
                // remove newline / carriage return
                xml = xml.replace(/\n/g, '');
                xml = xml.replace(/\r/g, '');
                // remove whitespace (tabs) before tags
                xml = xml.replace(/[\t]+\</g, '<');
                // remove whitespace between tags
                xml = xml.replace(/\>[\t]+\</g, '><');
                // remove whitespace after tags
                xml = xml.replace(/\>[\t]+$/g, '>');
                /** @type {?} */
                var domparser = new DOMParser();
                /** @type {?} */
                var domdoc = domparser.parseFromString(xml, 'text/xml');
                /** @type {?} */
                var targetDocument = new Document();
                if (domdoc.documentElement === null) {
                    return '';
                }
                /** @type {?} */
                var body = this.GetHtmlElementFromXmlElement(domdoc.documentElement, targetDocument);
                if (body && body.nodeType === Node.ELEMENT_NODE) {
                    /** @type {?} */
                    var html = ( /** @type {?} */(body)).outerHTML;
                    return html;
                }
                else {
                    throw new Error("root node " + XmlToolbox.GetNodeDebugContext(body) + " is no element");
                }
            };
        /**
         * @param {?} ruleElem
         * @return {?}
         */
        Xml2html.prototype.createNewElementHtml = /**
         * @param {?} ruleElem
         * @return {?}
         */
            function (ruleElem) {
                /** @type {?} */
                var elem = this.createNewElementByName(ruleElem.tagName);
                return elem.outerHTML;
            };
        /**
         * @param {?} tagName
         * @return {?}
         */
        Xml2html.prototype.createNewElementByName = /**
         * @param {?} tagName
         * @return {?}
         */
            function (tagName) {
                /** @type {?} */
                var tempDoc = new Document();
                /** @type {?} */
                var newElement = tempDoc.createElement('div');
                /** @type {?} */
                var rule = this.rules.ruleElements.get(tagName);
                if (rule && rule.floating === true) {
                    newElement.classList.add(Xml2html.FloatingTagClassName);
                }
                // visualize closing tag or not?
                if (rule && rule.empty === true) {
                    newElement.classList.add(Xml2html.NoClosingTagClassName);
                }
                newElement.setAttribute(Xml2html.DataTagName, tagName);
                return newElement;
            };
        /**
         * @param {?} node
         * @param {?} targetDocument
         * @return {?}
         */
        Xml2html.prototype.GetHtmlElementFromXmlElement = /**
         * @param {?} node
         * @param {?} targetDocument
         * @return {?}
         */
            function (node, targetDocument) {
                switch (node.nodeType) {
                    case Node.ELEMENT_NODE: // element node
                        /** @type {?} */
                        var asElement = /** @type {?} */ (node);
                        /** @type {?} */
                        var nodeName = asElement.nodeName;
                        /** @type {?} */
                        var newElement = targetDocument.createElement('div');
                        /** @type {?} */
                        var rule = this.rules.ruleElements.get(nodeName);
                        if (rule && rule.floating) {
                            newElement.classList.add(Xml2html.FloatingTagClassName);
                        }
                        // visualize closing tag or not?
                        if (rule && rule.empty) {
                            newElement.classList.add(Xml2html.NoClosingTagClassName);
                        }
                        newElement.setAttribute(Xml2html.DataTagName, nodeName);
                        /** @type {?} */
                        var children = asElement.childNodes;
                        if (children.length === 0) {
                            newElement.appendChild(targetDocument.createTextNode('')); // to prevent non closing tags
                        }
                        else {
                            for (var i = 0; i < children.length; ++i) {
                                /** @type {?} */
                                var childAsHtml = this.GetHtmlElementFromXmlElement(children[i], targetDocument);
                                if (childAsHtml !== undefined) {
                                    newElement.appendChild(childAsHtml);
                                }
                            }
                        }
                        // insert attributes
                        this.attributeWorker.writeAllXmlAttributesToHtml(asElement, newElement);
                        return newElement;
                    case Node.TEXT_NODE: // text node
                        /** @type {?} */
                        var content = ( /** @type {?} */(node)).textContent;
                        if (content.length > 0) {
                            return targetDocument.createTextNode(content);
                        }
                        else {
                            return undefined;
                        }
                    case Node.COMMENT_NODE:
                        // create element node
                        newElement = targetDocument.createElement('div');
                        newElement.classList.add(Xml2html.CommentTagClassName);
                        newElement.setAttribute(Xml2html.DataTagName, 'comment');
                        newElement.textContent = ( /** @type {?} */(node)).textContent;
                        return newElement;
                    /* yet not implemented types */
                    case Node.PROCESSING_INSTRUCTION_NODE:
                        console.warn("nodeType \"PROCESSING_INSTRUCTION_NODE\" " + XmlToolbox.GetNodeDebugContext(node) + " not implemented yet");
                        return undefined;
                    case Node.DOCUMENT_NODE:
                        throw new Error("nodeType \"Node.DOCUMENT_NODE\" " + XmlToolbox.GetNodeDebugContext(node) + " not implemented yet");
                    case Node.DOCUMENT_TYPE_NODE:
                        throw new Error("nodeType \"Node.DOCUMENT_NODE\" " + XmlToolbox.GetNodeDebugContext(node) + " not implemented yet");
                    case Node.DOCUMENT_FRAGMENT_NODE:
                        throw new Error("nodeType \"Node.DOCUMENT_FRAGMENT_NODE\" " + XmlToolbox.GetNodeDebugContext(node) + " not implemented yet");
                    /* Depreached node types */
                    case Node.ATTRIBUTE_NODE:
                        throw new Error("nodeType \"Node.ATTRIBUTE_NODE\" " + XmlToolbox.GetNodeDebugContext(node) + " is depreached");
                    case Node.CDATA_SECTION_NODE:
                        throw new Error("nodeType \"Node.CDATA_SECTION_NODE\" " + XmlToolbox.GetNodeDebugContext(node) + " is depreached");
                    case Node.ENTITY_REFERENCE_NODE:
                        throw new Error("nodeType \"Node.ENTITY_REFERENCE_NODE\" " + XmlToolbox.GetNodeDebugContext(node) + " is depreached");
                    case Node.ENTITY_NODE:
                        throw new Error("nodeType \"Node.ENTITY_NODE\" " + XmlToolbox.GetNodeDebugContext(node) + " is depreached");
                    case Node.NOTATION_NODE:
                        throw new Error("nodeType \"Node.NOTATION_NODE\" " + XmlToolbox.GetNodeDebugContext(node) + " is depreached");
                    default:
                        // tslint:disable-next-line:max-line-length
                        throw new Error("unknown xmlElement nodeType " + node.nodeType + " in value: " + XmlToolbox.GetNodeDebugContext(node));
                }
            };
        Xml2html.DataTagName = 'data-tagname';
        Xml2html.NoClosingTagClassName = 'xmlTagNoClosing';
        Xml2html.FloatingTagClassName = 'floating';
        Xml2html.CommentTagClassName = 'comment';
        return Xml2html;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var DomDummyNodeManager = /** @class */ (function () {
        function DomDummyNodeManager() {
        }
        /**
         * @param {?} node
         * @return {?}
         */
        DomDummyNodeManager.IsDummyNode = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                /** @type {?} */
                var asElem = /** @type {?} */ (node);
                if (asElem && node.nodeType === Node.ELEMENT_NODE) {
                    return asElem.classList.contains(DomDummyNodeManager.DummyNodeClassName);
                }
                return false;
            };
        /**
         * @param {?} node
         * @return {?}
         */
        DomDummyNodeManager.IsBeforeFirstTagDummyNode = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                if (DomDummyNodeManager.IsDummyNode(node)) {
                    /** @type {?} */
                    var asElem = /** @type {?} */ (node);
                    if (asElem && node.nodeType === Node.ELEMENT_NODE) {
                        return asElem.classList.contains(DomDummyNodeManager.DummyNodeBeforeFirstTagClassName);
                    }
                    return false;
                }
                else {
                    return false;
                }
            };
        /**
         * @param {?} node
         * @return {?}
         */
        DomDummyNodeManager.getPreviousSibling = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                if (!node) {
                    return undefined;
                }
                while (node) {
                    node = node.previousSibling;
                    if (node) {
                        if (DomDummyNodeManager.IsDummyNode(node)) ;
                        else {
                            return node;
                        }
                    }
                }
                return undefined;
            };
        /**
         * @param {?} node
         * @return {?}
         */
        DomDummyNodeManager.getNextSibling = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                if (!node) {
                    return undefined;
                }
                while (node) {
                    node = node.nextSibling;
                    if (node) {
                        if (DomDummyNodeManager.IsDummyNode(node)) ;
                        else {
                            return node;
                        }
                    }
                }
                return undefined;
            };
        /**
         * @param {?} node
         * @return {?}
         */
        DomDummyNodeManager.getChildNodeCount = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                if (!node) {
                    return 0;
                }
                /** @type {?} */
                var count = 0;
                for (var i = 0; i < node.childNodes.length; i++) {
                    if (!DomDummyNodeManager.IsDummyNode(node.childNodes[i])) {
                        count++;
                    }
                }
                return count;
            };
        /**
         * @param {?} node
         * @return {?}
         */
        DomDummyNodeManager.getFirstChild = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                if (!node) {
                    return undefined;
                }
                /** @type {?} */
                var first = /** @type {?} */ (node.firstChild);
                while (DomDummyNodeManager.IsDummyNode(first)) {
                    first = first.nextSibling;
                }
                return first;
            };
        /**
         * @param {?} node
         * @return {?}
         */
        DomDummyNodeManager.getLastChild = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                if (!node) {
                    return undefined;
                }
                /** @type {?} */
                var last = /** @type {?} */ (node.lastChild);
                while (DomDummyNodeManager.IsDummyNode(last)) {
                    last = last.previousSibling;
                }
                return last;
            };
        /**
         * @param {?} node
         * @param {?=} nodeDepth
         * @return {?}
         */
        DomDummyNodeManager.prototype.RemoveAllDummyNodes = /**
         * @param {?} node
         * @param {?=} nodeDepth
         * @return {?}
         */
            function (node, nodeDepth) {
                var _this = this;
                if (nodeDepth === void 0) {
                    nodeDepth = 0;
                }
                /** @type {?} */
                var children = [];
                for (var i = 0; i < node.childNodes.length; ++i) {
                    children.push(node.childNodes[i]);
                }
                // delete all dummy node children
                children.forEach(function (child) {
                    if (DomDummyNodeManager.IsDummyNode(child)) {
                        node.removeChild(child);
                    }
                });
                children = [];
                for (var i = 0; i < node.childNodes.length; ++i) {
                    children.push(node.childNodes[i]);
                }
                // update child nodes
                children.forEach(function (child) {
                    _this.RemoveAllDummyNodes(child, nodeDepth + 1);
                });
            };
        /**
         * @param {?} node
         * @param {?=} nodeDepth
         * @return {?}
         */
        DomDummyNodeManager.prototype.UpdateDummyNodes = /**
         * @param {?} node
         * @param {?=} nodeDepth
         * @return {?}
         */
            function (node, nodeDepth) {
                var _this = this;
                if (nodeDepth === void 0) {
                    nodeDepth = 0;
                }
                /** @type {?} */
                var document = node.ownerDocument;
                /** @type {?} */
                var asElement = /** @type {?} */ (node);
                /** @type {?} */
                var children = [];
                for (var i = 0; i < node.childNodes.length; ++i) {
                    children.push(node.childNodes[i]);
                }
                if (asElement && !DomDummyNodeManager.IsDummyNode(asElement) && !DomDummyNodeManager.IsDummyNode(asElement.parentElement)) {
                    if (asElement.nodeType === Node.TEXT_NODE) {
                        /** @type {?} */
                        var before = asElement.previousSibling;
                        if (before.nodeType === Node.TEXT_NODE) ;
                        else {
                            if (!DomDummyNodeManager.IsDummyNode(before)) {
                                asElement.parentNode.insertBefore(this.createDummyNode(document), asElement);
                            }
                        }
                    }
                    if (asElement.nodeType === Node.ELEMENT_NODE) {
                        /** @type {?} */
                        var firstChild = node.firstChild;
                        if (!firstChild) {
                            // create dummy node in empty tag
                            node.appendChild(this.createDummyNode(document));
                            firstChild = node.firstChild;
                        }
                        if (Xml2html.isNoClosingElement(node)) ;
                        else {
                            firstChild = node.firstChild;
                            if (!firstChild) {
                                // create dummy node in empty tag
                                node.appendChild(this.createDummyNode(document));
                                firstChild = node.firstChild;
                            }
                            // Insert a dummy node before the first child
                            if (!DomDummyNodeManager.IsDummyNode(firstChild)) {
                                if (firstChild) {
                                    node.insertBefore(this.createDummyNode(document), firstChild);
                                    firstChild = node.firstChild;
                                }
                                else {
                                    node.appendChild(this.createDummyNode(document));
                                }
                            }
                            /** @type {?} */
                            var lastChild = node.lastChild;
                            if (!DomDummyNodeManager.IsDummyNode(lastChild)) {
                                node.appendChild(this.createDummyNode(document));
                                lastChild = node.lastChild;
                            }
                            // Insert a dummy node before the first (dummy child) but optical in front of the node (to show the cursor in front of the node)
                            if (nodeDepth > 0) {
                                if (DomDummyNodeManager.IsDummyNode(firstChild) && !DomDummyNodeManager.IsBeforeFirstTagDummyNode(firstChild)) {
                                    /** @type {?} */
                                    var dummyNode = this.createDummyNode(document);
                                    dummyNode.classList.add(DomDummyNodeManager.DummyNodeBeforeFirstTagClassName);
                                    asElement.insertBefore(dummyNode, firstChild);
                                }
                            }
                        }
                    }
                }
                // update child nodes
                children.forEach(function (child) {
                    _this.UpdateDummyNodes(child, nodeDepth + 1);
                });
            };
        /**
         * @param {?} targetDocument
         * @param {?=} content
         * @return {?}
         */
        DomDummyNodeManager.prototype.createDummyNode = /**
         * @param {?} targetDocument
         * @param {?=} content
         * @return {?}
         */
            function (targetDocument, content) {
                /** @type {?} */
                var dummyNode = targetDocument.createElement('span');
                /** @type {?} */
                var dummy2TextNode;
                if (content === undefined) {
                    dummy2TextNode = targetDocument.createTextNode(DomDummyNodeManager.DummyNodeContent);
                }
                else {
                    dummy2TextNode = targetDocument.createTextNode(content);
                }
                dummyNode.classList.add(DomDummyNodeManager.DummyNodeClassName);
                dummyNode.appendChild(dummy2TextNode);
                return dummyNode;
            };
        DomDummyNodeManager.DummyNodeClassName = 'dummyNode';
        DomDummyNodeManager.DummyNodeBeforeFirstTagClassName = 'beforefirstTag';
        DomDummyNodeManager.DummyNodeContent = String.fromCharCode(160);
        return DomDummyNodeManager;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlCursorPos = /** @class */ (function () {
        function XmlCursorPos() {
            this.ActualNode = null; // no node selected
            this.PosAtNode = XMLCursorPositions.CursorOnCompleteNode;
            this.PosInTextnode = 0;
        }
        /**
         * @param {?} position
         * @return {?}
         */
        XmlCursorPos.getXmlCursorPositionDebugName = /**
         * @param {?} position
         * @return {?}
         */
            function (position) {
                switch (position) {
                    case XMLCursorPositions.CursorOnCompleteNode:
                        return 'CursorOnCompleteNode';
                    case XMLCursorPositions.CursorBehindNode:
                        return 'CursorBehindNode';
                    case XMLCursorPositions.CursorInEmptyNode:
                        return 'CursorInEmptyNode';
                    case XMLCursorPositions.CursorInsideTextNode:
                        return 'CursorInsideTextNode';
                    case XMLCursorPositions.CursorInFrontOfNode:
                        return 'CursorInFrontOfNode';
                    default:
                        return "unknown cursorPos " + position;
                }
            };
        /**
         * @param {?} pos
         * @return {?}
         */
        XmlCursorPos.getSelectionForPos = /**
         * @param {?} pos
         * @return {?}
         */
            function (pos) {
                if (DomDummyNodeManager.IsDummyNode(pos.ActualNode)) {
                    throw new Error("XmlCursorPos.getSelectionForPos: pos.AktNode " + pos.getDebugDescription() + " is a dummy node!");
                }
                if (DomDummyNodeManager.IsDummyNode(pos.ActualNode.parentElement)) {
                    throw new Error("XmlCursorPos.getSelectionForPos: pos.AktNode.parentElement " + pos.getDebugDescription() + " is a dummy node!");
                }
                switch (pos.PosAtNode) {
                    case XMLCursorPositions.CursorOnCompleteNode: // (0)
                        /** @type {?} */
                        var firstChild = pos.ActualNode.firstChild;
                        if (DomDummyNodeManager.IsBeforeFirstTagDummyNode(firstChild)) {
                            return {
                                node: firstChild.firstChild,
                                // text inside BeforeFirstTagDummyNod
                                offset: 0
                            };
                        }
                        else {
                            return {
                                node: pos.ActualNode,
                                offset: 0
                            };
                        }
                    case XMLCursorPositions.CursorInFrontOfNode: // (1)
                        // (1)
                        if (pos.ActualNode.nodeType === Node.TEXT_NODE) {
                            /** @type {?} */
                            var dummyBefore = pos.ActualNode.previousSibling;
                            if (DomDummyNodeManager.IsDummyNode(dummyBefore)) {
                                return {
                                    node: dummyBefore.firstChild,
                                    // before text node
                                    offset: 1
                                };
                            }
                            else {
                                throw new Error('XMLCursorPositions.CursorInFrontOfNode (1):text node: is no dummy node:  ' + pos.getDebugDescription());
                            }
                        }
                        else {
                            // no text node
                            firstChild = pos.ActualNode.firstChild;
                            if (DomDummyNodeManager.IsBeforeFirstTagDummyNode(firstChild)) {
                                return {
                                    node: firstChild.firstChild,
                                    // text inside BeforeFirstTagDummyNod
                                    offset: 1
                                };
                            }
                            if (Xml2html.isNoClosingElement(pos.ActualNode) && DomDummyNodeManager.IsDummyNode(firstChild)) {
                                return { node: firstChild.firstChild, offset: 1 };
                            }
                            throw new Error('XMLCursorPositions.CursorInFrontOfNode (1):no text node: dont know what to do! ');
                        }
                        break;
                    case XMLCursorPositions.CursorBehindNode: // (7, 11)
                        /** @type {?} */
                        var dummyAfter = pos.ActualNode.nextSibling;
                        if (DomDummyNodeManager.IsDummyNode(dummyAfter)) {
                            return {
                                node: dummyAfter.firstChild,
                                // before text node
                                offset: 0
                            };
                        }
                        else {
                            throw new Error("XMLCursorPositionen.CursorBehindNode should only be set, when the element has no next sibling.");
                        }
                    case XMLCursorPositions.CursorInEmptyNode:
                        /** @type {?} */
                        var lastChild = pos.ActualNode.lastChild;
                        if (!DomDummyNodeManager.IsDummyNode(firstChild) && !DomDummyNodeManager.IsBeforeFirstTagDummyNode(firstChild)) {
                            return {
                                node: lastChild.firstChild,
                                // text inside DummyNode
                                offset: 0
                            };
                        }
                        break;
                    case XMLCursorPositions.CursorInsideTextNode:
                        return {
                            node: pos.ActualNode,
                            offset: pos.PosInTextnode
                        };
                }
                throw new Error("showCursor.getSelectionForPos unknown CursorPos " + pos.getDebugDescription());
            };
        /**
         * @return {?}
         */
        XmlCursorPos.prototype.clone = /**
         * @return {?}
         */
            function () {
                /** @type {?} */
                var klon = new XmlCursorPos();
                klon.SetCursor(this.ActualNode, this.PosAtNode, this.PosInTextnode);
                return klon;
            };
        /**
         * @param {?} otherPos
         * @return {?}
         */
        XmlCursorPos.prototype.equals = /**
         * @param {?} otherPos
         * @return {?}
         */
            function (otherPos) {
                if (!otherPos) {
                    return false;
                }
                if (otherPos.ActualNode !== this.ActualNode) {
                    return false;
                }
                if (otherPos.PosAtNode !== this.PosAtNode) {
                    return false;
                }
                if (this.PosAtNode === XMLCursorPositions.CursorInsideTextNode && this.PosInTextnode !== otherPos.PosInTextnode) {
                    return false;
                }
                return true;
            };
        /**
         * @return {?}
         */
        XmlCursorPos.prototype.getDebugDescription = /**
         * @return {?}
         */
            function () {
                return "node:" + XmlToolbox.GetNodeDebugContext(this.ActualNode) + ", pos:" + XmlCursorPos.getXmlCursorPositionDebugName(this.PosAtNode) + ", posInText:" + this.PosInTextnode;
            };
        /**
         * @param {?} actualNode
         * @param {?} posAtNode
         * @param {?=} posInTextnode
         * @return {?}
         */
        XmlCursorPos.prototype.SetCursor = /**
         * @param {?} actualNode
         * @param {?} posAtNode
         * @param {?=} posInTextnode
         * @return {?}
         */
            function (actualNode, posAtNode, posInTextnode) {
                if (posInTextnode === void 0) {
                    posInTextnode = 0;
                }
                if (!actualNode) {
                    throw new Error('actualNode is null');
                }
                if (actualNode !== this.ActualNode) ;
                else {
                    if (posAtNode !== this.PosAtNode) ;
                    else {
                        if (posInTextnode !== this.PosInTextnode) ;
                    }
                }
                this.ActualNode = actualNode;
                this.PosAtNode = posAtNode;
                this.PosInTextnode = posInTextnode;
            };
        /**
         * @param {?} node
         * @return {?}
         */
        XmlCursorPos.prototype.setCursorBehindNodeForDefaultOrRightMovement = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                /** @type {?} */
                var nextSibling = DomDummyNodeManager.getNextSibling(node);
                if (nextSibling) {
                    this.SetCursor(nextSibling, XMLCursorPositions.CursorInFrontOfNode);
                }
                else {
                    this.SetCursor(node, XMLCursorPositions.CursorBehindNode);
                }
            };
        /**
         * @param {?} node
         * @return {?}
         */
        XmlCursorPos.prototype.setCursorpBehindNodeForLeftMovement = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                if (XmlToolbox.IsTextOrCommentNode(node)) {
                    //  For a text node, the cursor is placed after the last character.
                    this.SetCursor(node, XMLCursorPositions.CursorInsideTextNode, Math.max(0, node.textContent.length - 1));
                }
                else {
                    /** @type {?} */
                    var childNodeCount = DomDummyNodeManager.getChildNodeCount(node);
                    if (childNodeCount === 0) {
                        // There are no children in the node.
                        if (!Xml2html.isNoClosingElement(node)) {
                            // If the cursor shows a close tag, then put it in the empty node
                            this.SetCursor(node, XMLCursorPositions.CursorInEmptyNode);
                        }
                        else {
                            // If the cursor does not display a close tag, then place it before the empty node.
                            this.SetCursor(node, XMLCursorPositions.CursorInFrontOfNode);
                        }
                    }
                    else {
                        // There are children in node
                        this.SetCursor(DomDummyNodeManager.getLastChild(node), XMLCursorPositions.CursorBehindNode);
                    }
                }
            };
        return XmlCursorPos;
    }());
    /** @enum {number} */
    var XMLCursorPositions = {
        CursorInFrontOfNode: 0,
        CursorOnCompleteNode: 1,
        CursorInEmptyNode: 2,
        CursorInsideTextNode: 3,
        CursorBehindNode: 4,
    };
    XMLCursorPositions[XMLCursorPositions.CursorInFrontOfNode] = 'CursorInFrontOfNode';
    XMLCursorPositions[XMLCursorPositions.CursorOnCompleteNode] = 'CursorOnCompleteNode';
    XMLCursorPositions[XMLCursorPositions.CursorInEmptyNode] = 'CursorInEmptyNode';
    XMLCursorPositions[XMLCursorPositions.CursorInsideTextNode] = 'CursorInsideTextNode';
    XMLCursorPositions[XMLCursorPositions.CursorBehindNode] = 'CursorBehindNode';

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlCursorPosMover = /** @class */ (function () {
        function XmlCursorPosMover() {
        }
        /**
         * @param {?} pos
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
        XmlCursorPosMover.moveLeft = /**
         * @param {?} pos
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
            function (pos, rootNode, xmlRules) {
                if (pos === undefined) {
                    return false;
                }
                switch (pos.PosAtNode) {
                    case XMLCursorPositions.CursorOnCompleteNode:
                        // Put in front of the node
                        pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInFrontOfNode);
                        break;
                    case XMLCursorPositions.CursorInFrontOfNode:
                        if (pos.ActualNode === rootNode) {
                            return false;
                        }
                        else {
                            /** @type {?} */
                            var previousSibling = DomDummyNodeManager.getPreviousSibling(pos.ActualNode);
                            if (previousSibling) {
                                // Previous sibling node exists
                                pos.setCursorpBehindNodeForLeftMovement(previousSibling);
                            }
                            else {
                                // no previous sibling node available -> set before parent node
                                pos.SetCursor(pos.ActualNode.parentNode, XMLCursorPositions.CursorInFrontOfNode);
                            }
                        }
                        break;
                    case XMLCursorPositions.CursorBehindNode:
                        pos.setCursorpBehindNodeForLeftMovement(pos.ActualNode);
                        break;
                    case XMLCursorPositions.CursorInEmptyNode:
                        // Put in front of the node
                        pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInFrontOfNode);
                        break;
                    case XMLCursorPositions.CursorInsideTextNode:
                        if (XmlToolbox.IsTextOrCommentNode(pos.ActualNode)) {
                            // Node is Textnode
                            if (pos.PosInTextnode > 1) {
                                // Cursor one character to the left
                                pos.SetCursor(pos.ActualNode, pos.PosAtNode, pos.PosInTextnode - 1);
                            }
                            else {
                                // Put in front of the node
                                pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInFrontOfNode);
                            }
                        }
                        else {
                            /** @type {?} */
                            var elemt = /** @type {?} */ (pos.ActualNode);
                            throw new Error("XMLCursorPos.MoveLeft: CursorPos is XMLCursorPositionen.CursorInnerhalbDesTextNodes,\n                           but no text node has been chosen, but the node " + (elemt ? elemt.outerHTML : ''));
                        }
                        break;
                    default:
                        throw new Error("XMLCursorPos.MoveLeft: unknown CursorPos " + pos.PosAtNode);
                }
                return true;
            };
        /**
         * @param {?} pos
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
        XmlCursorPosMover.moveRight = /**
         * @param {?} pos
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
            function (pos, rootNode, xmlRules) {
                if (pos === undefined) {
                    return false;
                }
                switch (pos.PosAtNode) {
                    case XMLCursorPositions.CursorOnCompleteNode:
                        /** @type {?} */
                        var tagName = Xml2html.getTagNameFromNode(pos.ActualNode);
                        /** @type {?} */
                        var rule = xmlRules.ruleElements.get(tagName);
                        if (rule && rule.empty === true) {
                            pos.setCursorBehindNodeForDefaultOrRightMovement(pos.ActualNode);
                        }
                        else {
                            /** @type {?} */
                            var firstChild = DomDummyNodeManager.getFirstChild(pos.ActualNode);
                            if (firstChild) {
                                pos.SetCursor(firstChild, XMLCursorPositions.CursorInFrontOfNode);
                            }
                            else {
                                pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInEmptyNode);
                            }
                        }
                        break;
                    case XMLCursorPositions.CursorBehindNode:
                        /** @type {?} */
                        var nextSibling = DomDummyNodeManager.getNextSibling(pos.ActualNode);
                        if (nextSibling) {
                            /** @type {?} */
                            var elemt = /** @type {?} */ (pos.ActualNode);
                            throw new Error("XMLCursorPos.MoveRight: cursor behind node should only be set, when no other siblings are following " + (elemt ? elemt.outerHTML : ''));
                        }
                        else {
                            /** @type {?} */
                            var parentNextSibling = DomDummyNodeManager.getNextSibling(pos.ActualNode.parentElement);
                            if (parentNextSibling) {
                                pos.SetCursor(parentNextSibling, XMLCursorPositions.CursorInFrontOfNode);
                            }
                            else {
                                pos.SetCursor(pos.ActualNode.parentElement, XMLCursorPositions.CursorBehindNode);
                            }
                        }
                        break;
                    case XMLCursorPositions.CursorInEmptyNode:
                        // Place behind the node
                        pos.setCursorBehindNodeForDefaultOrRightMovement(pos.ActualNode);
                        break;
                    case XMLCursorPositions.CursorInFrontOfNode:
                        if (XmlToolbox.IsTextOrCommentNode(pos.ActualNode)) {
                            // Node is Textnode
                            if (( /** @type {?} */(pos.ActualNode)).textContent.length > 1) {
                                // Textnode is not empty
                                pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInsideTextNode, 1); // one character forward, behind the first character
                            }
                            else {
                                // Textnode is empty
                                // put behind the node
                                pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorBehindNode);
                                // Because "CursorBehindNode" is not attractive, one more step
                                this.moveRight(pos, rootNode, xmlRules);
                            }
                        }
                        else {
                            /** @type {?} */
                            var childNodeCount = DomDummyNodeManager.getChildNodeCount(pos.ActualNode);
                            if (childNodeCount === 0) {
                                // no Children existing
                                if (Xml2html.isNoClosingElement(pos.ActualNode)) {
                                    // If no closed tag is displayed for this node, then directly behind the node
                                    // Place behind the node
                                    pos.setCursorBehindNodeForDefaultOrRightMovement(pos.ActualNode);
                                }
                                else {
                                    // Node has closing tag, so put in between
                                    // Place in empty node
                                    pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInEmptyNode);
                                }
                            }
                            else {
                                /** @type {?} */
                                var firstChild = DomDummyNodeManager.getFirstChild(pos.ActualNode);
                                pos.SetCursor(firstChild, XMLCursorPositions.CursorInFrontOfNode);
                            }
                        }
                        break;
                    case XMLCursorPositions.CursorInsideTextNode:
                        if (XmlToolbox.IsTextOrCommentNode(pos.ActualNode)) {
                            // Node is Textnode
                            if (( /** @type {?} */(pos.ActualNode)).textContent.length > pos.PosInTextnode + 1) {
                                // there is still text in the right of the textnode
                                // step one character forwards: behind the first char
                                pos.SetCursor(pos.ActualNode, pos.PosAtNode, pos.PosInTextnode + 1);
                            }
                            else {
                                // no text after the textnode
                                // place cursor behind the node
                                pos.setCursorBehindNodeForDefaultOrRightMovement(pos.ActualNode);
                            }
                        }
                        else {
                            /** @type {?} */
                            var elemt = /** @type {?} */ (pos.ActualNode);
                            throw new Error("XMLCursorPos.MoveRight: CursorPos is XMLCursorPositionen.CursorInnerhalbDesTextNodes, \n                        but no text node has been chosen, but the node " + (elemt ? elemt.outerHTML : ''));
                        }
                        break;
                    default:
                        throw new Error("String.Format(\"XMLCursorPos.MoveRight: unknown CursorPos " + pos.PosAtNode);
                }
                return true;
            };
        return XmlCursorPosMover;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlCursor = /** @class */ (function () {
        function XmlCursor() {
            this.xmlDocumentRootNode = undefined;
            this.domDummyNodeManager = new DomDummyNodeManager();
            this.StartPos = new XmlCursorPos();
            this.EndPos = new XmlCursorPos();
        }
        /**
         * is there nothing between start and end pos?
         */
        /**
         * is there nothing between start and end pos?
         * @return {?}
         */
        XmlCursor.prototype.isEmptySelection = /**
         * is there nothing between start and end pos?
         * @return {?}
         */
            function () {
                if (this.StartPos.equals(this.EndPos)) {
                    return true;
                }
                return false;
            };
        /**
         * @return {?}
         */
        XmlCursor.prototype.sortStartAndEnd = /**
         * @return {?}
         */
            function () {
                if (this.StartPos.ActualNode && this.EndPos.ActualNode) {
                    if (this.StartPos.ActualNode.isSameNode(this.EndPos.ActualNode)) {
                        if (this.StartPos.PosAtNode === XMLCursorPositions.CursorInsideTextNode &&
                            this.EndPos.PosAtNode === XMLCursorPositions.CursorInsideTextNode &&
                            this.StartPos.PosInTextnode > this.EndPos.PosInTextnode) {
                            this.swapStartAndEnd();
                        }
                    }
                    else {
                        /** @type {?} */
                        var compared = this.StartPos.ActualNode.compareDocumentPosition(this.EndPos.ActualNode);
                        // tslint:disable-next-line:no-bitwise
                        if (!(compared & Node.DOCUMENT_POSITION_FOLLOWING)) {
                            this.swapStartAndEnd();
                        }
                    }
                }
            };
        /**
         * @return {?}
         */
        XmlCursor.prototype.swapStartAndEnd = /**
         * @return {?}
         */
            function () {
                /** @type {?} */
                var node = this.StartPos.ActualNode;
                /** @type {?} */
                var pos = this.StartPos.PosAtNode;
                /** @type {?} */
                var text = this.StartPos.PosInTextnode;
                this.StartPos.SetCursor(this.EndPos.ActualNode, this.EndPos.PosAtNode, this.EndPos.PosInTextnode);
                this.EndPos.SetCursor(node, pos, text);
            };
        /**
         * @return {?}
         */
        XmlCursor.prototype.show = /**
         * @return {?}
         */
            function () {
                if (window.getSelection) {
                    /** @type {?} */
                    var selection = window.getSelection();
                    this.show2(selection);
                }
                else {
                    throw new Error('showCursor: unable to get "window.getSelection"');
                }
            };
        /**
         * @param {?} selection
         * @return {?}
         */
        XmlCursor.prototype.show2 = /**
         * @param {?} selection
         * @return {?}
         */
            function (selection) {
                if (!selection) {
                    return;
                }
                /** @type {?} */
                var elems = document.querySelectorAll('.selected');
                [].forEach.call(elems, function (el) {
                    el.classList.remove('selected');
                });
                /** @type {?} */
                var startSelection = XmlCursorPos.getSelectionForPos(this.StartPos);
                if (this.EndPos && this.EndPos.ActualNode && !this.EndPos.equals(this.StartPos)) {
                    /** @type {?} */
                    var endSelection = XmlCursorPos.getSelectionForPos(this.EndPos);
                    selection.setBaseAndExtent(startSelection.node, startSelection.offset, endSelection.node, endSelection.offset);
                }
                else {
                    // only start pos
                    selection.setPosition(startSelection.node, startSelection.offset);
                    // select tag by adding "select" class
                    if (this.StartPos.PosAtNode === XMLCursorPositions.CursorOnCompleteNode) {
                        /** @type {?} */
                        var asElem = /** @type {?} */ (this.StartPos.ActualNode);
                        if (asElem && asElem.classList) {
                            asElem.classList.add('selected');
                            console.log('selected!');
                        }
                        else {
                            console.error("no asElem.classList for select! " + XmlToolbox.GetNodeDebugContext(asElem));
                        }
                    }
                }
            };
        return XmlCursor;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlCursorPosSetter = /** @class */ (function () {
        function XmlCursorPosSetter() {
        }
        /**
         * @param {?} pos
         * @param {?} selectionAnchorNode
         * @param {?} selectionAnchorOffset
         * @param {?=} debugLog
         * @return {?}
         */
        XmlCursorPosSetter.setFromSelection = /**
         * @param {?} pos
         * @param {?} selectionAnchorNode
         * @param {?} selectionAnchorOffset
         * @param {?=} debugLog
         * @return {?}
         */
            function (pos, selectionAnchorNode, selectionAnchorOffset, debugLog) {
                if (debugLog === void 0) {
                    debugLog = null;
                }
                if (selectionAnchorNode !== undefined && selectionAnchorNode !== null) {
                    /** @type {?} */
                    var node = /** @type {?} */ (selectionAnchorNode);
                    if (DomDummyNodeManager.IsDummyNode(selectionAnchorNode.parentElement)) {
                        // clicked inside a dummy node
                        node = /** @type {?} */ (selectionAnchorNode.parentElement);
                        if (DomDummyNodeManager.IsBeforeFirstTagDummyNode(node)) {
                            switch (selectionAnchorOffset) {
                                case 0:
                                    if (debugLog) {
                                        debugLog.setInputSelection("(1) cursor here: #<tag> pos 0");
                                    }
                                    pos.SetCursor(node.parentElement, XMLCursorPositions.CursorOnCompleteNode, 0);
                                    return;
                                case 1:
                                    if (debugLog) {
                                        debugLog.setInputSelection("(2) cursor here: #<tag> pos 1");
                                    }
                                    pos.SetCursor(node.parentElement, XMLCursorPositions.CursorInFrontOfNode, 0);
                                    return;
                                default:
                                    throw new Error("selectionAnchorOffset=" + selectionAnchorOffset + "?!?");
                            }
                        }
                        if (node.parentElement.childNodes.length === 2) {
                            if (debugLog) {
                                debugLog.setInputSelection("(13, 14) cursor here: <tag>#</tag>");
                            }
                            pos.SetCursor(node.parentElement, XMLCursorPositions.CursorInEmptyNode, 0);
                            return;
                        }
                        if (node === node.parentElement.lastChild && selectionAnchorOffset === 1) {
                            if (debugLog) {
                                debugLog.setInputSelection("(8, 12) cursor here: #</tag>, selecting complete node");
                            }
                            pos.SetCursor(node.parentElement, XMLCursorPositions.CursorOnCompleteNode, 0);
                            return;
                        }
                        /** @type {?} */
                        var nextSibling = node.nextSibling;
                        if (nextSibling) {
                            if (debugLog) {
                                debugLog.setInputSelection("(3, 4, 9, 10) cursor here: #Text or here #<tag>");
                            }
                            pos.SetCursor(nextSibling, XMLCursorPositions.CursorInFrontOfNode, 0);
                            return;
                        }
                        /** @type {?} */
                        var previousSibling = node.previousSibling;
                        if (previousSibling) {
                            if (debugLog) {
                                debugLog.setInputSelection("(7, 11) cursor here: Text# or here <tag>#");
                            }
                            pos.SetCursor(previousSibling, XMLCursorPositions.CursorBehindNode, 0);
                            return;
                        }
                    }
                    else {
                        // is no dummy node
                        if (selectionAnchorNode.nodeType === Node.TEXT_NODE) {
                            if (selectionAnchorOffset === 0) {
                                if (debugLog) {
                                    debugLog.setInputSelection("(6) cursor here: #Text");
                                }
                                pos.SetCursor(selectionAnchorNode, XMLCursorPositions.CursorInsideTextNode, 0);
                                return;
                            }
                            if (selectionAnchorOffset === selectionAnchorNode.textContent.length) {
                                if (debugLog) {
                                    debugLog.setInputSelection("(7 Alternative) cursor here: Text#");
                                }
                                pos.SetCursor(selectionAnchorNode, XMLCursorPositions.CursorInsideTextNode, selectionAnchorNode.textContent.length);
                                return;
                            }
                            if (debugLog) {
                                debugLog.setInputSelection("(5) cursor here: Text#Text");
                            }
                            if (selectionAnchorOffset > selectionAnchorNode.textContent.length) {
                                throw new Error("selectionAnchorOffset " + selectionAnchorOffset + " is > than text-lenght " + selectionAnchorNode.textContent.length + " of text '" + selectionAnchorNode.textContent + "' ");
                            }
                            pos.SetCursor(selectionAnchorNode, XMLCursorPositions.CursorInsideTextNode, selectionAnchorOffset);
                            return;
                        }
                    }
                    // if (DomDummyNodeManager.IsDummyNode(parentElem)) {
                    //     const dummyElement = parentElem;
                    //     const nextSibling = parentElem.nextSibling;
                    //     if (XmlToolbox.IstTextOderKommentarNode(nextSibling)) {
                    //         // cursor here: #text (# = red dummyNode)
                    //         pos.CursorSetzen(nextSibling, XMLCursorPositionen.CursorInnerhalbDesTextNodes, 0);
                    //         return;
                    //     }
                    //     const previousSibling = dummyElement.previousSibling;
                    //     if (!previousSibling) {
                    //     //    pos.CursorSetzen(dummyElement.parentElement, XMLCursorPositionen.c, 0);
                    //     }
                    // }
                    // switch (node.nodeType) {
                    //     case Node.TEXT_NODE:
                    // if (loopCount === 0) {
                    //     const nextSibling = parentElem.nextSibling;
                    //     if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE && selectionAnchorOffset === 1) {
                    //         // set cursor at start of following textnode
                    //         pos.CursorSetzen(nextSibling, XMLCursorPositionen.CursorInnerhalbDesTextNodes, 0);
                    //     } else {
                    //         const previousSibling = parentElem.previousSibling;
                    //         if (previousSibling && previousSibling.nodeType === Node.TEXT_NODE && selectionAnchorOffset === 0) {
                    //             // set cursor at end of previous textnode
                    //             pos.CursorSetzen(previousSibling, XMLCursorPositionen.CursorInnerhalbDesTextNodes, previousSibling.nodeValue.length);
                    //         }
                    //     }
                    // } else {
                    //     node = parentElem; // up to dummy node
                    // }
                    //         } else {
                    //             pos.CursorSetzen(node, XMLCursorPositionen.CursorInnerhalbDesTextNodes, selectionAnchorOffset);
                    //         }
                    //         break;
                    //     case Node.ELEMENT_NODE:
                    //         if (DomDummyNodeManager.IsDummyNode(node)) {
                    //             // node = parentElem; // up to parent node
                    //         } else {
                    //             pos.CursorSetzen(node, XMLCursorPositionen.CursorAufNodeSelbstVorderesTag);
                    //         }
                    //         break;
                    //     default:
                    //         throw new Error(`unhandled nodeType '${node.nodeType}' of node ${XmlToolbox.GetNodeDebugContext(node)}`);
                    // }
                }
                console.error("found no suiting cursor interpretation! For selectionAnchorNode=" + XmlToolbox.GetNodeDebugContext(selectionAnchorNode) + ", selectionAnchorOffset=" + selectionAnchorOffset);
            };
        return XmlCursorPosSetter;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlDomCleaner = /** @class */ (function () {
        function XmlDomCleaner() {
        }
        /**
         * @param {?} node
         * @param {?} actualCursor
         * @return {?}
         */
        XmlDomCleaner.cleanUp = /**
         * @param {?} node
         * @param {?} actualCursor
         * @return {?}
         */
            function (node, actualCursor) {
                this.concatTextNodes(node, actualCursor);
            };
        /**
         *
         * if two textnodes are direct siblings: concat to one textnode
         * @param {?} node
         * @param {?} actualCursor
         * @param {?=} nodeDepth
         * @return {?}
         */
        XmlDomCleaner.concatTextNodes = /**
         *
         * if two textnodes are direct siblings: concat to one textnode
         * @param {?} node
         * @param {?} actualCursor
         * @param {?=} nodeDepth
         * @return {?}
         */
            function (node, actualCursor, nodeDepth) {
                if (nodeDepth === void 0) {
                    nodeDepth = 0;
                }
                /** @type {?} */
                var restart = true;
                while (restart === true) {
                    restart = false;
                    for (var i = 0; i < node.childNodes.length; ++i) {
                        /** @type {?} */
                        var firstToCheck = node.childNodes[i];
                        if (DomDummyNodeManager.IsDummyNode(firstToCheck)) {
                            throw new Error('Dummynodes have to be removed before using XmlDomCleaner!');
                        }
                        if (firstToCheck.nodeType === Node.TEXT_NODE) {
                            /** @type {?} */
                            var secondToCheck = firstToCheck.nextSibling;
                            if (secondToCheck !== null && secondToCheck.nodeType === Node.TEXT_NODE) {
                                // two text nodes after each other => concat
                                if (actualCursor.StartPos.ActualNode === secondToCheck) {
                                    actualCursor.StartPos.SetCursor(firstToCheck, XMLCursorPositions.CursorInsideTextNode, firstToCheck.textContent.length + actualCursor.StartPos.PosInTextnode);
                                }
                                if (actualCursor.EndPos.ActualNode === secondToCheck) {
                                    actualCursor.EndPos.SetCursor(firstToCheck, XMLCursorPositions.CursorInsideTextNode, firstToCheck.textContent.length + actualCursor.EndPos.PosInTextnode);
                                }
                                firstToCheck.textContent = firstToCheck.textContent + secondToCheck.textContent;
                                node.removeChild(secondToCheck);
                                restart = true;
                            }
                        }
                    }
                }
                // update child nodes
                for (var i = 0; i < node.childNodes.length; ++i) {
                    this.concatTextNodes(node.childNodes[i], actualCursor, nodeDepth + 1);
                }
            };
        return XmlDomCleaner;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditDelete = /** @class */ (function () {
        function XmlEditDelete() {
        }
        /**
         * @param {?} cursor
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
        XmlEditDelete.deleteSelection = /**
         * @param {?} cursor
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
            function (cursor, rootNode, xmlRules) {
                return true;
            };
        /**
         * @param {?} pos
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
        XmlEditDelete.deleteAfter = /**
         * @param {?} pos
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
            function (pos, rootNode, xmlRules) {
                if (pos === undefined) {
                    return false;
                }
                switch (pos.PosAtNode) {
                    case XMLCursorPositions.CursorOnCompleteNode:
                        return XmlEditDelete.deleteBefore(pos, rootNode, xmlRules);
                    case XMLCursorPositions.CursorBehindNode:
                    case XMLCursorPositions.CursorInFrontOfNode:
                        XmlCursorPosMover.moveRight(pos, rootNode, xmlRules);
                        return XmlEditDelete.deleteBefore(pos, rootNode, xmlRules);
                    case XMLCursorPositions.CursorInEmptyNode:
                        return XmlEditDelete.deleteBefore(pos, rootNode, xmlRules);
                    case XMLCursorPositions.CursorInsideTextNode:
                        XmlCursorPosMover.moveRight(pos, rootNode, xmlRules);
                        return XmlEditDelete.deleteBefore(pos, rootNode, xmlRules);
                    default:
                        throw new Error("String.Format(\"XmlCursorEdit.deleteBefore: unknown CursorPos " + pos.PosAtNode);
                }
                return true;
            };
        /**
         * @param {?} pos
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
        XmlEditDelete.deleteBefore = /**
         * @param {?} pos
         * @param {?} rootNode
         * @param {?} xmlRules
         * @return {?}
         */
            function (pos, rootNode, xmlRules) {
                /** @type {?} */
                var deleteNode;
                // console.log(pos.getDebugDescription());
                if (pos === undefined) {
                    return false;
                }
                switch (pos.PosAtNode) {
                    case XMLCursorPositions.CursorOnCompleteNode:
                        deleteNode = pos.ActualNode;
                        XmlCursorPosMover.moveRight(pos, rootNode, xmlRules);
                        deleteNode.parentElement.removeChild(deleteNode);
                        break;
                    case XMLCursorPositions.CursorBehindNode:
                        if (pos.ActualNode.nodeType === Node.TEXT_NODE) {
                            pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInsideTextNode, pos.ActualNode.textContent.length);
                            return XmlEditDelete.deleteBefore(pos, rootNode, xmlRules);
                        }
                        else {
                            pos.ActualNode.parentElement.removeChild(pos.ActualNode);
                        }
                        break;
                    case XMLCursorPositions.CursorInEmptyNode:
                        deleteNode = pos.ActualNode;
                        XmlCursorPosMover.moveRight(pos, rootNode, xmlRules);
                        deleteNode.parentElement.removeChild(deleteNode);
                        break;
                    case XMLCursorPositions.CursorInFrontOfNode:
                        deleteNode = DomDummyNodeManager.getPreviousSibling(pos.ActualNode);
                        if (!deleteNode) {
                            deleteNode = pos.ActualNode.parentElement;
                        }
                        if (deleteNode) {
                            if (deleteNode.nodeType === Node.TEXT_NODE) {
                                pos.SetCursor(deleteNode, XMLCursorPositions.CursorInsideTextNode, deleteNode.textContent.length);
                                return XmlEditDelete.deleteBefore(pos, rootNode, xmlRules);
                            }
                            else {
                                deleteNode.parentElement.removeChild(deleteNode);
                            }
                        }
                        break;
                    case XMLCursorPositions.CursorInsideTextNode:
                        if (pos.PosInTextnode === 0) {
                            pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInFrontOfNode, 0);
                            return XmlEditDelete.deleteBefore(pos, rootNode, xmlRules);
                        }
                        else {
                            /** @type {?} */
                            var text = pos.ActualNode.textContent;
                            text = text.substring(0, pos.PosInTextnode - 1) + text.substr(pos.PosInTextnode, pos.ActualNode.textContent.length);
                            pos.ActualNode.textContent = text;
                            XmlCursorPosMover.moveLeft(pos, rootNode, xmlRules);
                            // pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInsideTextNode, pos.PosInTextnode - 1);
                        }
                        break;
                    default:
                        throw new Error("String.Format(\"XmlEdit.deleteBefore: unknown CursorPos " + pos.PosAtNode);
                }
                return true;
            };
        return XmlEditDelete;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditRuleCheckTextInsert = /** @class */ (function () {
        function XmlEditRuleCheckTextInsert(xsdNodes) {
            this.xsdNodes = xsdNodes;
            this.namespacePraefix = 'xs:';
        }
        /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
        XmlEditRuleCheckTextInsert.prototype.isTextAllowedAtThisCursorPos = /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
            function (cursorPosToCheck) {
                if (!cursorPosToCheck) {
                    return false;
                }
                /** @type {?} */
                var parentNode = this.getRelevantParentNodeForCursorPos(cursorPosToCheck);
                /** @type {?} */
                var parentName = Xml2html.getTagNameFromNode(parentNode);
                /** @type {?} */
                var xsdNode = this.xsdNodes.get(parentName);
                if (xsdNode) {
                    /** @type {?} */
                    var result = this.isTextAllowedInThisElement(xsdNode);
                    return result;
                }
                else {
                    return false; // element not found
                }
            };
        /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
        XmlEditRuleCheckTextInsert.prototype.getRelevantParentNodeForCursorPos = /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
            function (cursorPosToCheck) {
                if (cursorPosToCheck) {
                    /** @type {?} */
                    var parentNode = cursorPosToCheck.ActualNode;
                    switch (parentNode.nodeType) {
                        case Node.COMMENT_NODE:
                        case Node.TEXT_NODE:
                            parentNode = parentNode.parentElement;
                            break;
                        case Node.ELEMENT_NODE:
                            switch (cursorPosToCheck.PosAtNode) {
                                case XMLCursorPositions.CursorInEmptyNode:
                                case XMLCursorPositions.CursorInsideTextNode:
                                    break;
                                case XMLCursorPositions.CursorBehindNode:
                                case XMLCursorPositions.CursorInFrontOfNode:
                                case XMLCursorPositions.CursorOnCompleteNode:
                                    parentNode = parentNode.parentElement;
                                    break;
                                default:
                                    throw new Error("unhandled  cursorPosToCheck.PosAmNode \"" + cursorPosToCheck.PosAtNode + "\"/" + XmlCursorPos.getXmlCursorPositionDebugName(cursorPosToCheck.PosAtNode) + "\" ");
                            }
                            break;
                        default:
                            throw new Error("unhandled  parentNode.nodeType \"" + parentNode.nodeType + "\"");
                    }
                    return parentNode;
                }
            };
        /**
         * @param {?} xsdNode
         * @param {?=} alreadyAddedElementNames
         * @return {?}
         */
        XmlEditRuleCheckTextInsert.prototype.isTextAllowedInThisElement = /**
         * @param {?} xsdNode
         * @param {?=} alreadyAddedElementNames
         * @return {?}
         */
            function (xsdNode, alreadyAddedElementNames) {
                var _this = this;
                if (alreadyAddedElementNames === void 0) {
                    alreadyAddedElementNames = new Set();
                }
                /** @type {?} */
                var elementName;
                if (xsdNode.nodeType === Node.ELEMENT_NODE) {
                    /** @type {?} */
                    var asElem = /** @type {?} */ (xsdNode);
                    if (asElem) {
                        /** @type {?} */
                        var mixedAttrib = asElem.getAttribute('mixed');
                        if (mixedAttrib) {
                            return true;
                        }
                        /** @type {?} */
                        var typeAttrib = asElem.getAttribute('type');
                        if (typeAttrib && typeAttrib === this.namespacePraefix + "string") {
                            return true;
                        }
                        if (asElem.localName === 'element') {
                            elementName = asElem.getAttribute('name');
                            if (elementName) {
                                if (alreadyAddedElementNames.has(elementName)) {
                                    return false; // element recursion detected
                                }
                            }
                            alreadyAddedElementNames.add(elementName);
                        }
                    }
                }
                /** @type {?} */
                var childNodes = /** @type {?} */ (Array.prototype.slice.call(xsdNode.childNodes));
                /** @type {?} */
                var allowed = false;
                childNodes.forEach(function (child) {
                    if (child.nodeType === Node.ELEMENT_NODE) {
                        /** @type {?} */
                        var childElem = /** @type {?} */ (child);
                        if (childElem) {
                            switch (childElem.localName) {
                                case 'complexType':
                                case 'sequence':
                                case 'choice':
                                case 'simpleContent':
                                case 'extension':
                                    if (_this.isTextAllowedInThisElement(child, alreadyAddedElementNames) === true) {
                                        allowed = true;
                                        break;
                                    }
                                    break;
                                case 'element':
                                    /** @type {?} */
                                    var refname = childElem.attributes.getNamedItem('ref');
                                    if (refname) {
                                        /** @type {?} */
                                        var referedNode = _this.xsdNodes.get(refname.value);
                                        if (referedNode) {
                                            if (_this.isTextAllowedInThisElement(referedNode, alreadyAddedElementNames) === true) {
                                                allowed = true;
                                                break;
                                            }
                                        }
                                        else {
                                            throw new Error(" refered element \"" + refname + "\" for element \"" + childElem.outerHTML + "\" not found");
                                        }
                                    }
                                    break;
                                case 'attribute':
                                    break;
                                default:
                                    alert('unknown childElem.localname "' + childElem.localName + '"/' + childElem.outerHTML);
                            }
                        }
                    }
                });
                return allowed;
            };
        return XmlEditRuleCheckTextInsert;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditInsert = /** @class */ (function () {
        function XmlEditInsert() {
        }
        /**
         * @param {?} pos
         * @param {?} value
         * @param {?} rootNode
         * @param {?} xmlRules
         * @param {?} xmlSchema
         * @return {?}
         */
        XmlEditInsert.replaceWithText = /**
         * @param {?} pos
         * @param {?} value
         * @param {?} rootNode
         * @param {?} xmlRules
         * @param {?} xmlSchema
         * @return {?}
         */
            function (pos, value, rootNode, xmlRules, xmlSchema) {
                if (pos === undefined) {
                    return false;
                }
                if (value === '' || value === undefined || value == null) {
                    return false;
                }
                if (pos.isEmptySelection() === false) {
                    if (XmlEditDelete.deleteSelection(pos, rootNode, xmlRules) === false) {
                        return false;
                    }
                }
                return XmlEditInsert.insertText(pos.EndPos, value, rootNode, xmlRules, xmlSchema);
            };
        /**
         * @param {?} pos
         * @param {?} value
         * @param {?} rootNode
         * @param {?} xmlRules
         * @param {?} xmlSchema
         * @return {?}
         */
        XmlEditInsert.insertText = /**
         * @param {?} pos
         * @param {?} value
         * @param {?} rootNode
         * @param {?} xmlRules
         * @param {?} xmlSchema
         * @return {?}
         */
            function (pos, value, rootNode, xmlRules, xmlSchema) {
                if (pos === undefined) {
                    return false;
                }
                if (value === '' || value === undefined || value == null) {
                    return false;
                }
                switch (pos.PosAtNode) {
                    case XMLCursorPositions.CursorOnCompleteNode:
                        /** @type {?} */
                        var textAllowed = XmlEditInsert.isTextAllowedInParentNode(pos, xmlSchema);
                        if (textAllowed === true) {
                            /** @type {?} */
                            var newTextNode = pos.ActualNode.ownerDocument.createTextNode(value);
                            pos.ActualNode.parentElement.insertBefore(newTextNode, pos.ActualNode);
                            pos.ActualNode.parentElement.removeChild(pos.ActualNode);
                            /** @type {?} */
                            var nextSibling = DomDummyNodeManager.getNextSibling(newTextNode);
                            if (nextSibling) {
                                pos.SetCursor(nextSibling, XMLCursorPositions.CursorInFrontOfNode);
                            }
                            else {
                                pos.SetCursor(newTextNode, XMLCursorPositions.CursorBehindNode);
                            }
                            return true;
                        }
                        else {
                            return false;
                        }
                    case XMLCursorPositions.CursorBehindNode:
                        if (pos.ActualNode.nodeType === Node.TEXT_NODE) {
                            pos.ActualNode.textContent = pos.ActualNode.textContent + value;
                            return true;
                        }
                        else {
                            textAllowed = XmlEditInsert.isTextAllowedInParentNode(pos, xmlSchema);
                            if (textAllowed === true) {
                                /** @type {?} */
                                var newTextNode = pos.ActualNode.ownerDocument.createTextNode(value);
                                pos.ActualNode.parentElement.insertBefore(newTextNode, pos.ActualNode.nextSibling); // inserts the new node after the actual node
                                return true;
                            }
                            else {
                                return false;
                            }
                        }
                    case XMLCursorPositions.CursorInFrontOfNode:
                        if (pos.ActualNode.nodeType === Node.TEXT_NODE) {
                            pos.ActualNode.textContent = value + pos.ActualNode.textContent;
                            return true;
                        }
                        else {
                            textAllowed = XmlEditInsert.isTextAllowedInParentNode(pos, xmlSchema);
                            if (textAllowed === true) {
                                /** @type {?} */
                                var newTextNode = pos.ActualNode.ownerDocument.createTextNode(value);
                                pos.ActualNode.parentElement.insertBefore(newTextNode, pos.ActualNode);
                                return true;
                            }
                            else {
                                return false;
                            }
                        }
                    case XMLCursorPositions.CursorInEmptyNode:
                        textAllowed = new XmlEditRuleCheckTextInsert(xmlSchema.xsdNodes).isTextAllowedAtThisCursorPos(pos);
                        if (textAllowed === true) {
                            /** @type {?} */
                            var newTextNode = pos.ActualNode.ownerDocument.createTextNode(value);
                            pos.ActualNode.appendChild(newTextNode);
                            return true;
                        }
                        else {
                            return false;
                        }
                    case XMLCursorPositions.CursorInsideTextNode:
                        /** @type {?} */
                        var text = pos.ActualNode.textContent;
                        pos.ActualNode.textContent = text.substr(0, pos.PosInTextnode) + value + text.substr(pos.PosInTextnode, text.length);
                        pos.SetCursor(pos.ActualNode, XMLCursorPositions.CursorInsideTextNode, pos.PosInTextnode + 1);
                        break;
                    default:
                        throw new Error("String.Format(\"XmlEditInsert.insert: unknown CursorPos  " + pos.getDebugDescription());
                }
                return true;
            };
        /**
         * @param {?} pos
         * @param {?} xmlSchema
         * @return {?}
         */
        XmlEditInsert.isTextAllowedInParentNode = /**
         * @param {?} pos
         * @param {?} xmlSchema
         * @return {?}
         */
            function (pos, xmlSchema) {
                /** @type {?} */
                var parentNode = pos.ActualNode.parentElement;
                /** @type {?} */
                var parentCursorPos = pos.clone();
                parentCursorPos.SetCursor(parentNode, XMLCursorPositions.CursorInEmptyNode);
                return new XmlEditRuleCheckTextInsert(xmlSchema.xsdNodes).isTextAllowedAtThisCursorPos(parentCursorPos);
            };
        return XmlEditInsert;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditorContext = /** @class */ (function () {
        function XmlEditorContext(_document) {
            this._document = _document;
            this.actualCursor = new XmlCursor();
            this.dummyNodeManager = new DomDummyNodeManager();
            this.actualCursorChanged = new rxjs.Subject();
            this.debugService = new XmlEditorDebugger();
        }
        /**
         * @return {?}
         */
        XmlEditorContext.prototype.ngOnDestroy = /**
         * @return {?}
         */
            function () {
                this.actualCursorChanged.unsubscribe();
            };
        /**
         * @param {?} cursorPos
         * @return {?}
         */
        XmlEditorContext.prototype.setCursorPos = /**
         * @param {?} cursorPos
         * @return {?}
         */
            function (cursorPos) {
                this.actualCursor = cursorPos;
                this.actualCursorChanged.next(cursorPos);
                this.debugService.setActualCursorPos(cursorPos);
            };
        // /**
        //   * Executed command from editor header buttons
        //   * @param command string from triggerCommand
        //   */
        // executeCommand(command: string) {
        //   if (command !== '') {
        //     this.commander.executeCommand(command);
        //     this.exec();
        //   }
        //   this.onEditorFocus();
        //   const cleanUpFirst = false;
        //   this.domDummyNodeManager.UpdateDummyNodes(this.xmlDocumentRootNode, cleanUpFirst);
        //   return;
        // }
        /**
         * @param {?} mouseEvent
         * @return {?}
         */
        XmlEditorContext.prototype.mouseUp = /**
         * @param {?} mouseEvent
         * @return {?}
         */
            function (mouseEvent) {
                if (window.getSelection) {
                    /** @type {?} */
                    var userSelection = void 0;
                    userSelection = window.getSelection();
                    XmlCursorPosSetter.setFromSelection(this.actualCursor.StartPos, userSelection.anchorNode, userSelection.anchorOffset, this.debugService);
                    XmlCursorPosSetter.setFromSelection(this.actualCursor.EndPos, userSelection.focusNode, userSelection.focusOffset, this.debugService);
                    this.setCursorPos(this.actualCursor);
                    this.actualCursor.sortStartAndEnd();
                    this.actualCursor.show();
                }
                else {
                    throw new Error("can't get window.getSelection, target=" + JSON.stringify(mouseEvent.target));
                }
            };
        /**
         * @param {?} event
         * @return {?}
         */
        XmlEditorContext.prototype.keyDown = /**
         * @param {?} event
         * @return {?}
         */
            function (event) {
                console.log('keydown! key:' + event.key + ' / code:' + event.code);
                switch (event.key) {
                    case 'Control':
                        this.keyCtrlIsDown = true;
                        break;
                    case 'Shift':
                        this.keyShiftIsDown = true;
                        break;
                    case 'c':
                        if (this.keyCtrlIsDown) {
                            // Copy
                            return false;
                        }
                        else {
                            if (this.insertText('c')) {
                                return false;
                            }
                        }
                        break;
                    case 'ArrowUp':
                    case 'ArrowDown':
                        return true;
                    case 'ArrowRight':
                        if (this.keyShiftIsDown) {
                            XmlCursorPosMover.moveRight(this.actualCursor.EndPos, this.actualCursor.xmlDocumentRootNode, this.config.rules);
                        }
                        else {
                            XmlCursorPosMover.moveRight(this.actualCursor.EndPos, this.actualCursor.xmlDocumentRootNode, this.config.rules);
                            this.actualCursor.StartPos.SetCursor(this.actualCursor.EndPos.ActualNode, this.actualCursor.EndPos.PosAtNode, this.actualCursor.EndPos.PosInTextnode);
                        }
                        this.actualCursor.sortStartAndEnd();
                        this.actualCursor.show();
                        this.setCursorPos(this.actualCursor);
                        return false;
                    case 'ArrowLeft':
                        if (this.keyShiftIsDown) {
                            XmlCursorPosMover.moveLeft(this.actualCursor.EndPos, this.actualCursor.xmlDocumentRootNode, this.config.rules);
                        }
                        else {
                            XmlCursorPosMover.moveLeft(this.actualCursor.StartPos, this.actualCursor.xmlDocumentRootNode, this.config.rules);
                            this.actualCursor.EndPos.SetCursor(this.actualCursor.StartPos.ActualNode, this.actualCursor.StartPos.PosAtNode, this.actualCursor.StartPos.PosInTextnode);
                        }
                        this.actualCursor.sortStartAndEnd();
                        this.actualCursor.show();
                        this.setCursorPos(this.actualCursor);
                        return false;
                    case 'Backspace':
                        if (this.actualCursor.isEmptySelection()) {
                            XmlEditDelete.deleteBefore(this.actualCursor.StartPos, this.actualCursor.xmlDocumentRootNode, this.config.rules);
                        }
                        else {
                            XmlEditDelete.deleteSelection(this.actualCursor, this.actualCursor.xmlDocumentRootNode, this.config.rules);
                        }
                        this.actualCursor.EndPos.SetCursor(this.actualCursor.StartPos.ActualNode, this.actualCursor.StartPos.PosAtNode, this.actualCursor.StartPos.PosInTextnode);
                        this.cleanUpAndUpdateDummyElements();
                        this.actualCursor.show();
                        return false;
                    case 'Delete':
                        if (this.actualCursor.isEmptySelection()) {
                            XmlEditDelete.deleteAfter(this.actualCursor.StartPos, this.actualCursor.xmlDocumentRootNode, this.config.rules);
                        }
                        else {
                            XmlEditDelete.deleteSelection(this.actualCursor, this.actualCursor.xmlDocumentRootNode, this.config.rules);
                        }
                        this.cleanUpAndUpdateDummyElements();
                        this.actualCursor.show();
                        return false;
                    case 'Enter':
                        return false;
                    default:
                        /** @type {?} */
                        var textInsert = event.key;
                        if (this.insertText(textInsert)) {
                            return false;
                        }
                        break;
                }
                return true;
            };
        /**
         * @param {?} event
         * @return {?}
         */
        XmlEditorContext.prototype.keyUp = /**
         * @param {?} event
         * @return {?}
         */
            function (event) {
                switch (event.key) {
                    case 'Control':
                        this.keyCtrlIsDown = false;
                        break;
                    case 'Shift':
                        this.actualCursor.sortStartAndEnd();
                        this.keyShiftIsDown = false;
                        break;
                    case 'ArrowLeft':
                    case 'ArrowRight':
                        this.actualCursor.show();
                        break;
                    case 'ArrowUp':
                    case 'ArrowDown':
                    case 'Backspace':
                    case 'Delete':
                    case 'Enter':
                    case 'Control':
                    case 'Shift':
                        break;
                }
                return true;
            };
        /**
         * @param {?} text
         * @return {?}
         */
        XmlEditorContext.prototype.pasted = /**
         * @param {?} text
         * @return {?}
         */
            function (text) {
                alert('pasted: ' + text);
                return false;
            };
        /**
         * @return {?}
         */
        XmlEditorContext.prototype.copied = /**
         * @return {?}
         */
            function () {
                alert('copied');
                return false;
            };
        /**
         * @param {?} value
         * @return {?}
         */
        XmlEditorContext.prototype.insertText = /**
         * @param {?} value
         * @return {?}
         */
            function (value) {
                if (value === '' || value === null || value === undefined) {
                    return true;
                }
                /** @type {?} */
                var inserted = false;
                if (this.actualCursor.isEmptySelection()) {
                    inserted = XmlEditInsert.insertText(this.actualCursor.EndPos, value, this.actualCursor.xmlDocumentRootNode, this.config.rules, this.config.xmlSchema);
                }
                else {
                    inserted = XmlEditInsert.replaceWithText(this.actualCursor, value, this.actualCursor.xmlDocumentRootNode, this.config.rules, this.config.xmlSchema);
                }
                if (inserted) {
                    // character inserted -> move cursor right
                    // for (let index = 0; index < value.length; index++) {
                    //   XmlCursorPosMover.moveRight(this.actualCursor.EndPos, this.actualCursor.xmlDocumentRootNode, this.config.rules);
                    // }
                    this.actualCursor.StartPos.SetCursor(this.actualCursor.EndPos.ActualNode, this.actualCursor.EndPos.PosAtNode, this.actualCursor.EndPos.PosInTextnode);
                    this.cleanUpAndUpdateDummyElements();
                    this.actualCursor.show();
                    console.warn('text inserted!');
                    return true;
                }
                else {
                    console.warn('text NOT inserted!');
                    return false;
                }
            };
        /** inserts a new element at the actual cursor pos */
        /**
         * inserts a new element at the actual cursor pos
         * @param {?} element
         * @return {?}
         */
        XmlEditorContext.prototype.insertElement = /**
         * inserts a new element at the actual cursor pos
         * @param {?} element
         * @return {?}
         */
            function (element) {
                /** @type {?} */
                var html = new Xml2html(this.config.rules).createNewElementHtml(element);
                this.domInsertHtml(html);
                this.cleanUpAndUpdateDummyElements();
                // this.actualCursor.show();
                console.warn('element inserted!');
            };
        /**
         * Create raw HTML
         * @param {?} html HTML string
         * @return {?}
         */
        XmlEditorContext.prototype.domInsertHtml = /**
         * Create raw HTML
         * @param {?} html HTML string
         * @return {?}
         */
            function (html) {
                if (document.getSelection) {
                    /** @type {?} */
                    var range = document.getSelection().getRangeAt(0);
                    range.insertNode(range.createContextualFragment(html));
                }
                else {
                    throw new Error('document.getSelection not defined!');
                }
                this.cleanUpAndUpdateDummyElements();
                this.actualCursor.show();
            };
        /**
         * save selection when the editor is focussed out
         */
        /**
         * save selection when the editor is focussed out
         * @return {?}
         */
        XmlEditorContext.prototype.saveSelection = /**
         * save selection when the editor is focussed out
         * @return {?}
         */
            function () {
                if (window.getSelection) {
                    /** @type {?} */
                    var sel = window.getSelection();
                    if (sel.getRangeAt && sel.rangeCount) {
                        this.savedSelection = sel.getRangeAt(0);
                        this.selectedText = sel.toString();
                    }
                }
                else if (this._document.getSelection && this._document.createRange) {
                    this.savedSelection = document.createRange();
                }
                else {
                    this.savedSelection = null;
                }
            };
        /**
         * restore selection when the editor is focussed in
         */
        /**
         * restore selection when the editor is focussed in
         * @return {?}
         */
        XmlEditorContext.prototype.restoreSelection = /**
         * restore selection when the editor is focussed in
         * @return {?}
         */
            function () {
                if (this.savedSelection) {
                    if (window.getSelection) {
                        /** @type {?} */
                        var sel = window.getSelection();
                        sel.removeAllRanges();
                        sel.addRange(this.savedSelection);
                        return true;
                    }
                    else if (this._document.getSelection /*&& this.savedSelection.select*/) {
                        // this.savedSelection.select();
                        return true;
                    }
                }
                else {
                    return false;
                }
            };
        /**
         * @return {?}
         */
        XmlEditorContext.prototype.cleanUpAndUpdateDummyElements = /**
         * @return {?}
         */
            function () {
                this.dummyNodeManager.RemoveAllDummyNodes(this.actualCursor.xmlDocumentRootNode);
                XmlDomCleaner.cleanUp(this.actualCursor.xmlDocumentRootNode, this.actualCursor);
                this.dummyNodeManager.UpdateDummyNodes(this.actualCursor.xmlDocumentRootNode);
                this.actualCursor.sortStartAndEnd();
            };
        return XmlEditorContext;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * \@dynamic
     */
    var AngularXmlEditorService = /** @class */ (function () {
        function AngularXmlEditorService(_document) {
            this._document = _document;
            this.contexts = new Map();
        }
        /**
         * @return {?}
         */
        AngularXmlEditorService.prototype.getNewEditorContextId = /**
         * @return {?}
         */
            function () {
                /** @type {?} */
                var no = 0;
                while (this.contexts.has(no.toString())) {
                    no++;
                }
                return no.toString();
            };
        /**
         * @param {?} contextId
         * @return {?}
         */
        AngularXmlEditorService.prototype.getEditorContext = /**
         * @param {?} contextId
         * @return {?}
         */
            function (contextId) {
                /** @type {?} */
                var context = this.contexts.get(contextId);
                if (context === undefined) {
                    context = new XmlEditorContext(this._document);
                    this.contexts.set(contextId, context);
                }
                return context;
            };
        /**
         * @param {?} contextId
         * @return {?}
         */
        AngularXmlEditorService.prototype.disposeEditorContext = /**
         * @param {?} contextId
         * @return {?}
         */
            function (contextId) {
                this.contexts.delete(contextId);
            };
        AngularXmlEditorService.decorators = [
            { type: i0.Injectable, args: [{
                        providedIn: 'root'
                    },] }
        ];
        /** @nocollapse */
        AngularXmlEditorService.ctorParameters = function () {
            return [
                { type: Document, decorators: [{ type: i0.Inject, args: [i1.DOCUMENT,] }] }
            ];
        };
        /** @nocollapse */ AngularXmlEditorService.ngInjectableDef = i0.defineInjectable({ factory: function AngularXmlEditorService_Factory() { return new AngularXmlEditorService(i0.inject(i1.DOCUMENT)); }, token: AngularXmlEditorService, providedIn: "root" });
        return AngularXmlEditorService;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var Html2xml = /** @class */ (function () {
        function Html2xml(rules) {
            this.rules = rules;
            this.attributeWorker = new Xml2htmlAttributeWorker(rules);
        }
        /**
         * @param {?} html
         * @return {?}
         */
        Html2xml.prototype.ToXml = /**
         * @param {?} html
         * @return {?}
         */
            function (html) {
                if (html === '') {
                    return '';
                }
                /** @type {?} */
                var cleanHtml = this.CleanUpHtmlBeforeConvert2Xml(html);
                /** @type {?} */
                var domparser = new DOMParser();
                /** @type {?} */
                var domdoc = domparser.parseFromString(cleanHtml, 'text/xml');
                /** @type {?} */
                var targetDocument = new Document();
                if (domdoc.documentElement === null) {
                    return '';
                }
                /** @type {?} */
                var body = this.GetXmlElementFromHtmlElement(domdoc.documentElement, targetDocument);
                if (body && body.nodeType === Node.ELEMENT_NODE) {
                    /** @type {?} */
                    var xml = ( /** @type {?} */(body)).outerHTML;
                    return xml;
                }
                else {
                    throw new Error("root node " + XmlToolbox.GetNodeDebugContext(body) + " is no element");
                }
            };
        /**
         * @param {?} html
         * @return {?}
         */
        Html2xml.prototype.CleanUpHtmlBeforeConvert2Xml = /**
         * @param {?} html
         * @return {?}
         */
            function (html) {
                /** @type {?} */
                var domparser = new DOMParser();
                /** @type {?} */
                var domdoc = domparser.parseFromString(html, 'text/html');
                new DomDummyNodeManager().RemoveAllDummyNodes(domdoc.documentElement);
                /** @type {?} */
                var cleanHtml = domdoc.body.innerHTML;
                return cleanHtml;
            };
        /**
         * @param {?} node
         * @param {?} targetDocument
         * @return {?}
         */
        Html2xml.prototype.GetXmlElementFromHtmlElement = /**
         * @param {?} node
         * @param {?} targetDocument
         * @return {?}
         */
            function (node, targetDocument) {
                switch (node.nodeType) {
                    case Node.ELEMENT_NODE: // element node
                        /** @type {?} */
                        var asElement = /** @type {?} */ (node);
                        /** @type {?} */
                        var tagName = Xml2html.getTagNameFromNode(node);
                        if (!tagName || tagName === '') {
                            throw new Error("no tagname in " + XmlToolbox.GetNodeDebugContext(node));
                        }
                        /** @type {?} */
                        var newElement = targetDocument.createElement(tagName);
                        /** @type {?} */
                        var children = asElement.childNodes;
                        if (children.length === 0 && !asElement.classList.contains(Xml2html.NoClosingTagClassName)) {
                            newElement.appendChild(targetDocument.createTextNode('')); // to prevent non closing tags
                        }
                        else {
                            for (var i = 0; i < children.length; ++i) {
                                /** @type {?} */
                                var childAsHtml = this.GetXmlElementFromHtmlElement(children[i], targetDocument);
                                if (childAsHtml !== undefined) {
                                    newElement.appendChild(childAsHtml);
                                }
                            }
                        }
                        // // insert attributes
                        this.attributeWorker.writeAllHtmlAttributesToXml(asElement, newElement);
                        return newElement;
                    case Node.TEXT_NODE: // text node
                        /** @type {?} */
                        var content = ( /** @type {?} */(node)).textContent;
                        if (content.length > 0) {
                            return targetDocument.createTextNode(content);
                        }
                        else {
                            return undefined;
                        }
                    default:
                        // tslint:disable-next-line:max-line-length
                        throw new Error("unknown html element nodeType " + node.nodeType + " in value: " + XmlToolbox.GetNodeDebugContext(node));
                }
            };
        return Html2xml;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var AngularXmlEditorComponent = /** @class */ (function () {
        function AngularXmlEditorComponent(_renderer, editorService) {
            this._renderer = _renderer;
            this.editorService = editorService;
            this.isDebugMode = false;
            this.valueChange = new i0.EventEmitter();
            // actualXmlCursor: XmlCursor = new XmlCursor();
            this.domDummyNodeManager = new DomDummyNodeManager();
        }
        Object.defineProperty(AngularXmlEditorComponent.prototype, "config", {
            get: /**
             * @return {?}
             */ function () {
                if (this.editorContext !== undefined && this.editorContext.config !== undefined) {
                    return this.editorContext && this.editorContext.config;
                }
                return undefined;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(AngularXmlEditorComponent.prototype, "editorContextId", {
            set: /**
             * @param {?} value
             * @return {?}
             */ function (value) {
                if (!value) {
                    return;
                }
                this.editorContext = this.editorService.getEditorContext(value);
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(AngularXmlEditorComponent.prototype, "debugMode", {
            set: /**
             * @param {?} value
             * @return {?}
             */ function (value) {
                this.isDebugMode = value;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.ngOnChanges = /**
         * @return {?}
         */
            function () { };
        /**
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.ngOnDestroy = /**
         * @return {?}
         */
            function () { };
        /**
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.onLostFocus = /**
         * @return {?}
         */
            function () {
                this.editorContext.saveSelection(); // save selection on lost focus
                if (typeof this.onTouchedFunction === 'function') {
                    this.onTouchedFunction();
                }
                return;
            };
        /**
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.onGotFocus = /**
         * @return {?}
         */
            function () {
                this.editorContext.restoreSelection();
                this.textArea.nativeElement.focus(); // set focus to the text area
            };
        /**
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.clicked = /**
         * @return {?}
         */
            function () { };
        /**
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.mousedown = /**
         * @return {?}
         */
            function () { };
        /**
         * @param {?} mouseEvent
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.mouseup = /**
         * @param {?} mouseEvent
         * @return {?}
         */
            function (mouseEvent) {
                return this.editorContext.mouseUp(mouseEvent);
            };
        /**
         * @param {?} text
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.pasted = /**
         * @param {?} text
         * @return {?}
         */
            function (text) {
                return this.editorContext.pasted(text);
            };
        /**
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.copied = /**
         * @return {?}
         */
            function () {
                return this.editorContext.copied();
            };
        /**
         * @param {?} event
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.keyDown = /**
         * @param {?} event
         * @return {?}
         */
            function (event) {
                return this.editorContext.keyDown(event);
            };
        /**
         * @param {?} event
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.keyUp = /**
         * @param {?} event
         * @return {?}
         */
            function (event) {
                return this.editorContext.keyUp(event);
            };
        // exec(): boolean {
        //   let userSelection: Selection;
        //   if (window.getSelection) {
        //     userSelection = window.getSelection();
        //     this.editorBreadCrumb.showSelection(userSelection);
        //     this.actualXmlCursor.StartPos.SetCursor(userSelection.anchorNode, XMLCursorPositionen.CursorInsideTextNode, userSelection.anchorOffset);
        //     this.commander.setCursorPos(this.actualXmlCursor.StartPos);
        //   }
        //   this.domDummyNodeManager.UpdateDummyNodes(this.actualXmlCursor.xmlDocumentRootNode, false);
        //   return false;
        // }
        /**
         * @param {?} xml
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.showXml = /**
         * @param {?} xml
         * @return {?}
         */
            function (xml) {
                if (this.textArea && this.editorContext && this.editorContext.config && this.editorContext.config.rules) {
                    if (xml === undefined) {
                        return;
                    }
                    /** @type {?} */
                    var xml2html = new Xml2html(this.editorContext.config.rules);
                    /** @type {?} */
                    var html = xml2html.ToHtml(xml);
                    /** @type {?} */
                    var normalizedValue = xml === null ? '' : html;
                    this._renderer.setProperty(this.textArea.nativeElement, 'innerHTML', normalizedValue);
                }
            };
        /* START OF ControlValueAccessor  (see https://angular.io/api/forms/ControlValueAccessor ) */
        /**
         * Sets the function called when the control gets a change event
         */
        /**
         * Sets the function called when the control gets a change event
         * @param {?} func
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.registerOnChange = /**
         * Sets the function called when the control gets a change event
         * @param {?} func
         * @return {?}
         */
            function (func) {
                this.onChangeFunction = func;
            };
        /**
         * Sets the function called when the control gets a touch event
         */
        /**
         * Sets the function called when the control gets a touch event
         * @param {?} func
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.registerOnTouched = /**
         * Sets the function called when the control gets a touch event
         * @param {?} func
         * @return {?}
         */
            function (func) {
                this.onTouchedFunction = func;
            };
        /**
         * Write the new value to the element
         */
        /**
         * Write the new value to the element
         * @param {?} value
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.writeValue = /**
         * Write the new value to the element
         * @param {?} value
         * @return {?}
         */
            function (value) {
                if (this.editorContext && this.editorContext.config) {
                    if (value === null || value === undefined || value === '') {
                        value = undefined;
                    }
                    this.showXml(value);
                    if (value === undefined) {
                        this.editorContext.actualCursor.xmlDocumentRootNode = undefined;
                    }
                    else {
                        /** @type {?} */
                        var el = /** @type {?} */ (this.textArea.nativeElement);
                        /** @type {?} */
                        var node = /** @type {?} */ (el.firstChild);
                        this.editorContext.actualCursor.xmlDocumentRootNode = node;
                        this.editorContext.actualCursor.StartPos.SetCursor(this.editorContext.actualCursor.xmlDocumentRootNode, XMLCursorPositions.CursorOnCompleteNode);
                        this.domDummyNodeManager.UpdateDummyNodes(this.editorContext.actualCursor.xmlDocumentRootNode);
                    }
                }
            };
        /**
         * Executed from the contenteditable section while the input property changes
         * @param html html string from contenteditable
         */
        /**
         * Executed from the contenteditable section while the input property changes
         * @param {?} html html string from contenteditable
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.onContentChange = /**
         * Executed from the contenteditable section while the input property changes
         * @param {?} html html string from contenteditable
         * @return {?}
         */
            function (html) {
                if (typeof this.onChangeFunction === 'function') {
                    /** @type {?} */
                    var html2xml = new Html2xml(this.editorContext.config.rules);
                    /** @type {?} */
                    var xml = html2xml.ToXml(html);
                    /** @type {?} */
                    var normalizedValue = xml === null ? '' : xml;
                    this.onChangeFunction(normalizedValue);
                }
                return;
            };
        /**
         * sets the disabled state for this element
         */
        /**
         * sets the disabled state for this element
         * @param {?} isDisabled
         * @return {?}
         */
        AngularXmlEditorComponent.prototype.setDisabledState = /**
         * sets the disabled state for this element
         * @param {?} isDisabled
         * @return {?}
         */
            function (isDisabled) {
                /** @type {?} */
                var div = this.textArea.nativeElement;
                /** @type {?} */
                var action = isDisabled ? 'addClass' : 'removeClass';
                this._renderer[action](div, 'disabled');
            };
        AngularXmlEditorComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'axed-editor',
                        template: "<div\r\n  *ngIf=\"config\"\r\n  #editor\r\n  class=\"axed axed-textarea showtags debugOff\"\r\n  (focus)=\"onGotFocus()\"\r\n  [attr.contenteditable]=\"true\"\r\n  [style.height]=\"config.height\"\r\n  [style.width]=\"config.width\"\r\n  (input)=\"onContentChange($event.target.innerHTML)\"\r\n  (blur)=\"onLostFocus()\"\r\n  (click)=\"clicked()\"\r\n  (mousedown)=\"mousedown()\"\r\n  (mouseup)=\"mouseup($event)\"\r\n  (keyup)=\"keyUp($event)\"\r\n  (keydown)=\"keyDown($event)\"\r\n  (copy)=\"copied()\"\r\n  (paste)=\"pasted($event.clipboardData.getData('text/plain'))\"\r\n></div>\r\n",
                        encapsulation: i0.ViewEncapsulation.None,
                        // to prevent the scss to rename the class names and not match the new generated xml dom
                        providers: [
                            {
                                provide: forms.NG_VALUE_ACCESSOR,
                                useExisting: i0.forwardRef(function () { return AngularXmlEditorComponent; }),
                                multi: true
                            }
                        ],
                        styles: ["a{cursor:pointer}.axed-textarea{min-height:150px;overflow:auto;margin-top:5px;resize:vertical;outline:0;--font-size:15px;--topBottomTagPadding:2px;--tagIndent:20px;font-size:var(--font-size);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif}.axed-textarea.showtags{line-height:calc(var(--font-size) + (var(--topBottomTagPadding) * 2) + 10px)}.axed-textarea.showtags div::after,.axed-textarea.showtags div::before{background:orange;white-space:pre-wrap;border:1px solid #778899}.axed-textarea.showtags div::after,.axed-textarea.showtags div:not(.xmlTagNoClosing)::before{content:\" \" attr(data-tagname) \" \";padding:var(--topBottomTagPadding) 0 var(--topBottomTagPadding);margin:0 2px 2px}.axed-textarea.showtags div:not(.xmlTagNoClosing)::after{content:\"  \" attr(data-tagname);padding-right:7px;border-radius:10px 0 0 10px}.axed-textarea.showtags div:not(.xmlTagNoClosing)::before{border-radius:0 10px 10px 0}.axed-textarea.showtags div[data-attributes].xmlTagNoClosing:not([data-attributes=''])::after,.axed-textarea.showtags div[data-attributes]:not([data-attributes='']):not(.xmlTagNoClosing)::before{content:\" \" attr(data-tagname) \" \" attr(data-attributes) \" \"}.axed-textarea.showtags div.comment::after,.axed-textarea.showtags div.comment::before{content:' ' 'comment' ' ';background-color:#d3d3d3}.axed-textarea div div:not(.floating){margin-left:var(--tagIndent)}.tagElement>.dummyNode.parent{color:red}div.floating{display:inline}span.dummyNode.beforefirstTag{float:left;width:0}.axed-textarea.debug span.dummyNode{background-color:red;width:inherit}.axed-textarea.debug span.dummyNode.beforefirstTag{background-color:violet;width:inherit}.axed-textarea.showtags div.selected,.axed-textarea.showtags div.selected::after,.axed-textarea.showtags div.selected::before{background:#add8e6!important;color:#fff}[data-tagname=parsererror],[data-tagname=parsererror] div,[data-tagname=parsererror] div ::after,[data-tagname=parsererror] div::before,[data-tagname=parsererror]::after,[data-tagname=parsererror]::before{background:red!important;color:#fff!important;font-weight:700!important;font-size:20px!important;line-height:32px!important}.angular-editor{position:relative}.angular-editor ::ng-deep [contenteditable=true]:empty:before{content:attr(placeholder);display:block;color:#868e96;opacity:1}.angular-editor .axed-wrapper{position:relative}.angular-editor .axed-wrapper .axed-textarea{min-height:5rem;padding:.5rem .8rem 1rem;border:1px solid #ddd;background-color:transparent;overflow-x:hidden;overflow-y:auto;z-index:2;position:relative}.angular-editor .axed-wrapper .axed-textarea.focus,.angular-editor .axed-wrapper .axed-textarea:focus{outline:0}.angular-editor .axed-wrapper .axed-textarea ::ng-deep blockquote{margin-left:1rem;border-left:.2em solid #dfe2e5;padding-left:.5rem}.angular-editor .axed-wrapper ::ng-deep p{margin-bottom:0}.angular-editor .axed-wrapper .axed-placeholder{display:none;position:absolute;top:0;padding:.5rem .8rem 1rem .9rem;z-index:1;color:#6c757d;opacity:.75}.angular-editor .axed-wrapper.show-placeholder .angular-editor-placeholder{display:block}.angular-editor .axed-wrapper.disabled{cursor:not-allowed;opacity:.5;pointer-events:none}.axed-attribute-editor-toolbar{min-height:100px;font:100 .8rem/15px Roboto,Arial,sans-serif;background-color:#f5f5f5;padding:15px;border:1px solid #ddd;margin:0}.axed-attribute-editor-toolbar input,.axed-attribute-editor-toolbar select{width:100%}"]
                    }] }
        ];
        /** @nocollapse */
        AngularXmlEditorComponent.ctorParameters = function () {
            return [
                { type: i0.Renderer2 },
                { type: AngularXmlEditorService }
            ];
        };
        AngularXmlEditorComponent.propDecorators = {
            config: [{ type: i0.Input, args: ['config',] }],
            editorContextId: [{ type: i0.Input, args: ['editorContextId',] }],
            debugMode: [{ type: i0.Input, args: ['debugMode',] }],
            textArea: [{ type: i0.ViewChild, args: ['editor',] }],
            editorWrapper: [{ type: i0.ViewChild, args: ['editorWrapper',] }],
            valueChange: [{ type: i0.Output }]
        };
        return AngularXmlEditorComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlRuleElement = /** @class */ (function () {
        function XmlRuleElement(init) {
            Object.assign(this, init);
        }
        /**
         * @param {?} elements
         * @return {?}
         */
        XmlRuleElement.Sorted = /**
         * @param {?} elements
         * @return {?}
         */
            function (elements) {
                /** @type {?} */
                var result = elements.sort(function (e1, e2) {
                    if (e1.tagName > e2.tagName) {
                        return 1;
                    }
                    if (e1.tagName < e2.tagName) {
                        return -1;
                    }
                    return 0;
                });
                return result;
            };
        return XmlRuleElement;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditRuleCheckElements = /** @class */ (function () {
        function XmlEditRuleCheckElements(xsdNodes) {
            this.xsdNodes = xsdNodes;
        }
        /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
        XmlEditRuleCheckElements.prototype.ElementsAllowedAtThisCursorPos = /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
            function (cursorPosToCheck) {
                if (!cursorPosToCheck) {
                    return [];
                }
                /** @type {?} */
                var parentNode = this.getRelevantParentNodeForCursorPos(cursorPosToCheck);
                /** @type {?} */
                var parentName = Xml2html.getTagNameFromNode(parentNode);
                /** @type {?} */
                var xsdNode = this.xsdNodes.get(parentName);
                if (xsdNode) {
                    /** @type {?} */
                    var result = this.getSubElementNames(xsdNode, []);
                    return result;
                }
                else {
                    // console.warn('element "' + parentName + '" not found');
                    return [];
                }
            };
        /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
        XmlEditRuleCheckElements.prototype.getRelevantParentNodeForCursorPos = /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
            function (cursorPosToCheck) {
                if (cursorPosToCheck) {
                    /** @type {?} */
                    var parentNode = cursorPosToCheck.ActualNode;
                    switch (parentNode.nodeType) {
                        case Node.COMMENT_NODE:
                        case Node.TEXT_NODE:
                            parentNode = parentNode.parentElement;
                            break;
                        case Node.ELEMENT_NODE:
                            switch (cursorPosToCheck.PosAtNode) {
                                case XMLCursorPositions.CursorInEmptyNode:
                                case XMLCursorPositions.CursorInsideTextNode:
                                    break;
                                case XMLCursorPositions.CursorBehindNode:
                                case XMLCursorPositions.CursorInFrontOfNode:
                                case XMLCursorPositions.CursorOnCompleteNode:
                                    parentNode = parentNode.parentElement;
                                    break;
                                default:
                                    throw new Error("unhandled  cursorPosToCheck.PosAmNode \"" + cursorPosToCheck.PosAtNode + "\"/" + XmlCursorPos.getXmlCursorPositionDebugName(cursorPosToCheck.PosAtNode) + "\" ");
                            }
                            break;
                        default:
                            throw new Error("unhandled  parentNode.nodeType \"" + parentNode.nodeType + "\"");
                    }
                    return parentNode;
                }
            };
        /**
         * @param {?} xsdNode
         * @param {?} alreadyAddedElementNames
         * @param {?=} depth
         * @return {?}
         */
        XmlEditRuleCheckElements.prototype.getSubElementNames = /**
         * @param {?} xsdNode
         * @param {?} alreadyAddedElementNames
         * @param {?=} depth
         * @return {?}
         */
            function (xsdNode, alreadyAddedElementNames, depth) {
                var _this = this;
                if (depth === void 0) {
                    depth = 0;
                }
                /** @type {?} */
                var elementNames = [];
                /** @type {?} */
                var elementName;
                if (xsdNode.nodeType === Node.ELEMENT_NODE) {
                    /** @type {?} */
                    var asElem = /** @type {?} */ (xsdNode);
                    if (asElem) {
                        if (asElem.localName === 'element') {
                            elementName = asElem.getAttribute('name');
                        }
                    }
                }
                if (elementName) {
                    // console.warn('found: ' + JSON.stringify(elementName) + ' depth: ' + depth);
                    if (alreadyAddedElementNames.length !== 0) {
                        if (alreadyAddedElementNames.indexOf(elementName) !== -1) {
                            return elementNames; // element recursion detected
                        }
                        if (depth === 0) ;
                        else {
                            elementNames = elementNames.concat(elementName);
                            return elementNames;
                        }
                    }
                    alreadyAddedElementNames.push(elementName);
                }
                /** @type {?} */
                var childNodes = /** @type {?} */ (Array.prototype.slice.call(xsdNode.childNodes));
                depth++;
                childNodes.forEach(function (child) {
                    if (child.nodeType === Node.ELEMENT_NODE) {
                        /** @type {?} */
                        var childElem = /** @type {?} */ (child);
                        if (childElem) {
                            switch (childElem.localName) {
                                case 'complexType':
                                case 'sequence':
                                case 'choice':
                                case 'simpleContent':
                                case 'extension':
                                    elementNames = elementNames.concat(_this.getSubElementNames(child, alreadyAddedElementNames, depth));
                                    break;
                                case 'element':
                                    /** @type {?} */
                                    var refname = childElem.attributes.getNamedItem('ref');
                                    if (refname) {
                                        /** @type {?} */
                                        var referedNode = _this.xsdNodes.get(refname.value);
                                        if (referedNode) {
                                            elementNames = elementNames.concat(_this.getSubElementNames(referedNode, alreadyAddedElementNames, depth));
                                        }
                                        else {
                                            throw new Error(" refered element \"" + refname + "\" for element \"" + childElem.outerHTML + "\" not found");
                                        }
                                    }
                                    else {
                                        elementNames = elementNames.concat(_this.getSubElementNames(child, alreadyAddedElementNames, depth));
                                    }
                                    break;
                                case 'attribute':
                                    break;
                                default:
                                    throw new Error("unknown childElem.localname \"" + childElem.localName + "\"/" + childElem.outerHTML);
                            }
                        }
                    }
                });
                return elementNames;
            };
        return XmlEditRuleCheckElements;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditorToolbarComponent = /** @class */ (function () {
        function XmlEditorToolbarComponent(editorService) {
            this.editorService = editorService;
            this.elementGroups = [];
        }
        Object.defineProperty(XmlEditorToolbarComponent.prototype, "config", {
            get: /**
             * @return {?}
             */ function () {
                if (this.editorContext !== undefined && this.editorContext.config !== undefined) {
                    return this.editorContext && this.editorContext.config;
                }
                return undefined;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(XmlEditorToolbarComponent.prototype, "editorContextId", {
            set: /**
             * @param {?} value
             * @return {?}
             */ function (value) {
                var _this = this;
                if (!value) {
                    return;
                }
                this.editorContext = this.editorService.getEditorContext(value);
                this.actualCursorPosChangedSubscription = this.editorContext.actualCursorChanged.subscribe(function (pos) {
                    _this.elementGroups = _this.GetElementGroupsForCursorPos(pos.StartPos);
                });
            },
            enumerable: true,
            configurable: true
        });
        /** inserts an element at the actual cursor pos */
        /**
         * inserts an element at the actual cursor pos
         * @param {?} element
         * @return {?}
         */
        XmlEditorToolbarComponent.prototype.insertElement = /**
         * inserts an element at the actual cursor pos
         * @param {?} element
         * @return {?}
         */
            function (element) {
                /** @type {?} */
                var html = new Xml2html(this.editorContext.config.rules).createNewElementHtml(element);
                this.editorContext.domInsertHtml(html);
            };
        /**
         * @return {?}
         */
        XmlEditorToolbarComponent.prototype.ngAfterViewInit = /**
         * @return {?}
         */
            function () { };
        /**
         * @return {?}
         */
        XmlEditorToolbarComponent.prototype.ngOnChanges = /**
         * @return {?}
         */
            function () { };
        /**
         * @return {?}
         */
        XmlEditorToolbarComponent.prototype.ngOnDestroy = /**
         * @return {?}
         */
            function () {
                this.actualCursorPosChangedSubscription.unsubscribe();
            };
        /**
         * @param {?} pos
         * @return {?}
         */
        XmlEditorToolbarComponent.prototype.GetElementGroupsForCursorPos = /**
         * @param {?} pos
         * @return {?}
         */
            function (pos) {
                /** @type {?} */
                var allowedElements = new XmlEditRuleCheckElements(this.editorContext.config.xmlSchema.xsdNodes).ElementsAllowedAtThisCursorPos(pos);
                return this.GetAllElementGroups()
                    .map(function (g) {
                    return /** @type {?} */ ({
                        title: g.title,
                        elements: g.elements.filter(function (e) { return allowedElements.includes(e.tagName); })
                    });
                })
                    .filter(function (g) { return g.elements.length > 0; });
            };
        /**
         * @return {?}
         */
        XmlEditorToolbarComponent.prototype.GetAllElementGroups = /**
         * @return {?}
         */
            function () {
                var _this = this;
                /** @type {?} */
                var unusedElements = XmlRuleElement.Sorted(Array.from(this.editorContext.config.rules.ruleElements.values()).filter(function (elem) {
                    return _this.editorContext.config.elementGroups.some(function (group) { return !group.elementNames.includes(elem.tagName); });
                }));
                /** @type {?} */
                var otherElementsGroup = /** @type {?} */ ({
                    title: 'other',
                    elements: unusedElements
                });
                return this.editorContext.config.elementGroups
                    .map(function (g) {
                    return /** @type {?} */ ({
                        title: g.title,
                        elements: XmlRuleElement.Sorted(g.elementNames.map(function (elementName) { return _this.editorContext.config.rules.ruleElements.get(elementName); }).filter(function (e) { return e !== undefined; }))
                    });
                })
                    .concat(otherElementsGroup)
                    .filter(function (g) { return g.elements.length !== 0; });
            };
        XmlEditorToolbarComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'axed-toolbar',
                        template: "<div class=\"sws-xml-editor-toolbar\">\r\n  <h3>Insert element</h3>\r\n\r\n  <!--\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <button type=\"button\" title=\"Undo\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('undo')\"><i class='fa fa-undo'></i></button>\r\n      <button type=\"button\" title=\"Redo\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('redo')\"><i class='fa fa-repeat'></i></button>\r\n    </div>\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <button [id]=\"'bold-'+id\" type=\"button\" title=\"Bold\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('bold')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-bold'></i></button>\r\n      <button [id]=\"'italic-'+id\" type=\"button\" title=\"Italic\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('italic')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-italic'></i></button>\r\n      <button [id]=\"'underline-'+id\" type=\"button\" title=\"Underline\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('underline')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-underline'></i></button>\r\n      <button [id]=\"'strikeThrough-'+id\" type=\"button\" title=\"Strikethrough\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('strikeThrough')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-strikethrough'></i></button>\r\n      <button [id]=\"'subscript-'+id\" type=\"button\" title=\"Subscript\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('subscript')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-subscript'></i></button>\r\n      <button [id]=\"'superscript-'+id\" type=\"button\" title=\"Superscript\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('superscript')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-superscript'></i></button>\r\n    </div>\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <button [id]=\"'justifyLeft-'+id\" type=\"button\" title=\"Justify Left\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('justifyLeft')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-align-left'></i></button>\r\n      <button [id]=\"'justifyCenter-'+id\" type=\"button\" title=\"Justify Center\" class=\"angular-editor-button\" (click)=\"triggerCommand('justifyCenter')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-align-center'></i></button>\r\n      <button [id]=\"'justifyRight-'+id\" type=\"button\" title=\"Justify Right\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('justifyRight')\"\r\n        [disabled]=\"htmlMode\">\r\n        <i class='fa fa-align-right'></i></button>\r\n      <button [id]=\"'justifyFull-'+id\" type=\"button\" title=\"Justify Full\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('justifyFull')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-align-justify'></i></button>\r\n    </div>\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <button [id]=\"'indent-'+id\" type=\"button\" title=\"Indent\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('indent')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-indent'></i></button>\r\n      <button [id]=\"'outdent-'+id\" type=\"button\" title=\"Outdent\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('outdent')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-outdent'></i></button>\r\n    </div>\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <button [id]=\"'insertUnorderedList-'+id\" type=\"button\" title=\"Unordered List\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('insertUnorderedList')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-list-ul'></i></button>\r\n      <button [id]=\"'insertOrderedList-'+id\" type=\"button\" title=\"Ordered List\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('insertOrderedList')\"\r\n        [disabled]=\"htmlMode\"><i class='fa fa-list-ol'></i></button>\r\n    </div>\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <label [for]=\"'heading-'+id\" class=\"block-label\"></label>\r\n      <select title=\"Formatting\" [id]=\"'heading-'+id\" class=\"select-heading\" [(ngModel)]=\"block\" (change)=\"triggerCommand(block)\"\r\n        [disabled]=\"htmlMode\">\r\n        <optgroup label=\"Formatting\"></optgroup>\r\n        <option class=\"h1\" value=\"h1\">Heading 1</option>\r\n        <option class=\"h2\" value=\"h2\">Heading 2</option>\r\n        <option class=\"h3\" value=\"h3\">Heading 3</option>\r\n        <option class=\"h4\" value=\"h4\">Heading 4</option>\r\n        <option class=\"h5\" value=\"h5\">Heading 5</option>\r\n        <option class=\"h6\" value=\"h6\">Heading 6</option>\r\n        <option class=\"p\" value=\"p\">Paragraph</option>\r\n        <option class=\"pre\" value=\"pre\">Predefined</option>\r\n        <option class=\"div\" value=\"div\">Standard</option>\r\n        <option class=\"default\" value=\"default\">Default</option>\r\n      </select>\r\n    </div>\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <label [for]=\"'fontSelector-'+id\" class=\"block-label\"></label>\r\n      <select title=\"Font Name\" [id]=\"'fontSelector-'+id\" class=\"select-font\" [(ngModel)]=\"fontName\" (change)=\"setFontName(fontName)\"\r\n        [disabled]=\"htmlMode\">\r\n        <optgroup label=\"Font Name\"></optgroup>\r\n        <option class=\"arial\" value=\"Arial\">Arial</option>\r\n        <option class=\"calibri\" value=\"Calibri\">Calibri</option>\r\n        <option class=\"comic-sans-ms\" value=\"Comic Sans MS\">Comic Sans MS</option>\r\n        <option class=\"times-new-roman\" value=\"Times New Roman\">Times New Roman</option>\r\n      </select>\r\n    </div>\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <label [for]=\"'fontSizeSelector-'+id\" class=\"block-label\"></label>\r\n      <select title=\"Font Size\" [id]=\"'fontSizeSelector-'+id\" class=\"select-font-size\" [(ngModel)]=\"fontSize\" (change)=\"setFontSize(fontSize)\"\r\n        [disabled]=\"htmlMode\">\r\n        <optgroup label=\"Font Sizing\"></optgroup>\r\n        <option class=\"size1\" value=\"1\">1</option>\r\n        <option class=\"size2\" value=\"2\">2</option>\r\n        <option class=\"size3\" value=\"3\">3</option>\r\n        <option class=\"size4\" value=\"4\">4</option>\r\n        <option class=\"size5\" value=\"5\">5</option>\r\n        <option class=\"size6\" value=\"6\">6</option>\r\n        <option class=\"size7\" value=\"7\">7</option>\r\n      </select>\r\n    </div>\r\n    <div class=\"angular-editor-toolbar-set\">\r\n      <input style=\"display: none\" type=\"color\" (change)=\"insertColor(fgInput.value, 'textColor')\" #fgInput>\r\n      <button [id]=\"'foregroundColorPicker-'+id\" type=\"button\" class=\"sws-xml-editor-button\" (click)=\"fgInput.click()\"\r\n        title=\"Text Color\" [disabled]=\"htmlMode\"><span class=\"color-label foreground\"><i class=\"fa fa-font\"></i></span></button>\r\n      <input style=\"display: none\" type=\"color\" (change)=\"insertColor(bgInput.value, 'backgroundColor')\" #bgInput>\r\n      <button [id]=\"'backgroundColorPicker-'+id\" type=\"button\" class=\"sws-xml-editor-button\" (click)=\"bgInput.click()\"\r\n        title=\"Background Color\" [disabled]=\"htmlMode\"><span class=\"color-label background\"><i class=\"fa fa-font\"></i></span></button>\r\n    </div>\r\n    <div *ngIf=\"customClasses\" class=\"sws-xml-editor-toolbar-set\">\r\n      <label [for]=\"'customClassSelector-'+id\" class=\"block-label\"></label>\r\n      <select title=\"Custom Style\" [id]=\"'customClassSelector-'+id\" class=\"select-custom-style\" [(ngModel)]=\"customClassId\"\r\n        (change)=\"setCustomClass(customClassId)\" [disabled]=\"htmlMode\">\r\n        <optgroup label=\"Custom Class\"></optgroup>\r\n        <option class=\"\" value=-1>Clear Class</option>\r\n        <option *ngFor=\"let item of customClasses; let i = index\" [class]=\"item.class\" [value]=\"i\">{{item.name}}</option>\r\n      </select>\r\n    </div>\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <button [id]=\"'link-'+id\" type=\"button\" class=\"sws-xml-editor-button\" (click)=\"insertUrl()\" title=\"Insert Link\"\r\n        [disabled]=\"htmlMode\">\r\n        <i class=\"fa fa-link\"></i>\r\n      </button>\r\n      <button type=\"button\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('unlink')\" title=\"Unlink\" [disabled]=\"htmlMode\">\r\n        <i class=\"fa fa-chain-broken\"></i>\r\n      </button>\r\n      <input style=\"display: none\" type=\"file\" (change)=\"onFileChanged($event)\" #fileInput>\r\n      <button type=\"button\" class=\"sws-xml-editor-button\" (click)=\"fileInput.click()\" title=\"Insert Image\" [disabled]=\"htmlMode\"><i\r\n          class=\"fa fa-image\"></i></button>\r\n\r\n      <button type=\"button\" title=\"Horizontal Line\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('insertElement_STAR')\"\r\n        [disabled]=\"htmlMode\"><i class=\"fa fa-minus\"></i> STAR</button>\r\n    </div>\r\n  -->\r\n\r\n\r\n\r\n  <div class=\"sws-xml-editor-toolbar-set\" *ngFor=\"let group of elementGroups\">\r\n    <label class=\"sws-editor-toolbar-grouplabel\" *ngIf=\"group.title\">{{ group.title }}:</label>\r\n    <button *ngFor=\"let elem of group.elements\" type=\"button\" title=\"{{elem.title}}\" class=\"sws-xml-editor-button\"\r\n      (click)=\"insertElement(elem)\">\r\n      <span *ngIf=\"elem.iconClass\"><i class=\"{{elem.iconClass}}\"></i>&nbsp;</span>{{ elem.tagName }}\r\n    </button>\r\n  </div>\r\n\r\n  <div class=\"sws-xml-editor-toolbar-set\">\r\n    <button type=\"button\" title=\"remove tag\" class=\"sws-xml-editor-button\"><i class=\"fa fa-remove\"></i> remove</button>\r\n  </div>\r\n\r\n  <!--\r\n    <div class=\"sws-xml-editor-toolbar-set\">\r\n      <button [id]=\"'toggleEditorMode-'+id\" type=\"button\" title=\"HTML Code\" class=\"sws-xml-editor-button\" (click)=\"triggerCommand('toggleEditorMode')\"><i\r\n          class='fa fa-code'></i></button>\r\n    </div>\r\n  -->\r\n</div>\r\n",
                        styles: [".sws-xml-editor-toolbar{display:inline-block}.sws-xml-editor-toolbar .sws-xml-editor-toolbar-set{border-radius:5px;background-color:#fff;margin-right:5px;margin-bottom:5px;border:1px solid #ddd;clear:both;float:left;display:block;position:relative}.sws-xml-editor-toolbar .sws-xml-editor-toolbar-set .sws-editor-toolbar-grouplabel{display:block;font-weight:700;background-color:transparent;float:left;padding:.5em .5em 0}.sws-xml-editor-toolbar .sws-xml-editor-toolbar-set .sws-xml-editor-button{border-radius:5px;background-color:transparent;margin:2px;padding:.6em;min-width:3em;float:left;border:.5px solid #eee}.sws-xml-editor-toolbar .sws-xml-editor-toolbar-set .sws-xml-editor-button:hover{cursor:pointer;background-color:#ff8c00;transition:.2s}"]
                    }] }
        ];
        /** @nocollapse */
        XmlEditorToolbarComponent.ctorParameters = function () {
            return [
                { type: AngularXmlEditorService }
            ];
        };
        XmlEditorToolbarComponent.propDecorators = {
            config: [{ type: i0.Input, args: ['config',] }],
            editorContextId: [{ type: i0.Input, args: ['editorContextId',] }]
        };
        return XmlEditorToolbarComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlRuleAttribut = /** @class */ (function () {
        function XmlRuleAttribut(init) {
            Object.assign(this, init);
            this.typ = this.getTyp();
        }
        /**
         * @return {?}
         */
        XmlRuleAttribut.prototype.getTyp = /**
         * @return {?}
         */
            function () {
                if (this.fixedValues && this.fixedValues.length > 0) {
                    return RuleAttributeTypes.Enum;
                }
                return RuleAttributeTypes.String;
            };
        return XmlRuleAttribut;
    }());
    /** @enum {number} */
    var RuleAttributeTypes = {
        String: 0,
        Enum: 1,
        Number: 2,
    };
    RuleAttributeTypes[RuleAttributeTypes.String] = 'String';
    RuleAttributeTypes[RuleAttributeTypes.Enum] = 'Enum';
    RuleAttributeTypes[RuleAttributeTypes.Number] = 'Number';

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditRuleCheckAttributes = /** @class */ (function () {
        function XmlEditRuleCheckAttributes(xmlSchema) {
            this.xmlSchema = xmlSchema;
        }
        /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
        XmlEditRuleCheckAttributes.prototype.AttributesAllowedAtThisCursorPos = /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
            function (cursorPosToCheck) {
                if (!cursorPosToCheck) {
                    return [];
                }
                /** @type {?} */
                var parentNode = this.getRelevantParentNodeForCursorPos(cursorPosToCheck);
                /** @type {?} */
                var parentName = Xml2html.getTagNameFromNode(parentNode);
                return this.getAttributesForElementName(parentName);
            };
        /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
        XmlEditRuleCheckAttributes.prototype.getRelevantParentNodeForCursorPos = /**
         * @param {?} cursorPosToCheck
         * @return {?}
         */
            function (cursorPosToCheck) {
                if (cursorPosToCheck) {
                    /** @type {?} */
                    var parentNode = cursorPosToCheck.ActualNode;
                    switch (parentNode.nodeType) {
                        case Node.COMMENT_NODE:
                        case Node.TEXT_NODE:
                            parentNode = parentNode.parentElement;
                            break;
                        case Node.ELEMENT_NODE:
                            switch (cursorPosToCheck.PosAtNode) {
                                case XMLCursorPositions.CursorInEmptyNode:
                                case XMLCursorPositions.CursorInsideTextNode:
                                case XMLCursorPositions.CursorOnCompleteNode:
                                    break;
                                case XMLCursorPositions.CursorBehindNode:
                                case XMLCursorPositions.CursorInFrontOfNode:
                                    parentNode = parentNode.parentElement;
                                    break;
                                default:
                                    throw new Error("unhandled cursorPosToCheck.PosAmNode \"" + cursorPosToCheck.PosAtNode + "\"/" + XmlCursorPos.getXmlCursorPositionDebugName(cursorPosToCheck.PosAtNode) + "\" ");
                            }
                            break;
                        default:
                            throw new Error("unhandled parentNode.nodeType \"" + parentNode.nodeType + "\"");
                    }
                    return parentNode;
                }
            };
        /**
         * @param {?} elementName
         * @return {?}
         */
        XmlEditRuleCheckAttributes.prototype.getAttributesForElementName = /**
         * @param {?} elementName
         * @return {?}
         */
            function (elementName) {
                /** @type {?} */
                var xsdNode = this.xmlSchema.findXsdNodeForTagName(elementName);
                return this.getAttributesForElement(xsdNode, new Set([xsdNode]));
            };
        /**
         * @param {?} xsdNode
         * @param {?} alreadyAddedElements
         * @return {?}
         */
        XmlEditRuleCheckAttributes.prototype.getAttributesForElement = /**
         * @param {?} xsdNode
         * @param {?} alreadyAddedElements
         * @return {?}
         */
            function (xsdNode, alreadyAddedElements) {
                var _this = this;
                /** @type {?} */
                var attributes = [];
                if (xsdNode) {
                    alreadyAddedElements.add(xsdNode);
                    /** @type {?} */
                    var childNodes = Array.prototype.slice.call(xsdNode.childNodes);
                    childNodes.forEach(function (child) {
                        if (xsdNode.nodeType === Node.ELEMENT_NODE) {
                            /** @type {?} */
                            var childElem = /** @type {?} */ (child);
                            if (childElem) {
                                if (child.localName === 'attribute') {
                                    // is attribute
                                    attributes = attributes.concat([
                                        new XmlRuleAttribut({
                                            attribName: childElem.attributes.getNamedItem('name').value,
                                            required: _this.isRequiredAttribute(childElem),
                                            xsdRawNode: childElem,
                                            fixedValues: _this.getFixedValues(childElem),
                                            defaultValue: _this.getDefaultValue(childElem)
                                        })
                                    ]);
                                }
                                else {
                                    // no attribute
                                    if (!alreadyAddedElements.has(child)) {
                                        /** @type {?} */
                                        var subNodeAttributes = _this.getAttributesForElement(child, alreadyAddedElements);
                                        attributes = attributes.concat(subNodeAttributes);
                                    }
                                }
                            }
                        }
                    });
                }
                return attributes;
            };
        /**
         * the default value for this attribute
         * @param {?} childElem
         * @return {?}
         */
        XmlEditRuleCheckAttributes.prototype.getDefaultValue = /**
         * the default value for this attribute
         * @param {?} childElem
         * @return {?}
         */
            function (childElem) {
                /** @type {?} */
                var attrib = childElem.attributes.getNamedItem('default');
                if (attrib !== null) {
                    return attrib.value;
                }
                return undefined;
            };
        /**
         * is this attribute required?
         * @param {?} childElem
         * @return {?}
         */
        XmlEditRuleCheckAttributes.prototype.isRequiredAttribute = /**
         * is this attribute required?
         * @param {?} childElem
         * @return {?}
         */
            function (childElem) {
                /** @type {?} */
                var attrib = childElem.attributes.getNamedItem('use');
                /** @type {?} */
                var value = attrib !== null && attrib.value === 'required';
                return value;
            };
        /**
         * get the allowes values for this attribute
         * @param {?} xsdNode
         * @param {?=} alreadyChecked
         * @return {?}
         */
        XmlEditRuleCheckAttributes.prototype.getFixedValues = /**
         * get the allowes values for this attribute
         * @param {?} xsdNode
         * @param {?=} alreadyChecked
         * @return {?}
         */
            function (xsdNode, alreadyChecked) {
                var _this = this;
                if (alreadyChecked === void 0) {
                    alreadyChecked = [];
                }
                /** @type {?} */
                var values = [];
                /** @type {?} */
                var childNodes = Array.prototype.slice.call(xsdNode.childNodes);
                childNodes.forEach(function (child) {
                    if (xsdNode.nodeType === Node.ELEMENT_NODE) {
                        /** @type {?} */
                        var childElem = /** @type {?} */ (child);
                        if (childElem) {
                            if (child.localName === 'enumeration') {
                                values = values.concat([childElem.attributes.getNamedItem('value').value]);
                            }
                            else {
                                // no attribute
                                if (alreadyChecked.indexOf(child) === -1) {
                                    /** @type {?} */
                                    var subNodeAttributes = _this.getFixedValues(child, alreadyChecked);
                                    values = values.concat(subNodeAttributes);
                                }
                            }
                        }
                    }
                });
                return values;
            };
        return XmlEditRuleCheckAttributes;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditorAttributeEditorComponent = /** @class */ (function () {
        function XmlEditorAttributeEditorComponent(editorService) {
            this.editorService = editorService;
            this.attribTypes = RuleAttributeTypes;
            this.attributes = [];
        }
        Object.defineProperty(XmlEditorAttributeEditorComponent.prototype, "editorContextId", {
            set: /**
             * @param {?} value
             * @return {?}
             */ function (value) {
                var _this = this;
                if (!value) {
                    return;
                }
                this.editorContext = this.editorService.getEditorContext(value);
                this.actualCursorPosChangedSubscription = this.editorContext.actualCursorChanged.subscribe(function (pos) {
                    _this.attributes = _this.GetAttributesForCursorPos(pos.StartPos);
                    _this.elementName = _this.GetElementNameForCursorPos(pos.StartPos);
                });
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        XmlEditorAttributeEditorComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () { };
        /**
         * @return {?}
         */
        XmlEditorAttributeEditorComponent.prototype.ngOnDestroy = /**
         * @return {?}
         */
            function () {
                this.actualCursorPosChangedSubscription.unsubscribe();
            };
        /**
         * @param {?} key
         * @param {?} value
         * @return {?}
         */
        XmlEditorAttributeEditorComponent.prototype.attributeValueChanged = /**
         * @param {?} key
         * @param {?} value
         * @return {?}
         */
            function (key, value) {
                if (this.actualElement) {
                    /** @type {?} */
                    var attribWorker = new Xml2htmlAttributeWorker(this.editorContext.config.rules);
                    attribWorker.writeAttributeToHtml(this.actualElement, key, value);
                }
            };
        /**
         * @param {?} pos
         * @return {?}
         */
        XmlEditorAttributeEditorComponent.prototype.GetElementNameForCursorPos = /**
         * @param {?} pos
         * @return {?}
         */
            function (pos) {
                /** @type {?} */
                var rulesCheck = new XmlEditRuleCheckAttributes(this.editorContext.config.xmlSchema);
                /** @type {?} */
                var parentNode = /** @type {?} */ (rulesCheck.getRelevantParentNodeForCursorPos(pos));
                if (parentNode) {
                    return Xml2html.getTagNameFromNode(parentNode);
                }
                return undefined;
            };
        /**
         * @param {?} pos
         * @return {?}
         */
        XmlEditorAttributeEditorComponent.prototype.GetAttributesForCursorPos = /**
         * @param {?} pos
         * @return {?}
         */
            function (pos) {
                /** @type {?} */
                var attribWorker = new Xml2htmlAttributeWorker(this.editorContext.config.rules);
                /** @type {?} */
                var rulesCheck = new XmlEditRuleCheckAttributes(this.editorContext.config.xmlSchema);
                /** @type {?} */
                var parentNode = /** @type {?} */ (rulesCheck.getRelevantParentNodeForCursorPos(pos));
                this.actualElement = parentNode;
                if (parentNode) {
                    /** @type {?} */
                    var allowedAttributes = rulesCheck.AttributesAllowedAtThisCursorPos(pos);
                    return allowedAttributes.map(function (a) {
                        return /** @type {?} */ ({
                            rules: a,
                            value: attribWorker.getAttributeValueFromHtml(parentNode, a.attribName)
                        });
                    });
                }
                return [];
            };
        XmlEditorAttributeEditorComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'axed-attribute-editor',
                        template: "<div class=\"sws-attribute-editor-toolbar\" *ngIf=\"elementName\">\r\n\r\n  <h3>Attributes</h3>\r\n\r\n  <div *ngIf=\"attributes.length > 0; else noAttributes\">\r\n    <p>Attributes for <b>{{elementName}}</b> element</p>\r\n    <div *ngFor=\"let attrib of attributes\">\r\n      <span>{{attrib.rules.attribName}}</span>:<br />\r\n\r\n      <input type=\"text\" *ngIf=\"attrib.rules.typ === attribTypes.String\" value=\"{{attrib.value}}\"\r\n        (input)=\"attributeValueChanged(attrib.rules.attribName, $event.target.value);\">\r\n\r\n      <select *ngIf=\"attrib.rules.typ === attribTypes.Enum\" value=\"{{attrib.value}}\"\r\n        (input)=\"attributeValueChanged(attrib.rules.attribName, $event.target.value);\">\r\n        <option *ngIf=\"attrib.rules.required === false\"></option>\r\n        <option *ngFor=\"let value of attrib.rules.fixedValues\">{{value}}</option>\r\n      </select>\r\n\r\n    </div>\r\n  </div>\r\n\r\n  <ng-template #noAttributes>\r\n    No attributes to edit for element <b>{{elementName}}</b>\r\n  </ng-template>\r\n\r\n</div>\r\n",
                        styles: [".sws-attribute-editor-toolbar input,.sws-attribute-editor-toolbar select{width:100%;border-radius:5px;background-color:transparent;padding:.6em 0 .4em;margin-bottom:.3em;border:.5px solid #eee}"]
                    }] }
        ];
        /** @nocollapse */
        XmlEditorAttributeEditorComponent.ctorParameters = function () {
            return [
                { type: AngularXmlEditorService }
            ];
        };
        XmlEditorAttributeEditorComponent.propDecorators = {
            editorContextId: [{ type: i0.Input, args: ['editorContextId',] }]
        };
        return XmlEditorAttributeEditorComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlEditorDebugComponent = /** @class */ (function () {
        function XmlEditorDebugComponent(editorService) {
            this.editorService = editorService;
        }
        Object.defineProperty(XmlEditorDebugComponent.prototype, "editorContextId", {
            set: /**
             * @param {?} value
             * @return {?}
             */ function (value) {
                var _this = this;
                if (!value) {
                    return;
                }
                this.editorContext = this.editorService.getEditorContext(value);
                this.actualCursorPosChangedSubscription = this.editorContext.debugService.actualCursorPosChanged$.subscribe(function (pos) {
                    _this.cursorPosInfo = pos.StartPos.getDebugDescription();
                });
                this.inputSelectionSubscription = this.editorContext.debugService.inputSelectionChanged$.subscribe(function (info) {
                    _this.inputSelection = info;
                });
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        XmlEditorDebugComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () { };
        /**
         * @return {?}
         */
        XmlEditorDebugComponent.prototype.ngOnDestroy = /**
         * @return {?}
         */
            function () {
                this.actualCursorPosChangedSubscription.unsubscribe();
                this.inputSelectionSubscription.unsubscribe();
            };
        XmlEditorDebugComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'axed-debug',
                        template: "<div class=\"sws-xml-editor-toolbar\">\r\n\r\n  <h3>Debugging</h3>\r\n\r\n  <div class=\"block\">\r\n    <label>Cursor: </label>\r\n    {{cursorPosInfo}}\r\n  </div>\r\n\r\n  <div class=\"block\">\r\n    <label>Selection set: </label>\r\n    {{inputSelection}}\r\n  </div>\r\n\r\n</div>",
                        styles: [".sws-xml-editor-toolbar{min-height:50px;font:100 .8rem/15px Roboto,Arial,sans-serif;background-color:#f5f5f5;padding:15px;border:1px solid #ddd}.sws-xml-editor-toolbar .block{background-color:transparent;min-width:2rem;border:solid #ddd;padding-bottom:1em}.sws-xml-editor-toolbar label{font-weight:700}"]
                    }] }
        ];
        /** @nocollapse */
        XmlEditorDebugComponent.ctorParameters = function () {
            return [
                { type: AngularXmlEditorService }
            ];
        };
        XmlEditorDebugComponent.propDecorators = {
            editorContextId: [{ type: i0.Input, args: ['editorContextId',] }]
        };
        return XmlEditorDebugComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var DomBreakcrumbComponent = /** @class */ (function () {
        function DomBreakcrumbComponent() {
            this.nodes = [];
        }
        /**
         * @return {?}
         */
        DomBreakcrumbComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () { };
        /**
         * @param {?} selection
         * @return {?}
         */
        DomBreakcrumbComponent.prototype.showSelection = /**
         * @param {?} selection
         * @return {?}
         */
            function (selection) {
                if (selection === undefined) {
                    this.nodes = ['none'];
                }
                else {
                    /** @type {?} */
                    var collectNodes = [];
                    /** @type {?} */
                    var node = selection.focusNode;
                    /** @type {?} */
                    var reachedTop = node === undefined || node === null;
                    while (!reachedTop) {
                        switch (node.nodeType) {
                            case Node.ELEMENT_NODE: // element node
                                /** @type {?} */
                                var asElement = /** @type {?} */ (node);
                                if (asElement !== undefined) {
                                    /** @type {?} */
                                    var name_1 = asElement.getAttribute('data-tagname');
                                    if (asElement.className === 'sws-xml-editor-textarea') {
                                        reachedTop = true;
                                    }
                                    else {
                                        collectNodes.unshift(name_1);
                                    }
                                }
                        }
                        node = node.parentElement;
                        if (node === undefined || node == null) {
                            reachedTop = true;
                        }
                    }
                    this.nodes = collectNodes;
                }
            };
        DomBreakcrumbComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'axed-dom-breakcrumb',
                        template: "<ul>\r\n  <li *ngFor=\"let element of nodes\">\r\n    {{ element }}\r\n  </li>\r\n</ul>\r\n",
                        styles: ["ul{list-style-type:none;margin:0;padding:0}ul li{display:inline-block;zoom:1;padding-right:10px}ul li::before{content:'>';color:#d3d3d3}"]
                    }] }
        ];
        /** @nocollapse */
        DomBreakcrumbComponent.ctorParameters = function () { return []; };
        return DomBreakcrumbComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var AngularXmlEditorModule = /** @class */ (function () {
        function AngularXmlEditorModule() {
        }
        AngularXmlEditorModule.decorators = [
            { type: i0.NgModule, args: [{
                        imports: [i1.CommonModule, forms.FormsModule, forms.ReactiveFormsModule],
                        declarations: [AngularXmlEditorComponent, XmlEditorToolbarComponent, XmlEditorAttributeEditorComponent, XmlEditorDebugComponent, DomBreakcrumbComponent],
                        exports: [AngularXmlEditorComponent, XmlEditorToolbarComponent, XmlEditorAttributeEditorComponent, XmlEditorDebugComponent, DomBreakcrumbComponent]
                    },] }
        ];
        return AngularXmlEditorModule;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlSchema = /** @class */ (function () {
        function XmlSchema(xsdNodes) {
            this.xsdNodes = xsdNodes;
        }
        /**
         * @param {?} tagName
         * @return {?}
         */
        XmlSchema.prototype.findXsdNodeForTagName = /**
         * @param {?} tagName
         * @return {?}
         */
            function (tagName) {
                return this.xsdNodes.get(tagName);
            };
        return XmlSchema;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlSchemaLoader = /** @class */ (function () {
        function XmlSchemaLoader(schemaContent) {
            var _this = this;
            if (!schemaContent || schemaContent === '') {
                return;
            }
            /** @type {?} */
            var domparser = new DOMParser();
            /** @type {?} */
            var schemaDom = domparser.parseFromString(schemaContent, 'text/xml');
            /** @type {?} */
            var result = [];
            /** @type {?} */
            var rawElementsAtRoot = /** @type {?} */ (Array.from(schemaDom.documentElement.childNodes));
            rawElementsAtRoot.forEach(function (e) {
                /** @type {?} */
                var subChilds = _this.getRawElements(e);
                result = result.concat(subChilds);
            });
            this.xmlSchema = new XmlSchema(this.getXsdNodes(/** @type {?} */ (result)));
        }
        /**
         * @param {?} node
         * @return {?}
         */
        XmlSchemaLoader.prototype.getRawElements = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                var _this = this;
                /** @type {?} */
                var result = [];
                if (this.isValidXsdNode(node)) {
                    result = result.concat(node);
                }
                /** @type {?} */
                var children = /** @type {?} */ (Array.from(node.childNodes));
                children.forEach(function (child) {
                    result = result.concat(_this.getRawElements(child));
                });
                return result;
            };
        /**
         * @param {?} node
         * @return {?}
         */
        XmlSchemaLoader.prototype.isValidXsdNode = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                /** @type {?} */
                var allowedXsdTypes = ['element', 'group', 'complexType'];
                /** @type {?} */
                var asElem = /** @type {?} */ (node);
                if (asElem) {
                    if (allowedXsdTypes.includes(asElem.localName)) {
                        if (asElem.attributes.getNamedItem('name')) {
                            // console.warn(asElem.attributes.getNamedItem('name').value);
                            return true;
                        }
                        else {
                            return false;
                        }
                    }
                    else {
                        return false;
                    }
                }
                else {
                    return false;
                }
            };
        /**
         * @param {?} rawElements
         * @return {?}
         */
        XmlSchemaLoader.prototype.getXsdNodes = /**
         * @param {?} rawElements
         * @return {?}
         */
            function (rawElements) {
                // console.warn(rawElements.length);
                return new Map(rawElements.map(function (n) { return [n.attributes.getNamedItem('name').value, /** @type {?} */ (n)]; }));
            };
        return XmlSchemaLoader;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlRules = /** @class */ (function () {
        function XmlRules(ruleElements) {
            this.ruleElements = ruleElements;
        }
        return XmlRules;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var XmlRulesCreator = /** @class */ (function () {
        function XmlRulesCreator(schema, _floatingElementNames) {
            this.schema = schema;
            this._floatingElementNames = _floatingElementNames;
            this.rules = new XmlRules(this.getAllElementRuleNodes(Array.from(this.schema.xsdNodes.values())));
        }
        /**
         * @param {?} node
         * @return {?}
         */
        XmlRulesCreator.prototype.findXsdNodeForHtmlNode = /**
         * @param {?} node
         * @return {?}
         */
            function (node) {
                /** @type {?} */
                var tagName = Xml2html.getTagNameFromNode(node);
                return this.schema.xsdNodes.get(tagName);
            };
        /**
         * @param {?} xsdNodes
         * @return {?}
         */
        XmlRulesCreator.prototype.getAllElementRuleNodes = /**
         * @param {?} xsdNodes
         * @return {?}
         */
            function (xsdNodes) {
                var _this = this;
                return new Map(xsdNodes.map(function (xsdNode) { return [xsdNode.attributes.getNamedItem('name').value, _this.getRuleElementForXsdNode(xsdNode)]; }));
            };
        /**
         * @param {?} xsdNode
         * @return {?}
         */
        XmlRulesCreator.prototype.getRuleElementForXsdNode = /**
         * @param {?} xsdNode
         * @return {?}
         */
            function (xsdNode) {
                if (xsdNode) {
                    /** @type {?} */
                    var tagName = xsdNode.attributes.getNamedItem('name').value;
                    return new XmlRuleElement({
                        tagName: tagName,
                        floating: this.isFloating(tagName),
                        empty: this.isEmpty(xsdNode)
                    });
                }
                else {
                    return undefined;
                }
            };
        /**
         * @param {?} xsdNode
         * @return {?}
         */
        XmlRulesCreator.prototype.isEmpty = /**
         * @param {?} xsdNode
         * @return {?}
         */
            function (xsdNode) {
                if (new XmlEditRuleCheckTextInsert(this.schema.xsdNodes).isTextAllowedInThisElement(xsdNode) === true) {
                    return false;
                }
                return true;
            };
        /**
         * @param {?} tagName
         * @return {?}
         */
        XmlRulesCreator.prototype.isFloating = /**
         * @param {?} tagName
         * @return {?}
         */
            function (tagName) {
                return this._floatingElementNames.includes(tagName);
            };
        return XmlRulesCreator;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */

    exports.AngularXmlEditorService = AngularXmlEditorService;
    exports.AngularXmlEditorComponent = AngularXmlEditorComponent;
    exports.AngularXmlEditorModule = AngularXmlEditorModule;
    exports.XmlSchemaLoader = XmlSchemaLoader;
    exports.XmlRulesCreator = XmlRulesCreator;
    exports.XmlEditorContext = XmlEditorContext;
    exports.ɵe = XmlSchema;
    exports.ɵd = DomBreakcrumbComponent;
    exports.ɵb = XmlEditorAttributeEditorComponent;
    exports.ɵc = XmlEditorDebugComponent;
    exports.ɵa = XmlEditorToolbarComponent;

    Object.defineProperty(exports, '__esModule', { value: true });

})));

//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci14bWwtZWRpdG9yLnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb2RlL3htbEVkaXRvckRlYnVnZ2VyLnRzIiwibmc6Ly9hbmd1bGFyLXhtbC1lZGl0b3IvbGliL2NvZGUveG1sVG9vbGJveC5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb2RlL3htbC1odG1sLWNvbnZlcnRlci94bWwyaHRtbEF0dHJpYnV0ZVdvcmtlci5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb2RlL3htbC1odG1sLWNvbnZlcnRlci94bWwyaHRtbC5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb2RlL2R1bW15Tm9kZXMvZG9tRHVtbXlOb2RlTWFuYWdlci5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb2RlL2N1cnNvci94bWxDdXJzb3JQb3MuY2xhc3MudHMiLCJuZzovL2FuZ3VsYXIteG1sLWVkaXRvci9saWIvY29kZS9jdXJzb3IveG1sQ3Vyc29yUG9zTW92ZXIuY2xhc3MudHMiLCJuZzovL2FuZ3VsYXIteG1sLWVkaXRvci9saWIvY29kZS9jdXJzb3IveG1sQ3Vyc29yLmNsYXNzLnRzIiwibmc6Ly9hbmd1bGFyLXhtbC1lZGl0b3IvbGliL2NvZGUvY3Vyc29yL3htbEN1cnNvclBvc1NldHRlci5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb2RlL3htbC1lZGl0aW5nL3htbERvbUNsZWFuZXIuY2xhc3MudHMiLCJuZzovL2FuZ3VsYXIteG1sLWVkaXRvci9saWIvY29kZS94bWwtZWRpdGluZy94bWxFZGl0RGVsZXRlY2xhc3MudHMiLCJuZzovL2FuZ3VsYXIteG1sLWVkaXRvci9saWIvY29kZS94bWwtcnVsZXMtY2hlY2sveG1sRWRpdFJ1bGVDaGVja1RleHRJbnNlcnQuY2xhc3MudHMiLCJuZzovL2FuZ3VsYXIteG1sLWVkaXRvci9saWIvY29kZS94bWwtZWRpdGluZy94bWxFZGl0SW5zZXJ0LmNsYXNzLnRzIiwibmc6Ly9hbmd1bGFyLXhtbC1lZGl0b3IvbGliL2NvZGUveG1sRWRpdG9yQ29udGV4dC5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9hbmd1bGFyLXhtbC1lZGl0b3Iuc2VydmljZS50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb2RlL3htbC1odG1sLWNvbnZlcnRlci9odG1sMnhtbC5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9hbmd1bGFyLXhtbC1lZGl0b3IuY29tcG9uZW50LnRzIiwibmc6Ly9hbmd1bGFyLXhtbC1lZGl0b3IvbGliL2NvZGUveG1sLXJ1bGVzLWNoZWNrL3htbFJ1bGVFbGVtZW50LmNsYXNzLnRzIiwibmc6Ly9hbmd1bGFyLXhtbC1lZGl0b3IvbGliL2NvZGUveG1sLXJ1bGVzLWNoZWNrL3htbEVkaXRSdWxlQ2hlY2tFbGVtZW50cy5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb21wb25lbnRzL3htbC1lZGl0b3ItdG9vbGJhci94bWwtZWRpdG9yLXRvb2xiYXIuY29tcG9uZW50LnRzIiwibmc6Ly9hbmd1bGFyLXhtbC1lZGl0b3IvbGliL2NvZGUveG1sLXJ1bGVzLWNoZWNrL3htbFJ1bGVBdHRyaWJ1dC5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb2RlL3htbC1ydWxlcy1jaGVjay94bWxFZGl0UnVsZUNoZWNrQXR0cmlidXRlcy5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb21wb25lbnRzL3htbC1lZGl0b3ItYXR0cmlidXRlLWVkaXRvci94bWwtZWRpdG9yLWF0dHJpYnV0ZS1lZGl0b3IuY29tcG9uZW50LnRzIiwibmc6Ly9hbmd1bGFyLXhtbC1lZGl0b3IvbGliL2NvbXBvbmVudHMveG1sLWVkaXRvci1kZWJ1Zy94bWwtZWRpdG9yLWRlYnVnLmNvbXBvbmVudC50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb21wb25lbnRzL2RvbS1icmVha2NydW1iL2RvbS1icmVha2NydW1iLmNvbXBvbmVudC50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9hbmd1bGFyLXhtbC1lZGl0b3IubW9kdWxlLnRzIiwibmc6Ly9hbmd1bGFyLXhtbC1lZGl0b3IvbGliL2NvZGUveG1sLXJ1bGVzLWNoZWNrL3htbFNjaGVtYS5jbGFzcy50cyIsIm5nOi8vYW5ndWxhci14bWwtZWRpdG9yL2xpYi9jb2RlL3htbC1ydWxlcy1jaGVjay9YbWxTY2hlbWFMb2FkZXIuY2xhc3MudHMiLCJuZzovL2FuZ3VsYXIteG1sLWVkaXRvci9saWIvY29kZS94bWwtcnVsZXMtY2hlY2sveG1sUnVsZXMuY2xhc3MudHMiLCJuZzovL2FuZ3VsYXIteG1sLWVkaXRvci9saWIvY29kZS94bWwtcnVsZXMtY2hlY2sveG1sUnVsZXNDcmVhdG9yLmNsYXNzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IFhtbEN1cnNvciB9IGZyb20gJy4vY3Vyc29yL3htbEN1cnNvci5jbGFzcyc7XHJcblxyXG4vLyBASW5qZWN0YWJsZSh7XHJcbi8vICAgcHJvdmlkZWRJbjogJ3Jvb3QnXHJcbi8vIH0pXHJcbmV4cG9ydCBjbGFzcyBYbWxFZGl0b3JEZWJ1Z2dlciBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XHJcbiAgcHVibGljIGFjdHVhbEN1cnNvclBvc0NoYW5nZWQkID0gbmV3IFN1YmplY3Q8WG1sQ3Vyc29yPigpO1xyXG4gIHB1YmxpYyBpbnB1dFNlbGVjdGlvbkNoYW5nZWQkID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xyXG5cclxuICBjb25zdHJ1Y3RvcigpIHt9XHJcblxyXG4gIHNldEFjdHVhbEN1cnNvclBvcyhwb3M6IFhtbEN1cnNvcikge1xyXG4gICAgdGhpcy5hY3R1YWxDdXJzb3JQb3NDaGFuZ2VkJC5uZXh0KHBvcyk7XHJcbiAgfVxyXG5cclxuICBzZXRJbnB1dFNlbGVjdGlvbihpbmZvOiBzdHJpbmcpIHtcclxuICAgIHRoaXMuaW5wdXRTZWxlY3Rpb25DaGFuZ2VkJC5uZXh0KGluZm8pO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmFjdHVhbEN1cnNvclBvc0NoYW5nZWQkLmNvbXBsZXRlKCk7XHJcbiAgICB0aGlzLmlucHV0U2VsZWN0aW9uQ2hhbmdlZCQuY29tcGxldGUoKTtcclxuICB9XHJcbn1cclxuIiwiZXhwb3J0IGNsYXNzIFhtbFRvb2xib3gge1xyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gSXN0IGRpZXNlciBOb2RlIGVpbiBhbHMgVGV4dCBiZWFyYmVpdGJhcmVyIE5vZGVcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm5vZGVcIj48L3BhcmFtPlxyXG4gIC8vLyA8cmV0dXJucz48L3JldHVybnM+XHJcbiAgcHVibGljIHN0YXRpYyBJc1RleHRPckNvbW1lbnROb2RlKG5vZGU6IE5vZGUpOiBib29sZWFuIHtcclxuICAgIHN3aXRjaCAobm9kZS5ub2RlVHlwZSkge1xyXG4gICAgICBjYXNlIE5vZGUuVEVYVF9OT0RFOiAvLyB0ZXh0IG5vZGVcclxuICAgICAgY2FzZSBOb2RlLkNPTU1FTlRfTk9ERTpcclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgICAvLyByZXR1cm4gKChub2RlLm5vZGVUeXBlID09PSBTeXN0ZW0uWG1sLlhtbFRleHQpIHx8IChub2RlLm5vZGVUeXBlID09PSBTeXN0ZW0uWG1sLlhtbENvbW1lbnQpKTtcclxuICB9XHJcblxyXG4gIC8vIEdldHMgdGhlIGluZm8gdG8gaWRlbnRpZnkgYSBub2RlIGZvciBleGNlcHRpb24gb3IgZGVidWcgcHVycG9zZXNcclxuICBwdWJsaWMgc3RhdGljIEdldE5vZGVEZWJ1Z0NvbnRleHQobm9kZTogTm9kZSk6IHN0cmluZyB7XHJcbiAgICBpZiAobm9kZSA9PT0gbnVsbCB8fCBub2RlID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmV0dXJuICdOVUxMJztcclxuICAgIH1cclxuXHJcbiAgICBpZiAobm9kZS5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcclxuICAgICAgaWYgKG5vZGUudGV4dENvbnRlbnQgPT09ICcgJyB8fCBub2RlLnRleHRDb250ZW50ID09PSBTdHJpbmcuZnJvbUNoYXJDb2RlKDE2MCkpIHtcclxuICAgICAgICByZXR1cm4gYFRleHRDb250ZW50IVBhcmVudD0ke1htbFRvb2xib3guR2V0Tm9kZURlYnVnQ29udGV4dChub2RlLnBhcmVudE5vZGUpfWA7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmV0dXJuIGBUZXh0Q29udGVudD0nJHtub2RlLnRleHRDb250ZW50fSdgO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgYXNFbGVtID0gbm9kZSBhcyBFbGVtZW50O1xyXG4gICAgaWYgKGFzRWxlbSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybiBgbG9jYWxOYW1lOiAke25vZGUubm9kZU5hbWV9LCBub2RlVHlwZToke25vZGUubm9kZVR5cGV9YDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiBhc0VsZW0ub3V0ZXJIVE1MO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBYbWxSdWxlcyB9IGZyb20gJy4uL3htbC1ydWxlcy1jaGVjay94bWxSdWxlcy5jbGFzcyc7XHJcblxyXG5leHBvcnQgY2xhc3MgWG1sMmh0bWxBdHRyaWJ1dGVXb3JrZXIge1xyXG4gIHB1YmxpYyBzdGF0aWMgRGF0YUF0dHJpYlByYWVmaXggPSAnZGF0YS1hdHRyaWJ1dGUtJztcclxuXHJcbiAgY29uc3RydWN0b3IocHVibGljIHJ1bGVzOiBYbWxSdWxlcykge31cclxuXHJcbiAgLyoqIHdyaXRlcyB0aGUgZ2l2ZW4gYXR0cmlidXRlcyB0byB0aGUgaHRtbCBub2RlIGluIGRhdGEtYXR0cmlidXRlLXN5bnRheCAqKi9cclxuICB3cml0ZUFsbFhtbEF0dHJpYnV0ZXNUb0h0bWwoeG1sRWxlbWVudDogRWxlbWVudCwgaHRtbEVsZW1lbnQ6IEVsZW1lbnQpIHtcclxuICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB4bWxFbGVtZW50LmF0dHJpYnV0ZXM7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubGVuZ3RoOyArK2kpIHtcclxuICAgICAgY29uc3QgYXR0ciA9IGF0dHJpYnV0ZXNbaV07XHJcbiAgICAgIHRoaXMud3JpdGVBdHRyaWJ1dGVUb0h0bWwoaHRtbEVsZW1lbnQsIGF0dHIubmFtZSwgYXR0ci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogd3JpdGVzIHRoZSBnaXZlbiBhdHRyaWJ1dGUgdmFsdWUgdG8gdGhlIGh0bWwgbm9kZSBpbiBkYXRhLWF0dHJpYnV0ZS1zeW50YXggKiovXHJcbiAgd3JpdGVBdHRyaWJ1dGVUb0h0bWwoaHRtbEVsZW1lbnQ6IEVsZW1lbnQsIGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICBjb25zdCBuYW1lID0gYCR7WG1sMmh0bWxBdHRyaWJ1dGVXb3JrZXIuRGF0YUF0dHJpYlByYWVmaXh9JHtrZXl9YDtcclxuICAgIGlmICh2YWx1ZSAmJiB2YWx1ZS5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGh0bWxFbGVtZW50LnNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBodG1sRWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnVwZGF0ZUF0dHJpYnV0ZXNEZXNjcmlwdGlvbkluSHRtbEVsZW1lbnQoaHRtbEVsZW1lbnQpO1xyXG4gIH1cclxuXHJcbiAgLyoqIHdyaXRlcyB0aGUgZ2l2ZW4gYXR0cmlidXRlIHZhbHVlIGZyb20gdGhlIGh0bWwgbm9kZSBkYXRhLWF0dHJpYnV0ZS1zeW50YXggKiovXHJcbiAgZ2V0QXR0cmlidXRlVmFsdWVGcm9tSHRtbChodG1sRWxlbWVudDogRWxlbWVudCwga2V5OiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgYXR0cmlidXRlcyA9IGh0bWxFbGVtZW50LmF0dHJpYnV0ZXM7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubGVuZ3RoOyArK2kpIHtcclxuICAgICAgaWYgKGF0dHJpYnV0ZXNbaV0ubmFtZSA9PT0gYCR7WG1sMmh0bWxBdHRyaWJ1dGVXb3JrZXIuRGF0YUF0dHJpYlByYWVmaXh9JHtrZXl9YCkge1xyXG4gICAgICAgIHJldHVybiBhdHRyaWJ1dGVzW2ldLnZhbHVlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gIH1cclxuXHJcbiAgLyoqIHdyaXRlcyB0aGUgZ2l2ZW4gYXR0cmlidXRlIHZhbHVlIHRvIHRoZSB4bWwgbm9kZSAoYW5kIGdldHMgaXQgZnJvbSB0aGUgaHRtbCBub2RlIGZyb20gZGF0YS1hdHRyaWJ1dGUtc3ludGF4KSAqKi9cclxuICB3cml0ZUFsbEh0bWxBdHRyaWJ1dGVzVG9YbWwoaHRtbEVsZW1lbnQ6IEVsZW1lbnQsIHhtbEVsZW1lbnQ6IEVsZW1lbnQpIHtcclxuICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBodG1sRWxlbWVudC5hdHRyaWJ1dGVzO1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhdHRyaWJ1dGVzLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgIGNvbnN0IGF0dHIgPSBhdHRyaWJ1dGVzW2ldO1xyXG4gICAgICBpZiAoYXR0ci5uYW1lLnN0YXJ0c1dpdGgoWG1sMmh0bWxBdHRyaWJ1dGVXb3JrZXIuRGF0YUF0dHJpYlByYWVmaXgpKSB7XHJcbiAgICAgICAgeG1sRWxlbWVudC5zZXRBdHRyaWJ1dGUoYXR0ci5uYW1lLnN1YnN0cihYbWwyaHRtbEF0dHJpYnV0ZVdvcmtlci5EYXRhQXR0cmliUHJhZWZpeC5sZW5ndGgpLCBhdHRyLnZhbHVlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIHVwZGF0ZXMgdGhlICdmb3IgaHVtYW4gZXllcycgb25seSBkZXNjcmlwdGlvbiBvZiB0aGUgYXR0cmlidXRlcyBpbnNpZGUgYSBodG1sIG5vZGUgKiovXHJcbiAgcHJpdmF0ZSB1cGRhdGVBdHRyaWJ1dGVzRGVzY3JpcHRpb25Jbkh0bWxFbGVtZW50KGh0bWxFbGVtZW50OiBFbGVtZW50KSB7XHJcbiAgICBjb25zdCBhdHRyaWJ1dGVzID0gaHRtbEVsZW1lbnQuYXR0cmlidXRlcztcclxuICAgIGxldCBhbGxBdHRyaWJ1dGVzID0gJyc7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubGVuZ3RoOyArK2kpIHtcclxuICAgICAgY29uc3QgYXR0ciA9IGF0dHJpYnV0ZXNbaV07XHJcbiAgICAgIGlmIChhdHRyLm5hbWUuc3RhcnRzV2l0aChYbWwyaHRtbEF0dHJpYnV0ZVdvcmtlci5EYXRhQXR0cmliUHJhZWZpeCkpIHtcclxuICAgICAgICBhbGxBdHRyaWJ1dGVzID0gYCR7YWxsQXR0cmlidXRlc30gJHthdHRyLm5hbWUuc3Vic3RyKFhtbDJodG1sQXR0cmlidXRlV29ya2VyLkRhdGFBdHRyaWJQcmFlZml4Lmxlbmd0aCl9PVwiJHthdHRyLnZhbHVlfVwiYDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKGFsbEF0dHJpYnV0ZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICBodG1sRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cmlidXRlcycsIGFsbEF0dHJpYnV0ZXMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaHRtbEVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdkYXRhLWF0dHJpYnV0ZXMnKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgWG1sUnVsZXMgfSBmcm9tICcuLi94bWwtcnVsZXMtY2hlY2sveG1sUnVsZXMuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWxUb29sYm94IH0gZnJvbSAnLi4veG1sVG9vbGJveC5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbDJodG1sQXR0cmlidXRlV29ya2VyIH0gZnJvbSAnLi94bWwyaHRtbEF0dHJpYnV0ZVdvcmtlci5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbFJ1bGVFbGVtZW50IH0gZnJvbSAnLi4veG1sLXJ1bGVzLWNoZWNrL3htbFJ1bGVFbGVtZW50LmNsYXNzJztcclxuXHJcbmV4cG9ydCBjbGFzcyBYbWwyaHRtbCB7XHJcbiAgcHJpdmF0ZSBzdGF0aWMgRGF0YVRhZ05hbWUgPSAnZGF0YS10YWduYW1lJztcclxuICBwdWJsaWMgc3RhdGljIE5vQ2xvc2luZ1RhZ0NsYXNzTmFtZSA9ICd4bWxUYWdOb0Nsb3NpbmcnO1xyXG4gIHB1YmxpYyBzdGF0aWMgRmxvYXRpbmdUYWdDbGFzc05hbWUgPSAnZmxvYXRpbmcnO1xyXG4gIHB1YmxpYyBzdGF0aWMgQ29tbWVudFRhZ0NsYXNzTmFtZSA9ICdjb21tZW50JztcclxuXHJcbiAgcHJpdmF0ZSBhdHRyaWJ1dGVXb3JrZXI6IFhtbDJodG1sQXR0cmlidXRlV29ya2VyO1xyXG5cclxuICBjb25zdHJ1Y3RvcihwdWJsaWMgcnVsZXM6IFhtbFJ1bGVzKSB7XHJcbiAgICB0aGlzLmF0dHJpYnV0ZVdvcmtlciA9IG5ldyBYbWwyaHRtbEF0dHJpYnV0ZVdvcmtlcihydWxlcyk7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgZ2V0VGFnTmFtZUZyb21Ob2RlKG5vZGU6IE5vZGUpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgZWxlbSA9IG5vZGUgYXMgRWxlbWVudDtcclxuICAgIGxldCBuYW1lID0gJyc7XHJcbiAgICBpZiAoZWxlbSkge1xyXG4gICAgICBuYW1lID0gZWxlbS5nZXRBdHRyaWJ1dGUoWG1sMmh0bWwuRGF0YVRhZ05hbWUpO1xyXG4gICAgfVxyXG4gICAgaWYgKG5hbWUgPT09IHVuZGVmaW5lZCB8fCBuYW1lID09PSBudWxsIHx8IG5hbWUgPT09ICcnKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgbm9kZSBoYXMgbm8gRGF0YVRhZ05hbWUgYXR0cmlidXRlICR7WG1sVG9vbGJveC5HZXROb2RlRGVidWdDb250ZXh0KG5vZGUpfWApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5hbWU7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgaXNGbG9hdGluZ0VsZW1lbnQobm9kZTogTm9kZSk6IGJvb2xlYW4ge1xyXG4gICAgY29uc3QgZWxlbSA9IG5vZGUgYXMgRWxlbWVudDtcclxuICAgIGlmIChlbGVtICYmIGVsZW0uY2xhc3NMaXN0KSB7XHJcbiAgICAgIHJldHVybiBlbGVtLmNsYXNzTGlzdC5jb250YWlucyhYbWwyaHRtbC5GbG9hdGluZ1RhZ0NsYXNzTmFtZSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgaXNOb0Nsb3NpbmdFbGVtZW50KG5vZGU6IE5vZGUpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IGVsZW0gPSBub2RlIGFzIEVsZW1lbnQ7XHJcbiAgICBpZiAoZWxlbSAmJiBlbGVtLmNsYXNzTGlzdCkge1xyXG4gICAgICByZXR1cm4gZWxlbS5jbGFzc0xpc3QuY29udGFpbnMoWG1sMmh0bWwuTm9DbG9zaW5nVGFnQ2xhc3NOYW1lKTtcclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBUb0h0bWwoeG1sOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgaWYgKHhtbCA9PT0gJycgfHwgeG1sID09PSB1bmRlZmluZWQgfHwgeG1sID09PSBudWxsKSB7XHJcbiAgICAgIHJldHVybiAnJztcclxuICAgIH1cclxuXHJcbiAgICAvLyBhbGVydCh4bWwpO1xyXG5cclxuICAgIC8vIHJlbW92ZSBuZXdsaW5lIC8gY2FycmlhZ2UgcmV0dXJuXHJcbiAgICB4bWwgPSB4bWwucmVwbGFjZSgvXFxuL2csICcnKTtcclxuICAgIHhtbCA9IHhtbC5yZXBsYWNlKC9cXHIvZywgJycpO1xyXG4gICAgLy8gcmVtb3ZlIHdoaXRlc3BhY2UgKHRhYnMpIGJlZm9yZSB0YWdzXHJcbiAgICB4bWwgPSB4bWwucmVwbGFjZSgvW1xcdF0rXFw8L2csICc8Jyk7XHJcbiAgICAvLyByZW1vdmUgd2hpdGVzcGFjZSBiZXR3ZWVuIHRhZ3NcclxuICAgIHhtbCA9IHhtbC5yZXBsYWNlKC9cXD5bXFx0XStcXDwvZywgJz48Jyk7XHJcbiAgICAvLyByZW1vdmUgd2hpdGVzcGFjZSBhZnRlciB0YWdzXHJcbiAgICB4bWwgPSB4bWwucmVwbGFjZSgvXFw+W1xcdF0rJC9nLCAnPicpO1xyXG5cclxuICAgIGNvbnN0IGRvbXBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcclxuICAgIGNvbnN0IGRvbWRvYyA9IGRvbXBhcnNlci5wYXJzZUZyb21TdHJpbmcoeG1sLCAndGV4dC94bWwnKTtcclxuXHJcbiAgICBjb25zdCB0YXJnZXREb2N1bWVudCA9IG5ldyBEb2N1bWVudCgpO1xyXG5cclxuICAgIGlmIChkb21kb2MuZG9jdW1lbnRFbGVtZW50ID09PSBudWxsKSB7XHJcbiAgICAgIHJldHVybiAnJztcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBib2R5ID0gdGhpcy5HZXRIdG1sRWxlbWVudEZyb21YbWxFbGVtZW50KGRvbWRvYy5kb2N1bWVudEVsZW1lbnQsIHRhcmdldERvY3VtZW50KTtcclxuICAgIGlmIChib2R5ICYmIGJvZHkubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XHJcbiAgICAgIGNvbnN0IGh0bWwgPSAoYm9keSBhcyBFbGVtZW50KS5vdXRlckhUTUw7XHJcbiAgICAgIHJldHVybiBodG1sO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGByb290IG5vZGUgJHtYbWxUb29sYm94LkdldE5vZGVEZWJ1Z0NvbnRleHQoYm9keSl9IGlzIG5vIGVsZW1lbnRgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNyZWF0ZU5ld0VsZW1lbnRIdG1sKHJ1bGVFbGVtOiBYbWxSdWxlRWxlbWVudCk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBlbGVtID0gdGhpcy5jcmVhdGVOZXdFbGVtZW50QnlOYW1lKHJ1bGVFbGVtLnRhZ05hbWUpO1xyXG4gICAgcmV0dXJuIGVsZW0ub3V0ZXJIVE1MO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGNyZWF0ZU5ld0VsZW1lbnRCeU5hbWUodGFnTmFtZTogc3RyaW5nKTogRWxlbWVudCB7XHJcbiAgICBjb25zdCB0ZW1wRG9jID0gbmV3IERvY3VtZW50KCk7XHJcbiAgICBjb25zdCBuZXdFbGVtZW50ID0gdGVtcERvYy5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICAgIC8vIGZsb2F0aW5nIGVsZW1lbnQgb3Igbm90P1xyXG4gICAgY29uc3QgcnVsZSA9IHRoaXMucnVsZXMucnVsZUVsZW1lbnRzLmdldCh0YWdOYW1lKTtcclxuICAgIGlmIChydWxlICYmIHJ1bGUuZmxvYXRpbmcgPT09IHRydWUpIHtcclxuICAgICAgbmV3RWxlbWVudC5jbGFzc0xpc3QuYWRkKFhtbDJodG1sLkZsb2F0aW5nVGFnQ2xhc3NOYW1lKTtcclxuICAgIH1cclxuICAgIC8vIHZpc3VhbGl6ZSBjbG9zaW5nIHRhZyBvciBub3Q/XHJcbiAgICBpZiAocnVsZSAmJiBydWxlLmVtcHR5ID09PSB0cnVlKSB7XHJcbiAgICAgIG5ld0VsZW1lbnQuY2xhc3NMaXN0LmFkZChYbWwyaHRtbC5Ob0Nsb3NpbmdUYWdDbGFzc05hbWUpO1xyXG4gICAgfVxyXG4gICAgbmV3RWxlbWVudC5zZXRBdHRyaWJ1dGUoWG1sMmh0bWwuRGF0YVRhZ05hbWUsIHRhZ05hbWUpO1xyXG4gICAgcmV0dXJuIG5ld0VsZW1lbnQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIEdldEh0bWxFbGVtZW50RnJvbVhtbEVsZW1lbnQobm9kZTogTm9kZSwgdGFyZ2V0RG9jdW1lbnQ6IERvY3VtZW50KTogTm9kZSB7XHJcbiAgICBzd2l0Y2ggKG5vZGUubm9kZVR5cGUpIHtcclxuICAgICAgY2FzZSBOb2RlLkVMRU1FTlRfTk9ERTogLy8gZWxlbWVudCBub2RlXHJcbiAgICAgICAgY29uc3QgYXNFbGVtZW50ID0gbm9kZSBhcyBFbGVtZW50O1xyXG4gICAgICAgIGNvbnN0IG5vZGVOYW1lID0gYXNFbGVtZW50Lm5vZGVOYW1lO1xyXG5cclxuICAgICAgICAvLyBjcmVhdGUgZWxlbWVudCBub2RlXHJcbiAgICAgICAgbGV0IG5ld0VsZW1lbnQgPSB0YXJnZXREb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuXHJcbiAgICAgICAgLy8gZmxvYXRpbmcgZWxlbWVudCBvciBub3Q/XHJcbiAgICAgICAgY29uc3QgcnVsZSA9IHRoaXMucnVsZXMucnVsZUVsZW1lbnRzLmdldChub2RlTmFtZSk7XHJcbiAgICAgICAgaWYgKHJ1bGUgJiYgcnVsZS5mbG9hdGluZykge1xyXG4gICAgICAgICAgbmV3RWxlbWVudC5jbGFzc0xpc3QuYWRkKFhtbDJodG1sLkZsb2F0aW5nVGFnQ2xhc3NOYW1lKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gdmlzdWFsaXplIGNsb3NpbmcgdGFnIG9yIG5vdD9cclxuICAgICAgICBpZiAocnVsZSAmJiBydWxlLmVtcHR5KSB7XHJcbiAgICAgICAgICBuZXdFbGVtZW50LmNsYXNzTGlzdC5hZGQoWG1sMmh0bWwuTm9DbG9zaW5nVGFnQ2xhc3NOYW1lKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgbmV3RWxlbWVudC5zZXRBdHRyaWJ1dGUoWG1sMmh0bWwuRGF0YVRhZ05hbWUsIG5vZGVOYW1lKTtcclxuXHJcbiAgICAgICAgLy8gYXBwZW5kIGNoaWxkIGVsZW1lbnRzIHJlY3Vyc2l2ZVxyXG4gICAgICAgIGNvbnN0IGNoaWxkcmVuID0gYXNFbGVtZW50LmNoaWxkTm9kZXM7XHJcbiAgICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgbmV3RWxlbWVudC5hcHBlbmRDaGlsZCh0YXJnZXREb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJykpOyAvLyB0byBwcmV2ZW50IG5vbiBjbG9zaW5nIHRhZ3NcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7ICsraSkge1xyXG4gICAgICAgICAgICBjb25zdCBjaGlsZEFzSHRtbCA9IHRoaXMuR2V0SHRtbEVsZW1lbnRGcm9tWG1sRWxlbWVudChjaGlsZHJlbltpXSwgdGFyZ2V0RG9jdW1lbnQpO1xyXG4gICAgICAgICAgICBpZiAoY2hpbGRBc0h0bWwgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgIG5ld0VsZW1lbnQuYXBwZW5kQ2hpbGQoY2hpbGRBc0h0bWwpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBpbnNlcnQgYXR0cmlidXRlc1xyXG4gICAgICAgIHRoaXMuYXR0cmlidXRlV29ya2VyLndyaXRlQWxsWG1sQXR0cmlidXRlc1RvSHRtbChhc0VsZW1lbnQsIG5ld0VsZW1lbnQpO1xyXG5cclxuICAgICAgICByZXR1cm4gbmV3RWxlbWVudDtcclxuXHJcbiAgICAgIGNhc2UgTm9kZS5URVhUX05PREU6IC8vIHRleHQgbm9kZVxyXG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSAobm9kZSBhcyBFbGVtZW50KS50ZXh0Q29udGVudDtcclxuICAgICAgICBpZiAoY29udGVudC5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0RG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY29udGVudCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgY2FzZSBOb2RlLkNPTU1FTlRfTk9ERTpcclxuICAgICAgICAvLyBjcmVhdGUgZWxlbWVudCBub2RlXHJcbiAgICAgICAgbmV3RWxlbWVudCA9IHRhcmdldERvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG4gICAgICAgIG5ld0VsZW1lbnQuY2xhc3NMaXN0LmFkZChYbWwyaHRtbC5Db21tZW50VGFnQ2xhc3NOYW1lKTtcclxuICAgICAgICBuZXdFbGVtZW50LnNldEF0dHJpYnV0ZShYbWwyaHRtbC5EYXRhVGFnTmFtZSwgJ2NvbW1lbnQnKTtcclxuICAgICAgICBuZXdFbGVtZW50LnRleHRDb250ZW50ID0gKG5vZGUgYXMgRWxlbWVudCkudGV4dENvbnRlbnQ7XHJcbiAgICAgICAgcmV0dXJuIG5ld0VsZW1lbnQ7XHJcblxyXG4gICAgICAvKiB5ZXQgbm90IGltcGxlbWVudGVkIHR5cGVzICovXHJcbiAgICAgIGNhc2UgTm9kZS5QUk9DRVNTSU5HX0lOU1RSVUNUSU9OX05PREU6XHJcbiAgICAgICAgY29uc29sZS53YXJuKGBub2RlVHlwZSBcIlBST0NFU1NJTkdfSU5TVFJVQ1RJT05fTk9ERVwiICR7WG1sVG9vbGJveC5HZXROb2RlRGVidWdDb250ZXh0KG5vZGUpfSBub3QgaW1wbGVtZW50ZWQgeWV0YCk7XHJcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuXHJcbiAgICAgIGNhc2UgTm9kZS5ET0NVTUVOVF9OT0RFOlxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm9kZVR5cGUgXCJOb2RlLkRPQ1VNRU5UX05PREVcIiAke1htbFRvb2xib3guR2V0Tm9kZURlYnVnQ29udGV4dChub2RlKX0gbm90IGltcGxlbWVudGVkIHlldGApO1xyXG4gICAgICBjYXNlIE5vZGUuRE9DVU1FTlRfVFlQRV9OT0RFOlxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm9kZVR5cGUgXCJOb2RlLkRPQ1VNRU5UX05PREVcIiAke1htbFRvb2xib3guR2V0Tm9kZURlYnVnQ29udGV4dChub2RlKX0gbm90IGltcGxlbWVudGVkIHlldGApO1xyXG4gICAgICBjYXNlIE5vZGUuRE9DVU1FTlRfRlJBR01FTlRfTk9ERTpcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vZGVUeXBlIFwiTm9kZS5ET0NVTUVOVF9GUkFHTUVOVF9OT0RFXCIgJHtYbWxUb29sYm94LkdldE5vZGVEZWJ1Z0NvbnRleHQobm9kZSl9IG5vdCBpbXBsZW1lbnRlZCB5ZXRgKTtcclxuXHJcbiAgICAgIC8qIERlcHJlYWNoZWQgbm9kZSB0eXBlcyAqL1xyXG4gICAgICBjYXNlIE5vZGUuQVRUUklCVVRFX05PREU6XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub2RlVHlwZSBcIk5vZGUuQVRUUklCVVRFX05PREVcIiAke1htbFRvb2xib3guR2V0Tm9kZURlYnVnQ29udGV4dChub2RlKX0gaXMgZGVwcmVhY2hlZGApO1xyXG4gICAgICBjYXNlIE5vZGUuQ0RBVEFfU0VDVElPTl9OT0RFOlxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm9kZVR5cGUgXCJOb2RlLkNEQVRBX1NFQ1RJT05fTk9ERVwiICR7WG1sVG9vbGJveC5HZXROb2RlRGVidWdDb250ZXh0KG5vZGUpfSBpcyBkZXByZWFjaGVkYCk7XHJcbiAgICAgIGNhc2UgTm9kZS5FTlRJVFlfUkVGRVJFTkNFX05PREU6XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub2RlVHlwZSBcIk5vZGUuRU5USVRZX1JFRkVSRU5DRV9OT0RFXCIgJHtYbWxUb29sYm94LkdldE5vZGVEZWJ1Z0NvbnRleHQobm9kZSl9IGlzIGRlcHJlYWNoZWRgKTtcclxuICAgICAgY2FzZSBOb2RlLkVOVElUWV9OT0RFOlxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm9kZVR5cGUgXCJOb2RlLkVOVElUWV9OT0RFXCIgJHtYbWxUb29sYm94LkdldE5vZGVEZWJ1Z0NvbnRleHQobm9kZSl9IGlzIGRlcHJlYWNoZWRgKTtcclxuICAgICAgY2FzZSBOb2RlLk5PVEFUSU9OX05PREU6XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub2RlVHlwZSBcIk5vZGUuTk9UQVRJT05fTk9ERVwiICR7WG1sVG9vbGJveC5HZXROb2RlRGVidWdDb250ZXh0KG5vZGUpfSBpcyBkZXByZWFjaGVkYCk7XHJcblxyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTptYXgtbGluZS1sZW5ndGhcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24geG1sRWxlbWVudCBub2RlVHlwZSAke25vZGUubm9kZVR5cGV9IGluIHZhbHVlOiAke1htbFRvb2xib3guR2V0Tm9kZURlYnVnQ29udGV4dChub2RlKX1gKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgWG1sMmh0bWwgfSBmcm9tICcuLi94bWwtaHRtbC1jb252ZXJ0ZXIveG1sMmh0bWwuY2xhc3MnO1xyXG5cclxuZXhwb3J0IGNsYXNzIERvbUR1bW15Tm9kZU1hbmFnZXIge1xyXG4gIHB1YmxpYyBzdGF0aWMgRHVtbXlOb2RlQ2xhc3NOYW1lID0gJ2R1bW15Tm9kZSc7XHJcbiAgcHVibGljIHN0YXRpYyBEdW1teU5vZGVCZWZvcmVGaXJzdFRhZ0NsYXNzTmFtZSA9ICdiZWZvcmVmaXJzdFRhZyc7XHJcbiAgcHVibGljIHN0YXRpYyBEdW1teU5vZGVDb250ZW50ID0gU3RyaW5nLmZyb21DaGFyQ29kZSgxNjApO1xyXG5cclxuICBjb25zdHJ1Y3RvcigpIHt9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgSXNEdW1teU5vZGUobm9kZTogTm9kZSkge1xyXG4gICAgY29uc3QgYXNFbGVtID0gbm9kZSBhcyBFbGVtZW50O1xyXG4gICAgaWYgKGFzRWxlbSAmJiBub2RlLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xyXG4gICAgICByZXR1cm4gYXNFbGVtLmNsYXNzTGlzdC5jb250YWlucyhEb21EdW1teU5vZGVNYW5hZ2VyLkR1bW15Tm9kZUNsYXNzTmFtZSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIElzQmVmb3JlRmlyc3RUYWdEdW1teU5vZGUobm9kZTogTm9kZSkge1xyXG4gICAgaWYgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUobm9kZSkpIHtcclxuICAgICAgY29uc3QgYXNFbGVtID0gbm9kZSBhcyBFbGVtZW50O1xyXG4gICAgICBpZiAoYXNFbGVtICYmIG5vZGUubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XHJcbiAgICAgICAgcmV0dXJuIGFzRWxlbS5jbGFzc0xpc3QuY29udGFpbnMoRG9tRHVtbXlOb2RlTWFuYWdlci5EdW1teU5vZGVCZWZvcmVGaXJzdFRhZ0NsYXNzTmFtZSk7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gZ2V0IHByZXZpb3Mgc2libGluZyAtIGV4Y2VwdCBkdW1teSBub2Rlc1xyXG4gIHB1YmxpYyBzdGF0aWMgZ2V0UHJldmlvdXNTaWJsaW5nKG5vZGU6IE5vZGUpOiBOb2RlIHtcclxuICAgIGlmICghbm9kZSkge1xyXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG4gICAgd2hpbGUgKG5vZGUpIHtcclxuICAgICAgbm9kZSA9IG5vZGUucHJldmlvdXNTaWJsaW5nO1xyXG4gICAgICBpZiAobm9kZSkge1xyXG4gICAgICAgIGlmIChEb21EdW1teU5vZGVNYW5hZ2VyLklzRHVtbXlOb2RlKG5vZGUpKSB7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHJldHVybiBub2RlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIC8vIGdldCBuZXh0IHNpYmxpbmcgLSBleGNlcHQgZHVtbXkgbm9kZXNcclxuICBwdWJsaWMgc3RhdGljIGdldE5leHRTaWJsaW5nKG5vZGU6IE5vZGUpOiBOb2RlIHtcclxuICAgIGlmICghbm9kZSkge1xyXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG4gICAgd2hpbGUgKG5vZGUpIHtcclxuICAgICAgbm9kZSA9IG5vZGUubmV4dFNpYmxpbmc7XHJcbiAgICAgIGlmIChub2RlKSB7XHJcbiAgICAgICAgaWYgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUobm9kZSkpIHtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgcmV0dXJuIG5vZGU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gIH1cclxuXHJcbiAgLy8gZ2V0IGNoaWxkcmVuIGNvdW50IC0gZXhjZXB0IGR1bW15IG5vZGVzXHJcbiAgcHVibGljIHN0YXRpYyBnZXRDaGlsZE5vZGVDb3VudChub2RlOiBOb2RlKTogbnVtYmVyIHtcclxuICAgIGlmICghbm9kZSkge1xyXG4gICAgICByZXR1cm4gMDtcclxuICAgIH1cclxuICAgIGxldCBjb3VudCA9IDA7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAoIURvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUobm9kZS5jaGlsZE5vZGVzW2ldKSkge1xyXG4gICAgICAgIGNvdW50Kys7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBjb3VudDtcclxuICB9XHJcblxyXG4gIC8vIGdldCBmaXJzdCBjaGlsZCAtIGV4Y2VwdCBkdW1teSBub2Rlc1xyXG4gIHB1YmxpYyBzdGF0aWMgZ2V0Rmlyc3RDaGlsZChub2RlOiBOb2RlKTogTm9kZSB7XHJcbiAgICBpZiAoIW5vZGUpIHtcclxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgIH1cclxuICAgIGxldCBmaXJzdCA9IG5vZGUuZmlyc3RDaGlsZCBhcyBOb2RlO1xyXG4gICAgd2hpbGUgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUoZmlyc3QpKSB7XHJcbiAgICAgIGZpcnN0ID0gZmlyc3QubmV4dFNpYmxpbmc7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmlyc3Q7XHJcbiAgfVxyXG5cclxuICAvLyBnZXQgbGFzdCBjaGlsZCAtIGV4Y2VwdCBkdW1teSBub2Rlc1xyXG4gIHB1YmxpYyBzdGF0aWMgZ2V0TGFzdENoaWxkKG5vZGU6IE5vZGUpOiBOb2RlIHtcclxuICAgIGlmICghbm9kZSkge1xyXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG4gICAgbGV0IGxhc3QgPSBub2RlLmxhc3RDaGlsZCBhcyBOb2RlO1xyXG4gICAgd2hpbGUgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUobGFzdCkpIHtcclxuICAgICAgbGFzdCA9IGxhc3QucHJldmlvdXNTaWJsaW5nO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGxhc3Q7XHJcbiAgfVxyXG5cclxuICBSZW1vdmVBbGxEdW1teU5vZGVzKG5vZGU6IE5vZGUsIG5vZGVEZXB0aCA9IDApOiB2b2lkIHtcclxuICAgIGxldCBjaGlsZHJlbjogTm9kZVtdID0gW107XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7ICsraSkge1xyXG4gICAgICBjaGlsZHJlbi5wdXNoKG5vZGUuY2hpbGROb2Rlc1tpXSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZGVsZXRlIGFsbCBkdW1teSBub2RlIGNoaWxkcmVuXHJcbiAgICBjaGlsZHJlbi5mb3JFYWNoKGNoaWxkID0+IHtcclxuICAgICAgaWYgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUoY2hpbGQpKSB7XHJcbiAgICAgICAgbm9kZS5yZW1vdmVDaGlsZChjaGlsZCk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIGNoaWxkcmVuID0gW107XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7ICsraSkge1xyXG4gICAgICBjaGlsZHJlbi5wdXNoKG5vZGUuY2hpbGROb2Rlc1tpXSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gdXBkYXRlIGNoaWxkIG5vZGVzXHJcbiAgICBjaGlsZHJlbi5mb3JFYWNoKGNoaWxkID0+IHtcclxuICAgICAgdGhpcy5SZW1vdmVBbGxEdW1teU5vZGVzKGNoaWxkLCBub2RlRGVwdGggKyAxKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgVXBkYXRlRHVtbXlOb2Rlcyhub2RlOiBOb2RlLCBub2RlRGVwdGggPSAwKSB7XHJcbiAgICBjb25zdCBkb2N1bWVudCA9IG5vZGUub3duZXJEb2N1bWVudDtcclxuICAgIGNvbnN0IGFzRWxlbWVudCA9IG5vZGUgYXMgRWxlbWVudDtcclxuXHJcbiAgICBjb25zdCBjaGlsZHJlbjogTm9kZVtdID0gW107XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7ICsraSkge1xyXG4gICAgICBjaGlsZHJlbi5wdXNoKG5vZGUuY2hpbGROb2Rlc1tpXSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGFzRWxlbWVudCAmJiAhRG9tRHVtbXlOb2RlTWFuYWdlci5Jc0R1bW15Tm9kZShhc0VsZW1lbnQpICYmICFEb21EdW1teU5vZGVNYW5hZ2VyLklzRHVtbXlOb2RlKGFzRWxlbWVudC5wYXJlbnRFbGVtZW50KSkge1xyXG4gICAgICBpZiAoYXNFbGVtZW50Lm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xyXG4gICAgICAgIGNvbnN0IGJlZm9yZSA9IGFzRWxlbWVudC5wcmV2aW91c1NpYmxpbmc7XHJcbiAgICAgICAgaWYgKGJlZm9yZS5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcclxuICAgICAgICAgIC8vIHRleHRub2RlIGFmdGVyIHRleHQgbm9kZTogZG9udCBpbnNlcnQgZHVtbXkgbm9kZSFcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgaWYgKCFEb21EdW1teU5vZGVNYW5hZ2VyLklzRHVtbXlOb2RlKGJlZm9yZSkpIHtcclxuICAgICAgICAgICAgYXNFbGVtZW50LnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMuY3JlYXRlRHVtbXlOb2RlKGRvY3VtZW50KSwgYXNFbGVtZW50KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChhc0VsZW1lbnQubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XHJcbiAgICAgICAgbGV0IGZpcnN0Q2hpbGQgPSBub2RlLmZpcnN0Q2hpbGQ7XHJcbiAgICAgICAgaWYgKCFmaXJzdENoaWxkKSB7XHJcbiAgICAgICAgICAvLyBjcmVhdGUgZHVtbXkgbm9kZSBpbiBlbXB0eSB0YWdcclxuICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQodGhpcy5jcmVhdGVEdW1teU5vZGUoZG9jdW1lbnQpKTtcclxuICAgICAgICAgIGZpcnN0Q2hpbGQgPSBub2RlLmZpcnN0Q2hpbGQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoWG1sMmh0bWwuaXNOb0Nsb3NpbmdFbGVtZW50KG5vZGUpKSB7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGZpcnN0Q2hpbGQgPSBub2RlLmZpcnN0Q2hpbGQ7XHJcblxyXG4gICAgICAgICAgaWYgKCFmaXJzdENoaWxkKSB7XHJcbiAgICAgICAgICAgIC8vIGNyZWF0ZSBkdW1teSBub2RlIGluIGVtcHR5IHRhZ1xyXG4gICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKHRoaXMuY3JlYXRlRHVtbXlOb2RlKGRvY3VtZW50KSk7XHJcbiAgICAgICAgICAgIGZpcnN0Q2hpbGQgPSBub2RlLmZpcnN0Q2hpbGQ7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gSW5zZXJ0IGEgZHVtbXkgbm9kZSBiZWZvcmUgdGhlIGZpcnN0IGNoaWxkXHJcbiAgICAgICAgICBpZiAoIURvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUoZmlyc3RDaGlsZCkpIHtcclxuICAgICAgICAgICAgaWYgKGZpcnN0Q2hpbGQpIHtcclxuICAgICAgICAgICAgICBub2RlLmluc2VydEJlZm9yZSh0aGlzLmNyZWF0ZUR1bW15Tm9kZShkb2N1bWVudCksIGZpcnN0Q2hpbGQpO1xyXG4gICAgICAgICAgICAgIGZpcnN0Q2hpbGQgPSBub2RlLmZpcnN0Q2hpbGQ7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZCh0aGlzLmNyZWF0ZUR1bW15Tm9kZShkb2N1bWVudCkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gSW5zZXJ0IGEgZHVtbXkgbm9kZSBhZnRlciB0aGUgbGFzdCBjaGlsZFxyXG4gICAgICAgICAgbGV0IGxhc3RDaGlsZCA9IG5vZGUubGFzdENoaWxkO1xyXG4gICAgICAgICAgaWYgKCFEb21EdW1teU5vZGVNYW5hZ2VyLklzRHVtbXlOb2RlKGxhc3RDaGlsZCkpIHtcclxuICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZCh0aGlzLmNyZWF0ZUR1bW15Tm9kZShkb2N1bWVudCkpO1xyXG4gICAgICAgICAgICBsYXN0Q2hpbGQgPSBub2RlLmxhc3RDaGlsZDtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAvLyBJbnNlcnQgYSBkdW1teSBub2RlIGJlZm9yZSB0aGUgZmlyc3QgKGR1bW15IGNoaWxkKSBidXQgb3B0aWNhbCBpbiBmcm9udCBvZiB0aGUgbm9kZSAodG8gc2hvdyB0aGUgY3Vyc29yIGluIGZyb250IG9mIHRoZSBub2RlKVxyXG4gICAgICAgICAgaWYgKG5vZGVEZXB0aCA+IDApIHtcclxuICAgICAgICAgICAgaWYgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUoZmlyc3RDaGlsZCkgJiYgIURvbUR1bW15Tm9kZU1hbmFnZXIuSXNCZWZvcmVGaXJzdFRhZ0R1bW15Tm9kZShmaXJzdENoaWxkKSkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGR1bW15Tm9kZSA9IHRoaXMuY3JlYXRlRHVtbXlOb2RlKGRvY3VtZW50KTtcclxuICAgICAgICAgICAgICBkdW1teU5vZGUuY2xhc3NMaXN0LmFkZChEb21EdW1teU5vZGVNYW5hZ2VyLkR1bW15Tm9kZUJlZm9yZUZpcnN0VGFnQ2xhc3NOYW1lKTtcclxuICAgICAgICAgICAgICBhc0VsZW1lbnQuaW5zZXJ0QmVmb3JlKGR1bW15Tm9kZSwgZmlyc3RDaGlsZCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyB1cGRhdGUgY2hpbGQgbm9kZXNcclxuICAgIGNoaWxkcmVuLmZvckVhY2goY2hpbGQgPT4ge1xyXG4gICAgICB0aGlzLlVwZGF0ZUR1bW15Tm9kZXMoY2hpbGQsIG5vZGVEZXB0aCArIDEpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY3JlYXRlRHVtbXlOb2RlKHRhcmdldERvY3VtZW50OiBEb2N1bWVudCwgY29udGVudD86IHN0cmluZyk6IEVsZW1lbnQge1xyXG4gICAgY29uc3QgZHVtbXlOb2RlID0gdGFyZ2V0RG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xyXG4gICAgbGV0IGR1bW15MlRleHROb2RlO1xyXG4gICAgaWYgKGNvbnRlbnQgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBkdW1teTJUZXh0Tm9kZSA9IHRhcmdldERvY3VtZW50LmNyZWF0ZVRleHROb2RlKERvbUR1bW15Tm9kZU1hbmFnZXIuRHVtbXlOb2RlQ29udGVudCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBkdW1teTJUZXh0Tm9kZSA9IHRhcmdldERvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNvbnRlbnQpO1xyXG4gICAgfVxyXG4gICAgZHVtbXlOb2RlLmNsYXNzTGlzdC5hZGQoRG9tRHVtbXlOb2RlTWFuYWdlci5EdW1teU5vZGVDbGFzc05hbWUpO1xyXG4gICAgZHVtbXlOb2RlLmFwcGVuZENoaWxkKGR1bW15MlRleHROb2RlKTtcclxuICAgIHJldHVybiBkdW1teU5vZGU7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IFhtbFRvb2xib3ggfSBmcm9tICcuLi94bWxUb29sYm94LmNsYXNzJztcclxuaW1wb3J0IHsgU2VsZWN0aW9uUG9zIH0gZnJvbSAnLi94bWxDdXJzb3IuY2xhc3MnO1xyXG5pbXBvcnQgeyBEb21EdW1teU5vZGVNYW5hZ2VyIH0gZnJvbSAnLi4vZHVtbXlOb2Rlcy9kb21EdW1teU5vZGVNYW5hZ2VyLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sMmh0bWwgfSBmcm9tICcuLi94bWwtaHRtbC1jb252ZXJ0ZXIveG1sMmh0bWwuY2xhc3MnO1xyXG5cclxuZXhwb3J0IGNsYXNzIFhtbEN1cnNvclBvcyB7XHJcbiAgcHVibGljIEFjdHVhbE5vZGU6IE5vZGU7IC8vIHRoaXMgWE1MTm9kZSBhY3R1YWwgaGFzIHRoZSBlZGl0b3IgZm9jdXNcclxuICBwdWJsaWMgUG9zQXROb2RlOiBYTUxDdXJzb3JQb3NpdGlvbnM7IC8vIEF0IHRoaXMgcG9zaXRpb24gdGhlIGN1cnNvciBpcyAtIGluc2lkZSBvZGVyIG91dHNpZGUgdGhlIGFjdHVhbCBmb2N1c3NlZCBub2RlXHJcbiAgcHVibGljIFBvc0luVGV4dG5vZGU6IG51bWJlcjsgLy8gVGhlIGN1cnNvciBwb3NpdGlvIGluc2lkZSBmbG9hdGluZyB0ZXh0IHdoZW4gcG9zICBpcyBDdXJzb3JJbm5lcmhhbGJEZXNUZXh0Tm9kZXNcclxuXHJcbiAgc3RhdGljIGdldFhtbEN1cnNvclBvc2l0aW9uRGVidWdOYW1lKHBvc2l0aW9uOiBYTUxDdXJzb3JQb3NpdGlvbnMpOiBzdHJpbmcge1xyXG4gICAgc3dpdGNoIChwb3NpdGlvbikge1xyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JPbkNvbXBsZXRlTm9kZTpcclxuICAgICAgICByZXR1cm4gJ0N1cnNvck9uQ29tcGxldGVOb2RlJztcclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yQmVoaW5kTm9kZTpcclxuICAgICAgICByZXR1cm4gJ0N1cnNvckJlaGluZE5vZGUnO1xyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkVtcHR5Tm9kZTpcclxuICAgICAgICByZXR1cm4gJ0N1cnNvckluRW1wdHlOb2RlJztcclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5zaWRlVGV4dE5vZGU6XHJcbiAgICAgICAgcmV0dXJuICdDdXJzb3JJbnNpZGVUZXh0Tm9kZSc7XHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGU6XHJcbiAgICAgICAgcmV0dXJuICdDdXJzb3JJbkZyb250T2ZOb2RlJztcclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICByZXR1cm4gYHVua25vd24gY3Vyc29yUG9zICR7cG9zaXRpb259YDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHN0YXRpYyBnZXRTZWxlY3Rpb25Gb3JQb3MocG9zOiBYbWxDdXJzb3JQb3MpOiBTZWxlY3Rpb25Qb3Mge1xyXG4gICAgaWYgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUocG9zLkFjdHVhbE5vZGUpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgWG1sQ3Vyc29yUG9zLmdldFNlbGVjdGlvbkZvclBvczogcG9zLkFrdE5vZGUgJHtwb3MuZ2V0RGVidWdEZXNjcmlwdGlvbigpfSBpcyBhIGR1bW15IG5vZGUhYCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUocG9zLkFjdHVhbE5vZGUucGFyZW50RWxlbWVudCkpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBYbWxDdXJzb3JQb3MuZ2V0U2VsZWN0aW9uRm9yUG9zOiBwb3MuQWt0Tm9kZS5wYXJlbnRFbGVtZW50ICR7cG9zLmdldERlYnVnRGVzY3JpcHRpb24oKX0gaXMgYSBkdW1teSBub2RlIWApO1xyXG4gICAgfVxyXG5cclxuICAgIHN3aXRjaCAocG9zLlBvc0F0Tm9kZSkge1xyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JPbkNvbXBsZXRlTm9kZTogLy8gKDApXHJcbiAgICAgICAgbGV0IGZpcnN0Q2hpbGQgPSBwb3MuQWN0dWFsTm9kZS5maXJzdENoaWxkO1xyXG4gICAgICAgIGlmIChEb21EdW1teU5vZGVNYW5hZ2VyLklzQmVmb3JlRmlyc3RUYWdEdW1teU5vZGUoZmlyc3RDaGlsZCkpIHtcclxuICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIG5vZGU6IGZpcnN0Q2hpbGQuZmlyc3RDaGlsZCwgLy8gdGV4dCBpbnNpZGUgQmVmb3JlRmlyc3RUYWdEdW1teU5vZFxyXG4gICAgICAgICAgICBvZmZzZXQ6IDBcclxuICAgICAgICAgIH07XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIG5vZGU6IHBvcy5BY3R1YWxOb2RlLFxyXG4gICAgICAgICAgICBvZmZzZXQ6IDBcclxuICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5Gcm9udE9mTm9kZTogLy8gKDEpXHJcbiAgICAgICAgaWYgKHBvcy5BY3R1YWxOb2RlLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xyXG4gICAgICAgICAgLy8gdGV4dCBub2RlXHJcbiAgICAgICAgICBjb25zdCBkdW1teUJlZm9yZSA9IHBvcy5BY3R1YWxOb2RlLnByZXZpb3VzU2libGluZztcclxuICAgICAgICAgIGlmIChEb21EdW1teU5vZGVNYW5hZ2VyLklzRHVtbXlOb2RlKGR1bW15QmVmb3JlKSkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgIG5vZGU6IGR1bW15QmVmb3JlLmZpcnN0Q2hpbGQsIC8vIGJlZm9yZSB0ZXh0IG5vZGVcclxuICAgICAgICAgICAgICBvZmZzZXQ6IDFcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGUgKDEpOnRleHQgbm9kZTogaXMgbm8gZHVtbXkgbm9kZTogICcgKyBwb3MuZ2V0RGVidWdEZXNjcmlwdGlvbigpKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLy8gbm8gdGV4dCBub2RlXHJcbiAgICAgICAgICBmaXJzdENoaWxkID0gcG9zLkFjdHVhbE5vZGUuZmlyc3RDaGlsZDtcclxuICAgICAgICAgIGlmIChEb21EdW1teU5vZGVNYW5hZ2VyLklzQmVmb3JlRmlyc3RUYWdEdW1teU5vZGUoZmlyc3RDaGlsZCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICBub2RlOiBmaXJzdENoaWxkLmZpcnN0Q2hpbGQsIC8vIHRleHQgaW5zaWRlIEJlZm9yZUZpcnN0VGFnRHVtbXlOb2RcclxuICAgICAgICAgICAgICBvZmZzZXQ6IDFcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmIChYbWwyaHRtbC5pc05vQ2xvc2luZ0VsZW1lbnQocG9zLkFjdHVhbE5vZGUpICYmIERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUoZmlyc3RDaGlsZCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHsgbm9kZTogZmlyc3RDaGlsZC5maXJzdENoaWxkLCBvZmZzZXQ6IDEgfTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGUgKDEpOm5vIHRleHQgbm9kZTogZG9udCBrbm93IHdoYXQgdG8gZG8hICcpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckJlaGluZE5vZGU6IC8vICg3LCAxMSlcclxuICAgICAgICBjb25zdCBkdW1teUFmdGVyID0gcG9zLkFjdHVhbE5vZGUubmV4dFNpYmxpbmc7XHJcbiAgICAgICAgaWYgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUoZHVtbXlBZnRlcikpIHtcclxuICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIG5vZGU6IGR1bW15QWZ0ZXIuZmlyc3RDaGlsZCwgLy8gYmVmb3JlIHRleHQgbm9kZVxyXG4gICAgICAgICAgICBvZmZzZXQ6IDBcclxuICAgICAgICAgIH07XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgWE1MQ3Vyc29yUG9zaXRpb25lbi5DdXJzb3JCZWhpbmROb2RlIHNob3VsZCBvbmx5IGJlIHNldCwgd2hlbiB0aGUgZWxlbWVudCBoYXMgbm8gbmV4dCBzaWJsaW5nLmApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRW1wdHlOb2RlOlxyXG4gICAgICAgIGNvbnN0IGxhc3RDaGlsZCA9IHBvcy5BY3R1YWxOb2RlLmxhc3RDaGlsZDtcclxuICAgICAgICBpZiAoIURvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUoZmlyc3RDaGlsZCkgJiYgIURvbUR1bW15Tm9kZU1hbmFnZXIuSXNCZWZvcmVGaXJzdFRhZ0R1bW15Tm9kZShmaXJzdENoaWxkKSkge1xyXG4gICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgbm9kZTogbGFzdENoaWxkLmZpcnN0Q2hpbGQsIC8vIHRleHQgaW5zaWRlIER1bW15Tm9kZVxyXG4gICAgICAgICAgICBvZmZzZXQ6IDBcclxuICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5zaWRlVGV4dE5vZGU6XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgIG5vZGU6IHBvcy5BY3R1YWxOb2RlLFxyXG4gICAgICAgICAgb2Zmc2V0OiBwb3MuUG9zSW5UZXh0bm9kZVxyXG4gICAgICAgIH07XHJcbiAgICB9XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHNob3dDdXJzb3IuZ2V0U2VsZWN0aW9uRm9yUG9zIHVua25vd24gQ3Vyc29yUG9zICR7cG9zLmdldERlYnVnRGVzY3JpcHRpb24oKX1gKTtcclxuICB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKCkge1xyXG4gICAgdGhpcy5BY3R1YWxOb2RlID0gbnVsbDsgLy8gbm8gbm9kZSBzZWxlY3RlZFxyXG4gICAgdGhpcy5Qb3NBdE5vZGUgPSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yT25Db21wbGV0ZU5vZGU7XHJcbiAgICB0aGlzLlBvc0luVGV4dG5vZGUgPSAwO1xyXG4gIH1cclxuXHJcbiAgY2xvbmUoKTogWG1sQ3Vyc29yUG9zIHtcclxuICAgIGNvbnN0IGtsb24gPSBuZXcgWG1sQ3Vyc29yUG9zKCk7XHJcbiAgICBrbG9uLlNldEN1cnNvcih0aGlzLkFjdHVhbE5vZGUsIHRoaXMuUG9zQXROb2RlLCB0aGlzLlBvc0luVGV4dG5vZGUpO1xyXG4gICAgcmV0dXJuIGtsb247XHJcbiAgfVxyXG5cclxuICBlcXVhbHMob3RoZXJQb3M6IFhtbEN1cnNvclBvcyk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKCFvdGhlclBvcykge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgICBpZiAob3RoZXJQb3MuQWN0dWFsTm9kZSAhPT0gdGhpcy5BY3R1YWxOb2RlKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIGlmIChvdGhlclBvcy5Qb3NBdE5vZGUgIT09IHRoaXMuUG9zQXROb2RlKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLlBvc0F0Tm9kZSA9PT0gWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluc2lkZVRleHROb2RlICYmIHRoaXMuUG9zSW5UZXh0bm9kZSAhPT0gb3RoZXJQb3MuUG9zSW5UZXh0bm9kZSkge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIGdldERlYnVnRGVzY3JpcHRpb24oKTogc3RyaW5nIHtcclxuICAgIHJldHVybiBgbm9kZToke1htbFRvb2xib3guR2V0Tm9kZURlYnVnQ29udGV4dCh0aGlzLkFjdHVhbE5vZGUpfSwgcG9zOiR7WG1sQ3Vyc29yUG9zLmdldFhtbEN1cnNvclBvc2l0aW9uRGVidWdOYW1lKHRoaXMuUG9zQXROb2RlKX0sIHBvc0luVGV4dDoke3RoaXMuUG9zSW5UZXh0bm9kZX1gO1xyXG4gIH1cclxuXHJcbiAgU2V0Q3Vyc29yKGFjdHVhbE5vZGU6IE5vZGUsIHBvc0F0Tm9kZTogWE1MQ3Vyc29yUG9zaXRpb25zLCBwb3NJblRleHRub2RlOiBudW1iZXIgPSAwKSB7XHJcbiAgICBpZiAoIWFjdHVhbE5vZGUpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdhY3R1YWxOb2RlIGlzIG51bGwnKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgY2hhbmdlZDogYm9vbGVhbjtcclxuICAgIGlmIChhY3R1YWxOb2RlICE9PSB0aGlzLkFjdHVhbE5vZGUpIHtcclxuICAgICAgY2hhbmdlZCA9IHRydWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAocG9zQXROb2RlICE9PSB0aGlzLlBvc0F0Tm9kZSkge1xyXG4gICAgICAgIGNoYW5nZWQgPSB0cnVlO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGlmIChwb3NJblRleHRub2RlICE9PSB0aGlzLlBvc0luVGV4dG5vZGUpIHtcclxuICAgICAgICAgIGNoYW5nZWQgPSB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjaGFuZ2VkID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5BY3R1YWxOb2RlID0gYWN0dWFsTm9kZTtcclxuICAgIHRoaXMuUG9zQXROb2RlID0gcG9zQXROb2RlO1xyXG4gICAgdGhpcy5Qb3NJblRleHRub2RlID0gcG9zSW5UZXh0bm9kZTtcclxuXHJcbiAgICAvLyBjb25zb2xlLmxvZyhgU2V0Q3Vyc29yOiAke3RoaXMuZ2V0RGVidWdEZXNjcmlwdGlvbigpfWApO1xyXG5cclxuICAgIGlmIChjaGFuZ2VkKSB7XHJcbiAgICAgIC8vIFBvc0NoYW5nZWQoRXZlbnRBcmdzLkVtcHR5KTsgLy8gaW5mb3JtIHlvdSB0aGF0IHRoZSBjdXJzb3IgaGFzIG5vdyBiZWVuIGNoYW5nZWRcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHNldEN1cnNvckJlaGluZE5vZGVGb3JEZWZhdWx0T3JSaWdodE1vdmVtZW50KG5vZGU6IE5vZGUpIHtcclxuICAgIGNvbnN0IG5leHRTaWJsaW5nID0gRG9tRHVtbXlOb2RlTWFuYWdlci5nZXROZXh0U2libGluZyhub2RlKTtcclxuICAgIGlmIChuZXh0U2libGluZykge1xyXG4gICAgICB0aGlzLlNldEN1cnNvcihuZXh0U2libGluZywgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5TZXRDdXJzb3Iobm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckJlaGluZE5vZGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2V0Q3Vyc29ycEJlaGluZE5vZGVGb3JMZWZ0TW92ZW1lbnQobm9kZTogTm9kZSkge1xyXG4gICAgaWYgKFhtbFRvb2xib3guSXNUZXh0T3JDb21tZW50Tm9kZShub2RlKSkge1xyXG4gICAgICAvLyAgRm9yIGEgdGV4dCBub2RlLCB0aGUgY3Vyc29yIGlzIHBsYWNlZCBhZnRlciB0aGUgbGFzdCBjaGFyYWN0ZXIuXHJcbiAgICAgIHRoaXMuU2V0Q3Vyc29yKG5vZGUsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbnNpZGVUZXh0Tm9kZSwgTWF0aC5tYXgoMCwgbm9kZS50ZXh0Q29udGVudC5sZW5ndGggLSAxKSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25zdCBjaGlsZE5vZGVDb3VudCA9IERvbUR1bW15Tm9kZU1hbmFnZXIuZ2V0Q2hpbGROb2RlQ291bnQobm9kZSk7XHJcbiAgICAgIGlmIChjaGlsZE5vZGVDb3VudCA9PT0gMCkge1xyXG4gICAgICAgIC8vIFRoZXJlIGFyZSBubyBjaGlsZHJlbiBpbiB0aGUgbm9kZS5cclxuICAgICAgICBpZiAoIVhtbDJodG1sLmlzTm9DbG9zaW5nRWxlbWVudChub2RlKSkge1xyXG4gICAgICAgICAgLy8gSWYgdGhlIGN1cnNvciBzaG93cyBhIGNsb3NlIHRhZywgdGhlbiBwdXQgaXQgaW4gdGhlIGVtcHR5IG5vZGVcclxuICAgICAgICAgIHRoaXMuU2V0Q3Vyc29yKG5vZGUsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkVtcHR5Tm9kZSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIC8vIElmIHRoZSBjdXJzb3IgZG9lcyBub3QgZGlzcGxheSBhIGNsb3NlIHRhZywgdGhlbiBwbGFjZSBpdCBiZWZvcmUgdGhlIGVtcHR5IG5vZGUuXHJcbiAgICAgICAgICB0aGlzLlNldEN1cnNvcihub2RlLCBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5Gcm9udE9mTm9kZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIFRoZXJlIGFyZSBjaGlsZHJlbiBpbiBub2RlXHJcbiAgICAgICAgdGhpcy5TZXRDdXJzb3IoRG9tRHVtbXlOb2RlTWFuYWdlci5nZXRMYXN0Q2hpbGQobm9kZSksIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JCZWhpbmROb2RlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGVudW0gWE1MQ3Vyc29yUG9zaXRpb25zIHtcclxuICBDdXJzb3JJbkZyb250T2ZOb2RlID0gMCxcclxuICBDdXJzb3JPbkNvbXBsZXRlTm9kZSA9IDEsXHJcbiAgQ3Vyc29ySW5FbXB0eU5vZGUgPSAyLFxyXG4gIEN1cnNvckluc2lkZVRleHROb2RlID0gMyxcclxuICBDdXJzb3JCZWhpbmROb2RlID0gNFxyXG59XHJcbiIsImltcG9ydCB7IFhtbEN1cnNvclBvcywgWE1MQ3Vyc29yUG9zaXRpb25zIH0gZnJvbSAnLi94bWxDdXJzb3JQb3MuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWxSdWxlcyB9IGZyb20gJy4uL3htbC1ydWxlcy1jaGVjay94bWxSdWxlcy5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbFRvb2xib3ggfSBmcm9tICcuLi94bWxUb29sYm94LmNsYXNzJztcclxuaW1wb3J0IHsgRG9tRHVtbXlOb2RlTWFuYWdlciB9IGZyb20gJy4uL2R1bW15Tm9kZXMvZG9tRHVtbXlOb2RlTWFuYWdlci5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbDJodG1sIH0gZnJvbSAnLi4veG1sLWh0bWwtY29udmVydGVyL3htbDJodG1sLmNsYXNzJztcclxuXHJcbmV4cG9ydCBjbGFzcyBYbWxDdXJzb3JQb3NNb3ZlciB7XHJcbiAgcHVibGljIHN0YXRpYyBtb3ZlTGVmdChwb3M6IFhtbEN1cnNvclBvcywgcm9vdE5vZGU6IEVsZW1lbnQsIHhtbFJ1bGVzOiBYbWxSdWxlcyk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHBvcyA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBzd2l0Y2ggKHBvcy5Qb3NBdE5vZGUpIHtcclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yT25Db21wbGV0ZU5vZGU6XHJcbiAgICAgICAgLy8gUHV0IGluIGZyb250IG9mIHRoZSBub2RlXHJcbiAgICAgICAgcG9zLlNldEN1cnNvcihwb3MuQWN0dWFsTm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGUpO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5Gcm9udE9mTm9kZTpcclxuICAgICAgICBpZiAocG9zLkFjdHVhbE5vZGUgPT09IHJvb3ROb2RlKSB7XHJcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnN0IHByZXZpb3VzU2libGluZyA9IERvbUR1bW15Tm9kZU1hbmFnZXIuZ2V0UHJldmlvdXNTaWJsaW5nKHBvcy5BY3R1YWxOb2RlKTtcclxuICAgICAgICAgIGlmIChwcmV2aW91c1NpYmxpbmcpIHtcclxuICAgICAgICAgICAgLy8gUHJldmlvdXMgc2libGluZyBub2RlIGV4aXN0c1xyXG4gICAgICAgICAgICBwb3Muc2V0Q3Vyc29ycEJlaGluZE5vZGVGb3JMZWZ0TW92ZW1lbnQocHJldmlvdXNTaWJsaW5nKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIG5vIHByZXZpb3VzIHNpYmxpbmcgbm9kZSBhdmFpbGFibGUgLT4gc2V0IGJlZm9yZSBwYXJlbnQgbm9kZVxyXG4gICAgICAgICAgICBwb3MuU2V0Q3Vyc29yKHBvcy5BY3R1YWxOb2RlLnBhcmVudE5vZGUsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkZyb250T2ZOb2RlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JCZWhpbmROb2RlOlxyXG4gICAgICAgIHBvcy5zZXRDdXJzb3JwQmVoaW5kTm9kZUZvckxlZnRNb3ZlbWVudChwb3MuQWN0dWFsTm9kZSk7XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkVtcHR5Tm9kZTpcclxuICAgICAgICAvLyBQdXQgaW4gZnJvbnQgb2YgdGhlIG5vZGVcclxuICAgICAgICBwb3MuU2V0Q3Vyc29yKHBvcy5BY3R1YWxOb2RlLCBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5Gcm9udE9mTm9kZSk7XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbnNpZGVUZXh0Tm9kZTpcclxuICAgICAgICBpZiAoWG1sVG9vbGJveC5Jc1RleHRPckNvbW1lbnROb2RlKHBvcy5BY3R1YWxOb2RlKSkge1xyXG4gICAgICAgICAgLy8gTm9kZSBpcyBUZXh0bm9kZVxyXG4gICAgICAgICAgaWYgKHBvcy5Qb3NJblRleHRub2RlID4gMSkge1xyXG4gICAgICAgICAgICAvLyBDdXJzb3Igb25lIGNoYXJhY3RlciB0byB0aGUgbGVmdFxyXG4gICAgICAgICAgICBwb3MuU2V0Q3Vyc29yKHBvcy5BY3R1YWxOb2RlLCBwb3MuUG9zQXROb2RlLCBwb3MuUG9zSW5UZXh0bm9kZSAtIDEpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gUHV0IGluIGZyb250IG9mIHRoZSBub2RlXHJcbiAgICAgICAgICAgIHBvcy5TZXRDdXJzb3IocG9zLkFjdHVhbE5vZGUsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkZyb250T2ZOb2RlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLy8gbm8gVGV4dG5vZGVcclxuICAgICAgICAgIGNvbnN0IGVsZW10ID0gcG9zLkFjdHVhbE5vZGUgYXMgRWxlbWVudDtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgWE1MQ3Vyc29yUG9zLk1vdmVMZWZ0OiBDdXJzb3JQb3MgaXMgWE1MQ3Vyc29yUG9zaXRpb25lbi5DdXJzb3JJbm5lcmhhbGJEZXNUZXh0Tm9kZXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dCBubyB0ZXh0IG5vZGUgaGFzIGJlZW4gY2hvc2VuLCBidXQgdGhlIG5vZGUgJHtlbGVtdCA/IGVsZW10Lm91dGVySFRNTCA6ICcnfWApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBYTUxDdXJzb3JQb3MuTW92ZUxlZnQ6IHVua25vd24gQ3Vyc29yUG9zICR7cG9zLlBvc0F0Tm9kZX1gKTtcclxuICAgIH1cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHN0YXRpYyBtb3ZlUmlnaHQocG9zOiBYbWxDdXJzb3JQb3MsIHJvb3ROb2RlOiBFbGVtZW50LCB4bWxSdWxlczogWG1sUnVsZXMpOiBib29sZWFuIHtcclxuICAgIGlmIChwb3MgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgc3dpdGNoIChwb3MuUG9zQXROb2RlKSB7XHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvck9uQ29tcGxldGVOb2RlOlxyXG4gICAgICAgIC8vIEhpbnRlciBkZW4gTm9kZSBzZXR6ZW5cclxuICAgICAgICBjb25zdCB0YWdOYW1lID0gWG1sMmh0bWwuZ2V0VGFnTmFtZUZyb21Ob2RlKHBvcy5BY3R1YWxOb2RlKTtcclxuICAgICAgICBjb25zdCBydWxlID0geG1sUnVsZXMucnVsZUVsZW1lbnRzLmdldCh0YWdOYW1lKTtcclxuICAgICAgICBpZiAocnVsZSAmJiBydWxlLmVtcHR5ID09PSB0cnVlKSB7XHJcbiAgICAgICAgICBwb3Muc2V0Q3Vyc29yQmVoaW5kTm9kZUZvckRlZmF1bHRPclJpZ2h0TW92ZW1lbnQocG9zLkFjdHVhbE5vZGUpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zdCBmaXJzdENoaWxkID0gRG9tRHVtbXlOb2RlTWFuYWdlci5nZXRGaXJzdENoaWxkKHBvcy5BY3R1YWxOb2RlKTtcclxuICAgICAgICAgIGlmIChmaXJzdENoaWxkKSB7XHJcbiAgICAgICAgICAgIHBvcy5TZXRDdXJzb3IoZmlyc3RDaGlsZCwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGUpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcG9zLlNldEN1cnNvcihwb3MuQWN0dWFsTm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRW1wdHlOb2RlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JCZWhpbmROb2RlOlxyXG4gICAgICAgIGNvbnN0IG5leHRTaWJsaW5nID0gRG9tRHVtbXlOb2RlTWFuYWdlci5nZXROZXh0U2libGluZyhwb3MuQWN0dWFsTm9kZSk7XHJcbiAgICAgICAgaWYgKG5leHRTaWJsaW5nKSB7XHJcbiAgICAgICAgICAvLyBjdXJzb3IgYmVoaW5kIG5vZGUgc2hvdWxkIG9ubHkgYmUgc2V0LCB3aGVuIG5vIG90aGVyIHNpYmxpbmdzIGFyZSBmb2xsb3dpbmdcclxuICAgICAgICAgIGNvbnN0IGVsZW10ID0gcG9zLkFjdHVhbE5vZGUgYXMgRWxlbWVudDtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgWE1MQ3Vyc29yUG9zLk1vdmVSaWdodDogY3Vyc29yIGJlaGluZCBub2RlIHNob3VsZCBvbmx5IGJlIHNldCwgd2hlbiBubyBvdGhlciBzaWJsaW5ncyBhcmUgZm9sbG93aW5nICR7ZWxlbXQgPyBlbGVtdC5vdXRlckhUTUwgOiAnJ31gKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLy8gTm8gZm9sbG93aW5nIHNpYmxpbmdzIHByZXNlbnQsIHRoZW4gc2V0IGFmdGVyIHBhcmVudCBub2RlXHJcbiAgICAgICAgICBjb25zdCBwYXJlbnROZXh0U2libGluZyA9IERvbUR1bW15Tm9kZU1hbmFnZXIuZ2V0TmV4dFNpYmxpbmcocG9zLkFjdHVhbE5vZGUucGFyZW50RWxlbWVudCk7XHJcbiAgICAgICAgICBpZiAocGFyZW50TmV4dFNpYmxpbmcpIHtcclxuICAgICAgICAgICAgcG9zLlNldEN1cnNvcihwYXJlbnROZXh0U2libGluZywgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGUpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcG9zLlNldEN1cnNvcihwb3MuQWN0dWFsTm9kZS5wYXJlbnRFbGVtZW50LCBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yQmVoaW5kTm9kZSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5FbXB0eU5vZGU6XHJcbiAgICAgICAgLy8gUGxhY2UgYmVoaW5kIHRoZSBub2RlXHJcbiAgICAgICAgcG9zLnNldEN1cnNvckJlaGluZE5vZGVGb3JEZWZhdWx0T3JSaWdodE1vdmVtZW50KHBvcy5BY3R1YWxOb2RlKTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGU6XHJcbiAgICAgICAgaWYgKFhtbFRvb2xib3guSXNUZXh0T3JDb21tZW50Tm9kZShwb3MuQWN0dWFsTm9kZSkpIHtcclxuICAgICAgICAgIC8vIE5vZGUgaXMgVGV4dG5vZGVcclxuICAgICAgICAgIGlmICgocG9zLkFjdHVhbE5vZGUgYXMgRWxlbWVudCkudGV4dENvbnRlbnQubGVuZ3RoID4gMSkge1xyXG4gICAgICAgICAgICAvLyBUZXh0bm9kZSBpcyBub3QgZW1wdHlcclxuICAgICAgICAgICAgcG9zLlNldEN1cnNvcihwb3MuQWN0dWFsTm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluc2lkZVRleHROb2RlLCAxKTsgLy8gb25lIGNoYXJhY3RlciBmb3J3YXJkLCBiZWhpbmQgdGhlIGZpcnN0IGNoYXJhY3RlclxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gVGV4dG5vZGUgaXMgZW1wdHlcclxuICAgICAgICAgICAgLy8gcHV0IGJlaGluZCB0aGUgbm9kZVxyXG4gICAgICAgICAgICBwb3MuU2V0Q3Vyc29yKHBvcy5BY3R1YWxOb2RlLCBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yQmVoaW5kTm9kZSk7XHJcbiAgICAgICAgICAgIC8vIEJlY2F1c2UgXCJDdXJzb3JCZWhpbmROb2RlXCIgaXMgbm90IGF0dHJhY3RpdmUsIG9uZSBtb3JlIHN0ZXBcclxuICAgICAgICAgICAgdGhpcy5tb3ZlUmlnaHQocG9zLCByb290Tm9kZSwgeG1sUnVsZXMpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAvLyBOb2RlIGlzIG5vdCBUZXh0bm9kZVxyXG4gICAgICAgICAgY29uc3QgY2hpbGROb2RlQ291bnQgPSBEb21EdW1teU5vZGVNYW5hZ2VyLmdldENoaWxkTm9kZUNvdW50KHBvcy5BY3R1YWxOb2RlKTtcclxuICAgICAgICAgIGlmIChjaGlsZE5vZGVDb3VudCA9PT0gMCkge1xyXG4gICAgICAgICAgICAvLyBubyBDaGlsZHJlbiBleGlzdGluZ1xyXG4gICAgICAgICAgICBpZiAoWG1sMmh0bWwuaXNOb0Nsb3NpbmdFbGVtZW50KHBvcy5BY3R1YWxOb2RlKSkge1xyXG4gICAgICAgICAgICAgIC8vIElmIG5vIGNsb3NlZCB0YWcgaXMgZGlzcGxheWVkIGZvciB0aGlzIG5vZGUsIHRoZW4gZGlyZWN0bHkgYmVoaW5kIHRoZSBub2RlXHJcbiAgICAgICAgICAgICAgLy8gUGxhY2UgYmVoaW5kIHRoZSBub2RlXHJcbiAgICAgICAgICAgICAgcG9zLnNldEN1cnNvckJlaGluZE5vZGVGb3JEZWZhdWx0T3JSaWdodE1vdmVtZW50KHBvcy5BY3R1YWxOb2RlKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAvLyBOb2RlIGhhcyBjbG9zaW5nIHRhZywgc28gcHV0IGluIGJldHdlZW5cclxuICAgICAgICAgICAgICAvLyBQbGFjZSBpbiBlbXB0eSBub2RlXHJcbiAgICAgICAgICAgICAgcG9zLlNldEN1cnNvcihwb3MuQWN0dWFsTm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRW1wdHlOb2RlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gQ2hpbGRyZW4gZXhpc3RpbmdcclxuICAgICAgICAgICAgY29uc3QgZmlyc3RDaGlsZCA9IERvbUR1bW15Tm9kZU1hbmFnZXIuZ2V0Rmlyc3RDaGlsZChwb3MuQWN0dWFsTm9kZSk7XHJcbiAgICAgICAgICAgIHBvcy5TZXRDdXJzb3IoZmlyc3RDaGlsZCwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGUpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluc2lkZVRleHROb2RlOlxyXG4gICAgICAgIGlmIChYbWxUb29sYm94LklzVGV4dE9yQ29tbWVudE5vZGUocG9zLkFjdHVhbE5vZGUpKSB7XHJcbiAgICAgICAgICAvLyBOb2RlIGlzIFRleHRub2RlXHJcbiAgICAgICAgICBpZiAoKHBvcy5BY3R1YWxOb2RlIGFzIEVsZW1lbnQpLnRleHRDb250ZW50Lmxlbmd0aCA+IHBvcy5Qb3NJblRleHRub2RlICsgMSkge1xyXG4gICAgICAgICAgICAvLyB0aGVyZSBpcyBzdGlsbCB0ZXh0IGluIHRoZSByaWdodCBvZiB0aGUgdGV4dG5vZGVcclxuICAgICAgICAgICAgLy8gc3RlcCBvbmUgY2hhcmFjdGVyIGZvcndhcmRzOiBiZWhpbmQgdGhlIGZpcnN0IGNoYXJcclxuICAgICAgICAgICAgcG9zLlNldEN1cnNvcihwb3MuQWN0dWFsTm9kZSwgcG9zLlBvc0F0Tm9kZSwgcG9zLlBvc0luVGV4dG5vZGUgKyAxKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIG5vIHRleHQgYWZ0ZXIgdGhlIHRleHRub2RlXHJcbiAgICAgICAgICAgIC8vIHBsYWNlIGN1cnNvciBiZWhpbmQgdGhlIG5vZGVcclxuICAgICAgICAgICAgcG9zLnNldEN1cnNvckJlaGluZE5vZGVGb3JEZWZhdWx0T3JSaWdodE1vdmVtZW50KHBvcy5BY3R1YWxOb2RlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLy8gTm9kZSBpcyBubyBUZXh0bm9kZVxyXG4gICAgICAgICAgY29uc3QgZWxlbXQgPSBwb3MuQWN0dWFsTm9kZSBhcyBFbGVtZW50O1xyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBYTUxDdXJzb3JQb3MuTW92ZVJpZ2h0OiBDdXJzb3JQb3MgaXMgWE1MQ3Vyc29yUG9zaXRpb25lbi5DdXJzb3JJbm5lcmhhbGJEZXNUZXh0Tm9kZXMsIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBidXQgbm8gdGV4dCBub2RlIGhhcyBiZWVuIGNob3NlbiwgYnV0IHRoZSBub2RlICR7ZWxlbXQgPyBlbGVtdC5vdXRlckhUTUwgOiAnJ31gKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdHJpbmcuRm9ybWF0KFwiWE1MQ3Vyc29yUG9zLk1vdmVSaWdodDogdW5rbm93biBDdXJzb3JQb3MgJHtwb3MuUG9zQXROb2RlfWApO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBYbWxDdXJzb3JQb3MsIFhNTEN1cnNvclBvc2l0aW9ucyB9IGZyb20gJy4veG1sQ3Vyc29yUG9zLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sVG9vbGJveCB9IGZyb20gJy4uL3htbFRvb2xib3guY2xhc3MnO1xyXG5pbXBvcnQgeyBEb21EdW1teU5vZGVNYW5hZ2VyIH0gZnJvbSAnLi4vZHVtbXlOb2Rlcy9kb21EdW1teU5vZGVNYW5hZ2VyLmNsYXNzJztcclxuXHJcbmV4cG9ydCBjbGFzcyBYbWxDdXJzb3Ige1xyXG4gIHhtbERvY3VtZW50Um9vdE5vZGU6IEVsZW1lbnQgPSB1bmRlZmluZWQ7XHJcbiAgZG9tRHVtbXlOb2RlTWFuYWdlciA9IG5ldyBEb21EdW1teU5vZGVNYW5hZ2VyKCk7XHJcblxyXG4gIHB1YmxpYyBTdGFydFBvcyA9IG5ldyBYbWxDdXJzb3JQb3MoKTtcclxuICBwdWJsaWMgRW5kUG9zID0gbmV3IFhtbEN1cnNvclBvcygpO1xyXG5cclxuICAvKipcclxuICAgKiBpcyB0aGVyZSBub3RoaW5nIGJldHdlZW4gc3RhcnQgYW5kIGVuZCBwb3M/XHJcbiAgICovXHJcbiAgaXNFbXB0eVNlbGVjdGlvbigpOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLlN0YXJ0UG9zLmVxdWFscyh0aGlzLkVuZFBvcykpIHtcclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBzb3J0U3RhcnRBbmRFbmQoKSB7XHJcbiAgICBpZiAodGhpcy5TdGFydFBvcy5BY3R1YWxOb2RlICYmIHRoaXMuRW5kUG9zLkFjdHVhbE5vZGUpIHtcclxuICAgICAgaWYgKHRoaXMuU3RhcnRQb3MuQWN0dWFsTm9kZS5pc1NhbWVOb2RlKHRoaXMuRW5kUG9zLkFjdHVhbE5vZGUpKSB7XHJcbiAgICAgICAgaWYgKFxyXG4gICAgICAgICAgdGhpcy5TdGFydFBvcy5Qb3NBdE5vZGUgPT09IFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbnNpZGVUZXh0Tm9kZSAmJlxyXG4gICAgICAgICAgdGhpcy5FbmRQb3MuUG9zQXROb2RlID09PSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5zaWRlVGV4dE5vZGUgJiZcclxuICAgICAgICAgIHRoaXMuU3RhcnRQb3MuUG9zSW5UZXh0bm9kZSA+IHRoaXMuRW5kUG9zLlBvc0luVGV4dG5vZGVcclxuICAgICAgICApIHtcclxuICAgICAgICAgIHRoaXMuc3dhcFN0YXJ0QW5kRW5kKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNvbnN0IGNvbXBhcmVkID0gdGhpcy5TdGFydFBvcy5BY3R1YWxOb2RlLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKHRoaXMuRW5kUG9zLkFjdHVhbE5vZGUpO1xyXG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1iaXR3aXNlXHJcbiAgICAgICAgaWYgKCEoY29tcGFyZWQgJiBOb2RlLkRPQ1VNRU5UX1BPU0lUSU9OX0ZPTExPV0lORykpIHtcclxuICAgICAgICAgIHRoaXMuc3dhcFN0YXJ0QW5kRW5kKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzd2FwU3RhcnRBbmRFbmQoKSB7XHJcbiAgICBjb25zdCBub2RlID0gdGhpcy5TdGFydFBvcy5BY3R1YWxOb2RlO1xyXG4gICAgY29uc3QgcG9zID0gdGhpcy5TdGFydFBvcy5Qb3NBdE5vZGU7XHJcbiAgICBjb25zdCB0ZXh0ID0gdGhpcy5TdGFydFBvcy5Qb3NJblRleHRub2RlO1xyXG4gICAgdGhpcy5TdGFydFBvcy5TZXRDdXJzb3IodGhpcy5FbmRQb3MuQWN0dWFsTm9kZSwgdGhpcy5FbmRQb3MuUG9zQXROb2RlLCB0aGlzLkVuZFBvcy5Qb3NJblRleHRub2RlKTtcclxuICAgIHRoaXMuRW5kUG9zLlNldEN1cnNvcihub2RlLCBwb3MsIHRleHQpO1xyXG4gIH1cclxuXHJcbiAgc2hvdygpIHtcclxuICAgIGlmICh3aW5kb3cuZ2V0U2VsZWN0aW9uKSB7XHJcbiAgICAgIGNvbnN0IHNlbGVjdGlvbjogU2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xyXG4gICAgICB0aGlzLnNob3cyKHNlbGVjdGlvbik7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Nob3dDdXJzb3I6IHVuYWJsZSB0byBnZXQgXCJ3aW5kb3cuZ2V0U2VsZWN0aW9uXCInKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2hvdzIoc2VsZWN0aW9uOiBTZWxlY3Rpb24pIHtcclxuICAgIGlmICghc2VsZWN0aW9uKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZW1vdmUgYWxsIHNlbGVjdGVkIGNsYXNzZXNcclxuICAgIGNvbnN0IGVsZW1zID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLnNlbGVjdGVkJyk7XHJcbiAgICBbXS5mb3JFYWNoLmNhbGwoZWxlbXMsIGZ1bmN0aW9uKGVsKSB7XHJcbiAgICAgIGVsLmNsYXNzTGlzdC5yZW1vdmUoJ3NlbGVjdGVkJyk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCBzdGFydFNlbGVjdGlvbiA9IFhtbEN1cnNvclBvcy5nZXRTZWxlY3Rpb25Gb3JQb3ModGhpcy5TdGFydFBvcyk7XHJcbiAgICBpZiAodGhpcy5FbmRQb3MgJiYgdGhpcy5FbmRQb3MuQWN0dWFsTm9kZSAmJiAhdGhpcy5FbmRQb3MuZXF1YWxzKHRoaXMuU3RhcnRQb3MpKSB7XHJcbiAgICAgIC8vIHN0YXJ0ICsgZW5kIHBvc1xyXG4gICAgICBjb25zdCBlbmRTZWxlY3Rpb24gPSBYbWxDdXJzb3JQb3MuZ2V0U2VsZWN0aW9uRm9yUG9zKHRoaXMuRW5kUG9zKTtcclxuICAgICAgc2VsZWN0aW9uLnNldEJhc2VBbmRFeHRlbnQoc3RhcnRTZWxlY3Rpb24ubm9kZSwgc3RhcnRTZWxlY3Rpb24ub2Zmc2V0LCBlbmRTZWxlY3Rpb24ubm9kZSwgZW5kU2VsZWN0aW9uLm9mZnNldCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBvbmx5IHN0YXJ0IHBvc1xyXG4gICAgICBzZWxlY3Rpb24uc2V0UG9zaXRpb24oc3RhcnRTZWxlY3Rpb24ubm9kZSwgc3RhcnRTZWxlY3Rpb24ub2Zmc2V0KTtcclxuXHJcbiAgICAgIC8vIHNlbGVjdCB0YWcgYnkgYWRkaW5nIFwic2VsZWN0XCIgY2xhc3NcclxuICAgICAgaWYgKHRoaXMuU3RhcnRQb3MuUG9zQXROb2RlID09PSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yT25Db21wbGV0ZU5vZGUpIHtcclxuICAgICAgICBjb25zdCBhc0VsZW0gPSB0aGlzLlN0YXJ0UG9zLkFjdHVhbE5vZGUgYXMgRWxlbWVudDtcclxuICAgICAgICBpZiAoYXNFbGVtICYmIGFzRWxlbS5jbGFzc0xpc3QpIHtcclxuICAgICAgICAgIGFzRWxlbS5jbGFzc0xpc3QuYWRkKCdzZWxlY3RlZCcpO1xyXG4gICAgICAgICAgY29uc29sZS5sb2coJ3NlbGVjdGVkIScpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGBubyBhc0VsZW0uY2xhc3NMaXN0IGZvciBzZWxlY3QhICR7WG1sVG9vbGJveC5HZXROb2RlRGVidWdDb250ZXh0KGFzRWxlbSl9YCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFNlbGVjdGlvblBvcyB7XHJcbiAgbm9kZTogTm9kZTtcclxuICBvZmZzZXQ6IG51bWJlcjtcclxufVxyXG4iLCJpbXBvcnQgeyBYbWxDdXJzb3JQb3MsIFhNTEN1cnNvclBvc2l0aW9ucyB9IGZyb20gJy4veG1sQ3Vyc29yUG9zLmNsYXNzJztcclxuaW1wb3J0IHsgRG9tRHVtbXlOb2RlTWFuYWdlciB9IGZyb20gJy4uL2R1bW15Tm9kZXMvZG9tRHVtbXlOb2RlTWFuYWdlci5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbFRvb2xib3ggfSBmcm9tICcuLi94bWxUb29sYm94LmNsYXNzJztcclxuaW1wb3J0IHsgWG1sRWRpdG9yRGVidWdnZXIgfSBmcm9tICcuLi94bWxFZGl0b3JEZWJ1Z2dlcic7XHJcblxyXG5leHBvcnQgY2xhc3MgWG1sQ3Vyc29yUG9zU2V0dGVyIHtcclxuICBwdWJsaWMgc3RhdGljIHNldEZyb21TZWxlY3Rpb24ocG9zOiBYbWxDdXJzb3JQb3MsIHNlbGVjdGlvbkFuY2hvck5vZGU6IE5vZGUsIHNlbGVjdGlvbkFuY2hvck9mZnNldDogbnVtYmVyLCBkZWJ1Z0xvZzogWG1sRWRpdG9yRGVidWdnZXIgPSBudWxsKSB7XHJcbiAgICBpZiAoc2VsZWN0aW9uQW5jaG9yTm9kZSAhPT0gdW5kZWZpbmVkICYmIHNlbGVjdGlvbkFuY2hvck5vZGUgIT09IG51bGwpIHtcclxuICAgICAgbGV0IG5vZGUgPSBzZWxlY3Rpb25BbmNob3JOb2RlIGFzIEVsZW1lbnQ7XHJcbiAgICAgIGlmIChEb21EdW1teU5vZGVNYW5hZ2VyLklzRHVtbXlOb2RlKHNlbGVjdGlvbkFuY2hvck5vZGUucGFyZW50RWxlbWVudCkpIHtcclxuICAgICAgICAvLyBjbGlja2VkIGluc2lkZSBhIGR1bW15IG5vZGVcclxuICAgICAgICBub2RlID0gc2VsZWN0aW9uQW5jaG9yTm9kZS5wYXJlbnRFbGVtZW50IGFzIEVsZW1lbnQ7XHJcblxyXG4gICAgICAgIGlmIChEb21EdW1teU5vZGVNYW5hZ2VyLklzQmVmb3JlRmlyc3RUYWdEdW1teU5vZGUobm9kZSkpIHtcclxuICAgICAgICAgIHN3aXRjaCAoc2VsZWN0aW9uQW5jaG9yT2Zmc2V0KSB7XHJcbiAgICAgICAgICAgIGNhc2UgMDpcclxuICAgICAgICAgICAgICBpZiAoZGVidWdMb2cpIHtcclxuICAgICAgICAgICAgICAgIGRlYnVnTG9nLnNldElucHV0U2VsZWN0aW9uKGAoMSkgY3Vyc29yIGhlcmU6ICM8dGFnPiBwb3MgMGApO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBwb3MuU2V0Q3Vyc29yKG5vZGUucGFyZW50RWxlbWVudCwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvck9uQ29tcGxldGVOb2RlLCAwKTtcclxuICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICBjYXNlIDE6XHJcbiAgICAgICAgICAgICAgaWYgKGRlYnVnTG9nKSB7XHJcbiAgICAgICAgICAgICAgICBkZWJ1Z0xvZy5zZXRJbnB1dFNlbGVjdGlvbihgKDIpIGN1cnNvciBoZXJlOiAjPHRhZz4gcG9zIDFgKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgcG9zLlNldEN1cnNvcihub2RlLnBhcmVudEVsZW1lbnQsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkZyb250T2ZOb2RlLCAwKTtcclxuICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgc2VsZWN0aW9uQW5jaG9yT2Zmc2V0PSR7c2VsZWN0aW9uQW5jaG9yT2Zmc2V0fT8hP2ApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKG5vZGUucGFyZW50RWxlbWVudC5jaGlsZE5vZGVzLmxlbmd0aCA9PT0gMikge1xyXG4gICAgICAgICAgaWYgKGRlYnVnTG9nKSB7XHJcbiAgICAgICAgICAgIGRlYnVnTG9nLnNldElucHV0U2VsZWN0aW9uKGAoMTMsIDE0KSBjdXJzb3IgaGVyZTogPHRhZz4jPC90YWc+YCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBwb3MuU2V0Q3Vyc29yKG5vZGUucGFyZW50RWxlbWVudCwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRW1wdHlOb2RlLCAwKTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChub2RlID09PSBub2RlLnBhcmVudEVsZW1lbnQubGFzdENoaWxkICYmIHNlbGVjdGlvbkFuY2hvck9mZnNldCA9PT0gMSkge1xyXG4gICAgICAgICAgaWYgKGRlYnVnTG9nKSB7XHJcbiAgICAgICAgICAgIGRlYnVnTG9nLnNldElucHV0U2VsZWN0aW9uKGAoOCwgMTIpIGN1cnNvciBoZXJlOiAjPC90YWc+LCBzZWxlY3RpbmcgY29tcGxldGUgbm9kZWApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgcG9zLlNldEN1cnNvcihub2RlLnBhcmVudEVsZW1lbnQsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JPbkNvbXBsZXRlTm9kZSwgMCk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBuZXh0U2libGluZyA9IG5vZGUubmV4dFNpYmxpbmc7XHJcbiAgICAgICAgaWYgKG5leHRTaWJsaW5nKSB7XHJcbiAgICAgICAgICBpZiAoZGVidWdMb2cpIHtcclxuICAgICAgICAgICAgZGVidWdMb2cuc2V0SW5wdXRTZWxlY3Rpb24oYCgzLCA0LCA5LCAxMCkgY3Vyc29yIGhlcmU6ICNUZXh0IG9yIGhlcmUgIzx0YWc+YCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBwb3MuU2V0Q3Vyc29yKG5leHRTaWJsaW5nLCBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5Gcm9udE9mTm9kZSwgMCk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBwcmV2aW91c1NpYmxpbmcgPSBub2RlLnByZXZpb3VzU2libGluZztcclxuICAgICAgICBpZiAocHJldmlvdXNTaWJsaW5nKSB7XHJcbiAgICAgICAgICBpZiAoZGVidWdMb2cpIHtcclxuICAgICAgICAgICAgZGVidWdMb2cuc2V0SW5wdXRTZWxlY3Rpb24oYCg3LCAxMSkgY3Vyc29yIGhlcmU6IFRleHQjIG9yIGhlcmUgPHRhZz4jYCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBwb3MuU2V0Q3Vyc29yKHByZXZpb3VzU2libGluZywgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckJlaGluZE5vZGUsIDApO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBpcyBubyBkdW1teSBub2RlXHJcbiAgICAgICAgaWYgKHNlbGVjdGlvbkFuY2hvck5vZGUubm9kZVR5cGUgPT09IE5vZGUuVEVYVF9OT0RFKSB7XHJcbiAgICAgICAgICBpZiAoc2VsZWN0aW9uQW5jaG9yT2Zmc2V0ID09PSAwKSB7XHJcbiAgICAgICAgICAgIGlmIChkZWJ1Z0xvZykge1xyXG4gICAgICAgICAgICAgIGRlYnVnTG9nLnNldElucHV0U2VsZWN0aW9uKGAoNikgY3Vyc29yIGhlcmU6ICNUZXh0YCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcG9zLlNldEN1cnNvcihzZWxlY3Rpb25BbmNob3JOb2RlLCBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5zaWRlVGV4dE5vZGUsIDApO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHNlbGVjdGlvbkFuY2hvck9mZnNldCA9PT0gc2VsZWN0aW9uQW5jaG9yTm9kZS50ZXh0Q29udGVudC5sZW5ndGgpIHtcclxuICAgICAgICAgICAgaWYgKGRlYnVnTG9nKSB7XHJcbiAgICAgICAgICAgICAgZGVidWdMb2cuc2V0SW5wdXRTZWxlY3Rpb24oYCg3IEFsdGVybmF0aXZlKSBjdXJzb3IgaGVyZTogVGV4dCNgKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBwb3MuU2V0Q3Vyc29yKHNlbGVjdGlvbkFuY2hvck5vZGUsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbnNpZGVUZXh0Tm9kZSwgc2VsZWN0aW9uQW5jaG9yTm9kZS50ZXh0Q29udGVudC5sZW5ndGgpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKGRlYnVnTG9nKSB7XHJcbiAgICAgICAgICAgIGRlYnVnTG9nLnNldElucHV0U2VsZWN0aW9uKGAoNSkgY3Vyc29yIGhlcmU6IFRleHQjVGV4dGApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYgKHNlbGVjdGlvbkFuY2hvck9mZnNldCA+IHNlbGVjdGlvbkFuY2hvck5vZGUudGV4dENvbnRlbnQubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgICAgICAgICBgc2VsZWN0aW9uQW5jaG9yT2Zmc2V0ICR7c2VsZWN0aW9uQW5jaG9yT2Zmc2V0fSBpcyA+IHRoYW4gdGV4dC1sZW5naHQgJHtzZWxlY3Rpb25BbmNob3JOb2RlLnRleHRDb250ZW50Lmxlbmd0aH0gb2YgdGV4dCAnJHtzZWxlY3Rpb25BbmNob3JOb2RlLnRleHRDb250ZW50fScgYFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgcG9zLlNldEN1cnNvcihzZWxlY3Rpb25BbmNob3JOb2RlLCBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5zaWRlVGV4dE5vZGUsIHNlbGVjdGlvbkFuY2hvck9mZnNldCk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBpZiAoRG9tRHVtbXlOb2RlTWFuYWdlci5Jc0R1bW15Tm9kZShwYXJlbnRFbGVtKSkge1xyXG4gICAgICAvLyAgICAgY29uc3QgZHVtbXlFbGVtZW50ID0gcGFyZW50RWxlbTtcclxuXHJcbiAgICAgIC8vICAgICBjb25zdCBuZXh0U2libGluZyA9IHBhcmVudEVsZW0ubmV4dFNpYmxpbmc7XHJcbiAgICAgIC8vICAgICBpZiAoWG1sVG9vbGJveC5Jc3RUZXh0T2RlcktvbW1lbnRhck5vZGUobmV4dFNpYmxpbmcpKSB7XHJcbiAgICAgIC8vICAgICAgICAgLy8gY3Vyc29yIGhlcmU6ICN0ZXh0ICgjID0gcmVkIGR1bW15Tm9kZSlcclxuICAgICAgLy8gICAgICAgICBwb3MuQ3Vyc29yU2V0emVuKG5leHRTaWJsaW5nLCBYTUxDdXJzb3JQb3NpdGlvbmVuLkN1cnNvcklubmVyaGFsYkRlc1RleHROb2RlcywgMCk7XHJcbiAgICAgIC8vICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAvLyAgICAgfVxyXG5cclxuICAgICAgLy8gICAgIGNvbnN0IHByZXZpb3VzU2libGluZyA9IGR1bW15RWxlbWVudC5wcmV2aW91c1NpYmxpbmc7XHJcbiAgICAgIC8vICAgICBpZiAoIXByZXZpb3VzU2libGluZykge1xyXG4gICAgICAvLyAgICAgLy8gICAgcG9zLkN1cnNvclNldHplbihkdW1teUVsZW1lbnQucGFyZW50RWxlbWVudCwgWE1MQ3Vyc29yUG9zaXRpb25lbi5jLCAwKTtcclxuICAgICAgLy8gICAgIH1cclxuICAgICAgLy8gfVxyXG5cclxuICAgICAgLy8gc3dpdGNoIChub2RlLm5vZGVUeXBlKSB7XHJcblxyXG4gICAgICAvLyAgICAgY2FzZSBOb2RlLlRFWFRfTk9ERTpcclxuXHJcbiAgICAgIC8vIGlmIChsb29wQ291bnQgPT09IDApIHtcclxuICAgICAgLy8gICAgIGNvbnN0IG5leHRTaWJsaW5nID0gcGFyZW50RWxlbS5uZXh0U2libGluZztcclxuICAgICAgLy8gICAgIGlmIChuZXh0U2libGluZyAmJiBuZXh0U2libGluZy5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUgJiYgc2VsZWN0aW9uQW5jaG9yT2Zmc2V0ID09PSAxKSB7XHJcbiAgICAgIC8vICAgICAgICAgLy8gc2V0IGN1cnNvciBhdCBzdGFydCBvZiBmb2xsb3dpbmcgdGV4dG5vZGVcclxuICAgICAgLy8gICAgICAgICBwb3MuQ3Vyc29yU2V0emVuKG5leHRTaWJsaW5nLCBYTUxDdXJzb3JQb3NpdGlvbmVuLkN1cnNvcklubmVyaGFsYkRlc1RleHROb2RlcywgMCk7XHJcbiAgICAgIC8vICAgICB9IGVsc2Uge1xyXG4gICAgICAvLyAgICAgICAgIGNvbnN0IHByZXZpb3VzU2libGluZyA9IHBhcmVudEVsZW0ucHJldmlvdXNTaWJsaW5nO1xyXG4gICAgICAvLyAgICAgICAgIGlmIChwcmV2aW91c1NpYmxpbmcgJiYgcHJldmlvdXNTaWJsaW5nLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSAmJiBzZWxlY3Rpb25BbmNob3JPZmZzZXQgPT09IDApIHtcclxuICAgICAgLy8gICAgICAgICAgICAgLy8gc2V0IGN1cnNvciBhdCBlbmQgb2YgcHJldmlvdXMgdGV4dG5vZGVcclxuICAgICAgLy8gICAgICAgICAgICAgcG9zLkN1cnNvclNldHplbihwcmV2aW91c1NpYmxpbmcsIFhNTEN1cnNvclBvc2l0aW9uZW4uQ3Vyc29ySW5uZXJoYWxiRGVzVGV4dE5vZGVzLCBwcmV2aW91c1NpYmxpbmcubm9kZVZhbHVlLmxlbmd0aCk7XHJcbiAgICAgIC8vICAgICAgICAgfVxyXG4gICAgICAvLyAgICAgfVxyXG4gICAgICAvLyB9IGVsc2Uge1xyXG4gICAgICAvLyAgICAgbm9kZSA9IHBhcmVudEVsZW07IC8vIHVwIHRvIGR1bW15IG5vZGVcclxuICAgICAgLy8gfVxyXG5cclxuICAgICAgLy8gICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAvLyAgICAgICAgICAgICBwb3MuQ3Vyc29yU2V0emVuKG5vZGUsIFhNTEN1cnNvclBvc2l0aW9uZW4uQ3Vyc29ySW5uZXJoYWxiRGVzVGV4dE5vZGVzLCBzZWxlY3Rpb25BbmNob3JPZmZzZXQpO1xyXG4gICAgICAvLyAgICAgICAgIH1cclxuICAgICAgLy8gICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIC8vICAgICBjYXNlIE5vZGUuRUxFTUVOVF9OT0RFOlxyXG4gICAgICAvLyAgICAgICAgIGlmIChEb21EdW1teU5vZGVNYW5hZ2VyLklzRHVtbXlOb2RlKG5vZGUpKSB7XHJcbiAgICAgIC8vICAgICAgICAgICAgIC8vIG5vZGUgPSBwYXJlbnRFbGVtOyAvLyB1cCB0byBwYXJlbnQgbm9kZVxyXG4gICAgICAvLyAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vICAgICAgICAgICAgIHBvcy5DdXJzb3JTZXR6ZW4obm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25lbi5DdXJzb3JBdWZOb2RlU2VsYnN0Vm9yZGVyZXNUYWcpO1xyXG4gICAgICAvLyAgICAgICAgIH1cclxuICAgICAgLy8gICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIC8vICAgICBkZWZhdWx0OlxyXG4gICAgICAvLyAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5oYW5kbGVkIG5vZGVUeXBlICcke25vZGUubm9kZVR5cGV9JyBvZiBub2RlICR7WG1sVG9vbGJveC5HZXROb2RlRGVidWdDb250ZXh0KG5vZGUpfWApO1xyXG4gICAgICAvLyB9XHJcbiAgICB9XHJcbiAgICBjb25zb2xlLmVycm9yKFxyXG4gICAgICBgZm91bmQgbm8gc3VpdGluZyBjdXJzb3IgaW50ZXJwcmV0YXRpb24hIEZvciBzZWxlY3Rpb25BbmNob3JOb2RlPSR7WG1sVG9vbGJveC5HZXROb2RlRGVidWdDb250ZXh0KHNlbGVjdGlvbkFuY2hvck5vZGUpfSwgc2VsZWN0aW9uQW5jaG9yT2Zmc2V0PSR7c2VsZWN0aW9uQW5jaG9yT2Zmc2V0fWBcclxuICAgICk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IERvbUR1bW15Tm9kZU1hbmFnZXIgfSBmcm9tICcuLi9kdW1teU5vZGVzL2RvbUR1bW15Tm9kZU1hbmFnZXIuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWxDdXJzb3IgfSBmcm9tICcuLi9jdXJzb3IveG1sQ3Vyc29yLmNsYXNzJztcclxuaW1wb3J0IHsgWE1MQ3Vyc29yUG9zaXRpb25zIH0gZnJvbSAnLi4vY3Vyc29yL3htbEN1cnNvclBvcy5jbGFzcyc7XHJcblxyXG5leHBvcnQgY2xhc3MgWG1sRG9tQ2xlYW5lciB7XHJcbiAgcHVibGljIHN0YXRpYyBjbGVhblVwKG5vZGU6IE5vZGUsIGFjdHVhbEN1cnNvcjogWG1sQ3Vyc29yKSB7XHJcbiAgICB0aGlzLmNvbmNhdFRleHROb2Rlcyhub2RlLCBhY3R1YWxDdXJzb3IpO1xyXG4gIH1cclxuXHJcbiAgLyoqKlxyXG4gICAqIGlmIHR3byB0ZXh0bm9kZXMgYXJlIGRpcmVjdCBzaWJsaW5nczogY29uY2F0IHRvIG9uZSB0ZXh0bm9kZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBzdGF0aWMgY29uY2F0VGV4dE5vZGVzKG5vZGU6IE5vZGUsIGFjdHVhbEN1cnNvcjogWG1sQ3Vyc29yLCBub2RlRGVwdGggPSAwKTogdm9pZCB7XHJcbiAgICBsZXQgcmVzdGFydCA9IHRydWU7XHJcblxyXG4gICAgd2hpbGUgKHJlc3RhcnQgPT09IHRydWUpIHtcclxuICAgICAgcmVzdGFydCA9IGZhbHNlO1xyXG5cclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyArK2kpIHtcclxuICAgICAgICBjb25zdCBmaXJzdFRvQ2hlY2sgPSBub2RlLmNoaWxkTm9kZXNbaV07XHJcbiAgICAgICAgaWYgKERvbUR1bW15Tm9kZU1hbmFnZXIuSXNEdW1teU5vZGUoZmlyc3RUb0NoZWNrKSkge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEdW1teW5vZGVzIGhhdmUgdG8gYmUgcmVtb3ZlZCBiZWZvcmUgdXNpbmcgWG1sRG9tQ2xlYW5lciEnKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGZpcnN0VG9DaGVjay5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcclxuICAgICAgICAgIGNvbnN0IHNlY29uZFRvQ2hlY2sgPSBmaXJzdFRvQ2hlY2submV4dFNpYmxpbmc7XHJcbiAgICAgICAgICBpZiAoc2Vjb25kVG9DaGVjayAhPT0gbnVsbCAmJiBzZWNvbmRUb0NoZWNrLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xyXG4gICAgICAgICAgICAvLyB0d28gdGV4dCBub2RlcyBhZnRlciBlYWNoIG90aGVyID0+IGNvbmNhdFxyXG4gICAgICAgICAgICBpZiAoYWN0dWFsQ3Vyc29yLlN0YXJ0UG9zLkFjdHVhbE5vZGUgPT09IHNlY29uZFRvQ2hlY2spIHtcclxuICAgICAgICAgICAgICBhY3R1YWxDdXJzb3IuU3RhcnRQb3MuU2V0Q3Vyc29yKGZpcnN0VG9DaGVjaywgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluc2lkZVRleHROb2RlLCBmaXJzdFRvQ2hlY2sudGV4dENvbnRlbnQubGVuZ3RoICsgYWN0dWFsQ3Vyc29yLlN0YXJ0UG9zLlBvc0luVGV4dG5vZGUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChhY3R1YWxDdXJzb3IuRW5kUG9zLkFjdHVhbE5vZGUgPT09IHNlY29uZFRvQ2hlY2spIHtcclxuICAgICAgICAgICAgICBhY3R1YWxDdXJzb3IuRW5kUG9zLlNldEN1cnNvcihmaXJzdFRvQ2hlY2ssIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbnNpZGVUZXh0Tm9kZSwgZmlyc3RUb0NoZWNrLnRleHRDb250ZW50Lmxlbmd0aCArIGFjdHVhbEN1cnNvci5FbmRQb3MuUG9zSW5UZXh0bm9kZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZmlyc3RUb0NoZWNrLnRleHRDb250ZW50ID0gZmlyc3RUb0NoZWNrLnRleHRDb250ZW50ICsgc2Vjb25kVG9DaGVjay50ZXh0Q29udGVudDtcclxuICAgICAgICAgICAgbm9kZS5yZW1vdmVDaGlsZChzZWNvbmRUb0NoZWNrKTtcclxuICAgICAgICAgICAgcmVzdGFydCA9IHRydWU7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gdXBkYXRlIGNoaWxkIG5vZGVzXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7ICsraSkge1xyXG4gICAgICB0aGlzLmNvbmNhdFRleHROb2Rlcyhub2RlLmNoaWxkTm9kZXNbaV0sIGFjdHVhbEN1cnNvciwgbm9kZURlcHRoICsgMSk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IFhtbFJ1bGVzIH0gZnJvbSAnLi4veG1sLXJ1bGVzLWNoZWNrL3htbFJ1bGVzLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sQ3Vyc29yUG9zLCBYTUxDdXJzb3JQb3NpdGlvbnMgfSBmcm9tICcuLi9jdXJzb3IveG1sQ3Vyc29yUG9zLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sQ3Vyc29yUG9zTW92ZXIgfSBmcm9tICcuLi9jdXJzb3IveG1sQ3Vyc29yUG9zTW92ZXIuY2xhc3MnO1xyXG5pbXBvcnQgeyBEb21EdW1teU5vZGVNYW5hZ2VyIH0gZnJvbSAnLi4vZHVtbXlOb2Rlcy9kb21EdW1teU5vZGVNYW5hZ2VyLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sQ3Vyc29yIH0gZnJvbSAnLi4vY3Vyc29yL3htbEN1cnNvci5jbGFzcyc7XHJcblxyXG5leHBvcnQgY2xhc3MgWG1sRWRpdERlbGV0ZSB7XHJcbiAgcHVibGljIHN0YXRpYyBkZWxldGVTZWxlY3Rpb24oY3Vyc29yOiBYbWxDdXJzb3IsIHJvb3ROb2RlOiBFbGVtZW50LCB4bWxSdWxlczogWG1sUnVsZXMpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHN0YXRpYyBkZWxldGVBZnRlcihwb3M6IFhtbEN1cnNvclBvcywgcm9vdE5vZGU6IEVsZW1lbnQsIHhtbFJ1bGVzOiBYbWxSdWxlcyk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHBvcyA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBzd2l0Y2ggKHBvcy5Qb3NBdE5vZGUpIHtcclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yT25Db21wbGV0ZU5vZGU6XHJcbiAgICAgICAgcmV0dXJuIFhtbEVkaXREZWxldGUuZGVsZXRlQmVmb3JlKHBvcywgcm9vdE5vZGUsIHhtbFJ1bGVzKTtcclxuXHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckJlaGluZE5vZGU6XHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGU6XHJcbiAgICAgICAgWG1sQ3Vyc29yUG9zTW92ZXIubW92ZVJpZ2h0KHBvcywgcm9vdE5vZGUsIHhtbFJ1bGVzKTtcclxuICAgICAgICByZXR1cm4gWG1sRWRpdERlbGV0ZS5kZWxldGVCZWZvcmUocG9zLCByb290Tm9kZSwgeG1sUnVsZXMpO1xyXG5cclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5FbXB0eU5vZGU6XHJcbiAgICAgICAgcmV0dXJuIFhtbEVkaXREZWxldGUuZGVsZXRlQmVmb3JlKHBvcywgcm9vdE5vZGUsIHhtbFJ1bGVzKTtcclxuXHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluc2lkZVRleHROb2RlOlxyXG4gICAgICAgIFhtbEN1cnNvclBvc01vdmVyLm1vdmVSaWdodChwb3MsIHJvb3ROb2RlLCB4bWxSdWxlcyk7XHJcbiAgICAgICAgcmV0dXJuIFhtbEVkaXREZWxldGUuZGVsZXRlQmVmb3JlKHBvcywgcm9vdE5vZGUsIHhtbFJ1bGVzKTtcclxuXHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdHJpbmcuRm9ybWF0KFwiWG1sQ3Vyc29yRWRpdC5kZWxldGVCZWZvcmU6IHVua25vd24gQ3Vyc29yUG9zICR7cG9zLlBvc0F0Tm9kZX1gKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgZGVsZXRlQmVmb3JlKHBvczogWG1sQ3Vyc29yUG9zLCByb290Tm9kZTogRWxlbWVudCwgeG1sUnVsZXM6IFhtbFJ1bGVzKTogYm9vbGVhbiB7XHJcbiAgICBsZXQgZGVsZXRlTm9kZTogTm9kZTtcclxuXHJcbiAgICAvLyBjb25zb2xlLmxvZyhwb3MuZ2V0RGVidWdEZXNjcmlwdGlvbigpKTtcclxuXHJcbiAgICBpZiAocG9zID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgc3dpdGNoIChwb3MuUG9zQXROb2RlKSB7XHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvck9uQ29tcGxldGVOb2RlOlxyXG4gICAgICAgIGRlbGV0ZU5vZGUgPSBwb3MuQWN0dWFsTm9kZTtcclxuICAgICAgICBYbWxDdXJzb3JQb3NNb3Zlci5tb3ZlUmlnaHQocG9zLCByb290Tm9kZSwgeG1sUnVsZXMpO1xyXG4gICAgICAgIGRlbGV0ZU5vZGUucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZChkZWxldGVOb2RlKTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckJlaGluZE5vZGU6XHJcbiAgICAgICAgaWYgKHBvcy5BY3R1YWxOb2RlLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xyXG4gICAgICAgICAgcG9zLlNldEN1cnNvcihwb3MuQWN0dWFsTm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluc2lkZVRleHROb2RlLCBwb3MuQWN0dWFsTm9kZS50ZXh0Q29udGVudC5sZW5ndGgpO1xyXG4gICAgICAgICAgcmV0dXJuIFhtbEVkaXREZWxldGUuZGVsZXRlQmVmb3JlKHBvcywgcm9vdE5vZGUsIHhtbFJ1bGVzKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgcG9zLkFjdHVhbE5vZGUucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZChwb3MuQWN0dWFsTm9kZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5FbXB0eU5vZGU6XHJcbiAgICAgICAgZGVsZXRlTm9kZSA9IHBvcy5BY3R1YWxOb2RlO1xyXG4gICAgICAgIFhtbEN1cnNvclBvc01vdmVyLm1vdmVSaWdodChwb3MsIHJvb3ROb2RlLCB4bWxSdWxlcyk7XHJcbiAgICAgICAgZGVsZXRlTm9kZS5wYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKGRlbGV0ZU5vZGUpO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5Gcm9udE9mTm9kZTpcclxuICAgICAgICBkZWxldGVOb2RlID0gRG9tRHVtbXlOb2RlTWFuYWdlci5nZXRQcmV2aW91c1NpYmxpbmcocG9zLkFjdHVhbE5vZGUpO1xyXG4gICAgICAgIGlmICghZGVsZXRlTm9kZSkge1xyXG4gICAgICAgICAgZGVsZXRlTm9kZSA9IHBvcy5BY3R1YWxOb2RlLnBhcmVudEVsZW1lbnQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChkZWxldGVOb2RlKSB7XHJcbiAgICAgICAgICBpZiAoZGVsZXRlTm9kZS5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcclxuICAgICAgICAgICAgcG9zLlNldEN1cnNvcihkZWxldGVOb2RlLCBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5zaWRlVGV4dE5vZGUsIGRlbGV0ZU5vZGUudGV4dENvbnRlbnQubGVuZ3RoKTtcclxuICAgICAgICAgICAgcmV0dXJuIFhtbEVkaXREZWxldGUuZGVsZXRlQmVmb3JlKHBvcywgcm9vdE5vZGUsIHhtbFJ1bGVzKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZU5vZGUucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZChkZWxldGVOb2RlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbnNpZGVUZXh0Tm9kZTpcclxuICAgICAgICBpZiAocG9zLlBvc0luVGV4dG5vZGUgPT09IDApIHtcclxuICAgICAgICAgIHBvcy5TZXRDdXJzb3IocG9zLkFjdHVhbE5vZGUsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkZyb250T2ZOb2RlLCAwKTtcclxuICAgICAgICAgIHJldHVybiBYbWxFZGl0RGVsZXRlLmRlbGV0ZUJlZm9yZShwb3MsIHJvb3ROb2RlLCB4bWxSdWxlcyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGxldCB0ZXh0ID0gcG9zLkFjdHVhbE5vZGUudGV4dENvbnRlbnQ7XHJcbiAgICAgICAgICB0ZXh0ID0gdGV4dC5zdWJzdHJpbmcoMCwgcG9zLlBvc0luVGV4dG5vZGUgLSAxKSArIHRleHQuc3Vic3RyKHBvcy5Qb3NJblRleHRub2RlLCBwb3MuQWN0dWFsTm9kZS50ZXh0Q29udGVudC5sZW5ndGgpO1xyXG4gICAgICAgICAgcG9zLkFjdHVhbE5vZGUudGV4dENvbnRlbnQgPSB0ZXh0O1xyXG4gICAgICAgICAgWG1sQ3Vyc29yUG9zTW92ZXIubW92ZUxlZnQocG9zLCByb290Tm9kZSwgeG1sUnVsZXMpO1xyXG4gICAgICAgICAgLy8gcG9zLlNldEN1cnNvcihwb3MuQWN0dWFsTm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluc2lkZVRleHROb2RlLCBwb3MuUG9zSW5UZXh0bm9kZSAtIDEpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdHJpbmcuRm9ybWF0KFwiWG1sRWRpdC5kZWxldGVCZWZvcmU6IHVua25vd24gQ3Vyc29yUG9zICR7cG9zLlBvc0F0Tm9kZX1gKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgWG1sQ3Vyc29yUG9zLCBYTUxDdXJzb3JQb3NpdGlvbnMgfSBmcm9tICcuLi9jdXJzb3IveG1sQ3Vyc29yUG9zLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sMmh0bWwgfSBmcm9tICcuLi94bWwtaHRtbC1jb252ZXJ0ZXIveG1sMmh0bWwuY2xhc3MnO1xyXG5cclxuZXhwb3J0IGNsYXNzIFhtbEVkaXRSdWxlQ2hlY2tUZXh0SW5zZXJ0IHtcclxuICBuYW1lc3BhY2VQcmFlZml4ID0gJ3hzOic7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgeHNkTm9kZXM6IE1hcDxzdHJpbmcsIEVsZW1lbnQ+KSB7fVxyXG5cclxuICBpc1RleHRBbGxvd2VkQXRUaGlzQ3Vyc29yUG9zKGN1cnNvclBvc1RvQ2hlY2s6IFhtbEN1cnNvclBvcyk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKCFjdXJzb3JQb3NUb0NoZWNrKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIGNvbnN0IHBhcmVudE5vZGUgPSB0aGlzLmdldFJlbGV2YW50UGFyZW50Tm9kZUZvckN1cnNvclBvcyhjdXJzb3JQb3NUb0NoZWNrKTtcclxuICAgIGNvbnN0IHBhcmVudE5hbWUgPSBYbWwyaHRtbC5nZXRUYWdOYW1lRnJvbU5vZGUocGFyZW50Tm9kZSk7XHJcbiAgICBjb25zdCB4c2ROb2RlID0gdGhpcy54c2ROb2Rlcy5nZXQocGFyZW50TmFtZSk7XHJcbiAgICBpZiAoeHNkTm9kZSkge1xyXG4gICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmlzVGV4dEFsbG93ZWRJblRoaXNFbGVtZW50KHhzZE5vZGUpO1xyXG4gICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIGZhbHNlOyAvLyBlbGVtZW50IG5vdCBmb3VuZFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0UmVsZXZhbnRQYXJlbnROb2RlRm9yQ3Vyc29yUG9zKGN1cnNvclBvc1RvQ2hlY2s6IFhtbEN1cnNvclBvcyk6IE5vZGUge1xyXG4gICAgaWYgKGN1cnNvclBvc1RvQ2hlY2spIHtcclxuICAgICAgbGV0IHBhcmVudE5vZGUgPSBjdXJzb3JQb3NUb0NoZWNrLkFjdHVhbE5vZGU7XHJcblxyXG4gICAgICBzd2l0Y2ggKHBhcmVudE5vZGUubm9kZVR5cGUpIHtcclxuICAgICAgICBjYXNlIE5vZGUuQ09NTUVOVF9OT0RFOlxyXG4gICAgICAgIGNhc2UgTm9kZS5URVhUX05PREU6XHJcbiAgICAgICAgICBwYXJlbnROb2RlID0gcGFyZW50Tm9kZS5wYXJlbnRFbGVtZW50O1xyXG4gICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgIGNhc2UgTm9kZS5FTEVNRU5UX05PREU6XHJcbiAgICAgICAgICBzd2l0Y2ggKGN1cnNvclBvc1RvQ2hlY2suUG9zQXROb2RlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRW1wdHlOb2RlOlxyXG4gICAgICAgICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbnNpZGVUZXh0Tm9kZTpcclxuICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckJlaGluZE5vZGU6XHJcbiAgICAgICAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluRnJvbnRPZk5vZGU6XHJcbiAgICAgICAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvck9uQ29tcGxldGVOb2RlOlxyXG4gICAgICAgICAgICAgIHBhcmVudE5vZGUgPSBwYXJlbnROb2RlLnBhcmVudEVsZW1lbnQ7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5oYW5kbGVkICBjdXJzb3JQb3NUb0NoZWNrLlBvc0FtTm9kZSBcIiR7Y3Vyc29yUG9zVG9DaGVjay5Qb3NBdE5vZGV9XCIvJHtYbWxDdXJzb3JQb3MuZ2V0WG1sQ3Vyc29yUG9zaXRpb25EZWJ1Z05hbWUoY3Vyc29yUG9zVG9DaGVjay5Qb3NBdE5vZGUpfVwiIGApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuaGFuZGxlZCAgcGFyZW50Tm9kZS5ub2RlVHlwZSBcIiR7cGFyZW50Tm9kZS5ub2RlVHlwZX1cImApO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBwYXJlbnROb2RlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgaXNUZXh0QWxsb3dlZEluVGhpc0VsZW1lbnQoeHNkTm9kZTogTm9kZSwgYWxyZWFkeUFkZGVkRWxlbWVudE5hbWVzOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQ8c3RyaW5nPigpKTogYm9vbGVhbiB7XHJcbiAgICBsZXQgZWxlbWVudE5hbWU6IHN0cmluZztcclxuXHJcbiAgICBpZiAoeHNkTm9kZS5ub2RlVHlwZSA9PT0gTm9kZS5FTEVNRU5UX05PREUpIHtcclxuICAgICAgY29uc3QgYXNFbGVtID0geHNkTm9kZSBhcyBFbGVtZW50O1xyXG4gICAgICBpZiAoYXNFbGVtKSB7XHJcbiAgICAgICAgY29uc3QgbWl4ZWRBdHRyaWIgPSBhc0VsZW0uZ2V0QXR0cmlidXRlKCdtaXhlZCcpO1xyXG4gICAgICAgIGlmIChtaXhlZEF0dHJpYikge1xyXG4gICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IHR5cGVBdHRyaWIgPSBhc0VsZW0uZ2V0QXR0cmlidXRlKCd0eXBlJyk7XHJcbiAgICAgICAgaWYgKHR5cGVBdHRyaWIgJiYgdHlwZUF0dHJpYiA9PT0gYCR7dGhpcy5uYW1lc3BhY2VQcmFlZml4fXN0cmluZ2ApIHtcclxuICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGFzRWxlbS5sb2NhbE5hbWUgPT09ICdlbGVtZW50Jykge1xyXG4gICAgICAgICAgZWxlbWVudE5hbWUgPSBhc0VsZW0uZ2V0QXR0cmlidXRlKCduYW1lJyk7XHJcbiAgICAgICAgICBpZiAoZWxlbWVudE5hbWUpIHtcclxuICAgICAgICAgICAgaWYgKGFscmVhZHlBZGRlZEVsZW1lbnROYW1lcy5oYXMoZWxlbWVudE5hbWUpKSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBlbGVtZW50IHJlY3Vyc2lvbiBkZXRlY3RlZFxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBhbHJlYWR5QWRkZWRFbGVtZW50TmFtZXMuYWRkKGVsZW1lbnROYW1lKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjaGlsZE5vZGVzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoeHNkTm9kZS5jaGlsZE5vZGVzKSBhcyBOb2RlW107XHJcblxyXG4gICAgbGV0IGFsbG93ZWQgPSBmYWxzZTtcclxuXHJcbiAgICBjaGlsZE5vZGVzLmZvckVhY2goY2hpbGQgPT4ge1xyXG4gICAgICBpZiAoY2hpbGQubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XHJcbiAgICAgICAgY29uc3QgY2hpbGRFbGVtID0gY2hpbGQgYXMgRWxlbWVudDtcclxuICAgICAgICBpZiAoY2hpbGRFbGVtKSB7XHJcbiAgICAgICAgICBzd2l0Y2ggKGNoaWxkRWxlbS5sb2NhbE5hbWUpIHtcclxuICAgICAgICAgICAgY2FzZSAnY29tcGxleFR5cGUnOlxyXG4gICAgICAgICAgICBjYXNlICdzZXF1ZW5jZSc6XHJcbiAgICAgICAgICAgIGNhc2UgJ2Nob2ljZSc6XHJcbiAgICAgICAgICAgIGNhc2UgJ3NpbXBsZUNvbnRlbnQnOlxyXG4gICAgICAgICAgICBjYXNlICdleHRlbnNpb24nOlxyXG4gICAgICAgICAgICAgIGlmICh0aGlzLmlzVGV4dEFsbG93ZWRJblRoaXNFbGVtZW50KGNoaWxkLCBhbHJlYWR5QWRkZWRFbGVtZW50TmFtZXMpID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICBhbGxvd2VkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgIGNhc2UgJ2VsZW1lbnQnOlxyXG4gICAgICAgICAgICAgIGNvbnN0IHJlZm5hbWUgPSBjaGlsZEVsZW0uYXR0cmlidXRlcy5nZXROYW1lZEl0ZW0oJ3JlZicpO1xyXG4gICAgICAgICAgICAgIGlmIChyZWZuYW1lKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWZlcmVkTm9kZSA9IHRoaXMueHNkTm9kZXMuZ2V0KHJlZm5hbWUudmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHJlZmVyZWROb2RlKSB7XHJcbiAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzVGV4dEFsbG93ZWRJblRoaXNFbGVtZW50KHJlZmVyZWROb2RlLCBhbHJlYWR5QWRkZWRFbGVtZW50TmFtZXMpID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYWxsb3dlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgIHJlZmVyZWQgZWxlbWVudCBcIiR7cmVmbmFtZX1cIiBmb3IgZWxlbWVudCBcIiR7Y2hpbGRFbGVtLm91dGVySFRNTH1cIiBub3QgZm91bmRgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgICAgICBjYXNlICdhdHRyaWJ1dGUnOlxyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICBhbGVydCgndW5rbm93biBjaGlsZEVsZW0ubG9jYWxuYW1lIFwiJyArIGNoaWxkRWxlbS5sb2NhbE5hbWUgKyAnXCIvJyArIGNoaWxkRWxlbS5vdXRlckhUTUwpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIGFsbG93ZWQ7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IFhtbEN1cnNvclBvcywgWE1MQ3Vyc29yUG9zaXRpb25zIH0gZnJvbSAnLi4vY3Vyc29yL3htbEN1cnNvclBvcy5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbFJ1bGVzIH0gZnJvbSAnLi4veG1sLXJ1bGVzLWNoZWNrL3htbFJ1bGVzLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sRWRpdFJ1bGVDaGVja1RleHRJbnNlcnQgfSBmcm9tICcuLi94bWwtcnVsZXMtY2hlY2sveG1sRWRpdFJ1bGVDaGVja1RleHRJbnNlcnQuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWxTY2hlbWEgfSBmcm9tICcuLi94bWwtcnVsZXMtY2hlY2sveG1sU2NoZW1hLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sRWRpdERlbGV0ZSB9IGZyb20gJy4veG1sRWRpdERlbGV0ZWNsYXNzJztcclxuaW1wb3J0IHsgWG1sQ3Vyc29yIH0gZnJvbSAnLi4vY3Vyc29yL3htbEN1cnNvci5jbGFzcyc7XHJcbmltcG9ydCB7IERvbUR1bW15Tm9kZU1hbmFnZXIgfSBmcm9tICcuLi9kdW1teU5vZGVzL2RvbUR1bW15Tm9kZU1hbmFnZXIuY2xhc3MnO1xyXG5cclxuZXhwb3J0IGNsYXNzIFhtbEVkaXRJbnNlcnQge1xyXG4gIHB1YmxpYyBzdGF0aWMgcmVwbGFjZVdpdGhUZXh0KHBvczogWG1sQ3Vyc29yLCB2YWx1ZTogc3RyaW5nLCByb290Tm9kZTogRWxlbWVudCwgeG1sUnVsZXM6IFhtbFJ1bGVzLCB4bWxTY2hlbWE6IFhtbFNjaGVtYSk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHBvcyA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIGlmICh2YWx1ZSA9PT0gJycgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PSBudWxsKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAocG9zLmlzRW1wdHlTZWxlY3Rpb24oKSA9PT0gZmFsc2UpIHtcclxuICAgICAgaWYgKFhtbEVkaXREZWxldGUuZGVsZXRlU2VsZWN0aW9uKHBvcywgcm9vdE5vZGUsIHhtbFJ1bGVzKSA9PT0gZmFsc2UpIHtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gWG1sRWRpdEluc2VydC5pbnNlcnRUZXh0KHBvcy5FbmRQb3MsIHZhbHVlLCByb290Tm9kZSwgeG1sUnVsZXMsIHhtbFNjaGVtYSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGluc2VydFRleHQocG9zOiBYbWxDdXJzb3JQb3MsIHZhbHVlOiBzdHJpbmcsIHJvb3ROb2RlOiBFbGVtZW50LCB4bWxSdWxlczogWG1sUnVsZXMsIHhtbFNjaGVtYTogWG1sU2NoZW1hKTogYm9vbGVhbiB7XHJcbiAgICBpZiAocG9zID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh2YWx1ZSA9PT0gJycgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PSBudWxsKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBzd2l0Y2ggKHBvcy5Qb3NBdE5vZGUpIHtcclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yT25Db21wbGV0ZU5vZGU6XHJcbiAgICAgICAgbGV0IHRleHRBbGxvd2VkID0gWG1sRWRpdEluc2VydC5pc1RleHRBbGxvd2VkSW5QYXJlbnROb2RlKHBvcywgeG1sU2NoZW1hKTtcclxuICAgICAgICBpZiAodGV4dEFsbG93ZWQgPT09IHRydWUpIHtcclxuICAgICAgICAgIGNvbnN0IG5ld1RleHROb2RlID0gcG9zLkFjdHVhbE5vZGUub3duZXJEb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh2YWx1ZSk7XHJcbiAgICAgICAgICBwb3MuQWN0dWFsTm9kZS5wYXJlbnRFbGVtZW50Lmluc2VydEJlZm9yZShuZXdUZXh0Tm9kZSwgcG9zLkFjdHVhbE5vZGUpO1xyXG4gICAgICAgICAgcG9zLkFjdHVhbE5vZGUucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZChwb3MuQWN0dWFsTm9kZSk7XHJcbiAgICAgICAgICBjb25zdCBuZXh0U2libGluZyA9IERvbUR1bW15Tm9kZU1hbmFnZXIuZ2V0TmV4dFNpYmxpbmcobmV3VGV4dE5vZGUpO1xyXG4gICAgICAgICAgaWYgKG5leHRTaWJsaW5nKSB7XHJcbiAgICAgICAgICAgIHBvcy5TZXRDdXJzb3IobmV4dFNpYmxpbmcsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkZyb250T2ZOb2RlKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHBvcy5TZXRDdXJzb3IobmV3VGV4dE5vZGUsIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JCZWhpbmROb2RlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yQmVoaW5kTm9kZTpcclxuICAgICAgICBpZiAocG9zLkFjdHVhbE5vZGUubm9kZVR5cGUgPT09IE5vZGUuVEVYVF9OT0RFKSB7XHJcbiAgICAgICAgICBwb3MuQWN0dWFsTm9kZS50ZXh0Q29udGVudCA9IHBvcy5BY3R1YWxOb2RlLnRleHRDb250ZW50ICsgdmFsdWU7XHJcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgdGV4dEFsbG93ZWQgPSBYbWxFZGl0SW5zZXJ0LmlzVGV4dEFsbG93ZWRJblBhcmVudE5vZGUocG9zLCB4bWxTY2hlbWEpO1xyXG4gICAgICAgICAgaWYgKHRleHRBbGxvd2VkID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG5ld1RleHROb2RlID0gcG9zLkFjdHVhbE5vZGUub3duZXJEb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh2YWx1ZSk7XHJcbiAgICAgICAgICAgIHBvcy5BY3R1YWxOb2RlLnBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKG5ld1RleHROb2RlLCBwb3MuQWN0dWFsTm9kZS5uZXh0U2libGluZyk7IC8vIGluc2VydHMgdGhlIG5ldyBub2RlIGFmdGVyIHRoZSBhY3R1YWwgbm9kZVxyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkZyb250T2ZOb2RlOlxyXG4gICAgICAgIGlmIChwb3MuQWN0dWFsTm9kZS5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcclxuICAgICAgICAgIHBvcy5BY3R1YWxOb2RlLnRleHRDb250ZW50ID0gdmFsdWUgKyBwb3MuQWN0dWFsTm9kZS50ZXh0Q29udGVudDtcclxuICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0ZXh0QWxsb3dlZCA9IFhtbEVkaXRJbnNlcnQuaXNUZXh0QWxsb3dlZEluUGFyZW50Tm9kZShwb3MsIHhtbFNjaGVtYSk7XHJcbiAgICAgICAgICBpZiAodGV4dEFsbG93ZWQgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgY29uc3QgbmV3VGV4dE5vZGUgPSBwb3MuQWN0dWFsTm9kZS5vd25lckRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHZhbHVlKTtcclxuICAgICAgICAgICAgcG9zLkFjdHVhbE5vZGUucGFyZW50RWxlbWVudC5pbnNlcnRCZWZvcmUobmV3VGV4dE5vZGUsIHBvcy5BY3R1YWxOb2RlKTtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5FbXB0eU5vZGU6XHJcbiAgICAgICAgdGV4dEFsbG93ZWQgPSBuZXcgWG1sRWRpdFJ1bGVDaGVja1RleHRJbnNlcnQoeG1sU2NoZW1hLnhzZE5vZGVzKS5pc1RleHRBbGxvd2VkQXRUaGlzQ3Vyc29yUG9zKHBvcyk7XHJcbiAgICAgICAgaWYgKHRleHRBbGxvd2VkID09PSB0cnVlKSB7XHJcbiAgICAgICAgICBjb25zdCBuZXdUZXh0Tm9kZSA9IHBvcy5BY3R1YWxOb2RlLm93bmVyRG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUodmFsdWUpO1xyXG4gICAgICAgICAgcG9zLkFjdHVhbE5vZGUuYXBwZW5kQ2hpbGQobmV3VGV4dE5vZGUpO1xyXG4gICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbnNpZGVUZXh0Tm9kZTpcclxuICAgICAgICBjb25zdCB0ZXh0ID0gcG9zLkFjdHVhbE5vZGUudGV4dENvbnRlbnQ7XHJcbiAgICAgICAgcG9zLkFjdHVhbE5vZGUudGV4dENvbnRlbnQgPSB0ZXh0LnN1YnN0cigwLCBwb3MuUG9zSW5UZXh0bm9kZSkgKyB2YWx1ZSArIHRleHQuc3Vic3RyKHBvcy5Qb3NJblRleHRub2RlLCB0ZXh0Lmxlbmd0aCk7XHJcbiAgICAgICAgcG9zLlNldEN1cnNvcihwb3MuQWN0dWFsTm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvckluc2lkZVRleHROb2RlLCBwb3MuUG9zSW5UZXh0bm9kZSArIDEpO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFN0cmluZy5Gb3JtYXQoXCJYbWxFZGl0SW5zZXJ0Lmluc2VydDogdW5rbm93biBDdXJzb3JQb3MgICR7cG9zLmdldERlYnVnRGVzY3JpcHRpb24oKX1gKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc3RhdGljIGlzVGV4dEFsbG93ZWRJblBhcmVudE5vZGUocG9zOiBYbWxDdXJzb3JQb3MsIHhtbFNjaGVtYTogWG1sU2NoZW1hKTogYm9vbGVhbiB7XHJcbiAgICBjb25zdCBwYXJlbnROb2RlID0gcG9zLkFjdHVhbE5vZGUucGFyZW50RWxlbWVudDtcclxuICAgIGNvbnN0IHBhcmVudEN1cnNvclBvcyA9IHBvcy5jbG9uZSgpO1xyXG4gICAgcGFyZW50Q3Vyc29yUG9zLlNldEN1cnNvcihwYXJlbnROb2RlLCBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5FbXB0eU5vZGUpO1xyXG4gICAgcmV0dXJuIG5ldyBYbWxFZGl0UnVsZUNoZWNrVGV4dEluc2VydCh4bWxTY2hlbWEueHNkTm9kZXMpLmlzVGV4dEFsbG93ZWRBdFRoaXNDdXJzb3JQb3MocGFyZW50Q3Vyc29yUG9zKTtcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBYbWxSdWxlRWxlbWVudCB9IGZyb20gJy4veG1sLXJ1bGVzLWNoZWNrL3htbFJ1bGVFbGVtZW50LmNsYXNzJztcclxuaW1wb3J0IHsgWG1sRWRpdG9yQ29uZmlnIH0gZnJvbSAnLi94bWxFZGl0b3JDb25maWcnO1xyXG5pbXBvcnQgeyBYbWxFZGl0b3JEZWJ1Z2dlciB9IGZyb20gJy4veG1sRWRpdG9yRGVidWdnZXInO1xyXG5pbXBvcnQgeyBYbWxDdXJzb3JQb3NNb3ZlciB9IGZyb20gJy4vY3Vyc29yL3htbEN1cnNvclBvc01vdmVyLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sQ3Vyc29yIH0gZnJvbSAnLi9jdXJzb3IveG1sQ3Vyc29yLmNsYXNzJztcclxuaW1wb3J0IHsgT25EZXN0cm95IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFhtbEN1cnNvclBvc1NldHRlciB9IGZyb20gJy4vY3Vyc29yL3htbEN1cnNvclBvc1NldHRlci5jbGFzcyc7XHJcbmltcG9ydCB7IERvbUR1bW15Tm9kZU1hbmFnZXIgfSBmcm9tICcuL2R1bW15Tm9kZXMvZG9tRHVtbXlOb2RlTWFuYWdlci5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbERvbUNsZWFuZXIgfSBmcm9tICcuL3htbC1lZGl0aW5nL3htbERvbUNsZWFuZXIuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWxFZGl0RGVsZXRlIH0gZnJvbSAnLi94bWwtZWRpdGluZy94bWxFZGl0RGVsZXRlY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWwyaHRtbCB9IGZyb20gJy4veG1sLWh0bWwtY29udmVydGVyL3htbDJodG1sLmNsYXNzJztcclxuaW1wb3J0IHsgVG91Y2hTZXF1ZW5jZSB9IGZyb20gJ3NlbGVuaXVtLXdlYmRyaXZlcic7XHJcbmltcG9ydCB7IFhtbEVkaXRJbnNlcnQgfSBmcm9tICcuL3htbC1lZGl0aW5nL3htbEVkaXRJbnNlcnQuY2xhc3MnO1xyXG5pbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJ3V0aWwnO1xyXG5cclxuZXhwb3J0IGNsYXNzIFhtbEVkaXRvckNvbnRleHQgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xyXG4gIHB1YmxpYyBkZWJ1Z1NlcnZpY2U6IFhtbEVkaXRvckRlYnVnZ2VyO1xyXG4gIHB1YmxpYyBjb25maWc6IFhtbEVkaXRvckNvbmZpZztcclxuXHJcbiAgYWN0dWFsQ3Vyc29yQ2hhbmdlZDogU3ViamVjdDxYbWxDdXJzb3I+O1xyXG4gIGFjdHVhbEN1cnNvciA9IG5ldyBYbWxDdXJzb3IoKTtcclxuICBkdW1teU5vZGVNYW5hZ2VyID0gbmV3IERvbUR1bW15Tm9kZU1hbmFnZXIoKTtcclxuXHJcbiAgc2F2ZWRTZWxlY3Rpb246IFJhbmdlIHwgbnVsbDtcclxuICBzZWxlY3RlZFRleHQ6IHN0cmluZztcclxuXHJcbiAga2V5Q3RybElzRG93bjogYm9vbGVhbjtcclxuICBrZXlTaGlmdElzRG93bjogYm9vbGVhbjtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfZG9jdW1lbnQ6IERvY3VtZW50KSB7XHJcbiAgICB0aGlzLmFjdHVhbEN1cnNvckNoYW5nZWQgPSBuZXcgU3ViamVjdDxYbWxDdXJzb3I+KCk7XHJcbiAgICB0aGlzLmRlYnVnU2VydmljZSA9IG5ldyBYbWxFZGl0b3JEZWJ1Z2dlcigpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmFjdHVhbEN1cnNvckNoYW5nZWQudW5zdWJzY3JpYmUoKTtcclxuICB9XHJcblxyXG4gIHNldEN1cnNvclBvcyhjdXJzb3JQb3M6IFhtbEN1cnNvcikge1xyXG4gICAgdGhpcy5hY3R1YWxDdXJzb3IgPSBjdXJzb3JQb3M7XHJcbiAgICB0aGlzLmFjdHVhbEN1cnNvckNoYW5nZWQubmV4dChjdXJzb3JQb3MpO1xyXG4gICAgdGhpcy5kZWJ1Z1NlcnZpY2Uuc2V0QWN0dWFsQ3Vyc29yUG9zKGN1cnNvclBvcyk7XHJcbiAgfVxyXG5cclxuICAvLyAvKipcclxuICAvLyAgICogRXhlY3V0ZWQgY29tbWFuZCBmcm9tIGVkaXRvciBoZWFkZXIgYnV0dG9uc1xyXG4gIC8vICAgKiBAcGFyYW0gY29tbWFuZCBzdHJpbmcgZnJvbSB0cmlnZ2VyQ29tbWFuZFxyXG4gIC8vICAgKi9cclxuICAvLyBleGVjdXRlQ29tbWFuZChjb21tYW5kOiBzdHJpbmcpIHtcclxuICAvLyAgIGlmIChjb21tYW5kICE9PSAnJykge1xyXG4gIC8vICAgICB0aGlzLmNvbW1hbmRlci5leGVjdXRlQ29tbWFuZChjb21tYW5kKTtcclxuICAvLyAgICAgdGhpcy5leGVjKCk7XHJcbiAgLy8gICB9XHJcbiAgLy8gICB0aGlzLm9uRWRpdG9yRm9jdXMoKTtcclxuICAvLyAgIGNvbnN0IGNsZWFuVXBGaXJzdCA9IGZhbHNlO1xyXG4gIC8vICAgdGhpcy5kb21EdW1teU5vZGVNYW5hZ2VyLlVwZGF0ZUR1bW15Tm9kZXModGhpcy54bWxEb2N1bWVudFJvb3ROb2RlLCBjbGVhblVwRmlyc3QpO1xyXG4gIC8vICAgcmV0dXJuO1xyXG4gIC8vIH1cclxuXHJcbiAgbW91c2VVcChtb3VzZUV2ZW50OiBNb3VzZUV2ZW50KSB7XHJcbiAgICBpZiAod2luZG93LmdldFNlbGVjdGlvbikge1xyXG4gICAgICBsZXQgdXNlclNlbGVjdGlvbjogU2VsZWN0aW9uO1xyXG4gICAgICB1c2VyU2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xyXG4gICAgICBYbWxDdXJzb3JQb3NTZXR0ZXIuc2V0RnJvbVNlbGVjdGlvbih0aGlzLmFjdHVhbEN1cnNvci5TdGFydFBvcywgdXNlclNlbGVjdGlvbi5hbmNob3JOb2RlLCB1c2VyU2VsZWN0aW9uLmFuY2hvck9mZnNldCwgdGhpcy5kZWJ1Z1NlcnZpY2UpO1xyXG4gICAgICBYbWxDdXJzb3JQb3NTZXR0ZXIuc2V0RnJvbVNlbGVjdGlvbih0aGlzLmFjdHVhbEN1cnNvci5FbmRQb3MsIHVzZXJTZWxlY3Rpb24uZm9jdXNOb2RlLCB1c2VyU2VsZWN0aW9uLmZvY3VzT2Zmc2V0LCB0aGlzLmRlYnVnU2VydmljZSk7XHJcbiAgICAgIHRoaXMuc2V0Q3Vyc29yUG9zKHRoaXMuYWN0dWFsQ3Vyc29yKTtcclxuICAgICAgdGhpcy5hY3R1YWxDdXJzb3Iuc29ydFN0YXJ0QW5kRW5kKCk7XHJcbiAgICAgIHRoaXMuYWN0dWFsQ3Vyc29yLnNob3coKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgY2FuJ3QgZ2V0IHdpbmRvdy5nZXRTZWxlY3Rpb24sIHRhcmdldD0ke0pTT04uc3RyaW5naWZ5KG1vdXNlRXZlbnQudGFyZ2V0KX1gKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGtleURvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiBib29sZWFuIHtcclxuICAgIGNvbnNvbGUubG9nKCdrZXlkb3duISBrZXk6JyArIGV2ZW50LmtleSArICcgLyBjb2RlOicgKyBldmVudC5jb2RlKTtcclxuXHJcbiAgICBzd2l0Y2ggKGV2ZW50LmtleSkge1xyXG4gICAgICBjYXNlICdDb250cm9sJzpcclxuICAgICAgICB0aGlzLmtleUN0cmxJc0Rvd24gPSB0cnVlO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSAnU2hpZnQnOlxyXG4gICAgICAgIHRoaXMua2V5U2hpZnRJc0Rvd24gPSB0cnVlO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSAnYyc6XHJcbiAgICAgICAgaWYgKHRoaXMua2V5Q3RybElzRG93bikge1xyXG4gICAgICAgICAgLy8gQ29weVxyXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBpZiAodGhpcy5pbnNlcnRUZXh0KCdjJykpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgJ0Fycm93VXAnOlxyXG4gICAgICBjYXNlICdBcnJvd0Rvd24nOlxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG5cclxuICAgICAgY2FzZSAnQXJyb3dSaWdodCc6XHJcbiAgICAgICAgaWYgKHRoaXMua2V5U2hpZnRJc0Rvd24pIHtcclxuICAgICAgICAgIFhtbEN1cnNvclBvc01vdmVyLm1vdmVSaWdodCh0aGlzLmFjdHVhbEN1cnNvci5FbmRQb3MsIHRoaXMuYWN0dWFsQ3Vyc29yLnhtbERvY3VtZW50Um9vdE5vZGUsIHRoaXMuY29uZmlnLnJ1bGVzKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgWG1sQ3Vyc29yUG9zTW92ZXIubW92ZVJpZ2h0KHRoaXMuYWN0dWFsQ3Vyc29yLkVuZFBvcywgdGhpcy5hY3R1YWxDdXJzb3IueG1sRG9jdW1lbnRSb290Tm9kZSwgdGhpcy5jb25maWcucnVsZXMpO1xyXG4gICAgICAgICAgdGhpcy5hY3R1YWxDdXJzb3IuU3RhcnRQb3MuU2V0Q3Vyc29yKHRoaXMuYWN0dWFsQ3Vyc29yLkVuZFBvcy5BY3R1YWxOb2RlLCB0aGlzLmFjdHVhbEN1cnNvci5FbmRQb3MuUG9zQXROb2RlLCB0aGlzLmFjdHVhbEN1cnNvci5FbmRQb3MuUG9zSW5UZXh0bm9kZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuYWN0dWFsQ3Vyc29yLnNvcnRTdGFydEFuZEVuZCgpO1xyXG4gICAgICAgIHRoaXMuYWN0dWFsQ3Vyc29yLnNob3coKTtcclxuICAgICAgICB0aGlzLnNldEN1cnNvclBvcyh0aGlzLmFjdHVhbEN1cnNvcik7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG5cclxuICAgICAgY2FzZSAnQXJyb3dMZWZ0JzpcclxuICAgICAgICBpZiAodGhpcy5rZXlTaGlmdElzRG93bikge1xyXG4gICAgICAgICAgWG1sQ3Vyc29yUG9zTW92ZXIubW92ZUxlZnQodGhpcy5hY3R1YWxDdXJzb3IuRW5kUG9zLCB0aGlzLmFjdHVhbEN1cnNvci54bWxEb2N1bWVudFJvb3ROb2RlLCB0aGlzLmNvbmZpZy5ydWxlcyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIFhtbEN1cnNvclBvc01vdmVyLm1vdmVMZWZ0KHRoaXMuYWN0dWFsQ3Vyc29yLlN0YXJ0UG9zLCB0aGlzLmFjdHVhbEN1cnNvci54bWxEb2N1bWVudFJvb3ROb2RlLCB0aGlzLmNvbmZpZy5ydWxlcyk7XHJcbiAgICAgICAgICB0aGlzLmFjdHVhbEN1cnNvci5FbmRQb3MuU2V0Q3Vyc29yKHRoaXMuYWN0dWFsQ3Vyc29yLlN0YXJ0UG9zLkFjdHVhbE5vZGUsIHRoaXMuYWN0dWFsQ3Vyc29yLlN0YXJ0UG9zLlBvc0F0Tm9kZSwgdGhpcy5hY3R1YWxDdXJzb3IuU3RhcnRQb3MuUG9zSW5UZXh0bm9kZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuYWN0dWFsQ3Vyc29yLnNvcnRTdGFydEFuZEVuZCgpO1xyXG4gICAgICAgIHRoaXMuYWN0dWFsQ3Vyc29yLnNob3coKTtcclxuICAgICAgICB0aGlzLnNldEN1cnNvclBvcyh0aGlzLmFjdHVhbEN1cnNvcik7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG5cclxuICAgICAgY2FzZSAnQmFja3NwYWNlJzpcclxuICAgICAgICBpZiAodGhpcy5hY3R1YWxDdXJzb3IuaXNFbXB0eVNlbGVjdGlvbigpKSB7XHJcbiAgICAgICAgICBYbWxFZGl0RGVsZXRlLmRlbGV0ZUJlZm9yZSh0aGlzLmFjdHVhbEN1cnNvci5TdGFydFBvcywgdGhpcy5hY3R1YWxDdXJzb3IueG1sRG9jdW1lbnRSb290Tm9kZSwgdGhpcy5jb25maWcucnVsZXMpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBYbWxFZGl0RGVsZXRlLmRlbGV0ZVNlbGVjdGlvbih0aGlzLmFjdHVhbEN1cnNvciwgdGhpcy5hY3R1YWxDdXJzb3IueG1sRG9jdW1lbnRSb290Tm9kZSwgdGhpcy5jb25maWcucnVsZXMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmFjdHVhbEN1cnNvci5FbmRQb3MuU2V0Q3Vyc29yKHRoaXMuYWN0dWFsQ3Vyc29yLlN0YXJ0UG9zLkFjdHVhbE5vZGUsIHRoaXMuYWN0dWFsQ3Vyc29yLlN0YXJ0UG9zLlBvc0F0Tm9kZSwgdGhpcy5hY3R1YWxDdXJzb3IuU3RhcnRQb3MuUG9zSW5UZXh0bm9kZSk7XHJcbiAgICAgICAgdGhpcy5jbGVhblVwQW5kVXBkYXRlRHVtbXlFbGVtZW50cygpO1xyXG4gICAgICAgIHRoaXMuYWN0dWFsQ3Vyc29yLnNob3coKTtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgICBjYXNlICdEZWxldGUnOlxyXG4gICAgICAgIGlmICh0aGlzLmFjdHVhbEN1cnNvci5pc0VtcHR5U2VsZWN0aW9uKCkpIHtcclxuICAgICAgICAgIFhtbEVkaXREZWxldGUuZGVsZXRlQWZ0ZXIodGhpcy5hY3R1YWxDdXJzb3IuU3RhcnRQb3MsIHRoaXMuYWN0dWFsQ3Vyc29yLnhtbERvY3VtZW50Um9vdE5vZGUsIHRoaXMuY29uZmlnLnJ1bGVzKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgWG1sRWRpdERlbGV0ZS5kZWxldGVTZWxlY3Rpb24odGhpcy5hY3R1YWxDdXJzb3IsIHRoaXMuYWN0dWFsQ3Vyc29yLnhtbERvY3VtZW50Um9vdE5vZGUsIHRoaXMuY29uZmlnLnJ1bGVzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5jbGVhblVwQW5kVXBkYXRlRHVtbXlFbGVtZW50cygpO1xyXG4gICAgICAgIHRoaXMuYWN0dWFsQ3Vyc29yLnNob3coKTtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgICBjYXNlICdFbnRlcic6XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICBjb25zdCB0ZXh0SW5zZXJ0ID0gZXZlbnQua2V5O1xyXG4gICAgICAgIGlmICh0aGlzLmluc2VydFRleHQodGV4dEluc2VydCkpIHtcclxuICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICBrZXlVcChldmVudDogS2V5Ym9hcmRFdmVudCk6IGJvb2xlYW4ge1xyXG4gICAgc3dpdGNoIChldmVudC5rZXkpIHtcclxuICAgICAgY2FzZSAnQ29udHJvbCc6XHJcbiAgICAgICAgdGhpcy5rZXlDdHJsSXNEb3duID0gZmFsc2U7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgJ1NoaWZ0JzpcclxuICAgICAgICB0aGlzLmFjdHVhbEN1cnNvci5zb3J0U3RhcnRBbmRFbmQoKTtcclxuICAgICAgICB0aGlzLmtleVNoaWZ0SXNEb3duID0gZmFsc2U7XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBjYXNlICdBcnJvd0xlZnQnOlxyXG4gICAgICBjYXNlICdBcnJvd1JpZ2h0JzpcclxuICAgICAgICB0aGlzLmFjdHVhbEN1cnNvci5zaG93KCk7XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBjYXNlICdBcnJvd1VwJzpcclxuICAgICAgY2FzZSAnQXJyb3dEb3duJzpcclxuICAgICAgY2FzZSAnQmFja3NwYWNlJzpcclxuICAgICAgY2FzZSAnRGVsZXRlJzpcclxuICAgICAgY2FzZSAnRW50ZXInOlxyXG4gICAgICBjYXNlICdDb250cm9sJzpcclxuICAgICAgY2FzZSAnU2hpZnQnOlxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgcGFzdGVkKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgYWxlcnQoJ3Bhc3RlZDogJyArIHRleHQpO1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgY29waWVkKCk6IGJvb2xlYW4ge1xyXG4gICAgYWxlcnQoJ2NvcGllZCcpO1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgaW5zZXJ0VGV4dCh2YWx1ZTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodmFsdWUgPT09ICcnIHx8IHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGluc2VydGVkID0gZmFsc2U7XHJcblxyXG4gICAgaWYgKHRoaXMuYWN0dWFsQ3Vyc29yLmlzRW1wdHlTZWxlY3Rpb24oKSkge1xyXG4gICAgICBpbnNlcnRlZCA9IFhtbEVkaXRJbnNlcnQuaW5zZXJ0VGV4dCh0aGlzLmFjdHVhbEN1cnNvci5FbmRQb3MsIHZhbHVlLCB0aGlzLmFjdHVhbEN1cnNvci54bWxEb2N1bWVudFJvb3ROb2RlLCB0aGlzLmNvbmZpZy5ydWxlcywgdGhpcy5jb25maWcueG1sU2NoZW1hKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGluc2VydGVkID0gWG1sRWRpdEluc2VydC5yZXBsYWNlV2l0aFRleHQodGhpcy5hY3R1YWxDdXJzb3IsIHZhbHVlLCB0aGlzLmFjdHVhbEN1cnNvci54bWxEb2N1bWVudFJvb3ROb2RlLCB0aGlzLmNvbmZpZy5ydWxlcywgdGhpcy5jb25maWcueG1sU2NoZW1hKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoaW5zZXJ0ZWQpIHtcclxuICAgICAgLy8gY2hhcmFjdGVyIGluc2VydGVkIC0+IG1vdmUgY3Vyc29yIHJpZ2h0XHJcbiAgICAgIC8vIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB2YWx1ZS5sZW5ndGg7IGluZGV4KyspIHtcclxuICAgICAgLy8gICBYbWxDdXJzb3JQb3NNb3Zlci5tb3ZlUmlnaHQodGhpcy5hY3R1YWxDdXJzb3IuRW5kUG9zLCB0aGlzLmFjdHVhbEN1cnNvci54bWxEb2N1bWVudFJvb3ROb2RlLCB0aGlzLmNvbmZpZy5ydWxlcyk7XHJcbiAgICAgIC8vIH1cclxuICAgICAgdGhpcy5hY3R1YWxDdXJzb3IuU3RhcnRQb3MuU2V0Q3Vyc29yKHRoaXMuYWN0dWFsQ3Vyc29yLkVuZFBvcy5BY3R1YWxOb2RlLCB0aGlzLmFjdHVhbEN1cnNvci5FbmRQb3MuUG9zQXROb2RlLCB0aGlzLmFjdHVhbEN1cnNvci5FbmRQb3MuUG9zSW5UZXh0bm9kZSk7XHJcbiAgICAgIHRoaXMuY2xlYW5VcEFuZFVwZGF0ZUR1bW15RWxlbWVudHMoKTtcclxuICAgICAgdGhpcy5hY3R1YWxDdXJzb3Iuc2hvdygpO1xyXG4gICAgICBjb25zb2xlLndhcm4oJ3RleHQgaW5zZXJ0ZWQhJyk7XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc29sZS53YXJuKCd0ZXh0IE5PVCBpbnNlcnRlZCEnKTtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIGluc2VydHMgYSBuZXcgZWxlbWVudCBhdCB0aGUgYWN0dWFsIGN1cnNvciBwb3MgKi9cclxuICBpbnNlcnRFbGVtZW50KGVsZW1lbnQ6IFhtbFJ1bGVFbGVtZW50KSB7XHJcbiAgICBjb25zdCBodG1sID0gbmV3IFhtbDJodG1sKHRoaXMuY29uZmlnLnJ1bGVzKS5jcmVhdGVOZXdFbGVtZW50SHRtbChlbGVtZW50KTtcclxuICAgIHRoaXMuZG9tSW5zZXJ0SHRtbChodG1sKTtcclxuICAgIHRoaXMuY2xlYW5VcEFuZFVwZGF0ZUR1bW15RWxlbWVudHMoKTtcclxuICAgIC8vIHRoaXMuYWN0dWFsQ3Vyc29yLnNob3coKTtcclxuICAgIGNvbnNvbGUud2FybignZWxlbWVudCBpbnNlcnRlZCEnKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZSByYXcgSFRNTFxyXG4gICAqIEBwYXJhbSBodG1sIEhUTUwgc3RyaW5nXHJcbiAgICovXHJcbiAgcHVibGljIGRvbUluc2VydEh0bWwoaHRtbDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAoZG9jdW1lbnQuZ2V0U2VsZWN0aW9uKSB7XHJcbiAgICAgIGNvbnN0IHJhbmdlID0gZG9jdW1lbnQuZ2V0U2VsZWN0aW9uKCkuZ2V0UmFuZ2VBdCgwKTtcclxuICAgICAgcmFuZ2UuaW5zZXJ0Tm9kZShyYW5nZS5jcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQoaHRtbCkpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdkb2N1bWVudC5nZXRTZWxlY3Rpb24gbm90IGRlZmluZWQhJyk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmNsZWFuVXBBbmRVcGRhdGVEdW1teUVsZW1lbnRzKCk7XHJcbiAgICB0aGlzLmFjdHVhbEN1cnNvci5zaG93KCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBzYXZlIHNlbGVjdGlvbiB3aGVuIHRoZSBlZGl0b3IgaXMgZm9jdXNzZWQgb3V0XHJcbiAgICovXHJcbiAgc2F2ZVNlbGVjdGlvbigpOiBhbnkge1xyXG4gICAgaWYgKHdpbmRvdy5nZXRTZWxlY3Rpb24pIHtcclxuICAgICAgY29uc3Qgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xyXG4gICAgICBpZiAoc2VsLmdldFJhbmdlQXQgJiYgc2VsLnJhbmdlQ291bnQpIHtcclxuICAgICAgICB0aGlzLnNhdmVkU2VsZWN0aW9uID0gc2VsLmdldFJhbmdlQXQoMCk7XHJcbiAgICAgICAgdGhpcy5zZWxlY3RlZFRleHQgPSBzZWwudG9TdHJpbmcoKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIGlmICh0aGlzLl9kb2N1bWVudC5nZXRTZWxlY3Rpb24gJiYgdGhpcy5fZG9jdW1lbnQuY3JlYXRlUmFuZ2UpIHtcclxuICAgICAgdGhpcy5zYXZlZFNlbGVjdGlvbiA9IGRvY3VtZW50LmNyZWF0ZVJhbmdlKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnNhdmVkU2VsZWN0aW9uID0gbnVsbDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIHJlc3RvcmUgc2VsZWN0aW9uIHdoZW4gdGhlIGVkaXRvciBpcyBmb2N1c3NlZCBpblxyXG4gICAqL1xyXG4gIHJlc3RvcmVTZWxlY3Rpb24oKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5zYXZlZFNlbGVjdGlvbikge1xyXG4gICAgICBpZiAod2luZG93LmdldFNlbGVjdGlvbikge1xyXG4gICAgICAgIGNvbnN0IHNlbCA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcclxuICAgICAgICBzZWwucmVtb3ZlQWxsUmFuZ2VzKCk7XHJcbiAgICAgICAgc2VsLmFkZFJhbmdlKHRoaXMuc2F2ZWRTZWxlY3Rpb24pO1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX2RvY3VtZW50LmdldFNlbGVjdGlvbiAvKiYmIHRoaXMuc2F2ZWRTZWxlY3Rpb24uc2VsZWN0Ki8pIHtcclxuICAgICAgICAvLyB0aGlzLnNhdmVkU2VsZWN0aW9uLnNlbGVjdCgpO1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjbGVhblVwQW5kVXBkYXRlRHVtbXlFbGVtZW50cygpIHtcclxuICAgIHRoaXMuZHVtbXlOb2RlTWFuYWdlci5SZW1vdmVBbGxEdW1teU5vZGVzKHRoaXMuYWN0dWFsQ3Vyc29yLnhtbERvY3VtZW50Um9vdE5vZGUpO1xyXG4gICAgWG1sRG9tQ2xlYW5lci5jbGVhblVwKHRoaXMuYWN0dWFsQ3Vyc29yLnhtbERvY3VtZW50Um9vdE5vZGUsIHRoaXMuYWN0dWFsQ3Vyc29yKTtcclxuICAgIHRoaXMuZHVtbXlOb2RlTWFuYWdlci5VcGRhdGVEdW1teU5vZGVzKHRoaXMuYWN0dWFsQ3Vyc29yLnhtbERvY3VtZW50Um9vdE5vZGUpO1xyXG4gICAgdGhpcy5hY3R1YWxDdXJzb3Iuc29ydFN0YXJ0QW5kRW5kKCk7XHJcbiAgfVxyXG5cclxuICAvLyAvKiogY2hlY2sgYW55IHNsZWN0aW9uIGlzIG1hZGUgb3Igbm90ICovXHJcbiAgLy8gcHJpdmF0ZSBjaGVja1NlbGVjdGlvbigpOiBhbnkge1xyXG4gIC8vICAgY29uc3Qgc2xlY3RlZFRleHQgPSB0aGlzLnNhdmVkU2VsZWN0aW9uLnRvU3RyaW5nKCk7XHJcblxyXG4gIC8vICAgaWYgKHNsZWN0ZWRUZXh0Lmxlbmd0aCA9PT0gMCkge1xyXG4gIC8vICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIFNlbGVjdGlvbiBNYWRlJyk7XHJcbiAgLy8gICB9XHJcblxyXG4gIC8vICAgcmV0dXJuIHRydWU7XHJcbiAgLy8gfVxyXG5cclxuICAvLyBzZXREZWZhdWx0UGFyYWdyYXBoU2VwYXJhdG9yKHNlcGFyYXRvcjogc3RyaW5nKSB7XHJcbiAgLy8gICB0aGlzLl9kb2N1bWVudC5leGVjQ29tbWFuZCgnZGVmYXVsdFBhcmFncmFwaFNlcGFyYXRvcicsIGZhbHNlLCBzZXBhcmF0b3IpO1xyXG4gIC8vIH1cclxufVxyXG4iLCJpbXBvcnQgeyBJbmplY3RhYmxlLCBJbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBYbWxFZGl0b3JDb250ZXh0IH0gZnJvbSAnLi9jb2RlL3htbEVkaXRvckNvbnRleHQuY2xhc3MnO1xyXG5cclxuLyoqIEBkeW5hbWljICovXHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCdcclxufSlcclxuZXhwb3J0IGNsYXNzIEFuZ3VsYXJYbWxFZGl0b3JTZXJ2aWNlIHtcclxuICBwcml2YXRlIGNvbnRleHRzID0gbmV3IE1hcDxzdHJpbmcsIFhtbEVkaXRvckNvbnRleHQ+KCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKEBJbmplY3QoRE9DVU1FTlQpIHByaXZhdGUgX2RvY3VtZW50OiBEb2N1bWVudCkge31cclxuXHJcbiAgZ2V0TmV3RWRpdG9yQ29udGV4dElkKCk6IHN0cmluZyB7XHJcbiAgICBsZXQgbm8gPSAwO1xyXG4gICAgd2hpbGUgKHRoaXMuY29udGV4dHMuaGFzKG5vLnRvU3RyaW5nKCkpKSB7XHJcbiAgICAgIG5vKys7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbm8udG9TdHJpbmcoKTtcclxuICB9XHJcblxyXG4gIGdldEVkaXRvckNvbnRleHQoY29udGV4dElkOiBzdHJpbmcpOiBYbWxFZGl0b3JDb250ZXh0IHtcclxuICAgIGxldCBjb250ZXh0ID0gdGhpcy5jb250ZXh0cy5nZXQoY29udGV4dElkKTtcclxuICAgIGlmIChjb250ZXh0ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgY29udGV4dCA9IG5ldyBYbWxFZGl0b3JDb250ZXh0KHRoaXMuX2RvY3VtZW50KTtcclxuICAgICAgdGhpcy5jb250ZXh0cy5zZXQoY29udGV4dElkLCBjb250ZXh0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBjb250ZXh0O1xyXG4gIH1cclxuXHJcbiAgZGlzcG9zZUVkaXRvckNvbnRleHQoY29udGV4dElkOiBzdHJpbmcpIHtcclxuICAgIHRoaXMuY29udGV4dHMuZGVsZXRlKGNvbnRleHRJZCk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IFhtbFJ1bGVzIH0gZnJvbSAnLi4veG1sLXJ1bGVzLWNoZWNrL3htbFJ1bGVzLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sMmh0bWwgfSBmcm9tICcuL3htbDJodG1sLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sVG9vbGJveCB9IGZyb20gJy4uL3htbFRvb2xib3guY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWwyaHRtbEF0dHJpYnV0ZVdvcmtlciB9IGZyb20gJy4veG1sMmh0bWxBdHRyaWJ1dGVXb3JrZXIuY2xhc3MnO1xyXG5pbXBvcnQgeyBEb21EdW1teU5vZGVNYW5hZ2VyIH0gZnJvbSAnLi4vZHVtbXlOb2Rlcy9kb21EdW1teU5vZGVNYW5hZ2VyLmNsYXNzJztcclxuXHJcbmV4cG9ydCBjbGFzcyBIdG1sMnhtbCB7XHJcbiAgcHJpdmF0ZSBhdHRyaWJ1dGVXb3JrZXI6IFhtbDJodG1sQXR0cmlidXRlV29ya2VyO1xyXG5cclxuICBjb25zdHJ1Y3RvcihwdWJsaWMgcnVsZXM6IFhtbFJ1bGVzKSB7XHJcbiAgICB0aGlzLmF0dHJpYnV0ZVdvcmtlciA9IG5ldyBYbWwyaHRtbEF0dHJpYnV0ZVdvcmtlcihydWxlcyk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgVG9YbWwoaHRtbDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGlmIChodG1sID09PSAnJykge1xyXG4gICAgICByZXR1cm4gJyc7XHJcbiAgICB9XHJcbiAgICAvLyBodG1sID0gaHRtbC5yZXBsYWNlKCdcXHQnLCAnJyk7XHJcbiAgICAvLyBodG1sID0gaHRtbC5yZXBsYWNlKCdcXHInLCAnJyk7XHJcbiAgICAvLyBodG1sID0gaHRtbC5yZXBsYWNlKCdcXG4nLCAnJyk7XHJcblxyXG4gICAgY29uc3QgY2xlYW5IdG1sID0gdGhpcy5DbGVhblVwSHRtbEJlZm9yZUNvbnZlcnQyWG1sKGh0bWwpO1xyXG4gICAgY29uc3QgZG9tcGFyc2VyID0gbmV3IERPTVBhcnNlcigpO1xyXG4gICAgY29uc3QgZG9tZG9jID0gZG9tcGFyc2VyLnBhcnNlRnJvbVN0cmluZyhjbGVhbkh0bWwsICd0ZXh0L3htbCcpO1xyXG4gICAgY29uc3QgdGFyZ2V0RG9jdW1lbnQgPSBuZXcgRG9jdW1lbnQoKTtcclxuICAgIGlmIChkb21kb2MuZG9jdW1lbnRFbGVtZW50ID09PSBudWxsKSB7XHJcbiAgICAgIHJldHVybiAnJztcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBib2R5ID0gdGhpcy5HZXRYbWxFbGVtZW50RnJvbUh0bWxFbGVtZW50KGRvbWRvYy5kb2N1bWVudEVsZW1lbnQsIHRhcmdldERvY3VtZW50KTtcclxuICAgIGlmIChib2R5ICYmIGJvZHkubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XHJcbiAgICAgIGNvbnN0IHhtbCA9IChib2R5IGFzIEVsZW1lbnQpLm91dGVySFRNTDtcclxuICAgICAgcmV0dXJuIHhtbDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgcm9vdCBub2RlICR7WG1sVG9vbGJveC5HZXROb2RlRGVidWdDb250ZXh0KGJvZHkpfSBpcyBubyBlbGVtZW50YCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIENsZWFuVXBIdG1sQmVmb3JlQ29udmVydDJYbWwoaHRtbDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGRvbXBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcclxuICAgIGNvbnN0IGRvbWRvYyA9IGRvbXBhcnNlci5wYXJzZUZyb21TdHJpbmcoaHRtbCwgJ3RleHQvaHRtbCcpO1xyXG4gICAgbmV3IERvbUR1bW15Tm9kZU1hbmFnZXIoKS5SZW1vdmVBbGxEdW1teU5vZGVzKGRvbWRvYy5kb2N1bWVudEVsZW1lbnQpOyAvLyByZW1vdmUgYWxsIGR1bW15IG5vZGVzXHJcbiAgICBjb25zdCBjbGVhbkh0bWwgPSBkb21kb2MuYm9keS5pbm5lckhUTUw7XHJcbiAgICByZXR1cm4gY2xlYW5IdG1sO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBHZXRYbWxFbGVtZW50RnJvbUh0bWxFbGVtZW50KG5vZGU6IE5vZGUsIHRhcmdldERvY3VtZW50OiBEb2N1bWVudCk6IE5vZGUge1xyXG4gICAgc3dpdGNoIChub2RlLm5vZGVUeXBlKSB7XHJcbiAgICAgIGNhc2UgTm9kZS5FTEVNRU5UX05PREU6IC8vIGVsZW1lbnQgbm9kZVxyXG4gICAgICAgIGNvbnN0IGFzRWxlbWVudCA9IG5vZGUgYXMgRWxlbWVudDtcclxuICAgICAgICBjb25zdCB0YWdOYW1lID0gWG1sMmh0bWwuZ2V0VGFnTmFtZUZyb21Ob2RlKG5vZGUpO1xyXG5cclxuICAgICAgICBpZiAoIXRhZ05hbWUgfHwgdGFnTmFtZSA9PT0gJycpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgbm8gdGFnbmFtZSBpbiAke1htbFRvb2xib3guR2V0Tm9kZURlYnVnQ29udGV4dChub2RlKX1gKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGNyZWF0ZSBlbGVtZW50IG5vZGVcclxuICAgICAgICBjb25zdCBuZXdFbGVtZW50ID0gdGFyZ2V0RG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcclxuXHJcbiAgICAgICAgLy8gYXBwZW5kIGNoaWxkIGVsZW1lbnRzIHJlY3Vyc2l2ZVxyXG4gICAgICAgIGNvbnN0IGNoaWxkcmVuID0gYXNFbGVtZW50LmNoaWxkTm9kZXM7XHJcbiAgICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA9PT0gMCAmJiAhYXNFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhYbWwyaHRtbC5Ob0Nsb3NpbmdUYWdDbGFzc05hbWUpKSB7XHJcbiAgICAgICAgICBuZXdFbGVtZW50LmFwcGVuZENoaWxkKHRhcmdldERvY3VtZW50LmNyZWF0ZVRleHROb2RlKCcnKSk7IC8vIHRvIHByZXZlbnQgbm9uIGNsb3NpbmcgdGFnc1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGNoaWxkQXNIdG1sID0gdGhpcy5HZXRYbWxFbGVtZW50RnJvbUh0bWxFbGVtZW50KGNoaWxkcmVuW2ldLCB0YXJnZXREb2N1bWVudCk7XHJcbiAgICAgICAgICAgIGlmIChjaGlsZEFzSHRtbCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgbmV3RWxlbWVudC5hcHBlbmRDaGlsZChjaGlsZEFzSHRtbCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIC8vIGluc2VydCBhdHRyaWJ1dGVzXHJcbiAgICAgICAgdGhpcy5hdHRyaWJ1dGVXb3JrZXIud3JpdGVBbGxIdG1sQXR0cmlidXRlc1RvWG1sKGFzRWxlbWVudCwgbmV3RWxlbWVudCk7XHJcblxyXG4gICAgICAgIHJldHVybiBuZXdFbGVtZW50O1xyXG5cclxuICAgICAgY2FzZSBOb2RlLlRFWFRfTk9ERTogLy8gdGV4dCBub2RlXHJcbiAgICAgICAgY29uc3QgY29udGVudCA9IChub2RlIGFzIEVsZW1lbnQpLnRleHRDb250ZW50O1xyXG4gICAgICAgIGlmIChjb250ZW50Lmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgIHJldHVybiB0YXJnZXREb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShjb250ZW50KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTptYXgtbGluZS1sZW5ndGhcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gaHRtbCBlbGVtZW50IG5vZGVUeXBlICR7bm9kZS5ub2RlVHlwZX0gaW4gdmFsdWU6ICR7WG1sVG9vbGJveC5HZXROb2RlRGVidWdDb250ZXh0KG5vZGUpfWApO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IFhtbEVkaXRvckNvbmZpZyB9IGZyb20gJy4vY29kZS94bWxFZGl0b3JDb25maWcnO1xyXG5pbXBvcnQgeyBYTUxDdXJzb3JQb3NpdGlvbnMgfSBmcm9tICcuL2NvZGUvY3Vyc29yL3htbEN1cnNvclBvcy5jbGFzcyc7XHJcbmltcG9ydCB7IERvbUR1bW15Tm9kZU1hbmFnZXIgfSBmcm9tICcuL2NvZGUvZHVtbXlOb2Rlcy9kb21EdW1teU5vZGVNYW5hZ2VyLmNsYXNzJztcclxuaW1wb3J0IHsgQ29tcG9uZW50LCBPbkNoYW5nZXMsIElucHV0LCBWaWV3Q2hpbGQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBSZW5kZXJlcjIsIGZvcndhcmRSZWYsIFZpZXdFbmNhcHN1bGF0aW9uLCBPbkRlc3Ryb3ksIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQW5ndWxhclhtbEVkaXRvclNlcnZpY2UgfSBmcm9tICcuL2FuZ3VsYXIteG1sLWVkaXRvci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgWG1sRWRpdG9yQ29udGV4dCB9IGZyb20gJy4vY29kZS94bWxFZGl0b3JDb250ZXh0LmNsYXNzJztcclxuaW1wb3J0IHsgWG1sMmh0bWwgfSBmcm9tICcuL2NvZGUveG1sLWh0bWwtY29udmVydGVyL3htbDJodG1sLmNsYXNzJztcclxuaW1wb3J0IHsgSHRtbDJ4bWwgfSBmcm9tICcuL2NvZGUveG1sLWh0bWwtY29udmVydGVyL2h0bWwyeG1sLmNsYXNzJztcclxuaW1wb3J0IHsgRGVidWdDb250ZXh0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9zcmMvdmlldyc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2F4ZWQtZWRpdG9yJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vYW5ndWxhci14bWwtZWRpdG9yLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9hbmd1bGFyLXhtbC1lZGl0b3IuY29tcG9uZW50LnNjc3MnXSxcclxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLCAvLyB0byBwcmV2ZW50IHRoZSBzY3NzIHRvIHJlbmFtZSB0aGUgY2xhc3MgbmFtZXMgYW5kIG5vdCBtYXRjaCB0aGUgbmV3IGdlbmVyYXRlZCB4bWwgZG9tXHJcbiAgcHJvdmlkZXJzOiBbXHJcbiAgICB7XHJcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxyXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBBbmd1bGFyWG1sRWRpdG9yQ29tcG9uZW50KSxcclxuICAgICAgbXVsdGk6IHRydWVcclxuICAgIH1cclxuICBdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBBbmd1bGFyWG1sRWRpdG9yQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcclxuICBwcml2YXRlIGVkaXRvckNvbnRleHQ6IFhtbEVkaXRvckNvbnRleHQ7XHJcbiAgaXNEZWJ1Z01vZGUgPSBmYWxzZTtcclxuXHJcbiAgQElucHV0KCdjb25maWcnKVxyXG4gIGdldCBjb25maWcoKTogWG1sRWRpdG9yQ29uZmlnIHtcclxuICAgIGlmICh0aGlzLmVkaXRvckNvbnRleHQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmVkaXRvckNvbnRleHQuY29uZmlnICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuZWRpdG9yQ29udGV4dCAmJiB0aGlzLmVkaXRvckNvbnRleHQuY29uZmlnO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIEBJbnB1dCgnZWRpdG9yQ29udGV4dElkJylcclxuICBzZXQgZWRpdG9yQ29udGV4dElkKHZhbHVlOiBzdHJpbmcpIHtcclxuICAgIGlmICghdmFsdWUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5lZGl0b3JDb250ZXh0ID0gdGhpcy5lZGl0b3JTZXJ2aWNlLmdldEVkaXRvckNvbnRleHQodmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgQElucHV0KCdkZWJ1Z01vZGUnKVxyXG4gIHNldCBkZWJ1Z01vZGUodmFsdWU6IGJvb2xlYW4pIHtcclxuICAgIHRoaXMuaXNEZWJ1Z01vZGUgPSB2YWx1ZTtcclxuICB9XHJcblxyXG4gIEBWaWV3Q2hpbGQoJ2VkaXRvcicpXHJcbiAgdGV4dEFyZWE6IEVsZW1lbnRSZWY7XHJcbiAgQFZpZXdDaGlsZCgnZWRpdG9yV3JhcHBlcicpXHJcbiAgZWRpdG9yV3JhcHBlcjogRWxlbWVudFJlZjtcclxuXHJcbiAgQE91dHB1dCgpXHJcbiAgcHVibGljIHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xyXG5cclxuICAvLyBhY3R1YWxYbWxDdXJzb3I6IFhtbEN1cnNvciA9IG5ldyBYbWxDdXJzb3IoKTtcclxuICBkb21EdW1teU5vZGVNYW5hZ2VyID0gbmV3IERvbUR1bW15Tm9kZU1hbmFnZXIoKTtcclxuXHJcbiAgcHJpdmF0ZSBvblRvdWNoZWRGdW5jdGlvbjogKCkgPT4gdm9pZDtcclxuICBwcml2YXRlIG9uQ2hhbmdlRnVuY3Rpb246ICh2YWx1ZTogc3RyaW5nKSA9PiB2b2lkO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9yZW5kZXJlcjogUmVuZGVyZXIyLCBwcml2YXRlIGVkaXRvclNlcnZpY2U6IEFuZ3VsYXJYbWxFZGl0b3JTZXJ2aWNlKSB7fVxyXG5cclxuICBuZ09uQ2hhbmdlcygpIHt9XHJcblxyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge31cclxuXHJcbiAgb25Mb3N0Rm9jdXMoKSB7XHJcbiAgICB0aGlzLmVkaXRvckNvbnRleHQuc2F2ZVNlbGVjdGlvbigpOyAvLyBzYXZlIHNlbGVjdGlvbiBvbiBsb3N0IGZvY3VzXHJcbiAgICBpZiAodHlwZW9mIHRoaXMub25Ub3VjaGVkRnVuY3Rpb24gPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgdGhpcy5vblRvdWNoZWRGdW5jdGlvbigpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuO1xyXG4gIH1cclxuXHJcbiAgb25Hb3RGb2N1cygpIHtcclxuICAgIHRoaXMuZWRpdG9yQ29udGV4dC5yZXN0b3JlU2VsZWN0aW9uKCk7XHJcbiAgICB0aGlzLnRleHRBcmVhLm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTsgLy8gc2V0IGZvY3VzIHRvIHRoZSB0ZXh0IGFyZWFcclxuICB9XHJcblxyXG4gIGNsaWNrZWQoKSB7fVxyXG5cclxuICBtb3VzZWRvd24oKSB7fVxyXG5cclxuICBtb3VzZXVwKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQpIHtcclxuICAgIHJldHVybiB0aGlzLmVkaXRvckNvbnRleHQubW91c2VVcChtb3VzZUV2ZW50KTtcclxuICB9XHJcblxyXG4gIHBhc3RlZCh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLmVkaXRvckNvbnRleHQucGFzdGVkKHRleHQpO1xyXG4gIH1cclxuXHJcbiAgY29waWVkKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuZWRpdG9yQ29udGV4dC5jb3BpZWQoKTtcclxuICB9XHJcblxyXG4gIGtleURvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLmVkaXRvckNvbnRleHQua2V5RG93bihldmVudCk7XHJcbiAgfVxyXG5cclxuICBrZXlVcChldmVudDogS2V5Ym9hcmRFdmVudCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuZWRpdG9yQ29udGV4dC5rZXlVcChldmVudCk7XHJcbiAgfVxyXG5cclxuICAvLyBleGVjKCk6IGJvb2xlYW4ge1xyXG4gIC8vICAgbGV0IHVzZXJTZWxlY3Rpb246IFNlbGVjdGlvbjtcclxuICAvLyAgIGlmICh3aW5kb3cuZ2V0U2VsZWN0aW9uKSB7XHJcbiAgLy8gICAgIHVzZXJTZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XHJcbiAgLy8gICAgIHRoaXMuZWRpdG9yQnJlYWRDcnVtYi5zaG93U2VsZWN0aW9uKHVzZXJTZWxlY3Rpb24pO1xyXG4gIC8vICAgICB0aGlzLmFjdHVhbFhtbEN1cnNvci5TdGFydFBvcy5TZXRDdXJzb3IodXNlclNlbGVjdGlvbi5hbmNob3JOb2RlLCBYTUxDdXJzb3JQb3NpdGlvbmVuLkN1cnNvckluc2lkZVRleHROb2RlLCB1c2VyU2VsZWN0aW9uLmFuY2hvck9mZnNldCk7XHJcbiAgLy8gICAgIHRoaXMuY29tbWFuZGVyLnNldEN1cnNvclBvcyh0aGlzLmFjdHVhbFhtbEN1cnNvci5TdGFydFBvcyk7XHJcbiAgLy8gICB9XHJcblxyXG4gIC8vICAgdGhpcy5kb21EdW1teU5vZGVNYW5hZ2VyLlVwZGF0ZUR1bW15Tm9kZXModGhpcy5hY3R1YWxYbWxDdXJzb3IueG1sRG9jdW1lbnRSb290Tm9kZSwgZmFsc2UpO1xyXG5cclxuICAvLyAgIHJldHVybiBmYWxzZTtcclxuICAvLyB9XHJcblxyXG4gIHNob3dYbWwoeG1sOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnRleHRBcmVhICYmIHRoaXMuZWRpdG9yQ29udGV4dCAmJiB0aGlzLmVkaXRvckNvbnRleHQuY29uZmlnICYmIHRoaXMuZWRpdG9yQ29udGV4dC5jb25maWcucnVsZXMpIHtcclxuICAgICAgaWYgKHhtbCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCB4bWwyaHRtbCA9IG5ldyBYbWwyaHRtbCh0aGlzLmVkaXRvckNvbnRleHQuY29uZmlnLnJ1bGVzKTtcclxuICAgICAgY29uc3QgaHRtbCA9IHhtbDJodG1sLlRvSHRtbCh4bWwpO1xyXG4gICAgICBjb25zdCBub3JtYWxpemVkVmFsdWUgPSB4bWwgPT09IG51bGwgPyAnJyA6IGh0bWw7XHJcbiAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFByb3BlcnR5KHRoaXMudGV4dEFyZWEubmF0aXZlRWxlbWVudCwgJ2lubmVySFRNTCcsIG5vcm1hbGl6ZWRWYWx1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiBTVEFSVCBPRiBDb250cm9sVmFsdWVBY2Nlc3NvciAgKHNlZSBodHRwczovL2FuZ3VsYXIuaW8vYXBpL2Zvcm1zL0NvbnRyb2xWYWx1ZUFjY2Vzc29yICkgKi9cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0cyB0aGUgZnVuY3Rpb24gY2FsbGVkIHdoZW4gdGhlIGNvbnRyb2wgZ2V0cyBhIGNoYW5nZSBldmVudFxyXG4gICAqL1xyXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZnVuYzogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLm9uQ2hhbmdlRnVuY3Rpb24gPSBmdW5jO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0cyB0aGUgZnVuY3Rpb24gY2FsbGVkIHdoZW4gdGhlIGNvbnRyb2wgZ2V0cyBhIHRvdWNoIGV2ZW50XHJcbiAgICovXHJcbiAgcmVnaXN0ZXJPblRvdWNoZWQoZnVuYzogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLm9uVG91Y2hlZEZ1bmN0aW9uID0gZnVuYztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFdyaXRlIHRoZSBuZXcgdmFsdWUgdG8gdGhlIGVsZW1lbnRcclxuICAgKi9cclxuICB3cml0ZVZhbHVlKHZhbHVlOiBhbnkpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmVkaXRvckNvbnRleHQgJiYgdGhpcy5lZGl0b3JDb250ZXh0LmNvbmZpZykge1xyXG4gICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHtcclxuICAgICAgICB2YWx1ZSA9IHVuZGVmaW5lZDtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5zaG93WG1sKHZhbHVlKTtcclxuXHJcbiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgdGhpcy5lZGl0b3JDb250ZXh0LmFjdHVhbEN1cnNvci54bWxEb2N1bWVudFJvb3ROb2RlID0gdW5kZWZpbmVkO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNvbnN0IGVsID0gdGhpcy50ZXh0QXJlYS5uYXRpdmVFbGVtZW50IGFzIEVsZW1lbnQ7XHJcbiAgICAgICAgY29uc3Qgbm9kZSA9IGVsLmZpcnN0Q2hpbGQgYXMgRWxlbWVudDtcclxuICAgICAgICB0aGlzLmVkaXRvckNvbnRleHQuYWN0dWFsQ3Vyc29yLnhtbERvY3VtZW50Um9vdE5vZGUgPSBub2RlO1xyXG4gICAgICAgIHRoaXMuZWRpdG9yQ29udGV4dC5hY3R1YWxDdXJzb3IuU3RhcnRQb3MuU2V0Q3Vyc29yKHRoaXMuZWRpdG9yQ29udGV4dC5hY3R1YWxDdXJzb3IueG1sRG9jdW1lbnRSb290Tm9kZSwgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvck9uQ29tcGxldGVOb2RlKTtcclxuICAgICAgICB0aGlzLmRvbUR1bW15Tm9kZU1hbmFnZXIuVXBkYXRlRHVtbXlOb2Rlcyh0aGlzLmVkaXRvckNvbnRleHQuYWN0dWFsQ3Vyc29yLnhtbERvY3VtZW50Um9vdE5vZGUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFeGVjdXRlZCBmcm9tIHRoZSBjb250ZW50ZWRpdGFibGUgc2VjdGlvbiB3aGlsZSB0aGUgaW5wdXQgcHJvcGVydHkgY2hhbmdlc1xyXG4gICAqIEBwYXJhbSBodG1sIGh0bWwgc3RyaW5nIGZyb20gY29udGVudGVkaXRhYmxlXHJcbiAgICovXHJcbiAgb25Db250ZW50Q2hhbmdlKGh0bWw6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKHR5cGVvZiB0aGlzLm9uQ2hhbmdlRnVuY3Rpb24gPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgY29uc3QgaHRtbDJ4bWwgPSBuZXcgSHRtbDJ4bWwodGhpcy5lZGl0b3JDb250ZXh0LmNvbmZpZy5ydWxlcyk7XHJcbiAgICAgIGNvbnN0IHhtbCA9IGh0bWwyeG1sLlRvWG1sKGh0bWwpO1xyXG4gICAgICBjb25zdCBub3JtYWxpemVkVmFsdWUgPSB4bWwgPT09IG51bGwgPyAnJyA6IHhtbDtcclxuICAgICAgdGhpcy5vbkNoYW5nZUZ1bmN0aW9uKG5vcm1hbGl6ZWRWYWx1ZSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm47XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBzZXRzIHRoZSBkaXNhYmxlZCBzdGF0ZSBmb3IgdGhpcyBlbGVtZW50XHJcbiAgICovXHJcbiAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICBjb25zdCBkaXYgPSB0aGlzLnRleHRBcmVhLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICBjb25zdCBhY3Rpb24gPSBpc0Rpc2FibGVkID8gJ2FkZENsYXNzJyA6ICdyZW1vdmVDbGFzcyc7XHJcbiAgICB0aGlzLl9yZW5kZXJlclthY3Rpb25dKGRpdiwgJ2Rpc2FibGVkJyk7XHJcbiAgfVxyXG5cclxuICAvKiBFTkQgT0YgQ29udHJvbFZhbHVlQWNjZXNzb3IgKi9cclxufVxyXG4iLCJleHBvcnQgY2xhc3MgWG1sUnVsZUVsZW1lbnQge1xyXG4gIHB1YmxpYyB0YWdOYW1lOiBzdHJpbmc7XHJcbiAgcHVibGljIGVtcHR5OiBib29sZWFuO1xyXG4gIHB1YmxpYyBmbG9hdGluZzogYm9vbGVhbjtcclxuXHJcbiAgcHVibGljIHN0YXRpYyBTb3J0ZWQoZWxlbWVudHM6IFhtbFJ1bGVFbGVtZW50W10pOiBYbWxSdWxlRWxlbWVudFtdIHtcclxuICAgIGNvbnN0IHJlc3VsdCA9IGVsZW1lbnRzLnNvcnQoKGUxLCBlMikgPT4ge1xyXG4gICAgICBpZiAoZTEudGFnTmFtZSA+IGUyLnRhZ05hbWUpIHtcclxuICAgICAgICByZXR1cm4gMTtcclxuICAgICAgfVxyXG4gICAgICBpZiAoZTEudGFnTmFtZSA8IGUyLnRhZ05hbWUpIHtcclxuICAgICAgICByZXR1cm4gLTE7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIDA7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY29uc3RydWN0b3IoaW5pdD86IFBhcnRpYWw8WG1sUnVsZUVsZW1lbnQ+KSB7XHJcbiAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBYbWxDdXJzb3JQb3MsIFhNTEN1cnNvclBvc2l0aW9ucyB9IGZyb20gJy4uL2N1cnNvci94bWxDdXJzb3JQb3MuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWwyaHRtbCB9IGZyb20gJy4uL3htbC1odG1sLWNvbnZlcnRlci94bWwyaHRtbC5jbGFzcyc7XHJcblxyXG5leHBvcnQgY2xhc3MgWG1sRWRpdFJ1bGVDaGVja0VsZW1lbnRzIHtcclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHhzZE5vZGVzOiBNYXA8c3RyaW5nLCBFbGVtZW50Pikge31cclxuXHJcbiAgRWxlbWVudHNBbGxvd2VkQXRUaGlzQ3Vyc29yUG9zKGN1cnNvclBvc1RvQ2hlY2s6IFhtbEN1cnNvclBvcyk6IHN0cmluZ1tdIHtcclxuICAgIGlmICghY3Vyc29yUG9zVG9DaGVjaykge1xyXG4gICAgICByZXR1cm4gW107XHJcbiAgICB9XHJcbiAgICBjb25zdCBwYXJlbnROb2RlID0gdGhpcy5nZXRSZWxldmFudFBhcmVudE5vZGVGb3JDdXJzb3JQb3MoY3Vyc29yUG9zVG9DaGVjayk7XHJcbiAgICBjb25zdCBwYXJlbnROYW1lID0gWG1sMmh0bWwuZ2V0VGFnTmFtZUZyb21Ob2RlKHBhcmVudE5vZGUpO1xyXG4gICAgY29uc3QgeHNkTm9kZSA9IHRoaXMueHNkTm9kZXMuZ2V0KHBhcmVudE5hbWUpO1xyXG4gICAgaWYgKHhzZE5vZGUpIHtcclxuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5nZXRTdWJFbGVtZW50TmFtZXMoeHNkTm9kZSwgW10pO1xyXG4gICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gY29uc29sZS53YXJuKCdlbGVtZW50IFwiJyArIHBhcmVudE5hbWUgKyAnXCIgbm90IGZvdW5kJyk7XHJcbiAgICAgIHJldHVybiBbXTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGdldFJlbGV2YW50UGFyZW50Tm9kZUZvckN1cnNvclBvcyhjdXJzb3JQb3NUb0NoZWNrOiBYbWxDdXJzb3JQb3MpOiBOb2RlIHtcclxuICAgIGlmIChjdXJzb3JQb3NUb0NoZWNrKSB7XHJcbiAgICAgIGxldCBwYXJlbnROb2RlID0gY3Vyc29yUG9zVG9DaGVjay5BY3R1YWxOb2RlO1xyXG5cclxuICAgICAgc3dpdGNoIChwYXJlbnROb2RlLm5vZGVUeXBlKSB7XHJcbiAgICAgICAgY2FzZSBOb2RlLkNPTU1FTlRfTk9ERTpcclxuICAgICAgICBjYXNlIE5vZGUuVEVYVF9OT0RFOlxyXG4gICAgICAgICAgcGFyZW50Tm9kZSA9IHBhcmVudE5vZGUucGFyZW50RWxlbWVudDtcclxuICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICBjYXNlIE5vZGUuRUxFTUVOVF9OT0RFOlxyXG4gICAgICAgICAgc3dpdGNoIChjdXJzb3JQb3NUb0NoZWNrLlBvc0F0Tm9kZSkge1xyXG4gICAgICAgICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkVtcHR5Tm9kZTpcclxuICAgICAgICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5zaWRlVGV4dE5vZGU6XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JCZWhpbmROb2RlOlxyXG4gICAgICAgICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkZyb250T2ZOb2RlOlxyXG4gICAgICAgICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JPbkNvbXBsZXRlTm9kZTpcclxuICAgICAgICAgICAgICBwYXJlbnROb2RlID0gcGFyZW50Tm9kZS5wYXJlbnRFbGVtZW50O1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuaGFuZGxlZCAgY3Vyc29yUG9zVG9DaGVjay5Qb3NBbU5vZGUgXCIke2N1cnNvclBvc1RvQ2hlY2suUG9zQXROb2RlfVwiLyR7WG1sQ3Vyc29yUG9zLmdldFhtbEN1cnNvclBvc2l0aW9uRGVidWdOYW1lKGN1cnNvclBvc1RvQ2hlY2suUG9zQXROb2RlKX1cIiBgKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmhhbmRsZWQgIHBhcmVudE5vZGUubm9kZVR5cGUgXCIke3BhcmVudE5vZGUubm9kZVR5cGV9XCJgKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gcGFyZW50Tm9kZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBnZXRTdWJFbGVtZW50TmFtZXMoeHNkTm9kZTogTm9kZSwgYWxyZWFkeUFkZGVkRWxlbWVudE5hbWVzOiBzdHJpbmdbXSwgZGVwdGg6IG51bWJlciA9IDApOiBzdHJpbmdbXSB7XHJcbiAgICBsZXQgZWxlbWVudE5hbWVzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgbGV0IGVsZW1lbnROYW1lOiBzdHJpbmc7XHJcblxyXG4gICAgaWYgKHhzZE5vZGUubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XHJcbiAgICAgIGNvbnN0IGFzRWxlbSA9IHhzZE5vZGUgYXMgRWxlbWVudDtcclxuICAgICAgaWYgKGFzRWxlbSkge1xyXG4gICAgICAgIGlmIChhc0VsZW0ubG9jYWxOYW1lID09PSAnZWxlbWVudCcpIHtcclxuICAgICAgICAgIGVsZW1lbnROYW1lID0gYXNFbGVtLmdldEF0dHJpYnV0ZSgnbmFtZScpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChlbGVtZW50TmFtZSkge1xyXG4gICAgICAvLyBjb25zb2xlLndhcm4oJ2ZvdW5kOiAnICsgSlNPTi5zdHJpbmdpZnkoZWxlbWVudE5hbWUpICsgJyBkZXB0aDogJyArIGRlcHRoKTtcclxuICAgICAgaWYgKGFscmVhZHlBZGRlZEVsZW1lbnROYW1lcy5sZW5ndGggIT09IDApIHtcclxuICAgICAgICBpZiAoYWxyZWFkeUFkZGVkRWxlbWVudE5hbWVzLmluZGV4T2YoZWxlbWVudE5hbWUpICE9PSAtMSkge1xyXG4gICAgICAgICAgcmV0dXJuIGVsZW1lbnROYW1lczsgLy8gZWxlbWVudCByZWN1cnNpb24gZGV0ZWN0ZWRcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGRlcHRoID09PSAwKSB7XHJcbiAgICAgICAgICAvLyBpcyB0aGUgcGFyZW50IGVsZW1lbnQgaXRzZWxmIC0gc2tpcCFcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgZWxlbWVudE5hbWVzID0gZWxlbWVudE5hbWVzLmNvbmNhdChlbGVtZW50TmFtZSk7XHJcbiAgICAgICAgICByZXR1cm4gZWxlbWVudE5hbWVzO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBhbHJlYWR5QWRkZWRFbGVtZW50TmFtZXMucHVzaChlbGVtZW50TmFtZSk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgY2hpbGROb2RlcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHhzZE5vZGUuY2hpbGROb2RlcykgYXMgTm9kZVtdO1xyXG5cclxuICAgIGRlcHRoKys7XHJcblxyXG4gICAgY2hpbGROb2Rlcy5mb3JFYWNoKGNoaWxkID0+IHtcclxuICAgICAgaWYgKGNoaWxkLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xyXG4gICAgICAgIGNvbnN0IGNoaWxkRWxlbSA9IGNoaWxkIGFzIEVsZW1lbnQ7XHJcbiAgICAgICAgaWYgKGNoaWxkRWxlbSkge1xyXG4gICAgICAgICAgc3dpdGNoIChjaGlsZEVsZW0ubG9jYWxOYW1lKSB7XHJcbiAgICAgICAgICAgIGNhc2UgJ2NvbXBsZXhUeXBlJzpcclxuICAgICAgICAgICAgY2FzZSAnc2VxdWVuY2UnOlxyXG4gICAgICAgICAgICBjYXNlICdjaG9pY2UnOlxyXG4gICAgICAgICAgICBjYXNlICdzaW1wbGVDb250ZW50JzpcclxuICAgICAgICAgICAgY2FzZSAnZXh0ZW5zaW9uJzpcclxuICAgICAgICAgICAgICBlbGVtZW50TmFtZXMgPSBlbGVtZW50TmFtZXMuY29uY2F0KHRoaXMuZ2V0U3ViRWxlbWVudE5hbWVzKGNoaWxkLCBhbHJlYWR5QWRkZWRFbGVtZW50TmFtZXMsIGRlcHRoKSk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgICAgICBjYXNlICdlbGVtZW50JzpcclxuICAgICAgICAgICAgICBjb25zdCByZWZuYW1lID0gY2hpbGRFbGVtLmF0dHJpYnV0ZXMuZ2V0TmFtZWRJdGVtKCdyZWYnKTtcclxuICAgICAgICAgICAgICBpZiAocmVmbmFtZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmVmZXJlZE5vZGUgPSB0aGlzLnhzZE5vZGVzLmdldChyZWZuYW1lLnZhbHVlKTtcclxuICAgICAgICAgICAgICAgIGlmIChyZWZlcmVkTm9kZSkge1xyXG4gICAgICAgICAgICAgICAgICBlbGVtZW50TmFtZXMgPSBlbGVtZW50TmFtZXMuY29uY2F0KHRoaXMuZ2V0U3ViRWxlbWVudE5hbWVzKHJlZmVyZWROb2RlLCBhbHJlYWR5QWRkZWRFbGVtZW50TmFtZXMsIGRlcHRoKSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCByZWZlcmVkIGVsZW1lbnQgXCIke3JlZm5hbWV9XCIgZm9yIGVsZW1lbnQgXCIke2NoaWxkRWxlbS5vdXRlckhUTUx9XCIgbm90IGZvdW5kYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGVsZW1lbnROYW1lcyA9IGVsZW1lbnROYW1lcy5jb25jYXQodGhpcy5nZXRTdWJFbGVtZW50TmFtZXMoY2hpbGQsIGFscmVhZHlBZGRlZEVsZW1lbnROYW1lcywgZGVwdGgpKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgICAgICBjYXNlICdhdHRyaWJ1dGUnOlxyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gY2hpbGRFbGVtLmxvY2FsbmFtZSBcIiR7Y2hpbGRFbGVtLmxvY2FsTmFtZX1cIi8ke2NoaWxkRWxlbS5vdXRlckhUTUx9YCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gZWxlbWVudE5hbWVzO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgT3V0cHV0LCBSZW5kZXJlcjIsIElucHV0LCBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBYbWxSdWxlRWxlbWVudCB9IGZyb20gJy4uLy4uL2NvZGUveG1sLXJ1bGVzLWNoZWNrL3htbFJ1bGVFbGVtZW50LmNsYXNzJztcclxuaW1wb3J0IHsgWG1sQ3Vyc29yUG9zIH0gZnJvbSAnLi4vLi4vY29kZS9jdXJzb3IveG1sQ3Vyc29yUG9zLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sRWRpdFJ1bGVDaGVja0VsZW1lbnRzIH0gZnJvbSAnLi4vLi4vY29kZS94bWwtcnVsZXMtY2hlY2sveG1sRWRpdFJ1bGVDaGVja0VsZW1lbnRzLmNsYXNzJztcclxuaW1wb3J0IHsgQW5ndWxhclhtbEVkaXRvclNlcnZpY2UgfSBmcm9tICcuLi8uLi9hbmd1bGFyLXhtbC1lZGl0b3Iuc2VydmljZSc7XHJcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBYbWxFZGl0b3JDb250ZXh0IH0gZnJvbSAnLi4vLi4vY29kZS94bWxFZGl0b3JDb250ZXh0LmNsYXNzJztcclxuaW1wb3J0IHsgWG1sRWRpdG9yQ29uZmlnIH0gZnJvbSAnLi4vLi4vY29kZS94bWxFZGl0b3JDb25maWcnO1xyXG5pbXBvcnQgeyBYbWwyaHRtbCB9IGZyb20gJy4uLy4uL2NvZGUveG1sLWh0bWwtY29udmVydGVyL3htbDJodG1sLmNsYXNzJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnYXhlZC10b29sYmFyJyxcclxuICB0ZW1wbGF0ZVVybDogJy4veG1sLWVkaXRvci10b29sYmFyLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi94bWwtZWRpdG9yLXRvb2xiYXIuY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgWG1sRWRpdG9yVG9vbGJhckNvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcclxuICBwcml2YXRlIGVkaXRvckNvbnRleHQ6IFhtbEVkaXRvckNvbnRleHQ7XHJcblxyXG4gIEBJbnB1dCgnY29uZmlnJylcclxuICBnZXQgY29uZmlnKCk6IFhtbEVkaXRvckNvbmZpZyB7XHJcbiAgICBpZiAodGhpcy5lZGl0b3JDb250ZXh0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5lZGl0b3JDb250ZXh0LmNvbmZpZyAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmVkaXRvckNvbnRleHQgJiYgdGhpcy5lZGl0b3JDb250ZXh0LmNvbmZpZztcclxuICAgIH1cclxuICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICBASW5wdXQoJ2VkaXRvckNvbnRleHRJZCcpXHJcbiAgc2V0IGVkaXRvckNvbnRleHRJZCh2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICBpZiAoIXZhbHVlKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuZWRpdG9yQ29udGV4dCA9IHRoaXMuZWRpdG9yU2VydmljZS5nZXRFZGl0b3JDb250ZXh0KHZhbHVlKTtcclxuICAgIHRoaXMuYWN0dWFsQ3Vyc29yUG9zQ2hhbmdlZFN1YnNjcmlwdGlvbiA9IHRoaXMuZWRpdG9yQ29udGV4dC5hY3R1YWxDdXJzb3JDaGFuZ2VkLnN1YnNjcmliZShwb3MgPT4ge1xyXG4gICAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSB0aGlzLkdldEVsZW1lbnRHcm91cHNGb3JDdXJzb3JQb3MocG9zLlN0YXJ0UG9zKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZWxlbWVudEdyb3VwczogVG9vbGJhckVsZW1lbnRHcm91cFtdID0gW107XHJcblxyXG4gIGFjdHVhbEN1cnNvclBvc0NoYW5nZWRTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgLyoqIGluc2VydHMgYW4gZWxlbWVudCBhdCB0aGUgYWN0dWFsIGN1cnNvciBwb3MgKi9cclxuICBpbnNlcnRFbGVtZW50KGVsZW1lbnQ6IFhtbFJ1bGVFbGVtZW50KSB7XHJcbiAgICBjb25zdCBodG1sID0gbmV3IFhtbDJodG1sKHRoaXMuZWRpdG9yQ29udGV4dC5jb25maWcucnVsZXMpLmNyZWF0ZU5ld0VsZW1lbnRIdG1sKGVsZW1lbnQpO1xyXG4gICAgdGhpcy5lZGl0b3JDb250ZXh0LmRvbUluc2VydEh0bWwoaHRtbCk7XHJcbiAgfVxyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVkaXRvclNlcnZpY2U6IEFuZ3VsYXJYbWxFZGl0b3JTZXJ2aWNlKSB7fVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7fVxyXG4gIG5nT25DaGFuZ2VzKCk6IHZvaWQge31cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmFjdHVhbEN1cnNvclBvc0NoYW5nZWRTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICB9XHJcblxyXG4gIEdldEVsZW1lbnRHcm91cHNGb3JDdXJzb3JQb3MocG9zOiBYbWxDdXJzb3JQb3MpOiBUb29sYmFyRWxlbWVudEdyb3VwW10ge1xyXG4gICAgY29uc3QgYWxsb3dlZEVsZW1lbnRzID0gbmV3IFhtbEVkaXRSdWxlQ2hlY2tFbGVtZW50cyh0aGlzLmVkaXRvckNvbnRleHQuY29uZmlnLnhtbFNjaGVtYS54c2ROb2RlcykuRWxlbWVudHNBbGxvd2VkQXRUaGlzQ3Vyc29yUG9zKHBvcyk7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuR2V0QWxsRWxlbWVudEdyb3VwcygpXHJcbiAgICAgIC5tYXAoZyA9PiB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgIHRpdGxlOiBnLnRpdGxlLFxyXG4gICAgICAgICAgZWxlbWVudHM6IGcuZWxlbWVudHMuZmlsdGVyKGUgPT4gYWxsb3dlZEVsZW1lbnRzLmluY2x1ZGVzKGUudGFnTmFtZSkpXHJcbiAgICAgICAgfSBhcyBUb29sYmFyRWxlbWVudEdyb3VwO1xyXG4gICAgICB9KVxyXG4gICAgICAuZmlsdGVyKGcgPT4gZy5lbGVtZW50cy5sZW5ndGggPiAwKTtcclxuICB9XHJcblxyXG4gIEdldEFsbEVsZW1lbnRHcm91cHMoKTogVG9vbGJhckVsZW1lbnRHcm91cFtdIHtcclxuICAgIGNvbnN0IHVudXNlZEVsZW1lbnRzID0gWG1sUnVsZUVsZW1lbnQuU29ydGVkKFxyXG4gICAgICBBcnJheS5mcm9tKHRoaXMuZWRpdG9yQ29udGV4dC5jb25maWcucnVsZXMucnVsZUVsZW1lbnRzLnZhbHVlcygpKS5maWx0ZXIoZWxlbSA9PlxyXG4gICAgICAgIHRoaXMuZWRpdG9yQ29udGV4dC5jb25maWcuZWxlbWVudEdyb3Vwcy5zb21lKGdyb3VwID0+ICFncm91cC5lbGVtZW50TmFtZXMuaW5jbHVkZXMoZWxlbS50YWdOYW1lKSlcclxuICAgICAgKVxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCBvdGhlckVsZW1lbnRzR3JvdXAgPSB7XHJcbiAgICAgIHRpdGxlOiAnb3RoZXInLFxyXG4gICAgICBlbGVtZW50czogdW51c2VkRWxlbWVudHNcclxuICAgIH0gYXMgVG9vbGJhckVsZW1lbnRHcm91cDtcclxuXHJcbiAgICByZXR1cm4gdGhpcy5lZGl0b3JDb250ZXh0LmNvbmZpZy5lbGVtZW50R3JvdXBzXHJcbiAgICAgIC5tYXAoZyA9PiB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgIHRpdGxlOiBnLnRpdGxlLFxyXG4gICAgICAgICAgZWxlbWVudHM6IFhtbFJ1bGVFbGVtZW50LlNvcnRlZChnLmVsZW1lbnROYW1lcy5tYXAoZWxlbWVudE5hbWUgPT4gdGhpcy5lZGl0b3JDb250ZXh0LmNvbmZpZy5ydWxlcy5ydWxlRWxlbWVudHMuZ2V0KGVsZW1lbnROYW1lKSkuZmlsdGVyKGUgPT4gZSAhPT0gdW5kZWZpbmVkKSlcclxuICAgICAgICB9IGFzIFRvb2xiYXJFbGVtZW50R3JvdXA7XHJcbiAgICAgIH0pXHJcbiAgICAgIC5jb25jYXQob3RoZXJFbGVtZW50c0dyb3VwKVxyXG4gICAgICAuZmlsdGVyKGcgPT4gZy5lbGVtZW50cy5sZW5ndGggIT09IDApO1xyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBUb29sYmFyRWxlbWVudEdyb3VwIHtcclxuICB0aXRsZTogc3RyaW5nO1xyXG4gIGVsZW1lbnRzOiBYbWxSdWxlRWxlbWVudFtdO1xyXG59XHJcbiIsImV4cG9ydCBjbGFzcyBYbWxSdWxlQXR0cmlidXQge1xyXG4gIHB1YmxpYyBhdHRyaWJOYW1lOiBzdHJpbmc7XHJcblxyXG4gIHB1YmxpYyByZXF1aXJlZDogYm9vbGVhbjtcclxuXHJcbiAgLyoqIHdoZW4gdGhlIHZhbHVlcyBhcmUgZnJvbSBhIGdpdmVuIGxpc3QgKiovXHJcbiAgcHVibGljIGZpeGVkVmFsdWVzOiBzdHJpbmdbXTtcclxuXHJcbiAgcHVibGljIGRlZmF1bHRWYWx1ZTogc3RyaW5nO1xyXG5cclxuICBwdWJsaWMgeHNkUmF3Tm9kZTogTm9kZTtcclxuXHJcbiAgcHVibGljIHR5cDogUnVsZUF0dHJpYnV0ZVR5cGVzO1xyXG5cclxuICBwdWJsaWMgY29uc3RydWN0b3IoaW5pdD86IFBhcnRpYWw8WG1sUnVsZUF0dHJpYnV0Pikge1xyXG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLCBpbml0KTtcclxuICAgIHRoaXMudHlwID0gdGhpcy5nZXRUeXAoKTtcclxuICB9XHJcblxyXG4gIGdldFR5cCgpOiBSdWxlQXR0cmlidXRlVHlwZXMge1xyXG4gICAgaWYgKHRoaXMuZml4ZWRWYWx1ZXMgJiYgdGhpcy5maXhlZFZhbHVlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHJldHVybiBSdWxlQXR0cmlidXRlVHlwZXMuRW51bTtcclxuICAgIH1cclxuICAgIHJldHVybiBSdWxlQXR0cmlidXRlVHlwZXMuU3RyaW5nO1xyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGVudW0gUnVsZUF0dHJpYnV0ZVR5cGVzIHtcclxuICBTdHJpbmcgPSAwLFxyXG4gIEVudW0gPSAxLFxyXG4gIE51bWJlciA9IDJcclxufVxyXG4iLCJpbXBvcnQgeyBYbWxDdXJzb3JQb3MsIFhNTEN1cnNvclBvc2l0aW9ucyB9IGZyb20gJy4uL2N1cnNvci94bWxDdXJzb3JQb3MuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWxSdWxlQXR0cmlidXQgfSBmcm9tICcuL3htbFJ1bGVBdHRyaWJ1dC5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbFNjaGVtYSB9IGZyb20gJy4veG1sU2NoZW1hLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sMmh0bWwgfSBmcm9tICcuLi94bWwtaHRtbC1jb252ZXJ0ZXIveG1sMmh0bWwuY2xhc3MnO1xyXG5cclxuZXhwb3J0IGNsYXNzIFhtbEVkaXRSdWxlQ2hlY2tBdHRyaWJ1dGVzIHtcclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHhtbFNjaGVtYTogWG1sU2NoZW1hKSB7fVxyXG5cclxuICBBdHRyaWJ1dGVzQWxsb3dlZEF0VGhpc0N1cnNvclBvcyhjdXJzb3JQb3NUb0NoZWNrOiBYbWxDdXJzb3JQb3MpOiBYbWxSdWxlQXR0cmlidXRbXSB7XHJcbiAgICBpZiAoIWN1cnNvclBvc1RvQ2hlY2spIHtcclxuICAgICAgcmV0dXJuIFtdO1xyXG4gICAgfVxyXG4gICAgY29uc3QgcGFyZW50Tm9kZSA9IHRoaXMuZ2V0UmVsZXZhbnRQYXJlbnROb2RlRm9yQ3Vyc29yUG9zKGN1cnNvclBvc1RvQ2hlY2spO1xyXG4gICAgY29uc3QgcGFyZW50TmFtZSA9IFhtbDJodG1sLmdldFRhZ05hbWVGcm9tTm9kZShwYXJlbnROb2RlKTtcclxuICAgIHJldHVybiB0aGlzLmdldEF0dHJpYnV0ZXNGb3JFbGVtZW50TmFtZShwYXJlbnROYW1lKTtcclxuICB9XHJcblxyXG4gIGdldFJlbGV2YW50UGFyZW50Tm9kZUZvckN1cnNvclBvcyhjdXJzb3JQb3NUb0NoZWNrOiBYbWxDdXJzb3JQb3MpOiBOb2RlIHtcclxuICAgIGlmIChjdXJzb3JQb3NUb0NoZWNrKSB7XHJcbiAgICAgIGxldCBwYXJlbnROb2RlID0gY3Vyc29yUG9zVG9DaGVjay5BY3R1YWxOb2RlO1xyXG5cclxuICAgICAgc3dpdGNoIChwYXJlbnROb2RlLm5vZGVUeXBlKSB7XHJcbiAgICAgICAgY2FzZSBOb2RlLkNPTU1FTlRfTk9ERTpcclxuICAgICAgICBjYXNlIE5vZGUuVEVYVF9OT0RFOlxyXG4gICAgICAgICAgcGFyZW50Tm9kZSA9IHBhcmVudE5vZGUucGFyZW50RWxlbWVudDtcclxuICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICBjYXNlIE5vZGUuRUxFTUVOVF9OT0RFOlxyXG4gICAgICAgICAgc3dpdGNoIChjdXJzb3JQb3NUb0NoZWNrLlBvc0F0Tm9kZSkge1xyXG4gICAgICAgICAgICBjYXNlIFhNTEN1cnNvclBvc2l0aW9ucy5DdXJzb3JJbkVtcHR5Tm9kZTpcclxuICAgICAgICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5zaWRlVGV4dE5vZGU6XHJcbiAgICAgICAgICAgIGNhc2UgWE1MQ3Vyc29yUG9zaXRpb25zLkN1cnNvck9uQ29tcGxldGVOb2RlOlxyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29yQmVoaW5kTm9kZTpcclxuICAgICAgICAgICAgY2FzZSBYTUxDdXJzb3JQb3NpdGlvbnMuQ3Vyc29ySW5Gcm9udE9mTm9kZTpcclxuICAgICAgICAgICAgICBwYXJlbnROb2RlID0gcGFyZW50Tm9kZS5wYXJlbnRFbGVtZW50O1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuaGFuZGxlZCBjdXJzb3JQb3NUb0NoZWNrLlBvc0FtTm9kZSBcIiR7Y3Vyc29yUG9zVG9DaGVjay5Qb3NBdE5vZGV9XCIvJHtYbWxDdXJzb3JQb3MuZ2V0WG1sQ3Vyc29yUG9zaXRpb25EZWJ1Z05hbWUoY3Vyc29yUG9zVG9DaGVjay5Qb3NBdE5vZGUpfVwiIGApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuaGFuZGxlZCBwYXJlbnROb2RlLm5vZGVUeXBlIFwiJHtwYXJlbnROb2RlLm5vZGVUeXBlfVwiYCk7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBnZXRBdHRyaWJ1dGVzRm9yRWxlbWVudE5hbWUoZWxlbWVudE5hbWU6IHN0cmluZyk6IFhtbFJ1bGVBdHRyaWJ1dFtdIHtcclxuICAgIGNvbnN0IHhzZE5vZGUgPSB0aGlzLnhtbFNjaGVtYS5maW5kWHNkTm9kZUZvclRhZ05hbWUoZWxlbWVudE5hbWUpO1xyXG4gICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlc0ZvckVsZW1lbnQoeHNkTm9kZSwgbmV3IFNldChbeHNkTm9kZV0pKTtcclxuICB9XHJcblxyXG4gIGdldEF0dHJpYnV0ZXNGb3JFbGVtZW50KHhzZE5vZGU6IE5vZGUsIGFscmVhZHlBZGRlZEVsZW1lbnRzOiBTZXQ8Tm9kZT4pOiBYbWxSdWxlQXR0cmlidXRbXSB7XHJcbiAgICBsZXQgYXR0cmlidXRlczogWG1sUnVsZUF0dHJpYnV0W10gPSBbXTtcclxuXHJcbiAgICBpZiAoeHNkTm9kZSkge1xyXG4gICAgICBhbHJlYWR5QWRkZWRFbGVtZW50cy5hZGQoeHNkTm9kZSk7XHJcblxyXG4gICAgICBjb25zdCBjaGlsZE5vZGVzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoeHNkTm9kZS5jaGlsZE5vZGVzKTtcclxuXHJcbiAgICAgIGNoaWxkTm9kZXMuZm9yRWFjaChjaGlsZCA9PiB7XHJcbiAgICAgICAgaWYgKHhzZE5vZGUubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XHJcbiAgICAgICAgICBjb25zdCBjaGlsZEVsZW0gPSBjaGlsZCBhcyBFbGVtZW50O1xyXG4gICAgICAgICAgaWYgKGNoaWxkRWxlbSkge1xyXG4gICAgICAgICAgICBpZiAoY2hpbGQubG9jYWxOYW1lID09PSAnYXR0cmlidXRlJykge1xyXG4gICAgICAgICAgICAgIC8vIGlzIGF0dHJpYnV0ZVxyXG4gICAgICAgICAgICAgIGF0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzLmNvbmNhdChbXHJcbiAgICAgICAgICAgICAgICBuZXcgWG1sUnVsZUF0dHJpYnV0KHtcclxuICAgICAgICAgICAgICAgICAgYXR0cmliTmFtZTogY2hpbGRFbGVtLmF0dHJpYnV0ZXMuZ2V0TmFtZWRJdGVtKCduYW1lJykudmFsdWUsXHJcbiAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiB0aGlzLmlzUmVxdWlyZWRBdHRyaWJ1dGUoY2hpbGRFbGVtKSxcclxuICAgICAgICAgICAgICAgICAgeHNkUmF3Tm9kZTogY2hpbGRFbGVtLFxyXG4gICAgICAgICAgICAgICAgICBmaXhlZFZhbHVlczogdGhpcy5nZXRGaXhlZFZhbHVlcyhjaGlsZEVsZW0pLFxyXG4gICAgICAgICAgICAgICAgICBkZWZhdWx0VmFsdWU6IHRoaXMuZ2V0RGVmYXVsdFZhbHVlKGNoaWxkRWxlbSlcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgXSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgLy8gbm8gYXR0cmlidXRlXHJcbiAgICAgICAgICAgICAgaWYgKCFhbHJlYWR5QWRkZWRFbGVtZW50cy5oYXMoY2hpbGQpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzdWJOb2RlQXR0cmlidXRlcyA9IHRoaXMuZ2V0QXR0cmlidXRlc0ZvckVsZW1lbnQoY2hpbGQsIGFscmVhZHlBZGRlZEVsZW1lbnRzKTtcclxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzLmNvbmNhdChzdWJOb2RlQXR0cmlidXRlcyk7XHJcbiAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIC8vIEVsZW1lbnQgYWxyZWFkeSBhZGRlZFxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGF0dHJpYnV0ZXM7XHJcbiAgfVxyXG5cclxuICAvKiogdGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoaXMgYXR0cmlidXRlICovXHJcbiAgcHJpdmF0ZSBnZXREZWZhdWx0VmFsdWUoY2hpbGRFbGVtOiBFbGVtZW50KSB7XHJcbiAgICBjb25zdCBhdHRyaWIgPSBjaGlsZEVsZW0uYXR0cmlidXRlcy5nZXROYW1lZEl0ZW0oJ2RlZmF1bHQnKTtcclxuICAgIGlmIChhdHRyaWIgIT09IG51bGwpIHtcclxuICAgICAgcmV0dXJuIGF0dHJpYi52YWx1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICAvKiogaXMgdGhpcyBhdHRyaWJ1dGUgcmVxdWlyZWQ/ICovXHJcbiAgcHJpdmF0ZSBpc1JlcXVpcmVkQXR0cmlidXRlKGNoaWxkRWxlbTogRWxlbWVudCkge1xyXG4gICAgY29uc3QgYXR0cmliID0gY2hpbGRFbGVtLmF0dHJpYnV0ZXMuZ2V0TmFtZWRJdGVtKCd1c2UnKTtcclxuICAgIGNvbnN0IHZhbHVlID0gYXR0cmliICE9PSBudWxsICYmIGF0dHJpYi52YWx1ZSA9PT0gJ3JlcXVpcmVkJztcclxuICAgIHJldHVybiB2YWx1ZTtcclxuICB9XHJcblxyXG4gIC8qKiBnZXQgdGhlIGFsbG93ZXMgdmFsdWVzIGZvciB0aGlzIGF0dHJpYnV0ZSAqL1xyXG4gIHByaXZhdGUgZ2V0Rml4ZWRWYWx1ZXMoeHNkTm9kZTogRWxlbWVudCwgYWxyZWFkeUNoZWNrZWQ6IE5vZGVbXSA9IFtdKTogc3RyaW5nW10ge1xyXG4gICAgbGV0IHZhbHVlczogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgICBjb25zdCBjaGlsZE5vZGVzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoeHNkTm9kZS5jaGlsZE5vZGVzKTtcclxuICAgIGNoaWxkTm9kZXMuZm9yRWFjaChjaGlsZCA9PiB7XHJcbiAgICAgIGlmICh4c2ROb2RlLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xyXG4gICAgICAgIGNvbnN0IGNoaWxkRWxlbSA9IGNoaWxkIGFzIEVsZW1lbnQ7XHJcbiAgICAgICAgaWYgKGNoaWxkRWxlbSkge1xyXG4gICAgICAgICAgaWYgKGNoaWxkLmxvY2FsTmFtZSA9PT0gJ2VudW1lcmF0aW9uJykge1xyXG4gICAgICAgICAgICB2YWx1ZXMgPSB2YWx1ZXMuY29uY2F0KFtjaGlsZEVsZW0uYXR0cmlidXRlcy5nZXROYW1lZEl0ZW0oJ3ZhbHVlJykudmFsdWVdKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIG5vIGF0dHJpYnV0ZVxyXG4gICAgICAgICAgICBpZiAoYWxyZWFkeUNoZWNrZWQuaW5kZXhPZihjaGlsZCkgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgY29uc3Qgc3ViTm9kZUF0dHJpYnV0ZXMgPSB0aGlzLmdldEZpeGVkVmFsdWVzKGNoaWxkLCBhbHJlYWR5Q2hlY2tlZCk7XHJcbiAgICAgICAgICAgICAgdmFsdWVzID0gdmFsdWVzLmNvbmNhdChzdWJOb2RlQXR0cmlidXRlcyk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgLy8gRWxlbWVudCBhbHJlYWR5IGFkZGVkXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiB2YWx1ZXM7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT25EZXN0cm95IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFhtbEN1cnNvclBvcyB9IGZyb20gJy4uLy4uL2NvZGUvY3Vyc29yL3htbEN1cnNvclBvcy5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbEVkaXRSdWxlQ2hlY2tBdHRyaWJ1dGVzIH0gZnJvbSAnLi4vLi4vY29kZS94bWwtcnVsZXMtY2hlY2sveG1sRWRpdFJ1bGVDaGVja0F0dHJpYnV0ZXMuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWxSdWxlQXR0cmlidXQsIFJ1bGVBdHRyaWJ1dGVUeXBlcyB9IGZyb20gJy4uLy4uL2NvZGUveG1sLXJ1bGVzLWNoZWNrL3htbFJ1bGVBdHRyaWJ1dC5jbGFzcyc7XHJcbmltcG9ydCB7IEFuZ3VsYXJYbWxFZGl0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vYW5ndWxhci14bWwtZWRpdG9yLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgWG1sRWRpdG9yQ29udGV4dCB9IGZyb20gJy4uLy4uL2NvZGUveG1sRWRpdG9yQ29udGV4dC5jbGFzcyc7XHJcbmltcG9ydCB7IFhtbDJodG1sQXR0cmlidXRlV29ya2VyIH0gZnJvbSAnLi4vLi4vY29kZS94bWwtaHRtbC1jb252ZXJ0ZXIveG1sMmh0bWxBdHRyaWJ1dGVXb3JrZXIuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWwyaHRtbCB9IGZyb20gJy4uLy4uL2NvZGUveG1sLWh0bWwtY29udmVydGVyL3htbDJodG1sLmNsYXNzJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnYXhlZC1hdHRyaWJ1dGUtZWRpdG9yJyxcclxuICB0ZW1wbGF0ZVVybDogJy4veG1sLWVkaXRvci1hdHRyaWJ1dGUtZWRpdG9yLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi94bWwtZWRpdG9yLWF0dHJpYnV0ZS1lZGl0b3IuY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgWG1sRWRpdG9yQXR0cmlidXRlRWRpdG9yQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xyXG4gIHByaXZhdGUgZWRpdG9yQ29udGV4dDogWG1sRWRpdG9yQ29udGV4dDtcclxuXHJcbiAgQElucHV0KCdlZGl0b3JDb250ZXh0SWQnKVxyXG4gIHNldCBlZGl0b3JDb250ZXh0SWQodmFsdWU6IHN0cmluZykge1xyXG4gICAgaWYgKCF2YWx1ZSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLmVkaXRvckNvbnRleHQgPSB0aGlzLmVkaXRvclNlcnZpY2UuZ2V0RWRpdG9yQ29udGV4dCh2YWx1ZSk7XHJcbiAgICB0aGlzLmFjdHVhbEN1cnNvclBvc0NoYW5nZWRTdWJzY3JpcHRpb24gPSB0aGlzLmVkaXRvckNvbnRleHQuYWN0dWFsQ3Vyc29yQ2hhbmdlZC5zdWJzY3JpYmUocG9zID0+IHtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVzID0gdGhpcy5HZXRBdHRyaWJ1dGVzRm9yQ3Vyc29yUG9zKHBvcy5TdGFydFBvcyk7XHJcbiAgICAgIHRoaXMuZWxlbWVudE5hbWUgPSB0aGlzLkdldEVsZW1lbnROYW1lRm9yQ3Vyc29yUG9zKHBvcy5TdGFydFBvcyk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGFjdHVhbEN1cnNvclBvc0NoYW5nZWRTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgYXR0cmliVHlwZXMgPSBSdWxlQXR0cmlidXRlVHlwZXM7XHJcblxyXG4gIGF0dHJpYnV0ZXM6IFRvb2xiYXJBdHRyaWJ1dERhdGFbXSA9IFtdO1xyXG4gIGVsZW1lbnROYW1lOiBzdHJpbmc7XHJcbiAgYWN0dWFsRWxlbWVudDogRWxlbWVudDtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBlZGl0b3JTZXJ2aWNlOiBBbmd1bGFyWG1sRWRpdG9yU2VydmljZSkge31cclxuXHJcbiAgbmdPbkluaXQoKSB7fVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuYWN0dWFsQ3Vyc29yUG9zQ2hhbmdlZFN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xyXG4gIH1cclxuXHJcbiAgYXR0cmlidXRlVmFsdWVDaGFuZ2VkKGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICBpZiAodGhpcy5hY3R1YWxFbGVtZW50KSB7XHJcbiAgICAgIGNvbnN0IGF0dHJpYldvcmtlciA9IG5ldyBYbWwyaHRtbEF0dHJpYnV0ZVdvcmtlcih0aGlzLmVkaXRvckNvbnRleHQuY29uZmlnLnJ1bGVzKTtcclxuICAgICAgYXR0cmliV29ya2VyLndyaXRlQXR0cmlidXRlVG9IdG1sKHRoaXMuYWN0dWFsRWxlbWVudCwga2V5LCB2YWx1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBHZXRFbGVtZW50TmFtZUZvckN1cnNvclBvcyhwb3M6IFhtbEN1cnNvclBvcyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBydWxlc0NoZWNrID0gbmV3IFhtbEVkaXRSdWxlQ2hlY2tBdHRyaWJ1dGVzKHRoaXMuZWRpdG9yQ29udGV4dC5jb25maWcueG1sU2NoZW1hKTtcclxuICAgIGNvbnN0IHBhcmVudE5vZGUgPSBydWxlc0NoZWNrLmdldFJlbGV2YW50UGFyZW50Tm9kZUZvckN1cnNvclBvcyhwb3MpIGFzIEVsZW1lbnQ7XHJcbiAgICBpZiAocGFyZW50Tm9kZSkge1xyXG4gICAgICByZXR1cm4gWG1sMmh0bWwuZ2V0VGFnTmFtZUZyb21Ob2RlKHBhcmVudE5vZGUpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIEdldEF0dHJpYnV0ZXNGb3JDdXJzb3JQb3MocG9zOiBYbWxDdXJzb3JQb3MpOiBUb29sYmFyQXR0cmlidXREYXRhW10ge1xyXG4gICAgY29uc3QgYXR0cmliV29ya2VyID0gbmV3IFhtbDJodG1sQXR0cmlidXRlV29ya2VyKHRoaXMuZWRpdG9yQ29udGV4dC5jb25maWcucnVsZXMpO1xyXG4gICAgY29uc3QgcnVsZXNDaGVjayA9IG5ldyBYbWxFZGl0UnVsZUNoZWNrQXR0cmlidXRlcyh0aGlzLmVkaXRvckNvbnRleHQuY29uZmlnLnhtbFNjaGVtYSk7XHJcbiAgICBjb25zdCBwYXJlbnROb2RlID0gcnVsZXNDaGVjay5nZXRSZWxldmFudFBhcmVudE5vZGVGb3JDdXJzb3JQb3MocG9zKSBhcyBFbGVtZW50O1xyXG4gICAgdGhpcy5hY3R1YWxFbGVtZW50ID0gcGFyZW50Tm9kZTtcclxuICAgIGlmIChwYXJlbnROb2RlKSB7XHJcbiAgICAgIGNvbnN0IGFsbG93ZWRBdHRyaWJ1dGVzID0gcnVsZXNDaGVjay5BdHRyaWJ1dGVzQWxsb3dlZEF0VGhpc0N1cnNvclBvcyhwb3MpO1xyXG4gICAgICByZXR1cm4gYWxsb3dlZEF0dHJpYnV0ZXMubWFwKGEgPT4ge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICBydWxlczogYSxcclxuICAgICAgICAgIHZhbHVlOiBhdHRyaWJXb3JrZXIuZ2V0QXR0cmlidXRlVmFsdWVGcm9tSHRtbChwYXJlbnROb2RlLCBhLmF0dHJpYk5hbWUpXHJcbiAgICAgICAgfSBhcyBUb29sYmFyQXR0cmlidXREYXRhO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIHJldHVybiBbXTtcclxuICB9XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVG9vbGJhckF0dHJpYnV0RGF0YSB7XHJcbiAgcnVsZXM6IFhtbFJ1bGVBdHRyaWJ1dDtcclxuICB2YWx1ZTogc3RyaW5nO1xyXG59XHJcbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBPbkRlc3Ryb3ksIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBYbWxFZGl0b3JEZWJ1Z2dlciB9IGZyb20gJy4uLy4uL2NvZGUveG1sRWRpdG9yRGVidWdnZXInO1xyXG5pbXBvcnQgeyBBbmd1bGFyWG1sRWRpdG9yU2VydmljZSB9IGZyb20gJy4uLy4uL2FuZ3VsYXIteG1sLWVkaXRvci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgWG1sRWRpdG9yQ29udGV4dCB9IGZyb20gJy4uLy4uL2NvZGUveG1sRWRpdG9yQ29udGV4dC5jbGFzcyc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2F4ZWQtZGVidWcnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi94bWwtZWRpdG9yLWRlYnVnLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi94bWwtZWRpdG9yLWRlYnVnLmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIFhtbEVkaXRvckRlYnVnQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xyXG4gIHByaXZhdGUgZWRpdG9yQ29udGV4dDogWG1sRWRpdG9yQ29udGV4dDtcclxuXHJcbiAgQElucHV0KCdlZGl0b3JDb250ZXh0SWQnKVxyXG4gIHNldCBlZGl0b3JDb250ZXh0SWQodmFsdWU6IHN0cmluZykge1xyXG4gICAgaWYgKCF2YWx1ZSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLmVkaXRvckNvbnRleHQgPSB0aGlzLmVkaXRvclNlcnZpY2UuZ2V0RWRpdG9yQ29udGV4dCh2YWx1ZSk7XHJcbiAgICB0aGlzLmFjdHVhbEN1cnNvclBvc0NoYW5nZWRTdWJzY3JpcHRpb24gPSB0aGlzLmVkaXRvckNvbnRleHQuZGVidWdTZXJ2aWNlLmFjdHVhbEN1cnNvclBvc0NoYW5nZWQkLnN1YnNjcmliZShwb3MgPT4ge1xyXG4gICAgICB0aGlzLmN1cnNvclBvc0luZm8gPSBwb3MuU3RhcnRQb3MuZ2V0RGVidWdEZXNjcmlwdGlvbigpO1xyXG4gICAgfSk7XHJcbiAgICB0aGlzLmlucHV0U2VsZWN0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5lZGl0b3JDb250ZXh0LmRlYnVnU2VydmljZS5pbnB1dFNlbGVjdGlvbkNoYW5nZWQkLnN1YnNjcmliZShpbmZvID0+IHtcclxuICAgICAgdGhpcy5pbnB1dFNlbGVjdGlvbiA9IGluZm87XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGN1cnNvclBvc0luZm86IHN0cmluZztcclxuICBpbnB1dFNlbGVjdGlvbjogc3RyaW5nO1xyXG5cclxuICBwcml2YXRlIGFjdHVhbEN1cnNvclBvc0NoYW5nZWRTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcclxuICBwcml2YXRlIGlucHV0U2VsZWN0aW9uU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWRpdG9yU2VydmljZTogQW5ndWxhclhtbEVkaXRvclNlcnZpY2UpIHt9XHJcblxyXG4gIG5nT25Jbml0KCkge31cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmFjdHVhbEN1cnNvclBvc0NoYW5nZWRTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICAgIHRoaXMuaW5wdXRTZWxlY3Rpb25TdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnYXhlZC1kb20tYnJlYWtjcnVtYicsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2RvbS1icmVha2NydW1iLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9kb20tYnJlYWtjcnVtYi5jb21wb25lbnQuY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIERvbUJyZWFrY3J1bWJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xyXG4gIG5vZGVzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICBjb25zdHJ1Y3RvcigpIHt9XHJcblxyXG4gIG5nT25Jbml0KCkge31cclxuXHJcbiAgc2hvd1NlbGVjdGlvbihzZWxlY3Rpb246IFNlbGVjdGlvbikge1xyXG4gICAgaWYgKHNlbGVjdGlvbiA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHRoaXMubm9kZXMgPSBbJ25vbmUnXTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnN0IGNvbGxlY3ROb2RlcyA9IFtdO1xyXG4gICAgICBsZXQgbm9kZSA9IHNlbGVjdGlvbi5mb2N1c05vZGU7XHJcbiAgICAgIGxldCByZWFjaGVkVG9wID0gbm9kZSA9PT0gdW5kZWZpbmVkIHx8IG5vZGUgPT09IG51bGw7XHJcbiAgICAgIHdoaWxlICghcmVhY2hlZFRvcCkge1xyXG4gICAgICAgIHN3aXRjaCAobm9kZS5ub2RlVHlwZSkge1xyXG4gICAgICAgICAgY2FzZSBOb2RlLkVMRU1FTlRfTk9ERTogLy8gZWxlbWVudCBub2RlXHJcbiAgICAgICAgICAgIGNvbnN0IGFzRWxlbWVudCA9IG5vZGUgYXMgRWxlbWVudDtcclxuICAgICAgICAgICAgaWYgKGFzRWxlbWVudCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgY29uc3QgbmFtZSA9IGFzRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtdGFnbmFtZScpO1xyXG4gICAgICAgICAgICAgIGlmIChhc0VsZW1lbnQuY2xhc3NOYW1lID09PSAnc3dzLXhtbC1lZGl0b3ItdGV4dGFyZWEnKSB7XHJcbiAgICAgICAgICAgICAgICByZWFjaGVkVG9wID0gdHJ1ZTtcclxuICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgY29sbGVjdE5vZGVzLnVuc2hpZnQobmFtZSk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG5vZGUgPSBub2RlLnBhcmVudEVsZW1lbnQ7XHJcbiAgICAgICAgaWYgKG5vZGUgPT09IHVuZGVmaW5lZCB8fCBub2RlID09IG51bGwpIHtcclxuICAgICAgICAgIHJlYWNoZWRUb3AgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICB0aGlzLm5vZGVzID0gY29sbGVjdE5vZGVzO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBBbmd1bGFyWG1sRWRpdG9yQ29tcG9uZW50IH0gZnJvbSAnLi9hbmd1bGFyLXhtbC1lZGl0b3IuY29tcG9uZW50JztcclxuaW1wb3J0IHsgWG1sRWRpdG9yVG9vbGJhckNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy94bWwtZWRpdG9yLXRvb2xiYXIveG1sLWVkaXRvci10b29sYmFyLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFhtbEVkaXRvckF0dHJpYnV0ZUVkaXRvckNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy94bWwtZWRpdG9yLWF0dHJpYnV0ZS1lZGl0b3IveG1sLWVkaXRvci1hdHRyaWJ1dGUtZWRpdG9yLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFhtbEVkaXRvckRlYnVnQ29tcG9uZW50IH0gZnJvbSAnLi9jb21wb25lbnRzL3htbC1lZGl0b3ItZGVidWcveG1sLWVkaXRvci1kZWJ1Zy5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBEb21CcmVha2NydW1iQ29tcG9uZW50IH0gZnJvbSAnLi9jb21wb25lbnRzL2RvbS1icmVha2NydW1iL2RvbS1icmVha2NydW1iLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFJlYWN0aXZlRm9ybXNNb2R1bGUsIEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuQE5nTW9kdWxlKHtcclxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBGb3Jtc01vZHVsZSwgUmVhY3RpdmVGb3Jtc01vZHVsZV0sXHJcbiAgZGVjbGFyYXRpb25zOiBbQW5ndWxhclhtbEVkaXRvckNvbXBvbmVudCwgWG1sRWRpdG9yVG9vbGJhckNvbXBvbmVudCwgWG1sRWRpdG9yQXR0cmlidXRlRWRpdG9yQ29tcG9uZW50LCBYbWxFZGl0b3JEZWJ1Z0NvbXBvbmVudCwgRG9tQnJlYWtjcnVtYkNvbXBvbmVudF0sXHJcbiAgZXhwb3J0czogW0FuZ3VsYXJYbWxFZGl0b3JDb21wb25lbnQsIFhtbEVkaXRvclRvb2xiYXJDb21wb25lbnQsIFhtbEVkaXRvckF0dHJpYnV0ZUVkaXRvckNvbXBvbmVudCwgWG1sRWRpdG9yRGVidWdDb21wb25lbnQsIERvbUJyZWFrY3J1bWJDb21wb25lbnRdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBBbmd1bGFyWG1sRWRpdG9yTW9kdWxlIHt9XHJcbiIsImV4cG9ydCBjbGFzcyBYbWxTY2hlbWEge1xyXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgeHNkTm9kZXM6IE1hcDxzdHJpbmcsIEVsZW1lbnQ+KSB7fVxyXG5cclxuICBmaW5kWHNkTm9kZUZvclRhZ05hbWUodGFnTmFtZTogc3RyaW5nKTogTm9kZSB7XHJcbiAgICByZXR1cm4gdGhpcy54c2ROb2Rlcy5nZXQodGFnTmFtZSk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IFhtbFNjaGVtYSB9IGZyb20gJy4veG1sU2NoZW1hLmNsYXNzJztcclxuXHJcbmV4cG9ydCBjbGFzcyBYbWxTY2hlbWFMb2FkZXIge1xyXG4gIHB1YmxpYyB4bWxTY2hlbWE6IFhtbFNjaGVtYTtcclxuXHJcbiAgcHVibGljIGNvbnN0cnVjdG9yKHNjaGVtYUNvbnRlbnQ6IHN0cmluZykge1xyXG4gICAgaWYgKCFzY2hlbWFDb250ZW50IHx8IHNjaGVtYUNvbnRlbnQgPT09ICcnKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGNvbnN0IGRvbXBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcclxuICAgIGNvbnN0IHNjaGVtYURvbSA9IGRvbXBhcnNlci5wYXJzZUZyb21TdHJpbmcoc2NoZW1hQ29udGVudCwgJ3RleHQveG1sJyk7XHJcbiAgICAvLyBjb25zdCByYXdFbGVtZW50cyA9IEFycmF5LmZyb20oc2NoZW1hRG9tLmRvY3VtZW50RWxlbWVudC5jaGlsZE5vZGVzKSBhcyBFbGVtZW50W107XHJcbiAgICAvLyB0aGlzLnhtbFNjaGVtYSA9IG5ldyBYbWxTY2hlbWEodGhpcy5nZXRYc2ROb2RlcyhyYXdFbGVtZW50cykpO1xyXG5cclxuICAgIGxldCByZXN1bHQ6IE5vZGVbXSA9IFtdO1xyXG4gICAgY29uc3QgcmF3RWxlbWVudHNBdFJvb3QgPSBBcnJheS5mcm9tKHNjaGVtYURvbS5kb2N1bWVudEVsZW1lbnQuY2hpbGROb2RlcykgYXMgRWxlbWVudFtdO1xyXG4gICAgcmF3RWxlbWVudHNBdFJvb3QuZm9yRWFjaChlID0+IHtcclxuICAgICAgY29uc3Qgc3ViQ2hpbGRzID0gdGhpcy5nZXRSYXdFbGVtZW50cyhlKTtcclxuICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdChzdWJDaGlsZHMpO1xyXG4gICAgfSk7XHJcbiAgICB0aGlzLnhtbFNjaGVtYSA9IG5ldyBYbWxTY2hlbWEodGhpcy5nZXRYc2ROb2RlcyhyZXN1bHQgYXMgRWxlbWVudFtdKSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldFJhd0VsZW1lbnRzKG5vZGU6IE5vZGUpOiBOb2RlW10ge1xyXG4gICAgbGV0IHJlc3VsdDogTm9kZVtdID0gW107XHJcbiAgICBpZiAodGhpcy5pc1ZhbGlkWHNkTm9kZShub2RlKSkge1xyXG4gICAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KG5vZGUpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGNoaWxkcmVuID0gQXJyYXkuZnJvbShub2RlLmNoaWxkTm9kZXMpIGFzIE5vZGVbXTtcclxuICAgIGNoaWxkcmVuLmZvckVhY2goY2hpbGQgPT4ge1xyXG4gICAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KHRoaXMuZ2V0UmF3RWxlbWVudHMoY2hpbGQpKTtcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGlzVmFsaWRYc2ROb2RlKG5vZGU6IE5vZGUpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IGFsbG93ZWRYc2RUeXBlcyA9IFsnZWxlbWVudCcsICdncm91cCcsICdjb21wbGV4VHlwZSddO1xyXG4gICAgY29uc3QgYXNFbGVtID0gbm9kZSBhcyBFbGVtZW50O1xyXG5cclxuICAgIGlmIChhc0VsZW0pIHtcclxuICAgICAgaWYgKGFsbG93ZWRYc2RUeXBlcy5pbmNsdWRlcyhhc0VsZW0ubG9jYWxOYW1lKSkge1xyXG4gICAgICAgIGlmIChhc0VsZW0uYXR0cmlidXRlcy5nZXROYW1lZEl0ZW0oJ25hbWUnKSkge1xyXG4gICAgICAgICAgLy8gY29uc29sZS53YXJuKGFzRWxlbS5hdHRyaWJ1dGVzLmdldE5hbWVkSXRlbSgnbmFtZScpLnZhbHVlKTtcclxuICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRYc2ROb2RlcyhyYXdFbGVtZW50czogRWxlbWVudFtdKSB7XHJcbiAgICAvLyBjb25zb2xlLndhcm4ocmF3RWxlbWVudHMubGVuZ3RoKTtcclxuICAgIHJldHVybiBuZXcgTWFwKHJhd0VsZW1lbnRzLm1hcDxbc3RyaW5nLCBFbGVtZW50XT4obiA9PiBbbi5hdHRyaWJ1dGVzLmdldE5hbWVkSXRlbSgnbmFtZScpLnZhbHVlLCBuIGFzIEVsZW1lbnRdKSk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IFhtbFJ1bGVFbGVtZW50IH0gZnJvbSAnLi94bWxSdWxlRWxlbWVudC5jbGFzcyc7XHJcblxyXG5leHBvcnQgY2xhc3MgWG1sUnVsZXMge1xyXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcnVsZUVsZW1lbnRzOiBNYXA8c3RyaW5nLCBYbWxSdWxlRWxlbWVudD4pIHt9XHJcbn1cclxuIiwiaW1wb3J0IHsgWG1sUnVsZUVsZW1lbnQgfSBmcm9tICcuL3htbFJ1bGVFbGVtZW50LmNsYXNzJztcclxuaW1wb3J0IHsgWG1sRWRpdFJ1bGVDaGVja1RleHRJbnNlcnQgfSBmcm9tICcuL3htbEVkaXRSdWxlQ2hlY2tUZXh0SW5zZXJ0LmNsYXNzJztcclxuaW1wb3J0IHsgWG1sUnVsZXMgfSBmcm9tICcuL3htbFJ1bGVzLmNsYXNzJztcclxuaW1wb3J0IHsgWG1sU2NoZW1hIH0gZnJvbSAnLi94bWxTY2hlbWEuY2xhc3MnO1xyXG5pbXBvcnQgeyBYbWwyaHRtbCB9IGZyb20gJy4uL3htbC1odG1sLWNvbnZlcnRlci94bWwyaHRtbC5jbGFzcyc7XHJcblxyXG5leHBvcnQgY2xhc3MgWG1sUnVsZXNDcmVhdG9yIHtcclxuICBwdWJsaWMgcnVsZXM6IFhtbFJ1bGVzO1xyXG5cclxuICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSBzY2hlbWE6IFhtbFNjaGVtYSwgcHJpdmF0ZSBfZmxvYXRpbmdFbGVtZW50TmFtZXM6IHN0cmluZ1tdKSB7XHJcbiAgICB0aGlzLnJ1bGVzID0gbmV3IFhtbFJ1bGVzKHRoaXMuZ2V0QWxsRWxlbWVudFJ1bGVOb2RlcyhBcnJheS5mcm9tKHRoaXMuc2NoZW1hLnhzZE5vZGVzLnZhbHVlcygpKSkpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmaW5kWHNkTm9kZUZvckh0bWxOb2RlKG5vZGU6IE5vZGUpOiBOb2RlIHtcclxuICAgIGNvbnN0IHRhZ05hbWUgPSBYbWwyaHRtbC5nZXRUYWdOYW1lRnJvbU5vZGUobm9kZSk7XHJcbiAgICByZXR1cm4gdGhpcy5zY2hlbWEueHNkTm9kZXMuZ2V0KHRhZ05hbWUpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRBbGxFbGVtZW50UnVsZU5vZGVzKHhzZE5vZGVzOiBFbGVtZW50W10pIHtcclxuICAgIHJldHVybiBuZXcgTWFwKHhzZE5vZGVzLm1hcDxbc3RyaW5nLCBYbWxSdWxlRWxlbWVudF0+KHhzZE5vZGUgPT4gW3hzZE5vZGUuYXR0cmlidXRlcy5nZXROYW1lZEl0ZW0oJ25hbWUnKS52YWx1ZSwgdGhpcy5nZXRSdWxlRWxlbWVudEZvclhzZE5vZGUoeHNkTm9kZSldKSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldFJ1bGVFbGVtZW50Rm9yWHNkTm9kZSh4c2ROb2RlOiBFbGVtZW50KTogWG1sUnVsZUVsZW1lbnQge1xyXG4gICAgaWYgKHhzZE5vZGUpIHtcclxuICAgICAgY29uc3QgdGFnTmFtZSA9IHhzZE5vZGUuYXR0cmlidXRlcy5nZXROYW1lZEl0ZW0oJ25hbWUnKS52YWx1ZTtcclxuICAgICAgcmV0dXJuIG5ldyBYbWxSdWxlRWxlbWVudCh7XHJcbiAgICAgICAgdGFnTmFtZTogdGFnTmFtZSxcclxuICAgICAgICBmbG9hdGluZzogdGhpcy5pc0Zsb2F0aW5nKHRhZ05hbWUpLFxyXG4gICAgICAgIGVtcHR5OiB0aGlzLmlzRW1wdHkoeHNkTm9kZSlcclxuICAgICAgICAvLyB4c2RSYXdOb2RlOiB4c2ROb2RlLFxyXG4gICAgICB9KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGlzRW1wdHkoeHNkTm9kZTogTm9kZSk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKG5ldyBYbWxFZGl0UnVsZUNoZWNrVGV4dEluc2VydCh0aGlzLnNjaGVtYS54c2ROb2RlcykuaXNUZXh0QWxsb3dlZEluVGhpc0VsZW1lbnQoeHNkTm9kZSkgPT09IHRydWUpIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGlzRmxvYXRpbmcodGFnTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5fZmxvYXRpbmdFbGVtZW50TmFtZXMuaW5jbHVkZXModGFnTmFtZSk7XHJcbiAgfVxyXG59XHJcbiJdLCJuYW1lcyI6WyJTdWJqZWN0IiwiSW5qZWN0YWJsZSIsIkluamVjdCIsIkRPQ1VNRU5UIiwiRXZlbnRFbWl0dGVyIiwiQ29tcG9uZW50IiwiVmlld0VuY2Fwc3VsYXRpb24iLCJOR19WQUxVRV9BQ0NFU1NPUiIsImZvcndhcmRSZWYiLCJSZW5kZXJlcjIiLCJJbnB1dCIsIlZpZXdDaGlsZCIsIk91dHB1dCIsIk5nTW9kdWxlIiwiQ29tbW9uTW9kdWxlIiwiRm9ybXNNb2R1bGUiLCJSZWFjdGl2ZUZvcm1zTW9kdWxlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQ0EsSUFNQSxJQUFBO1FBSUU7MkNBSGlDLElBQUlBLFlBQU8sRUFBYTswQ0FDekIsSUFBSUEsWUFBTyxFQUFVO1NBRXJDOzs7OztRQUVoQiw4Q0FBa0I7Ozs7WUFBbEIsVUFBbUIsR0FBYztnQkFDL0IsSUFBSSxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUN4Qzs7Ozs7UUFFRCw2Q0FBaUI7Ozs7WUFBakIsVUFBa0IsSUFBWTtnQkFDNUIsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUN4Qzs7OztRQUVELHVDQUFXOzs7WUFBWDtnQkFDRSxJQUFJLENBQUMsdUJBQXVCLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ3hDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQzthQUN4QztnQ0F4Qkg7UUF5QkMsQ0FBQTs7Ozs7O0lDekJELElBQUE7Ozs7Ozs7UUFNZ0IsOEJBQW1COzs7O3NCQUFDLElBQVU7Z0JBQzFDLFFBQVEsSUFBSSxDQUFDLFFBQVE7b0JBQ25CLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDcEIsS0FBSyxJQUFJLENBQUMsWUFBWTt3QkFDcEIsT0FBTyxJQUFJLENBQUM7b0JBQ2Q7d0JBQ0UsT0FBTyxLQUFLLENBQUM7aUJBQ2hCOzs7Ozs7O1FBS1csOEJBQW1COzs7O3NCQUFDLElBQVU7Z0JBQzFDLElBQUksSUFBSSxLQUFLLElBQUksSUFBSSxJQUFJLEtBQUssU0FBUyxFQUFFO29CQUN2QyxPQUFPLE1BQU0sQ0FBQztpQkFDZjtnQkFFRCxJQUFJLElBQUks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