diff --git a/README.md b/README.md
index 86a4df4..40fb4a7 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ has loaded.
# Getting started
-Checkout the Demo
+Checkout the Demo
and Blueprint
or `npm i -S search-collector`
diff --git a/demo/index.html b/demo/index.html
index 374bc22..544ef20 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -73,6 +73,10 @@
Usage
- Search for any search phrase
+ -
+ (Optional) search for a "redirect" to be redirected to a special campaign landing page to test redirect
+ tracking
+
- Click a product
- Put it into the basket
- Repeat as many times you wish
diff --git a/demo/js/collector-integration.js b/demo/js/collector-integration.js
index bbfeff5..f6104e9 100644
--- a/demo/js/collector-integration.js
+++ b/demo/js/collector-integration.js
@@ -24,7 +24,8 @@ const {
CheckoutClickCollector,
ConsoleTransport,
SuggestSearchCollector,
- AssociatedProductCollector
+ AssociatedProductCollector,
+ ListenerType,
} = window.SearchCollector;
@@ -88,13 +89,44 @@ collectorModule.add(new SuggestSearchCollector((writer, type, context) => {
});
}));
-collectorModule.add(new RedirectCollector(firedSearchCallback, isSearchPage, context));
+const redirectProductClickCollector = new ProductClickCollector('[data-track-id="product"]', {
+ idResolver: element => element.getAttribute('data-product-id'),
+ positionResolver: element => positionResolver('[data-track-id="product"]', element),
+ priceResolver: element => extractPrice(element.querySelector('[data-track-id="priceContainer"]')?.textContent),
+ metadataResolver: element => void 0, // metadata can be anything
+ trail
+});
+
+const redirectImpressionCollector = new ImpressionCollector('[data-track-id="product"]',
+ element => element.getAttribute('data-product-id'),
+ element => positionResolver('[data-track-id="product"]', element));
+
+redirectProductClickCollector.setContext(context);
+redirectImpressionCollector.setContext(context);
+
+collectorModule.add(new RedirectCollector(firedSearchCallback, isSearchPage, {
+ resultCountResolver: searchResultCountResolver,
+ collectors: [redirectProductClickCollector, redirectImpressionCollector],
+ nestedRedirects: {
+ depth: 2,
+ subSelectors: ['[data-track-id="redirectSubSelector"]']
+ }
+}, ListenerType.Sentinel, context));
+
+// basket PDP
collectorModule.add(
new BasketClickCollector('[data-track-id="addToCartPDP"]',
element => element.getAttribute('data-product-id'),
element => extractPrice(document.querySelector('[data-track-id="priceContainer"]').textContent))
);
+// basket PLP
+collectorModule.add(
+ new BasketClickCollector('[data-track-id="addToCartPLP"]',
+ element => element.getAttribute('data-product-id'),
+ element => extractPrice(document.querySelector('[data-track-id="priceContainer"]').textContent))
+);
+
collectorModule.add(
new CheckoutClickCollector('[data-track-id="checkoutButton"]', '[data-track-id="checkoutProduct"]',
element => element.getAttribute("data-product-id"),
diff --git a/demo/js/index.window.bundle.js b/demo/js/index.window.bundle.js
index c28914a..607ceb2 100644
--- a/demo/js/index.window.bundle.js
+++ b/demo/js/index.window.bundle.js
@@ -1,14 +1,548 @@
/******/ (() => { // webpackBootstrap
+/******/ "use strict";
/******/ var __webpack_modules__ = ({
-/***/ "./node_modules/scrollmonitor/scrollMonitor.js":
-/*!*****************************************************!*\
- !*** ./node_modules/scrollmonitor/scrollMonitor.js ***!
- \*****************************************************/
-/***/ (function(module) {
+/***/ "./node_modules/scrollmonitor/dist/module/index.js":
+/*!*********************************************************!*\
+ !*** ./node_modules/scrollmonitor/dist/module/index.js ***!
+ \*********************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-!function(t,e){ true?module.exports=e():0}(this,function(){return function(t){function e(o){if(i[o])return i[o].exports;var s=i[o]={exports:{},id:o,loaded:!1};return t[o].call(s.exports,s,s.exports,e),s.loaded=!0,s.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){"use strict";var o=i(1),s=o.isInBrowser,n=i(2),r=new n(s?document.body:null);r.setStateFromDOM(null),r.listenToDOM(),s&&(window.scrollMonitor=r),t.exports=r},function(t,e){"use strict";e.VISIBILITYCHANGE="visibilityChange",e.ENTERVIEWPORT="enterViewport",e.FULLYENTERVIEWPORT="fullyEnterViewport",e.EXITVIEWPORT="exitViewport",e.PARTIALLYEXITVIEWPORT="partiallyExitViewport",e.LOCATIONCHANGE="locationChange",e.STATECHANGE="stateChange",e.eventTypes=[e.VISIBILITYCHANGE,e.ENTERVIEWPORT,e.FULLYENTERVIEWPORT,e.EXITVIEWPORT,e.PARTIALLYEXITVIEWPORT,e.LOCATIONCHANGE,e.STATECHANGE],e.isOnServer="undefined"==typeof window,e.isInBrowser=!e.isOnServer,e.defaultOffsets={top:0,bottom:0}},function(t,e,i){"use strict";function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function s(t){return c?0:t===document.body?window.innerHeight||document.documentElement.clientHeight:t.clientHeight}function n(t){return c?0:t===document.body?Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.documentElement.clientHeight):t.scrollHeight}function r(t){return c?0:t===document.body?window.pageYOffset||document.documentElement&&document.documentElement.scrollTop||document.body.scrollTop:t.scrollTop}var h=i(1),c=h.isOnServer,a=h.isInBrowser,l=h.eventTypes,p=i(3),u=!1;if(a)try{var w=Object.defineProperty({},"passive",{get:function(){u=!0}});window.addEventListener("test",null,w)}catch(t){}var d=!!u&&{capture:!1,passive:!0},f=function(){function t(e,i){function h(){if(a.viewportTop=r(e),a.viewportBottom=a.viewportTop+a.viewportHeight,a.documentHeight=n(e),a.documentHeight!==p){for(u=a.watchers.length;u--;)a.watchers[u].recalculateLocation();p=a.documentHeight}}function c(){for(w=a.watchers.length;w--;)a.watchers[w].update();for(w=a.watchers.length;w--;)a.watchers[w].triggerCallbacks()}o(this,t);var a=this;this.item=e,this.watchers=[],this.viewportTop=null,this.viewportBottom=null,this.documentHeight=n(e),this.viewportHeight=s(e),this.DOMListener=function(){t.prototype.DOMListener.apply(a,arguments)},this.eventTypes=l,i&&(this.containerWatcher=i.create(e));var p,u,w;this.update=function(){h(),c()},this.recalculateLocations=function(){this.documentHeight=0,this.update()}}return t.prototype.listenToDOM=function(){a&&(window.addEventListener?(this.item===document.body?window.addEventListener("scroll",this.DOMListener,d):this.item.addEventListener("scroll",this.DOMListener,d),window.addEventListener("resize",this.DOMListener)):(this.item===document.body?window.attachEvent("onscroll",this.DOMListener):this.item.attachEvent("onscroll",this.DOMListener),window.attachEvent("onresize",this.DOMListener)),this.destroy=function(){window.addEventListener?(this.item===document.body?(window.removeEventListener("scroll",this.DOMListener,d),this.containerWatcher.destroy()):this.item.removeEventListener("scroll",this.DOMListener,d),window.removeEventListener("resize",this.DOMListener)):(this.item===document.body?(window.detachEvent("onscroll",this.DOMListener),this.containerWatcher.destroy()):this.item.detachEvent("onscroll",this.DOMListener),window.detachEvent("onresize",this.DOMListener))})},t.prototype.destroy=function(){},t.prototype.DOMListener=function(t){this.setStateFromDOM(t)},t.prototype.setStateFromDOM=function(t){var e=r(this.item),i=s(this.item),o=n(this.item);this.setState(e,i,o,t)},t.prototype.setState=function(t,e,i,o){var s=e!==this.viewportHeight||i!==this.contentHeight;if(this.latestEvent=o,this.viewportTop=t,this.viewportHeight=e,this.viewportBottom=t+e,this.contentHeight=i,s)for(var n=this.watchers.length;n--;)this.watchers[n].recalculateLocation();this.updateAndTriggerWatchers(o)},t.prototype.updateAndTriggerWatchers=function(t){for(var e=this.watchers.length;e--;)this.watchers[e].update();for(e=this.watchers.length;e--;)this.watchers[e].triggerCallbacks(t)},t.prototype.createCustomContainer=function(){return new t},t.prototype.createContainer=function(e){"string"==typeof e?e=document.querySelector(e):e&&e.length>0&&(e=e[0]);var i=new t(e,this);return i.setStateFromDOM(),i.listenToDOM(),i},t.prototype.create=function(t,e){"string"==typeof t?t=document.querySelector(t):t&&t.length>0&&(t=t[0]);var i=new p(this,t,e);return this.watchers.push(i),i},t.prototype.beget=function(t,e){return this.create(t,e)},t}();t.exports=f},function(t,e,i){"use strict";function o(t,e,i){function o(t,e){if(0!==t.length)for(E=t.length;E--;)y=t[E],y.callback.call(s,e,s),y.isOne&&t.splice(E,1)}var s=this;this.watchItem=e,this.container=t,i?i===+i?this.offsets={top:i,bottom:i}:this.offsets={top:i.top||w.top,bottom:i.bottom||w.bottom}:this.offsets=w,this.callbacks={};for(var d=0,f=u.length;d0?this.top=this.bottom=this.watchItem:this.top=this.bottom=this.container.documentHeight-this.watchItem:(this.top=this.watchItem.top,this.bottom=this.watchItem.bottom);this.top-=this.offsets.top,this.bottom+=this.offsets.bottom,this.height=this.bottom-this.top,void 0===t&&void 0===e||this.top===t&&this.bottom===e||o(this.callbacks[l],null)}},this.recalculateLocation(),this.update(),m=this.isInViewport,v=this.isFullyInViewport,b=this.isAboveViewport,I=this.isBelowViewport}var s=i(1),n=s.VISIBILITYCHANGE,r=s.ENTERVIEWPORT,h=s.FULLYENTERVIEWPORT,c=s.EXITVIEWPORT,a=s.PARTIALLYEXITVIEWPORT,l=s.LOCATIONCHANGE,p=s.STATECHANGE,u=s.eventTypes,w=s.defaultOffsets;o.prototype={on:function(t,e,i){switch(!0){case t===n&&!this.isInViewport&&this.isAboveViewport:case t===r&&this.isInViewport:case t===h&&this.isFullyInViewport:case t===c&&this.isAboveViewport&&!this.isInViewport:case t===a&&this.isInViewport&&this.isAboveViewport:if(e.call(this,this.container.latestEvent,this),i)return}if(!this.callbacks[t])throw new Error("Tried to add a scroll monitor listener of type "+t+". Your options are: "+u.join(", "));this.callbacks[t].push({callback:e,isOne:i||!1})},off:function(t,e){if(!this.callbacks[t])throw new Error("Tried to remove a scroll monitor listener of type "+t+". Your options are: "+u.join(", "));for(var i,o=0;i=this.callbacks[t][o];o++)if(i.callback===e){this.callbacks[t].splice(o,1);break}},one:function(t,e){this.on(t,e,!0)},recalculateSize:function(){this.height=this.watchItem.offsetHeight+this.offsets.top+this.offsets.bottom,this.bottom=this.top+this.height},update:function(){this.isAboveViewport=this.topthis.container.viewportBottom,this.isInViewport=this.topthis.container.viewportTop,this.isFullyInViewport=this.top>=this.container.viewportTop&&this.bottom<=this.container.viewportBottom||this.isAboveViewport&&this.isBelowViewport},destroy:function(){var t=this.container.watchers.indexOf(this),e=this;this.container.watchers.splice(t,1);for(var i=0,o=u.length;i (/* reexport safe */ _src_container_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMonitorContainer),
+/* harmony export */ "Watcher": () => (/* reexport safe */ _src_watcher_js__WEBPACK_IMPORTED_MODULE_1__.Watcher),
+/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
+/* harmony export */ });
+/* harmony import */ var _src_container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/container.js */ "./node_modules/scrollmonitor/dist/module/src/container.js");
+/* harmony import */ var _src_watcher_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./src/watcher.js */ "./node_modules/scrollmonitor/dist/module/src/watcher.js");
+/* harmony import */ var _src_types__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./src/types */ "./node_modules/scrollmonitor/dist/module/src/types.js");
+/* harmony import */ var _src_constants_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./src/constants.js */ "./node_modules/scrollmonitor/dist/module/src/constants.js");
+
+
+
+
+
+// this is needed for the type, but if we're not in a browser the only
+// way listenToDOM will be called is if you call scrollmonitor.createContainer
+// and you can't do that until you have a DOM element.
+var scrollMonitor = new _src_container_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMonitorContainer(_src_constants_js__WEBPACK_IMPORTED_MODULE_3__.isInBrowser ? document.body : undefined);
+if (_src_constants_js__WEBPACK_IMPORTED_MODULE_3__.isInBrowser) {
+ scrollMonitor.updateState();
+ scrollMonitor.listenToDOM();
+}
+//@ts-ignore
+window.scrollMonitor = scrollMonitor;
+/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (scrollMonitor);
+//# sourceMappingURL=index.js.map
+
+/***/ }),
+
+/***/ "./node_modules/scrollmonitor/dist/module/src/constants.js":
+/*!*****************************************************************!*\
+ !*** ./node_modules/scrollmonitor/dist/module/src/constants.js ***!
+ \*****************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */ "ENTERVIEWPORT": () => (/* binding */ ENTERVIEWPORT),
+/* harmony export */ "EXITVIEWPORT": () => (/* binding */ EXITVIEWPORT),
+/* harmony export */ "FULLYENTERVIEWPORT": () => (/* binding */ FULLYENTERVIEWPORT),
+/* harmony export */ "LOCATIONCHANGE": () => (/* binding */ LOCATIONCHANGE),
+/* harmony export */ "PARTIALLYEXITVIEWPORT": () => (/* binding */ PARTIALLYEXITVIEWPORT),
+/* harmony export */ "STATECHANGE": () => (/* binding */ STATECHANGE),
+/* harmony export */ "VISIBILITYCHANGE": () => (/* binding */ VISIBILITYCHANGE),
+/* harmony export */ "defaultOffsets": () => (/* binding */ defaultOffsets),
+/* harmony export */ "eventTypes": () => (/* binding */ eventTypes),
+/* harmony export */ "isInBrowser": () => (/* binding */ isInBrowser),
+/* harmony export */ "isOnServer": () => (/* binding */ isOnServer)
+/* harmony export */ });
+var VISIBILITYCHANGE = 'visibilityChange';
+var ENTERVIEWPORT = 'enterViewport';
+var FULLYENTERVIEWPORT = 'fullyEnterViewport';
+var EXITVIEWPORT = 'exitViewport';
+var PARTIALLYEXITVIEWPORT = 'partiallyExitViewport';
+var LOCATIONCHANGE = 'locationChange';
+var STATECHANGE = 'stateChange';
+var eventTypes = [
+ VISIBILITYCHANGE,
+ ENTERVIEWPORT,
+ FULLYENTERVIEWPORT,
+ EXITVIEWPORT,
+ PARTIALLYEXITVIEWPORT,
+ LOCATIONCHANGE,
+ STATECHANGE,
+];
+var isOnServer = typeof window === 'undefined';
+var isInBrowser = !isOnServer;
+var defaultOffsets = { top: 0, bottom: 0 };
+//# sourceMappingURL=constants.js.map
+
+/***/ }),
+
+/***/ "./node_modules/scrollmonitor/dist/module/src/container.js":
+/*!*****************************************************************!*\
+ !*** ./node_modules/scrollmonitor/dist/module/src/container.js ***!
+ \*****************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */ "ScrollMonitorContainer": () => (/* binding */ ScrollMonitorContainer)
+/* harmony export */ });
+/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants.js */ "./node_modules/scrollmonitor/dist/module/src/constants.js");
+/* harmony import */ var _watcher_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./watcher.js */ "./node_modules/scrollmonitor/dist/module/src/watcher.js");
+
+
+function getViewportHeight(element) {
+ if (_constants_js__WEBPACK_IMPORTED_MODULE_0__.isOnServer) {
+ return 0;
+ }
+ if (element === document.body) {
+ return window.innerHeight || document.documentElement.clientHeight;
+ }
+ else {
+ return element.clientHeight;
+ }
+}
+function getContentHeight(element) {
+ if (_constants_js__WEBPACK_IMPORTED_MODULE_0__.isOnServer) {
+ return 0;
+ }
+ if (element === document.body) {
+ // jQuery approach
+ // whichever is greatest
+ return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.documentElement.clientHeight);
+ }
+ else {
+ return element.scrollHeight;
+ }
+}
+function scrollTop(element) {
+ if (_constants_js__WEBPACK_IMPORTED_MODULE_0__.isOnServer) {
+ return 0;
+ }
+ if (element === document.body) {
+ return (window.pageYOffset ||
+ (document.documentElement && document.documentElement.scrollTop) ||
+ document.body.scrollTop);
+ }
+ else {
+ return element.scrollTop;
+ }
+}
+var browserSupportsPassive = false;
+if (_constants_js__WEBPACK_IMPORTED_MODULE_0__.isInBrowser) {
+ try {
+ var opts = Object.defineProperty({}, 'passive', {
+ get: function () {
+ browserSupportsPassive = true;
+ },
+ });
+ window.addEventListener('test', null, opts);
+ }
+ catch (e) { }
+}
+var useCapture = browserSupportsPassive ? { capture: false, passive: true } : false;
+var ScrollMonitorContainer = /** @class */ (function () {
+ function ScrollMonitorContainer(item, parentWatcher) {
+ this.eventTypes = _constants_js__WEBPACK_IMPORTED_MODULE_0__.eventTypes;
+ var self = this;
+ this.item = item;
+ this.watchers = [];
+ this.viewportTop = null;
+ this.viewportBottom = null;
+ this.documentHeight = getContentHeight(item);
+ this.viewportHeight = getViewportHeight(item);
+ this.DOMListener = function () {
+ ScrollMonitorContainer.prototype.DOMListener.apply(self, arguments);
+ };
+ if (parentWatcher) {
+ this.containerWatcher = parentWatcher.create(item);
+ }
+ var previousDocumentHeight;
+ var calculateViewportI;
+ function calculateViewport() {
+ self.viewportTop = scrollTop(item);
+ self.viewportBottom = self.viewportTop + self.viewportHeight;
+ self.documentHeight = getContentHeight(item);
+ if (self.documentHeight !== previousDocumentHeight) {
+ calculateViewportI = self.watchers.length;
+ while (calculateViewportI--) {
+ self.watchers[calculateViewportI].recalculateLocation();
+ }
+ previousDocumentHeight = self.documentHeight;
+ }
+ }
+ var updateAndTriggerWatchersI;
+ function updateAndTriggerWatchers() {
+ // update all watchers then trigger the events so one can rely on another being up to date.
+ updateAndTriggerWatchersI = self.watchers.length;
+ while (updateAndTriggerWatchersI--) {
+ self.watchers[updateAndTriggerWatchersI].update();
+ }
+ updateAndTriggerWatchersI = self.watchers.length;
+ while (updateAndTriggerWatchersI--) {
+ self.watchers[updateAndTriggerWatchersI].triggerCallbacks(undefined);
+ }
+ }
+ this.update = function () {
+ calculateViewport();
+ updateAndTriggerWatchers();
+ };
+ this.recalculateLocations = function () {
+ this.documentHeight = 0;
+ this.update();
+ };
+ }
+ ScrollMonitorContainer.prototype.listenToDOM = function () {
+ if (_constants_js__WEBPACK_IMPORTED_MODULE_0__.isInBrowser) {
+ if (this.item === document.body) {
+ window.addEventListener('scroll', this.DOMListener, useCapture);
+ }
+ else {
+ this.item.addEventListener('scroll', this.DOMListener, useCapture);
+ }
+ window.addEventListener('resize', this.DOMListener);
+ this.destroy = function () {
+ if (this.item === document.body) {
+ window.removeEventListener('scroll', this.DOMListener, useCapture);
+ this.containerWatcher.destroy();
+ }
+ else {
+ this.item.removeEventListener('scroll', this.DOMListener, useCapture);
+ }
+ window.removeEventListener('resize', this.DOMListener);
+ };
+ }
+ };
+ ScrollMonitorContainer.prototype.destroy = function () {
+ // noop, override for your own purposes.
+ // in listenToDOM, for example.
+ };
+ ScrollMonitorContainer.prototype.DOMListener = function (event) {
+ //alert('got scroll');
+ this.updateState();
+ this.updateAndTriggerWatchers(event);
+ };
+ ScrollMonitorContainer.prototype.updateState = function () {
+ var viewportTop = scrollTop(this.item);
+ var viewportHeight = getViewportHeight(this.item);
+ var contentHeight = getContentHeight(this.item);
+ var needsRecalcuate = viewportHeight !== this.viewportHeight || contentHeight !== this.contentHeight;
+ this.viewportTop = viewportTop;
+ this.viewportHeight = viewportHeight;
+ this.viewportBottom = viewportTop + viewportHeight;
+ this.contentHeight = contentHeight;
+ if (needsRecalcuate) {
+ var i = this.watchers.length;
+ while (i--) {
+ this.watchers[i].recalculateLocation();
+ }
+ }
+ };
+ ScrollMonitorContainer.prototype.updateAndTriggerWatchers = function (event) {
+ var i = this.watchers.length;
+ while (i--) {
+ this.watchers[i].update();
+ }
+ i = this.watchers.length;
+ while (i--) {
+ this.watchers[i].triggerCallbacks(event);
+ }
+ };
+ ScrollMonitorContainer.prototype.createContainer = function (input) {
+ var item;
+ if (typeof input === 'string') {
+ item = document.querySelector(input);
+ }
+ else if (Array.isArray(input) || input instanceof NodeList) {
+ item = input[0];
+ }
+ else {
+ item = input;
+ }
+ var container = new ScrollMonitorContainer(item, this);
+ this.updateState();
+ container.listenToDOM();
+ return container;
+ };
+ ScrollMonitorContainer.prototype.create = function (input, offsets) {
+ var item;
+ if (typeof item === 'string') {
+ item = document.querySelector(item);
+ }
+ else if (Array.isArray(input) || input instanceof NodeList) {
+ item = input[0];
+ }
+ else {
+ item = input;
+ }
+ var watcher = new _watcher_js__WEBPACK_IMPORTED_MODULE_1__.Watcher(this, item, offsets);
+ this.watchers.push(watcher);
+ return watcher;
+ };
+ /**
+ * @deprecated since version 1.1
+ */
+ ScrollMonitorContainer.prototype.beget = function (input, offsets) {
+ return this.create(input, offsets);
+ };
+ return ScrollMonitorContainer;
+}());
+
+//# sourceMappingURL=container.js.map
+
+/***/ }),
+
+/***/ "./node_modules/scrollmonitor/dist/module/src/types.js":
+/*!*************************************************************!*\
+ !*** ./node_modules/scrollmonitor/dist/module/src/types.js ***!
+ \*************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+__webpack_require__.r(__webpack_exports__);
+
+//# sourceMappingURL=types.js.map
+
+/***/ }),
+
+/***/ "./node_modules/scrollmonitor/dist/module/src/watcher.js":
+/*!***************************************************************!*\
+ !*** ./node_modules/scrollmonitor/dist/module/src/watcher.js ***!
+ \***************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */ "Watcher": () => (/* binding */ Watcher)
+/* harmony export */ });
+/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants.js */ "./node_modules/scrollmonitor/dist/module/src/constants.js");
+
+var Watcher = /** @class */ (function () {
+ function Watcher(container, watchItem, offsets) {
+ this.container = container;
+ this.watchItem = watchItem;
+ this.locked = false;
+ this.callbacks = {};
+ var self = this;
+ if (!offsets) {
+ this.offsets = _constants_js__WEBPACK_IMPORTED_MODULE_0__.defaultOffsets;
+ }
+ else if (typeof offsets === 'number') {
+ this.offsets = { top: offsets, bottom: offsets };
+ }
+ else {
+ this.offsets = {
+ top: 'top' in offsets ? offsets.top : _constants_js__WEBPACK_IMPORTED_MODULE_0__.defaultOffsets.top,
+ bottom: 'bottom' in offsets ? offsets.bottom : _constants_js__WEBPACK_IMPORTED_MODULE_0__.defaultOffsets.bottom,
+ };
+ }
+ for (var i = 0, j = _constants_js__WEBPACK_IMPORTED_MODULE_0__.eventTypes.length; i < j; i++) {
+ self.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.eventTypes[i]] = [];
+ }
+ this.locked = false;
+ var wasInViewport;
+ var wasFullyInViewport;
+ var wasAboveViewport;
+ var wasBelowViewport;
+ var listenerToTriggerListI;
+ var listener;
+ var needToTriggerStateChange = false;
+ function triggerCallbackArray(listeners, event) {
+ needToTriggerStateChange = true;
+ if (listeners.length === 0) {
+ return;
+ }
+ listenerToTriggerListI = listeners.length;
+ while (listenerToTriggerListI--) {
+ listener = listeners[listenerToTriggerListI];
+ listener.callback.call(self, event, self);
+ if (listener.isOne) {
+ listeners.splice(listenerToTriggerListI, 1);
+ }
+ }
+ }
+ this.triggerCallbacks = function triggerCallbacks(event) {
+ if (this.isInViewport && !wasInViewport) {
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.ENTERVIEWPORT], event);
+ }
+ if (this.isFullyInViewport && !wasFullyInViewport) {
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.FULLYENTERVIEWPORT], event);
+ }
+ if (this.isAboveViewport !== wasAboveViewport &&
+ this.isBelowViewport !== wasBelowViewport) {
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.VISIBILITYCHANGE], event);
+ // if you skip completely past this element
+ if (!wasFullyInViewport && !this.isFullyInViewport) {
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.FULLYENTERVIEWPORT], event);
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.PARTIALLYEXITVIEWPORT], event);
+ }
+ if (!wasInViewport && !this.isInViewport) {
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.ENTERVIEWPORT], event);
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.EXITVIEWPORT], event);
+ }
+ }
+ if (!this.isFullyInViewport && wasFullyInViewport) {
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.PARTIALLYEXITVIEWPORT], event);
+ }
+ if (!this.isInViewport && wasInViewport) {
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.EXITVIEWPORT], event);
+ }
+ if (this.isInViewport !== wasInViewport) {
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.VISIBILITYCHANGE], event);
+ }
+ if (needToTriggerStateChange) {
+ needToTriggerStateChange = false;
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.STATECHANGE], event);
+ }
+ wasInViewport = this.isInViewport;
+ wasFullyInViewport = this.isFullyInViewport;
+ wasAboveViewport = this.isAboveViewport;
+ wasBelowViewport = this.isBelowViewport;
+ };
+ this.recalculateLocation = function () {
+ if (this.locked) {
+ return;
+ }
+ var previousTop = this.top;
+ var previousBottom = this.bottom;
+ if (this.watchItem.nodeName) {
+ // a dom element
+ var cachedDisplay = this.watchItem.style.display;
+ if (cachedDisplay === 'none') {
+ this.watchItem.style.display = '';
+ }
+ var containerOffset = 0;
+ var container = this.container;
+ while (container.containerWatcher) {
+ containerOffset +=
+ container.containerWatcher.top -
+ container.containerWatcher.container.viewportTop;
+ container = container.containerWatcher.container;
+ }
+ var boundingRect = this.watchItem.getBoundingClientRect();
+ this.top = boundingRect.top + this.container.viewportTop - containerOffset;
+ this.bottom = boundingRect.bottom + this.container.viewportTop - containerOffset;
+ if (cachedDisplay === 'none') {
+ this.watchItem.style.display = cachedDisplay;
+ }
+ }
+ else if (this.watchItem === +this.watchItem) {
+ // number
+ if (this.watchItem > 0) {
+ this.top = this.bottom = this.watchItem;
+ }
+ else {
+ this.top = this.bottom = this.container.documentHeight - this.watchItem;
+ }
+ }
+ else {
+ // an object with a top and bottom property
+ this.top = this.watchItem.top;
+ this.bottom = this.watchItem.bottom;
+ }
+ this.top -= this.offsets.top;
+ this.bottom += this.offsets.bottom;
+ this.height = this.bottom - this.top;
+ if ((previousTop !== undefined || previousBottom !== undefined) &&
+ (this.top !== previousTop || this.bottom !== previousBottom)) {
+ triggerCallbackArray(this.callbacks[_constants_js__WEBPACK_IMPORTED_MODULE_0__.LOCATIONCHANGE], undefined);
+ }
+ };
+ this.recalculateLocation();
+ this.update();
+ wasInViewport = this.isInViewport;
+ wasFullyInViewport = this.isFullyInViewport;
+ wasAboveViewport = this.isAboveViewport;
+ wasBelowViewport = this.isBelowViewport;
+ }
+ Watcher.prototype.on = function (event, callback, isOne) {
+ if (isOne === void 0) { isOne = false; }
+ // trigger the event if it applies to the element right now.
+ switch (true) {
+ case event === _constants_js__WEBPACK_IMPORTED_MODULE_0__.VISIBILITYCHANGE && !this.isInViewport && this.isAboveViewport:
+ case event === _constants_js__WEBPACK_IMPORTED_MODULE_0__.ENTERVIEWPORT && this.isInViewport:
+ case event === _constants_js__WEBPACK_IMPORTED_MODULE_0__.FULLYENTERVIEWPORT && this.isFullyInViewport:
+ case event === _constants_js__WEBPACK_IMPORTED_MODULE_0__.EXITVIEWPORT && this.isAboveViewport && !this.isInViewport:
+ case event === _constants_js__WEBPACK_IMPORTED_MODULE_0__.PARTIALLYEXITVIEWPORT && this.isInViewport && this.isAboveViewport:
+ callback.call(this, this);
+ if (isOne) {
+ return;
+ }
+ }
+ if (this.callbacks[event]) {
+ this.callbacks[event].push({ callback: callback, isOne: isOne });
+ }
+ else {
+ throw new Error('Tried to add a scroll monitor listener of type ' +
+ event +
+ '. Your options are: ' +
+ _constants_js__WEBPACK_IMPORTED_MODULE_0__.eventTypes.join(', '));
+ }
+ };
+ Watcher.prototype.off = function (event, callback) {
+ if (this.callbacks[event]) {
+ for (var i = 0, item; (item = this.callbacks[event][i]); i++) {
+ if (item.callback === callback) {
+ this.callbacks[event].splice(i, 1);
+ break;
+ }
+ }
+ }
+ else {
+ throw new Error('Tried to remove a scroll monitor listener of type ' +
+ event +
+ '. Your options are: ' +
+ _constants_js__WEBPACK_IMPORTED_MODULE_0__.eventTypes.join(', '));
+ }
+ };
+ Watcher.prototype.one = function (event, callback) {
+ this.on(event, callback, true);
+ };
+ Watcher.prototype.recalculateSize = function () {
+ if (this.watchItem instanceof HTMLElement) {
+ this.height = this.watchItem.offsetHeight + this.offsets.top + this.offsets.bottom;
+ this.bottom = this.top + this.height;
+ }
+ };
+ Watcher.prototype.update = function () {
+ this.isAboveViewport = this.top < this.container.viewportTop;
+ this.isBelowViewport = this.bottom > this.container.viewportBottom;
+ this.isInViewport =
+ this.top < this.container.viewportBottom && this.bottom > this.container.viewportTop;
+ this.isFullyInViewport =
+ (this.top >= this.container.viewportTop &&
+ this.bottom <= this.container.viewportBottom) ||
+ (this.isAboveViewport && this.isBelowViewport);
+ };
+ Watcher.prototype.destroy = function () {
+ var index = this.container.watchers.indexOf(this), self = this;
+ this.container.watchers.splice(index, 1);
+ self.callbacks = {};
+ };
+ // prevent recalculating the element location
+ Watcher.prototype.lock = function () {
+ this.locked = true;
+ };
+ Watcher.prototype.unlock = function () {
+ this.locked = false;
+ };
+ return Watcher;
+}());
+
+var eventHandlerFactory = function (type) {
+ return function (callback, isOne) {
+ if (isOne === void 0) { isOne = false; }
+ this.on.call(this, type, callback, isOne);
+ };
+};
+for (var i = 0, j = _constants_js__WEBPACK_IMPORTED_MODULE_0__.eventTypes.length; i < j; i++) {
+ var type = _constants_js__WEBPACK_IMPORTED_MODULE_0__.eventTypes[i];
+ Watcher.prototype[type] = eventHandlerFactory(type);
+}
+//# sourceMappingURL=watcher.js.map
/***/ }),
@@ -18,16 +552,13 @@
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "CollectorModule": () => (/* binding */ CollectorModule)
/* harmony export */ });
-/* harmony import */ var _writers_SplitStreamWriter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./writers/SplitStreamWriter */ "./src/main/writers/SplitStreamWriter.ts");
-/* harmony import */ var _logger_TransportLogger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./logger/TransportLogger */ "./src/main/logger/TransportLogger.ts");
-/* harmony import */ var _writers_ConsoleWriter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./writers/ConsoleWriter */ "./src/main/writers/ConsoleWriter.ts");
-/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./logger */ "./src/main/logger/index.ts");
-
+/* harmony import */ var _writers__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./writers */ "./src/main/writers/index.ts");
+/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./logger */ "./src/main/logger/index.ts");
+/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ "./src/main/utils/index.ts");
@@ -43,8 +574,8 @@ class CollectorModule {
this.options = options || {};
}
add(collector) {
- if (this.options.context && !collector.getContext())
- collector.setContext(this.options.context);
+ if (!collector.getContext())
+ collector.setContext(this.options.context || new _utils__WEBPACK_IMPORTED_MODULE_2__.Context(window, document));
this.collectors.push(collector);
if (this.hasStarted === true)
this.invokedCollector(collector);
@@ -83,17 +614,14 @@ class CollectorModule {
if (hasLogger)
return this.logger;
if (!this.transports || this.transports.length === 0) {
- console.warn("ATTENTION-SEARCH-COLLECTOR-WARNING");
- console.warn("search-collector: no LoggerTransport configured while using the default TransportLogger. Please add a transport CollectorModule#addLogTransport or CollectorModule#setTransports");
- console.warn("search-collector: will FALLBACK to ConsoleTransport");
- return new _logger_TransportLogger__WEBPACK_IMPORTED_MODULE_1__.TransportLogger([new _logger__WEBPACK_IMPORTED_MODULE_3__.ConsoleTransport()]);
+ return new _logger__WEBPACK_IMPORTED_MODULE_1__.TransportLogger([new _logger__WEBPACK_IMPORTED_MODULE_1__.ConsoleTransport()]);
}
- return new _logger_TransportLogger__WEBPACK_IMPORTED_MODULE_1__.TransportLogger(this.transports);
+ return new _logger__WEBPACK_IMPORTED_MODULE_1__.TransportLogger(this.transports);
}
getWriter() {
return this.writers.length == 0
- ? this.options.writer || new _writers_ConsoleWriter__WEBPACK_IMPORTED_MODULE_2__.ConsoleWriter()
- : new _writers_SplitStreamWriter__WEBPACK_IMPORTED_MODULE_0__.SplitStreamWriter(this.writers);
+ ? this.options.writer || new _writers__WEBPACK_IMPORTED_MODULE_0__.ConsoleWriter()
+ : new _writers__WEBPACK_IMPORTED_MODULE_0__.SplitStreamWriter(this.writers);
}
}
@@ -106,15 +634,12 @@ class CollectorModule {
\**************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "AbstractCollector": () => (/* binding */ AbstractCollector)
/* harmony export */ });
-/* harmony import */ var _utils_Context__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/Context */ "./src/main/utils/Context.ts");
-
class AbstractCollector {
- constructor(type, context = new _utils_Context__WEBPACK_IMPORTED_MODULE_0__.Context(window, document)) {
+ constructor(type, context) {
this.type = type;
this.context = context;
}
@@ -150,7 +675,8 @@ class AbstractCollector {
return handler(...args, ...handlerArgs);
}
catch (e) {
- log.error(`[${this.constructor.name}] Unexpected error during resolver execution: `, e);
+ if (log)
+ log.error(`[${this.constructor.name}] Unexpected error during resolver execution: `, e);
}
};
}
@@ -172,7 +698,9 @@ class AbstractCollector {
}
}
catch (e) {
- log.error(`[${this.constructor.name}] Unexpected error during resolver execution: `, e);
+ if (log && log.error) {
+ log.error(`[${this.constructor.name}] Unexpected error during resolver execution: `, e);
+ }
}
}
}
@@ -186,7 +714,6 @@ class AbstractCollector {
\***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "AssociatedProductCollector": () => (/* binding */ AssociatedProductCollector)
@@ -273,7 +800,6 @@ class AssociatedProductCollector extends _AbstractCollector__WEBPACK_IMPORTED_MO
\*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "BasketClickCollector": () => (/* binding */ BasketClickCollector)
@@ -315,7 +841,6 @@ class BasketClickCollector extends _ClickCollector__WEBPACK_IMPORTED_MODULE_0__.
\*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "BrowserCollector": () => (/* binding */ BrowserCollector)
@@ -327,11 +852,12 @@ __webpack_require__.r(__webpack_exports__);
* need to consult the GDPR guidelines
*/
class BrowserCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__.AbstractCollector {
- constructor(options = { recordUrl: true, recordReferrer: true, recordLanguage: false }) {
+ constructor(options = { recordUrl: true, recordReferrer: true, recordLanguage: false, recordUserAgent: false }) {
super("browser");
this.recordUrl = options.recordUrl || false;
this.recordReferrer = options.recordReferrer || false;
this.recordLanguage = options.recordLanguage || false;
+ this.recordUserAgent = options.recordUserAgent || false;
}
/**
* Attach a writer, note that this collector is not asynchronous and will write
@@ -352,6 +878,8 @@ class BrowserCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__.A
data.url = win.location.href;
if (this.recordReferrer)
data.ref = doc.referrer;
+ if (this.recordUserAgent)
+ data.agent = window.navigator.userAgent;
writer.write(data);
}
}
@@ -365,7 +893,6 @@ class BrowserCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__.A
\*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "CheckoutClickCollector": () => (/* binding */ CheckoutClickCollector)
@@ -427,11 +954,17 @@ class CheckoutClickCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE
// "sentinel (default)" - works on elements inserted in the DOM anytime, but interferes with CSS animations on these elements
if (this.listenerType === _utils_ListenerType__WEBPACK_IMPORTED_MODULE_2__.ListenerType.Dom) {
const nodeList = doc.querySelectorAll(this.clickSelector);
- nodeList.forEach((el) => el.addEventListener("click", this.logWrapHandler(handler, log)));
+ nodeList.forEach((el) => el.addEventListener("click", this.logWrapHandler(handler, log), {
+ passive: true,
+ capture: true
+ }));
}
else {
const sentinel = new _utils_Sentinel__WEBPACK_IMPORTED_MODULE_1__.Sentinel(this.getDocument());
- sentinel.on(this.clickSelector, el => el.addEventListener("click", this.logWrapHandler(handler, log)));
+ sentinel.on(this.clickSelector, el => el.addEventListener("click", this.logWrapHandler(handler, log), {
+ passive: true,
+ capture: true
+ }));
}
}
}
@@ -445,7 +978,6 @@ class CheckoutClickCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ClickCollector": () => (/* binding */ ClickCollector)
@@ -471,9 +1003,10 @@ class ClickCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__.Abs
* @param {string} selectorExpression - Document query selector identifying the elements to attach to
* @param {string} type - The type OF element click to report
* @param {string} listenerType - Whether the listener should be a dom or sentinel listener
+ * @param context
*/
- constructor(selectorExpression, type = "click", listenerType = _utils_ListenerType__WEBPACK_IMPORTED_MODULE_2__.ListenerType.Sentinel) {
- super(type);
+ constructor(selectorExpression, type = "click", listenerType = _utils_ListenerType__WEBPACK_IMPORTED_MODULE_2__.ListenerType.Sentinel, context) {
+ super(type, context);
this.selectorExpression = selectorExpression;
this.listenerType = listenerType;
}
@@ -508,11 +1041,17 @@ class ClickCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__.Abs
// "sentinel (default)" - works on elements inserted in the DOM anytime, but interferes with CSS animations on these elements
if (this.listenerType === _utils_ListenerType__WEBPACK_IMPORTED_MODULE_2__.ListenerType.Dom) {
const nodeList = this.getDocument().querySelectorAll(this.selectorExpression);
- nodeList.forEach((el) => el.addEventListener("click", this.logWrapHandler(handler, log, el)));
+ nodeList.forEach((el) => el.addEventListener("click", this.logWrapHandler(handler, log, el), {
+ passive: true,
+ capture: true
+ }));
}
else {
const sentinel = new _utils_Sentinel__WEBPACK_IMPORTED_MODULE_1__.Sentinel(this.getDocument());
- sentinel.on(this.selectorExpression, el => el.addEventListener("click", this.logWrapHandler(handler, log, el)));
+ sentinel.on(this.selectorExpression, el => el.addEventListener("click", this.logWrapHandler(handler, log, el), {
+ passive: true,
+ capture: true
+ }));
}
}
}
@@ -526,7 +1065,6 @@ class ClickCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__.Abs
\*************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ClickWriterResolverCollector": () => (/* binding */ ClickWriterResolverCollector)
@@ -560,11 +1098,17 @@ class ClickWriterResolverCollector extends _WriterResolverCollector__WEBPACK_IMP
};
if (this.listenerType === _utils_ListenerType__WEBPACK_IMPORTED_MODULE_0__.ListenerType.Dom) {
const nodeList = this.getDocument().querySelectorAll(this.selectorExpression);
- nodeList.forEach(el => el.addEventListener("click", ev => this.logWrapHandler(handler, log, el, ev)()));
+ nodeList.forEach(el => el.addEventListener("click", ev => this.logWrapHandler(handler, log, el, ev)(), {
+ passive: true,
+ capture: true
+ }));
}
else {
const sentinel = new _utils_Sentinel__WEBPACK_IMPORTED_MODULE_1__.Sentinel(this.getDocument());
- sentinel.on(this.selectorExpression, el => el.addEventListener("click", ev => this.logWrapHandler(handler, log, el, ev)()));
+ sentinel.on(this.selectorExpression, el => el.addEventListener("click", ev => this.logWrapHandler(handler, log, el, ev)(), {
+ passive: true,
+ capture: true
+ }));
}
}
}
@@ -578,7 +1122,6 @@ class ClickWriterResolverCollector extends _WriterResolverCollector__WEBPACK_IMP
\*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "FilterClickCollector": () => (/* binding */ FilterClickCollector)
@@ -611,7 +1154,6 @@ class FilterClickCollector extends _ClickCollector__WEBPACK_IMPORTED_MODULE_0__.
\*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "FiredSearchCollector": () => (/* binding */ FiredSearchCollector)
@@ -642,7 +1184,6 @@ class FiredSearchCollector extends _WriterResolverCollector__WEBPACK_IMPORTED_MO
\******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "GenericEventCollector": () => (/* binding */ GenericEventCollector)
@@ -693,15 +1234,13 @@ class GenericEventCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_
\****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ImpressionCollector": () => (/* binding */ ImpressionCollector)
/* harmony export */ });
/* harmony import */ var _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractCollector */ "./src/main/collectors/AbstractCollector.ts");
/* harmony import */ var _utils_Sentinel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/Sentinel */ "./src/main/utils/Sentinel.ts");
-/* harmony import */ var scrollmonitor__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! scrollmonitor */ "./node_modules/scrollmonitor/scrollMonitor.js");
-/* harmony import */ var scrollmonitor__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(scrollmonitor__WEBPACK_IMPORTED_MODULE_2__);
+/* harmony import */ var scrollmonitor__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! scrollmonitor */ "./node_modules/scrollmonitor/dist/module/index.js");
/* harmony import */ var _utils_LocalStorageQueue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/LocalStorageQueue */ "./src/main/utils/LocalStorageQueue.ts");
/* harmony import */ var _utils_Util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/Util */ "./src/main/utils/Util.ts");
@@ -723,12 +1262,14 @@ class ImpressionCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0_
* @param {string} selectorExpression - Document query selector identifying the elements to attach to
* @param idResolver - Resolve the id of the element
* @param positionResolver - Resolve the position of the element in dom
+ * @param expectedPageResolver - If supplied, impressions will only be tracked if this resolver returns true. Comes in handy for single page applications
*/
- constructor(selectorExpression, idResolver, positionResolver) {
+ constructor(selectorExpression, idResolver, positionResolver, expectedPageResolver) {
super("impression");
this.selectorExpression = selectorExpression;
this.idResolver = idResolver;
this.positionResolver = positionResolver;
+ this.expectedPageResolver = expectedPageResolver;
this.queue = new _utils_LocalStorageQueue__WEBPACK_IMPORTED_MODULE_3__.LocalStorageQueue("impressions");
}
/**
@@ -749,13 +1290,16 @@ class ImpressionCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0_
.catch(err => log.error("Could not drain queue: ", err));
}, 250);
const handler = element => {
- scrollmonitor__WEBPACK_IMPORTED_MODULE_2___default().create(element).enterViewport(() => {
+ scrollmonitor__WEBPACK_IMPORTED_MODULE_2__["default"].create(element).enterViewport(() => {
+ if (this.expectedPageResolver && !this.expectedPageResolver()) {
+ return;
+ }
this.queue.push({
id: this.resolve(this.idResolver, log, element),
position: this.resolve(this.positionResolver, log, element)
});
flush();
- });
+ }, true);
};
new _utils_Sentinel__WEBPACK_IMPORTED_MODULE_1__.Sentinel(this.getDocument()).on(this.selectorExpression, this.logWrapHandler(handler, log));
}
@@ -770,7 +1314,6 @@ class ImpressionCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0_
\************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "InstantSearchQueryCollector": () => (/* binding */ InstantSearchQueryCollector)
@@ -820,12 +1363,13 @@ class InstantSearchQueryCollector extends _AbstractCollector__WEBPACK_IMPORTED_M
}
// Delay the reaction of the event, clean the timeout if the event fires
// again and start counting from 0
- delay(() => {
+ delay((timestamp) => {
const keywords = searchBox.value;
if (keywords && keywords.length >= this.minLength) {
writer.write({
"type": type,
- "keywords": keywords
+ "keywords": keywords,
+ timestamp
});
}
}, this.delayMs);
@@ -848,9 +1392,15 @@ class InstantSearchQueryCollector extends _AbstractCollector__WEBPACK_IMPORTED_M
}
const delay = (function () {
let timer;
+ let time;
return function (callback, ms) {
clearTimeout(timer);
- timer = setTimeout(callback, ms);
+ if (!time)
+ time = new Date().getTime();
+ timer = setTimeout(() => {
+ callback(time);
+ time = null;
+ }, ms);
};
})();
@@ -863,13 +1413,16 @@ const delay = (function () {
\******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ProductClickCollector": () => (/* binding */ ProductClickCollector)
/* harmony export */ });
/* harmony import */ var _ClickCollector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ClickCollector */ "./src/main/collectors/ClickCollector.ts");
/* harmony import */ var _utils_ListenerType__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/ListenerType */ "./src/main/utils/ListenerType.ts");
+/* harmony import */ var _query__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../query */ "./src/main/query/index.ts");
+/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ "./src/main/utils/index.ts");
+
+
/**
@@ -892,18 +1445,25 @@ class ProductClickCollector extends _ClickCollector__WEBPACK_IMPORTED_MODULE_0__
collect(element, event, log) {
const id = this.resolve(this.idResolver, log, element, event);
if (id) {
- if (this.trail) {
- // Register that this product journey into potential purchase started
- // with this query
- this.trail.register(id);
- }
- return {
+ const clickData = {
id,
position: this.resolve(this.positionResolver, log, element, event),
price: this.resolve(this.priceResolver, log, element, event),
image: this.resolve(this.imageResolver, log, element, event),
metadata: this.resolve(this.metadataResolver, log, element, event)
};
+ if (this.trail) {
+ // After a redirect a trail with the pathname is registered containing the query which triggered the redirect.
+ // If we have such a query we use it to build the trail.
+ const trailData = this.trail.fetch((0,_utils__WEBPACK_IMPORTED_MODULE_3__.normalizePathname)(location.pathname));
+ if (trailData) {
+ clickData.query = trailData.query;
+ }
+ // Register that this product journey into potential purchase started
+ // with this query
+ this.trail.register(id, _query__WEBPACK_IMPORTED_MODULE_2__.TrailType.Main, trailData === null || trailData === void 0 ? void 0 : trailData.query);
+ }
+ return clickData;
}
}
}
@@ -917,14 +1477,15 @@ class ProductClickCollector extends _ClickCollector__WEBPACK_IMPORTED_MODULE_0__
\**************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "RedirectCollector": () => (/* binding */ RedirectCollector)
/* harmony export */ });
/* harmony import */ var _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractCollector */ "./src/main/collectors/AbstractCollector.ts");
-/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils */ "./src/main/utils/index.ts");
-/* harmony import */ var _query__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../query */ "./src/main/query/index.ts");
+/* harmony import */ var _resolvers_Resolver__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../resolvers/Resolver */ "./src/main/resolvers/Resolver.ts");
+/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ "./src/main/utils/index.ts");
+/* harmony import */ var _query__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../query */ "./src/main/query/index.ts");
+
@@ -938,12 +1499,98 @@ class RedirectCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__.
* @constructor
* @param {function} triggerResolver - Function that fires when a search happens, should return the keyword
* @param {function} expectedPageResolver - Function that should return whether the page we load is the expected one
+ * @param redirectKpiParams - Parameters for collecting KPI's after a redirect
+ * @param listenerType
* @param context
*/
- constructor(triggerResolver, expectedPageResolver, context) {
+ constructor(triggerResolver, expectedPageResolver, redirectKpiParams = {}, listenerType = _utils__WEBPACK_IMPORTED_MODULE_2__.ListenerType.Sentinel, context) {
+ var _a, _b;
super("redirect", context);
this.triggerResolver = triggerResolver;
this.expectedPageResolver = expectedPageResolver;
+ this.redirectKpiParams = redirectKpiParams;
+ this.listenerType = listenerType;
+ /**
+ * Used to track if the collectors have been attached already in case attached is called multiple times
+ * @private
+ */
+ this.isCollectorsAttached = false;
+ /**
+ * Used to track if the trigger has been installed already in case attached is called multiple times
+ */
+ this.isTriggerInstalled = false;
+ this.triggerResolver = triggerResolver;
+ this.expectedPageResolver = expectedPageResolver;
+ this.listenerType = listenerType;
+ this.collectors = redirectKpiParams.collectors || [];
+ this.resultCountResolver = redirectKpiParams.resultCountResolver || (_ => void 0);
+ this.redirectTTL = this.redirectKpiParams.redirectTTLMillis || 86400000;
+ this.maxPathSegments = this.redirectKpiParams.maxPathSegments || -1;
+ this.subSelectors = ((_a = this.redirectKpiParams.nestedRedirects) === null || _a === void 0 ? void 0 : _a.subSelectors) || [];
+ this.depth = ((_b = this.redirectKpiParams.nestedRedirects) === null || _b === void 0 ? void 0 : _b.depth) || 1;
+ this.queryResolver = (phrase) => {
+ if (phrase.indexOf("$s=") > -1) {
+ return new _query__WEBPACK_IMPORTED_MODULE_3__.Query(phrase);
+ }
+ const query = new _query__WEBPACK_IMPORTED_MODULE_3__.Query();
+ query.setSearch(phrase);
+ return query;
+ };
+ this.sessionResolver = () => (0,_resolvers_Resolver__WEBPACK_IMPORTED_MODULE_1__.cookieSessionResolver)();
+ this.redirectTrail = new _query__WEBPACK_IMPORTED_MODULE_3__.Trail(() => {
+ const pathInfo = RedirectCollector.getRedirectPathInfo(this.getPathname());
+ return new _query__WEBPACK_IMPORTED_MODULE_3__.Query(pathInfo === null || pathInfo === void 0 ? void 0 : pathInfo.query);
+ }, this.sessionResolver);
+ }
+ setContext(context) {
+ super.setContext(context);
+ this.collectors.forEach(collector => collector.setContext(context));
+ }
+ /**
+ * Marks this path as a redirect landing page.
+ * @param path the pathname e.g. /some-path
+ * @param query the query which lead to this path
+ * @param key the key to store the redirect path in
+ * @private
+ */
+ static setRedirectPath(path, query, key = RedirectCollector.PATH_STORAGE_KEY) {
+ const redirectPaths = this.getRedirectPaths();
+ redirectPaths[path] = {
+ query,
+ timestamp: new Date().getTime()
+ };
+ (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getSessionStorage)().setItem(key, JSON.stringify(redirectPaths));
+ }
+ /**
+ * Get all marked paths
+ * @private
+ */
+ static getRedirectPaths(key = RedirectCollector.PATH_STORAGE_KEY) {
+ return JSON.parse((0,_utils__WEBPACK_IMPORTED_MODULE_2__.getSessionStorage)().getItem(key) || "{}");
+ }
+ /**
+ * Retrieve data for the given path
+ * @param path
+ * @param key
+ * @private
+ */
+ static getRedirectPathInfo(path, key = RedirectCollector.PATH_STORAGE_KEY) {
+ return this.getRedirectPaths(key)[path];
+ }
+ /**
+ * Delete all expired redirect paths
+ * @private
+ */
+ expireRedirectPaths(key = RedirectCollector.PATH_STORAGE_KEY) {
+ const redirectPaths = RedirectCollector.getRedirectPaths(key);
+ const now = new Date().getTime();
+ Object.keys(redirectPaths).forEach(path => {
+ const pathInfo = redirectPaths[path];
+ if (now - Number(pathInfo.timestamp) > this.redirectTTL) {
+ delete redirectPaths[path];
+ }
+ });
+ (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getSessionStorage)().setItem(key, JSON.stringify(redirectPaths));
}
/**
* Check whether we should be recording a redirect event
@@ -952,30 +1599,146 @@ class RedirectCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__.
* @param log
*/
attach(writer, log) {
- this.resolve(this.triggerResolver, log, keyword => {
- (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getSessionStorage)().setItem(RedirectCollector.STORAGE_KEY, keyword);
- });
+ if (this.isTriggerInstalled === false) {
+ this.resolve(this.triggerResolver, log, keyword => (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getSessionStorage)().setItem(RedirectCollector.LAST_SEARCH_STORAGE_KEY, keyword));
+ this.isTriggerInstalled = true;
+ }
+ this.expireRedirectPaths();
// Fetch the latest search if any
- const lastSearch = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getSessionStorage)().getItem(RedirectCollector.STORAGE_KEY);
+ const lastSearch = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getSessionStorage)().getItem(RedirectCollector.LAST_SEARCH_STORAGE_KEY);
+ const pathname = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.normalizePathname)(this.getWindow().location.pathname);
if (lastSearch) {
- // Remove the search action, as we're either on a search result page or we've redirected
- (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getSessionStorage)().removeItem(RedirectCollector.STORAGE_KEY);
- // If we have not landed on the expected search page, it must have been (looove) a redirect
- if (!this.resolve(this.expectedPageResolver, log)) {
- // Thus record the redirect
- const query = new _query__WEBPACK_IMPORTED_MODULE_2__.Query();
- query.setSearch(lastSearch);
+ (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getSessionStorage)().removeItem(RedirectCollector.LAST_SEARCH_STORAGE_KEY);
+ // If we have not landed on the expected search page, it must have been a redirect
+ if (shouldTrackRedirect(document.referrer) && !this.resolve(this.expectedPageResolver, log)) {
+ const query = this.queryResolver(lastSearch).toString();
writer.write({
type: "redirect",
keywords: lastSearch,
- query: query.toString(),
- url: window.location.href
+ query,
+ url: window.location.href,
+ resultCount: this.resolve(this.resultCountResolver, log)
});
+ // mark as redirect landing page
+ RedirectCollector.setRedirectPath(this.getPathname(), query);
+ // register trail on the current pathname because the ProductClick collector doesn't know about the maxPathSegments property
+ this.redirectTrail.register(pathname, _query__WEBPACK_IMPORTED_MODULE_3__.TrailType.Main);
+ }
+ }
+ // this is only triggered when a subSelector item was clicked i.e. a nested redirect
+ const lastSearchNestedRedirect = this.getNestedRedirect();
+ if (lastSearchNestedRedirect) {
+ const query = this.queryResolver(lastSearchNestedRedirect.query).toString();
+ RedirectCollector.setRedirectPath(this.getPathname(), query);
+ // register trail on the current pathname because the ProductClick collector doesn't know about the maxPathSegments property
+ this.redirectTrail.register(pathname, _query__WEBPACK_IMPORTED_MODULE_3__.TrailType.Main);
+ (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getSessionStorage)().removeItem(RedirectCollector.NESTED_REDIRECT_KEYWORDS_STORAGE_KEY);
+ }
+ /**
+ * Check if we have tracked this path before and if it is still valid.
+ * If valid, we have to attach the KPI collectors to gather KPIs for this landing page.
+ * We have to do this because people can navigate away from the landing page and back again and we don't want to lose all subsequent clicks etc.
+ */
+ const pathInfo = this.redirectTrail.fetch(this.getPathname());
+ if (pathInfo && this.isCollectorsAttached !== true) {
+ this.attachCollectors(writer, log, pathInfo.query);
+ this.isCollectorsAttached = true;
+ // register trail on the current pathname because the ProductClick collector doesn't know about the maxPathSegments property
+ this.redirectTrail.register(pathname, _query__WEBPACK_IMPORTED_MODULE_3__.TrailType.Main);
+ // if we have nested redirects, we have to carry the query parameters over to the next page
+ this.attachSubSelectors(pathInfo, (lastSearchNestedRedirect === null || lastSearchNestedRedirect === void 0 ? void 0 : lastSearchNestedRedirect.depth) || 0);
+ }
+ }
+ getNestedRedirect() {
+ const payload = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getSessionStorage)().getItem(RedirectCollector.NESTED_REDIRECT_KEYWORDS_STORAGE_KEY);
+ if (payload) {
+ return JSON.parse(payload);
+ }
+ return undefined;
+ }
+ isMaxDepthExceeded(currentDepth = 0) {
+ return currentDepth >= this.depth;
+ }
+ registerNestedRedirect(query, currentDepth = 0) {
+ if (this.isMaxDepthExceeded(currentDepth))
+ return;
+ const payload = {
+ query: query,
+ depth: currentDepth + 1
+ };
+ (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getSessionStorage)().setItem(RedirectCollector.NESTED_REDIRECT_KEYWORDS_STORAGE_KEY, JSON.stringify(payload));
+ }
+ attachSubSelectors(pathInfo, currentDepth) {
+ if (this.isMaxDepthExceeded(currentDepth))
+ return;
+ this.subSelectors.forEach(selector => {
+ const handleClick = () => {
+ this.registerNestedRedirect(pathInfo.query, currentDepth);
+ };
+ if (this.listenerType === _utils__WEBPACK_IMPORTED_MODULE_2__.ListenerType.Sentinel) {
+ const sentinel = new _utils__WEBPACK_IMPORTED_MODULE_2__.Sentinel(this.getDocument());
+ sentinel.on(selector, element => {
+ const info = this.redirectTrail.fetch(this.getPathname());
+ if (info) { // the sentinel can trigger on any page, we need to make sure we attach subSelectors only on valid redirect paths
+ element.addEventListener("click", handleClick);
+ }
+ });
+ }
+ else {
+ document.querySelectorAll(selector).forEach(element => {
+ element.addEventListener("click", handleClick);
+ });
+ }
+ });
+ }
+ getPathname() {
+ const pathname = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.normalizePathname)(this.getWindow().location.pathname);
+ if (this.maxPathSegments > 0) {
+ const pathSegments = pathname.split("/");
+ return (0,_utils__WEBPACK_IMPORTED_MODULE_2__.normalizePathname)(pathSegments.filter(s => !!s).slice(0, this.maxPathSegments).join("/"));
+ }
+ return pathname;
+ }
+ attachCollectors(writer, log, query) {
+ // attach all collectors which are responsible to gather kpi's after the redirect
+ this.collectors.forEach(collector => {
+ try {
+ collector.attach({
+ write(data) {
+ writer.write({ ...data, query: data.query || query });
+ }
+ }, log);
}
+ catch (e) {
+ if (log)
+ log.error(e);
+ }
+ });
+ }
+}
+/**
+ * Key used to store the keywords of the last executed search
+ */
+RedirectCollector.LAST_SEARCH_STORAGE_KEY = "__lastSearch";
+/**
+ * Key used to store query information for a given redirect landing page (path of the url)
+ */
+RedirectCollector.PATH_STORAGE_KEY = "___pathStorage";
+RedirectCollector.NESTED_REDIRECT_KEYWORDS_STORAGE_KEY = "___nestedRedirectKeywordsStorage";
+function shouldTrackRedirect(referer) {
+ if (referer) {
+ try {
+ const refUrl = new URL(referer);
+ const currentUrl = new URL(window.location.href);
+ if (currentUrl.origin && refUrl.origin)
+ return refUrl.origin === currentUrl.origin;
+ }
+ catch (e) {
+ console.error(e);
}
}
+ return true;
}
-RedirectCollector.STORAGE_KEY = "__lastSearch";
/***/ }),
@@ -986,7 +1749,6 @@ RedirectCollector.STORAGE_KEY = "__lastSearch";
\******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SearchResultCollector": () => (/* binding */ SearchResultCollector)
@@ -1040,7 +1802,6 @@ class SearchResultCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODULE_
\*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SuggestSearchCollector": () => (/* binding */ SuggestSearchCollector)
@@ -1071,7 +1832,6 @@ class SuggestSearchCollector extends _WriterResolverCollector__WEBPACK_IMPORTED_
\********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "WriterResolverCollector": () => (/* binding */ WriterResolverCollector)
@@ -1100,7 +1860,6 @@ class WriterResolverCollector extends _AbstractCollector__WEBPACK_IMPORTED_MODUL
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "AbstractCollector": () => (/* reexport safe */ _AbstractCollector__WEBPACK_IMPORTED_MODULE_0__.AbstractCollector),
@@ -1165,7 +1924,6 @@ __webpack_require__.r(__webpack_exports__);
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
@@ -1178,7 +1936,6 @@ __webpack_require__.r(__webpack_exports__);
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
@@ -1191,7 +1948,6 @@ __webpack_require__.r(__webpack_exports__);
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "TransportLogger": () => (/* binding */ TransportLogger)
@@ -1237,13 +1993,12 @@ class TransportLogger {
\**********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ "TransportLogger": () => (/* reexport safe */ _TransportLogger__WEBPACK_IMPORTED_MODULE_2__.TransportLogger),
/* harmony export */ "ConsoleTransport": () => (/* reexport safe */ _transport__WEBPACK_IMPORTED_MODULE_3__.ConsoleTransport),
/* harmony export */ "SQSErrorTransport": () => (/* reexport safe */ _transport__WEBPACK_IMPORTED_MODULE_3__.SQSErrorTransport),
-/* harmony export */ "SQSTransport": () => (/* reexport safe */ _transport__WEBPACK_IMPORTED_MODULE_3__.SQSTransport)
+/* harmony export */ "SQSTransport": () => (/* reexport safe */ _transport__WEBPACK_IMPORTED_MODULE_3__.SQSTransport),
+/* harmony export */ "TransportLogger": () => (/* reexport safe */ _TransportLogger__WEBPACK_IMPORTED_MODULE_2__.TransportLogger)
/* harmony export */ });
/* harmony import */ var _Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Logger */ "./src/main/logger/Logger.ts");
/* harmony import */ var _LoggerTransport__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LoggerTransport */ "./src/main/logger/LoggerTransport.ts");
@@ -1263,7 +2018,6 @@ __webpack_require__.r(__webpack_exports__);
\*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ConsoleTransport": () => (/* binding */ ConsoleTransport)
@@ -1296,7 +2050,6 @@ class ConsoleTransport {
\********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SQSErrorTransport": () => (/* binding */ SQSErrorTransport)
@@ -1353,7 +2106,6 @@ class SQSErrorTransport {
\***************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SQSTransport": () => (/* binding */ SQSTransport)
@@ -1399,7 +2151,6 @@ class SQSTransport extends _SQSErrorTransport__WEBPACK_IMPORTED_MODULE_0__.SQSEr
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ConsoleTransport": () => (/* reexport safe */ _ConsoleTransport__WEBPACK_IMPORTED_MODULE_0__.ConsoleTransport),
@@ -1422,7 +2173,6 @@ __webpack_require__.r(__webpack_exports__);
\*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Query": () => (/* binding */ Query)
@@ -1671,7 +2421,6 @@ function arrayRemove(array, from, to) {
\*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Trail": () => (/* binding */ Trail)
@@ -1754,7 +2503,6 @@ class Trail {
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "TrailType": () => (/* binding */ TrailType)
@@ -1774,7 +2522,6 @@ var TrailType;
\*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Query": () => (/* reexport safe */ _Query__WEBPACK_IMPORTED_MODULE_0__.Query),
@@ -1797,23 +2544,25 @@ __webpack_require__.r(__webpack_exports__);
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "cookieResolver": () => (/* binding */ cookieResolver),
/* harmony export */ "cookieSessionResolver": () => (/* binding */ cookieSessionResolver),
-/* harmony export */ "positionResolver": () => (/* binding */ positionResolver),
-/* harmony export */ "debugResolver": () => (/* binding */ debugResolver)
+/* harmony export */ "debugResolver": () => (/* binding */ debugResolver),
+/* harmony export */ "positionResolver": () => (/* binding */ positionResolver)
/* harmony export */ });
-/* harmony import */ var _utils_Util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/Util */ "./src/main/utils/Util.ts");
+/* harmony import */ var _utils_Context__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/Context */ "./src/main/utils/Context.ts");
+/* harmony import */ var _utils_Util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/Util */ "./src/main/utils/Util.ts");
+
const MINUTES_ONE_DAY = 60 * 24;
+const MINUTES_TWO_DAYS = 60 * 24 * 2;
const MINUTES_HALF_HOUR = 30;
/**
* Read the cookie with the provided name
* @param name the name of the cookie
*/
-const cookieResolver = (name = "") => (0,_utils_Util__WEBPACK_IMPORTED_MODULE_0__.getCookie)(name);
+const cookieResolver = (name = "") => (0,_utils_Util__WEBPACK_IMPORTED_MODULE_1__.getCookie)(name);
/**
* Resolve the id of the current search session. A search session is defined as
* limited time slice of search activity across multiple tabs. By default a session
@@ -1825,16 +2574,17 @@ const cookieResolver = (name = "") => (0,_utils_Util__WEBPACK_IMPORTED_MODULE_0_
*
* @param name the name of the session cookie
*/
-const cookieSessionResolver = (name = "SearchCollectorSession") => (0,_utils_Util__WEBPACK_IMPORTED_MODULE_0__.setCookie)(name, cookieResolver(name) || (0,_utils_Util__WEBPACK_IMPORTED_MODULE_0__.generateId)(), MINUTES_HALF_HOUR);
+const cookieSessionResolver = (name = "SearchCollectorSession") => (0,_utils_Util__WEBPACK_IMPORTED_MODULE_1__.setCookie)(name, cookieResolver(name) || (0,_utils_Util__WEBPACK_IMPORTED_MODULE_1__.generateId)(), MINUTES_TWO_DAYS);
/**
* Find the position of a DOM element relative to other DOM elements of the same type.
* To be used to find the position of an item in a search result.
*
* @param selectorExpression the css expression to query for other elements
* @param element the element for which we want to know the position relative to the elements selected by selectorExpression
+ * @param ctx the context to use. defaults to new Context(window, document)
*/
-const positionResolver = (selectorExpression, element) => {
- return Array.from(document.querySelectorAll(selectorExpression))
+const positionResolver = (selectorExpression, element, ctx = new _utils_Context__WEBPACK_IMPORTED_MODULE_0__.Context(window, document)) => {
+ return Array.from(ctx.getDocument().querySelectorAll(selectorExpression))
.reduce((acc, node, index) => node === element ? index : acc, undefined);
};
/**
@@ -1846,9 +2596,9 @@ const debugResolver = () => {
const isDebugParamExists = debugParam != null;
if (isDebugParamExists) {
const debug = debugParam === "true";
- (0,_utils_Util__WEBPACK_IMPORTED_MODULE_0__.getLocalStorage)().setItem(DEBUG_KEY, String(debug));
+ (0,_utils_Util__WEBPACK_IMPORTED_MODULE_1__.getLocalStorage)().setItem(DEBUG_KEY, String(debug));
}
- return (0,_utils_Util__WEBPACK_IMPORTED_MODULE_0__.getLocalStorage)().getItem(DEBUG_KEY) === "true";
+ return (0,_utils_Util__WEBPACK_IMPORTED_MODULE_1__.getLocalStorage)().getItem(DEBUG_KEY) === "true";
};
@@ -1860,7 +2610,6 @@ const debugResolver = () => {
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "cookieResolver": () => (/* reexport safe */ _Resolver__WEBPACK_IMPORTED_MODULE_0__.cookieResolver),
@@ -1880,7 +2629,6 @@ __webpack_require__.r(__webpack_exports__);
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Context": () => (/* binding */ Context)
@@ -1907,7 +2655,6 @@ class Context {
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ListenerType": () => (/* binding */ ListenerType)
@@ -1927,7 +2674,6 @@ var ListenerType;
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "LocalStorageQueue": () => (/* binding */ LocalStorageQueue)
@@ -1984,7 +2730,6 @@ class LocalStorageQueue {
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Sentinel": () => (/* binding */ Sentinel)
@@ -2119,17 +2864,17 @@ class Sentinel {
\********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ "parseQueryString": () => (/* binding */ parseQueryString),
-/* harmony export */ "getLocalStorage": () => (/* binding */ getLocalStorage),
/* harmony export */ "base64Encode": () => (/* binding */ base64Encode),
+/* harmony export */ "debounce": () => (/* binding */ debounce),
/* harmony export */ "generateId": () => (/* binding */ generateId),
-/* harmony export */ "getSessionStorage": () => (/* binding */ getSessionStorage),
-/* harmony export */ "setCookie": () => (/* binding */ setCookie),
/* harmony export */ "getCookie": () => (/* binding */ getCookie),
-/* harmony export */ "debounce": () => (/* binding */ debounce)
+/* harmony export */ "getLocalStorage": () => (/* binding */ getLocalStorage),
+/* harmony export */ "getSessionStorage": () => (/* binding */ getSessionStorage),
+/* harmony export */ "normalizePathname": () => (/* binding */ normalizePathname),
+/* harmony export */ "parseQueryString": () => (/* binding */ parseQueryString),
+/* harmony export */ "setCookie": () => (/* binding */ setCookie)
/* harmony export */ });
/**
* Parse the browser query string or the passed string into a javascript object
@@ -2141,6 +2886,13 @@ __webpack_require__.r(__webpack_exports__);
const parseQueryString = (queryString = window.location.search) => {
return new URLSearchParams(queryString);
};
+const normalizePathname = (path) => {
+ if (!path.startsWith("/"))
+ path = "/" + path;
+ if (path.endsWith("/"))
+ path = path.substring(0, path.length - 1);
+ return path;
+};
/**
* Some browser like Safari prevent accessing localStorage in private mode by throwing exceptions.
* Use this method to retrieve a mock impl which will at least prevent errors.
@@ -2351,7 +3103,6 @@ const debounce = (func, wait = 100, immediate = false) => {
\*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Context": () => (/* reexport safe */ _Context__WEBPACK_IMPORTED_MODULE_0__.Context),
@@ -2364,6 +3115,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ "getCookie": () => (/* reexport safe */ _Util__WEBPACK_IMPORTED_MODULE_4__.getCookie),
/* harmony export */ "getLocalStorage": () => (/* reexport safe */ _Util__WEBPACK_IMPORTED_MODULE_4__.getLocalStorage),
/* harmony export */ "getSessionStorage": () => (/* reexport safe */ _Util__WEBPACK_IMPORTED_MODULE_4__.getSessionStorage),
+/* harmony export */ "normalizePathname": () => (/* reexport safe */ _Util__WEBPACK_IMPORTED_MODULE_4__.normalizePathname),
/* harmony export */ "parseQueryString": () => (/* reexport safe */ _Util__WEBPACK_IMPORTED_MODULE_4__.parseQueryString),
/* harmony export */ "setCookie": () => (/* reexport safe */ _Util__WEBPACK_IMPORTED_MODULE_4__.setCookie)
/* harmony export */ });
@@ -2387,7 +3139,6 @@ __webpack_require__.r(__webpack_exports__);
\************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Base64EncodeWriter": () => (/* binding */ Base64EncodeWriter)
@@ -2413,7 +3164,6 @@ class Base64EncodeWriter {
\***************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "BrowserTrackingWriter": () => (/* binding */ BrowserTrackingWriter)
@@ -2452,7 +3202,6 @@ class BrowserTrackingWriter {
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "BufferingWriter": () => (/* binding */ BufferingWriter)
@@ -2499,7 +3248,6 @@ class BufferingWriter {
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ConsoleWriter": () => (/* binding */ ConsoleWriter)
@@ -2520,7 +3268,6 @@ class ConsoleWriter {
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "DebugWriter": () => (/* binding */ DebugWriter)
@@ -2549,7 +3296,6 @@ class DebugWriter {
\*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "DefaultWriter": () => (/* binding */ DefaultWriter)
@@ -2610,7 +3356,6 @@ function isSQS(endpoint, forceSQS) {
\************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "JSONEnvelopeWriter": () => (/* binding */ JSONEnvelopeWriter)
@@ -2625,7 +3370,8 @@ class JSONEnvelopeWriter {
this.channel = channel;
}
write(data) {
- data.timestamp = new Date().getTime();
+ if (!data.timestamp)
+ data.timestamp = new Date().getTime();
data.session = this.sessionResolver();
data.channel = this.channel;
this.delegate.write(data);
@@ -2641,7 +3387,6 @@ class JSONEnvelopeWriter {
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "QueryWriter": () => (/* binding */ QueryWriter)
@@ -2670,7 +3415,6 @@ class QueryWriter {
\*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "RestEventWriter": () => (/* binding */ RestEventWriter)
@@ -2697,7 +3441,6 @@ class RestEventWriter {
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SQSEventWriter": () => (/* binding */ SQSEventWriter)
@@ -2733,7 +3476,6 @@ class SQSEventWriter {
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SplitStreamWriter": () => (/* binding */ SplitStreamWriter)
@@ -2766,7 +3508,6 @@ class SplitStreamWriter {
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "TrailWriter": () => (/* binding */ TrailWriter)
@@ -2835,7 +3576,6 @@ class TrailWriter {
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Base64EncodeWriter": () => (/* reexport safe */ _Base64EncodeWriter__WEBPACK_IMPORTED_MODULE_0__.Base64EncodeWriter),
@@ -2843,8 +3583,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ "DefaultWriter": () => (/* reexport safe */ _DefaultWriter__WEBPACK_IMPORTED_MODULE_2__.DefaultWriter),
/* harmony export */ "JSONEnvelopeWriter": () => (/* reexport safe */ _JSONEnvelopeWriter__WEBPACK_IMPORTED_MODULE_3__.JSONEnvelopeWriter),
/* harmony export */ "RestEventWriter": () => (/* reexport safe */ _RestEventWriter__WEBPACK_IMPORTED_MODULE_4__.RestEventWriter),
-/* harmony export */ "SplitStreamWriter": () => (/* reexport safe */ _SplitStreamWriter__WEBPACK_IMPORTED_MODULE_5__.SplitStreamWriter),
-/* harmony export */ "SQSEventWriter": () => (/* reexport safe */ _SQSEventWriter__WEBPACK_IMPORTED_MODULE_6__.SQSEventWriter)
+/* harmony export */ "SQSEventWriter": () => (/* reexport safe */ _SQSEventWriter__WEBPACK_IMPORTED_MODULE_6__.SQSEventWriter),
+/* harmony export */ "SplitStreamWriter": () => (/* reexport safe */ _SplitStreamWriter__WEBPACK_IMPORTED_MODULE_5__.SplitStreamWriter)
/* harmony export */ });
/* harmony import */ var _Base64EncodeWriter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Base64EncodeWriter */ "./src/main/writers/Base64EncodeWriter.ts");
/* harmony import */ var _BufferingWriter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BufferingWriter */ "./src/main/writers/BufferingWriter.ts");
@@ -2870,7 +3610,6 @@ __webpack_require__.r(__webpack_exports__);
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Base64EncodeWriter": () => (/* reexport safe */ _Base64EncodeWriter__WEBPACK_IMPORTED_MODULE_0__.Base64EncodeWriter),
@@ -2882,8 +3621,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ "JSONEnvelopeWriter": () => (/* reexport safe */ _JSONEnvelopeWriter__WEBPACK_IMPORTED_MODULE_6__.JSONEnvelopeWriter),
/* harmony export */ "QueryWriter": () => (/* reexport safe */ _QueryWriter__WEBPACK_IMPORTED_MODULE_7__.QueryWriter),
/* harmony export */ "RestEventWriter": () => (/* reexport safe */ _RestEventWriter__WEBPACK_IMPORTED_MODULE_8__.RestEventWriter),
-/* harmony export */ "SplitStreamWriter": () => (/* reexport safe */ _SplitStreamWriter__WEBPACK_IMPORTED_MODULE_9__.SplitStreamWriter),
/* harmony export */ "SQSEventWriter": () => (/* reexport safe */ _SQSEventWriter__WEBPACK_IMPORTED_MODULE_10__.SQSEventWriter),
+/* harmony export */ "SplitStreamWriter": () => (/* reexport safe */ _SplitStreamWriter__WEBPACK_IMPORTED_MODULE_9__.SplitStreamWriter),
/* harmony export */ "TrailWriter": () => (/* reexport safe */ _TrailWriter__WEBPACK_IMPORTED_MODULE_11__.TrailWriter)
/* harmony export */ });
/* harmony import */ var _Base64EncodeWriter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Base64EncodeWriter */ "./src/main/writers/Base64EncodeWriter.ts");
@@ -2936,25 +3675,13 @@ __webpack_require__.r(__webpack_exports__);
/******/ };
/******/
/******/ // Execute the module function
-/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
-/******/ /* webpack/runtime/compat get default export */
-/******/ (() => {
-/******/ // getDefaultExport function for compatibility with non-harmony modules
-/******/ __webpack_require__.n = (module) => {
-/******/ var getter = module && module.__esModule ?
-/******/ () => (module['default']) :
-/******/ () => (module);
-/******/ __webpack_require__.d(getter, { a: getter });
-/******/ return getter;
-/******/ };
-/******/ })();
-/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
@@ -2985,66 +3712,66 @@ __webpack_require__.r(__webpack_exports__);
/******/
/************************************************************************/
var __webpack_exports__ = {};
-// This entry need to be wrapped in an IIFE because it need to be in strict mode.
+// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
-"use strict";
/*!***************************!*\
!*** ./src/main/index.ts ***!
\***************************/
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ "CollectorModule": () => (/* reexport safe */ _CollectorModule__WEBPACK_IMPORTED_MODULE_0__.CollectorModule),
/* harmony export */ "AbstractCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.AbstractCollector),
/* harmony export */ "AssociatedProductCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.AssociatedProductCollector),
+/* harmony export */ "Base64EncodeWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.Base64EncodeWriter),
/* harmony export */ "BasketClickCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.BasketClickCollector),
/* harmony export */ "BrowserCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.BrowserCollector),
+/* harmony export */ "BrowserTrackingWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.BrowserTrackingWriter),
+/* harmony export */ "BufferingWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.BufferingWriter),
/* harmony export */ "CheckoutClickCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.CheckoutClickCollector),
/* harmony export */ "ClickCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.ClickCollector),
/* harmony export */ "ClickWriterResolverCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.ClickWriterResolverCollector),
+/* harmony export */ "CollectorModule": () => (/* reexport safe */ _CollectorModule__WEBPACK_IMPORTED_MODULE_0__.CollectorModule),
+/* harmony export */ "ConsoleTransport": () => (/* reexport safe */ _logger__WEBPACK_IMPORTED_MODULE_4__.ConsoleTransport),
+/* harmony export */ "ConsoleWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.ConsoleWriter),
+/* harmony export */ "Context": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.Context),
+/* harmony export */ "DebugWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.DebugWriter),
+/* harmony export */ "DefaultWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.DefaultWriter),
/* harmony export */ "FilterClickCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.FilterClickCollector),
/* harmony export */ "FiredSearchCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.FiredSearchCollector),
/* harmony export */ "GenericEventCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.GenericEventCollector),
/* harmony export */ "ImpressionCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.ImpressionCollector),
/* harmony export */ "InstantSearchQueryCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.InstantSearchQueryCollector),
-/* harmony export */ "ProductClickCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.ProductClickCollector),
-/* harmony export */ "RedirectCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.RedirectCollector),
-/* harmony export */ "SearchResultCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.SearchResultCollector),
-/* harmony export */ "SuggestSearchCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.SuggestSearchCollector),
-/* harmony export */ "WriterResolverCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.WriterResolverCollector),
-/* harmony export */ "Base64EncodeWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.Base64EncodeWriter),
-/* harmony export */ "BrowserTrackingWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.BrowserTrackingWriter),
-/* harmony export */ "BufferingWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.BufferingWriter),
-/* harmony export */ "ConsoleWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.ConsoleWriter),
-/* harmony export */ "DebugWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.DebugWriter),
-/* harmony export */ "DefaultWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.DefaultWriter),
/* harmony export */ "JSONEnvelopeWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.JSONEnvelopeWriter),
+/* harmony export */ "ListenerType": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.ListenerType),
+/* harmony export */ "LocalStorageQueue": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.LocalStorageQueue),
+/* harmony export */ "ProductClickCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.ProductClickCollector),
+/* harmony export */ "Query": () => (/* reexport safe */ _query__WEBPACK_IMPORTED_MODULE_3__.Query),
/* harmony export */ "QueryWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.QueryWriter),
+/* harmony export */ "RedirectCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.RedirectCollector),
/* harmony export */ "RestEventWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.RestEventWriter),
+/* harmony export */ "SQSErrorTransport": () => (/* reexport safe */ _logger__WEBPACK_IMPORTED_MODULE_4__.SQSErrorTransport),
/* harmony export */ "SQSEventWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.SQSEventWriter),
+/* harmony export */ "SQSTransport": () => (/* reexport safe */ _logger__WEBPACK_IMPORTED_MODULE_4__.SQSTransport),
+/* harmony export */ "SearchResultCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.SearchResultCollector),
+/* harmony export */ "Sentinel": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.Sentinel),
/* harmony export */ "SplitStreamWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.SplitStreamWriter),
-/* harmony export */ "TrailWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.TrailWriter),
-/* harmony export */ "Query": () => (/* reexport safe */ _query__WEBPACK_IMPORTED_MODULE_3__.Query),
+/* harmony export */ "SuggestSearchCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.SuggestSearchCollector),
/* harmony export */ "Trail": () => (/* reexport safe */ _query__WEBPACK_IMPORTED_MODULE_3__.Trail),
/* harmony export */ "TrailType": () => (/* reexport safe */ _query__WEBPACK_IMPORTED_MODULE_3__.TrailType),
-/* harmony export */ "ConsoleTransport": () => (/* reexport safe */ _logger__WEBPACK_IMPORTED_MODULE_4__.ConsoleTransport),
-/* harmony export */ "SQSErrorTransport": () => (/* reexport safe */ _logger__WEBPACK_IMPORTED_MODULE_4__.SQSErrorTransport),
-/* harmony export */ "SQSTransport": () => (/* reexport safe */ _logger__WEBPACK_IMPORTED_MODULE_4__.SQSTransport),
+/* harmony export */ "TrailWriter": () => (/* reexport safe */ _writers__WEBPACK_IMPORTED_MODULE_2__.TrailWriter),
/* harmony export */ "TransportLogger": () => (/* reexport safe */ _logger__WEBPACK_IMPORTED_MODULE_4__.TransportLogger),
+/* harmony export */ "WriterResolverCollector": () => (/* reexport safe */ _collectors___WEBPACK_IMPORTED_MODULE_1__.WriterResolverCollector),
+/* harmony export */ "base64Encode": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.base64Encode),
/* harmony export */ "cookieResolver": () => (/* reexport safe */ _resolvers__WEBPACK_IMPORTED_MODULE_5__.cookieResolver),
/* harmony export */ "cookieSessionResolver": () => (/* reexport safe */ _resolvers__WEBPACK_IMPORTED_MODULE_5__.cookieSessionResolver),
-/* harmony export */ "debugResolver": () => (/* reexport safe */ _resolvers__WEBPACK_IMPORTED_MODULE_5__.debugResolver),
-/* harmony export */ "positionResolver": () => (/* reexport safe */ _resolvers__WEBPACK_IMPORTED_MODULE_5__.positionResolver),
-/* harmony export */ "Context": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.Context),
-/* harmony export */ "ListenerType": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.ListenerType),
-/* harmony export */ "LocalStorageQueue": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.LocalStorageQueue),
-/* harmony export */ "Sentinel": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.Sentinel),
-/* harmony export */ "base64Encode": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.base64Encode),
/* harmony export */ "debounce": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.debounce),
+/* harmony export */ "debugResolver": () => (/* reexport safe */ _resolvers__WEBPACK_IMPORTED_MODULE_5__.debugResolver),
/* harmony export */ "generateId": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.generateId),
/* harmony export */ "getCookie": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.getCookie),
/* harmony export */ "getLocalStorage": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.getLocalStorage),
/* harmony export */ "getSessionStorage": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.getSessionStorage),
+/* harmony export */ "normalizePathname": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.normalizePathname),
/* harmony export */ "parseQueryString": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.parseQueryString),
+/* harmony export */ "positionResolver": () => (/* reexport safe */ _resolvers__WEBPACK_IMPORTED_MODULE_5__.positionResolver),
/* harmony export */ "setCookie": () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.setCookie)
/* harmony export */ });
/* harmony import */ var _CollectorModule__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./CollectorModule */ "./src/main/CollectorModule.ts");
@@ -3067,4 +3794,4 @@ __webpack_require__.r(__webpack_exports__);
window.SearchCollector = __webpack_exports__;
/******/ })()
;
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,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O0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLDBCQUEwQjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLDBCQUEwQjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsMEJBQTBCO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUN6T21FO0FBQzNCO0FBQ3hDO0FBQ087QUFD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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUNYTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUNwQkE7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7O0FDakJPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNyRHFDO0FBQ0g7QUFDRjtBQUNLO0FBQ0g7QUFDRTtBQUNIOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDTkk7QUFDRztBQUNOO0FBQ0Y7QUFDRjtBQUNFO0FBQ0s7QUFDUDtBQUNJO0FBQ0U7QUFDSDtBQUNIO0FBQ0w7Ozs7Ozs7VUNaekI7VUFDQTs7VUFFQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTs7VUFFQTtVQUNBOztVQUVBO1VBQ0E7VUFDQTs7Ozs7V0N0QkE7V0FDQTtXQUNBO1dBQ0E7V0FDQTtXQUNBLGlDQUFpQyxXQUFXO1dBQzVDO1dBQ0E7Ozs7O1dDUEE7V0FDQTtXQUNBO1dBQ0E7V0FDQSx5Q0FBeUMsd0NBQXdDO1dBQ2pGO1dBQ0E7V0FDQTs7Ozs7V0NQQTs7Ozs7V0NBQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDTmtDO0FBQ0o7QUFDSjtBQUNGO0FBQ0M7QUFDRztBQUNKIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vbm9kZV9tb2R1bGVzL3Njcm9sbG1vbml0b3Ivc2Nyb2xsTW9uaXRvci5qcyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9Db2xsZWN0b3JNb2R1bGUudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9BYnN0cmFjdENvbGxlY3Rvci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL0Fzc29jaWF0ZWRQcm9kdWN0Q29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvQmFza2V0Q2xpY2tDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9Ccm93c2VyQ29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvQ2hlY2tvdXRDbGlja0NvbGxlY3Rvci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL0NsaWNrQ29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvQ2xpY2tXcml0ZXJSZXNvbHZlckNvbGxlY3Rvci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL0ZpbHRlckNsaWNrQ29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvRmlyZWRTZWFyY2hDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9HZW5lcmljRXZlbnRDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9JbXByZXNzaW9uQ29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvSW5zdGFudFNlYXJjaFF1ZXJ5Q29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvUHJvZHVjdENsaWNrQ29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvUmVkaXJlY3RDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9TZWFyY2hSZXN1bHRDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9TdWdnZXN0U2VhcmNoQ29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9pbmRleC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9sb2dnZXIvTG9nZ2VyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2xvZ2dlci9Mb2dnZXJUcmFuc3BvcnQudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vbG9nZ2VyL1RyYW5zcG9ydExvZ2dlci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9sb2dnZXIvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vbG9nZ2VyL3RyYW5zcG9ydC9Db25zb2xlVHJhbnNwb3J0LnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2xvZ2dlci90cmFuc3BvcnQvU1FTRXJyb3JUcmFuc3BvcnQudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vbG9nZ2VyL3RyYW5zcG9ydC9TUVNUcmFuc3BvcnQudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vbG9nZ2VyL3RyYW5zcG9ydC9pbmRleC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9xdWVyeS9RdWVyeS50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9xdWVyeS9UcmFpbC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9xdWVyeS9UcmFpbFR5cGUudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vcXVlcnkvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vcmVzb2x2ZXJzL1Jlc29sdmVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3Jlc29sdmVycy9pbmRleC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi91dGlscy9Db250ZXh0LnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3V0aWxzL0xpc3RlbmVyVHlwZS50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi91dGlscy9Mb2NhbFN0b3JhZ2VRdWV1ZS50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi91dGlscy9TZW50aW5lbC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi91dGlscy9VdGlsLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3V0aWxzL2luZGV4LnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvQmFzZTY0RW5jb2RlV3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvQnJvd3NlclRyYWNraW5nV3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvQnVmZmVyaW5nV3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvQ29uc29sZVdyaXRlci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi93cml0ZXJzL0RlYnVnV3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvRGVmYXVsdFdyaXRlci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi93cml0ZXJzL0pTT05FbnZlbG9wZVdyaXRlci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi93cml0ZXJzL1F1ZXJ5V3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvUmVzdEV2ZW50V3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvU1FTRXZlbnRXcml0ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9TcGxpdFN0cmVhbVdyaXRlci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi93cml0ZXJzL1RyYWlsV3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvV3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci93ZWJwYWNrL3J1bnRpbWUvY29tcGF0IGdldCBkZWZhdWx0IGV4cG9ydCIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3Ivd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci93ZWJwYWNrL3J1bnRpbWUvaGFzT3duUHJvcGVydHkgc2hvcnRoYW5kIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIiFmdW5jdGlvbih0LGUpe1wib2JqZWN0XCI9PXR5cGVvZiBleHBvcnRzJiZcIm9iamVjdFwiPT10eXBlb2YgbW9kdWxlP21vZHVsZS5leHBvcnRzPWUoKTpcImZ1bmN0aW9uXCI9PXR5cGVvZiBkZWZpbmUmJmRlZmluZS5hbWQ/ZGVmaW5lKFwic2Nyb2xsTW9uaXRvclwiLFtdLGUpOlwib2JqZWN0XCI9PXR5cGVvZiBleHBvcnRzP2V4cG9ydHMuc2Nyb2xsTW9uaXRvcj1lKCk6dC5zY3JvbGxNb25pdG9yPWUoKX0odGhpcyxmdW5jdGlvbigpe3JldHVybiBmdW5jdGlvbih0KXtmdW5jdGlvbiBlKG8pe2lmKGlbb10pcmV0dXJuIGlbb10uZXhwb3J0czt2YXIgcz1pW29dPXtleHBvcnRzOnt9LGlkOm8sbG9hZGVkOiExfTtyZXR1cm4gdFtvXS5jYWxsKHMuZXhwb3J0cyxzLHMuZXhwb3J0cyxlKSxzLmxvYWRlZD0hMCxzLmV4cG9ydHN9dmFyIGk9e307cmV0dXJuIGUubT10LGUuYz1pLGUucD1cIlwiLGUoMCl9KFtmdW5jdGlvbih0LGUsaSl7XCJ1c2Ugc3RyaWN0XCI7dmFyIG89aSgxKSxzPW8uaXNJbkJyb3dzZXIsbj1pKDIpLHI9bmV3IG4ocz9kb2N1bWVudC5ib2R5Om51bGwpO3Iuc2V0U3RhdGVGcm9tRE9NKG51bGwpLHIubGlzdGVuVG9ET00oKSxzJiYod2luZG93LnNjcm9sbE1vbml0b3I9ciksdC5leHBvcnRzPXJ9LGZ1bmN0aW9uKHQsZSl7XCJ1c2Ugc3RyaWN0XCI7ZS5WSVNJQklMSVRZQ0hBTkdFPVwidmlzaWJpbGl0eUNoYW5nZVwiLGUuRU5URVJWSUVXUE9SVD1cImVudGVyVmlld3BvcnRcIixlLkZVTExZRU5URVJWSUVXUE9SVD1cImZ1bGx5RW50ZXJWaWV3cG9ydFwiLGUuRVhJVFZJRVdQT1JUPVwiZXhpdFZpZXdwb3J0XCIsZS5QQVJUSUFMTFlFWElUVklFV1BPUlQ9XCJwYXJ0aWFsbHlFeGl0Vmlld3BvcnRcIixlLkxPQ0FUSU9OQ0hBTkdFPVwibG9jYXRpb25DaGFuZ2VcIixlLlNUQVRFQ0hBTkdFPVwic3RhdGVDaGFuZ2VcIixlLmV2ZW50VHlwZXM9W2UuVklTSUJJTElUWUNIQU5HRSxlLkVOVEVSVklFV1BPUlQsZS5GVUxMWUVOVEVSVklFV1BPUlQsZS5FWElUVklFV1BPUlQsZS5QQVJUSUFMTFlFWElUVklFV1BPUlQsZS5MT0NBVElPTkNIQU5HRSxlLlNUQVRFQ0hBTkdFXSxlLmlzT25TZXJ2ZXI9XCJ1bmRlZmluZWRcIj09dHlwZW9mIHdpbmRvdyxlLmlzSW5Ccm93c2VyPSFlLmlzT25TZXJ2ZXIsZS5kZWZhdWx0T2Zmc2V0cz17dG9wOjAsYm90dG9tOjB9fSxmdW5jdGlvbih0LGUsaSl7XCJ1c2Ugc3RyaWN0XCI7ZnVuY3Rpb24gbyh0LGUpe2lmKCEodCBpbnN0YW5jZW9mIGUpKXRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIil9ZnVuY3Rpb24gcyh0KXtyZXR1cm4gYz8wOnQ9PT1kb2N1bWVudC5ib2R5P3dpbmRvdy5pbm5lckhlaWdodHx8ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodDp0LmNsaWVudEhlaWdodH1mdW5jdGlvbiBuKHQpe3JldHVybiBjPzA6dD09PWRvY3VtZW50LmJvZHk/TWF0aC5tYXgoZG9jdW1lbnQuYm9keS5zY3JvbGxIZWlnaHQsZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbEhlaWdodCxkb2N1bWVudC5ib2R5Lm9mZnNldEhlaWdodCxkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQub2Zmc2V0SGVpZ2h0LGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQpOnQuc2Nyb2xsSGVpZ2h0fWZ1bmN0aW9uIHIodCl7cmV0dXJuIGM/MDp0PT09ZG9jdW1lbnQuYm9keT93aW5kb3cucGFnZVlPZmZzZXR8fGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCYmZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcHx8ZG9jdW1lbnQuYm9keS5zY3JvbGxUb3A6dC5zY3JvbGxUb3B9dmFyIGg9aSgxKSxjPWguaXNPblNlcnZlcixhPWguaXNJbkJyb3dzZXIsbD1oLmV2ZW50VHlwZXMscD1pKDMpLHU9ITE7aWYoYSl0cnl7dmFyIHc9T2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LFwicGFzc2l2ZVwiLHtnZXQ6ZnVuY3Rpb24oKXt1PSEwfX0pO3dpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwidGVzdFwiLG51bGwsdyl9Y2F0Y2godCl7fXZhciBkPSEhdSYme2NhcHR1cmU6ITEscGFzc2l2ZTohMH0sZj1mdW5jdGlvbigpe2Z1bmN0aW9uIHQoZSxpKXtmdW5jdGlvbiBoKCl7aWYoYS52aWV3cG9ydFRvcD1yKGUpLGEudmlld3BvcnRCb3R0b209YS52aWV3cG9ydFRvcCthLnZpZXdwb3J0SGVpZ2h0LGEuZG9jdW1lbnRIZWlnaHQ9bihlKSxhLmRvY3VtZW50SGVpZ2h0IT09cCl7Zm9yKHU9YS53YXRjaGVycy5sZW5ndGg7dS0tOylhLndhdGNoZXJzW3VdLnJlY2FsY3VsYXRlTG9jYXRpb24oKTtwPWEuZG9jdW1lbnRIZWlnaHR9fWZ1bmN0aW9uIGMoKXtmb3Iodz1hLndhdGNoZXJzLmxlbmd0aDt3LS07KWEud2F0Y2hlcnNbd10udXBkYXRlKCk7Zm9yKHc9YS53YXRjaGVycy5sZW5ndGg7dy0tOylhLndhdGNoZXJzW3ddLnRyaWdnZXJDYWxsYmFja3MoKX1vKHRoaXMsdCk7dmFyIGE9dGhpczt0aGlzLml0ZW09ZSx0aGlzLndhdGNoZXJzPVtdLHRoaXMudmlld3BvcnRUb3A9bnVsbCx0aGlzLnZpZXdwb3J0Qm90dG9tPW51bGwsdGhpcy5kb2N1bWVudEhlaWdodD1uKGUpLHRoaXMudmlld3BvcnRIZWlnaHQ9cyhlKSx0aGlzLkRPTUxpc3RlbmVyPWZ1bmN0aW9uKCl7dC5wcm90b3R5cGUuRE9NTGlzdGVuZXIuYXBwbHkoYSxhcmd1bWVudHMpfSx0aGlzLmV2ZW50VHlwZXM9bCxpJiYodGhpcy5jb250YWluZXJXYXRjaGVyPWkuY3JlYXRlKGUpKTt2YXIgcCx1LHc7dGhpcy51cGRhdGU9ZnVuY3Rpb24oKXtoKCksYygpfSx0aGlzLnJlY2FsY3VsYXRlTG9jYXRpb25zPWZ1bmN0aW9uKCl7dGhpcy5kb2N1bWVudEhlaWdodD0wLHRoaXMudXBkYXRlKCl9fXJldHVybiB0LnByb3RvdHlwZS5saXN0ZW5Ub0RPTT1mdW5jdGlvbigpe2EmJih3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcj8odGhpcy5pdGVtPT09ZG9jdW1lbnQuYm9keT93aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcInNjcm9sbFwiLHRoaXMuRE9NTGlzdGVuZXIsZCk6dGhpcy5pdGVtLmFkZEV2ZW50TGlzdGVuZXIoXCJzY3JvbGxcIix0aGlzLkRPTUxpc3RlbmVyLGQpLHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwicmVzaXplXCIsdGhpcy5ET01MaXN0ZW5lcikpOih0aGlzLml0ZW09PT1kb2N1bWVudC5ib2R5P3dpbmRvdy5hdHRhY2hFdmVudChcIm9uc2Nyb2xsXCIsdGhpcy5ET01MaXN0ZW5lcik6dGhpcy5pdGVtLmF0dGFjaEV2ZW50KFwib25zY3JvbGxcIix0aGlzLkRPTUxpc3RlbmVyKSx3aW5kb3cuYXR0YWNoRXZlbnQoXCJvbnJlc2l6ZVwiLHRoaXMuRE9NTGlzdGVuZXIpKSx0aGlzLmRlc3Ryb3k9ZnVuY3Rpb24oKXt3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcj8odGhpcy5pdGVtPT09ZG9jdW1lbnQuYm9keT8od2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJzY3JvbGxcIix0aGlzLkRPTUxpc3RlbmVyLGQpLHRoaXMuY29udGFpbmVyV2F0Y2hlci5kZXN0cm95KCkpOnRoaXMuaXRlbS5yZW1vdmVFdmVudExpc3RlbmVyKFwic2Nyb2xsXCIsdGhpcy5ET01MaXN0ZW5lcixkKSx3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInJlc2l6ZVwiLHRoaXMuRE9NTGlzdGVuZXIpKToodGhpcy5pdGVtPT09ZG9jdW1lbnQuYm9keT8od2luZG93LmRldGFjaEV2ZW50KFwib25zY3JvbGxcIix0aGlzLkRPTUxpc3RlbmVyKSx0aGlzLmNvbnRhaW5lcldhdGNoZXIuZGVzdHJveSgpKTp0aGlzLml0ZW0uZGV0YWNoRXZlbnQoXCJvbnNjcm9sbFwiLHRoaXMuRE9NTGlzdGVuZXIpLHdpbmRvdy5kZXRhY2hFdmVudChcIm9ucmVzaXplXCIsdGhpcy5ET01MaXN0ZW5lcikpfSl9LHQucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt9LHQucHJvdG90eXBlLkRPTUxpc3RlbmVyPWZ1bmN0aW9uKHQpe3RoaXMuc2V0U3RhdGVGcm9tRE9NKHQpfSx0LnByb3RvdHlwZS5zZXRTdGF0ZUZyb21ET009ZnVuY3Rpb24odCl7dmFyIGU9cih0aGlzLml0ZW0pLGk9cyh0aGlzLml0ZW0pLG89bih0aGlzLml0ZW0pO3RoaXMuc2V0U3RhdGUoZSxpLG8sdCl9LHQucHJvdG90eXBlLnNldFN0YXRlPWZ1bmN0aW9uKHQsZSxpLG8pe3ZhciBzPWUhPT10aGlzLnZpZXdwb3J0SGVpZ2h0fHxpIT09dGhpcy5jb250ZW50SGVpZ2h0O2lmKHRoaXMubGF0ZXN0RXZlbnQ9byx0aGlzLnZpZXdwb3J0VG9wPXQsdGhpcy52aWV3cG9ydEhlaWdodD1lLHRoaXMudmlld3BvcnRCb3R0b209dCtlLHRoaXMuY29udGVudEhlaWdodD1pLHMpZm9yKHZhciBuPXRoaXMud2F0Y2hlcnMubGVuZ3RoO24tLTspdGhpcy53YXRjaGVyc1tuXS5yZWNhbGN1bGF0ZUxvY2F0aW9uKCk7dGhpcy51cGRhdGVBbmRUcmlnZ2VyV2F0Y2hlcnMobyl9LHQucHJvdG90eXBlLnVwZGF0ZUFuZFRyaWdnZXJXYXRjaGVycz1mdW5jdGlvbih0KXtmb3IodmFyIGU9dGhpcy53YXRjaGVycy5sZW5ndGg7ZS0tOyl0aGlzLndhdGNoZXJzW2VdLnVwZGF0ZSgpO2ZvcihlPXRoaXMud2F0Y2hlcnMubGVuZ3RoO2UtLTspdGhpcy53YXRjaGVyc1tlXS50cmlnZ2VyQ2FsbGJhY2tzKHQpfSx0LnByb3RvdHlwZS5jcmVhdGVDdXN0b21Db250YWluZXI9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IHR9LHQucHJvdG90eXBlLmNyZWF0ZUNvbnRhaW5lcj1mdW5jdGlvbihlKXtcInN0cmluZ1wiPT10eXBlb2YgZT9lPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoZSk6ZSYmZS5sZW5ndGg+MCYmKGU9ZVswXSk7dmFyIGk9bmV3IHQoZSx0aGlzKTtyZXR1cm4gaS5zZXRTdGF0ZUZyb21ET00oKSxpLmxpc3RlblRvRE9NKCksaX0sdC5wcm90b3R5cGUuY3JlYXRlPWZ1bmN0aW9uKHQsZSl7XCJzdHJpbmdcIj09dHlwZW9mIHQ/dD1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKHQpOnQmJnQubGVuZ3RoPjAmJih0PXRbMF0pO3ZhciBpPW5ldyBwKHRoaXMsdCxlKTtyZXR1cm4gdGhpcy53YXRjaGVycy5wdXNoKGkpLGl9LHQucHJvdG90eXBlLmJlZ2V0PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuY3JlYXRlKHQsZSl9LHR9KCk7dC5leHBvcnRzPWZ9LGZ1bmN0aW9uKHQsZSxpKXtcInVzZSBzdHJpY3RcIjtmdW5jdGlvbiBvKHQsZSxpKXtmdW5jdGlvbiBvKHQsZSl7aWYoMCE9PXQubGVuZ3RoKWZvcihFPXQubGVuZ3RoO0UtLTspeT10W0VdLHkuY2FsbGJhY2suY2FsbChzLGUscykseS5pc09uZSYmdC5zcGxpY2UoRSwxKX12YXIgcz10aGlzO3RoaXMud2F0Y2hJdGVtPWUsdGhpcy5jb250YWluZXI9dCxpP2k9PT0raT90aGlzLm9mZnNldHM9e3RvcDppLGJvdHRvbTppfTp0aGlzLm9mZnNldHM9e3RvcDppLnRvcHx8dy50b3AsYm90dG9tOmkuYm90dG9tfHx3LmJvdHRvbX06dGhpcy5vZmZzZXRzPXcsdGhpcy5jYWxsYmFja3M9e307Zm9yKHZhciBkPTAsZj11Lmxlbmd0aDtkPGY7ZCsrKXMuY2FsbGJhY2tzW3VbZF1dPVtdO3RoaXMubG9ja2VkPSExO3ZhciBtLHYsYixJLEUseTt0aGlzLnRyaWdnZXJDYWxsYmFja3M9ZnVuY3Rpb24odCl7c3dpdGNoKHRoaXMuaXNJblZpZXdwb3J0JiYhbSYmbyh0aGlzLmNhbGxiYWNrc1tyXSx0KSx0aGlzLmlzRnVsbHlJblZpZXdwb3J0JiYhdiYmbyh0aGlzLmNhbGxiYWNrc1toXSx0KSx0aGlzLmlzQWJvdmVWaWV3cG9ydCE9PWImJnRoaXMuaXNCZWxvd1ZpZXdwb3J0IT09SSYmKG8odGhpcy5jYWxsYmFja3Nbbl0sdCksdnx8dGhpcy5pc0Z1bGx5SW5WaWV3cG9ydHx8KG8odGhpcy5jYWxsYmFja3NbaF0sdCksbyh0aGlzLmNhbGxiYWNrc1thXSx0KSksbXx8dGhpcy5pc0luVmlld3BvcnR8fChvKHRoaXMuY2FsbGJhY2tzW3JdLHQpLG8odGhpcy5jYWxsYmFja3NbY10sdCkpKSwhdGhpcy5pc0Z1bGx5SW5WaWV3cG9ydCYmdiYmbyh0aGlzLmNhbGxiYWNrc1thXSx0KSwhdGhpcy5pc0luVmlld3BvcnQmJm0mJm8odGhpcy5jYWxsYmFja3NbY10sdCksdGhpcy5pc0luVmlld3BvcnQhPT1tJiZvKHRoaXMuY2FsbGJhY2tzW25dLHQpLCEwKXtjYXNlIG0hPT10aGlzLmlzSW5WaWV3cG9ydDpjYXNlIHYhPT10aGlzLmlzRnVsbHlJblZpZXdwb3J0OmNhc2UgYiE9PXRoaXMuaXNBYm92ZVZpZXdwb3J0OmNhc2UgSSE9PXRoaXMuaXNCZWxvd1ZpZXdwb3J0Om8odGhpcy5jYWxsYmFja3NbcF0sdCl9bT10aGlzLmlzSW5WaWV3cG9ydCx2PXRoaXMuaXNGdWxseUluVmlld3BvcnQsYj10aGlzLmlzQWJvdmVWaWV3cG9ydCxJPXRoaXMuaXNCZWxvd1ZpZXdwb3J0fSx0aGlzLnJlY2FsY3VsYXRlTG9jYXRpb249ZnVuY3Rpb24oKXtpZighdGhpcy5sb2NrZWQpe3ZhciB0PXRoaXMudG9wLGU9dGhpcy5ib3R0b207aWYodGhpcy53YXRjaEl0ZW0ubm9kZU5hbWUpe3ZhciBpPXRoaXMud2F0Y2hJdGVtLnN0eWxlLmRpc3BsYXk7XCJub25lXCI9PT1pJiYodGhpcy53YXRjaEl0ZW0uc3R5bGUuZGlzcGxheT1cIlwiKTtmb3IodmFyIHM9MCxuPXRoaXMuY29udGFpbmVyO24uY29udGFpbmVyV2F0Y2hlcjspcys9bi5jb250YWluZXJXYXRjaGVyLnRvcC1uLmNvbnRhaW5lcldhdGNoZXIuY29udGFpbmVyLnZpZXdwb3J0VG9wLG49bi5jb250YWluZXJXYXRjaGVyLmNvbnRhaW5lcjt2YXIgcj10aGlzLndhdGNoSXRlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTt0aGlzLnRvcD1yLnRvcCt0aGlzLmNvbnRhaW5lci52aWV3cG9ydFRvcC1zLHRoaXMuYm90dG9tPXIuYm90dG9tK3RoaXMuY29udGFpbmVyLnZpZXdwb3J0VG9wLXMsXCJub25lXCI9PT1pJiYodGhpcy53YXRjaEl0ZW0uc3R5bGUuZGlzcGxheT1pKX1lbHNlIHRoaXMud2F0Y2hJdGVtPT09K3RoaXMud2F0Y2hJdGVtP3RoaXMud2F0Y2hJdGVtPjA/dGhpcy50b3A9dGhpcy5ib3R0b209dGhpcy53YXRjaEl0ZW06dGhpcy50b3A9dGhpcy5ib3R0b209dGhpcy5jb250YWluZXIuZG9jdW1lbnRIZWlnaHQtdGhpcy53YXRjaEl0ZW06KHRoaXMudG9wPXRoaXMud2F0Y2hJdGVtLnRvcCx0aGlzLmJvdHRvbT10aGlzLndhdGNoSXRlbS5ib3R0b20pO3RoaXMudG9wLT10aGlzLm9mZnNldHMudG9wLHRoaXMuYm90dG9tKz10aGlzLm9mZnNldHMuYm90dG9tLHRoaXMuaGVpZ2h0PXRoaXMuYm90dG9tLXRoaXMudG9wLHZvaWQgMD09PXQmJnZvaWQgMD09PWV8fHRoaXMudG9wPT09dCYmdGhpcy5ib3R0b209PT1lfHxvKHRoaXMuY2FsbGJhY2tzW2xdLG51bGwpfX0sdGhpcy5yZWNhbGN1bGF0ZUxvY2F0aW9uKCksdGhpcy51cGRhdGUoKSxtPXRoaXMuaXNJblZpZXdwb3J0LHY9dGhpcy5pc0Z1bGx5SW5WaWV3cG9ydCxiPXRoaXMuaXNBYm92ZVZpZXdwb3J0LEk9dGhpcy5pc0JlbG93Vmlld3BvcnR9dmFyIHM9aSgxKSxuPXMuVklTSUJJTElUWUNIQU5HRSxyPXMuRU5URVJWSUVXUE9SVCxoPXMuRlVMTFlFTlRFUlZJRVdQT1JULGM9cy5FWElUVklFV1BPUlQsYT1zLlBBUlRJQUxMWUVYSVRWSUVXUE9SVCxsPXMuTE9DQVRJT05DSEFOR0UscD1zLlNUQVRFQ0hBTkdFLHU9cy5ldmVudFR5cGVzLHc9cy5kZWZhdWx0T2Zmc2V0cztvLnByb3RvdHlwZT17b246ZnVuY3Rpb24odCxlLGkpe3N3aXRjaCghMCl7Y2FzZSB0PT09biYmIXRoaXMuaXNJblZpZXdwb3J0JiZ0aGlzLmlzQWJvdmVWaWV3cG9ydDpjYXNlIHQ9PT1yJiZ0aGlzLmlzSW5WaWV3cG9ydDpjYXNlIHQ9PT1oJiZ0aGlzLmlzRnVsbHlJblZpZXdwb3J0OmNhc2UgdD09PWMmJnRoaXMuaXNBYm92ZVZpZXdwb3J0JiYhdGhpcy5pc0luVmlld3BvcnQ6Y2FzZSB0PT09YSYmdGhpcy5pc0luVmlld3BvcnQmJnRoaXMuaXNBYm92ZVZpZXdwb3J0OmlmKGUuY2FsbCh0aGlzLHRoaXMuY29udGFpbmVyLmxhdGVzdEV2ZW50LHRoaXMpLGkpcmV0dXJufWlmKCF0aGlzLmNhbGxiYWNrc1t0XSl0aHJvdyBuZXcgRXJyb3IoXCJUcmllZCB0byBhZGQgYSBzY3JvbGwgbW9uaXRvciBsaXN0ZW5lciBvZiB0eXBlIFwiK3QrXCIuIFlvdXIgb3B0aW9ucyBhcmU6IFwiK3Uuam9pbihcIiwgXCIpKTt0aGlzLmNhbGxiYWNrc1t0XS5wdXNoKHtjYWxsYmFjazplLGlzT25lOml8fCExfSl9LG9mZjpmdW5jdGlvbih0LGUpe2lmKCF0aGlzLmNhbGxiYWNrc1t0XSl0aHJvdyBuZXcgRXJyb3IoXCJUcmllZCB0byByZW1vdmUgYSBzY3JvbGwgbW9uaXRvciBsaXN0ZW5lciBvZiB0eXBlIFwiK3QrXCIuIFlvdXIgb3B0aW9ucyBhcmU6IFwiK3Uuam9pbihcIiwgXCIpKTtmb3IodmFyIGksbz0wO2k9dGhpcy5jYWxsYmFja3NbdF1bb107bysrKWlmKGkuY2FsbGJhY2s9PT1lKXt0aGlzLmNhbGxiYWNrc1t0XS5zcGxpY2UobywxKTticmVha319LG9uZTpmdW5jdGlvbih0LGUpe3RoaXMub24odCxlLCEwKX0scmVjYWxjdWxhdGVTaXplOmZ1bmN0aW9uKCl7dGhpcy5oZWlnaHQ9dGhpcy53YXRjaEl0ZW0ub2Zmc2V0SGVpZ2h0K3RoaXMub2Zmc2V0cy50b3ArdGhpcy5vZmZzZXRzLmJvdHRvbSx0aGlzLmJvdHRvbT10aGlzLnRvcCt0aGlzLmhlaWdodH0sdXBkYXRlOmZ1bmN0aW9uKCl7dGhpcy5pc0Fib3ZlVmlld3BvcnQ9dGhpcy50b3A8dGhpcy5jb250YWluZXIudmlld3BvcnRUb3AsdGhpcy5pc0JlbG93Vmlld3BvcnQ9dGhpcy5ib3R0b20+dGhpcy5jb250YWluZXIudmlld3BvcnRCb3R0b20sdGhpcy5pc0luVmlld3BvcnQ9dGhpcy50b3A8dGhpcy5jb250YWluZXIudmlld3BvcnRCb3R0b20mJnRoaXMuYm90dG9tPnRoaXMuY29udGFpbmVyLnZpZXdwb3J0VG9wLHRoaXMuaXNGdWxseUluVmlld3BvcnQ9dGhpcy50b3A+PXRoaXMuY29udGFpbmVyLnZpZXdwb3J0VG9wJiZ0aGlzLmJvdHRvbTw9dGhpcy5jb250YWluZXIudmlld3BvcnRCb3R0b218fHRoaXMuaXNBYm92ZVZpZXdwb3J0JiZ0aGlzLmlzQmVsb3dWaWV3cG9ydH0sZGVzdHJveTpmdW5jdGlvbigpe3ZhciB0PXRoaXMuY29udGFpbmVyLndhdGNoZXJzLmluZGV4T2YodGhpcyksZT10aGlzO3RoaXMuY29udGFpbmVyLndhdGNoZXJzLnNwbGljZSh0LDEpO2Zvcih2YXIgaT0wLG89dS5sZW5ndGg7aTxvO2krKyllLmNhbGxiYWNrc1t1W2ldXS5sZW5ndGg9MH0sbG9jazpmdW5jdGlvbigpe3RoaXMubG9ja2VkPSEwfSx1bmxvY2s6ZnVuY3Rpb24oKXt0aGlzLmxvY2tlZD0hMX19O2Zvcih2YXIgZD1mdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSxpKXt0aGlzLm9uLmNhbGwodGhpcyx0LGUsaSl9fSxmPTAsbT11Lmxlbmd0aDtmPG07ZisrKXt2YXIgdj11W2ZdO28ucHJvdG90eXBlW3ZdPWQodil9dC5leHBvcnRzPW99XSl9KTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNjcm9sbE1vbml0b3IuanMubWFwIiwiaW1wb3J0IHsgU3BsaXRTdHJlYW1Xcml0ZXIgfSBmcm9tIFwiLi93cml0ZXJzL1NwbGl0U3RyZWFtV3JpdGVyXCI7XG5pbXBvcnQgeyBUcmFuc3BvcnRMb2dnZXIgfSBmcm9tIFwiLi9sb2dnZXIvVHJhbnNwb3J0TG9nZ2VyXCI7XG5pbXBvcnQgeyBDb25zb2xlV3JpdGVyIH0gZnJvbSBcIi4vd3JpdGVycy9Db25zb2xlV3JpdGVyXCI7XG5pbXBvcnQgeyBDb25zb2xlVHJhbnNwb3J0IH0gZnJvbSBcIi4vbG9nZ2VyXCI7XG4vKipcbiAqIERlZmF1bHQgYXNzZW1ibHkgcG9pbnQgb2YgY29sbGVjdG9ycyBhbmQgd3JpdGVycy5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbGxlY3Rvck1vZHVsZSB7XG4gICAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgICAgICB0aGlzLmNvbGxlY3RvcnMgPSBbXTtcbiAgICAgICAgdGhpcy53cml0ZXJzID0gW107XG4gICAgICAgIHRoaXMudHJhbnNwb3J0cyA9IFtdO1xuICAgICAgICB0aGlzLmhhc1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICB9XG4gICAgYWRkKGNvbGxlY3Rvcikge1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNvbnRleHQgJiYgIWNvbGxlY3Rvci5nZXRDb250ZXh0KCkpXG4gICAgICAgICAgICBjb2xsZWN0b3Iuc2V0Q29udGV4dCh0aGlzLm9wdGlvbnMuY29udGV4dCk7XG4gICAgICAgIHRoaXMuY29sbGVjdG9ycy5wdXNoKGNvbGxlY3Rvcik7XG4gICAgICAgIGlmICh0aGlzLmhhc1N0YXJ0ZWQgPT09IHRydWUpXG4gICAgICAgICAgICB0aGlzLmludm9rZWRDb2xsZWN0b3IoY29sbGVjdG9yKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3RhcnQgY29sbGVjdGluZyBkYXRhIGJ5IGF0dGFjaGluZyBhbGwgY29sbGVjdG9yc1xuICAgICAqL1xuICAgIHN0YXJ0KCkge1xuICAgICAgICB0aGlzLmNvbGxlY3RvcnMuZm9yRWFjaChjb2xsZWN0b3IgPT4gdGhpcy5pbnZva2VkQ29sbGVjdG9yKGNvbGxlY3RvcikpO1xuICAgICAgICB0aGlzLmhhc1N0YXJ0ZWQgPSB0cnVlO1xuICAgIH1cbiAgICBhZGRMb2dUcmFuc3BvcnQodHJhbnNwb3J0KSB7XG4gICAgICAgIHRoaXMudHJhbnNwb3J0cy5wdXNoKHRyYW5zcG9ydCk7XG4gICAgfVxuICAgIHNldFRyYW5zcG9ydHModHJhbnNwb3J0cykge1xuICAgICAgICB0aGlzLnRyYW5zcG9ydHMgPSB0cmFuc3BvcnRzIHx8IFtdO1xuICAgIH1cbiAgICBzZXRXcml0ZXJzKHJlcGxhY2VtZW50V3JpdGVycykge1xuICAgICAgICB0aGlzLndyaXRlcnMgPSBBcnJheS5pc0FycmF5KHJlcGxhY2VtZW50V3JpdGVycykgPyBbLi4ucmVwbGFjZW1lbnRXcml0ZXJzXSA6IFtyZXBsYWNlbWVudFdyaXRlcnNdO1xuICAgIH1cbiAgICBzZXRMb2dnZXIobG9nZ2VyKSB7XG4gICAgICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyO1xuICAgIH1cbiAgICBpbnZva2VkQ29sbGVjdG9yKGNvbGxlY3Rvcikge1xuICAgICAgICBjb25zdCB3cml0ZXIgPSB0aGlzLmdldFdyaXRlcigpO1xuICAgICAgICBjb25zdCBsb2cgPSB0aGlzLmdldExvZ2dlcigpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29sbGVjdG9yLmF0dGFjaCh3cml0ZXIsIGxvZyk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGxvZy5lcnJvcihgWyR7Y29sbGVjdG9yLmNvbnN0cnVjdG9yLm5hbWV9XSBVbmV4cGVjdGVkIEV4Y2VwdGlvbiBkdXJpbmcgY29sbGVjdG9yIGF0dGFjaDogYCwgZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZ2V0TG9nZ2VyKCkge1xuICAgICAgICBjb25zdCBoYXNMb2dnZXIgPSAhIXRoaXMubG9nZ2VyO1xuICAgICAgICBpZiAoaGFzTG9nZ2VyKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9nZ2VyO1xuICAgICAgICBpZiAoIXRoaXMudHJhbnNwb3J0cyB8fCB0aGlzLnRyYW5zcG9ydHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBVFRFTlRJT04tU0VBUkNILUNPTExFQ1RPUi1XQVJOSU5HXCIpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwic2VhcmNoLWNvbGxlY3Rvcjogbm8gTG9nZ2VyVHJhbnNwb3J0IGNvbmZpZ3VyZWQgd2hpbGUgdXNpbmcgdGhlIGRlZmF1bHQgVHJhbnNwb3J0TG9nZ2VyLiBQbGVhc2UgYWRkIGEgdHJhbnNwb3J0IENvbGxlY3Rvck1vZHVsZSNhZGRMb2dUcmFuc3BvcnQgb3IgQ29sbGVjdG9yTW9kdWxlI3NldFRyYW5zcG9ydHNcIik7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJzZWFyY2gtY29sbGVjdG9yOiB3aWxsIEZBTExCQUNLIHRvIENvbnNvbGVUcmFuc3BvcnRcIik7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFRyYW5zcG9ydExvZ2dlcihbbmV3IENvbnNvbGVUcmFuc3BvcnQoKV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgVHJhbnNwb3J0TG9nZ2VyKHRoaXMudHJhbnNwb3J0cyk7XG4gICAgfVxuICAgIGdldFdyaXRlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud3JpdGVycy5sZW5ndGggPT0gMFxuICAgICAgICAgICAgPyB0aGlzLm9wdGlvbnMud3JpdGVyIHx8IG5ldyBDb25zb2xlV3JpdGVyKClcbiAgICAgICAgICAgIDogbmV3IFNwbGl0U3RyZWFtV3JpdGVyKHRoaXMud3JpdGVycyk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuLi91dGlscy9Db250ZXh0XCI7XG5leHBvcnQgY2xhc3MgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIGNvbnN0cnVjdG9yKHR5cGUsIGNvbnRleHQgPSBuZXcgQ29udGV4dCh3aW5kb3csIGRvY3VtZW50KSkge1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgIH1cbiAgICBnZXRUeXBlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50eXBlO1xuICAgIH1cbiAgICBzZXRDb250ZXh0KGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICB9XG4gICAgZ2V0Q29udGV4dCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGV4dDtcbiAgICB9XG4gICAgZ2V0V2luZG93KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0LmdldFdpbmRvdygpO1xuICAgIH1cbiAgICBnZXREb2N1bWVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGV4dC5nZXREb2N1bWVudCgpO1xuICAgIH1cbiAgICBhdHRhY2god3JpdGVyLCBsb2cpIHtcbiAgICAgICAgLy8gb3ZlcnJpZGUgaW4gc3ViY2xhc3NcbiAgICB9XG4gICAgLyoqXG4gICAgICogVXNlZCB0byBsb2cgaWYgYSBoYW5kbGVyIGZhaWxzIGl0cyBleGVjdXRpb25cbiAgICAgKiBVc2FnZTogZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHRoaXMubG9nV3JhcEhhbmRsZXIoeW91cmhhbmRsZXIsIGxvZ2dlcikpXG4gICAgICogQHBhcmFtIGhhbmRsZXJcbiAgICAgKiBAcGFyYW0gbG9nXG4gICAgICogQHBhcmFtIGhhbmRsZXJBcmdzXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIGxvZ1dyYXBIYW5kbGVyKGhhbmRsZXIsIGxvZywgLi4uaGFuZGxlckFyZ3MpIHtcbiAgICAgICAgcmV0dXJuICguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiBoYW5kbGVyKC4uLmFyZ3MsIC4uLmhhbmRsZXJBcmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgbG9nLmVycm9yKGBbJHt0aGlzLmNvbnN0cnVjdG9yLm5hbWV9XSBVbmV4cGVjdGVkIGVycm9yIGR1cmluZyByZXNvbHZlciBleGVjdXRpb246IGAsIGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBVc2VkIHRvIGV4ZWN1dGUgcmVzb2x2ZXIgZnVuY3Rpb25zLlxuICAgICAqIExvZ3MgYSBkZWJ1ZyBtZXNzYWdlIGlmIHRoZSB2YWx1ZSBpcyB1bmRlZmluZWQgb3IgbG9ncyBhbiBlcnJvciBpZiBhbiBleGNlcHRpb24gaXMgdGhyb3duIGJ5IHRoZSByZXNvbHZlclxuICAgICAqIEBwYXJhbSByZXNvbHZlciBBIHJlc29sdmVyIGZ1bmN0aW9uXG4gICAgICogQHBhcmFtIGxvZyB0aGUgbG9nZ2VyXG4gICAgICogQHBhcmFtIHJlc29sdmVyQXJncyBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIHRoZSByZXNvbHZlciBmdW5jdGlvblxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKi9cbiAgICByZXNvbHZlKHJlc29sdmVyLCBsb2csIC4uLnJlc29sdmVyQXJncykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHJlc29sdmVyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsID0gcmVzb2x2ZXIoLi4ucmVzb2x2ZXJBcmdzKTtcbiAgICAgICAgICAgICAgICBpZiAodmFsID09IHZvaWQgMClcbiAgICAgICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiUmVzb2x2ZXIgcmV0dXJuZWQgbm8gdmFsdWUuXCIsIHJlc29sdmVyKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBsb2cuZXJyb3IoYFske3RoaXMuY29uc3RydWN0b3IubmFtZX1dIFVuZXhwZWN0ZWQgZXJyb3IgZHVyaW5nIHJlc29sdmVyIGV4ZWN1dGlvbjogYCwgZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJpbXBvcnQgeyBTZW50aW5lbCB9IGZyb20gXCIuLi91dGlscy9TZW50aW5lbFwiO1xuaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuaW1wb3J0IHsgVHJhaWxUeXBlIH0gZnJvbSBcIi4uL3F1ZXJ5L1RyYWlsVHlwZVwiO1xuLyoqXG4gKiBDb2xsZWN0IGNsaWNrcyBvbiBlbGVtZW50cyBtYXRjaGluZyBhIHF1ZXJ5IHNlbGVjdG9yLiBIYW5kbGVzIGJvdGggRE9NIGVsZW1lbnRzXG4gKiBwcmVzZW50IGluIHRoZSBET00gYW5kIGVsZW1lbnRzIGluc2VydGVkIGFmdGVyIHRoZSBwYWdlIGxvYWQgLyBjb2xsZWN0b3IgY29uc3RydWN0aW9uLlxuICpcbiAqIFdoZW4gYSBjbGljayBvY2N1cnMsIGEgZnVuY3Rpb24gcHJvdmlkZWQgYXQgY29uc3RydWN0aW9uIHRpbWUgZ2V0IGludm9rZWQgdG8gY29sbGVjdCBkYXRhIHBvaW50c1xuICogZnJvbSB0aGUgZWxlbWVudC5cbiAqL1xuZXhwb3J0IGNsYXNzIEFzc29jaWF0ZWRQcm9kdWN0Q29sbGVjdG9yIGV4dGVuZHMgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdCBhIGNsaWNrIGNvbGxlY3RvclxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yRXhwcmVzc2lvbiAtIERvY3VtZW50IHF1ZXJ5IHNlbGVjdG9yIGlkZW50aWZ5aW5nIHRoZSBlbGVtZW50cyB0byBhdHRhY2ggdG9cbiAgICAgKiBAcGFyYW0gbWFpblByb2R1Y3RJZFxuICAgICAqIEBwYXJhbSByZXNvbHZlcnNcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZWxlY3RvckV4cHJlc3Npb24sIG1haW5Qcm9kdWN0SWQsIHJlc29sdmVycykge1xuICAgICAgICBzdXBlcihcImFzc29jaWF0ZWQtcHJvZHVjdFwiKTtcbiAgICAgICAgdGhpcy5tYWluUHJvZHVjdElkID0gbWFpblByb2R1Y3RJZDtcbiAgICAgICAgdGhpcy5zZWxlY3RvckV4cHJlc3Npb24gPSBzZWxlY3RvckV4cHJlc3Npb247XG4gICAgICAgIHRoaXMuaWRSZXNvbHZlciA9IHJlc29sdmVycy5pZFJlc29sdmVyO1xuICAgICAgICB0aGlzLnBvc2l0aW9uUmVzb2x2ZXIgPSByZXNvbHZlcnMucG9zaXRpb25SZXNvbHZlcjtcbiAgICAgICAgdGhpcy5wcmljZVJlc29sdmVyID0gcmVzb2x2ZXJzLnByaWNlUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMudHJhaWwgPSByZXNvbHZlcnMudHJhaWw7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFkZCBjbGljayBldmVudCBsaXN0ZW5lcnMgdG8gdGhlIGlkZW50aWZpZWQgZWxlbWVudHMsIHdyaXRlIHRoZSBkYXRhXG4gICAgICogd2hlbiB0aGUgZXZlbnQgb2NjdXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gd3JpdGVyIC0gVGhlIHdyaXRlciB0byBzZW5kIHRoZSBkYXRhIHRvXG4gICAgICogQHBhcmFtIGxvZ1xuICAgICAqL1xuICAgIGF0dGFjaCh3cml0ZXIsIGxvZykge1xuICAgICAgICBjb25zdCBjb2xsZWN0ID0gZWxlbWVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBpZCA9IHRoaXMucmVzb2x2ZSh0aGlzLmlkUmVzb2x2ZXIsIGxvZywgZWxlbWVudCk7XG4gICAgICAgICAgICBpZiAoaWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy50cmFpbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBGaW5kIG91dCB0aGUgcXVlcnkgc291cmNlIG9mIHRoZSBtYWluIHByb2R1Y3QuIE5vdGUgdGhhdCBkZXNwaXRlIGJlaW5nIGFcbiAgICAgICAgICAgICAgICAgICAgLy8gXCJtYWluXCIgcHJvZHVjdCwgaXQgY291bGQgYmUgYSAybmQgb3IgM3JkLCA0dGggbGV2ZWwgb2YgYXNzb2NpYXRlZCBwcm9kdWN0IGJyb3dzaW5nXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzVHJhaWwgPSB0aGlzLnRyYWlsLmZldGNoKHRoaXMubWFpblByb2R1Y3RJZCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1RyYWlsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVcG9uIGEgZm9sbG93LXVwIGV2ZW50IGZvciB0aGlzIHByb2R1Y3QgKGV4LiBiYXNrZXQpLCB3ZSB3b3VsZCBwaWNrIHRoaXMgdHJhaWxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhaWwucmVnaXN0ZXIoaWQsIFRyYWlsVHlwZS5Bc3NvY2lhdGVkLCBwcmV2aW91c1RyYWlsLnF1ZXJ5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBpZCxcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHRoaXMucmVzb2x2ZSh0aGlzLnBvc2l0aW9uUmVzb2x2ZXIsIGxvZywgZWxlbWVudCksXG4gICAgICAgICAgICAgICAgICAgIHByaWNlOiB0aGlzLnJlc29sdmUodGhpcy5wcmljZVJlc29sdmVyLCBsb2csIGVsZW1lbnQpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IGVsID0+IHtcbiAgICAgICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCB0aGlzLmxvZ1dyYXBIYW5kbGVyKGV2ID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gY29sbGVjdChlbCk7XG4gICAgICAgICAgICAgICAgaWYgKHBheWxvYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLndyaXRlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwidHlwZVwiOiB0aGlzLmdldFR5cGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLnBheWxvYWRcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgbG9nKSk7XG4gICAgICAgIH07XG4gICAgICAgIG5ldyBTZW50aW5lbCh0aGlzLmdldERvY3VtZW50KCkpLm9uKHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uLCBoYW5kbGVyKTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBDbGlja0NvbGxlY3RvciB9IGZyb20gXCIuL0NsaWNrQ29sbGVjdG9yXCI7XG5pbXBvcnQgeyBMaXN0ZW5lclR5cGUgfSBmcm9tIFwiLi4vdXRpbHMvTGlzdGVuZXJUeXBlXCI7XG4vKipcbiAqIENvbGxlY3QgaWQgYW5kIHByaWNlIGlmIGFuIGl0ZW0gd2FzIGFkZCBpbnRvIHRoZSBiYXNrZXRcbiAqL1xuZXhwb3J0IGNsYXNzIEJhc2tldENsaWNrQ29sbGVjdG9yIGV4dGVuZHMgQ2xpY2tDb2xsZWN0b3Ige1xuICAgIGNvbnN0cnVjdG9yKHNlbGVjdG9yLCBpZFJlc29sdmVyLCBwcmljZVJlc29sdmVyLCBsaXN0ZW5lclR5cGUgPSBMaXN0ZW5lclR5cGUuU2VudGluZWwpIHtcbiAgICAgICAgc3VwZXIoc2VsZWN0b3IsIFwiYmFza2V0XCIsIGxpc3RlbmVyVHlwZSk7XG4gICAgICAgIHRoaXMuaWRSZXNvbHZlciA9IGlkUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMucHJpY2VSZXNvbHZlciA9IHByaWNlUmVzb2x2ZXI7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbGxlY3QgdGhlIHByb2R1Y3QgY2xpY2sgaW5mb3JtYXRpb24gZnJvbSB0aGUgZWxlbWVudFxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIGNvbGxlY3QoZWxlbWVudCwgZXZlbnQsIGxvZykge1xuICAgICAgICBjb25zdCBpZCA9IHRoaXMucmVzb2x2ZSh0aGlzLmlkUmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpO1xuICAgICAgICBpZiAoaWQpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgICAgcHJpY2U6IHRoaXMucmVzb2x2ZSh0aGlzLnByaWNlUmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuLyoqXG4gKiBDb2xsZWN0IGJhc2ljIGJyb3dzZXIgaW5mb3JtYXRpb24uIE5vdGUgdGhhdCBkZXBlbmRpbmcgb24gaG93IHlvdSB1c2UgdGhpcyB5b3UgbWF5XG4gKiBuZWVkIHRvIGNvbnN1bHQgdGhlIEdEUFIgZ3VpZGVsaW5lc1xuICovXG5leHBvcnQgY2xhc3MgQnJvd3NlckNvbGxlY3RvciBleHRlbmRzIEFic3RyYWN0Q29sbGVjdG9yIHtcbiAgICBjb25zdHJ1Y3RvcihvcHRpb25zID0geyByZWNvcmRVcmw6IHRydWUsIHJlY29yZFJlZmVycmVyOiB0cnVlLCByZWNvcmRMYW5ndWFnZTogZmFsc2UgfSkge1xuICAgICAgICBzdXBlcihcImJyb3dzZXJcIik7XG4gICAgICAgIHRoaXMucmVjb3JkVXJsID0gb3B0aW9ucy5yZWNvcmRVcmwgfHwgZmFsc2U7XG4gICAgICAgIHRoaXMucmVjb3JkUmVmZXJyZXIgPSBvcHRpb25zLnJlY29yZFJlZmVycmVyIHx8IGZhbHNlO1xuICAgICAgICB0aGlzLnJlY29yZExhbmd1YWdlID0gb3B0aW9ucy5yZWNvcmRMYW5ndWFnZSB8fCBmYWxzZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXR0YWNoIGEgd3JpdGVyLCBub3RlIHRoYXQgdGhpcyBjb2xsZWN0b3IgaXMgbm90IGFzeW5jaHJvbm91cyBhbmQgd2lsbCB3cml0ZVxuICAgICAqIHRoZSBkYXRhIGltbWVkaWF0ZWxseVxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHdyaXRlciAtIFRoZSB3cml0ZXIgdG8gc2VuZCB0aGUgZGF0YSB0b1xuICAgICAqL1xuICAgIGF0dGFjaCh3cml0ZXIpIHtcbiAgICAgICAgY29uc3Qgd2luID0gdGhpcy5nZXRXaW5kb3coKTtcbiAgICAgICAgY29uc3QgZG9jID0gdGhpcy5nZXREb2N1bWVudCgpO1xuICAgICAgICBjb25zdCBkYXRhID0ge1xuICAgICAgICAgICAgdHlwZTogdGhpcy5nZXRUeXBlKCksXG4gICAgICAgICAgICB0b3VjaDogKCdvbnRvdWNoc3RhcnQnIGluIHdpbmRvdykgfHwgKG5hdmlnYXRvci5tYXhUb3VjaFBvaW50cyA+IDApXG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLnJlY29yZExhbmd1YWdlKVxuICAgICAgICAgICAgZGF0YS5sYW5nID0gd2luLm5hdmlnYXRvci5sYW5ndWFnZTtcbiAgICAgICAgaWYgKHRoaXMucmVjb3JkVXJsKVxuICAgICAgICAgICAgZGF0YS51cmwgPSB3aW4ubG9jYXRpb24uaHJlZjtcbiAgICAgICAgaWYgKHRoaXMucmVjb3JkUmVmZXJyZXIpXG4gICAgICAgICAgICBkYXRhLnJlZiA9IGRvYy5yZWZlcnJlcjtcbiAgICAgICAgd3JpdGVyLndyaXRlKGRhdGEpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IEFic3RyYWN0Q29sbGVjdG9yIH0gZnJvbSBcIi4vQWJzdHJhY3RDb2xsZWN0b3JcIjtcbmltcG9ydCB7IFNlbnRpbmVsIH0gZnJvbSBcIi4uL3V0aWxzL1NlbnRpbmVsXCI7XG5pbXBvcnQgeyBMaXN0ZW5lclR5cGUgfSBmcm9tIFwiLi4vdXRpbHMvTGlzdGVuZXJUeXBlXCI7XG4vKipcbiAqIFRyaWdnZXJlZCBieSBhIGNsaWNrU2VsZWN0b3IsIHRoZSBjb2xsZWN0b3Igd2lsbCBmaXJlIHRoZSBjb250ZW50U2VsZWN0b3IgdG8gc2VsZWN0IGVsZW1lbnRzIHRvIGNvbGxlY3RcbiAqIGluZm9ybWF0aW9uIGZyb20gYW5kIHdyaXRlIHRvIHRoZSBjb2xsZWN0b3Igd3JpdGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBDaGVja291dENsaWNrQ29sbGVjdG9yIGV4dGVuZHMgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIGNvbnN0cnVjdG9yKGNsaWNrU2VsZWN0b3IsIGNvbnRlbnRTZWxlY3RvciwgaWRSZXNvbHZlciwgcHJpY2VSZXNvbHZlciwgYW1vdW50UmVzb2x2ZXIsIGxpc3RlbmVyVHlwZSA9IExpc3RlbmVyVHlwZS5TZW50aW5lbCkge1xuICAgICAgICBzdXBlcihcImNoZWNrb3V0XCIpO1xuICAgICAgICB0aGlzLmNsaWNrU2VsZWN0b3IgPSBjbGlja1NlbGVjdG9yO1xuICAgICAgICB0aGlzLmNvbnRlbnRTZWxlY3RvciA9IGNvbnRlbnRTZWxlY3RvcjtcbiAgICAgICAgdGhpcy5pZFJlc29sdmVyID0gaWRSZXNvbHZlcjtcbiAgICAgICAgdGhpcy5wcmljZVJlc29sdmVyID0gcHJpY2VSZXNvbHZlcjtcbiAgICAgICAgdGhpcy5hbW91bnRSZXNvbHZlciA9IGFtb3VudFJlc29sdmVyO1xuICAgICAgICB0aGlzLmxpc3RlbmVyVHlwZSA9IGxpc3RlbmVyVHlwZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkIGNsaWNrIGV2ZW50IGxpc3RlbmVycyB0byB0aGUgaWRlbnRpZmllZCBlbGVtZW50cywgd3JpdGUgdGhlIGRhdGFcbiAgICAgKiB3aGVuIHRoZSBldmVudCBvY2N1cnNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB3cml0ZXIgLSBUaGUgd3JpdGVyIHRvIHNlbmQgdGhlIGRhdGEgdG9cbiAgICAgKiBAcGFyYW0gbG9nXG4gICAgICovXG4gICAgYXR0YWNoKHdyaXRlciwgbG9nKSB7XG4gICAgICAgIGNvbnN0IGRvYyA9IHRoaXMuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgLy8gQWN0aXZhdGVzIG9uIGNsaWNrIG9mIHRoZSBlbGVtZW50IHNlbGVjdGVkIHVzaW5nIHRoZSBjbGlja1NlbGVjdG9yXG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRzID0gZG9jLnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5jb250ZW50U2VsZWN0b3IpO1xuICAgICAgICAgICAgZWxlbWVudHMuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBpZCA9IHRoaXMucmVzb2x2ZSh0aGlzLmlkUmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpO1xuICAgICAgICAgICAgICAgIGlmIChpZCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcmljZTogdGhpcy5yZXNvbHZlKHRoaXMucHJpY2VSZXNvbHZlciwgbG9nLCBlbGVtZW50LCBldmVudCksXG4gICAgICAgICAgICAgICAgICAgICAgICBhbW91bnQ6IHRoaXMucmVzb2x2ZSh0aGlzLmFtb3VudFJlc29sdmVyLCBsb2csIGVsZW1lbnQsIGV2ZW50KVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSB3cml0ZSBlYWNoIGl0ZW0gc2VwYXJhdGVseSAtIHRoZXkgbWF5IGJlIGNvbWluZyBmcm9tIGRpZmZlcmVudCBxdWVyaWVzXG4gICAgICAgICAgICAgICAgICAgIC8vIHRodXMgd2hlbiB3ZSB0cnkgdG8gcmVzb2x2ZSB0aGUgdHJhaWwgZm9yIGVhY2ggb2YgdGhlbSB3ZSBuZWVkIHRvIGhhdmUgdGhlbVxuICAgICAgICAgICAgICAgICAgICAvLyBhcyBzZXBhcmF0ZSByZWNvcmRzXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci53cml0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLmdldFR5cGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmRhdGFcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8vIFRoZSBTZW50aWVsIGxpYnJhcnkgdXNlcyBhbmltYXRpb25zdGFydCBldmVudCBsaXN0ZW5lcnMgd2hpY2ggbWF5IGludGVyZmVyZSB3aXRoXG4gICAgICAgIC8vIGFuaW1hdGlvbnMgYXR0YWNoZWQgb24gZWxlbWVuZXRzLiBUaGUgaW4tbGlicmFyeSBwcm92aWRlZCB3b3JrYXJvdW5kIG1lY2hhbmlzbSBkb2VzIG5vdCB3b3JrXG4gICAgICAgIC8vIDEwMCUsIHRodXMgd2UgcHJvdmlkZSB0aGUgbGlzdGVuZXJUeXBlIGNob2ljZSBiZWxvdy4gVGhlIHRyYWRlb2Zmc1xuICAgICAgICAvLyBcImRvbVwiIC0gbm8gYW5pbWF0aW9uIGludGVyZmVyZW5jZSwgb25seSBvbmNsaWNrIGF0dGFjaGVkLCBidXQgZG9lcyBub3QgaGFuZGxlIGVsZW1lbnRzIGluc2VydGVkIGluIHRoZSBET00gbGF0ZXJcbiAgICAgICAgLy8gXCJzZW50aW5lbCAoZGVmYXVsdClcIiAtIHdvcmtzIG9uIGVsZW1lbnRzIGluc2VydGVkIGluIHRoZSBET00gYW55dGltZSwgYnV0IGludGVyZmVyZXMgd2l0aCBDU1MgYW5pbWF0aW9ucyBvbiB0aGVzZSBlbGVtZW50c1xuICAgICAgICBpZiAodGhpcy5saXN0ZW5lclR5cGUgPT09IExpc3RlbmVyVHlwZS5Eb20pIHtcbiAgICAgICAgICAgIGNvbnN0IG5vZGVMaXN0ID0gZG9jLnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5jbGlja1NlbGVjdG9yKTtcbiAgICAgICAgICAgIG5vZGVMaXN0LmZvckVhY2goKGVsKSA9PiBlbC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgdGhpcy5sb2dXcmFwSGFuZGxlcihoYW5kbGVyLCBsb2cpKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBzZW50aW5lbCA9IG5ldyBTZW50aW5lbCh0aGlzLmdldERvY3VtZW50KCkpO1xuICAgICAgICAgICAgc2VudGluZWwub24odGhpcy5jbGlja1NlbGVjdG9yLCBlbCA9PiBlbC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgdGhpcy5sb2dXcmFwSGFuZGxlcihoYW5kbGVyLCBsb2cpKSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJpbXBvcnQgeyBBYnN0cmFjdENvbGxlY3RvciB9IGZyb20gXCIuL0Fic3RyYWN0Q29sbGVjdG9yXCI7XG5pbXBvcnQgeyBTZW50aW5lbCB9IGZyb20gXCIuLi91dGlscy9TZW50aW5lbFwiO1xuaW1wb3J0IHsgTGlzdGVuZXJUeXBlIH0gZnJvbSBcIi4uL3V0aWxzL0xpc3RlbmVyVHlwZVwiO1xuLyoqXG4gKiBDb2xsZWN0IGNsaWNrcyBvbiBlbGVtZW50cyBtYXRjaGluZyBhIHF1ZXJ5IHNlbGVjdG9yLiBIYW5kbGVzIGJvdGggRE9NIGVsZW1lbnRzXG4gKiBwcmVzZW50IGluIHRoZSBET00gYW5kIGVsZW1lbnRzIGluc2VydGVkIGFmdGVyIHRoZSBwYWdlIGxvYWQgLyBjb2xsZWN0b3IgY29uc3RydWN0aW9uLlxuICpcbiAqIFdoZW4gYSBjbGljayBvY2N1cnMsIGEgZnVuY3Rpb24gcHJvdmlkZWQgYXQgY29uc3RydWN0aW9uIHRpbWUgZ2V0IGludm9rZWQgdG8gY29sbGVjdCBkYXRhIHBvaW50c1xuICogZnJvbSB0aGUgZWxlbWVudC5cbiAqL1xuZXhwb3J0IGNsYXNzIENsaWNrQ29sbGVjdG9yIGV4dGVuZHMgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdCBhIGNsaWNrIGNvbGxlY3RvclxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yRXhwcmVzc2lvbiAtIERvY3VtZW50IHF1ZXJ5IHNlbGVjdG9yIGlkZW50aWZ5aW5nIHRoZSBlbGVtZW50cyB0byBhdHRhY2ggdG9cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSAtIFRoZSB0eXBlIE9GIGVsZW1lbnQgY2xpY2sgdG8gcmVwb3J0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxpc3RlbmVyVHlwZSAtIFdoZXRoZXIgdGhlIGxpc3RlbmVyIHNob3VsZCBiZSBhIGRvbSBvciBzZW50aW5lbCBsaXN0ZW5lclxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlbGVjdG9yRXhwcmVzc2lvbiwgdHlwZSA9IFwiY2xpY2tcIiwgbGlzdGVuZXJUeXBlID0gTGlzdGVuZXJUeXBlLlNlbnRpbmVsKSB7XG4gICAgICAgIHN1cGVyKHR5cGUpO1xuICAgICAgICB0aGlzLnNlbGVjdG9yRXhwcmVzc2lvbiA9IHNlbGVjdG9yRXhwcmVzc2lvbjtcbiAgICAgICAgdGhpcy5saXN0ZW5lclR5cGUgPSBsaXN0ZW5lclR5cGU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFic3RyYWN0IGNvbGxlY3Rpb24gbWV0aG9kLCBtdXN0IGJlIG92ZXJyaWRkZW4gaW4gdGhlIHN1YmNsYXNzZXNcbiAgICAgKiBAYWJzdHJhY3RcbiAgICAgKi9cbiAgICBjb2xsZWN0KGVsZW1lbnQsIGV2ZW50LCBsb2cpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkIGNsaWNrIGV2ZW50IGxpc3RlbmVycyB0byB0aGUgaWRlbnRpZmllZCBlbGVtZW50cywgd3JpdGUgdGhlIGRhdGFcbiAgICAgKiB3aGVuIHRoZSBldmVudCBvY2N1cnNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB3cml0ZXIgLSBUaGUgd3JpdGVyIHRvIHNlbmQgdGhlIGRhdGEgdG9cbiAgICAgKiBAcGFyYW0gbG9nXG4gICAgICovXG4gICAgYXR0YWNoKHdyaXRlciwgbG9nKSB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSAoZXZlbnQsIGVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB0aGlzLmNvbGxlY3QoZWxlbWVudCwgZXZlbnQsIGxvZyk7XG4gICAgICAgICAgICBpZiAocGF5bG9hZCkge1xuICAgICAgICAgICAgICAgIHdyaXRlci53cml0ZSh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMudHlwZSxcbiAgICAgICAgICAgICAgICAgICAgLi4ucGF5bG9hZFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvLyBUaGUgU2VudGllbCBsaWJyYXJ5IHVzZXMgYW5pbWF0aW9uc3RhcnQgZXZlbnQgbGlzdGVuZXJzIHdoaWNoIG1heSBpbnRlcmZlcmUgd2l0aFxuICAgICAgICAvLyBhbmltYXRpb25zIGF0dGFjaGVkIG9uIGVsZW1lbmV0cy4gVGhlIGluLWxpYnJhcnkgcHJvdmlkZWQgd29ya2Fyb3VuZCBtZWNoYW5pc20gZG9lcyBub3Qgd29ya1xuICAgICAgICAvLyAxMDAlLCB0aHVzIHdlIHByb3ZpZGUgdGhlIGxpc3RlbmVyVHlwZSBjaG9pY2UgYmVsb3cuIFRoZSB0cmFkZW9mZnNcbiAgICAgICAgLy8gXCJkb21cIiAtIG5vIGFuaW1hdGlvbiBpbnRlcmZlcmVuY2UsIG9ubHkgb25jbGljayBhdHRhY2hlZCwgYnV0IGRvZXMgbm90IGhhbmRsZSBlbGVtZW50cyBpbnNlcnRlZCBpbiB0aGUgRE9NIGxhdGVyXG4gICAgICAgIC8vIFwic2VudGluZWwgKGRlZmF1bHQpXCIgLSB3b3JrcyBvbiBlbGVtZW50cyBpbnNlcnRlZCBpbiB0aGUgRE9NIGFueXRpbWUsIGJ1dCBpbnRlcmZlcmVzIHdpdGggQ1NTIGFuaW1hdGlvbnMgb24gdGhlc2UgZWxlbWVudHNcbiAgICAgICAgaWYgKHRoaXMubGlzdGVuZXJUeXBlID09PSBMaXN0ZW5lclR5cGUuRG9tKSB7XG4gICAgICAgICAgICBjb25zdCBub2RlTGlzdCA9IHRoaXMuZ2V0RG9jdW1lbnQoKS5xdWVyeVNlbGVjdG9yQWxsKHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uKTtcbiAgICAgICAgICAgIG5vZGVMaXN0LmZvckVhY2goKGVsKSA9PiBlbC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgdGhpcy5sb2dXcmFwSGFuZGxlcihoYW5kbGVyLCBsb2csIGVsKSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3Qgc2VudGluZWwgPSBuZXcgU2VudGluZWwodGhpcy5nZXREb2N1bWVudCgpKTtcbiAgICAgICAgICAgIHNlbnRpbmVsLm9uKHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uLCBlbCA9PiBlbC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgdGhpcy5sb2dXcmFwSGFuZGxlcihoYW5kbGVyLCBsb2csIGVsKSkpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgTGlzdGVuZXJUeXBlIH0gZnJvbSBcIi4uL3V0aWxzL0xpc3RlbmVyVHlwZVwiO1xuaW1wb3J0IHsgU2VudGluZWwgfSBmcm9tIFwiLi4vdXRpbHMvU2VudGluZWxcIjtcbmltcG9ydCB7IFdyaXRlclJlc29sdmVyQ29sbGVjdG9yIH0gZnJvbSBcIi4vV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3JcIjtcbi8qKlxuICogRXh0ZW5kcyBXcml0ZXJSZXNvbHZlckNvbGxlY3RvciBhbmQgaW52b2tlcyB0aGUgV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3IjYXR0YWNoKHdyaXRlciwgbG9nKVxuICogd2hlbiBhIGNsaWNrIG9uIGFuIGVsZW1lbnQgZm9yIHRoZSBwcm92aWRlZCBcInNlbGVjdG9yRXhwcmVzc2lvblwiIG9jY3Vyc1xuICovXG5leHBvcnQgY2xhc3MgQ2xpY2tXcml0ZXJSZXNvbHZlckNvbGxlY3RvciBleHRlbmRzIFdyaXRlclJlc29sdmVyQ29sbGVjdG9yIHtcbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBzZWxlY3RvckV4cHJlc3Npb24gdGhlIGNzcyBleHByZXNzaW9uIHRvIHF1ZXJ5IGZvciBvdGhlciBlbGVtZW50c1xuICAgICAqIEBwYXJhbSB0eXBlIHRoZSB0eXBlIG9mIHRoZSBldmVudFxuICAgICAqIEBwYXJhbSByZXNvbHZlciBhIHtXcml0ZXJSZXNvbHZlcn0gd2hpY2ggd2lsbCBiZSBleGVjdXRlZCBhcyBzb29uIGFzIGFuIGVsZW1lbnQgbWF0Y2hpbmcgdGhlIHNlbGVjdG9yRXhwcmVzc2lvbiBpcyBjbGlja2VkXG4gICAgICogQHBhcmFtIGxpc3RlbmVyVHlwZSB7TGlzdGVuZXJUeXBlfVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlbGVjdG9yRXhwcmVzc2lvbiwgdHlwZSwgcmVzb2x2ZXIsIGxpc3RlbmVyVHlwZSA9IExpc3RlbmVyVHlwZS5TZW50aW5lbCkge1xuICAgICAgICBzdXBlcih0eXBlLCByZXNvbHZlcik7XG4gICAgICAgIHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uID0gc2VsZWN0b3JFeHByZXNzaW9uO1xuICAgICAgICB0aGlzLmxpc3RlbmVyVHlwZSA9IGxpc3RlbmVyVHlwZTtcbiAgICB9XG4gICAgYXR0YWNoKHdyaXRlciwgbG9nKSB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSAoZWwsIGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBzdXBlci5hdHRhY2god3JpdGVyLCBsb2cpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5saXN0ZW5lclR5cGUgPT09IExpc3RlbmVyVHlwZS5Eb20pIHtcbiAgICAgICAgICAgIGNvbnN0IG5vZGVMaXN0ID0gdGhpcy5nZXREb2N1bWVudCgpLnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5zZWxlY3RvckV4cHJlc3Npb24pO1xuICAgICAgICAgICAgbm9kZUxpc3QuZm9yRWFjaChlbCA9PiBlbC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZXYgPT4gdGhpcy5sb2dXcmFwSGFuZGxlcihoYW5kbGVyLCBsb2csIGVsLCBldikoKSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3Qgc2VudGluZWwgPSBuZXcgU2VudGluZWwodGhpcy5nZXREb2N1bWVudCgpKTtcbiAgICAgICAgICAgIHNlbnRpbmVsLm9uKHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uLCBlbCA9PiBlbC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZXYgPT4gdGhpcy5sb2dXcmFwSGFuZGxlcihoYW5kbGVyLCBsb2csIGVsLCBldikoKSkpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQ2xpY2tDb2xsZWN0b3IgfSBmcm9tIFwiLi9DbGlja0NvbGxlY3RvclwiO1xuLyoqXG4gKiBDbGlja0NvbGxlY3RvciBlbWl0dGluZyBcImZpbHRlclwiIGV2ZW50cywgYXR0YWNoIHRvIGZhY2V0IGxpbmtzXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWx0ZXJDbGlja0NvbGxlY3RvciBleHRlbmRzIENsaWNrQ29sbGVjdG9yIHtcbiAgICBjb25zdHJ1Y3RvcihzZWxlY3RvciwgY29sbGVjdG9yKSB7XG4gICAgICAgIHN1cGVyKHNlbGVjdG9yLCBcImZpbHRlclwiKTtcbiAgICAgICAgdGhpcy5yZXNvbHZlciA9IGNvbGxlY3RvcjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29sbGVjdCB0aGUgcHJvZHVjdCBjbGljayBpbmZvcm1hdGlvbiBmcm9tIHRoZSBlbGVtZW50XG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgY29sbGVjdChlbGVtZW50LCBldmVudCwgbG9nKSB7XG4gICAgICAgIHJldHVybiB7IHF1ZXJ5OiB0aGlzLnJlc29sdmUodGhpcy5yZXNvbHZlciwgbG9nLCBlbGVtZW50LCBldmVudCkgfTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBXcml0ZXJSZXNvbHZlckNvbGxlY3RvciB9IGZyb20gXCIuL1dyaXRlclJlc29sdmVyQ29sbGVjdG9yXCI7XG4vKipcbiAqIFRyaWdnZXJlZCB3aGVuIHRoZSBjbGllbnQgaGFzIHRyaWdnZXJlZC9maXJlZCBhIHNlYXJjaFxuICovXG5leHBvcnQgY2xhc3MgRmlyZWRTZWFyY2hDb2xsZWN0b3IgZXh0ZW5kcyBXcml0ZXJSZXNvbHZlckNvbGxlY3RvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0IGZpcmVkIHNlYXJjaCBjb2xsZWN0b3JcbiAgICAgKlxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IHJlc29sdmVyIC0gRnVuY3Rpb24gdGhhdCB0cmlnZ2VycyB0aGUgd3JpdGluZy4gV2UgY2FuJ3QgYWx3YXlzIGRldGVybWluZSB3aGVuIHNlYXJjaCB0cmlnZ2VycywgbGVhdmUgdG8gdGhlIGltcGxlbWVudGF0aW9uIHRvIGRldGVybWluZSB3aGVuL2hvd1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHJlc29sdmVyKSB7XG4gICAgICAgIHN1cGVyKFwiZmlyZWQtc2VhcmNoXCIsIHJlc29sdmVyKTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBBYnN0cmFjdENvbGxlY3RvciB9IGZyb20gXCIuL0Fic3RyYWN0Q29sbGVjdG9yXCI7XG4vKipcbiAqIENvbGxlY3QgZGlmZmVyZW50IHR5cGUgb2YgZXZlbnRzIHZpYSBhIGN1c3RvbSBldmVudC4gVGhlIGN1c3RvbSBldmVudCBzaG91bGQgaG9sZCB0aGUgcHJvcGVydGllc1xuICogXCJ0eXBlXCIgYW5kIFwiZGF0YVwiIGluIHRoZSBjdXN0b20gcGF5bG9hZC5cbiAqXG4gKiBTZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvR3VpZGUvRXZlbnRzL0NyZWF0aW5nX2FuZF90cmlnZ2VyaW5nX2V2ZW50cyBmb3IgZ3VpZGFuY2VcbiAqL1xuZXhwb3J0IGNsYXNzIEdlbmVyaWNFdmVudENvbGxlY3RvciBleHRlbmRzIEFic3RyYWN0Q29sbGVjdG9yIHtcbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3QgZXZlbnQgYmFzZWQgY29sbGVjdG9yXG4gICAgICpcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gdGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlYWN0IG9uXG4gICAgICogQHBhcmFtIHR5cGVcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihldmVudE5hbWUsIHR5cGUgPSBcIkdlbmVyaWNFdmVudFwiKSB7XG4gICAgICAgIHN1cGVyKHR5cGUpO1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXR0YWNoIGEgd3JpdGVyLCBub3RlIHRoYXQgdGhpcyBjb2xsZWN0b3IgaXMgYXN5bmNocm9ub3VzIGFuZCB3aWxsIHdyaXRlXG4gICAgICogdGhlIGRhdGEgd2hlbiB0aGUgZXZlbnQgdHJpZ2dlcnNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB3cml0ZXIgLSBUaGUgd3JpdGVyIHRvIHNlbmQgdGhlIGRhdGEgdG9cbiAgICAgKiBAcGFyYW0gbG9nXG4gICAgICovXG4gICAgYXR0YWNoKHdyaXRlciwgbG9nKSB7XG4gICAgICAgIHRoaXMuZ2V0V2luZG93KCkuYWRkRXZlbnRMaXN0ZW5lcih0aGlzLmV2ZW50TmFtZSwgdGhpcy5sb2dXcmFwSGFuZGxlcigoZSkgPT4ge1xuICAgICAgICAgICAgd3JpdGVyLndyaXRlKHtcbiAgICAgICAgICAgICAgICBcInR5cGVcIjogZS5kZXRhaWwudHlwZSxcbiAgICAgICAgICAgICAgICAuLi5lLmRldGFpbC5kYXRhXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgbG9nKSk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuaW1wb3J0IHsgU2VudGluZWwgfSBmcm9tIFwiLi4vdXRpbHMvU2VudGluZWxcIjtcbmltcG9ydCBTY3JvbGxNb25pdG9yIGZyb20gXCJzY3JvbGxtb25pdG9yXCI7XG5pbXBvcnQgeyBMb2NhbFN0b3JhZ2VRdWV1ZSB9IGZyb20gXCIuLi91dGlscy9Mb2NhbFN0b3JhZ2VRdWV1ZVwiO1xuaW1wb3J0IHsgZGVib3VuY2UgfSBmcm9tIFwiLi4vdXRpbHMvVXRpbFwiO1xuLyoqXG4gKiBDb2xsZWN0IGltcHJlc3Npb25zIC0gYSBkaXNwbGF5IG9mIGEgcHJvZHVjdCBpbiB0aGUgYnJvd3NlciB2aWV3cG9ydC4gSWYgdGhlIHByb2R1Y3QgaXMgc2hvd24gbXVsdGlwbGVcbiAqIHRpbWVzLCB0aGUgY29sbGVjdG9yIHdpbGwgcmVjb3JkIG11bHRpcGxlIGV2ZW50cyBpLmUuIHdlIGRvbid0IGFwcGx5IGZpbHRlciBsb2dpYyBoZXJlLlxuICpcbiAqIEhhbmRsZXMgYm90aCBET00gZWxlbWVudHMgcHJlc2VudCBpbiB0aGUgRE9NIGFuZCBlbGVtZW50cyBpbnNlcnRlZCBhZnRlciB0aGUgcGFnZSBsb2FkIC8gY29sbGVjdG9yIGNvbnN0cnVjdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIEltcHJlc3Npb25Db2xsZWN0b3IgZXh0ZW5kcyBBYnN0cmFjdENvbGxlY3RvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0IGltcHJlc3Npb24gY29sbGVjdG9yXG4gICAgICpcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JFeHByZXNzaW9uIC0gRG9jdW1lbnQgcXVlcnkgc2VsZWN0b3IgaWRlbnRpZnlpbmcgdGhlIGVsZW1lbnRzIHRvIGF0dGFjaCB0b1xuICAgICAqIEBwYXJhbSBpZFJlc29sdmVyIC0gUmVzb2x2ZSB0aGUgaWQgb2YgdGhlIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0gcG9zaXRpb25SZXNvbHZlciAtIFJlc29sdmUgdGhlIHBvc2l0aW9uIG9mIHRoZSBlbGVtZW50IGluIGRvbVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlbGVjdG9yRXhwcmVzc2lvbiwgaWRSZXNvbHZlciwgcG9zaXRpb25SZXNvbHZlcikge1xuICAgICAgICBzdXBlcihcImltcHJlc3Npb25cIik7XG4gICAgICAgIHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uID0gc2VsZWN0b3JFeHByZXNzaW9uO1xuICAgICAgICB0aGlzLmlkUmVzb2x2ZXIgPSBpZFJlc29sdmVyO1xuICAgICAgICB0aGlzLnBvc2l0aW9uUmVzb2x2ZXIgPSBwb3NpdGlvblJlc29sdmVyO1xuICAgICAgICB0aGlzLnF1ZXVlID0gbmV3IExvY2FsU3RvcmFnZVF1ZXVlKFwiaW1wcmVzc2lvbnNcIik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFkZCBpbXByZXNzaW9uIGV2ZW50IGxpc3RlbmVycyB0byB0aGUgaWRlbnRpZmllZCBlbGVtZW50cywgd3JpdGUgdGhlIGRhdGFcbiAgICAgKiB3aGVuIHRoZSBldmVudCBvY2N1cnMsIHdpdGggYSBkZWxheSBvZiAxcyAtIHdlIGNvdWxkIGdhdGhlciBtYW55IGV2ZW50cyB3aXRoaW4gdGhpcyB0aW1lZnJhbWVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB3cml0ZXIgLSBUaGUgd3JpdGVyIHRvIHNlbmQgdGhlIGRhdGEgdG9cbiAgICAgKiBAcGFyYW0ge0xvZ2dlcn0gbG9nIC0gVGhlIGxvZ2dlclxuICAgICAqL1xuICAgIGF0dGFjaCh3cml0ZXIsIGxvZykge1xuICAgICAgICBjb25zdCBmbHVzaCA9IGRlYm91bmNlKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMucXVldWUudHJhbnNhY3Rpb25hbERyYWluKHF1ZXVlID0+IG5ldyBQcm9taXNlKHJlcyA9PiB7XG4gICAgICAgICAgICAgICAgcmVzKHdyaXRlci53cml0ZSh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMudHlwZSxcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogcXVldWVcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICB9KSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyID0+IGxvZy5lcnJvcihcIkNvdWxkIG5vdCBkcmFpbiBxdWV1ZTogXCIsIGVycikpO1xuICAgICAgICB9LCAyNTApO1xuICAgICAgICBjb25zdCBoYW5kbGVyID0gZWxlbWVudCA9PiB7XG4gICAgICAgICAgICBTY3JvbGxNb25pdG9yLmNyZWF0ZShlbGVtZW50KS5lbnRlclZpZXdwb3J0KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnF1ZXVlLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBpZDogdGhpcy5yZXNvbHZlKHRoaXMuaWRSZXNvbHZlciwgbG9nLCBlbGVtZW50KSxcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHRoaXMucmVzb2x2ZSh0aGlzLnBvc2l0aW9uUmVzb2x2ZXIsIGxvZywgZWxlbWVudClcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBmbHVzaCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIG5ldyBTZW50aW5lbCh0aGlzLmdldERvY3VtZW50KCkpLm9uKHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uLCB0aGlzLmxvZ1dyYXBIYW5kbGVyKGhhbmRsZXIsIGxvZykpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IEFic3RyYWN0Q29sbGVjdG9yIH0gZnJvbSBcIi4vQWJzdHJhY3RDb2xsZWN0b3JcIjtcbmltcG9ydCB7IFNlbnRpbmVsIH0gZnJvbSBcIi4uL3V0aWxzL1NlbnRpbmVsXCI7XG5pbXBvcnQgeyBMaXN0ZW5lclR5cGUgfSBmcm9tIFwiLi4vdXRpbHMvTGlzdGVuZXJUeXBlXCI7XG4vKipcbiAqIENvbGxlY3Qgc2VhcmNoIGluZm9ybWF0aW9uIGZyb20gYSBmaWVsZCB0aGF0IGhhcyBhIFwiYXMteW91LXR5cGVcIiB0cmlnZ2VyIGFuZFxuICogcmVuZGVycyBzZWFyY2ggcmVzdWx0cyBpbW1lZGlhdGVseS4gTWF5IHRyaWdnZXIgbXVsdGlwbGUgdGltZXMgZGVwZW5kaW5nIG9uXG4gKiB0eXBlIHNwZWVkIHBhdHRlcm5zIC0gd2UgZXhwZWN0IHRoYXQgdGhlIGludGVydmFsIGJldHdlZW4ga2V5IHN0cm9rZXMgd291bGQgYmVcbiAqIGxlc3MgdGhhbiA1MDBtc1xuICovXG5leHBvcnQgY2xhc3MgSW5zdGFudFNlYXJjaFF1ZXJ5Q29sbGVjdG9yIGV4dGVuZHMgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdCBpbnN0YW50IHNlYXJjaCBjb2xsZWN0b3JcbiAgICAgKlxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvckV4cHJlc3Npb24gLSBEb2N1bWVudCBxdWVyeSBzZWxlY3RvciBpZGVudGlmeWluZyB0aGUgZWxlbWVudHMgdG8gYXR0YWNoIHRvXG4gICAgICogQHBhcmFtIGRlbGF5TXNcbiAgICAgKiBAcGFyYW0gbWluTGVuZ3RoXG4gICAgICogQHBhcmFtIGxpc3RlbmVyVHlwZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlbGVjdG9yRXhwcmVzc2lvbiwgZGVsYXlNcyA9IDUwMCwgbWluTGVuZ3RoID0gMiwgbGlzdGVuZXJUeXBlID0gTGlzdGVuZXJUeXBlLlNlbnRpbmVsKSB7XG4gICAgICAgIHN1cGVyKFwiaW5zdGFudC1zZWFyY2hcIik7XG4gICAgICAgIHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uID0gc2VsZWN0b3JFeHByZXNzaW9uO1xuICAgICAgICB0aGlzLmRlbGF5TXMgPSBkZWxheU1zO1xuICAgICAgICB0aGlzLm1pbkxlbmd0aCA9IG1pbkxlbmd0aDtcbiAgICAgICAgdGhpcy5saXN0ZW5lclR5cGUgPSBsaXN0ZW5lclR5cGU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFkZCBpbXByZXNzaW9uIGV2ZW50IGxpc3RlbmVycyB0byB0aGUgaWRlbnRpZmllZCBlbGVtZW50cywgd3JpdGUgdGhlIGRhdGFcbiAgICAgKiB3aGVuIHRoZSBldmVudCBvY2N1cnNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB3cml0ZXIgLSBUaGUgd3JpdGVyIHRvIHNlbmQgdGhlIGRhdGEgdG9cbiAgICAgKiBAcGFyYW0gbG9nXG4gICAgICovXG4gICAgYXR0YWNoKHdyaXRlciwgbG9nKSB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSB0aGlzLmdldFR5cGUoKTtcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IChlLCBzZWFyY2hCb3gpID0+IHtcbiAgICAgICAgICAgIC8vIElnbm9yZSBzaGlmdCwgY3RybCwgZXRjLiBwcmVzc2VzLCByZWFjdCBvbmx5IG9uIGNoYXJhY3RlcnNcbiAgICAgICAgICAgIGlmIChlLndoaWNoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRGVsYXkgdGhlIHJlYWN0aW9uIG9mIHRoZSBldmVudCwgY2xlYW4gdGhlIHRpbWVvdXQgaWYgdGhlIGV2ZW50IGZpcmVzXG4gICAgICAgICAgICAvLyBhZ2FpbiBhbmQgc3RhcnQgY291bnRpbmcgZnJvbSAwXG4gICAgICAgICAgICBkZWxheSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qga2V5d29yZHMgPSBzZWFyY2hCb3gudmFsdWU7XG4gICAgICAgICAgICAgICAgaWYgKGtleXdvcmRzICYmIGtleXdvcmRzLmxlbmd0aCA+PSB0aGlzLm1pbkxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICB3cml0ZXIud3JpdGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJ0eXBlXCI6IHR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBcImtleXdvcmRzXCI6IGtleXdvcmRzXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIHRoaXMuZGVsYXlNcyk7XG4gICAgICAgIH07XG4gICAgICAgIC8vIFRoZSBTZW50aWVsIGxpYnJhcnkgdXNlcyBhbmltYXRpb25zdGFydCBldmVudCBsaXN0ZW5lcnMgd2hpY2ggbWF5IGludGVyZmVyZSB3aXRoXG4gICAgICAgIC8vIGFuaW1hdGlvbnMgYXR0YWNoZWQgb24gZWxlbWVuZXRzLiBUaGUgaW4tbGlicmFyeSBwcm92aWRlZCB3b3JrYXJvdW5kIG1lY2hhbmlzbSBkb2VzIG5vdCB3b3JrXG4gICAgICAgIC8vIDEwMCUsIHRodXMgd2UgcHJvdmlkZSB0aGUgbGlzdGVuZXJUeXBlIGNob2ljZSBiZWxvdy4gVGhlIHRyYWRlb2Zmc1xuICAgICAgICAvLyBcImRvbVwiIC0gbm8gYW5pbWF0aW9uIGludGVyZmVyZW5jZSwgb25seSBvbmNsaWNrIGF0dGFjaGVkLCBidXQgZG9lcyBub3QgaGFuZGxlIGVsZW1lbnRzIGluc2VydGVkIGluIHRoZSBET00gbGF0ZXJcbiAgICAgICAgLy8gXCJzZW50aW5lbCAoZGVmYXVsdClcIiAtIHdvcmtzIG9uIGVsZW1lbnRzIGluc2VydGVkIGluIHRoZSBET00gYW55dGltZSwgYnV0IGludGVyZmVyZXMgd2l0aCBDU1MgYW5pbWF0aW9ucyBvbiB0aGVzZSBlbGVtZW50c1xuICAgICAgICBpZiAodGhpcy5saXN0ZW5lclR5cGUgPT09IExpc3RlbmVyVHlwZS5Eb20pIHtcbiAgICAgICAgICAgIGNvbnN0IG5vZGVMaXN0ID0gdGhpcy5nZXREb2N1bWVudCgpLnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5zZWxlY3RvckV4cHJlc3Npb24pO1xuICAgICAgICAgICAgbm9kZUxpc3QuZm9yRWFjaChlbCA9PiBlbC5hZGRFdmVudExpc3RlbmVyKFwia2V5dXBcIiwgdGhpcy5sb2dXcmFwSGFuZGxlcihoYW5kbGVyLCBsb2csIGVsKSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbmV3IFNlbnRpbmVsKHRoaXMuZ2V0RG9jdW1lbnQoKSkub24odGhpcy5zZWxlY3RvckV4cHJlc3Npb24sIChlbCkgPT4ge1xuICAgICAgICAgICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoXCJrZXl1cFwiLCB0aGlzLmxvZ1dyYXBIYW5kbGVyKGhhbmRsZXIsIGxvZywgZWwpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxufVxuY29uc3QgZGVsYXkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGxldCB0aW1lcjtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGNhbGxiYWNrLCBtcykge1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQoY2FsbGJhY2ssIG1zKTtcbiAgICB9O1xufSkoKTtcbiIsImltcG9ydCB7IENsaWNrQ29sbGVjdG9yIH0gZnJvbSBcIi4vQ2xpY2tDb2xsZWN0b3JcIjtcbmltcG9ydCB7IExpc3RlbmVyVHlwZSB9IGZyb20gXCIuLi91dGlscy9MaXN0ZW5lclR5cGVcIjtcbi8qKlxuICogQ2xpY2tDb2xsZWN0b3IgZW1pdHRpbmcgXCJwcm9kdWN0XCIgZXZlbnRzLCBhdHRhY2ggdG8gcHJvZHVjdCBsaW5rc1xuICovXG5leHBvcnQgY2xhc3MgUHJvZHVjdENsaWNrQ29sbGVjdG9yIGV4dGVuZHMgQ2xpY2tDb2xsZWN0b3Ige1xuICAgIGNvbnN0cnVjdG9yKHNlbGVjdG9yLCByZXNvbHZlcnMsIGxpc3RlbmVyVHlwZSA9IExpc3RlbmVyVHlwZS5TZW50aW5lbCkge1xuICAgICAgICBzdXBlcihzZWxlY3RvciwgXCJwcm9kdWN0XCIsIGxpc3RlbmVyVHlwZSk7XG4gICAgICAgIHRoaXMuaWRSZXNvbHZlciA9IHJlc29sdmVycy5pZFJlc29sdmVyO1xuICAgICAgICB0aGlzLnBvc2l0aW9uUmVzb2x2ZXIgPSByZXNvbHZlcnMucG9zaXRpb25SZXNvbHZlcjtcbiAgICAgICAgdGhpcy5wcmljZVJlc29sdmVyID0gcmVzb2x2ZXJzLnByaWNlUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMuaW1hZ2VSZXNvbHZlciA9IHJlc29sdmVycy5pbWFnZVJlc29sdmVyO1xuICAgICAgICB0aGlzLm1ldGFkYXRhUmVzb2x2ZXIgPSByZXNvbHZlcnMubWV0YWRhdGFSZXNvbHZlcjtcbiAgICAgICAgdGhpcy50cmFpbCA9IHJlc29sdmVycy50cmFpbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29sbGVjdCB0aGUgcHJvZHVjdCBjbGljayBpbmZvcm1hdGlvbiBmcm9tIHRoZSBlbGVtZW50XG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgY29sbGVjdChlbGVtZW50LCBldmVudCwgbG9nKSB7XG4gICAgICAgIGNvbnN0IGlkID0gdGhpcy5yZXNvbHZlKHRoaXMuaWRSZXNvbHZlciwgbG9nLCBlbGVtZW50LCBldmVudCk7XG4gICAgICAgIGlmIChpZCkge1xuICAgICAgICAgICAgaWYgKHRoaXMudHJhaWwpIHtcbiAgICAgICAgICAgICAgICAvLyBSZWdpc3RlciB0aGF0IHRoaXMgcHJvZHVjdCBqb3VybmV5IGludG8gcG90ZW50aWFsIHB1cmNoYXNlIHN0YXJ0ZWRcbiAgICAgICAgICAgICAgICAvLyB3aXRoIHRoaXMgcXVlcnlcbiAgICAgICAgICAgICAgICB0aGlzLnRyYWlsLnJlZ2lzdGVyKGlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgICAgcG9zaXRpb246IHRoaXMucmVzb2x2ZSh0aGlzLnBvc2l0aW9uUmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpLFxuICAgICAgICAgICAgICAgIHByaWNlOiB0aGlzLnJlc29sdmUodGhpcy5wcmljZVJlc29sdmVyLCBsb2csIGVsZW1lbnQsIGV2ZW50KSxcbiAgICAgICAgICAgICAgICBpbWFnZTogdGhpcy5yZXNvbHZlKHRoaXMuaW1hZ2VSZXNvbHZlciwgbG9nLCBlbGVtZW50LCBldmVudCksXG4gICAgICAgICAgICAgICAgbWV0YWRhdGE6IHRoaXMucmVzb2x2ZSh0aGlzLm1ldGFkYXRhUmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuaW1wb3J0IHsgZ2V0U2Vzc2lvblN0b3JhZ2UgfSBmcm9tIFwiLi4vdXRpbHNcIjtcbmltcG9ydCB7IFF1ZXJ5IH0gZnJvbSBcIi4uL3F1ZXJ5XCI7XG4vKipcbiAqIEtlZXAgdHJhY2sgb2YgaHVtYW4gdHJpZ2dlcmVkIHNlYXJjaGVzIGZvbGxvd2VkIGJ5IGEgcmVkaXJlY3QgdG8gYSBwYWdlIGRpZmZlcmVudCB0aGFuIHRoZSBzZWFyY2ggcmVzdWx0IHBhZ2VcbiAqL1xuZXhwb3J0IGNsYXNzIFJlZGlyZWN0Q29sbGVjdG9yIGV4dGVuZHMgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdCByZWRpcmVjdCBjb2xsZWN0b3JcbiAgICAgKlxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IHRyaWdnZXJSZXNvbHZlciAtIEZ1bmN0aW9uIHRoYXQgZmlyZXMgd2hlbiBhIHNlYXJjaCBoYXBwZW5zLCBzaG91bGQgcmV0dXJuIHRoZSBrZXl3b3JkXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gZXhwZWN0ZWRQYWdlUmVzb2x2ZXIgLSBGdW5jdGlvbiB0aGF0IHNob3VsZCByZXR1cm4gd2hldGhlciB0aGUgcGFnZSB3ZSBsb2FkIGlzIHRoZSBleHBlY3RlZCBvbmVcbiAgICAgKiBAcGFyYW0gY29udGV4dFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRyaWdnZXJSZXNvbHZlciwgZXhwZWN0ZWRQYWdlUmVzb2x2ZXIsIGNvbnRleHQpIHtcbiAgICAgICAgc3VwZXIoXCJyZWRpcmVjdFwiLCBjb250ZXh0KTtcbiAgICAgICAgdGhpcy50cmlnZ2VyUmVzb2x2ZXIgPSB0cmlnZ2VyUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMuZXhwZWN0ZWRQYWdlUmVzb2x2ZXIgPSBleHBlY3RlZFBhZ2VSZXNvbHZlcjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2hlY2sgd2hldGhlciB3ZSBzaG91bGQgYmUgcmVjb3JkaW5nIGEgcmVkaXJlY3QgZXZlbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB3cml0ZXIgLSBUaGUgd3JpdGVyIHRvIHNlbmQgdGhlIGRhdGEgdG9cbiAgICAgKiBAcGFyYW0gbG9nXG4gICAgICovXG4gICAgYXR0YWNoKHdyaXRlciwgbG9nKSB7XG4gICAgICAgIHRoaXMucmVzb2x2ZSh0aGlzLnRyaWdnZXJSZXNvbHZlciwgbG9nLCBrZXl3b3JkID0+IHtcbiAgICAgICAgICAgIGdldFNlc3Npb25TdG9yYWdlKCkuc2V0SXRlbShSZWRpcmVjdENvbGxlY3Rvci5TVE9SQUdFX0tFWSwga2V5d29yZCk7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBGZXRjaCB0aGUgbGF0ZXN0IHNlYXJjaCBpZiBhbnlcbiAgICAgICAgY29uc3QgbGFzdFNlYXJjaCA9IGdldFNlc3Npb25TdG9yYWdlKCkuZ2V0SXRlbShSZWRpcmVjdENvbGxlY3Rvci5TVE9SQUdFX0tFWSk7XG4gICAgICAgIGlmIChsYXN0U2VhcmNoKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIHNlYXJjaCBhY3Rpb24sIGFzIHdlJ3JlIGVpdGhlciBvbiBhIHNlYXJjaCByZXN1bHQgcGFnZSBvciB3ZSd2ZSByZWRpcmVjdGVkXG4gICAgICAgICAgICBnZXRTZXNzaW9uU3RvcmFnZSgpLnJlbW92ZUl0ZW0oUmVkaXJlY3RDb2xsZWN0b3IuU1RPUkFHRV9LRVkpO1xuICAgICAgICAgICAgLy8gSWYgd2UgaGF2ZSBub3QgbGFuZGVkIG9uIHRoZSBleHBlY3RlZCBzZWFyY2ggcGFnZSwgaXQgbXVzdCBoYXZlIGJlZW4gKGxvb292ZSkgYSByZWRpcmVjdFxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlc29sdmUodGhpcy5leHBlY3RlZFBhZ2VSZXNvbHZlciwgbG9nKSkge1xuICAgICAgICAgICAgICAgIC8vIFRodXMgcmVjb3JkIHRoZSByZWRpcmVjdFxuICAgICAgICAgICAgICAgIGNvbnN0IHF1ZXJ5ID0gbmV3IFF1ZXJ5KCk7XG4gICAgICAgICAgICAgICAgcXVlcnkuc2V0U2VhcmNoKGxhc3RTZWFyY2gpO1xuICAgICAgICAgICAgICAgIHdyaXRlci53cml0ZSh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IFwicmVkaXJlY3RcIixcbiAgICAgICAgICAgICAgICAgICAga2V5d29yZHM6IGxhc3RTZWFyY2gsXG4gICAgICAgICAgICAgICAgICAgIHF1ZXJ5OiBxdWVyeS50b1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICB1cmw6IHdpbmRvdy5sb2NhdGlvbi5ocmVmXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5SZWRpcmVjdENvbGxlY3Rvci5TVE9SQUdFX0tFWSA9IFwiX19sYXN0U2VhcmNoXCI7XG4iLCJpbXBvcnQgeyBBYnN0cmFjdENvbGxlY3RvciB9IGZyb20gXCIuL0Fic3RyYWN0Q29sbGVjdG9yXCI7XG4vKipcbiAqIENvbGxlY3QgdGhlIGJhc2ljIHNlYXJjaCBpbmZvcm1hdGlvbiAtIHRoZSBrZXl3b3JkcyB1c2VkIGZvciB0aGUgc2VhcmNoIGFuZFxuICogdGhlIG51bWJlciBvZiByZXN1bHRzLiBTeW5jaHJvbm91cyBpLmUuIHRoZSB3cml0aW5nIGhhcHBlbnMgZGlyZWN0bHkgd2hlbiBhIHdyaXRlciBpcyBhdHRhY2hlZC5cbiAqIFNlZSB0aGUgb3RoZXIgc2VhcmNoIGNvbGxlY3RvcnMgZm9yIGR5bmFtaWMgb25lcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFNlYXJjaFJlc3VsdENvbGxlY3RvciBleHRlbmRzIEFic3RyYWN0Q29sbGVjdG9yIHtcbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3Qgc2VhcmNoIHJlc3VsdCBjb2xsZWN0b3JcbiAgICAgKlxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IHBocmFzZVJlc29sdmVyIC0gRnVuY3Rpb24gdGhhdCBzaG91bGQgcmV0dXJuIHRoZSBzZWFyY2ggcGhyYXNlIHVzZWQgZm9yIHRoZSBzZWFyY2hcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjb3VudFJlc29sdmVyIC0gRnVuY3Rpb24gdGhhdCBzaG91bGQgcmV0dXJuIHRoZSBudW1uYmVyIG9mIHJlc3VsdHMgaW4gdGhlIHNlYXJjaFxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGFjdGlvblJlc29sdmVyIC0gQSBzZWFyY2ggcmVzdWx0IG1heSBiZSByZWZpbmVkIG9yIGEgY2xpZW50IG1heSBicm93c2UgMiwzLDQgcGFnZS5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHNob3VsZCBwcm92aWRlIGEgdGV4dCByZXByZXNhbnRpb24gb2YgdGhlIGFjdGlvblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHBocmFzZVJlc29sdmVyLCBjb3VudFJlc29sdmVyLCBhY3Rpb25SZXNvbHZlcikge1xuICAgICAgICBzdXBlcihcInNlYXJjaFwiKTtcbiAgICAgICAgdGhpcy5waHJhc2VSZXNvbHZlciA9IHBocmFzZVJlc29sdmVyO1xuICAgICAgICB0aGlzLmNvdW50UmVzb2x2ZXIgPSBjb3VudFJlc29sdmVyO1xuICAgICAgICB0aGlzLmFjdGlvblJlc29sdmVyID0gYWN0aW9uUmVzb2x2ZXI7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEF0dGFjaCBhIHdyaXRlciwgbm90ZSB0aGF0IHRoaXMgY29sbGVjdG9yIGlzIG5vdCBhc3luY2hyb25vdXMgYW5kIHdpbGwgd3JpdGVcbiAgICAgKiB0aGUgZGF0YSBpbW1lZGlhdGVsbHlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB3cml0ZXIgLSBUaGUgd3JpdGVyIHRvIHNlbmQgdGhlIGRhdGEgdG9cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gbG9nIC0gVGhlIGxvZ2dlclxuICAgICAqL1xuICAgIGF0dGFjaCh3cml0ZXIsIGxvZykge1xuICAgICAgICB3cml0ZXIud3JpdGUoe1xuICAgICAgICAgICAgdHlwZTogXCJzZWFyY2hcIixcbiAgICAgICAgICAgIGtleXdvcmRzOiB0aGlzLnJlc29sdmUodGhpcy5waHJhc2VSZXNvbHZlciwgbG9nLCB7fSksXG4gICAgICAgICAgICBjb3VudDogdGhpcy5yZXNvbHZlKHRoaXMuY291bnRSZXNvbHZlciwgbG9nLCB7fSksXG4gICAgICAgICAgICBhY3Rpb246IHRoaXMucmVzb2x2ZSh0aGlzLmFjdGlvblJlc29sdmVyLCBsb2csIHt9KSB8fCBcInNlYXJjaFwiXG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IFdyaXRlclJlc29sdmVyQ29sbGVjdG9yIH0gZnJvbSBcIi4vV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3JcIjtcbi8qKlxuICogQ29sbGVjdCBzdWdnZXN0IHNlYXJjaCBpbmZvcm1hdGlvbiAtIGtleXdvcmQgc2VhcmNoZXMgY29taW5nIGZyb20gYSBzdWdnZXN0aW9uIHdpZGdldC9mdW5jdGlvbmFsaXR5XG4gKi9cbmV4cG9ydCBjbGFzcyBTdWdnZXN0U2VhcmNoQ29sbGVjdG9yIGV4dGVuZHMgV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3Ige1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdCBzdWdnZXN0IHNlYXJjaCBjb2xsZWN0b3JcbiAgICAgKlxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IHJlc29sdmVyIC0gRnVuY3Rpb24gdGhhdCB0cmlnZ2VycyB0aGUgd3JpdGluZy4gU3VnZ2VzdCBtaWdodCBiZSBjb21wbGV4LCBsZWF2ZSB0byB0aGUgaW1wbGVtZW50YXRpb24gdG8gZGV0ZXJtaW5lIHdoZW4vaG93XG4gICAgICovXG4gICAgY29uc3RydWN0b3IocmVzb2x2ZXIpIHtcbiAgICAgICAgc3VwZXIoXCJzdWdnZXN0LXNlYXJjaFwiLCByZXNvbHZlcik7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuLyoqXG4gKiBSZXNvbHZlcyBpbW1lZGlhdGVseSBhbmQgcGFzc2luZyB0aGUgd3JpdGVyLCB0aGUgdHlwZSBvZiB0aGUgZXZlbnQgKyBjb250ZXh0IHRvIHRoZSBwcm92aWRlZCByZXNvbHZlciBmdW5jdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIFdyaXRlclJlc29sdmVyQ29sbGVjdG9yIGV4dGVuZHMgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIGNvbnN0cnVjdG9yKHR5cGUsIHJlc29sdmVyKSB7XG4gICAgICAgIHN1cGVyKHR5cGUpO1xuICAgICAgICB0aGlzLnJlc29sdmVyID0gcmVzb2x2ZXI7XG4gICAgfVxuICAgIGF0dGFjaCh3cml0ZXIsIGxvZykge1xuICAgICAgICB0aGlzLnJlc29sdmUodGhpcy5yZXNvbHZlciwgbG9nLCB3cml0ZXIsIHRoaXMuZ2V0VHlwZSgpLCB0aGlzLmdldENvbnRleHQoKSk7XG4gICAgfVxufVxuIiwiZXhwb3J0ICogZnJvbSBcIi4vQWJzdHJhY3RDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0Fzc29jaWF0ZWRQcm9kdWN0Q29sbGVjdG9yXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9CYXNrZXRDbGlja0NvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vQnJvd3NlckNvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vQ2hlY2tvdXRDbGlja0NvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vQ2xpY2tDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0NsaWNrV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0ZpbHRlckNsaWNrQ29sbGVjdG9yXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9GaXJlZFNlYXJjaENvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vR2VuZXJpY0V2ZW50Q29sbGVjdG9yXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9JbXByZXNzaW9uQ29sbGVjdG9yXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9JbnN0YW50U2VhcmNoUXVlcnlDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1Byb2R1Y3RDbGlja0NvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vUmVkaXJlY3RDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1NlYXJjaFJlc3VsdENvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vU3VnZ2VzdFNlYXJjaENvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3JcIjtcbiIsImV4cG9ydCB7fTtcbiIsImV4cG9ydCB7fTtcbiIsIi8qKlxuICogUGFzc2VzIGFsbCBsb2cgbWVzc2FnZXMgdG8gdGhlIHByb3ZpZGVkIHRyYW5zcG9ydHNcbiAqL1xuZXhwb3J0IGNsYXNzIFRyYW5zcG9ydExvZ2dlciB7XG4gICAgY29uc3RydWN0b3IodHJhbnNwb3J0cywgaXNEZWJ1Z0VuYWJsZWQgPSBmYWxzZSkge1xuICAgICAgICB0aGlzLnRyYW5zcG9ydHMgPSB0cmFuc3BvcnRzO1xuICAgICAgICB0aGlzLmlzRGVidWdFbmFibGVkID0gaXNEZWJ1Z0VuYWJsZWQ7XG4gICAgfVxuICAgIGRlYnVnKG1zZywgLi4uZGF0YUFyZ3MpIHtcbiAgICAgICAgdGhpcy50cmFuc3BvcnRzLmZvckVhY2godHJhbnNwb3J0ID0+IHRoaXMuY2FsbFRyYW5zcG9ydCh0cmFuc3BvcnQsIFwiZGVidWdcIiwgbXNnLCAuLi5kYXRhQXJncykpO1xuICAgIH1cbiAgICBlcnJvcihtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIHRoaXMudHJhbnNwb3J0cy5mb3JFYWNoKHRyYW5zcG9ydCA9PiB0aGlzLmNhbGxUcmFuc3BvcnQodHJhbnNwb3J0LCBcImVycm9yXCIsIG1zZywgLi4uZGF0YUFyZ3MpKTtcbiAgICB9XG4gICAgaW5mbyhtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIHRoaXMudHJhbnNwb3J0cy5mb3JFYWNoKHRyYW5zcG9ydCA9PiB0aGlzLmNhbGxUcmFuc3BvcnQodHJhbnNwb3J0LCBcImluZm9cIiwgbXNnLCAuLi5kYXRhQXJncykpO1xuICAgIH1cbiAgICB3YXJuKG1zZywgLi4uZGF0YUFyZ3MpIHtcbiAgICAgICAgdGhpcy50cmFuc3BvcnRzLmZvckVhY2godHJhbnNwb3J0ID0+IHRoaXMuY2FsbFRyYW5zcG9ydCh0cmFuc3BvcnQsIFwid2FyblwiLCBtc2csIC4uLmRhdGFBcmdzKSk7XG4gICAgfVxuICAgIGNhbGxUcmFuc3BvcnQodHJhbnNwb3J0LCBsZXZlbCwgbXNnLCAuLi5kYXRhQXJncykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydFtsZXZlbF0gJiYgdHlwZW9mIHRyYW5zcG9ydFtsZXZlbF0gPT09IFwiZnVuY3Rpb25cIilcbiAgICAgICAgICAgICAgICB0cmFuc3BvcnRbbGV2ZWxdKG1zZywgLi4uZGF0YUFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0RlYnVnRW5hYmxlZClcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiQ291bGQgbm90IGNhbGwgdHJhbnNwb3J0OiBcIiwgZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9Mb2dnZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0xvZ2dlclRyYW5zcG9ydFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vVHJhbnNwb3J0TG9nZ2VyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi90cmFuc3BvcnRcIjtcbiIsImV4cG9ydCBjbGFzcyBDb25zb2xlVHJhbnNwb3J0IHtcbiAgICBkZWJ1Zyhtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIGNvbnNvbGUuZGVidWcobXNnLCAuLi5kYXRhQXJncyk7XG4gICAgfVxuICAgIDtcbiAgICBpbmZvKG1zZywgLi4uZGF0YUFyZ3MpIHtcbiAgICAgICAgY29uc29sZS5pbmZvKG1zZywgLi4uZGF0YUFyZ3MpO1xuICAgIH1cbiAgICA7XG4gICAgd2Fybihtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIGNvbnNvbGUud2Fybihtc2csIC4uLmRhdGFBcmdzKTtcbiAgICB9XG4gICAgO1xuICAgIGVycm9yKG1zZywgLi4uZGF0YUFyZ3MpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihtc2csIC4uLmRhdGFBcmdzKTtcbiAgICB9XG4gICAgO1xufVxuIiwiaW1wb3J0IHsgYmFzZTY0RW5jb2RlIH0gZnJvbSBcIi4uLy4uL3V0aWxzXCI7XG4vKipcbiAqIE9ubHkgYWRkcyBlcnJvciBtZXNzYWdlcyB0byBhbiBzcXMgcXVldWVcbiAqL1xuZXhwb3J0IGNsYXNzIFNRU0Vycm9yVHJhbnNwb3J0IHtcbiAgICBjb25zdHJ1Y3RvcihxdWV1ZSwgY2hhbm5lbCwgc2Vzc2lvblJlc29sdmVyLCBmaWZvID0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy5xdWV1ZSA9IHF1ZXVlO1xuICAgICAgICB0aGlzLmNoYW5uZWwgPSBjaGFubmVsO1xuICAgICAgICB0aGlzLnNlc3Npb25SZXNvbHZlciA9IHNlc3Npb25SZXNvbHZlcjtcbiAgICAgICAgdGhpcy5maWZvID0gZmlmbztcbiAgICB9XG4gICAgc2VuZChkYXRhKSB7XG4gICAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpO1xuICAgICAgICBsZXQgc3JjID0gdGhpcy5xdWV1ZSArIFwiP1ZlcnNpb249MjAxMi0xMS0wNSZBY3Rpb249U2VuZE1lc3NhZ2VcIjtcbiAgICAgICAgLy8gU1FTIHN1cHBvcnRzIEZJRk8gcXVldWVzIGluIHNvbWUgcmVnaW9ucyB0aGF0IGNhbiBhbHNvIGd1YXJhbnRlZSB0aGUgb3JkZXJcbiAgICAgICAgLy8gb2YgdGhlIG1lc3NhZ2VzLlxuICAgICAgICBpZiAodGhpcy5maWZvKSB7XG4gICAgICAgICAgICAvLyBUT0RPIHdoZW4gZW5vdWdoIGluZm9ybWF0aW9uIGlzIHByZXNlbnQgdG8gdW5pcXVlbHkgaWRlbnRpZnkgYSBtZXNzYWdlLCBzd2l0Y2ggdGhlIGRlZHVwbGljYXRpb24gaWQgdG8gYSBtZXNzYWdlIGhhc2hcbiAgICAgICAgICAgIHNyYyArPSBcIiZNZXNzYWdlR3JvdXBJZD0xJk1lc3NhZ2VEZWR1cGxpY2F0aW9uSWQ9XCIgKyBNYXRoLnJhbmRvbSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShkYXRhKSAmJiB0eXBlb2YgZGF0YSAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgZGF0YSA9IFtkYXRhXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGRhdGEgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIGRhdGEgPSBKU09OLnN0cmluZ2lmeShkYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBzcmMgKz0gXCImTWVzc2FnZUJvZHk9XCIgKyBiYXNlNjRFbmNvZGUoZW5jb2RlVVJJQ29tcG9uZW50KGRhdGEpKTtcbiAgICAgICAgaW1nLnNyYyA9IHNyYztcbiAgICB9XG4gICAgZXJyb3IobXNnLCAuLi5kYXRhQXJncykge1xuICAgICAgICB0aGlzLnNlbmQoe1xuICAgICAgICAgICAgdHlwZTogXCJlcnJvclwiLFxuICAgICAgICAgICAgbXNnLFxuICAgICAgICAgICAgY2hhbm5lbDogdGhpcy5jaGFubmVsLFxuICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uUmVzb2x2ZXIoKSxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS5nZXRUaW1lKCksXG4gICAgICAgICAgICAuLi5kYXRhQXJnc1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgO1xufVxuIiwiaW1wb3J0IHsgU1FTRXJyb3JUcmFuc3BvcnQgfSBmcm9tIFwiLi9TUVNFcnJvclRyYW5zcG9ydFwiO1xuLyoqXG4gKiBBZGRzIGFsbCBsb2cgbGV2ZWxzIHRvIGFuIFNRUyBxdWV1ZVxuICovXG5leHBvcnQgY2xhc3MgU1FTVHJhbnNwb3J0IGV4dGVuZHMgU1FTRXJyb3JUcmFuc3BvcnQge1xuICAgIGRlYnVnKG1zZywgLi4uZGF0YUFyZ3MpIHtcbiAgICAgICAgdGhpcy5zZW5kKHtcbiAgICAgICAgICAgIHR5cGU6IFwiZGVidWdcIixcbiAgICAgICAgICAgIG1zZyxcbiAgICAgICAgICAgIC4uLmRhdGFBcmdzXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICA7XG4gICAgaW5mbyhtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIHRoaXMuc2VuZCh7XG4gICAgICAgICAgICB0eXBlOiBcImluZm9cIixcbiAgICAgICAgICAgIG1zZyxcbiAgICAgICAgICAgIC4uLmRhdGFBcmdzXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICA7XG4gICAgd2Fybihtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIHRoaXMuc2VuZCh7XG4gICAgICAgICAgICB0eXBlOiBcIndhcm5pbmdcIixcbiAgICAgICAgICAgIG1zZyxcbiAgICAgICAgICAgIC4uLmRhdGFBcmdzXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICA7XG59XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9Db25zb2xlVHJhbnNwb3J0XCI7XG5leHBvcnQgKiBmcm9tIFwiLi9TUVNFcnJvclRyYW5zcG9ydFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vU1FTVHJhbnNwb3J0XCI7XG4iLCJleHBvcnQgY2xhc3MgUXVlcnkge1xuICAgIGNvbnN0cnVjdG9yKHF1ZXJ5U3RyaW5nKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZW1vdmUgYWxsIHNlbGVjdGlvbnMgb24gdGhpcyBmaWVsZFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5yZW1vdmVTZWxlY3Rpb25BdCA9IGZ1bmN0aW9uIChwb3MpIHtcbiAgICAgICAgICAgIGFycmF5UmVtb3ZlKHRoaXMuY3JpdGVyaWEsIHBvcywgcG9zKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jcml0ZXJpYSA9IFtdO1xuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgIGlmIChxdWVyeVN0cmluZykge1xuICAgICAgICAgICAgdmFyIGNyaXRlcmlhID0gW107XG4gICAgICAgICAgICB2YXIgYW5kcyA9IHF1ZXJ5U3RyaW5nLnNwbGl0KFwiL1wiKTtcbiAgICAgICAgICAgIGFuZHMuZm9yRWFjaChmdW5jdGlvbiAoYW5kKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFuZC5pbmRleE9mKFwifFwiKSAhPSAtMSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgb3JzID0gYW5kLnNwbGl0KFwifFwiKTtcbiAgICAgICAgICAgICAgICAgICAgb3JzLmZvckVhY2goZnVuY3Rpb24gKG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjcml0ZXJpYS5wdXNoKHsgXCJzZWxlY3Rpb25cIjogb3IsIFwidHlwZVwiOiBcIm9yXCIgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY3JpdGVyaWEucHVzaCh7IFwic2VsZWN0aW9uXCI6IGFuZCwgXCJ0eXBlXCI6IFwiYW5kXCIgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjcml0ZXJpYS5mb3JFYWNoKGZ1bmN0aW9uIChjcml0ZXJpb24pIHtcbiAgICAgICAgICAgICAgICB2YXIgYyA9IHVuZXNjYXBlKGNyaXRlcmlvbi5zZWxlY3Rpb24pO1xuICAgICAgICAgICAgICAgIGlmIChjLmluZGV4T2YoXCI9XCIpICE9IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZVNwbGl0ID0gYy5zcGxpdChcIj1cIik7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuY3JpdGVyaWEucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBcImZpZWxkXCI6IHZhbHVlU3BsaXRbMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICBcIm9wZXJhdGlvblwiOiBcIj1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwidmFsdWVcIjogdmFsdWVTcGxpdFsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiYWdncmVnYXRpb25cIjogY3JpdGVyaW9uLnR5cGVcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGMuaW5kZXhPZihcIjxcIikgIT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlU3BsaXQgPSBjLnNwbGl0KFwiPFwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKDIgPT0gdmFsdWVTcGxpdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuY3JpdGVyaWEucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJmaWVsZFwiOiB2YWx1ZVNwbGl0WzBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwib3BlcmF0aW9uXCI6IFwiPFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidmFsdWVcIjogdmFsdWVTcGxpdFsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImFnZ3JlZ2F0aW9uXCI6IGNyaXRlcmlvbi50eXBlXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICgzID09IHZhbHVlU3BsaXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNyaXRlcmlhLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZmllbGRcIjogdmFsdWVTcGxpdFsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIm9wZXJhdGlvblwiOiBcIj48XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJsb3dlclZhbHVlXCI6IHZhbHVlU3BsaXRbMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ1cHBlclZhbHVlXCI6IHZhbHVlU3BsaXRbMl0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJhZ2dyZWdhdGlvblwiOiBjcml0ZXJpb24udHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoYy5pbmRleE9mKFwiPlwiKSAhPSAtMSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVTcGxpdCA9IGMuc3BsaXQoXCI+XCIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoMiA9PSB2YWx1ZVNwbGl0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jcml0ZXJpYS5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImZpZWxkXCI6IHZhbHVlU3BsaXRbMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJvcGVyYXRpb25cIjogXCI+XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ2YWx1ZVwiOiB2YWx1ZVNwbGl0WzFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYWdncmVnYXRpb25cIjogY3JpdGVyaW9uLnR5cGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKDMgPT0gdmFsdWVTcGxpdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuY3JpdGVyaWEucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJmaWVsZFwiOiB2YWx1ZVNwbGl0WzFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwib3BlcmF0aW9uXCI6IFwiPjxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImxvd2VyVmFsdWVcIjogdmFsdWVTcGxpdFsyXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInVwcGVyVmFsdWVcIjogdmFsdWVTcGxpdFsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImFnZ3JlZ2F0aW9uXCI6IGNyaXRlcmlvbi50eXBlXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFB1dCBiYWNrIHRvIHN0cmluZyB0aGUgcXVlcnkgb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBhIHN0cmluZyBpbiB0aGUgZm9ybSBvZiAvYnJhbmQ9ZGVidXQvcHJpY2U+MTAwL1xuICAgICAqL1xuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gXCJcIjtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNyaXRlcmlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY3JpdGVyaW9uID0gdGhpcy5jcml0ZXJpYVtpXTtcbiAgICAgICAgICAgIHZhciBzZXBhcmF0b3IgPSBcIi9cIjtcbiAgICAgICAgICAgIGlmIChcIm9yXCIgPT0gY3JpdGVyaW9uLmFnZ3JlZ2F0aW9uKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5leHQgPSB0aGlzLmNyaXRlcmlhW2kgKyAxXTtcbiAgICAgICAgICAgICAgICBpZiAobmV4dCAmJiBcIm9yXCIgPT0gbmV4dC5hZ2dyZWdhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBcInxcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY3JpdGVyaW9uLm9wZXJhdGlvbiA9PSBcIj48XCIpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gY3JpdGVyaW9uLmxvd2VyVmFsdWUgKyBcIjxcIiArIGNyaXRlcmlvbi5maWVsZCArIFwiPFwiICsgY3JpdGVyaW9uLnVwcGVyVmFsdWUgKyBzZXBhcmF0b3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gY3JpdGVyaW9uLmZpZWxkICsgY3JpdGVyaW9uLm9wZXJhdGlvbiArIGNyaXRlcmlvbi52YWx1ZSArIHNlcGFyYXRvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBZGQgYSBzZWxlY3Rpb24gdG8gdGhpcyBxdWVyeS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBmaWVsZCB0aGUgbmFtZSBvZiB0aGUgZmllbGQgd2UncmUgZHJpbGxpbmcgZG93biB3aXRoXG4gICAgICogQHBhcmFtIG9wZXJhdGlvbiB0aGUgb3BlcmF0aW9uLCBleCA9LD4sPFxuICAgICAqIEBwYXJhbSB2YWx1ZSB0aGUgdmFsdWUgZm9yIHRoZSBvcGVyYXRpb25cbiAgICAgKiBAcGFyYW0gdmFsdWUxIG9wdGlvbmFsIHNlY29uZCB2YWx1ZSBmb3IgY29uc3RydWN0aW5nIHJhbmdlcyBsaWtlIDEwMDxwcmljZTwyMDBcbiAgICAgKi9cbiAgICBhZGRTZWxlY3Rpb24oZmllbGQsIG9wZXJhdGlvbiwgdmFsdWUsIHZhbHVlMSwgYWdncmVnYXRpb24pIHtcbiAgICAgICAgY29uc3QgYWdnID0gYWdncmVnYXRpb24gPyBhZ2dyZWdhdGlvbiA6IFwiYW5kXCI7XG4gICAgICAgIGlmICh2YWx1ZTEgJiYgXCI+PFwiID09IG9wZXJhdGlvbikge1xuICAgICAgICAgICAgdGhpcy5jcml0ZXJpYS5wdXNoKHtcbiAgICAgICAgICAgICAgICBcImZpZWxkXCI6IGZpZWxkLFxuICAgICAgICAgICAgICAgIFwib3BlcmF0aW9uXCI6IFwiPjxcIixcbiAgICAgICAgICAgICAgICBcImxvd2VyVmFsdWVcIjogdmFsdWUsXG4gICAgICAgICAgICAgICAgXCJ1cHBlclZhbHVlXCI6IHZhbHVlMSxcbiAgICAgICAgICAgICAgICBcImFnZ3JlZ2F0aW9uXCI6IGFnZ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmNyaXRlcmlhLnB1c2goe1xuICAgICAgICAgICAgICAgIFwiZmllbGRcIjogZmllbGQsXG4gICAgICAgICAgICAgICAgXCJvcGVyYXRpb25cIjogb3BlcmF0aW9uLFxuICAgICAgICAgICAgICAgIFwidmFsdWVcIjogdmFsdWUsXG4gICAgICAgICAgICAgICAgXCJhZ2dyZWdhdGlvblwiOiBhZ2dcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFBhcnNlIGFuZCBjb25zdHJ1Y3QgYSBuZXcgb2JqZWN0IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBxdWVyeSBzdHJpbmcgZm9ybVxuICAgICAqXG4gICAgICogQHBhcmFtIHF1ZXJ5U3RyaW5nIHRoZSBxdWVyeSBzdHJpbmcgaW4gdGhlIGZvcm0gb2YgXCIvXCIgam9pbmVkIGNyaXRlcmlhLiBleC4gL2JyYW5kPWRlYnV0L3ByaWNlPjEwMC9cbiAgICAgKiBAcmV0dXJuc1xuICAgICAqL1xuICAgIGdldFNlbGVjdGlvbnMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNyaXRlcmlhO1xuICAgIH1cbiAgICBnZXRTZWxlY3Rpb24oZmllbGQpIHtcbiAgICAgICAgZm9yICh2YXIgYyBpbiB0aGlzLmNyaXRlcmlhKSB7XG4gICAgICAgICAgICB2YXIgY3JpdCA9IHRoaXMuY3JpdGVyaWFbY107XG4gICAgICAgICAgICBpZiAoY3JpdC5maWVsZCA9PSBmaWVsZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjcml0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHRoaXMgcXVlcnkgYWxyZWFkeSBoYXMgYSBzZWxlY3Rpb24gZm9yIHRoZSBnaXZlbiBmaWVsZFxuICAgICAqXG4gICAgICogQHJldHVybnMgdHJ1ZSBpZiB3ZSBoYXZlIGEgc2VsZWN0aW9uIG9mIHRoaXMgZmllbGQsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIGhhc1NlbGVjdGlvbihmaWVsZCkge1xuICAgICAgICBmb3IgKHZhciBjIGluIHRoaXMuY3JpdGVyaWEpIHtcbiAgICAgICAgICAgIHZhciBjcml0ID0gdGhpcy5jcml0ZXJpYVtjXTtcbiAgICAgICAgICAgIGlmIChjcml0LmZpZWxkID09IGZpZWxkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGlzIHF1ZXJ5IGFscmVhZHkgaGFzIGEgc2VsZWN0aW9uIGZvciB0aGUgZ2l2ZW4gZmllbGRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHRydWUgaWYgd2UgaGF2ZSBhIHNlbGVjdGlvbiBvZiB0aGlzIGZpZWxkLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBoYXNFeGFjdFNlbGVjdGlvbihmaWVsZCkge1xuICAgICAgICBmb3IgKHZhciBjIGluIHRoaXMuY3JpdGVyaWEpIHtcbiAgICAgICAgICAgIHZhciBjcml0ID0gdGhpcy5jcml0ZXJpYVtjXTtcbiAgICAgICAgICAgIGlmIChjcml0LmZpZWxkID09IGZpZWxkICYmIGNyaXQub3BlcmF0aW9uID09IFwiPVwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYWxsIHNlbGVjdGlvbnMgb24gdGhpcyBmaWVsZFxuICAgICAqL1xuICAgIHJlbW92ZVNlbGVjdGlvbihmaWVsZCkge1xuICAgICAgICB2YXIgY3JpdGVyaWEgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNyaXRlcmlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY3JpdCA9IHRoaXMuY3JpdGVyaWFbaV07XG4gICAgICAgICAgICBpZiAoY3JpdC5maWVsZCA9PSBmaWVsZCkge1xuICAgICAgICAgICAgICAgIGNyaXRlcmlhLnB1c2goaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKGNyaXRlcmlhLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHZhciBjID0gY3JpdGVyaWEucG9wKCk7XG4gICAgICAgICAgICBhcnJheVJlbW92ZSh0aGlzLmNyaXRlcmlhLCBjLCBjKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY3JpdGVyaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBjdXJyZW50ID0gdGhpcy5jcml0ZXJpYVtpXTtcbiAgICAgICAgICAgIHZhciBwcmV2aW91cyA9IHRoaXMuY3JpdGVyaWFbaSAtIDFdO1xuICAgICAgICAgICAgdmFyIG5leHQgPSB0aGlzLmNyaXRlcmlhW2kgKyAxXTtcbiAgICAgICAgICAgIGlmIChcIm9yXCIgPT0gY3VycmVudC5hZ2dyZWdhdGlvbikge1xuICAgICAgICAgICAgICAgIGlmICgoIW5leHQgfHwgXCJhbmRcIiA9PSBuZXh0LmFnZ3JlZ2F0aW9uKSAmJiAoIXByZXZpb3VzIHx8IFwiYW5kXCIgPT0gcHJldmlvdXMuYWdncmVnYXRpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuYWdncmVnYXRpb24gPSBcImFuZFwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBzZXRTZWFyY2godGVybSkge1xuICAgICAgICBpZiAodGVybSkge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVTZWxlY3Rpb24oXCIkc1wiKTtcbiAgICAgICAgICAgIHRoaXMuY3JpdGVyaWEudW5zaGlmdCh7XG4gICAgICAgICAgICAgICAgXCJmaWVsZFwiOiBcIiRzXCIsXG4gICAgICAgICAgICAgICAgXCJvcGVyYXRpb25cIjogXCI9XCIsXG4gICAgICAgICAgICAgICAgXCJ2YWx1ZVwiOiB0ZXJtXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXRTZWFyY2goKSB7XG4gICAgICAgIGNvbnN0IHMgPSB0aGlzLmdldFNlbGVjdGlvbihcIiRzXCIpO1xuICAgICAgICByZXR1cm4gcyA/IHMudmFsdWUgOiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGlzVmFsaWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNyaXRlcmlhLmxlbmd0aCA+IDA7XG4gICAgfVxufVxuLyoqXG4gKiBXZSBoYXZlIHRoZSBzYW1lIGZ1bmN0aW9uIGluIHV0aWwgYnV0IHdlIHdhbnQgdG8gaGF2ZSBxdWVyeS5qcyB3aXRob3V0IGFueSBkZXBlbmRlbmNpZXNcbiAqXG4gKiBAcGFyYW0gYXJyYXlcbiAqIEBwYXJhbSBmcm9tXG4gKiBAcGFyYW0gdG9cbiAqIEByZXR1cm5zIHtOdW1iZXJ8Kn1cbiAqL1xuZnVuY3Rpb24gYXJyYXlSZW1vdmUoYXJyYXksIGZyb20sIHRvKSB7XG4gICAgdmFyIHJlc3QgPSBhcnJheS5zbGljZSgodG8gfHwgZnJvbSkgKyAxIHx8IGFycmF5Lmxlbmd0aCk7XG4gICAgYXJyYXkubGVuZ3RoID0gZnJvbSA8IDAgPyBhcnJheS5sZW5ndGggKyBmcm9tIDogZnJvbTtcbiAgICByZXR1cm4gYXJyYXkucHVzaC5hcHBseShhcnJheSwgcmVzdCk7XG59XG4iLCJpbXBvcnQgeyBnZXRMb2NhbFN0b3JhZ2UsIGdldFNlc3Npb25TdG9yYWdlIH0gZnJvbSBcIi4uL3V0aWxzL1V0aWxcIjtcbmltcG9ydCB7IFRyYWlsVHlwZSB9IGZyb20gXCIuL1RyYWlsVHlwZVwiO1xuY29uc3QgVFRMID0gMTAwMCAqIDYwICogNjAgKiAyNCAqIDI7XG5leHBvcnQgY2xhc3MgVHJhaWwge1xuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHF1ZXJ5UmVzb2x2ZXJcbiAgICAgKiBAcGFyYW0gc2Vzc2lvblJlc29sdmVyXG4gICAgICogQHBhcmFtIHVpZCB0aGUgdW5pcXVlIGlkIG9mIHRoaXMgdHJhaWwuIFVzZWQgYXMgcGFydCBvZiB0aGUga2V5IHRvIHNhdmUgYWxsIFRyYWlsIHN0ZXBzL3BhcnRzXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocXVlcnlSZXNvbHZlciwgc2Vzc2lvblJlc29sdmVyLCB1aWQpIHtcbiAgICAgICAgdGhpcy5xdWVyeVJlc29sdmVyID0gcXVlcnlSZXNvbHZlcjtcbiAgICAgICAgdGhpcy5zZXNzaW9uUmVzb2x2ZXIgPSBzZXNzaW9uUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMua2V5ID0gXCJzZWFyY2gtY29sbGVjdG9yLXRyYWlsXCIgKyAodWlkID8gXCItXCIgKyB1aWQgOiBcIlwiKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsVHJhaWxzID0gdGhpcy5fbG9hZChnZXRMb2NhbFN0b3JhZ2UoKSk7XG4gICAgICAgICAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgICAgIC8vIERyb3AgYWxsIGV4cGlyZWQgdHJhaWxzLCBUVEwgaW4gc3luYyB3aXRoIHNlc3Npb24gZHVyYXRpb24gb2YgMzAgbWluXG4gICAgICAgICAgICBmb3IgKGxldCBpZCBvZiBPYmplY3Qua2V5cyhsb2NhbFRyYWlscykpIHtcbiAgICAgICAgICAgICAgICBpZiAobm93ID4gbG9jYWxUcmFpbHNbaWRdLnRpbWVzdGFtcCArIFRUTCkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgbG9jYWxUcmFpbHNbaWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3NhdmUoZ2V0TG9jYWxTdG9yYWdlKCksIGxvY2FsVHJhaWxzKTtcbiAgICAgICAgICAgIC8vIExvYWQgZXhpc3Rpbmcgc2Vzc2lvbiB0cmFpbHMgYW5kIG1lcmdlIGl0IHdpdGggdGhlIGxvY2FsIHN0b3JhZ2UgdHJhaWxzLlxuICAgICAgICAgICAgLy8gVGhpcyBzaG91bGQgZ3VhcmFudGVlIHRoYXQgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIHRoZSBwYWdlcyBmdXJ0aGVyIGRvd24gdGhlIHRyYWlsXG4gICAgICAgICAgICAvLyAoYmFza2V0LCBjaGVja291dCkgd2VyZSBvcGVuIGluIGEgbmV3IHRhYiBvciBub3QsIHdlIGhhdmUgYSBmdWxsIHJlcHJlc2VudGF0aW9uXG4gICAgICAgICAgICAvLyBvZiBhbGwgcHJvZHVjdCBjbGlja3Mgd2l0aGluIHRoZSBzZXNzaW9uLiBSZW1pbmRlciwgc2Vzc2lvblN0b3JhZ2UgaXMgbWFpbnRhaW5lZFxuICAgICAgICAgICAgLy8gcGVyIHRhYi93aW5kb3cgYW5kIGlzIGRlbGV0ZWQgdXBvbiBjbG9zaW5nLCBsb2NhbFN0b3JhZ2UgaXMgcGVyIHdlYnNpdGUgd2l0aCBub1xuICAgICAgICAgICAgLy8gZGVmYXVsdCBleHBpcnkuXG4gICAgICAgICAgICBjb25zdCBzZXNzaW9uVHJhaWxzID0gdGhpcy5fbG9hZChnZXRTZXNzaW9uU3RvcmFnZSgpKTtcbiAgICAgICAgICAgIGNvbnN0IHRyYWlscyA9IE9iamVjdC5hc3NpZ24obG9jYWxUcmFpbHMsIHNlc3Npb25UcmFpbHMpO1xuICAgICAgICAgICAgdGhpcy5fc2F2ZShnZXRTZXNzaW9uU3RvcmFnZSgpLCB0cmFpbHMpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkVycm9yIHBhcnNpbmcgc3RvcmVkIGV2ZW50IHF1ZXVlIFwiICsgZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgdGhpcyBwcm9kdWN0IGlkIGFzIHN0YXJ0aW5nIGEgcHVyY2hhc2Ugam91cm5leSBhdCB0aGlzIHNlc3Npb24vcXVlcnlcbiAgICAgKiBQb3NzaWJsZSB0cmFpbCB0eXBlcyBhcmUgXCJtYWluXCIgYW5kIFwiYXNzb2NpYXRlZFwiXG4gICAgICovXG4gICAgcmVnaXN0ZXIoaWQsIHRyYWlsVHlwZSA9IFRyYWlsVHlwZS5NYWluLCBxdWVyeVN0cmluZykge1xuICAgICAgICBjb25zdCB0cmFpbCA9IHtcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS5nZXRUaW1lKCksXG4gICAgICAgICAgICBxdWVyeTogcXVlcnlTdHJpbmcgfHwgdGhpcy5xdWVyeVJlc29sdmVyKCkudG9TdHJpbmcoKSxcbiAgICAgICAgICAgIHR5cGU6IHRyYWlsVHlwZVxuICAgICAgICB9O1xuICAgICAgICBmb3IgKGxldCBzdG9yYWdlIG9mIFtnZXRMb2NhbFN0b3JhZ2UoKSwgZ2V0U2Vzc2lvblN0b3JhZ2UoKV0pIHtcbiAgICAgICAgICAgIGNvbnN0IHRyYWlscyA9IHRoaXMuX2xvYWQoc3RvcmFnZSk7XG4gICAgICAgICAgICB0cmFpbHNbaWRdID0gdHJhaWw7XG4gICAgICAgICAgICB0aGlzLl9zYXZlKHN0b3JhZ2UsIHRyYWlscyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZmV0Y2goaWQpIHtcbiAgICAgICAgY29uc3QgdHJhaWxzID0gdGhpcy5fbG9hZChnZXRTZXNzaW9uU3RvcmFnZSgpKTtcbiAgICAgICAgcmV0dXJuIHRyYWlsc1tpZF07XG4gICAgfVxuICAgIF9sb2FkKHN0b3JhZ2UpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IHN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmtleSk7XG4gICAgICAgIHJldHVybiBkYXRhID8gSlNPTi5wYXJzZShkYXRhKSA6IHt9O1xuICAgIH1cbiAgICBfc2F2ZShzdG9yYWdlLCBkYXRhKSB7XG4gICAgICAgIHN0b3JhZ2Uuc2V0SXRlbSh0aGlzLmtleSwgSlNPTi5zdHJpbmdpZnkoZGF0YSkpO1xuICAgIH1cbn1cbiIsImV4cG9ydCB2YXIgVHJhaWxUeXBlO1xuKGZ1bmN0aW9uIChUcmFpbFR5cGUpIHtcbiAgICBUcmFpbFR5cGVbXCJNYWluXCJdID0gXCJtYWluXCI7XG4gICAgVHJhaWxUeXBlW1wiQXNzb2NpYXRlZFwiXSA9IFwiYXNzb2NpYXRlZFwiO1xufSkoVHJhaWxUeXBlIHx8IChUcmFpbFR5cGUgPSB7fSkpO1xuIiwiZXhwb3J0ICogZnJvbSBcIi4vUXVlcnlcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1RyYWlsXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9UcmFpbFR5cGVcIjtcbiIsImltcG9ydCB7IGdlbmVyYXRlSWQsIGdldENvb2tpZSwgZ2V0TG9jYWxTdG9yYWdlLCBzZXRDb29raWUgfSBmcm9tIFwiLi4vdXRpbHMvVXRpbFwiO1xuY29uc3QgTUlOVVRFU19PTkVfREFZID0gNjAgKiAyNDtcbmNvbnN0IE1JTlVURVNfSEFMRl9IT1VSID0gMzA7XG4vKipcbiAqIFJlYWQgdGhlIGNvb2tpZSB3aXRoIHRoZSBwcm92aWRlZCBuYW1lXG4gKiBAcGFyYW0gbmFtZSB0aGUgbmFtZSBvZiB0aGUgY29va2llXG4gKi9cbmV4cG9ydCBjb25zdCBjb29raWVSZXNvbHZlciA9IChuYW1lID0gXCJcIikgPT4gZ2V0Q29va2llKG5hbWUpO1xuLyoqXG4gKiBSZXNvbHZlIHRoZSBpZCBvZiB0aGUgY3VycmVudCBzZWFyY2ggc2Vzc2lvbi4gQSBzZWFyY2ggc2Vzc2lvbiBpcyBkZWZpbmVkIGFzXG4gKiBsaW1pdGVkIHRpbWUgc2xpY2Ugb2Ygc2VhcmNoIGFjdGl2aXR5IGFjcm9zcyBtdWx0aXBsZSB0YWJzLiBCeSBkZWZhdWx0IGEgc2Vzc2lvblxuICogd291bGQgYmUgY29uc2lkZXJlZCBleHBpcmVkIGFmdGVyIDMwIG1pbiBvZiBpbmFjdGl2aXR5LlxuICpcbiAqIEluIGNhc2UgdGhlIHJlc29sdmVyIGlzIGNvbnN0cnVjdGVkIHdpdGggYSBjb29raWUgbmFtZSwgdGhlIHNlc3Npb24gbGlmZWN5Y2xlXG4gKiB3aWxsIGJlIGdvdmVybmVkIGJ5IHRoZSBsaWZlY3ljbGUgb2YgdGhhdCBjb29raWUuIE90aGVyd2lzZSB0aGUgcmVzb2x2ZXIgd2lsbFxuICogc2V0IGl0cyBvd24gY29va2llLlxuICpcbiAqIEBwYXJhbSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBzZXNzaW9uIGNvb2tpZVxuICovXG5leHBvcnQgY29uc3QgY29va2llU2Vzc2lvblJlc29sdmVyID0gKG5hbWUgPSBcIlNlYXJjaENvbGxlY3RvclNlc3Npb25cIikgPT4gc2V0Q29va2llKG5hbWUsIGNvb2tpZVJlc29sdmVyKG5hbWUpIHx8IGdlbmVyYXRlSWQoKSwgTUlOVVRFU19IQUxGX0hPVVIpO1xuLyoqXG4gKiBGaW5kIHRoZSBwb3NpdGlvbiBvZiBhIERPTSBlbGVtZW50IHJlbGF0aXZlIHRvIG90aGVyIERPTSBlbGVtZW50cyBvZiB0aGUgc2FtZSB0eXBlLlxuICogVG8gYmUgdXNlZCB0byBmaW5kIHRoZSBwb3NpdGlvbiBvZiBhbiBpdGVtIGluIGEgc2VhcmNoIHJlc3VsdC5cbiAqXG4gKiBAcGFyYW0gc2VsZWN0b3JFeHByZXNzaW9uIHRoZSBjc3MgZXhwcmVzc2lvbiB0byBxdWVyeSBmb3Igb3RoZXIgZWxlbWVudHNcbiAqIEBwYXJhbSBlbGVtZW50IHRoZSBlbGVtZW50IGZvciB3aGljaCB3ZSB3YW50IHRvIGtub3cgdGhlIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBlbGVtZW50cyBzZWxlY3RlZCBieSBzZWxlY3RvckV4cHJlc3Npb25cbiAqL1xuZXhwb3J0IGNvbnN0IHBvc2l0aW9uUmVzb2x2ZXIgPSAoc2VsZWN0b3JFeHByZXNzaW9uLCBlbGVtZW50KSA9PiB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20oZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvckV4cHJlc3Npb24pKVxuICAgICAgICAucmVkdWNlKChhY2MsIG5vZGUsIGluZGV4KSA9PiBub2RlID09PSBlbGVtZW50ID8gaW5kZXggOiBhY2MsIHVuZGVmaW5lZCk7XG59O1xuLyoqXG4gKiBUaGlzIGlzIGEgcGVyc2lzdGVudCBkZWJ1ZyByZXNvbHZlciB3aGljaCBzdG9yZXMgdGhlIGRlYnVnIHF1ZXJ5IHBhcmFtZXRlciBhY3Jvc3MgcmVxdWVzdHMuXG4gKi9cbmV4cG9ydCBjb25zdCBkZWJ1Z1Jlc29sdmVyID0gKCkgPT4ge1xuICAgIGNvbnN0IERFQlVHX0tFWSA9IFwiX19jb2xsZWN0b3JEZWJ1Z1wiO1xuICAgIGNvbnN0IGRlYnVnUGFyYW0gPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpLmdldChcImRlYnVnXCIpO1xuICAgIGNvbnN0IGlzRGVidWdQYXJhbUV4aXN0cyA9IGRlYnVnUGFyYW0gIT0gbnVsbDtcbiAgICBpZiAoaXNEZWJ1Z1BhcmFtRXhpc3RzKSB7XG4gICAgICAgIGNvbnN0IGRlYnVnID0gZGVidWdQYXJhbSA9PT0gXCJ0cnVlXCI7XG4gICAgICAgIGdldExvY2FsU3RvcmFnZSgpLnNldEl0ZW0oREVCVUdfS0VZLCBTdHJpbmcoZGVidWcpKTtcbiAgICB9XG4gICAgcmV0dXJuIGdldExvY2FsU3RvcmFnZSgpLmdldEl0ZW0oREVCVUdfS0VZKSA9PT0gXCJ0cnVlXCI7XG59O1xuIiwiZXhwb3J0ICogZnJvbSBcIi4vUmVzb2x2ZXJcIjtcbiIsImV4cG9ydCBjbGFzcyBDb250ZXh0IHtcbiAgICBjb25zdHJ1Y3Rvcih3aW5kb3csIGRvY3VtZW50KSB7XG4gICAgICAgIHRoaXMud2luZG93ID0gd2luZG93O1xuICAgICAgICB0aGlzLmRvY3VtZW50ID0gZG9jdW1lbnQ7XG4gICAgfVxuICAgIGdldFdpbmRvdygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2luZG93O1xuICAgIH1cbiAgICBnZXREb2N1bWVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZG9jdW1lbnQ7XG4gICAgfVxufVxuIiwiZXhwb3J0IHZhciBMaXN0ZW5lclR5cGU7XG4oZnVuY3Rpb24gKExpc3RlbmVyVHlwZSkge1xuICAgIExpc3RlbmVyVHlwZVtcIkRvbVwiXSA9IFwiZG9tXCI7XG4gICAgTGlzdGVuZXJUeXBlW1wiU2VudGluZWxcIl0gPSBcInNlbnRpbmVsXCI7XG59KShMaXN0ZW5lclR5cGUgfHwgKExpc3RlbmVyVHlwZSA9IHt9KSk7XG4iLCJpbXBvcnQgeyBnZXRMb2NhbFN0b3JhZ2UgfSBmcm9tIFwiLi9VdGlsXCI7XG5leHBvcnQgY2xhc3MgTG9jYWxTdG9yYWdlUXVldWUge1xuICAgIGNvbnN0cnVjdG9yKGlkKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IFwic2VhcmNoLWNvbGxlY3Rvci1xdWV1ZVwiICsgKGlkID8gXCItXCIgKyBpZCA6IFwiXCIpO1xuICAgICAgICB0aGlzLnF1ZXVlID0gW107XG4gICAgICAgIGNvbnN0IHN0b3JlZFF1ZXVlID0gZ2V0TG9jYWxTdG9yYWdlKCkuZ2V0SXRlbSh0aGlzLm5hbWUpO1xuICAgICAgICBpZiAoc3RvcmVkUXVldWUpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy5xdWV1ZSA9IEpTT04ucGFyc2Uoc3RvcmVkUXVldWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgcGFyc2luZyBzdG9yZWQgZXZlbnQgcXVldWUgXCIgKyBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBwdXNoKGRhdGEpIHtcbiAgICAgICAgdGhpcy5xdWV1ZS5wdXNoKGRhdGEpO1xuICAgICAgICB0aGlzLl9zYXZlKCk7XG4gICAgfVxuICAgIGRyYWluKCkge1xuICAgICAgICBjb25zdCBidWZmZXIgPSB0aGlzLnF1ZXVlO1xuICAgICAgICB0aGlzLnF1ZXVlID0gW107XG4gICAgICAgIHRoaXMuX3NhdmUoKTtcbiAgICAgICAgcmV0dXJuIGJ1ZmZlcjtcbiAgICB9XG4gICAgdHJhbnNhY3Rpb25hbERyYWluKGFzeW5jQ2FsbGJhY2spIHtcbiAgICAgICAgY29uc3QgYnVmZmVyID0gdGhpcy5xdWV1ZTtcbiAgICAgICAgcmV0dXJuIGFzeW5jQ2FsbGJhY2sodGhpcy5xdWV1ZSlcbiAgICAgICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgICB0aGlzLnF1ZXVlID0gW107XG4gICAgICAgICAgICB0aGlzLl9zYXZlKCk7XG4gICAgICAgICAgICByZXR1cm4gYnVmZmVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgc2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBfc2F2ZSgpIHtcbiAgICAgICAgZ2V0TG9jYWxTdG9yYWdlKCkuc2V0SXRlbSh0aGlzLm5hbWUsIEpTT04uc3RyaW5naWZ5KHRoaXMucXVldWUpKTtcbiAgICB9XG59XG4iLCIvKipcbiAqIENsb25lZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9tdWljc3Mvc2VudGluZWxqcyB1bnRpbCBhIHBhdGNoZWQgdmVyc2lvblxuICogc3VwcG9yaW5nIGlmcmFtZXMgZ2V0cyBhdmFpbGFibGVcbiAqIExpY2Vuc2UgdW5kZXIgTUlUXG4gKi9cbnZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheSwgc2VsZWN0b3JUb0FuaW1hdGlvbk1hcCA9IHt9LCBhbmltYXRpb25DYWxsYmFja3MgPSB7fSwgc3R5bGVFbCwgc3R5bGVTaGVldCwgY3NzUnVsZXM7XG5leHBvcnQgY2xhc3MgU2VudGluZWwge1xuICAgIGNvbnN0cnVjdG9yKGRvYyA9IGRvY3VtZW50KSB7XG4gICAgICAgIHRoaXMuZG9jdW1lbnQgPSBkb2M7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFkZCB3YXRjaGVyLlxuICAgICAqIEBwYXJhbSB7YXJyYXl9IGNzc1NlbGVjdG9ycyAtIExpc3Qgb2YgQ1NTIHNlbGVjdG9yIHN0cmluZ3NcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvblxuICAgICAqL1xuICAgIG9uKGNzc1NlbGVjdG9ycywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKCFjYWxsYmFjaylcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gaW5pdGlhbGl6ZSBhbmltYXRpb25zdGFydCBldmVudCBsaXN0ZW5lclxuICAgICAgICBpZiAoIXN0eWxlRWwpIHtcbiAgICAgICAgICAgIHZhciBkb2MgPSB0aGlzLmRvY3VtZW50LCBoZWFkID0gZG9jLmhlYWQ7XG4gICAgICAgICAgICAvLyBhZGQgYW5pbWF0aW9uc3RhcnQgZXZlbnQgbGlzdGVuZXJcbiAgICAgICAgICAgIC8vQHRzLWlnbm9yZVxuICAgICAgICAgICAgZG9jLmFkZEV2ZW50TGlzdGVuZXIoJ2FuaW1hdGlvbnN0YXJ0JywgZnVuY3Rpb24gKGV2LCBjYWxsYmFja3MsIGwsIGkpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFja3MgPSBhbmltYXRpb25DYWxsYmFja3NbZXYuYW5pbWF0aW9uTmFtZV07XG4gICAgICAgICAgICAgICAgLy8gZXhpdCBpZiBjYWxsYmFja3MgaGF2ZW4ndCBiZWVuIHJlZ2lzdGVyZWRcbiAgICAgICAgICAgICAgICBpZiAoIWNhbGxiYWNrcylcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIC8vIHN0b3Agb3RoZXIgY2FsbGJhY2tzIGZyb20gZmlyaW5nXG4gICAgICAgICAgICAgICAgZXYuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgLy8gaXRlcmF0ZSB0aHJvdWdoIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgIGwgPSBjYWxsYmFja3MubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsOyBpKyspXG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrc1tpXShldi50YXJnZXQpO1xuICAgICAgICAgICAgfSwgdHJ1ZSk7XG4gICAgICAgICAgICAvLyBhZGQgc3R5bGVzaGVldCB0byBkb2N1bWVudFxuICAgICAgICAgICAgc3R5bGVFbCA9IGRvYy5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xuICAgICAgICAgICAgaGVhZC5pbnNlcnRCZWZvcmUoc3R5bGVFbCwgaGVhZC5maXJzdENoaWxkKTtcbiAgICAgICAgICAgIHN0eWxlU2hlZXQgPSBzdHlsZUVsLnNoZWV0O1xuICAgICAgICAgICAgY3NzUnVsZXMgPSBzdHlsZVNoZWV0LmNzc1J1bGVzO1xuICAgICAgICB9XG4gICAgICAgIC8vIGxpc3RpZnkgYXJndW1lbnQgYW5kIGFkZCBjc3MgcnVsZXMvIGNhY2hlIGNhbGxiYWNrc1xuICAgICAgICAoaXNBcnJheShjc3NTZWxlY3RvcnMpID8gY3NzU2VsZWN0b3JzIDogW2Nzc1NlbGVjdG9yc10pXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uIChzZWxlY3RvciwgYW5pbUlkLCBpc0N1c3RvbU5hbWUpIHtcbiAgICAgICAgICAgIGFuaW1JZCA9IHNlbGVjdG9yVG9BbmltYXRpb25NYXBbc2VsZWN0b3JdO1xuICAgICAgICAgICAgaWYgKCFhbmltSWQpIHtcbiAgICAgICAgICAgICAgICAvL0B0cy1pZ25vcmVcbiAgICAgICAgICAgICAgICBpc0N1c3RvbU5hbWUgPSBzZWxlY3RvclswXSA9PSAnISc7XG4gICAgICAgICAgICAgICAgLy8gZGVmaW5lIGFuaW1hdGlvbiBuYW1lIGFuZCBhZGQgdG8gbWFwXG4gICAgICAgICAgICAgICAgc2VsZWN0b3JUb0FuaW1hdGlvbk1hcFtzZWxlY3Rvcl0gPSBhbmltSWQgPVxuICAgICAgICAgICAgICAgICAgICBpc0N1c3RvbU5hbWUgPyBzZWxlY3Rvci5zbGljZSgxKSA6ICdzZW50aW5lbC0nICtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMTYpLnNsaWNlKDIpO1xuICAgICAgICAgICAgICAgIC8vIGFkZCBrZXlmcmFtZSBydWxlXG4gICAgICAgICAgICAgICAgY3NzUnVsZXNbc3R5bGVTaGVldC5pbnNlcnRSdWxlKCdAa2V5ZnJhbWVzICcgKyBhbmltSWQgK1xuICAgICAgICAgICAgICAgICAgICAne2Zyb217dHJhbnNmb3JtOm5vbmU7fXRve3RyYW5zZm9ybTpub25lO319JywgY3NzUnVsZXMubGVuZ3RoKV1cbiAgICAgICAgICAgICAgICAgICAgLl9pZCA9IHNlbGVjdG9yO1xuICAgICAgICAgICAgICAgIC8vIGFkZCBzZWxlY3RvciBhbmltYXRpb24gcnVsZVxuICAgICAgICAgICAgICAgIGlmICghaXNDdXN0b21OYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGNzc1J1bGVzW3N0eWxlU2hlZXQuaW5zZXJ0UnVsZShzZWxlY3RvciArICd7YW5pbWF0aW9uLWR1cmF0aW9uOjAuMDAwMXM7YW5pbWF0aW9uLW5hbWU6JyArXG4gICAgICAgICAgICAgICAgICAgICAgICBhbmltSWQgKyAnO30nLCBjc3NSdWxlcy5sZW5ndGgpXVxuICAgICAgICAgICAgICAgICAgICAgICAgLl9pZCA9IHNlbGVjdG9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBhZGQgdG8gbWFwXG4gICAgICAgICAgICAgICAgc2VsZWN0b3JUb0FuaW1hdGlvbk1hcFtzZWxlY3Rvcl0gPSBhbmltSWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBhZGQgdG8gY2FsbGJhY2tzXG4gICAgICAgICAgICAoYW5pbWF0aW9uQ2FsbGJhY2tzW2FuaW1JZF0gPSBhbmltYXRpb25DYWxsYmFja3NbYW5pbUlkXSB8fCBbXSlcbiAgICAgICAgICAgICAgICAucHVzaChjYWxsYmFjayk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgd2F0Y2hlci5cbiAgICAgKiBAcGFyYW0ge2FycmF5fSBjc3NTZWxlY3RvcnMgLSBMaXN0IG9mIENTUyBzZWxlY3RvciBzdHJpbmdzXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gKG9wdGlvbmFsKVxuICAgICAqL1xuICAgIG9mZihjc3NTZWxlY3RvcnMsIGNhbGxiYWNrKSB7XG4gICAgICAgIC8vIGxpc3RpZnkgYXJndW1lbnQgYW5kIGl0ZXJhdGUgdGhyb3VnaCBydWxlc1xuICAgICAgICAoaXNBcnJheShjc3NTZWxlY3RvcnMpID8gY3NzU2VsZWN0b3JzIDogW2Nzc1NlbGVjdG9yc10pXG4gICAgICAgICAgICAvL0B0cy1pZ25vcmVcbiAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24gKHNlbGVjdG9yLCBhbmltSWQsIGNhbGxiYWNrTGlzdCwgaSkge1xuICAgICAgICAgICAgLy8gZ2V0IGFuaW1JZFxuICAgICAgICAgICAgaWYgKCEoYW5pbUlkID0gc2VsZWN0b3JUb0FuaW1hdGlvbk1hcFtzZWxlY3Rvcl0pKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIC8vIGdldCBjYWxsYmFja3NcbiAgICAgICAgICAgIGNhbGxiYWNrTGlzdCA9IGFuaW1hdGlvbkNhbGxiYWNrc1thbmltSWRdO1xuICAgICAgICAgICAgLy8gcmVtb3ZlIGNhbGxiYWNrIGZyb20gbGlzdFxuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgaSA9IGNhbGxiYWNrTGlzdC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2tMaXN0W2ldID09PSBjYWxsYmFjaylcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrTGlzdC5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2tMaXN0ID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBleGl0IGlmIGNhbGxiYWNrcyBzdGlsbCBleGlzdFxuICAgICAgICAgICAgaWYgKGNhbGxiYWNrTGlzdC5sZW5ndGgpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgLy8gY2xlYXIgY2FjaGUgYW5kIHJlbW92ZSBjc3MgcnVsZXNcbiAgICAgICAgICAgIGkgPSBjc3NSdWxlcy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNzc1J1bGVzW2ldLl9pZCA9PSBzZWxlY3RvcilcbiAgICAgICAgICAgICAgICAgICAgc3R5bGVTaGVldC5kZWxldGVSdWxlKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIHNlbGVjdG9yVG9BbmltYXRpb25NYXBbc2VsZWN0b3JdO1xuICAgICAgICAgICAgZGVsZXRlIGFuaW1hdGlvbkNhbGxiYWNrc1thbmltSWRdO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVzZXQgd2F0Y2hlcnMgYW5kIGNhY2hlXG4gICAgICovXG4gICAgcmVzZXQoKSB7XG4gICAgICAgIHNlbGVjdG9yVG9BbmltYXRpb25NYXAgPSB7fTtcbiAgICAgICAgYW5pbWF0aW9uQ2FsbGJhY2tzID0ge307XG4gICAgICAgIGlmIChzdHlsZUVsKVxuICAgICAgICAgICAgc3R5bGVFbC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHN0eWxlRWwpO1xuICAgICAgICBzdHlsZUVsID0gMDtcbiAgICB9XG59XG4iLCIvKipcbiAqIFBhcnNlIHRoZSBicm93c2VyIHF1ZXJ5IHN0cmluZyBvciB0aGUgcGFzc2VkIHN0cmluZyBpbnRvIGEgamF2YXNjcmlwdCBvYmplY3RcbiAqIHdpdGgga2V5cyB0aGUgcXVlcnkgcGFyYW1ldGVyIG5hbWVzIGFuZCB2YWx1ZXMgdGhlIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBxdWVyeVN0cmluZyAtIHRoZSBxdWVyeSBzdHJpbmcgdG8gcGFyc2UsIHdpbmRvdy5sb2NhdGlvbi5zZWFyY2ggaWYgbm90IGF2YWlsYWJsZVxuICogQHJldHVybiB7b2JqZWN0fVxuICovXG5leHBvcnQgY29uc3QgcGFyc2VRdWVyeVN0cmluZyA9IChxdWVyeVN0cmluZyA9IHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpID0+IHtcbiAgICByZXR1cm4gbmV3IFVSTFNlYXJjaFBhcmFtcyhxdWVyeVN0cmluZyk7XG59O1xuLyoqXG4gKiBTb21lIGJyb3dzZXIgbGlrZSBTYWZhcmkgcHJldmVudCBhY2Nlc3NpbmcgbG9jYWxTdG9yYWdlIGluIHByaXZhdGUgbW9kZSBieSB0aHJvd2luZyBleGNlcHRpb25zLlxuICogVXNlIHRoaXMgbWV0aG9kIHRvIHJldHJpZXZlIGEgbW9jayBpbXBsIHdoaWNoIHdpbGwgYXQgbGVhc3QgcHJldmVudCBlcnJvcnMuXG4gKi9cbmV4cG9ydCBjb25zdCBnZXRMb2NhbFN0b3JhZ2UgPSAoKSA9PiB7XG4gICAgaWYgKFwibG9jYWxTdG9yYWdlXCIgaW4gd2luZG93KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2UuZ2V0SXRlbShcImFiY1wiKTsgLy8gYWNjZXNzIGxvY2FsU3RvcmFnZSB0byB0cmlnZ2VyIGluY29nbml0byBtb2RlIGV4Y2VwdGlvbnNcbiAgICAgICAgICAgIHJldHVybiBsb2NhbFN0b3JhZ2U7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGNvb2tpZVN0b3JhZ2UoNTI1NjAwLCBcIl9fbG9jYWxTdG9yYWdlTW9ja19fX1wiKTtcbn07XG4vKipcbiAqIFVSTCBzYWZlIGJhc2U2NCBlbmNvZGluZ1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBUaGUgc3RyaW5nIHRvIGJlIGVuY29kZWQsIG9ubHkgQVNDSUkvSVNPLTg4NTktMSBzdXBwb3J0ZWRcbiAqL1xuZXhwb3J0IGNvbnN0IGJhc2U2NEVuY29kZSA9IChzdHIpID0+IHtcbiAgICAvLyBOb3RlLCArIHJlcGxhY2VkIHdpdGggLSwgLyByZXBsYWNlZCB3aXRoIF9cbiAgICBjb25zdCBiNjQgPSBcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5LV89XCI7XG4gICAgbGV0IG8xLCBvMiwgbzMsIGJpdHMsIGgxLCBoMiwgaDMsIGg0LCBlID0gW10sIHBhZCA9ICcnLCBjO1xuICAgIGMgPSBzdHIubGVuZ3RoICUgMzsgLy8gcGFkIHN0cmluZyB0byBsZW5ndGggb2YgbXVsdGlwbGUgb2YgM1xuICAgIGlmIChjID4gMCkge1xuICAgICAgICB3aGlsZSAoYysrIDwgMykge1xuICAgICAgICAgICAgcGFkICs9ICc9JztcbiAgICAgICAgICAgIHN0ciArPSAnXFwwJztcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBub3RlOiBkb2luZyBwYWRkaW5nIGhlcmUgc2F2ZXMgdXMgZG9pbmcgc3BlY2lhbC1jYXNlIHBhY2tpbmcgZm9yIHRyYWlsaW5nIDEgb3IgMiBjaGFyc1xuICAgIGZvciAoYyA9IDA7IGMgPCBzdHIubGVuZ3RoOyBjICs9IDMpIHsgLy8gcGFjayB0aHJlZSBvY3RldHMgaW50byBmb3VyIGhleGV0c1xuICAgICAgICBvMSA9IHN0ci5jaGFyQ29kZUF0KGMpO1xuICAgICAgICBvMiA9IHN0ci5jaGFyQ29kZUF0KGMgKyAxKTtcbiAgICAgICAgbzMgPSBzdHIuY2hhckNvZGVBdChjICsgMik7XG4gICAgICAgIGJpdHMgPSBvMSA8PCAxNiB8IG8yIDw8IDggfCBvMztcbiAgICAgICAgaDEgPSBiaXRzID4+IDE4ICYgMHgzZjtcbiAgICAgICAgaDIgPSBiaXRzID4+IDEyICYgMHgzZjtcbiAgICAgICAgaDMgPSBiaXRzID4+IDYgJiAweDNmO1xuICAgICAgICBoNCA9IGJpdHMgJiAweDNmO1xuICAgICAgICAvLyB1c2UgaGV4dGV0cyB0byBpbmRleCBpbnRvIGNvZGUgc3RyaW5nXG4gICAgICAgIGVbYyAvIDNdID0gYjY0LmNoYXJBdChoMSkgKyBiNjQuY2hhckF0KGgyKSArIGI2NC5jaGFyQXQoaDMpICsgYjY0LmNoYXJBdChoNCk7XG4gICAgfVxuICAgIHN0ciA9IGUuam9pbignJyk7IC8vIHVzZSBBcnJheS5qb2luKCkgZm9yIGJldHRlciBwZXJmb3JtYW5jZSB0aGFuIHJlcGVhdGVkIHN0cmluZyBhcHBlbmRzXG4gICAgLy8gcmVwbGFjZSAnQSdzIGZyb20gcGFkZGVkIG51bGxzIHdpdGggJz0nc1xuICAgIHN0ciA9IHN0ci5zbGljZSgwLCBzdHIubGVuZ3RoIC0gcGFkLmxlbmd0aCkgKyBwYWQ7XG4gICAgcmV0dXJuIHN0cjtcbn07XG5leHBvcnQgY29uc3QgZ2VuZXJhdGVJZCA9ICgpID0+IHtcbiAgICBjb25zdCBwb3NzaWJsZSA9IFwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODlcIjtcbiAgICBsZXQgdGV4dCA9IFwiXCI7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgdGV4dCArPSBwb3NzaWJsZS5jaGFyQXQoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogcG9zc2libGUubGVuZ3RoKSk7XG4gICAgfVxuICAgIHJldHVybiB0ZXh0O1xufTtcbmV4cG9ydCBjb25zdCBnZXRTZXNzaW9uU3RvcmFnZSA9ICgpID0+IHtcbiAgICBpZiAoXCJzZXNzaW9uU3RvcmFnZVwiIGluIHdpbmRvdykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2Vzc2lvblN0b3JhZ2UuZ2V0SXRlbShcImFiY1wiKTsgLy8gYWNjZXNzIHNlc3Npb25TdG9yYWdlIHRvIHRyaWdnZXIgaW5jb2duaXRvIG1vZGUgZXhjZXB0aW9uc1xuICAgICAgICAgICAgcmV0dXJuIHNlc3Npb25TdG9yYWdlO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjb29raWVTdG9yYWdlKHZvaWQgMCwgXCJfX3Nlc3Npb25TdG9yYWdlTW9ja19fX1wiKTtcbn07XG5mdW5jdGlvbiBjb29raWVTdG9yYWdlKHR0bE1pbnV0ZXMsIHN0b3JhZ2VOYW1lKSB7XG4gICAgY29uc3QgTE9DQUxfU1RPUkFHRV9DT09LSUVfTkFNRSA9IHN0b3JhZ2VOYW1lO1xuICAgIGZ1bmN0aW9uIGdldFN0b3JhZ2VGcm9tQ29va2llKCkge1xuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShnZXRDb29raWUoTE9DQUxfU1RPUkFHRV9DT09LSUVfTkFNRSkgfHwgXCJ7fVwiKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2F2ZVN0b3JhZ2VUb0Nvb2tpZShkYXRhKSB7XG4gICAgICAgIHNldENvb2tpZShMT0NBTF9TVE9SQUdFX0NPT0tJRV9OQU1FLCBkYXRhLCB0dGxNaW51dGVzKTsgLy8gb25lIHllYXJcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZ2V0SXRlbShrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBnZXRTdG9yYWdlRnJvbUNvb2tpZSgpW2tleV0gfHwgbnVsbDtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0SXRlbShrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICBjb25zdCBsb2NhbFN0b3JhZ2VTdGF0ZSA9IGdldFN0b3JhZ2VGcm9tQ29va2llKCk7XG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2VTdGF0ZVtrZXldID0gdmFsdWU7XG4gICAgICAgICAgICBzYXZlU3RvcmFnZVRvQ29va2llKEpTT04uc3RyaW5naWZ5KGxvY2FsU3RvcmFnZVN0YXRlKSk7XG4gICAgICAgIH0sXG4gICAgICAgIHJlbW92ZUl0ZW0oa2V5KSB7XG4gICAgICAgICAgICBjb25zdCBsb2NhbFN0b3JhZ2VTdGF0ZSA9IGdldFN0b3JhZ2VGcm9tQ29va2llKCk7XG4gICAgICAgICAgICBkZWxldGUgbG9jYWxTdG9yYWdlU3RhdGVba2V5XTtcbiAgICAgICAgICAgIHNhdmVTdG9yYWdlVG9Db29raWUoSlNPTi5zdHJpbmdpZnkobG9jYWxTdG9yYWdlU3RhdGUpKTtcbiAgICAgICAgfSxcbiAgICAgICAgY2xlYXIoKSB7XG4gICAgICAgICAgICBjb25zdCBsb2NhbFN0b3JhZ2VTdGF0ZSA9IHt9O1xuICAgICAgICAgICAgc2F2ZVN0b3JhZ2VUb0Nvb2tpZShKU09OLnN0cmluZ2lmeShsb2NhbFN0b3JhZ2VTdGF0ZSkpO1xuICAgICAgICB9LFxuICAgICAgICBrZXkobikge1xuICAgICAgICAgICAgY29uc3QgbG9jYWxTdG9yYWdlU3RhdGUgPSBnZXRTdG9yYWdlRnJvbUNvb2tpZSgpO1xuICAgICAgICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGxvY2FsU3RvcmFnZVN0YXRlKTtcbiAgICAgICAgICAgIGlmIChuID4ga2V5cy5sZW5ndGggLSAxKVxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIGtleXNbbl07XG4gICAgICAgIH0sXG4gICAgICAgIGdldCBsZW5ndGgoKSB7XG4gICAgICAgICAgICBjb25zdCBsb2NhbFN0b3JhZ2VTdGF0ZSA9IGdldFN0b3JhZ2VGcm9tQ29va2llKCk7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMobG9jYWxTdG9yYWdlU3RhdGUpLmxlbmd0aDtcbiAgICAgICAgfVxuICAgIH07XG59XG5leHBvcnQgY29uc3Qgc2V0Q29va2llID0gKG5hbWUsIHZhbHVlLCB0dGxNaW51dGVzKSA9PiB7XG4gICAgbGV0IGV4cGlyZXMgPSBcIlwiO1xuICAgIGlmICh0dGxNaW51dGVzKSB7XG4gICAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpO1xuICAgICAgICBkYXRlLnNldFRpbWUoZGF0ZS5nZXRUaW1lKCkgKyAodHRsTWludXRlcyAqIDYwICogMTAwMCkpO1xuICAgICAgICBleHBpcmVzID0gXCI7IGV4cGlyZXM9XCIgKyBkYXRlLnRvVVRDU3RyaW5nKCk7XG4gICAgfVxuICAgIC8vIEhhbmRsZSB0aGUgdXBjb21pbmcgZm9yY2VkIHN3aXRjaCB0byBTYW1lU2l0ZSAmIFNlY3VyZSBwYXJhbXMgaHR0cHM6Ly93d3cuY2hyb21lc3RhdHVzLmNvbS9mZWF0dXJlLzU2MzM1MjE2MjIxODgwMzJcbiAgICAvLyBTaW5jZSB0aGlzIGlzIGEgZ2VuZXJpYyBsaWJyYXJ5LCB3ZSBjYW4ndCByZXN0cmljdCB0aGUgZG9tYWluIHVuZGVyIHdoaWNoIGl0J3MgYmVlaW5nIHNlcnZlZCwgdGh1cyBub3Qgc2V0dGluZyBkb21haW5cbiAgICAvLyBmb3IgdGhlIGNvb2tpZS4gSXQncyB1c3VhbGx5IGxvYWRlZCBhbmQgc3Vic2VxdWVudGx5IHJlcXVlc3RlZCBmcm9tIGEgdGhpcmQtcGFydHkgZG9tYWluLCB0aHVzIHdlIG5lZWQgdG8gc3BlY2lmeSBTYW1lU2l0ZT1Ob25lIHdoaWNoXG4gICAgLy8gcGVyIHRoZSBsYXRlc3Qgc3BlY2lmaWNhdGlvbnMgcmVxdWlyZXMgdGhlIFNlY3VyZSBhdHRyaWJ1dGUuXG4gICAgLy9cbiAgICAvLyBUbyBhbGxvdyBsb2NhbCBkZWJ1Z2dpbmcsIHdlIHdvbid0IHNldCB0aGVzZSB3aGVuIGxvYWRlZCBvbiBsb2NhbGhvc3QuIE5vdGUsIGFmdGVyIHRoaXMgY2hhbmdlLCB5b3Ugd29uJ3QgYmUgYWJsZSB0byBzZXJ2ZVxuICAgIC8vIHRoZSBjb2xsZWN0b3IgdG8gcmVhbCBjbGllbnRzIG92ZXIgbm9uLWh0dHBzIGNvbm5lY3Rpb25zIC0gdGhlIHNlc3Npb24gY29va2llcyB3b24ndCBtYXRjaFxuICAgIGNvbnN0IHNhbWVTaXRlID0gd2luZG93LmxvY2F0aW9uLmhvc3RuYW1lID09PSBcImxvY2FsaG9zdFwiID8gXCJcIiA6IFwiOyBTYW1lU2l0ZT1Ob25lOyBTZWN1cmVcIjtcbiAgICBkb2N1bWVudC5jb29raWUgPSBuYW1lICsgXCI9XCIgKyAodmFsdWUgfHwgXCJcIikgKyBleHBpcmVzICsgXCI7IHBhdGg9L1wiICsgc2FtZVNpdGU7XG4gICAgcmV0dXJuIHZhbHVlO1xufTtcbmV4cG9ydCBjb25zdCBnZXRDb29raWUgPSAoY25hbWUpID0+IHtcbiAgICBjb25zdCBuYW1lID0gY25hbWUgKyBcIj1cIjtcbiAgICBjb25zdCBkZWNvZGVkQ29va2llID0gZGVjb2RlVVJJQ29tcG9uZW50KGRvY3VtZW50LmNvb2tpZSk7XG4gICAgY29uc3QgY2EgPSBkZWNvZGVkQ29va2llLnNwbGl0KCc7Jyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjYS5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgYyA9IGNhW2ldO1xuICAgICAgICB3aGlsZSAoYy5jaGFyQXQoMCkgPT0gJyAnKSB7XG4gICAgICAgICAgICBjID0gYy5zdWJzdHJpbmcoMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGMuaW5kZXhPZihuYW1lKSA9PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gYy5zdWJzdHJpbmcobmFtZS5sZW5ndGgsIGMubGVuZ3RoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gXCJcIjtcbn07XG4vKipcbiAqIFJldHVybnMgYSBmdW5jdGlvbiwgdGhhdCwgYXMgbG9uZyBhcyBpdCBjb250aW51ZXMgdG8gYmUgaW52b2tlZCwgd2lsbCBub3RcbiAqIGJlIHRyaWdnZXJlZC4gVGhlIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGFmdGVyIGl0IHN0b3BzIGJlaW5nIGNhbGxlZCBmb3JcbiAqIE4gbWlsbGlzZWNvbmRzLiBJZiBgaW1tZWRpYXRlYCBpcyBwYXNzZWQsIHRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZVxuICogbGVhZGluZyBlZGdlLCBpbnN0ZWFkIG9mIHRoZSB0cmFpbGluZy4gVGhlIGZ1bmN0aW9uIGFsc28gaGFzIGEgcHJvcGVydHkgJ2NsZWFyJ1xuICogdGhhdCBpcyBhIGZ1bmN0aW9uIHdoaWNoIHdpbGwgY2xlYXIgdGhlIHRpbWVyIHRvIHByZXZlbnQgcHJldmlvdXNseSBzY2hlZHVsZWQgZXhlY3V0aW9ucy5cbiAqXG4gKiBAc291cmNlIHVuZGVyc2NvcmUuanNcbiAqIEBzZWUgaHR0cDovL3Vuc2NyaXB0YWJsZS5jb20vMjAwOS8wMy8yMC9kZWJvdW5jaW5nLWphdmFzY3JpcHQtbWV0aG9kcy9cbiAqIEBwYXJhbSBmdW5jIHtGdW5jdGlvbn0gZnVuY3Rpb24gdG8gd3JhcFxuICogQHBhcmFtIHdhaXQge051bWJlcn0gdGltZW91dCBpbiBtcyAoYDEwMGApXG4gKiBAcGFyYW0gaW1tZWRpYXRlIHtCb29sZWFufSB3aGV0aGVyIHRvIGV4ZWN1dGUgYXQgdGhlIGJlZ2lubmluZyAoYGZhbHNlYClcbiAqIEBhcGkgcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBkZWJvdW5jZSA9IChmdW5jLCB3YWl0ID0gMTAwLCBpbW1lZGlhdGUgPSBmYWxzZSkgPT4ge1xuICAgIHZhciB0aW1lb3V0LCBhcmdzLCBjb250ZXh0LCB0aW1lc3RhbXAsIHJlc3VsdDtcbiAgICBmdW5jdGlvbiBsYXRlcigpIHtcbiAgICAgICAgdmFyIGxhc3QgPSBEYXRlLm5vdygpIC0gdGltZXN0YW1wO1xuICAgICAgICBpZiAobGFzdCA8IHdhaXQgJiYgbGFzdCA+PSAwKSB7XG4gICAgICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCAtIGxhc3QpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICAgICAgICBpZiAoIWltbWVkaWF0ZSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgICAgICAgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGRlYm91bmNlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29udGV4dCA9IHRoaXM7XG4gICAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIHRpbWVzdGFtcCA9IERhdGUubm93KCk7XG4gICAgICAgIHZhciBjYWxsTm93ID0gaW1tZWRpYXRlICYmICF0aW1lb3V0O1xuICAgICAgICBpZiAoIXRpbWVvdXQpXG4gICAgICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCk7XG4gICAgICAgIGlmIChjYWxsTm93KSB7XG4gICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBkZWJvdW5jZWQuY2xlYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aW1lb3V0KSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgZGVib3VuY2VkLmZsdXNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGltZW91dCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gZGVib3VuY2VkO1xufTtcbiIsImV4cG9ydCAqIGZyb20gXCIuL0NvbnRleHRcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0xpc3RlbmVyVHlwZVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vTG9jYWxTdG9yYWdlUXVldWVcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1NlbnRpbmVsXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9VdGlsXCI7XG4iLCJpbXBvcnQgeyBiYXNlNjRFbmNvZGUgfSBmcm9tIFwiLi4vdXRpbHNcIjtcbmV4cG9ydCBjbGFzcyBCYXNlNjRFbmNvZGVXcml0ZXIge1xuICAgIGNvbnN0cnVjdG9yKGRlbGVnYXRlKSB7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTtcbiAgICB9XG4gICAgd3JpdGUoZGF0YSkge1xuICAgICAgICBjb25zdCBkID0gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUud3JpdGUoYmFzZTY0RW5jb2RlKGVuY29kZVVSSUNvbXBvbmVudChkKSkpO1xuICAgIH1cbn1cbiIsImV4cG9ydCBjbGFzcyBCcm93c2VyVHJhY2tpbmdXcml0ZXIge1xuICAgIGNvbnN0cnVjdG9yKGRlbGVnYXRlLCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB9XG4gICAgd3JpdGUoZGF0YSkge1xuICAgICAgICBjb25zdCB7IHJlY29yZFVybCwgcmVjb3JkUmVmZXJyZXIsIHJlY29yZExhbmd1YWdlIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGlmIChyZWNvcmRVcmwgJiYgIWRhdGEudXJsKVxuICAgICAgICAgICAgZGF0YS51cmwgPSB0aGlzLmdldFdpbmRvdygpLmxvY2F0aW9uLmhyZWY7XG4gICAgICAgIGlmIChyZWNvcmRSZWZlcnJlciAmJiAhZGF0YS5yZWYpXG4gICAgICAgICAgICBkYXRhLnJlZiA9IHRoaXMuZ2V0RG9jdW1lbnQoKS5yZWZlcnJlcjtcbiAgICAgICAgaWYgKHJlY29yZExhbmd1YWdlICYmICFkYXRhLmxhbmcpXG4gICAgICAgICAgICBkYXRhLmxhbmcgPSB0aGlzLmdldFdpbmRvdygpLm5hdmlnYXRvci5sYW5ndWFnZTtcbiAgICAgICAgdGhpcy5kZWxlZ2F0ZS53cml0ZShkYXRhKTtcbiAgICB9XG4gICAgZ2V0RG9jdW1lbnQoKSB7XG4gICAgICAgIGNvbnN0IHsgY29udGV4dCB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICByZXR1cm4gY29udGV4dCA/IGNvbnRleHQuZ2V0RG9jdW1lbnQoKSA6IGRvY3VtZW50O1xuICAgIH1cbiAgICBnZXRXaW5kb3coKSB7XG4gICAgICAgIGNvbnN0IHsgY29udGV4dCB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICByZXR1cm4gY29udGV4dCA/IGNvbnRleHQuZ2V0V2luZG93KCkgOiB3aW5kb3c7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgTG9jYWxTdG9yYWdlUXVldWUgfSBmcm9tIFwiLi4vdXRpbHMvTG9jYWxTdG9yYWdlUXVldWVcIjtcbi8qKlxuICogQSB3cml0ZXIgdGhhdCBidWZmZXJzIHRoZSBpbmNvbWluZyBldmVudHMgaW4gYSBsb2NhbCBzdG9yYWdlIHF1ZXVlIGFuZCB3cml0ZXNcbiAqIHRoZW0gb3V0IGluIGJhdGNoZXMgZXZlcnkgc2Vjb25kLiBJZiB0aGUgcXVldWUgaXMgbm90IGVtcHR5LCB3aGVuIHRoZSB0aW1lciB0aWNrc1xuICogdGhlIHdyaXRlciB3aWxsIHNlbmQgdGhlIGF2YWlsYWJsZSBkYXRhIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGVyZSBhcmUgY29sbGVjdG9yIGV2ZW50cyBpLmUuXG4gKiBldmVuIGluIHRpbWVzIG9mIGluYWN0aXZpdHkgb3Igd2hlbiBsb2FkaW5nIHRoZSBwYWdlIGFuZCBwcmV2aW91cyBzdGF0ZSBpcyBhdmFpbGFibGUuXG4gKlxuICogVGhlIHdyaXRlciB3aWxsIGFsc28gdHJ5IHRvIHNlbmQgdGhlIGF2YWlsYWJsZSBkYXRhIG9uIGJyb3dzZXIgdW5sb2FkIGV2ZW50LlxuICovXG5leHBvcnQgY2xhc3MgQnVmZmVyaW5nV3JpdGVyIHtcbiAgICBjb25zdHJ1Y3RvcihkZWxlZ2F0ZSwgaWQsIHRpbWVyTXMgPSAxMDAwKSB7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTtcbiAgICAgICAgdGhpcy5xdWV1ZSA9IG5ldyBMb2NhbFN0b3JhZ2VRdWV1ZShpZCk7XG4gICAgICAgIHRoaXMudGltZXJNcyA9IHRpbWVyTXM7XG4gICAgICAgIHRoaXMudGltZXIgPSBzZXRUaW1lb3V0KHRoaXMuZmx1c2guYmluZCh0aGlzKSwgdGltZXJNcyk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICB9XG4gICAgd3JpdGUoZGF0YSkge1xuICAgICAgICB0aGlzLnF1ZXVlLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIGZsdXNoKGNhbmNlbFRpbWVyKSB7XG4gICAgICAgIGlmICh0aGlzLnF1ZXVlLnNpemUoKSA+IDApIHtcbiAgICAgICAgICAgIC8vIGlmIHRoZSBicm93c2VyIHNodXRzZG93biBiZWZvcmUgdGhlIHdyaXRlIGlzIGNvbXBsZXRlXG4gICAgICAgICAgICB0aGlzLnF1ZXVlLnRyYW5zYWN0aW9uYWxEcmFpbihxdWV1ZSA9PiBuZXcgUHJvbWlzZShyZXMgPT4gcmVzKHRoaXMuZGVsZWdhdGUud3JpdGUocXVldWUpKSkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmVycm9yKFwiY291bGQgbm90IGRyYWluIHF1ZXVlOiBcIiwgZXJyKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjYW5jZWxUaW1lcikge1xuICAgICAgICAgICAgdGhpcy50aW1lciA9IHNldFRpbWVvdXQodGhpcy5mbHVzaC5iaW5kKHRoaXMpLCB0aGlzLnRpbWVyTXMpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiZXhwb3J0IGNsYXNzIENvbnNvbGVXcml0ZXIge1xuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcIkNvbnNvbGVXcml0ZXIgcmVjZWl2aW5nIG5ldyBkYXRhOiBcIik7XG4gICAgICAgIGNvbnNvbGUubG9nKGRhdGEpO1xuICAgIH1cbn1cbiIsIi8qKlxuICogTG9ncyB0aGUgZGF0YSB0byB0aGUgYnJvd3NlciBjb25zb2xlIHVzaW5nIGNvbnNvbGUuZGVidWdcbiAqL1xuZXhwb3J0IGNsYXNzIERlYnVnV3JpdGVyIHtcbiAgICBjb25zdHJ1Y3RvcihkZWxlZ2F0ZSwgZGVidWcpIHtcbiAgICAgICAgdGhpcy5kZWxlZ2F0ZSA9IGRlbGVnYXRlO1xuICAgICAgICB0aGlzLmRlYnVnID0gZGVidWc7XG4gICAgfVxuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgaWYgKHRoaXMuZGVidWcpXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhkYXRhKTtcbiAgICAgICAgdGhpcy5kZWxlZ2F0ZS53cml0ZShkYXRhKTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBTUVNFdmVudFdyaXRlciB9IGZyb20gXCIuL1NRU0V2ZW50V3JpdGVyXCI7XG5pbXBvcnQgeyBSZXN0RXZlbnRXcml0ZXIgfSBmcm9tIFwiLi9SZXN0RXZlbnRXcml0ZXJcIjtcbmltcG9ydCB7IEJ1ZmZlcmluZ1dyaXRlciB9IGZyb20gXCIuL0J1ZmZlcmluZ1dyaXRlclwiO1xuaW1wb3J0IHsgQmFzZTY0RW5jb2RlV3JpdGVyIH0gZnJvbSBcIi4vQmFzZTY0RW5jb2RlV3JpdGVyXCI7XG5pbXBvcnQgeyBKU09ORW52ZWxvcGVXcml0ZXIgfSBmcm9tIFwiLi9KU09ORW52ZWxvcGVXcml0ZXJcIjtcbmltcG9ydCB7IFRyYWlsV3JpdGVyIH0gZnJvbSBcIi4vVHJhaWxXcml0ZXJcIjtcbmltcG9ydCB7IEJyb3dzZXJUcmFja2luZ1dyaXRlciB9IGZyb20gXCIuL0Jyb3dzZXJUcmFja2luZ1dyaXRlclwiO1xuaW1wb3J0IHsgRGVidWdXcml0ZXIgfSBmcm9tIFwiLi9EZWJ1Z1dyaXRlclwiO1xuaW1wb3J0IHsgUXVlcnlXcml0ZXIgfSBmcm9tIFwiLi9RdWVyeVdyaXRlclwiO1xuaW1wb3J0IHsgVHJhaWwgfSBmcm9tIFwiLi4vcXVlcnkvVHJhaWxcIjtcbmV4cG9ydCBjbGFzcyBEZWZhdWx0V3JpdGVyIHtcbiAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHsgZW5kcG9pbnQsIHNxcyB9ID0gb3B0aW9ucztcbiAgICAgICAgLy8gV3JpdGVyIHBpcGVsaW5lLCBhZGQvcmVtb3ZlIHBpZWNlcyBhY2NvcmRpbmcgdG8gdXNlIGNhc2VcbiAgICAgICAgLy8gVGhpcyB3cml0ZXIgcGlwZWxpbmUgd2lsbCBzZW5kIEJhc2U2NCBlbmNvZGVkIGFycmF5IG9mIGpzb24gZXZlbnRzXG4gICAgICAgIGxldCB3cml0ZXIgPSBpc1NRUyhlbmRwb2ludCwgc3FzKSA/IG5ldyBTUVNFdmVudFdyaXRlcihlbmRwb2ludCkgOiBuZXcgUmVzdEV2ZW50V3JpdGVyKGVuZHBvaW50KTtcbiAgICAgICAgd3JpdGVyID0gbmV3IEJhc2U2NEVuY29kZVdyaXRlcih3cml0ZXIpO1xuICAgICAgICB3cml0ZXIgPSBuZXcgQnVmZmVyaW5nV3JpdGVyKHdyaXRlciwgXCJidWZmZXI6XCIgKyBvcHRpb25zLmVuZHBvaW50KTtcbiAgICAgICAgd3JpdGVyID0gbmV3IERlYnVnV3JpdGVyKHdyaXRlciwgb3B0aW9ucy5kZWJ1Zyk7XG4gICAgICAgIHdyaXRlciA9IG5ldyBRdWVyeVdyaXRlcih3cml0ZXIsIG9wdGlvbnMucmVzb2x2ZXIucXVlcnlSZXNvbHZlcik7XG4gICAgICAgIHdyaXRlciA9IG5ldyBUcmFpbFdyaXRlcih3cml0ZXIsIG9wdGlvbnMudHJhaWwgfHwgbmV3IFRyYWlsKG9wdGlvbnMucmVzb2x2ZXIucXVlcnlSZXNvbHZlciwgb3B0aW9ucy5yZXNvbHZlci5zZXNzaW9uUmVzb2x2ZXIpLCBvcHRpb25zLnJlc29sdmVyLnF1ZXJ5UmVzb2x2ZXIpO1xuICAgICAgICB3cml0ZXIgPSBuZXcgSlNPTkVudmVsb3BlV3JpdGVyKHdyaXRlciwgb3B0aW9ucy5yZXNvbHZlci5zZXNzaW9uUmVzb2x2ZXIsIG9wdGlvbnMuY2hhbm5lbCk7XG4gICAgICAgIHdyaXRlciA9IG5ldyBCcm93c2VyVHJhY2tpbmdXcml0ZXIod3JpdGVyLCB7XG4gICAgICAgICAgICByZWNvcmRSZWZlcnJlcjogb3B0aW9ucy5yZWNvcmRSZWZlcnJlcixcbiAgICAgICAgICAgIHJlY29yZFVybDogb3B0aW9ucy5yZWNvcmRVcmwsXG4gICAgICAgICAgICByZWNvcmRMYW5ndWFnZTogb3B0aW9ucy5yZWNvcmRMYW5ndWFnZVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy53cml0ZXIgPSB3cml0ZXI7XG4gICAgfVxuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgdGhpcy53cml0ZXIud3JpdGUoZGF0YSk7XG4gICAgfVxufVxuZnVuY3Rpb24gaXNTUVMoZW5kcG9pbnQsIGZvcmNlU1FTKSB7XG4gICAgcmV0dXJuIGZvcmNlU1FTIHx8IChlbmRwb2ludC5pbmRleE9mKFwic3FzXCIpICE9IC0xICYmIGVuZHBvaW50LmluZGV4T2YoXCJhbWF6b25hd3MuY29tXCIpICE9IC0xKTtcbn1cbiIsIi8qKlxuICogV3JhcCB0aGUgZXZlbnRzIGluIGEgSlNPTiBlbnZlbG9wZSwgZW5yaWNoIGVhY2ggcmVjb3JkIHdpdGggdGltZXN0YW1wLCBzZXNzaW9uIGFuZCBjaGFubmVsIGluZm9ybWF0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgSlNPTkVudmVsb3BlV3JpdGVyIHtcbiAgICBjb25zdHJ1Y3RvcihkZWxlZ2F0ZSwgc2Vzc2lvblJlc29sdmVyLCBjaGFubmVsKSB7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTtcbiAgICAgICAgdGhpcy5zZXNzaW9uUmVzb2x2ZXIgPSBzZXNzaW9uUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMuY2hhbm5lbCA9IGNoYW5uZWw7XG4gICAgfVxuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgZGF0YS50aW1lc3RhbXAgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgZGF0YS5zZXNzaW9uID0gdGhpcy5zZXNzaW9uUmVzb2x2ZXIoKTtcbiAgICAgICAgZGF0YS5jaGFubmVsID0gdGhpcy5jaGFubmVsO1xuICAgICAgICB0aGlzLmRlbGVnYXRlLndyaXRlKGRhdGEpO1xuICAgIH1cbn1cbiIsIi8qKlxuICogQXBwZW5kcyB0aGUgcXVlcnkgdG8gdGhlIGRhdGEgaWYgbm8gcXVlcnkgcHJvcGVydHkgZXhpc3RzXG4gKi9cbmV4cG9ydCBjbGFzcyBRdWVyeVdyaXRlciB7XG4gICAgY29uc3RydWN0b3IoZGVsZWdhdGUsIHF1ZXJ5UmVzb2x2ZXIpIHtcbiAgICAgICAgdGhpcy5kZWxlZ2F0ZSA9IGRlbGVnYXRlO1xuICAgICAgICB0aGlzLnF1ZXJ5UmVzb2x2ZXIgPSBxdWVyeVJlc29sdmVyO1xuICAgIH1cbiAgICB3cml0ZShkYXRhKSB7XG4gICAgICAgIGlmICghZGF0YS5xdWVyeSlcbiAgICAgICAgICAgIGRhdGEucXVlcnkgPSB0aGlzLnF1ZXJ5UmVzb2x2ZXIoKS50b1N0cmluZygpO1xuICAgICAgICB0aGlzLmRlbGVnYXRlLndyaXRlKGRhdGEpO1xuICAgIH1cbn1cbiIsIi8qKlxuICogU3RyYWlnaHQtZm9yd2FyZCBSRVNUIHdyaXRlIHZpYSBHRVQgcmVxdWVzdFxuICovXG5leHBvcnQgY2xhc3MgUmVzdEV2ZW50V3JpdGVyIHtcbiAgICBjb25zdHJ1Y3RvcihlbmRwb2ludCkge1xuICAgICAgICB0aGlzLmVuZHBvaW50ID0gZW5kcG9pbnQ7XG4gICAgfVxuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgY29uc3QgaW1nID0gbmV3IEltYWdlKCk7XG4gICAgICAgIGltZy5zcmMgPSB0aGlzLmVuZHBvaW50ICsgXCI/ZGF0YT1cIiArIEpTT04uc3RyaW5naWZ5KGRhdGEpO1xuICAgIH1cbn1cbiIsImV4cG9ydCBjbGFzcyBTUVNFdmVudFdyaXRlciB7XG4gICAgY29uc3RydWN0b3IocXVldWUsIGZpZm8gPSBmYWxzZSkge1xuICAgICAgICB0aGlzLnF1ZXVlID0gcXVldWU7XG4gICAgICAgIHRoaXMuZmlmbyA9IGZpZm87XG4gICAgfVxuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgY29uc3QgaW1nID0gbmV3IEltYWdlKCk7XG4gICAgICAgIGxldCBzcmMgPSB0aGlzLnF1ZXVlICsgXCI/VmVyc2lvbj0yMDEyLTExLTA1JkFjdGlvbj1TZW5kTWVzc2FnZVwiO1xuICAgICAgICAvLyBTUVMgc3VwcG9ydHMgRklGTyBxdWV1ZXMgaW4gc29tZSByZWdpb25zIHRoYXQgY2FuIGFsc28gZ3VhcmFudGVlIHRoZSBvcmRlclxuICAgICAgICAvLyBvZiB0aGUgbWVzc2FnZXMuXG4gICAgICAgIGlmICh0aGlzLmZpZm8pIHtcbiAgICAgICAgICAgIC8vIFRPRE8gd2hlbiBlbm91Z2ggaW5mb3JtYXRpb24gaXMgcHJlc2VudCB0byB1bmlxdWVseSBpZGVudGlmeSBhIG1lc3NhZ2UsIHN3aXRjaCB0aGUgZGVkdXBsaWNhdGlvbiBpZCB0byBhIG1lc3NhZ2UgaGFzaFxuICAgICAgICAgICAgc3JjICs9IFwiJk1lc3NhZ2VHcm91cElkPTEmTWVzc2FnZURlZHVwbGljYXRpb25JZD1cIiArIE1hdGgucmFuZG9tKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICBkYXRhID0gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgc3JjICs9IFwiJk1lc3NhZ2VCb2R5PVwiICsgZGF0YTtcbiAgICAgICAgaW1nLnNyYyA9IHNyYztcbiAgICB9XG59XG4iLCIvKipcbiAqIENhbGxzIGFsbCB3cml0ZXJzIHBhc3NlZCB0byB0aGUgY29uc3RydWN0b3IgZXJyb3Igc2FmZVxuICovXG5leHBvcnQgY2xhc3MgU3BsaXRTdHJlYW1Xcml0ZXIge1xuICAgIGNvbnN0cnVjdG9yKHdyaXRlcnMpIHtcbiAgICAgICAgdGhpcy53cml0ZXJzID0gd3JpdGVycztcbiAgICB9XG4gICAgd3JpdGUoZGF0YSkge1xuICAgICAgICBmb3IgKGxldCB3cml0ZXIgb2YgdGhpcy53cml0ZXJzKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHdyaXRlci53cml0ZShkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCB3cml0ZSBkYXRhOiBcIiwgZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJleHBvcnQgY2xhc3MgVHJhaWxXcml0ZXIge1xuICAgIGNvbnN0cnVjdG9yKGRlbGVnYXRlLCB0cmFpbCwgcXVlcnlSZXNvbHZlcikge1xuICAgICAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7XG4gICAgICAgIHRoaXMudHJhaWwgPSB0cmFpbDtcbiAgICAgICAgdGhpcy5xdWVyeVJlc29sdmVyID0gcXVlcnlSZXNvbHZlcjtcbiAgICB9XG4gICAgd3JpdGUoZGF0YSkge1xuICAgICAgICBjb25zdCBxID0gdGhpcy5xdWVyeVJlc29sdmVyKCk7XG4gICAgICAgIGlmICgoIXEgfHwgIXEuaXNWYWxpZCgpKSAmJiAhZGF0YS5xdWVyeSAmJiB0aGlzLmlzQXBwZW5kVHJhaWwoZGF0YSkpIHtcbiAgICAgICAgICAgIC8vIFNlZSBpZiB3ZSBoYXZlIGEgcGF5bG9hZCBpZCBhbmQgYSB0cmFpbCBmb3IgaXQuIFRoaXMgbWVhbnMgd2VcbiAgICAgICAgICAgIC8vIGFyZSBjb2xsZWN0aW5nIGRhdGEgZm9yIGFuIGV2ZW50IHRoYXQgZG9lcyBub3QgaGF2ZSBhIHF1ZXJ5IGNvbnRleHRcbiAgICAgICAgICAgIC8vIG9uIHRoZSBwYWdlIGFueW1vcmUgYnV0IHdlIHdhbnQgdG8gYXNzb2NpYXRlIHRoZSBldmVudCB3aXRoIHRoZSBxdWVyeVxuICAgICAgICAgICAgLy8gY29udGV4dCBvZiB0aGUgb3JpZ2luYWwgc2VhcmNoIHJlc3VsdFxuICAgICAgICAgICAgdGhpcy5hcHBlbmRUcmFpbChkYXRhKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRlbGVnYXRlLndyaXRlKGRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBcHBlbmQgdGhlIFRyYWlsIGlmIGFueVxuICAgICAqIEBwYXJhbSBkYXRhXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBhcHBlbmRUcmFpbChkYXRhKSB7XG4gICAgICAgIGNvbnN0IHRyYWlsID0gdGhpcy50cmFpbC5mZXRjaCh0aGlzLmdldElkKGRhdGEpKTtcbiAgICAgICAgaWYgKHRyYWlsICYmIHRyYWlsLnF1ZXJ5KSB7XG4gICAgICAgICAgICBkYXRhLnF1ZXJ5ID0gdHJhaWwucXVlcnk7XG4gICAgICAgICAgICBkYXRhLnF1ZXJ5VGltZSA9IHRyYWlsLnRpbWVzdGFtcDtcbiAgICAgICAgICAgIGRhdGEudHJhaWxUeXBlID0gdHJhaWwudHlwZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBmb3IgbGVnYWN5IHN1cHBvcnQ6IHNvbWV0aW1lcyBkYXRhIHdhcyB3cmFwcGVkIGluIHByb3BlcnR5IGNhbGxlZCBcImRhdGFcIlxuICAgICAqIEBwYXJhbSBkYXRhXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXRJZChkYXRhKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgaWYgKGRhdGEpXG4gICAgICAgICAgICByZXR1cm4gZGF0YS5pZCB8fCAoKF9hID0gZGF0YS5kYXRhKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuaWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFdmFsdWF0ZXMgaWYgdGhlIFRyYWlsIHNob3VsZCBiZSBhcHBlbmRlZCB0byB0aGlzIGV2ZW50XG4gICAgICogQHBhcmFtIGRhdGFcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGlzQXBwZW5kVHJhaWwoZGF0YSkge1xuICAgICAgICByZXR1cm4gZGF0YSAmJiBbXCJjaGVja291dFwiLCBcImJhc2tldFwiLCBcImZpbHRlclwiXS5pbmRleE9mKGRhdGEudHlwZSkgPiAtMTtcbiAgICAgICAgLy8gVEE6IFRoaXMgd2FzIHByZXZpb3VzbHkgXCJkYXRhLmRhdGEgJiYgZGF0YS5kYXRhLmlkICYmIHRoaXMudHJhaWxcIlxuICAgICAgICAvLyB0aGUgb25seSBDb2xsZWN0b3JzIGFwcGVuZGluZyBhIHByb3BlcnR5IGNhbGxlZCBcImRhdGFcIiB0byBpdHMgZXZlbnQgYXJlIENsaWNrQ29sbGVjdG9yIGkuZS5cbiAgICAgICAgLy8gQ2hlY2tvdXRDbGlja0NvbGxlY3RvciwgQmFza2V0Q2xpY2tDb2xsZWN0b3IsIEZpbHRlckNsaWNrQ29sbGVjdG9yXG4gICAgICAgIC8vIEkndmUgcmVmYWN0b3JlZCB0aGlzIGltcGxpY2l0IGNvbmRpdGlvbiB0byB0aGlzIGZ1bmN0aW9uXG4gICAgICAgIC8vIFRPRE8gdmFsaWRhdGUgaWYgdGhpbmdzIHdpbGwgYnJlYWsgd2l0aCBuZXcgaW1wbFxuICAgIH1cbn1cbiIsImV4cG9ydCAqIGZyb20gXCIuL0Jhc2U2NEVuY29kZVdyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vQnVmZmVyaW5nV3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9EZWZhdWx0V3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9KU09ORW52ZWxvcGVXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1Jlc3RFdmVudFdyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vU3BsaXRTdHJlYW1Xcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1NRU0V2ZW50V3JpdGVyXCI7XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9CYXNlNjRFbmNvZGVXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0Jyb3dzZXJUcmFja2luZ1dyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vQnVmZmVyaW5nV3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9Db25zb2xlV3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9EZWJ1Z1dyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vRGVmYXVsdFdyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vSlNPTkVudmVsb3BlV3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9RdWVyeVdyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vUmVzdEV2ZW50V3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9TcGxpdFN0cmVhbVdyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vU1FTRXZlbnRXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1RyYWlsV3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9Xcml0ZXJcIjtcbiIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gKG1vZHVsZSkgPT4ge1xuXHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cblx0XHQoKSA9PiAobW9kdWxlWydkZWZhdWx0J10pIDpcblx0XHQoKSA9PiAobW9kdWxlKTtcblx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgeyBhOiBnZXR0ZXIgfSk7XG5cdHJldHVybiBnZXR0ZXI7XG59OyIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJleHBvcnQgKiBmcm9tIFwiLi9Db2xsZWN0b3JNb2R1bGVcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2NvbGxlY3RvcnMvXCI7XG5leHBvcnQgKiBmcm9tIFwiLi93cml0ZXJzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9xdWVyeVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbG9nZ2VyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9yZXNvbHZlcnNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3V0aWxzXCI7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=
\ No newline at end of file
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,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Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNOa0M7QUFDSjtBQUNKO0FBQ0Y7QUFDQztBQUNHO0FBQ0oiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9ub2RlX21vZHVsZXMvc2Nyb2xsbW9uaXRvci9kaXN0L21vZHVsZS9pbmRleC5qcyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9ub2RlX21vZHVsZXMvc2Nyb2xsbW9uaXRvci9kaXN0L21vZHVsZS9zcmMvY29uc3RhbnRzLmpzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL25vZGVfbW9kdWxlcy9zY3JvbGxtb25pdG9yL2Rpc3QvbW9kdWxlL3NyYy9jb250YWluZXIuanMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vbm9kZV9tb2R1bGVzL3Njcm9sbG1vbml0b3IvZGlzdC9tb2R1bGUvc3JjL3R5cGVzLmpzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL25vZGVfbW9kdWxlcy9zY3JvbGxtb25pdG9yL2Rpc3QvbW9kdWxlL3NyYy93YXRjaGVyLmpzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL0NvbGxlY3Rvck1vZHVsZS50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL0Fic3RyYWN0Q29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvQXNzb2NpYXRlZFByb2R1Y3RDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9CYXNrZXRDbGlja0NvbGxlY3Rvci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL0Jyb3dzZXJDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9DaGVja291dENsaWNrQ29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvQ2xpY2tDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9DbGlja1dyaXRlclJlc29sdmVyQ29sbGVjdG9yLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2NvbGxlY3RvcnMvRmlsdGVyQ2xpY2tDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9GaXJlZFNlYXJjaENvbGxlY3Rvci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL0dlbmVyaWNFdmVudENvbGxlY3Rvci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL0ltcHJlc3Npb25Db2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9JbnN0YW50U2VhcmNoUXVlcnlDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9Qcm9kdWN0Q2xpY2tDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9SZWRpcmVjdENvbGxlY3Rvci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL1NlYXJjaFJlc3VsdENvbGxlY3Rvci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL1N1Z2dlc3RTZWFyY2hDb2xsZWN0b3IudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vY29sbGVjdG9ycy9Xcml0ZXJSZXNvbHZlckNvbGxlY3Rvci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9jb2xsZWN0b3JzL2luZGV4LnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2xvZ2dlci9Mb2dnZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vbG9nZ2VyL0xvZ2dlclRyYW5zcG9ydC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9sb2dnZXIvVHJhbnNwb3J0TG9nZ2VyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL2xvZ2dlci9pbmRleC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9sb2dnZXIvdHJhbnNwb3J0L0NvbnNvbGVUcmFuc3BvcnQudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vbG9nZ2VyL3RyYW5zcG9ydC9TUVNFcnJvclRyYW5zcG9ydC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9sb2dnZXIvdHJhbnNwb3J0L1NRU1RyYW5zcG9ydC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9sb2dnZXIvdHJhbnNwb3J0L2luZGV4LnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3F1ZXJ5L1F1ZXJ5LnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3F1ZXJ5L1RyYWlsLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3F1ZXJ5L1RyYWlsVHlwZS50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9xdWVyeS9pbmRleC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9yZXNvbHZlcnMvUmVzb2x2ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vcmVzb2x2ZXJzL2luZGV4LnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3V0aWxzL0NvbnRleHQudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vdXRpbHMvTGlzdGVuZXJUeXBlLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3V0aWxzL0xvY2FsU3RvcmFnZVF1ZXVlLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3V0aWxzL1NlbnRpbmVsLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3V0aWxzL1V0aWwudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vdXRpbHMvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9CYXNlNjRFbmNvZGVXcml0ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9Ccm93c2VyVHJhY2tpbmdXcml0ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9CdWZmZXJpbmdXcml0ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9Db25zb2xlV3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvRGVidWdXcml0ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9EZWZhdWx0V3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvSlNPTkVudmVsb3BlV3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvUXVlcnlXcml0ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9SZXN0RXZlbnRXcml0ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9TUVNFdmVudFdyaXRlci50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi93cml0ZXJzL1NwbGl0U3RyZWFtV3JpdGVyLnRzIiwid2VicGFjazovL1NlYXJjaENvbGxlY3Rvci8uL3NyYy9tYWluL3dyaXRlcnMvVHJhaWxXcml0ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9Xcml0ZXIudHMiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yLy4vc3JjL21haW4vd3JpdGVycy9pbmRleC50cyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3Ivd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vU2VhcmNoQ29sbGVjdG9yL3dlYnBhY2svcnVudGltZS9kZWZpbmUgcHJvcGVydHkgZ2V0dGVycyIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3Ivd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3Ivd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9TZWFyY2hDb2xsZWN0b3IvLi9zcmMvbWFpbi9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgeyBTY3JvbGxNb25pdG9yQ29udGFpbmVyIH0gZnJvbSAnLi9zcmMvY29udGFpbmVyLmpzJztcbmV4cG9ydCB7IFdhdGNoZXIgfSBmcm9tICcuL3NyYy93YXRjaGVyLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL3R5cGVzJztcbmltcG9ydCB7IGlzSW5Ccm93c2VyIH0gZnJvbSAnLi9zcmMvY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IFNjcm9sbE1vbml0b3JDb250YWluZXIgfSBmcm9tICcuL3NyYy9jb250YWluZXIuanMnO1xuLy8gdGhpcyBpcyBuZWVkZWQgZm9yIHRoZSB0eXBlLCBidXQgaWYgd2UncmUgbm90IGluIGEgYnJvd3NlciB0aGUgb25seVxuLy8gd2F5IGxpc3RlblRvRE9NIHdpbGwgYmUgY2FsbGVkIGlzIGlmIHlvdSBjYWxsIHNjcm9sbG1vbml0b3IuY3JlYXRlQ29udGFpbmVyXG4vLyBhbmQgeW91IGNhbid0IGRvIHRoYXQgdW50aWwgeW91IGhhdmUgYSBET00gZWxlbWVudC5cbnZhciBzY3JvbGxNb25pdG9yID0gbmV3IFNjcm9sbE1vbml0b3JDb250YWluZXIoaXNJbkJyb3dzZXIgPyBkb2N1bWVudC5ib2R5IDogdW5kZWZpbmVkKTtcbmlmIChpc0luQnJvd3Nlcikge1xuICAgIHNjcm9sbE1vbml0b3IudXBkYXRlU3RhdGUoKTtcbiAgICBzY3JvbGxNb25pdG9yLmxpc3RlblRvRE9NKCk7XG59XG4vL0B0cy1pZ25vcmVcbndpbmRvdy5zY3JvbGxNb25pdG9yID0gc2Nyb2xsTW9uaXRvcjtcbmV4cG9ydCBkZWZhdWx0IHNjcm9sbE1vbml0b3I7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5qcy5tYXAiLCJleHBvcnQgdmFyIFZJU0lCSUxJVFlDSEFOR0UgPSAndmlzaWJpbGl0eUNoYW5nZSc7XG5leHBvcnQgdmFyIEVOVEVSVklFV1BPUlQgPSAnZW50ZXJWaWV3cG9ydCc7XG5leHBvcnQgdmFyIEZVTExZRU5URVJWSUVXUE9SVCA9ICdmdWxseUVudGVyVmlld3BvcnQnO1xuZXhwb3J0IHZhciBFWElUVklFV1BPUlQgPSAnZXhpdFZpZXdwb3J0JztcbmV4cG9ydCB2YXIgUEFSVElBTExZRVhJVFZJRVdQT1JUID0gJ3BhcnRpYWxseUV4aXRWaWV3cG9ydCc7XG5leHBvcnQgdmFyIExPQ0FUSU9OQ0hBTkdFID0gJ2xvY2F0aW9uQ2hhbmdlJztcbmV4cG9ydCB2YXIgU1RBVEVDSEFOR0UgPSAnc3RhdGVDaGFuZ2UnO1xuZXhwb3J0IHZhciBldmVudFR5cGVzID0gW1xuICAgIFZJU0lCSUxJVFlDSEFOR0UsXG4gICAgRU5URVJWSUVXUE9SVCxcbiAgICBGVUxMWUVOVEVSVklFV1BPUlQsXG4gICAgRVhJVFZJRVdQT1JULFxuICAgIFBBUlRJQUxMWUVYSVRWSUVXUE9SVCxcbiAgICBMT0NBVElPTkNIQU5HRSxcbiAgICBTVEFURUNIQU5HRSxcbl07XG5leHBvcnQgdmFyIGlzT25TZXJ2ZXIgPSB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJztcbmV4cG9ydCB2YXIgaXNJbkJyb3dzZXIgPSAhaXNPblNlcnZlcjtcbmV4cG9ydCB2YXIgZGVmYXVsdE9mZnNldHMgPSB7IHRvcDogMCwgYm90dG9tOiAwIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jb25zdGFudHMuanMubWFwIiwiaW1wb3J0IHsgaXNPblNlcnZlciwgaXNJbkJyb3dzZXIsIGV2ZW50VHlwZXMgfSBmcm9tICcuL2NvbnN0YW50cy5qcyc7XG5pbXBvcnQgeyBXYXRjaGVyIH0gZnJvbSAnLi93YXRjaGVyLmpzJztcbmZ1bmN0aW9uIGdldFZpZXdwb3J0SGVpZ2h0KGVsZW1lbnQpIHtcbiAgICBpZiAoaXNPblNlcnZlcikge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgaWYgKGVsZW1lbnQgPT09IGRvY3VtZW50LmJvZHkpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5pbm5lckhlaWdodCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgIH1cbn1cbmZ1bmN0aW9uIGdldENvbnRlbnRIZWlnaHQoZWxlbWVudCkge1xuICAgIGlmIChpc09uU2VydmVyKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBpZiAoZWxlbWVudCA9PT0gZG9jdW1lbnQuYm9keSkge1xuICAgICAgICAvLyBqUXVlcnkgYXBwcm9hY2hcbiAgICAgICAgLy8gd2hpY2hldmVyIGlzIGdyZWF0ZXN0XG4gICAgICAgIHJldHVybiBNYXRoLm1heChkb2N1bWVudC5ib2R5LnNjcm9sbEhlaWdodCwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbEhlaWdodCwgZG9jdW1lbnQuYm9keS5vZmZzZXRIZWlnaHQsIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5vZmZzZXRIZWlnaHQsIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQuc2Nyb2xsSGVpZ2h0O1xuICAgIH1cbn1cbmZ1bmN0aW9uIHNjcm9sbFRvcChlbGVtZW50KSB7XG4gICAgaWYgKGlzT25TZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGlmIChlbGVtZW50ID09PSBkb2N1bWVudC5ib2R5KSB7XG4gICAgICAgIHJldHVybiAod2luZG93LnBhZ2VZT2Zmc2V0IHx8XG4gICAgICAgICAgICAoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3ApIHx8XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gZWxlbWVudC5zY3JvbGxUb3A7XG4gICAgfVxufVxudmFyIGJyb3dzZXJTdXBwb3J0c1Bhc3NpdmUgPSBmYWxzZTtcbmlmIChpc0luQnJvd3Nlcikge1xuICAgIHRyeSB7XG4gICAgICAgIHZhciBvcHRzID0gT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCAncGFzc2l2ZScsIHtcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGJyb3dzZXJTdXBwb3J0c1Bhc3NpdmUgPSB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd0ZXN0JywgbnVsbCwgb3B0cyk7XG4gICAgfVxuICAgIGNhdGNoIChlKSB7IH1cbn1cbnZhciB1c2VDYXB0dXJlID0gYnJvd3NlclN1cHBvcnRzUGFzc2l2ZSA/IHsgY2FwdHVyZTogZmFsc2UsIHBhc3NpdmU6IHRydWUgfSA6IGZhbHNlO1xudmFyIFNjcm9sbE1vbml0b3JDb250YWluZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gU2Nyb2xsTW9uaXRvckNvbnRhaW5lcihpdGVtLCBwYXJlbnRXYXRjaGVyKSB7XG4gICAgICAgIHRoaXMuZXZlbnRUeXBlcyA9IGV2ZW50VHlwZXM7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgdGhpcy5pdGVtID0gaXRlbTtcbiAgICAgICAgdGhpcy53YXRjaGVycyA9IFtdO1xuICAgICAgICB0aGlzLnZpZXdwb3J0VG9wID0gbnVsbDtcbiAgICAgICAgdGhpcy52aWV3cG9ydEJvdHRvbSA9IG51bGw7XG4gICAgICAgIHRoaXMuZG9jdW1lbnRIZWlnaHQgPSBnZXRDb250ZW50SGVpZ2h0KGl0ZW0pO1xuICAgICAgICB0aGlzLnZpZXdwb3J0SGVpZ2h0ID0gZ2V0Vmlld3BvcnRIZWlnaHQoaXRlbSk7XG4gICAgICAgIHRoaXMuRE9NTGlzdGVuZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBTY3JvbGxNb25pdG9yQ29udGFpbmVyLnByb3RvdHlwZS5ET01MaXN0ZW5lci5hcHBseShzZWxmLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAocGFyZW50V2F0Y2hlcikge1xuICAgICAgICAgICAgdGhpcy5jb250YWluZXJXYXRjaGVyID0gcGFyZW50V2F0Y2hlci5jcmVhdGUoaXRlbSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByZXZpb3VzRG9jdW1lbnRIZWlnaHQ7XG4gICAgICAgIHZhciBjYWxjdWxhdGVWaWV3cG9ydEk7XG4gICAgICAgIGZ1bmN0aW9uIGNhbGN1bGF0ZVZpZXdwb3J0KCkge1xuICAgICAgICAgICAgc2VsZi52aWV3cG9ydFRvcCA9IHNjcm9sbFRvcChpdGVtKTtcbiAgICAgICAgICAgIHNlbGYudmlld3BvcnRCb3R0b20gPSBzZWxmLnZpZXdwb3J0VG9wICsgc2VsZi52aWV3cG9ydEhlaWdodDtcbiAgICAgICAgICAgIHNlbGYuZG9jdW1lbnRIZWlnaHQgPSBnZXRDb250ZW50SGVpZ2h0KGl0ZW0pO1xuICAgICAgICAgICAgaWYgKHNlbGYuZG9jdW1lbnRIZWlnaHQgIT09IHByZXZpb3VzRG9jdW1lbnRIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBjYWxjdWxhdGVWaWV3cG9ydEkgPSBzZWxmLndhdGNoZXJzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB3aGlsZSAoY2FsY3VsYXRlVmlld3BvcnRJLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi53YXRjaGVyc1tjYWxjdWxhdGVWaWV3cG9ydEldLnJlY2FsY3VsYXRlTG9jYXRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJldmlvdXNEb2N1bWVudEhlaWdodCA9IHNlbGYuZG9jdW1lbnRIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHVwZGF0ZUFuZFRyaWdnZXJXYXRjaGVyc0k7XG4gICAgICAgIGZ1bmN0aW9uIHVwZGF0ZUFuZFRyaWdnZXJXYXRjaGVycygpIHtcbiAgICAgICAgICAgIC8vIHVwZGF0ZSBhbGwgd2F0Y2hlcnMgdGhlbiB0cmlnZ2VyIHRoZSBldmVudHMgc28gb25lIGNhbiByZWx5IG9uIGFub3RoZXIgYmVpbmcgdXAgdG8gZGF0ZS5cbiAgICAgICAgICAgIHVwZGF0ZUFuZFRyaWdnZXJXYXRjaGVyc0kgPSBzZWxmLndhdGNoZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlICh1cGRhdGVBbmRUcmlnZ2VyV2F0Y2hlcnNJLS0pIHtcbiAgICAgICAgICAgICAgICBzZWxmLndhdGNoZXJzW3VwZGF0ZUFuZFRyaWdnZXJXYXRjaGVyc0ldLnVwZGF0ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdXBkYXRlQW5kVHJpZ2dlcldhdGNoZXJzSSA9IHNlbGYud2F0Y2hlcnMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKHVwZGF0ZUFuZFRyaWdnZXJXYXRjaGVyc0ktLSkge1xuICAgICAgICAgICAgICAgIHNlbGYud2F0Y2hlcnNbdXBkYXRlQW5kVHJpZ2dlcldhdGNoZXJzSV0udHJpZ2dlckNhbGxiYWNrcyh1bmRlZmluZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY2FsY3VsYXRlVmlld3BvcnQoKTtcbiAgICAgICAgICAgIHVwZGF0ZUFuZFRyaWdnZXJXYXRjaGVycygpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnJlY2FsY3VsYXRlTG9jYXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5kb2N1bWVudEhlaWdodCA9IDA7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBTY3JvbGxNb25pdG9yQ29udGFpbmVyLnByb3RvdHlwZS5saXN0ZW5Ub0RPTSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGlzSW5Ccm93c2VyKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pdGVtID09PSBkb2N1bWVudC5ib2R5KSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuRE9NTGlzdGVuZXIsIHVzZUNhcHR1cmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pdGVtLmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuRE9NTGlzdGVuZXIsIHVzZUNhcHR1cmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMuRE9NTGlzdGVuZXIpO1xuICAgICAgICAgICAgdGhpcy5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLml0ZW0gPT09IGRvY3VtZW50LmJvZHkpIHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuRE9NTGlzdGVuZXIsIHVzZUNhcHR1cmUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lcldhdGNoZXIuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pdGVtLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuRE9NTGlzdGVuZXIsIHVzZUNhcHR1cmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5ET01MaXN0ZW5lcik7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTY3JvbGxNb25pdG9yQ29udGFpbmVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBub29wLCBvdmVycmlkZSBmb3IgeW91ciBvd24gcHVycG9zZXMuXG4gICAgICAgIC8vIGluIGxpc3RlblRvRE9NLCBmb3IgZXhhbXBsZS5cbiAgICB9O1xuICAgIFNjcm9sbE1vbml0b3JDb250YWluZXIucHJvdG90eXBlLkRPTUxpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIC8vYWxlcnQoJ2dvdCBzY3JvbGwnKTtcbiAgICAgICAgdGhpcy51cGRhdGVTdGF0ZSgpO1xuICAgICAgICB0aGlzLnVwZGF0ZUFuZFRyaWdnZXJXYXRjaGVycyhldmVudCk7XG4gICAgfTtcbiAgICBTY3JvbGxNb25pdG9yQ29udGFpbmVyLnByb3RvdHlwZS51cGRhdGVTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHZpZXdwb3J0VG9wID0gc2Nyb2xsVG9wKHRoaXMuaXRlbSk7XG4gICAgICAgIHZhciB2aWV3cG9ydEhlaWdodCA9IGdldFZpZXdwb3J0SGVpZ2h0KHRoaXMuaXRlbSk7XG4gICAgICAgIHZhciBjb250ZW50SGVpZ2h0ID0gZ2V0Q29udGVudEhlaWdodCh0aGlzLml0ZW0pO1xuICAgICAgICB2YXIgbmVlZHNSZWNhbGN1YXRlID0gdmlld3BvcnRIZWlnaHQgIT09IHRoaXMudmlld3BvcnRIZWlnaHQgfHwgY29udGVudEhlaWdodCAhPT0gdGhpcy5jb250ZW50SGVpZ2h0O1xuICAgICAgICB0aGlzLnZpZXdwb3J0VG9wID0gdmlld3BvcnRUb3A7XG4gICAgICAgIHRoaXMudmlld3BvcnRIZWlnaHQgPSB2aWV3cG9ydEhlaWdodDtcbiAgICAgICAgdGhpcy52aWV3cG9ydEJvdHRvbSA9IHZpZXdwb3J0VG9wICsgdmlld3BvcnRIZWlnaHQ7XG4gICAgICAgIHRoaXMuY29udGVudEhlaWdodCA9IGNvbnRlbnRIZWlnaHQ7XG4gICAgICAgIGlmIChuZWVkc1JlY2FsY3VhdGUpIHtcbiAgICAgICAgICAgIHZhciBpID0gdGhpcy53YXRjaGVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53YXRjaGVyc1tpXS5yZWNhbGN1bGF0ZUxvY2F0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNjcm9sbE1vbml0b3JDb250YWluZXIucHJvdG90eXBlLnVwZGF0ZUFuZFRyaWdnZXJXYXRjaGVycyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgaSA9IHRoaXMud2F0Y2hlcnMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICB0aGlzLndhdGNoZXJzW2ldLnVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgICAgIGkgPSB0aGlzLndhdGNoZXJzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgdGhpcy53YXRjaGVyc1tpXS50cmlnZ2VyQ2FsbGJhY2tzKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2Nyb2xsTW9uaXRvckNvbnRhaW5lci5wcm90b3R5cGUuY3JlYXRlQ29udGFpbmVyID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHZhciBpdGVtO1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaXRlbSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoaW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpIHx8IGlucHV0IGluc3RhbmNlb2YgTm9kZUxpc3QpIHtcbiAgICAgICAgICAgIGl0ZW0gPSBpbnB1dFswXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGl0ZW0gPSBpbnB1dDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29udGFpbmVyID0gbmV3IFNjcm9sbE1vbml0b3JDb250YWluZXIoaXRlbSwgdGhpcyk7XG4gICAgICAgIHRoaXMudXBkYXRlU3RhdGUoKTtcbiAgICAgICAgY29udGFpbmVyLmxpc3RlblRvRE9NKCk7XG4gICAgICAgIHJldHVybiBjb250YWluZXI7XG4gICAgfTtcbiAgICBTY3JvbGxNb25pdG9yQ29udGFpbmVyLnByb3RvdHlwZS5jcmVhdGUgPSBmdW5jdGlvbiAoaW5wdXQsIG9mZnNldHMpIHtcbiAgICAgICAgdmFyIGl0ZW07XG4gICAgICAgIGlmICh0eXBlb2YgaXRlbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGl0ZW0gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGl0ZW0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpIHx8IGlucHV0IGluc3RhbmNlb2YgTm9kZUxpc3QpIHtcbiAgICAgICAgICAgIGl0ZW0gPSBpbnB1dFswXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGl0ZW0gPSBpbnB1dDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgd2F0Y2hlciA9IG5ldyBXYXRjaGVyKHRoaXMsIGl0ZW0sIG9mZnNldHMpO1xuICAgICAgICB0aGlzLndhdGNoZXJzLnB1c2god2F0Y2hlcik7XG4gICAgICAgIHJldHVybiB3YXRjaGVyO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgc2luY2UgdmVyc2lvbiAxLjFcbiAgICAgKi9cbiAgICBTY3JvbGxNb25pdG9yQ29udGFpbmVyLnByb3RvdHlwZS5iZWdldCA9IGZ1bmN0aW9uIChpbnB1dCwgb2Zmc2V0cykge1xuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGUoaW5wdXQsIG9mZnNldHMpO1xuICAgIH07XG4gICAgcmV0dXJuIFNjcm9sbE1vbml0b3JDb250YWluZXI7XG59KCkpO1xuZXhwb3J0IHsgU2Nyb2xsTW9uaXRvckNvbnRhaW5lciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29udGFpbmVyLmpzLm1hcCIsImV4cG9ydCB7fTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXR5cGVzLmpzLm1hcCIsImltcG9ydCB7IFZJU0lCSUxJVFlDSEFOR0UsIEVOVEVSVklFV1BPUlQsIEZVTExZRU5URVJWSUVXUE9SVCwgRVhJVFZJRVdQT1JULCBQQVJUSUFMTFlFWElUVklFV1BPUlQsIExPQ0FUSU9OQ0hBTkdFLCBTVEFURUNIQU5HRSwgZXZlbnRUeXBlcywgZGVmYXVsdE9mZnNldHMsIH0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xudmFyIFdhdGNoZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gV2F0Y2hlcihjb250YWluZXIsIHdhdGNoSXRlbSwgb2Zmc2V0cykge1xuICAgICAgICB0aGlzLmNvbnRhaW5lciA9IGNvbnRhaW5lcjtcbiAgICAgICAgdGhpcy53YXRjaEl0ZW0gPSB3YXRjaEl0ZW07XG4gICAgICAgIHRoaXMubG9ja2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0ge307XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKCFvZmZzZXRzKSB7XG4gICAgICAgICAgICB0aGlzLm9mZnNldHMgPSBkZWZhdWx0T2Zmc2V0cztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2Zmc2V0cyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0cyA9IHsgdG9wOiBvZmZzZXRzLCBib3R0b206IG9mZnNldHMgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0cyA9IHtcbiAgICAgICAgICAgICAgICB0b3A6ICd0b3AnIGluIG9mZnNldHMgPyBvZmZzZXRzLnRvcCA6IGRlZmF1bHRPZmZzZXRzLnRvcCxcbiAgICAgICAgICAgICAgICBib3R0b206ICdib3R0b20nIGluIG9mZnNldHMgPyBvZmZzZXRzLmJvdHRvbSA6IGRlZmF1bHRPZmZzZXRzLmJvdHRvbSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGogPSBldmVudFR5cGVzLmxlbmd0aDsgaSA8IGo7IGkrKykge1xuICAgICAgICAgICAgc2VsZi5jYWxsYmFja3NbZXZlbnRUeXBlc1tpXV0gPSBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxvY2tlZCA9IGZhbHNlO1xuICAgICAgICB2YXIgd2FzSW5WaWV3cG9ydDtcbiAgICAgICAgdmFyIHdhc0Z1bGx5SW5WaWV3cG9ydDtcbiAgICAgICAgdmFyIHdhc0Fib3ZlVmlld3BvcnQ7XG4gICAgICAgIHZhciB3YXNCZWxvd1ZpZXdwb3J0O1xuICAgICAgICB2YXIgbGlzdGVuZXJUb1RyaWdnZXJMaXN0STtcbiAgICAgICAgdmFyIGxpc3RlbmVyO1xuICAgICAgICB2YXIgbmVlZFRvVHJpZ2dlclN0YXRlQ2hhbmdlID0gZmFsc2U7XG4gICAgICAgIGZ1bmN0aW9uIHRyaWdnZXJDYWxsYmFja0FycmF5KGxpc3RlbmVycywgZXZlbnQpIHtcbiAgICAgICAgICAgIG5lZWRUb1RyaWdnZXJTdGF0ZUNoYW5nZSA9IHRydWU7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpc3RlbmVyVG9UcmlnZ2VyTGlzdEkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGxpc3RlbmVyVG9UcmlnZ2VyTGlzdEktLSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyID0gbGlzdGVuZXJzW2xpc3RlbmVyVG9UcmlnZ2VyTGlzdEldO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLmNhbGxiYWNrLmNhbGwoc2VsZiwgZXZlbnQsIHNlbGYpO1xuICAgICAgICAgICAgICAgIGlmIChsaXN0ZW5lci5pc09uZSkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnMuc3BsaWNlKGxpc3RlbmVyVG9UcmlnZ2VyTGlzdEksIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRyaWdnZXJDYWxsYmFja3MgPSBmdW5jdGlvbiB0cmlnZ2VyQ2FsbGJhY2tzKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0luVmlld3BvcnQgJiYgIXdhc0luVmlld3BvcnQpIHtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyQ2FsbGJhY2tBcnJheSh0aGlzLmNhbGxiYWNrc1tFTlRFUlZJRVdQT1JUXSwgZXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNGdWxseUluVmlld3BvcnQgJiYgIXdhc0Z1bGx5SW5WaWV3cG9ydCkge1xuICAgICAgICAgICAgICAgIHRyaWdnZXJDYWxsYmFja0FycmF5KHRoaXMuY2FsbGJhY2tzW0ZVTExZRU5URVJWSUVXUE9SVF0sIGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzQWJvdmVWaWV3cG9ydCAhPT0gd2FzQWJvdmVWaWV3cG9ydCAmJlxuICAgICAgICAgICAgICAgIHRoaXMuaXNCZWxvd1ZpZXdwb3J0ICE9PSB3YXNCZWxvd1ZpZXdwb3J0KSB7XG4gICAgICAgICAgICAgICAgdHJpZ2dlckNhbGxiYWNrQXJyYXkodGhpcy5jYWxsYmFja3NbVklTSUJJTElUWUNIQU5HRV0sIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAvLyBpZiB5b3Ugc2tpcCBjb21wbGV0ZWx5IHBhc3QgdGhpcyBlbGVtZW50XG4gICAgICAgICAgICAgICAgaWYgKCF3YXNGdWxseUluVmlld3BvcnQgJiYgIXRoaXMuaXNGdWxseUluVmlld3BvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckNhbGxiYWNrQXJyYXkodGhpcy5jYWxsYmFja3NbRlVMTFlFTlRFUlZJRVdQT1JUXSwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyQ2FsbGJhY2tBcnJheSh0aGlzLmNhbGxiYWNrc1tQQVJUSUFMTFlFWElUVklFV1BPUlRdLCBldmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghd2FzSW5WaWV3cG9ydCAmJiAhdGhpcy5pc0luVmlld3BvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckNhbGxiYWNrQXJyYXkodGhpcy5jYWxsYmFja3NbRU5URVJWSUVXUE9SVF0sIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckNhbGxiYWNrQXJyYXkodGhpcy5jYWxsYmFja3NbRVhJVFZJRVdQT1JUXSwgZXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5pc0Z1bGx5SW5WaWV3cG9ydCAmJiB3YXNGdWxseUluVmlld3BvcnQpIHtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyQ2FsbGJhY2tBcnJheSh0aGlzLmNhbGxiYWNrc1tQQVJUSUFMTFlFWElUVklFV1BPUlRdLCBldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNJblZpZXdwb3J0ICYmIHdhc0luVmlld3BvcnQpIHtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyQ2FsbGJhY2tBcnJheSh0aGlzLmNhbGxiYWNrc1tFWElUVklFV1BPUlRdLCBldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc0luVmlld3BvcnQgIT09IHdhc0luVmlld3BvcnQpIHtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyQ2FsbGJhY2tBcnJheSh0aGlzLmNhbGxiYWNrc1tWSVNJQklMSVRZQ0hBTkdFXSwgZXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5lZWRUb1RyaWdnZXJTdGF0ZUNoYW5nZSkge1xuICAgICAgICAgICAgICAgIG5lZWRUb1RyaWdnZXJTdGF0ZUNoYW5nZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRyaWdnZXJDYWxsYmFja0FycmF5KHRoaXMuY2FsbGJhY2tzW1NUQVRFQ0hBTkdFXSwgZXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2FzSW5WaWV3cG9ydCA9IHRoaXMuaXNJblZpZXdwb3J0O1xuICAgICAgICAgICAgd2FzRnVsbHlJblZpZXdwb3J0ID0gdGhpcy5pc0Z1bGx5SW5WaWV3cG9ydDtcbiAgICAgICAgICAgIHdhc0Fib3ZlVmlld3BvcnQgPSB0aGlzLmlzQWJvdmVWaWV3cG9ydDtcbiAgICAgICAgICAgIHdhc0JlbG93Vmlld3BvcnQgPSB0aGlzLmlzQmVsb3dWaWV3cG9ydDtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5yZWNhbGN1bGF0ZUxvY2F0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubG9ja2VkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHByZXZpb3VzVG9wID0gdGhpcy50b3A7XG4gICAgICAgICAgICB2YXIgcHJldmlvdXNCb3R0b20gPSB0aGlzLmJvdHRvbTtcbiAgICAgICAgICAgIGlmICh0aGlzLndhdGNoSXRlbS5ub2RlTmFtZSkge1xuICAgICAgICAgICAgICAgIC8vIGEgZG9tIGVsZW1lbnRcbiAgICAgICAgICAgICAgICB2YXIgY2FjaGVkRGlzcGxheSA9IHRoaXMud2F0Y2hJdGVtLnN0eWxlLmRpc3BsYXk7XG4gICAgICAgICAgICAgICAgaWYgKGNhY2hlZERpc3BsYXkgPT09ICdub25lJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndhdGNoSXRlbS5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBjb250YWluZXJPZmZzZXQgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lcjtcbiAgICAgICAgICAgICAgICB3aGlsZSAoY29udGFpbmVyLmNvbnRhaW5lcldhdGNoZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyT2Zmc2V0ICs9XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuY29udGFpbmVyV2F0Y2hlci50b3AgLVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lci5jb250YWluZXJXYXRjaGVyLmNvbnRhaW5lci52aWV3cG9ydFRvcDtcbiAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyID0gY29udGFpbmVyLmNvbnRhaW5lcldhdGNoZXIuY29udGFpbmVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgYm91bmRpbmdSZWN0ID0gdGhpcy53YXRjaEl0ZW0uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy50b3AgPSBib3VuZGluZ1JlY3QudG9wICsgdGhpcy5jb250YWluZXIudmlld3BvcnRUb3AgLSBjb250YWluZXJPZmZzZXQ7XG4gICAgICAgICAgICAgICAgdGhpcy5ib3R0b20gPSBib3VuZGluZ1JlY3QuYm90dG9tICsgdGhpcy5jb250YWluZXIudmlld3BvcnRUb3AgLSBjb250YWluZXJPZmZzZXQ7XG4gICAgICAgICAgICAgICAgaWYgKGNhY2hlZERpc3BsYXkgPT09ICdub25lJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndhdGNoSXRlbS5zdHlsZS5kaXNwbGF5ID0gY2FjaGVkRGlzcGxheTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLndhdGNoSXRlbSA9PT0gK3RoaXMud2F0Y2hJdGVtKSB7XG4gICAgICAgICAgICAgICAgLy8gbnVtYmVyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2F0Y2hJdGVtID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRvcCA9IHRoaXMuYm90dG9tID0gdGhpcy53YXRjaEl0ZW07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRvcCA9IHRoaXMuYm90dG9tID0gdGhpcy5jb250YWluZXIuZG9jdW1lbnRIZWlnaHQgLSB0aGlzLndhdGNoSXRlbTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBhbiBvYmplY3Qgd2l0aCBhIHRvcCBhbmQgYm90dG9tIHByb3BlcnR5XG4gICAgICAgICAgICAgICAgdGhpcy50b3AgPSB0aGlzLndhdGNoSXRlbS50b3A7XG4gICAgICAgICAgICAgICAgdGhpcy5ib3R0b20gPSB0aGlzLndhdGNoSXRlbS5ib3R0b207XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnRvcCAtPSB0aGlzLm9mZnNldHMudG9wO1xuICAgICAgICAgICAgdGhpcy5ib3R0b20gKz0gdGhpcy5vZmZzZXRzLmJvdHRvbTtcbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gdGhpcy5ib3R0b20gLSB0aGlzLnRvcDtcbiAgICAgICAgICAgIGlmICgocHJldmlvdXNUb3AgIT09IHVuZGVmaW5lZCB8fCBwcmV2aW91c0JvdHRvbSAhPT0gdW5kZWZpbmVkKSAmJlxuICAgICAgICAgICAgICAgICh0aGlzLnRvcCAhPT0gcHJldmlvdXNUb3AgfHwgdGhpcy5ib3R0b20gIT09IHByZXZpb3VzQm90dG9tKSkge1xuICAgICAgICAgICAgICAgIHRyaWdnZXJDYWxsYmFja0FycmF5KHRoaXMuY2FsbGJhY2tzW0xPQ0FUSU9OQ0hBTkdFXSwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5yZWNhbGN1bGF0ZUxvY2F0aW9uKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgICAgIHdhc0luVmlld3BvcnQgPSB0aGlzLmlzSW5WaWV3cG9ydDtcbiAgICAgICAgd2FzRnVsbHlJblZpZXdwb3J0ID0gdGhpcy5pc0Z1bGx5SW5WaWV3cG9ydDtcbiAgICAgICAgd2FzQWJvdmVWaWV3cG9ydCA9IHRoaXMuaXNBYm92ZVZpZXdwb3J0O1xuICAgICAgICB3YXNCZWxvd1ZpZXdwb3J0ID0gdGhpcy5pc0JlbG93Vmlld3BvcnQ7XG4gICAgfVxuICAgIFdhdGNoZXIucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50LCBjYWxsYmFjaywgaXNPbmUpIHtcbiAgICAgICAgaWYgKGlzT25lID09PSB2b2lkIDApIHsgaXNPbmUgPSBmYWxzZTsgfVxuICAgICAgICAvLyB0cmlnZ2VyIHRoZSBldmVudCBpZiBpdCBhcHBsaWVzIHRvIHRoZSBlbGVtZW50IHJpZ2h0IG5vdy5cbiAgICAgICAgc3dpdGNoICh0cnVlKSB7XG4gICAgICAgICAgICBjYXNlIGV2ZW50ID09PSBWSVNJQklMSVRZQ0hBTkdFICYmICF0aGlzLmlzSW5WaWV3cG9ydCAmJiB0aGlzLmlzQWJvdmVWaWV3cG9ydDpcbiAgICAgICAgICAgIGNhc2UgZXZlbnQgPT09IEVOVEVSVklFV1BPUlQgJiYgdGhpcy5pc0luVmlld3BvcnQ6XG4gICAgICAgICAgICBjYXNlIGV2ZW50ID09PSBGVUxMWUVOVEVSVklFV1BPUlQgJiYgdGhpcy5pc0Z1bGx5SW5WaWV3cG9ydDpcbiAgICAgICAgICAgIGNhc2UgZXZlbnQgPT09IEVYSVRWSUVXUE9SVCAmJiB0aGlzLmlzQWJvdmVWaWV3cG9ydCAmJiAhdGhpcy5pc0luVmlld3BvcnQ6XG4gICAgICAgICAgICBjYXNlIGV2ZW50ID09PSBQQVJUSUFMTFlFWElUVklFV1BPUlQgJiYgdGhpcy5pc0luVmlld3BvcnQgJiYgdGhpcy5pc0Fib3ZlVmlld3BvcnQ6XG4gICAgICAgICAgICAgICAgY2FsbGJhY2suY2FsbCh0aGlzLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNPbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5jYWxsYmFja3NbZXZlbnRdKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrc1tldmVudF0ucHVzaCh7IGNhbGxiYWNrOiBjYWxsYmFjaywgaXNPbmU6IGlzT25lIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUcmllZCB0byBhZGQgYSBzY3JvbGwgbW9uaXRvciBsaXN0ZW5lciBvZiB0eXBlICcgK1xuICAgICAgICAgICAgICAgIGV2ZW50ICtcbiAgICAgICAgICAgICAgICAnLiBZb3VyIG9wdGlvbnMgYXJlOiAnICtcbiAgICAgICAgICAgICAgICBldmVudFR5cGVzLmpvaW4oJywgJykpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBXYXRjaGVyLnByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGNhbGxiYWNrKSB7XG4gICAgICAgIGlmICh0aGlzLmNhbGxiYWNrc1tldmVudF0pIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpdGVtOyAoaXRlbSA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XVtpXSk7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChpdGVtLmNhbGxiYWNrID09PSBjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrc1tldmVudF0uc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyaWVkIHRvIHJlbW92ZSBhIHNjcm9sbCBtb25pdG9yIGxpc3RlbmVyIG9mIHR5cGUgJyArXG4gICAgICAgICAgICAgICAgZXZlbnQgK1xuICAgICAgICAgICAgICAgICcuIFlvdXIgb3B0aW9ucyBhcmU6ICcgK1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZXMuam9pbignLCAnKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFdhdGNoZXIucHJvdG90eXBlLm9uZSA9IGZ1bmN0aW9uIChldmVudCwgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5vbihldmVudCwgY2FsbGJhY2ssIHRydWUpO1xuICAgIH07XG4gICAgV2F0Y2hlci5wcm90b3R5cGUucmVjYWxjdWxhdGVTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy53YXRjaEl0ZW0gaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLndhdGNoSXRlbS5vZmZzZXRIZWlnaHQgKyB0aGlzLm9mZnNldHMudG9wICsgdGhpcy5vZmZzZXRzLmJvdHRvbTtcbiAgICAgICAgICAgIHRoaXMuYm90dG9tID0gdGhpcy50b3AgKyB0aGlzLmhlaWdodDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgV2F0Y2hlci5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmlzQWJvdmVWaWV3cG9ydCA9IHRoaXMudG9wIDwgdGhpcy5jb250YWluZXIudmlld3BvcnRUb3A7XG4gICAgICAgIHRoaXMuaXNCZWxvd1ZpZXdwb3J0ID0gdGhpcy5ib3R0b20gPiB0aGlzLmNvbnRhaW5lci52aWV3cG9ydEJvdHRvbTtcbiAgICAgICAgdGhpcy5pc0luVmlld3BvcnQgPVxuICAgICAgICAgICAgdGhpcy50b3AgPCB0aGlzLmNvbnRhaW5lci52aWV3cG9ydEJvdHRvbSAmJiB0aGlzLmJvdHRvbSA+IHRoaXMuY29udGFpbmVyLnZpZXdwb3J0VG9wO1xuICAgICAgICB0aGlzLmlzRnVsbHlJblZpZXdwb3J0ID1cbiAgICAgICAgICAgICh0aGlzLnRvcCA+PSB0aGlzLmNvbnRhaW5lci52aWV3cG9ydFRvcCAmJlxuICAgICAgICAgICAgICAgIHRoaXMuYm90dG9tIDw9IHRoaXMuY29udGFpbmVyLnZpZXdwb3J0Qm90dG9tKSB8fFxuICAgICAgICAgICAgICAgICh0aGlzLmlzQWJvdmVWaWV3cG9ydCAmJiB0aGlzLmlzQmVsb3dWaWV3cG9ydCk7XG4gICAgfTtcbiAgICBXYXRjaGVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5kZXggPSB0aGlzLmNvbnRhaW5lci53YXRjaGVycy5pbmRleE9mKHRoaXMpLCBzZWxmID0gdGhpcztcbiAgICAgICAgdGhpcy5jb250YWluZXIud2F0Y2hlcnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgc2VsZi5jYWxsYmFja3MgPSB7fTtcbiAgICB9O1xuICAgIC8vIHByZXZlbnQgcmVjYWxjdWxhdGluZyB0aGUgZWxlbWVudCBsb2NhdGlvblxuICAgIFdhdGNoZXIucHJvdG90eXBlLmxvY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMubG9ja2VkID0gdHJ1ZTtcbiAgICB9O1xuICAgIFdhdGNoZXIucHJvdG90eXBlLnVubG9jayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5sb2NrZWQgPSBmYWxzZTtcbiAgICB9O1xuICAgIHJldHVybiBXYXRjaGVyO1xufSgpKTtcbmV4cG9ydCB7IFdhdGNoZXIgfTtcbnZhciBldmVudEhhbmRsZXJGYWN0b3J5ID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGNhbGxiYWNrLCBpc09uZSkge1xuICAgICAgICBpZiAoaXNPbmUgPT09IHZvaWQgMCkgeyBpc09uZSA9IGZhbHNlOyB9XG4gICAgICAgIHRoaXMub24uY2FsbCh0aGlzLCB0eXBlLCBjYWxsYmFjaywgaXNPbmUpO1xuICAgIH07XG59O1xuZm9yICh2YXIgaSA9IDAsIGogPSBldmVudFR5cGVzLmxlbmd0aDsgaSA8IGo7IGkrKykge1xuICAgIHZhciB0eXBlID0gZXZlbnRUeXBlc1tpXTtcbiAgICBXYXRjaGVyLnByb3RvdHlwZVt0eXBlXSA9IGV2ZW50SGFuZGxlckZhY3RvcnkodHlwZSk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD13YXRjaGVyLmpzLm1hcCIsImltcG9ydCB7IENvbnNvbGVXcml0ZXIsIFNwbGl0U3RyZWFtV3JpdGVyIH0gZnJvbSBcIi4vd3JpdGVyc1wiO1xuaW1wb3J0IHsgQ29uc29sZVRyYW5zcG9ydCwgVHJhbnNwb3J0TG9nZ2VyIH0gZnJvbSBcIi4vbG9nZ2VyXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4vdXRpbHNcIjtcbi8qKlxuICogRGVmYXVsdCBhc3NlbWJseSBwb2ludCBvZiBjb2xsZWN0b3JzIGFuZCB3cml0ZXJzLlxuICovXG5leHBvcnQgY2xhc3MgQ29sbGVjdG9yTW9kdWxlIHtcbiAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuY29sbGVjdG9ycyA9IFtdO1xuICAgICAgICB0aGlzLndyaXRlcnMgPSBbXTtcbiAgICAgICAgdGhpcy50cmFuc3BvcnRzID0gW107XG4gICAgICAgIHRoaXMuaGFzU3RhcnRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIH1cbiAgICBhZGQoY29sbGVjdG9yKSB7XG4gICAgICAgIGlmICghY29sbGVjdG9yLmdldENvbnRleHQoKSlcbiAgICAgICAgICAgIGNvbGxlY3Rvci5zZXRDb250ZXh0KHRoaXMub3B0aW9ucy5jb250ZXh0IHx8IG5ldyBDb250ZXh0KHdpbmRvdywgZG9jdW1lbnQpKTtcbiAgICAgICAgdGhpcy5jb2xsZWN0b3JzLnB1c2goY29sbGVjdG9yKTtcbiAgICAgICAgaWYgKHRoaXMuaGFzU3RhcnRlZCA9PT0gdHJ1ZSlcbiAgICAgICAgICAgIHRoaXMuaW52b2tlZENvbGxlY3Rvcihjb2xsZWN0b3IpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTdGFydCBjb2xsZWN0aW5nIGRhdGEgYnkgYXR0YWNoaW5nIGFsbCBjb2xsZWN0b3JzXG4gICAgICovXG4gICAgc3RhcnQoKSB7XG4gICAgICAgIHRoaXMuY29sbGVjdG9ycy5mb3JFYWNoKGNvbGxlY3RvciA9PiB0aGlzLmludm9rZWRDb2xsZWN0b3IoY29sbGVjdG9yKSk7XG4gICAgICAgIHRoaXMuaGFzU3RhcnRlZCA9IHRydWU7XG4gICAgfVxuICAgIGFkZExvZ1RyYW5zcG9ydCh0cmFuc3BvcnQpIHtcbiAgICAgICAgdGhpcy50cmFuc3BvcnRzLnB1c2godHJhbnNwb3J0KTtcbiAgICB9XG4gICAgc2V0VHJhbnNwb3J0cyh0cmFuc3BvcnRzKSB7XG4gICAgICAgIHRoaXMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHMgfHwgW107XG4gICAgfVxuICAgIHNldFdyaXRlcnMocmVwbGFjZW1lbnRXcml0ZXJzKSB7XG4gICAgICAgIHRoaXMud3JpdGVycyA9IEFycmF5LmlzQXJyYXkocmVwbGFjZW1lbnRXcml0ZXJzKSA/IFsuLi5yZXBsYWNlbWVudFdyaXRlcnNdIDogW3JlcGxhY2VtZW50V3JpdGVyc107XG4gICAgfVxuICAgIHNldExvZ2dlcihsb2dnZXIpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBsb2dnZXI7XG4gICAgfVxuICAgIGludm9rZWRDb2xsZWN0b3IoY29sbGVjdG9yKSB7XG4gICAgICAgIGNvbnN0IHdyaXRlciA9IHRoaXMuZ2V0V3JpdGVyKCk7XG4gICAgICAgIGNvbnN0IGxvZyA9IHRoaXMuZ2V0TG9nZ2VyKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb2xsZWN0b3IuYXR0YWNoKHdyaXRlciwgbG9nKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgbG9nLmVycm9yKGBbJHtjb2xsZWN0b3IuY29uc3RydWN0b3IubmFtZX1dIFVuZXhwZWN0ZWQgRXhjZXB0aW9uIGR1cmluZyBjb2xsZWN0b3IgYXR0YWNoOiBgLCBlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXRMb2dnZXIoKSB7XG4gICAgICAgIGNvbnN0IGhhc0xvZ2dlciA9ICEhdGhpcy5sb2dnZXI7XG4gICAgICAgIGlmIChoYXNMb2dnZXIpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2dnZXI7XG4gICAgICAgIGlmICghdGhpcy50cmFuc3BvcnRzIHx8IHRoaXMudHJhbnNwb3J0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgVHJhbnNwb3J0TG9nZ2VyKFtuZXcgQ29uc29sZVRyYW5zcG9ydCgpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBUcmFuc3BvcnRMb2dnZXIodGhpcy50cmFuc3BvcnRzKTtcbiAgICB9XG4gICAgZ2V0V3JpdGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53cml0ZXJzLmxlbmd0aCA9PSAwXG4gICAgICAgICAgICA/IHRoaXMub3B0aW9ucy53cml0ZXIgfHwgbmV3IENvbnNvbGVXcml0ZXIoKVxuICAgICAgICAgICAgOiBuZXcgU3BsaXRTdHJlYW1Xcml0ZXIodGhpcy53cml0ZXJzKTtcbiAgICB9XG59XG4iLCJleHBvcnQgY2xhc3MgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIGNvbnN0cnVjdG9yKHR5cGUsIGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICB9XG4gICAgZ2V0VHlwZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudHlwZTtcbiAgICB9XG4gICAgc2V0Q29udGV4dChjb250ZXh0KSB7XG4gICAgICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgfVxuICAgIGdldENvbnRleHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQ7XG4gICAgfVxuICAgIGdldFdpbmRvdygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGV4dC5nZXRXaW5kb3coKTtcbiAgICB9XG4gICAgZ2V0RG9jdW1lbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQuZ2V0RG9jdW1lbnQoKTtcbiAgICB9XG4gICAgYXR0YWNoKHdyaXRlciwgbG9nKSB7XG4gICAgICAgIC8vIG92ZXJyaWRlIGluIHN1YmNsYXNzXG4gICAgfVxuICAgIC8qKlxuICAgICAqIFVzZWQgdG8gbG9nIGlmIGEgaGFuZGxlciBmYWlscyBpdHMgZXhlY3V0aW9uXG4gICAgICogVXNhZ2U6IGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCB0aGlzLmxvZ1dyYXBIYW5kbGVyKHlvdXJoYW5kbGVyLCBsb2dnZXIpKVxuICAgICAqIEBwYXJhbSBoYW5kbGVyXG4gICAgICogQHBhcmFtIGxvZ1xuICAgICAqIEBwYXJhbSBoYW5kbGVyQXJnc1xuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKi9cbiAgICBsb2dXcmFwSGFuZGxlcihoYW5kbGVyLCBsb2csIC4uLmhhbmRsZXJBcmdzKSB7XG4gICAgICAgIHJldHVybiAoLi4uYXJncykgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlciguLi5hcmdzLCAuLi5oYW5kbGVyQXJncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChsb2cpXG4gICAgICAgICAgICAgICAgICAgIGxvZy5lcnJvcihgWyR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfV0gVW5leHBlY3RlZCBlcnJvciBkdXJpbmcgcmVzb2x2ZXIgZXhlY3V0aW9uOiBgLCBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVXNlZCB0byBleGVjdXRlIHJlc29sdmVyIGZ1bmN0aW9ucy5cbiAgICAgKiBMb2dzIGEgZGVidWcgbWVzc2FnZSBpZiB0aGUgdmFsdWUgaXMgdW5kZWZpbmVkIG9yIGxvZ3MgYW4gZXJyb3IgaWYgYW4gZXhjZXB0aW9uIGlzIHRocm93biBieSB0aGUgcmVzb2x2ZXJcbiAgICAgKiBAcGFyYW0gcmVzb2x2ZXIgQSByZXNvbHZlciBmdW5jdGlvblxuICAgICAqIEBwYXJhbSBsb2cgdGhlIGxvZ2dlclxuICAgICAqIEBwYXJhbSByZXNvbHZlckFyZ3MgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byB0aGUgcmVzb2x2ZXIgZnVuY3Rpb25cbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICovXG4gICAgcmVzb2x2ZShyZXNvbHZlciwgbG9nLCAuLi5yZXNvbHZlckFyZ3MpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyZXNvbHZlcikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbCA9IHJlc29sdmVyKC4uLnJlc29sdmVyQXJncyk7XG4gICAgICAgICAgICAgICAgaWYgKHZhbCA9PSB2b2lkIDApXG4gICAgICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIlJlc29sdmVyIHJldHVybmVkIG5vIHZhbHVlLlwiLCByZXNvbHZlcik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgaWYgKGxvZyAmJiBsb2cuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBsb2cuZXJyb3IoYFske3RoaXMuY29uc3RydWN0b3IubmFtZX1dIFVuZXhwZWN0ZWQgZXJyb3IgZHVyaW5nIHJlc29sdmVyIGV4ZWN1dGlvbjogYCwgZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJpbXBvcnQgeyBTZW50aW5lbCB9IGZyb20gXCIuLi91dGlscy9TZW50aW5lbFwiO1xuaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuaW1wb3J0IHsgVHJhaWxUeXBlIH0gZnJvbSBcIi4uL3F1ZXJ5L1RyYWlsVHlwZVwiO1xuLyoqXG4gKiBDb2xsZWN0IGNsaWNrcyBvbiBlbGVtZW50cyBtYXRjaGluZyBhIHF1ZXJ5IHNlbGVjdG9yLiBIYW5kbGVzIGJvdGggRE9NIGVsZW1lbnRzXG4gKiBwcmVzZW50IGluIHRoZSBET00gYW5kIGVsZW1lbnRzIGluc2VydGVkIGFmdGVyIHRoZSBwYWdlIGxvYWQgLyBjb2xsZWN0b3IgY29uc3RydWN0aW9uLlxuICpcbiAqIFdoZW4gYSBjbGljayBvY2N1cnMsIGEgZnVuY3Rpb24gcHJvdmlkZWQgYXQgY29uc3RydWN0aW9uIHRpbWUgZ2V0IGludm9rZWQgdG8gY29sbGVjdCBkYXRhIHBvaW50c1xuICogZnJvbSB0aGUgZWxlbWVudC5cbiAqL1xuZXhwb3J0IGNsYXNzIEFzc29jaWF0ZWRQcm9kdWN0Q29sbGVjdG9yIGV4dGVuZHMgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdCBhIGNsaWNrIGNvbGxlY3RvclxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yRXhwcmVzc2lvbiAtIERvY3VtZW50IHF1ZXJ5IHNlbGVjdG9yIGlkZW50aWZ5aW5nIHRoZSBlbGVtZW50cyB0byBhdHRhY2ggdG9cbiAgICAgKiBAcGFyYW0gbWFpblByb2R1Y3RJZFxuICAgICAqIEBwYXJhbSByZXNvbHZlcnNcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZWxlY3RvckV4cHJlc3Npb24sIG1haW5Qcm9kdWN0SWQsIHJlc29sdmVycykge1xuICAgICAgICBzdXBlcihcImFzc29jaWF0ZWQtcHJvZHVjdFwiKTtcbiAgICAgICAgdGhpcy5tYWluUHJvZHVjdElkID0gbWFpblByb2R1Y3RJZDtcbiAgICAgICAgdGhpcy5zZWxlY3RvckV4cHJlc3Npb24gPSBzZWxlY3RvckV4cHJlc3Npb247XG4gICAgICAgIHRoaXMuaWRSZXNvbHZlciA9IHJlc29sdmVycy5pZFJlc29sdmVyO1xuICAgICAgICB0aGlzLnBvc2l0aW9uUmVzb2x2ZXIgPSByZXNvbHZlcnMucG9zaXRpb25SZXNvbHZlcjtcbiAgICAgICAgdGhpcy5wcmljZVJlc29sdmVyID0gcmVzb2x2ZXJzLnByaWNlUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMudHJhaWwgPSByZXNvbHZlcnMudHJhaWw7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFkZCBjbGljayBldmVudCBsaXN0ZW5lcnMgdG8gdGhlIGlkZW50aWZpZWQgZWxlbWVudHMsIHdyaXRlIHRoZSBkYXRhXG4gICAgICogd2hlbiB0aGUgZXZlbnQgb2NjdXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gd3JpdGVyIC0gVGhlIHdyaXRlciB0byBzZW5kIHRoZSBkYXRhIHRvXG4gICAgICogQHBhcmFtIGxvZ1xuICAgICAqL1xuICAgIGF0dGFjaCh3cml0ZXIsIGxvZykge1xuICAgICAgICBjb25zdCBjb2xsZWN0ID0gZWxlbWVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBpZCA9IHRoaXMucmVzb2x2ZSh0aGlzLmlkUmVzb2x2ZXIsIGxvZywgZWxlbWVudCk7XG4gICAgICAgICAgICBpZiAoaWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy50cmFpbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBGaW5kIG91dCB0aGUgcXVlcnkgc291cmNlIG9mIHRoZSBtYWluIHByb2R1Y3QuIE5vdGUgdGhhdCBkZXNwaXRlIGJlaW5nIGFcbiAgICAgICAgICAgICAgICAgICAgLy8gXCJtYWluXCIgcHJvZHVjdCwgaXQgY291bGQgYmUgYSAybmQgb3IgM3JkLCA0dGggbGV2ZWwgb2YgYXNzb2NpYXRlZCBwcm9kdWN0IGJyb3dzaW5nXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzVHJhaWwgPSB0aGlzLnRyYWlsLmZldGNoKHRoaXMubWFpblByb2R1Y3RJZCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1RyYWlsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVcG9uIGEgZm9sbG93LXVwIGV2ZW50IGZvciB0aGlzIHByb2R1Y3QgKGV4LiBiYXNrZXQpLCB3ZSB3b3VsZCBwaWNrIHRoaXMgdHJhaWxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhaWwucmVnaXN0ZXIoaWQsIFRyYWlsVHlwZS5Bc3NvY2lhdGVkLCBwcmV2aW91c1RyYWlsLnF1ZXJ5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBpZCxcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHRoaXMucmVzb2x2ZSh0aGlzLnBvc2l0aW9uUmVzb2x2ZXIsIGxvZywgZWxlbWVudCksXG4gICAgICAgICAgICAgICAgICAgIHByaWNlOiB0aGlzLnJlc29sdmUodGhpcy5wcmljZVJlc29sdmVyLCBsb2csIGVsZW1lbnQpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IGVsID0+IHtcbiAgICAgICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCB0aGlzLmxvZ1dyYXBIYW5kbGVyKGV2ID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gY29sbGVjdChlbCk7XG4gICAgICAgICAgICAgICAgaWYgKHBheWxvYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLndyaXRlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwidHlwZVwiOiB0aGlzLmdldFR5cGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLnBheWxvYWRcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgbG9nKSk7XG4gICAgICAgIH07XG4gICAgICAgIG5ldyBTZW50aW5lbCh0aGlzLmdldERvY3VtZW50KCkpLm9uKHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uLCBoYW5kbGVyKTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBDbGlja0NvbGxlY3RvciB9IGZyb20gXCIuL0NsaWNrQ29sbGVjdG9yXCI7XG5pbXBvcnQgeyBMaXN0ZW5lclR5cGUgfSBmcm9tIFwiLi4vdXRpbHMvTGlzdGVuZXJUeXBlXCI7XG4vKipcbiAqIENvbGxlY3QgaWQgYW5kIHByaWNlIGlmIGFuIGl0ZW0gd2FzIGFkZCBpbnRvIHRoZSBiYXNrZXRcbiAqL1xuZXhwb3J0IGNsYXNzIEJhc2tldENsaWNrQ29sbGVjdG9yIGV4dGVuZHMgQ2xpY2tDb2xsZWN0b3Ige1xuICAgIGNvbnN0cnVjdG9yKHNlbGVjdG9yLCBpZFJlc29sdmVyLCBwcmljZVJlc29sdmVyLCBsaXN0ZW5lclR5cGUgPSBMaXN0ZW5lclR5cGUuU2VudGluZWwpIHtcbiAgICAgICAgc3VwZXIoc2VsZWN0b3IsIFwiYmFza2V0XCIsIGxpc3RlbmVyVHlwZSk7XG4gICAgICAgIHRoaXMuaWRSZXNvbHZlciA9IGlkUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMucHJpY2VSZXNvbHZlciA9IHByaWNlUmVzb2x2ZXI7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbGxlY3QgdGhlIHByb2R1Y3QgY2xpY2sgaW5mb3JtYXRpb24gZnJvbSB0aGUgZWxlbWVudFxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIGNvbGxlY3QoZWxlbWVudCwgZXZlbnQsIGxvZykge1xuICAgICAgICBjb25zdCBpZCA9IHRoaXMucmVzb2x2ZSh0aGlzLmlkUmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpO1xuICAgICAgICBpZiAoaWQpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgICAgcHJpY2U6IHRoaXMucmVzb2x2ZSh0aGlzLnByaWNlUmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuLyoqXG4gKiBDb2xsZWN0IGJhc2ljIGJyb3dzZXIgaW5mb3JtYXRpb24uIE5vdGUgdGhhdCBkZXBlbmRpbmcgb24gaG93IHlvdSB1c2UgdGhpcyB5b3UgbWF5XG4gKiBuZWVkIHRvIGNvbnN1bHQgdGhlIEdEUFIgZ3VpZGVsaW5lc1xuICovXG5leHBvcnQgY2xhc3MgQnJvd3NlckNvbGxlY3RvciBleHRlbmRzIEFic3RyYWN0Q29sbGVjdG9yIHtcbiAgICBjb25zdHJ1Y3RvcihvcHRpb25zID0geyByZWNvcmRVcmw6IHRydWUsIHJlY29yZFJlZmVycmVyOiB0cnVlLCByZWNvcmRMYW5ndWFnZTogZmFsc2UsIHJlY29yZFVzZXJBZ2VudDogZmFsc2UgfSkge1xuICAgICAgICBzdXBlcihcImJyb3dzZXJcIik7XG4gICAgICAgIHRoaXMucmVjb3JkVXJsID0gb3B0aW9ucy5yZWNvcmRVcmwgfHwgZmFsc2U7XG4gICAgICAgIHRoaXMucmVjb3JkUmVmZXJyZXIgPSBvcHRpb25zLnJlY29yZFJlZmVycmVyIHx8IGZhbHNlO1xuICAgICAgICB0aGlzLnJlY29yZExhbmd1YWdlID0gb3B0aW9ucy5yZWNvcmRMYW5ndWFnZSB8fCBmYWxzZTtcbiAgICAgICAgdGhpcy5yZWNvcmRVc2VyQWdlbnQgPSBvcHRpb25zLnJlY29yZFVzZXJBZ2VudCB8fCBmYWxzZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXR0YWNoIGEgd3JpdGVyLCBub3RlIHRoYXQgdGhpcyBjb2xsZWN0b3IgaXMgbm90IGFzeW5jaHJvbm91cyBhbmQgd2lsbCB3cml0ZVxuICAgICAqIHRoZSBkYXRhIGltbWVkaWF0ZWxseVxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHdyaXRlciAtIFRoZSB3cml0ZXIgdG8gc2VuZCB0aGUgZGF0YSB0b1xuICAgICAqL1xuICAgIGF0dGFjaCh3cml0ZXIpIHtcbiAgICAgICAgY29uc3Qgd2luID0gdGhpcy5nZXRXaW5kb3coKTtcbiAgICAgICAgY29uc3QgZG9jID0gdGhpcy5nZXREb2N1bWVudCgpO1xuICAgICAgICBjb25zdCBkYXRhID0ge1xuICAgICAgICAgICAgdHlwZTogdGhpcy5nZXRUeXBlKCksXG4gICAgICAgICAgICB0b3VjaDogKCdvbnRvdWNoc3RhcnQnIGluIHdpbmRvdykgfHwgKG5hdmlnYXRvci5tYXhUb3VjaFBvaW50cyA+IDApXG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLnJlY29yZExhbmd1YWdlKVxuICAgICAgICAgICAgZGF0YS5sYW5nID0gd2luLm5hdmlnYXRvci5sYW5ndWFnZTtcbiAgICAgICAgaWYgKHRoaXMucmVjb3JkVXJsKVxuICAgICAgICAgICAgZGF0YS51cmwgPSB3aW4ubG9jYXRpb24uaHJlZjtcbiAgICAgICAgaWYgKHRoaXMucmVjb3JkUmVmZXJyZXIpXG4gICAgICAgICAgICBkYXRhLnJlZiA9IGRvYy5yZWZlcnJlcjtcbiAgICAgICAgaWYgKHRoaXMucmVjb3JkVXNlckFnZW50KVxuICAgICAgICAgICAgZGF0YS5hZ2VudCA9IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50O1xuICAgICAgICB3cml0ZXIud3JpdGUoZGF0YSk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuaW1wb3J0IHsgU2VudGluZWwgfSBmcm9tIFwiLi4vdXRpbHMvU2VudGluZWxcIjtcbmltcG9ydCB7IExpc3RlbmVyVHlwZSB9IGZyb20gXCIuLi91dGlscy9MaXN0ZW5lclR5cGVcIjtcbi8qKlxuICogVHJpZ2dlcmVkIGJ5IGEgY2xpY2tTZWxlY3RvciwgdGhlIGNvbGxlY3RvciB3aWxsIGZpcmUgdGhlIGNvbnRlbnRTZWxlY3RvciB0byBzZWxlY3QgZWxlbWVudHMgdG8gY29sbGVjdFxuICogaW5mb3JtYXRpb24gZnJvbSBhbmQgd3JpdGUgdG8gdGhlIGNvbGxlY3RvciB3cml0ZXJcbiAqL1xuZXhwb3J0IGNsYXNzIENoZWNrb3V0Q2xpY2tDb2xsZWN0b3IgZXh0ZW5kcyBBYnN0cmFjdENvbGxlY3RvciB7XG4gICAgY29uc3RydWN0b3IoY2xpY2tTZWxlY3RvciwgY29udGVudFNlbGVjdG9yLCBpZFJlc29sdmVyLCBwcmljZVJlc29sdmVyLCBhbW91bnRSZXNvbHZlciwgbGlzdGVuZXJUeXBlID0gTGlzdGVuZXJUeXBlLlNlbnRpbmVsKSB7XG4gICAgICAgIHN1cGVyKFwiY2hlY2tvdXRcIik7XG4gICAgICAgIHRoaXMuY2xpY2tTZWxlY3RvciA9IGNsaWNrU2VsZWN0b3I7XG4gICAgICAgIHRoaXMuY29udGVudFNlbGVjdG9yID0gY29udGVudFNlbGVjdG9yO1xuICAgICAgICB0aGlzLmlkUmVzb2x2ZXIgPSBpZFJlc29sdmVyO1xuICAgICAgICB0aGlzLnByaWNlUmVzb2x2ZXIgPSBwcmljZVJlc29sdmVyO1xuICAgICAgICB0aGlzLmFtb3VudFJlc29sdmVyID0gYW1vdW50UmVzb2x2ZXI7XG4gICAgICAgIHRoaXMubGlzdGVuZXJUeXBlID0gbGlzdGVuZXJUeXBlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBZGQgY2xpY2sgZXZlbnQgbGlzdGVuZXJzIHRvIHRoZSBpZGVudGlmaWVkIGVsZW1lbnRzLCB3cml0ZSB0aGUgZGF0YVxuICAgICAqIHdoZW4gdGhlIGV2ZW50IG9jY3Vyc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHdyaXRlciAtIFRoZSB3cml0ZXIgdG8gc2VuZCB0aGUgZGF0YSB0b1xuICAgICAqIEBwYXJhbSBsb2dcbiAgICAgKi9cbiAgICBhdHRhY2god3JpdGVyLCBsb2cpIHtcbiAgICAgICAgY29uc3QgZG9jID0gdGhpcy5nZXREb2N1bWVudCgpO1xuICAgICAgICAvLyBBY3RpdmF0ZXMgb24gY2xpY2sgb2YgdGhlIGVsZW1lbnQgc2VsZWN0ZWQgdXNpbmcgdGhlIGNsaWNrU2VsZWN0b3JcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IChldmVudCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudHMgPSBkb2MucXVlcnlTZWxlY3RvckFsbCh0aGlzLmNvbnRlbnRTZWxlY3Rvcik7XG4gICAgICAgICAgICBlbGVtZW50cy5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gdGhpcy5yZXNvbHZlKHRoaXMuaWRSZXNvbHZlciwgbG9nLCBlbGVtZW50LCBldmVudCk7XG4gICAgICAgICAgICAgICAgaWYgKGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByaWNlOiB0aGlzLnJlc29sdmUodGhpcy5wcmljZVJlc29sdmVyLCBsb2csIGVsZW1lbnQsIGV2ZW50KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFtb3VudDogdGhpcy5yZXNvbHZlKHRoaXMuYW1vdW50UmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIHdyaXRlIGVhY2ggaXRlbSBzZXBhcmF0ZWx5IC0gdGhleSBtYXkgYmUgY29taW5nIGZyb20gZGlmZmVyZW50IHF1ZXJpZXNcbiAgICAgICAgICAgICAgICAgICAgLy8gdGh1cyB3aGVuIHdlIHRyeSB0byByZXNvbHZlIHRoZSB0cmFpbCBmb3IgZWFjaCBvZiB0aGVtIHdlIG5lZWQgdG8gaGF2ZSB0aGVtXG4gICAgICAgICAgICAgICAgICAgIC8vIGFzIHNlcGFyYXRlIHJlY29yZHNcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLndyaXRlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMuZ2V0VHlwZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uZGF0YVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gVGhlIFNlbnRpZWwgbGlicmFyeSB1c2VzIGFuaW1hdGlvbnN0YXJ0IGV2ZW50IGxpc3RlbmVycyB3aGljaCBtYXkgaW50ZXJmZXJlIHdpdGhcbiAgICAgICAgLy8gYW5pbWF0aW9ucyBhdHRhY2hlZCBvbiBlbGVtZW5ldHMuIFRoZSBpbi1saWJyYXJ5IHByb3ZpZGVkIHdvcmthcm91bmQgbWVjaGFuaXNtIGRvZXMgbm90IHdvcmtcbiAgICAgICAgLy8gMTAwJSwgdGh1cyB3ZSBwcm92aWRlIHRoZSBsaXN0ZW5lclR5cGUgY2hvaWNlIGJlbG93LiBUaGUgdHJhZGVvZmZzXG4gICAgICAgIC8vIFwiZG9tXCIgLSBubyBhbmltYXRpb24gaW50ZXJmZXJlbmNlLCBvbmx5IG9uY2xpY2sgYXR0YWNoZWQsIGJ1dCBkb2VzIG5vdCBoYW5kbGUgZWxlbWVudHMgaW5zZXJ0ZWQgaW4gdGhlIERPTSBsYXRlclxuICAgICAgICAvLyBcInNlbnRpbmVsIChkZWZhdWx0KVwiIC0gd29ya3Mgb24gZWxlbWVudHMgaW5zZXJ0ZWQgaW4gdGhlIERPTSBhbnl0aW1lLCBidXQgaW50ZXJmZXJlcyB3aXRoIENTUyBhbmltYXRpb25zIG9uIHRoZXNlIGVsZW1lbnRzXG4gICAgICAgIGlmICh0aGlzLmxpc3RlbmVyVHlwZSA9PT0gTGlzdGVuZXJUeXBlLkRvbSkge1xuICAgICAgICAgICAgY29uc3Qgbm9kZUxpc3QgPSBkb2MucXVlcnlTZWxlY3RvckFsbCh0aGlzLmNsaWNrU2VsZWN0b3IpO1xuICAgICAgICAgICAgbm9kZUxpc3QuZm9yRWFjaCgoZWwpID0+IGVsLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCB0aGlzLmxvZ1dyYXBIYW5kbGVyKGhhbmRsZXIsIGxvZyksIHtcbiAgICAgICAgICAgICAgICBwYXNzaXZlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHNlbnRpbmVsID0gbmV3IFNlbnRpbmVsKHRoaXMuZ2V0RG9jdW1lbnQoKSk7XG4gICAgICAgICAgICBzZW50aW5lbC5vbih0aGlzLmNsaWNrU2VsZWN0b3IsIGVsID0+IGVsLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCB0aGlzLmxvZ1dyYXBIYW5kbGVyKGhhbmRsZXIsIGxvZyksIHtcbiAgICAgICAgICAgICAgICBwYXNzaXZlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsImltcG9ydCB7IEFic3RyYWN0Q29sbGVjdG9yIH0gZnJvbSBcIi4vQWJzdHJhY3RDb2xsZWN0b3JcIjtcbmltcG9ydCB7IFNlbnRpbmVsIH0gZnJvbSBcIi4uL3V0aWxzL1NlbnRpbmVsXCI7XG5pbXBvcnQgeyBMaXN0ZW5lclR5cGUgfSBmcm9tIFwiLi4vdXRpbHMvTGlzdGVuZXJUeXBlXCI7XG4vKipcbiAqIENvbGxlY3QgY2xpY2tzIG9uIGVsZW1lbnRzIG1hdGNoaW5nIGEgcXVlcnkgc2VsZWN0b3IuIEhhbmRsZXMgYm90aCBET00gZWxlbWVudHNcbiAqIHByZXNlbnQgaW4gdGhlIERPTSBhbmQgZWxlbWVudHMgaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHBhZ2UgbG9hZCAvIGNvbGxlY3RvciBjb25zdHJ1Y3Rpb24uXG4gKlxuICogV2hlbiBhIGNsaWNrIG9jY3VycywgYSBmdW5jdGlvbiBwcm92aWRlZCBhdCBjb25zdHJ1Y3Rpb24gdGltZSBnZXQgaW52b2tlZCB0byBjb2xsZWN0IGRhdGEgcG9pbnRzXG4gKiBmcm9tIHRoZSBlbGVtZW50LlxuICovXG5leHBvcnQgY2xhc3MgQ2xpY2tDb2xsZWN0b3IgZXh0ZW5kcyBBYnN0cmFjdENvbGxlY3RvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0IGEgY2xpY2sgY29sbGVjdG9yXG4gICAgICpcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JFeHByZXNzaW9uIC0gRG9jdW1lbnQgcXVlcnkgc2VsZWN0b3IgaWRlbnRpZnlpbmcgdGhlIGVsZW1lbnRzIHRvIGF0dGFjaCB0b1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIC0gVGhlIHR5cGUgT0YgZWxlbWVudCBjbGljayB0byByZXBvcnRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGlzdGVuZXJUeXBlIC0gV2hldGhlciB0aGUgbGlzdGVuZXIgc2hvdWxkIGJlIGEgZG9tIG9yIHNlbnRpbmVsIGxpc3RlbmVyXG4gICAgICogQHBhcmFtIGNvbnRleHRcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZWxlY3RvckV4cHJlc3Npb24sIHR5cGUgPSBcImNsaWNrXCIsIGxpc3RlbmVyVHlwZSA9IExpc3RlbmVyVHlwZS5TZW50aW5lbCwgY29udGV4dCkge1xuICAgICAgICBzdXBlcih0eXBlLCBjb250ZXh0KTtcbiAgICAgICAgdGhpcy5zZWxlY3RvckV4cHJlc3Npb24gPSBzZWxlY3RvckV4cHJlc3Npb247XG4gICAgICAgIHRoaXMubGlzdGVuZXJUeXBlID0gbGlzdGVuZXJUeXBlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBYnN0cmFjdCBjb2xsZWN0aW9uIG1ldGhvZCwgbXVzdCBiZSBvdmVycmlkZGVuIGluIHRoZSBzdWJjbGFzc2VzXG4gICAgICogQGFic3RyYWN0XG4gICAgICovXG4gICAgY29sbGVjdChlbGVtZW50LCBldmVudCwgbG9nKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFkZCBjbGljayBldmVudCBsaXN0ZW5lcnMgdG8gdGhlIGlkZW50aWZpZWQgZWxlbWVudHMsIHdyaXRlIHRoZSBkYXRhXG4gICAgICogd2hlbiB0aGUgZXZlbnQgb2NjdXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gd3JpdGVyIC0gVGhlIHdyaXRlciB0byBzZW5kIHRoZSBkYXRhIHRvXG4gICAgICogQHBhcmFtIGxvZ1xuICAgICAqL1xuICAgIGF0dGFjaCh3cml0ZXIsIGxvZykge1xuICAgICAgICBjb25zdCBoYW5kbGVyID0gKGV2ZW50LCBlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gdGhpcy5jb2xsZWN0KGVsZW1lbnQsIGV2ZW50LCBsb2cpO1xuICAgICAgICAgICAgaWYgKHBheWxvYWQpIHtcbiAgICAgICAgICAgICAgICB3cml0ZXIud3JpdGUoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLnR5cGUsXG4gICAgICAgICAgICAgICAgICAgIC4uLnBheWxvYWRcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLy8gVGhlIFNlbnRpZWwgbGlicmFyeSB1c2VzIGFuaW1hdGlvbnN0YXJ0IGV2ZW50IGxpc3RlbmVycyB3aGljaCBtYXkgaW50ZXJmZXJlIHdpdGhcbiAgICAgICAgLy8gYW5pbWF0aW9ucyBhdHRhY2hlZCBvbiBlbGVtZW5ldHMuIFRoZSBpbi1saWJyYXJ5IHByb3ZpZGVkIHdvcmthcm91bmQgbWVjaGFuaXNtIGRvZXMgbm90IHdvcmtcbiAgICAgICAgLy8gMTAwJSwgdGh1cyB3ZSBwcm92aWRlIHRoZSBsaXN0ZW5lclR5cGUgY2hvaWNlIGJlbG93LiBUaGUgdHJhZGVvZmZzXG4gICAgICAgIC8vIFwiZG9tXCIgLSBubyBhbmltYXRpb24gaW50ZXJmZXJlbmNlLCBvbmx5IG9uY2xpY2sgYXR0YWNoZWQsIGJ1dCBkb2VzIG5vdCBoYW5kbGUgZWxlbWVudHMgaW5zZXJ0ZWQgaW4gdGhlIERPTSBsYXRlclxuICAgICAgICAvLyBcInNlbnRpbmVsIChkZWZhdWx0KVwiIC0gd29ya3Mgb24gZWxlbWVudHMgaW5zZXJ0ZWQgaW4gdGhlIERPTSBhbnl0aW1lLCBidXQgaW50ZXJmZXJlcyB3aXRoIENTUyBhbmltYXRpb25zIG9uIHRoZXNlIGVsZW1lbnRzXG4gICAgICAgIGlmICh0aGlzLmxpc3RlbmVyVHlwZSA9PT0gTGlzdGVuZXJUeXBlLkRvbSkge1xuICAgICAgICAgICAgY29uc3Qgbm9kZUxpc3QgPSB0aGlzLmdldERvY3VtZW50KCkucXVlcnlTZWxlY3RvckFsbCh0aGlzLnNlbGVjdG9yRXhwcmVzc2lvbik7XG4gICAgICAgICAgICBub2RlTGlzdC5mb3JFYWNoKChlbCkgPT4gZWwuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHRoaXMubG9nV3JhcEhhbmRsZXIoaGFuZGxlciwgbG9nLCBlbCksIHtcbiAgICAgICAgICAgICAgICBwYXNzaXZlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHNlbnRpbmVsID0gbmV3IFNlbnRpbmVsKHRoaXMuZ2V0RG9jdW1lbnQoKSk7XG4gICAgICAgICAgICBzZW50aW5lbC5vbih0aGlzLnNlbGVjdG9yRXhwcmVzc2lvbiwgZWwgPT4gZWwuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHRoaXMubG9nV3JhcEhhbmRsZXIoaGFuZGxlciwgbG9nLCBlbCksIHtcbiAgICAgICAgICAgICAgICBwYXNzaXZlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsImltcG9ydCB7IExpc3RlbmVyVHlwZSB9IGZyb20gXCIuLi91dGlscy9MaXN0ZW5lclR5cGVcIjtcbmltcG9ydCB7IFNlbnRpbmVsIH0gZnJvbSBcIi4uL3V0aWxzL1NlbnRpbmVsXCI7XG5pbXBvcnQgeyBXcml0ZXJSZXNvbHZlckNvbGxlY3RvciB9IGZyb20gXCIuL1dyaXRlclJlc29sdmVyQ29sbGVjdG9yXCI7XG4vKipcbiAqIEV4dGVuZHMgV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3IgYW5kIGludm9rZXMgdGhlIFdyaXRlclJlc29sdmVyQ29sbGVjdG9yI2F0dGFjaCh3cml0ZXIsIGxvZylcbiAqIHdoZW4gYSBjbGljayBvbiBhbiBlbGVtZW50IGZvciB0aGUgcHJvdmlkZWQgXCJzZWxlY3RvckV4cHJlc3Npb25cIiBvY2N1cnNcbiAqL1xuZXhwb3J0IGNsYXNzIENsaWNrV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3IgZXh0ZW5kcyBXcml0ZXJSZXNvbHZlckNvbGxlY3RvciB7XG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc2VsZWN0b3JFeHByZXNzaW9uIHRoZSBjc3MgZXhwcmVzc2lvbiB0byBxdWVyeSBmb3Igb3RoZXIgZWxlbWVudHNcbiAgICAgKiBAcGFyYW0gdHlwZSB0aGUgdHlwZSBvZiB0aGUgZXZlbnRcbiAgICAgKiBAcGFyYW0gcmVzb2x2ZXIgYSB7V3JpdGVyUmVzb2x2ZXJ9IHdoaWNoIHdpbGwgYmUgZXhlY3V0ZWQgYXMgc29vbiBhcyBhbiBlbGVtZW50IG1hdGNoaW5nIHRoZSBzZWxlY3RvckV4cHJlc3Npb24gaXMgY2xpY2tlZFxuICAgICAqIEBwYXJhbSBsaXN0ZW5lclR5cGUge0xpc3RlbmVyVHlwZX1cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZWxlY3RvckV4cHJlc3Npb24sIHR5cGUsIHJlc29sdmVyLCBsaXN0ZW5lclR5cGUgPSBMaXN0ZW5lclR5cGUuU2VudGluZWwpIHtcbiAgICAgICAgc3VwZXIodHlwZSwgcmVzb2x2ZXIpO1xuICAgICAgICB0aGlzLnNlbGVjdG9yRXhwcmVzc2lvbiA9IHNlbGVjdG9yRXhwcmVzc2lvbjtcbiAgICAgICAgdGhpcy5saXN0ZW5lclR5cGUgPSBsaXN0ZW5lclR5cGU7XG4gICAgfVxuICAgIGF0dGFjaCh3cml0ZXIsIGxvZykge1xuICAgICAgICBjb25zdCBoYW5kbGVyID0gKGVsLCBldmVudCkgPT4ge1xuICAgICAgICAgICAgc3VwZXIuYXR0YWNoKHdyaXRlciwgbG9nKTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMubGlzdGVuZXJUeXBlID09PSBMaXN0ZW5lclR5cGUuRG9tKSB7XG4gICAgICAgICAgICBjb25zdCBub2RlTGlzdCA9IHRoaXMuZ2V0RG9jdW1lbnQoKS5xdWVyeVNlbGVjdG9yQWxsKHRoaXMuc2VsZWN0b3JFeHByZXNzaW9uKTtcbiAgICAgICAgICAgIG5vZGVMaXN0LmZvckVhY2goZWwgPT4gZWwuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGV2ID0+IHRoaXMubG9nV3JhcEhhbmRsZXIoaGFuZGxlciwgbG9nLCBlbCwgZXYpKCksIHtcbiAgICAgICAgICAgICAgICBwYXNzaXZlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHNlbnRpbmVsID0gbmV3IFNlbnRpbmVsKHRoaXMuZ2V0RG9jdW1lbnQoKSk7XG4gICAgICAgICAgICBzZW50aW5lbC5vbih0aGlzLnNlbGVjdG9yRXhwcmVzc2lvbiwgZWwgPT4gZWwuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGV2ID0+IHRoaXMubG9nV3JhcEhhbmRsZXIoaGFuZGxlciwgbG9nLCBlbCwgZXYpKCksIHtcbiAgICAgICAgICAgICAgICBwYXNzaXZlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsImltcG9ydCB7IENsaWNrQ29sbGVjdG9yIH0gZnJvbSBcIi4vQ2xpY2tDb2xsZWN0b3JcIjtcbi8qKlxuICogQ2xpY2tDb2xsZWN0b3IgZW1pdHRpbmcgXCJmaWx0ZXJcIiBldmVudHMsIGF0dGFjaCB0byBmYWNldCBsaW5rc1xuICovXG5leHBvcnQgY2xhc3MgRmlsdGVyQ2xpY2tDb2xsZWN0b3IgZXh0ZW5kcyBDbGlja0NvbGxlY3RvciB7XG4gICAgY29uc3RydWN0b3Ioc2VsZWN0b3IsIGNvbGxlY3Rvcikge1xuICAgICAgICBzdXBlcihzZWxlY3RvciwgXCJmaWx0ZXJcIik7XG4gICAgICAgIHRoaXMucmVzb2x2ZXIgPSBjb2xsZWN0b3I7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbGxlY3QgdGhlIHByb2R1Y3QgY2xpY2sgaW5mb3JtYXRpb24gZnJvbSB0aGUgZWxlbWVudFxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIGNvbGxlY3QoZWxlbWVudCwgZXZlbnQsIGxvZykge1xuICAgICAgICByZXR1cm4geyBxdWVyeTogdGhpcy5yZXNvbHZlKHRoaXMucmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpIH07XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3IgfSBmcm9tIFwiLi9Xcml0ZXJSZXNvbHZlckNvbGxlY3RvclwiO1xuLyoqXG4gKiBUcmlnZ2VyZWQgd2hlbiB0aGUgY2xpZW50IGhhcyB0cmlnZ2VyZWQvZmlyZWQgYSBzZWFyY2hcbiAqL1xuZXhwb3J0IGNsYXNzIEZpcmVkU2VhcmNoQ29sbGVjdG9yIGV4dGVuZHMgV3JpdGVyUmVzb2x2ZXJDb2xsZWN0b3Ige1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdCBmaXJlZCBzZWFyY2ggY29sbGVjdG9yXG4gICAgICpcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSByZXNvbHZlciAtIEZ1bmN0aW9uIHRoYXQgdHJpZ2dlcnMgdGhlIHdyaXRpbmcuIFdlIGNhbid0IGFsd2F5cyBkZXRlcm1pbmUgd2hlbiBzZWFyY2ggdHJpZ2dlcnMsIGxlYXZlIHRvIHRoZSBpbXBsZW1lbnRhdGlvbiB0byBkZXRlcm1pbmUgd2hlbi9ob3dcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihyZXNvbHZlcikge1xuICAgICAgICBzdXBlcihcImZpcmVkLXNlYXJjaFwiLCByZXNvbHZlcik7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuLyoqXG4gKiBDb2xsZWN0IGRpZmZlcmVudCB0eXBlIG9mIGV2ZW50cyB2aWEgYSBjdXN0b20gZXZlbnQuIFRoZSBjdXN0b20gZXZlbnQgc2hvdWxkIGhvbGQgdGhlIHByb3BlcnRpZXNcbiAqIFwidHlwZVwiIGFuZCBcImRhdGFcIiBpbiB0aGUgY3VzdG9tIHBheWxvYWQuXG4gKlxuICogU2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0d1aWRlL0V2ZW50cy9DcmVhdGluZ19hbmRfdHJpZ2dlcmluZ19ldmVudHMgZm9yIGd1aWRhbmNlXG4gKi9cbmV4cG9ydCBjbGFzcyBHZW5lcmljRXZlbnRDb2xsZWN0b3IgZXh0ZW5kcyBBYnN0cmFjdENvbGxlY3RvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0IGV2ZW50IGJhc2VkIGNvbGxlY3RvclxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIHRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWFjdCBvblxuICAgICAqIEBwYXJhbSB0eXBlXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCB0eXBlID0gXCJHZW5lcmljRXZlbnRcIikge1xuICAgICAgICBzdXBlcih0eXBlKTtcbiAgICAgICAgdGhpcy5ldmVudE5hbWUgPSBldmVudE5hbWU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEF0dGFjaCBhIHdyaXRlciwgbm90ZSB0aGF0IHRoaXMgY29sbGVjdG9yIGlzIGFzeW5jaHJvbm91cyBhbmQgd2lsbCB3cml0ZVxuICAgICAqIHRoZSBkYXRhIHdoZW4gdGhlIGV2ZW50IHRyaWdnZXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gd3JpdGVyIC0gVGhlIHdyaXRlciB0byBzZW5kIHRoZSBkYXRhIHRvXG4gICAgICogQHBhcmFtIGxvZ1xuICAgICAqL1xuICAgIGF0dGFjaCh3cml0ZXIsIGxvZykge1xuICAgICAgICB0aGlzLmdldFdpbmRvdygpLmFkZEV2ZW50TGlzdGVuZXIodGhpcy5ldmVudE5hbWUsIHRoaXMubG9nV3JhcEhhbmRsZXIoKGUpID0+IHtcbiAgICAgICAgICAgIHdyaXRlci53cml0ZSh7XG4gICAgICAgICAgICAgICAgXCJ0eXBlXCI6IGUuZGV0YWlsLnR5cGUsXG4gICAgICAgICAgICAgICAgLi4uZS5kZXRhaWwuZGF0YVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIGxvZykpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IEFic3RyYWN0Q29sbGVjdG9yIH0gZnJvbSBcIi4vQWJzdHJhY3RDb2xsZWN0b3JcIjtcbmltcG9ydCB7IFNlbnRpbmVsIH0gZnJvbSBcIi4uL3V0aWxzL1NlbnRpbmVsXCI7XG5pbXBvcnQgU2Nyb2xsTW9uaXRvciBmcm9tIFwic2Nyb2xsbW9uaXRvclwiO1xuaW1wb3J0IHsgTG9jYWxTdG9yYWdlUXVldWUgfSBmcm9tIFwiLi4vdXRpbHMvTG9jYWxTdG9yYWdlUXVldWVcIjtcbmltcG9ydCB7IGRlYm91bmNlIH0gZnJvbSBcIi4uL3V0aWxzL1V0aWxcIjtcbi8qKlxuICogQ29sbGVjdCBpbXByZXNzaW9ucyAtIGEgZGlzcGxheSBvZiBhIHByb2R1Y3QgaW4gdGhlIGJyb3dzZXIgdmlld3BvcnQuIElmIHRoZSBwcm9kdWN0IGlzIHNob3duIG11bHRpcGxlXG4gKiB0aW1lcywgdGhlIGNvbGxlY3RvciB3aWxsIHJlY29yZCBtdWx0aXBsZSBldmVudHMgaS5lLiB3ZSBkb24ndCBhcHBseSBmaWx0ZXIgbG9naWMgaGVyZS5cbiAqXG4gKiBIYW5kbGVzIGJvdGggRE9NIGVsZW1lbnRzIHByZXNlbnQgaW4gdGhlIERPTSBhbmQgZWxlbWVudHMgaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHBhZ2UgbG9hZCAvIGNvbGxlY3RvciBjb25zdHJ1Y3Rpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBJbXByZXNzaW9uQ29sbGVjdG9yIGV4dGVuZHMgQWJzdHJhY3RDb2xsZWN0b3Ige1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdCBpbXByZXNzaW9uIGNvbGxlY3RvclxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yRXhwcmVzc2lvbiAtIERvY3VtZW50IHF1ZXJ5IHNlbGVjdG9yIGlkZW50aWZ5aW5nIHRoZSBlbGVtZW50cyB0byBhdHRhY2ggdG9cbiAgICAgKiBAcGFyYW0gaWRSZXNvbHZlciAtIFJlc29sdmUgdGhlIGlkIG9mIHRoZSBlbGVtZW50XG4gICAgICogQHBhcmFtIHBvc2l0aW9uUmVzb2x2ZXIgLSBSZXNvbHZlIHRoZSBwb3NpdGlvbiBvZiB0aGUgZWxlbWVudCBpbiBkb21cbiAgICAgKiBAcGFyYW0gZXhwZWN0ZWRQYWdlUmVzb2x2ZXIgLSBJZiBzdXBwbGllZCwgaW1wcmVzc2lvbnMgd2lsbCBvbmx5IGJlIHRyYWNrZWQgaWYgdGhpcyByZXNvbHZlciByZXR1cm5zIHRydWUuIENvbWVzIGluIGhhbmR5IGZvciBzaW5nbGUgcGFnZSBhcHBsaWNhdGlvbnNcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZWxlY3RvckV4cHJlc3Npb24sIGlkUmVzb2x2ZXIsIHBvc2l0aW9uUmVzb2x2ZXIsIGV4cGVjdGVkUGFnZVJlc29sdmVyKSB7XG4gICAgICAgIHN1cGVyKFwiaW1wcmVzc2lvblwiKTtcbiAgICAgICAgdGhpcy5zZWxlY3RvckV4cHJlc3Npb24gPSBzZWxlY3RvckV4cHJlc3Npb247XG4gICAgICAgIHRoaXMuaWRSZXNvbHZlciA9IGlkUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMucG9zaXRpb25SZXNvbHZlciA9IHBvc2l0aW9uUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMuZXhwZWN0ZWRQYWdlUmVzb2x2ZXIgPSBleHBlY3RlZFBhZ2VSZXNvbHZlcjtcbiAgICAgICAgdGhpcy5xdWV1ZSA9IG5ldyBMb2NhbFN0b3JhZ2VRdWV1ZShcImltcHJlc3Npb25zXCIpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBZGQgaW1wcmVzc2lvbiBldmVudCBsaXN0ZW5lcnMgdG8gdGhlIGlkZW50aWZpZWQgZWxlbWVudHMsIHdyaXRlIHRoZSBkYXRhXG4gICAgICogd2hlbiB0aGUgZXZlbnQgb2NjdXJzLCB3aXRoIGEgZGVsYXkgb2YgMXMgLSB3ZSBjb3VsZCBnYXRoZXIgbWFueSBldmVudHMgd2l0aGluIHRoaXMgdGltZWZyYW1lXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gd3JpdGVyIC0gVGhlIHdyaXRlciB0byBzZW5kIHRoZSBkYXRhIHRvXG4gICAgICogQHBhcmFtIHtMb2dnZXJ9IGxvZyAtIFRoZSBsb2dnZXJcbiAgICAgKi9cbiAgICBhdHRhY2god3JpdGVyLCBsb2cpIHtcbiAgICAgICAgY29uc3QgZmx1c2ggPSBkZWJvdW5jZSgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnF1ZXVlLnRyYW5zYWN0aW9uYWxEcmFpbihxdWV1ZSA9PiBuZXcgUHJvbWlzZShyZXMgPT4ge1xuICAgICAgICAgICAgICAgIHJlcyh3cml0ZXIud3JpdGUoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLnR5cGUsXG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IHF1ZXVlXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVyciA9PiBsb2cuZXJyb3IoXCJDb3VsZCBub3QgZHJhaW4gcXVldWU6IFwiLCBlcnIpKTtcbiAgICAgICAgfSwgMjUwKTtcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgU2Nyb2xsTW9uaXRvci5jcmVhdGUoZWxlbWVudCkuZW50ZXJWaWV3cG9ydCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXhwZWN0ZWRQYWdlUmVzb2x2ZXIgJiYgIXRoaXMuZXhwZWN0ZWRQYWdlUmVzb2x2ZXIoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucXVldWUucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGlkOiB0aGlzLnJlc29sdmUodGhpcy5pZFJlc29sdmVyLCBsb2csIGVsZW1lbnQpLFxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbjogdGhpcy5yZXNvbHZlKHRoaXMucG9zaXRpb25SZXNvbHZlciwgbG9nLCBlbGVtZW50KVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGZsdXNoKCk7XG4gICAgICAgICAgICB9LCB0cnVlKTtcbiAgICAgICAgfTtcbiAgICAgICAgbmV3IFNlbnRpbmVsKHRoaXMuZ2V0RG9jdW1lbnQoKSkub24odGhpcy5zZWxlY3RvckV4cHJlc3Npb24sIHRoaXMubG9nV3JhcEhhbmRsZXIoaGFuZGxlciwgbG9nKSk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuaW1wb3J0IHsgU2VudGluZWwgfSBmcm9tIFwiLi4vdXRpbHMvU2VudGluZWxcIjtcbmltcG9ydCB7IExpc3RlbmVyVHlwZSB9IGZyb20gXCIuLi91dGlscy9MaXN0ZW5lclR5cGVcIjtcbi8qKlxuICogQ29sbGVjdCBzZWFyY2ggaW5mb3JtYXRpb24gZnJvbSBhIGZpZWxkIHRoYXQgaGFzIGEgXCJhcy15b3UtdHlwZVwiIHRyaWdnZXIgYW5kXG4gKiByZW5kZXJzIHNlYXJjaCByZXN1bHRzIGltbWVkaWF0ZWx5LiBNYXkgdHJpZ2dlciBtdWx0aXBsZSB0aW1lcyBkZXBlbmRpbmcgb25cbiAqIHR5cGUgc3BlZWQgcGF0dGVybnMgLSB3ZSBleHBlY3QgdGhhdCB0aGUgaW50ZXJ2YWwgYmV0d2VlbiBrZXkgc3Ryb2tlcyB3b3VsZCBiZVxuICogbGVzcyB0aGFuIDUwMG1zXG4gKi9cbmV4cG9ydCBjbGFzcyBJbnN0YW50U2VhcmNoUXVlcnlDb2xsZWN0b3IgZXh0ZW5kcyBBYnN0cmFjdENvbGxlY3RvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0IGluc3RhbnQgc2VhcmNoIGNvbGxlY3RvclxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yRXhwcmVzc2lvbiAtIERvY3VtZW50IHF1ZXJ5IHNlbGVjdG9yIGlkZW50aWZ5aW5nIHRoZSBlbGVtZW50cyB0byBhdHRhY2ggdG9cbiAgICAgKiBAcGFyYW0gZGVsYXlNc1xuICAgICAqIEBwYXJhbSBtaW5MZW5ndGhcbiAgICAgKiBAcGFyYW0gbGlzdGVuZXJUeXBlXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2VsZWN0b3JFeHByZXNzaW9uLCBkZWxheU1zID0gNTAwLCBtaW5MZW5ndGggPSAyLCBsaXN0ZW5lclR5cGUgPSBMaXN0ZW5lclR5cGUuU2VudGluZWwpIHtcbiAgICAgICAgc3VwZXIoXCJpbnN0YW50LXNlYXJjaFwiKTtcbiAgICAgICAgdGhpcy5zZWxlY3RvckV4cHJlc3Npb24gPSBzZWxlY3RvckV4cHJlc3Npb247XG4gICAgICAgIHRoaXMuZGVsYXlNcyA9IGRlbGF5TXM7XG4gICAgICAgIHRoaXMubWluTGVuZ3RoID0gbWluTGVuZ3RoO1xuICAgICAgICB0aGlzLmxpc3RlbmVyVHlwZSA9IGxpc3RlbmVyVHlwZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkIGltcHJlc3Npb24gZXZlbnQgbGlzdGVuZXJzIHRvIHRoZSBpZGVudGlmaWVkIGVsZW1lbnRzLCB3cml0ZSB0aGUgZGF0YVxuICAgICAqIHdoZW4gdGhlIGV2ZW50IG9jY3Vyc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHdyaXRlciAtIFRoZSB3cml0ZXIgdG8gc2VuZCB0aGUgZGF0YSB0b1xuICAgICAqIEBwYXJhbSBsb2dcbiAgICAgKi9cbiAgICBhdHRhY2god3JpdGVyLCBsb2cpIHtcbiAgICAgICAgY29uc3QgdHlwZSA9IHRoaXMuZ2V0VHlwZSgpO1xuICAgICAgICBjb25zdCBoYW5kbGVyID0gKGUsIHNlYXJjaEJveCkgPT4ge1xuICAgICAgICAgICAgLy8gSWdub3JlIHNoaWZ0LCBjdHJsLCBldGMuIHByZXNzZXMsIHJlYWN0IG9ubHkgb24gY2hhcmFjdGVyc1xuICAgICAgICAgICAgaWYgKGUud2hpY2ggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBEZWxheSB0aGUgcmVhY3Rpb24gb2YgdGhlIGV2ZW50LCBjbGVhbiB0aGUgdGltZW91dCBpZiB0aGUgZXZlbnQgZmlyZXNcbiAgICAgICAgICAgIC8vIGFnYWluIGFuZCBzdGFydCBjb3VudGluZyBmcm9tIDBcbiAgICAgICAgICAgIGRlbGF5KCh0aW1lc3RhbXApID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBrZXl3b3JkcyA9IHNlYXJjaEJveC52YWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAoa2V5d29yZHMgJiYga2V5d29yZHMubGVuZ3RoID49IHRoaXMubWluTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci53cml0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBcInR5cGVcIjogdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFwia2V5d29yZHNcIjoga2V5d29yZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICB0aW1lc3RhbXBcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgdGhpcy5kZWxheU1zKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gVGhlIFNlbnRpZWwgbGlicmFyeSB1c2VzIGFuaW1hdGlvbnN0YXJ0IGV2ZW50IGxpc3RlbmVycyB3aGljaCBtYXkgaW50ZXJmZXJlIHdpdGhcbiAgICAgICAgLy8gYW5pbWF0aW9ucyBhdHRhY2hlZCBvbiBlbGVtZW5ldHMuIFRoZSBpbi1saWJyYXJ5IHByb3ZpZGVkIHdvcmthcm91bmQgbWVjaGFuaXNtIGRvZXMgbm90IHdvcmtcbiAgICAgICAgLy8gMTAwJSwgdGh1cyB3ZSBwcm92aWRlIHRoZSBsaXN0ZW5lclR5cGUgY2hvaWNlIGJlbG93LiBUaGUgdHJhZGVvZmZzXG4gICAgICAgIC8vIFwiZG9tXCIgLSBubyBhbmltYXRpb24gaW50ZXJmZXJlbmNlLCBvbmx5IG9uY2xpY2sgYXR0YWNoZWQsIGJ1dCBkb2VzIG5vdCBoYW5kbGUgZWxlbWVudHMgaW5zZXJ0ZWQgaW4gdGhlIERPTSBsYXRlclxuICAgICAgICAvLyBcInNlbnRpbmVsIChkZWZhdWx0KVwiIC0gd29ya3Mgb24gZWxlbWVudHMgaW5zZXJ0ZWQgaW4gdGhlIERPTSBhbnl0aW1lLCBidXQgaW50ZXJmZXJlcyB3aXRoIENTUyBhbmltYXRpb25zIG9uIHRoZXNlIGVsZW1lbnRzXG4gICAgICAgIGlmICh0aGlzLmxpc3RlbmVyVHlwZSA9PT0gTGlzdGVuZXJUeXBlLkRvbSkge1xuICAgICAgICAgICAgY29uc3Qgbm9kZUxpc3QgPSB0aGlzLmdldERvY3VtZW50KCkucXVlcnlTZWxlY3RvckFsbCh0aGlzLnNlbGVjdG9yRXhwcmVzc2lvbik7XG4gICAgICAgICAgICBub2RlTGlzdC5mb3JFYWNoKGVsID0+IGVsLmFkZEV2ZW50TGlzdGVuZXIoXCJrZXl1cFwiLCB0aGlzLmxvZ1dyYXBIYW5kbGVyKGhhbmRsZXIsIGxvZywgZWwpKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBuZXcgU2VudGluZWwodGhpcy5nZXREb2N1bWVudCgpKS5vbih0aGlzLnNlbGVjdG9yRXhwcmVzc2lvbiwgKGVsKSA9PiB7XG4gICAgICAgICAgICAgICAgZWwuYWRkRXZlbnRMaXN0ZW5lcihcImtleXVwXCIsIHRoaXMubG9nV3JhcEhhbmRsZXIoaGFuZGxlciwgbG9nLCBlbCkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5jb25zdCBkZWxheSA9IChmdW5jdGlvbiAoKSB7XG4gICAgbGV0IHRpbWVyO1xuICAgIGxldCB0aW1lO1xuICAgIHJldHVybiBmdW5jdGlvbiAoY2FsbGJhY2ssIG1zKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgIGlmICghdGltZSlcbiAgICAgICAgICAgIHRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRpbWUpO1xuICAgICAgICAgICAgdGltZSA9IG51bGw7XG4gICAgICAgIH0sIG1zKTtcbiAgICB9O1xufSkoKTtcbiIsImltcG9ydCB7IENsaWNrQ29sbGVjdG9yIH0gZnJvbSBcIi4vQ2xpY2tDb2xsZWN0b3JcIjtcbmltcG9ydCB7IExpc3RlbmVyVHlwZSB9IGZyb20gXCIuLi91dGlscy9MaXN0ZW5lclR5cGVcIjtcbmltcG9ydCB7IFRyYWlsVHlwZSB9IGZyb20gXCIuLi9xdWVyeVwiO1xuaW1wb3J0IHsgbm9ybWFsaXplUGF0aG5hbWUgfSBmcm9tIFwiLi4vdXRpbHNcIjtcbi8qKlxuICogQ2xpY2tDb2xsZWN0b3IgZW1pdHRpbmcgXCJwcm9kdWN0XCIgZXZlbnRzLCBhdHRhY2ggdG8gcHJvZHVjdCBsaW5rc1xuICovXG5leHBvcnQgY2xhc3MgUHJvZHVjdENsaWNrQ29sbGVjdG9yIGV4dGVuZHMgQ2xpY2tDb2xsZWN0b3Ige1xuICAgIGNvbnN0cnVjdG9yKHNlbGVjdG9yLCByZXNvbHZlcnMsIGxpc3RlbmVyVHlwZSA9IExpc3RlbmVyVHlwZS5TZW50aW5lbCkge1xuICAgICAgICBzdXBlcihzZWxlY3RvciwgXCJwcm9kdWN0XCIsIGxpc3RlbmVyVHlwZSk7XG4gICAgICAgIHRoaXMuaWRSZXNvbHZlciA9IHJlc29sdmVycy5pZFJlc29sdmVyO1xuICAgICAgICB0aGlzLnBvc2l0aW9uUmVzb2x2ZXIgPSByZXNvbHZlcnMucG9zaXRpb25SZXNvbHZlcjtcbiAgICAgICAgdGhpcy5wcmljZVJlc29sdmVyID0gcmVzb2x2ZXJzLnByaWNlUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMuaW1hZ2VSZXNvbHZlciA9IHJlc29sdmVycy5pbWFnZVJlc29sdmVyO1xuICAgICAgICB0aGlzLm1ldGFkYXRhUmVzb2x2ZXIgPSByZXNvbHZlcnMubWV0YWRhdGFSZXNvbHZlcjtcbiAgICAgICAgdGhpcy50cmFpbCA9IHJlc29sdmVycy50cmFpbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29sbGVjdCB0aGUgcHJvZHVjdCBjbGljayBpbmZvcm1hdGlvbiBmcm9tIHRoZSBlbGVtZW50XG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgY29sbGVjdChlbGVtZW50LCBldmVudCwgbG9nKSB7XG4gICAgICAgIGNvbnN0IGlkID0gdGhpcy5yZXNvbHZlKHRoaXMuaWRSZXNvbHZlciwgbG9nLCBlbGVtZW50LCBldmVudCk7XG4gICAgICAgIGlmIChpZCkge1xuICAgICAgICAgICAgY29uc3QgY2xpY2tEYXRhID0ge1xuICAgICAgICAgICAgICAgIGlkLFxuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiB0aGlzLnJlc29sdmUodGhpcy5wb3NpdGlvblJlc29sdmVyLCBsb2csIGVsZW1lbnQsIGV2ZW50KSxcbiAgICAgICAgICAgICAgICBwcmljZTogdGhpcy5yZXNvbHZlKHRoaXMucHJpY2VSZXNvbHZlciwgbG9nLCBlbGVtZW50LCBldmVudCksXG4gICAgICAgICAgICAgICAgaW1hZ2U6IHRoaXMucmVzb2x2ZSh0aGlzLmltYWdlUmVzb2x2ZXIsIGxvZywgZWxlbWVudCwgZXZlbnQpLFxuICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB0aGlzLnJlc29sdmUodGhpcy5tZXRhZGF0YVJlc29sdmVyLCBsb2csIGVsZW1lbnQsIGV2ZW50KVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmICh0aGlzLnRyYWlsKSB7XG4gICAgICAgICAgICAgICAgLy8gQWZ0ZXIgYSByZWRpcmVjdCBhIHRyYWlsIHdpdGggdGhlIHBhdGhuYW1lIGlzIHJlZ2lzdGVyZWQgY29udGFpbmluZyB0aGUgcXVlcnkgd2hpY2ggdHJpZ2dlcmVkIHRoZSByZWRpcmVjdC5cbiAgICAgICAgICAgICAgICAvLyBJZiB3ZSBoYXZlIHN1Y2ggYSBxdWVyeSB3ZSB1c2UgaXQgdG8gYnVpbGQgdGhlIHRyYWlsLlxuICAgICAgICAgICAgICAgIGNvbnN0IHRyYWlsRGF0YSA9IHRoaXMudHJhaWwuZmV0Y2gobm9ybWFsaXplUGF0aG5hbWUobG9jYXRpb24ucGF0aG5hbWUpKTtcbiAgICAgICAgICAgICAgICBpZiAodHJhaWxEYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsaWNrRGF0YS5xdWVyeSA9IHRyYWlsRGF0YS5xdWVyeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gUmVnaXN0ZXIgdGhhdCB0aGlzIHByb2R1Y3Qgam91cm5leSBpbnRvIHBvdGVudGlhbCBwdXJjaGFzZSBzdGFydGVkXG4gICAgICAgICAgICAgICAgLy8gd2l0aCB0aGlzIHF1ZXJ5XG4gICAgICAgICAgICAgICAgdGhpcy50cmFpbC5yZWdpc3RlcihpZCwgVHJhaWxUeXBlLk1haW4sIHRyYWlsRGF0YSA9PT0gbnVsbCB8fCB0cmFpbERhdGEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHRyYWlsRGF0YS5xdWVyeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY2xpY2tEYXRhO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuaW1wb3J0IHsgY29va2llU2Vzc2lvblJlc29sdmVyIH0gZnJvbSBcIi4uL3Jlc29sdmVycy9SZXNvbHZlclwiO1xuaW1wb3J0IHsgZ2V0U2Vzc2lvblN0b3JhZ2UsIExpc3RlbmVyVHlwZSwgbm9ybWFsaXplUGF0aG5hbWUsIFNlbnRpbmVsIH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5pbXBvcnQgeyBRdWVyeSwgVHJhaWwsIFRyYWlsVHlwZSB9IGZyb20gXCIuLi9xdWVyeVwiO1xuLyoqXG4gKiBLZWVwIHRyYWNrIG9mIGh1bWFuIHRyaWdnZXJlZCBzZWFyY2hlcyBmb2xsb3dlZCBieSBhIHJlZGlyZWN0IHRvIGEgcGFnZSBkaWZmZXJlbnQgdGhhbiB0aGUgc2VhcmNoIHJlc3VsdCBwYWdlXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWRpcmVjdENvbGxlY3RvciBleHRlbmRzIEFic3RyYWN0Q29sbGVjdG9yIHtcbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3QgcmVkaXJlY3QgY29sbGVjdG9yXG4gICAgICpcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSB0cmlnZ2VyUmVzb2x2ZXIgLSBGdW5jdGlvbiB0aGF0IGZpcmVzIHdoZW4gYSBzZWFyY2ggaGFwcGVucywgc2hvdWxkIHJldHVybiB0aGUga2V5d29yZFxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGV4cGVjdGVkUGFnZVJlc29sdmVyIC0gRnVuY3Rpb24gdGhhdCBzaG91bGQgcmV0dXJuIHdoZXRoZXIgdGhlIHBhZ2Ugd2UgbG9hZCBpcyB0aGUgZXhwZWN0ZWQgb25lXG4gICAgICogQHBhcmFtIHJlZGlyZWN0S3BpUGFyYW1zIC0gUGFyYW1ldGVycyBmb3IgY29sbGVjdGluZyBLUEkncyBhZnRlciBhIHJlZGlyZWN0XG4gICAgICogQHBhcmFtIGxpc3RlbmVyVHlwZVxuICAgICAqIEBwYXJhbSBjb250ZXh0XG4gICAgICovXG4gICAgY29uc3RydWN0b3IodHJpZ2dlclJlc29sdmVyLCBleHBlY3RlZFBhZ2VSZXNvbHZlciwgcmVkaXJlY3RLcGlQYXJhbXMgPSB7fSwgbGlzdGVuZXJUeXBlID0gTGlzdGVuZXJUeXBlLlNlbnRpbmVsLCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBfYSwgX2I7XG4gICAgICAgIHN1cGVyKFwicmVkaXJlY3RcIiwgY29udGV4dCk7XG4gICAgICAgIHRoaXMudHJpZ2dlclJlc29sdmVyID0gdHJpZ2dlclJlc29sdmVyO1xuICAgICAgICB0aGlzLmV4cGVjdGVkUGFnZVJlc29sdmVyID0gZXhwZWN0ZWRQYWdlUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMucmVkaXJlY3RLcGlQYXJhbXMgPSByZWRpcmVjdEtwaVBhcmFtcztcbiAgICAgICAgdGhpcy5saXN0ZW5lclR5cGUgPSBsaXN0ZW5lclR5cGU7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBVc2VkIHRvIHRyYWNrIGlmIHRoZSBjb2xsZWN0b3JzIGhhdmUgYmVlbiBhdHRhY2hlZCBhbHJlYWR5IGluIGNhc2UgYXR0YWNoZWQgaXMgY2FsbGVkIG11bHRpcGxlIHRpbWVzXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmlzQ29sbGVjdG9yc0F0dGFjaGVkID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBVc2VkIHRvIHRyYWNrIGlmIHRoZSB0cmlnZ2VyIGhhcyBiZWVuIGluc3RhbGxlZCBhbHJlYWR5IGluIGNhc2UgYXR0YWNoZWQgaXMgY2FsbGVkIG11bHRpcGxlIHRpbWVzXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmlzVHJpZ2dlckluc3RhbGxlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnRyaWdnZXJSZXNvbHZlciA9IHRyaWdnZXJSZXNvbHZlcjtcbiAgICAgICAgdGhpcy5leHBlY3RlZFBhZ2VSZXNvbHZlciA9IGV4cGVjdGVkUGFnZVJlc29sdmVyO1xuICAgICAgICB0aGlzLmxpc3RlbmVyVHlwZSA9IGxpc3RlbmVyVHlwZTtcbiAgICAgICAgdGhpcy5jb2xsZWN0b3JzID0gcmVkaXJlY3RLcGlQYXJhbXMuY29sbGVjdG9ycyB8fCBbXTtcbiAgICAgICAgdGhpcy5yZXN1bHRDb3VudFJlc29sdmVyID0gcmVkaXJlY3RLcGlQYXJhbXMucmVzdWx0Q291bnRSZXNvbHZlciB8fCAoXyA9PiB2b2lkIDApO1xuICAgICAgICB0aGlzLnJlZGlyZWN0VFRMID0gdGhpcy5yZWRpcmVjdEtwaVBhcmFtcy5yZWRpcmVjdFRUTE1pbGxpcyB8fCA4NjQwMDAwMDtcbiAgICAgICAgdGhpcy5tYXhQYXRoU2VnbWVudHMgPSB0aGlzLnJlZGlyZWN0S3BpUGFyYW1zLm1heFBhdGhTZWdtZW50cyB8fCAtMTtcbiAgICAgICAgdGhpcy5zdWJTZWxlY3RvcnMgPSAoKF9hID0gdGhpcy5yZWRpcmVjdEtwaVBhcmFtcy5uZXN0ZWRSZWRpcmVjdHMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5zdWJTZWxlY3RvcnMpIHx8IFtdO1xuICAgICAgICB0aGlzLmRlcHRoID0gKChfYiA9IHRoaXMucmVkaXJlY3RLcGlQYXJhbXMubmVzdGVkUmVkaXJlY3RzKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IuZGVwdGgpIHx8IDE7XG4gICAgICAgIHRoaXMucXVlcnlSZXNvbHZlciA9IChwaHJhc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChwaHJhc2UuaW5kZXhPZihcIiRzPVwiKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBRdWVyeShwaHJhc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcXVlcnkgPSBuZXcgUXVlcnkoKTtcbiAgICAgICAgICAgIHF1ZXJ5LnNldFNlYXJjaChwaHJhc2UpO1xuICAgICAgICAgICAgcmV0dXJuIHF1ZXJ5O1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnNlc3Npb25SZXNvbHZlciA9ICgpID0+IGNvb2tpZVNlc3Npb25SZXNvbHZlcigpO1xuICAgICAgICB0aGlzLnJlZGlyZWN0VHJhaWwgPSBuZXcgVHJhaWwoKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF0aEluZm8gPSBSZWRpcmVjdENvbGxlY3Rvci5nZXRSZWRpcmVjdFBhdGhJbmZvKHRoaXMuZ2V0UGF0aG5hbWUoKSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFF1ZXJ5KHBhdGhJbmZvID09PSBudWxsIHx8IHBhdGhJbmZvID09PSB2b2lkIDAgPyB2b2lkIDAgOiBwYXRoSW5mby5xdWVyeSk7XG4gICAgICAgIH0sIHRoaXMuc2Vzc2lvblJlc29sdmVyKTtcbiAgICB9XG4gICAgc2V0Q29udGV4dChjb250ZXh0KSB7XG4gICAgICAgIHN1cGVyLnNldENvbnRleHQoY29udGV4dCk7XG4gICAgICAgIHRoaXMuY29sbGVjdG9ycy5mb3JFYWNoKGNvbGxlY3RvciA9PiBjb2xsZWN0b3Iuc2V0Q29udGV4dChjb250ZXh0KSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE1hcmtzIHRoaXMgcGF0aCBhcyBhIHJlZGlyZWN0IGxhbmRpbmcgcGFnZS5cbiAgICAgKiBAcGFyYW0gcGF0aCB0aGUgcGF0aG5hbWUgZS5nLiAvc29tZS1wYXRoXG4gICAgICogQHBhcmFtIHF1ZXJ5IHRoZSBxdWVyeSB3aGljaCBsZWFkIHRvIHRoaXMgcGF0aFxuICAgICAqIEBwYXJhbSBrZXkgdGhlIGtleSB0byBzdG9yZSB0aGUgcmVkaXJlY3QgcGF0aCBpblxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIHNldFJlZGlyZWN0UGF0aChwYXRoLCBxdWVyeSwga2V5ID0gUmVkaXJlY3RDb2xsZWN0b3IuUEFUSF9TVE9SQUdFX0tFWSkge1xuICAgICAgICBjb25zdCByZWRpcmVjdFBhdGhzID0gdGhpcy5nZXRSZWRpcmVjdFBhdGhzKCk7XG4gICAgICAgIHJlZGlyZWN0UGF0aHNbcGF0aF0gPSB7XG4gICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS5nZXRUaW1lKClcbiAgICAgICAgfTtcbiAgICAgICAgZ2V0U2Vzc2lvblN0b3JhZ2UoKS5zZXRJdGVtKGtleSwgSlNPTi5zdHJpbmdpZnkocmVkaXJlY3RQYXRocykpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIG1hcmtlZCBwYXRoc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJlZGlyZWN0UGF0aHMoa2V5ID0gUmVkaXJlY3RDb2xsZWN0b3IuUEFUSF9TVE9SQUdFX0tFWSkge1xuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShnZXRTZXNzaW9uU3RvcmFnZSgpLmdldEl0ZW0oa2V5KSB8fCBcInt9XCIpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZSBkYXRhIGZvciB0aGUgZ2l2ZW4gcGF0aFxuICAgICAqIEBwYXJhbSBwYXRoXG4gICAgICogQHBhcmFtIGtleVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJlZGlyZWN0UGF0aEluZm8ocGF0aCwga2V5ID0gUmVkaXJlY3RDb2xsZWN0b3IuUEFUSF9TVE9SQUdFX0tFWSkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRSZWRpcmVjdFBhdGhzKGtleSlbcGF0aF07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERlbGV0ZSBhbGwgZXhwaXJlZCByZWRpcmVjdCBwYXRoc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZXhwaXJlUmVkaXJlY3RQYXRocyhrZXkgPSBSZWRpcmVjdENvbGxlY3Rvci5QQVRIX1NUT1JBR0VfS0VZKSB7XG4gICAgICAgIGNvbnN0IHJlZGlyZWN0UGF0aHMgPSBSZWRpcmVjdENvbGxlY3Rvci5nZXRSZWRpcmVjdFBhdGhzKGtleSk7XG4gICAgICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICBPYmplY3Qua2V5cyhyZWRpcmVjdFBhdGhzKS5mb3JFYWNoKHBhdGggPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF0aEluZm8gPSByZWRpcmVjdFBhdGhzW3BhdGhdO1xuICAgICAgICAgICAgaWYgKG5vdyAtIE51bWJlcihwYXRoSW5mby50aW1lc3RhbXApID4gdGhpcy5yZWRpcmVjdFRUTCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSByZWRpcmVjdFBhdGhzW3BhdGhdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZ2V0U2Vzc2lvblN0b3JhZ2UoKS5zZXRJdGVtKGtleSwgSlNPTi5zdHJpbmdpZnkocmVkaXJlY3RQYXRocykpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDaGVjayB3aGV0aGVyIHdlIHNob3VsZCBiZSByZWNvcmRpbmcgYSByZWRpcmVjdCBldmVudFxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHdyaXRlciAtIFRoZSB3cml0ZXIgdG8gc2VuZCB0aGUgZGF0YSB0b1xuICAgICAqIEBwYXJhbSBsb2dcbiAgICAgKi9cbiAgICBhdHRhY2god3JpdGVyLCBsb2cpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNUcmlnZ2VySW5zdGFsbGVkID09PSBmYWxzZSkge1xuICAgICAgICAgICAgdGhpcy5yZXNvbHZlKHRoaXMudHJpZ2dlclJlc29sdmVyLCBsb2csIGtleXdvcmQgPT4gZ2V0U2Vzc2lvblN0b3JhZ2UoKS5zZXRJdGVtKFJlZGlyZWN0Q29sbGVjdG9yLkxBU1RfU0VBUkNIX1NUT1JBR0VfS0VZLCBrZXl3b3JkKSk7XG4gICAgICAgICAgICB0aGlzLmlzVHJpZ2dlckluc3RhbGxlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5leHBpcmVSZWRpcmVjdFBhdGhzKCk7XG4gICAgICAgIC8vIEZldGNoIHRoZSBsYXRlc3Qgc2VhcmNoIGlmIGFueVxuICAgICAgICBjb25zdCBsYXN0U2VhcmNoID0gZ2V0U2Vzc2lvblN0b3JhZ2UoKS5nZXRJdGVtKFJlZGlyZWN0Q29sbGVjdG9yLkxBU1RfU0VBUkNIX1NUT1JBR0VfS0VZKTtcbiAgICAgICAgY29uc3QgcGF0aG5hbWUgPSBub3JtYWxpemVQYXRobmFtZSh0aGlzLmdldFdpbmRvdygpLmxvY2F0aW9uLnBhdGhuYW1lKTtcbiAgICAgICAgaWYgKGxhc3RTZWFyY2gpIHtcbiAgICAgICAgICAgIGdldFNlc3Npb25TdG9yYWdlKCkucmVtb3ZlSXRlbShSZWRpcmVjdENvbGxlY3Rvci5MQVNUX1NFQVJDSF9TVE9SQUdFX0tFWSk7XG4gICAgICAgICAgICAvLyBJZiB3ZSBoYXZlIG5vdCBsYW5kZWQgb24gdGhlIGV4cGVjdGVkIHNlYXJjaCBwYWdlLCBpdCBtdXN0IGhhdmUgYmVlbiBhIHJlZGlyZWN0XG4gICAgICAgICAgICBpZiAoc2hvdWxkVHJhY2tSZWRpcmVjdChkb2N1bWVudC5yZWZlcnJlcikgJiYgIXRoaXMucmVzb2x2ZSh0aGlzLmV4cGVjdGVkUGFnZVJlc29sdmVyLCBsb2cpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcXVlcnkgPSB0aGlzLnF1ZXJ5UmVzb2x2ZXIobGFzdFNlYXJjaCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICB3cml0ZXIud3JpdGUoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInJlZGlyZWN0XCIsXG4gICAgICAgICAgICAgICAgICAgIGtleXdvcmRzOiBsYXN0U2VhcmNoLFxuICAgICAgICAgICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgICAgICAgICAgdXJsOiB3aW5kb3cubG9jYXRpb24uaHJlZixcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0Q291bnQ6IHRoaXMucmVzb2x2ZSh0aGlzLnJlc3VsdENvdW50UmVzb2x2ZXIsIGxvZylcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAvLyBtYXJrIGFzIHJlZGlyZWN0IGxhbmRpbmcgcGFnZVxuICAgICAgICAgICAgICAgIFJlZGlyZWN0Q29sbGVjdG9yLnNldFJlZGlyZWN0UGF0aCh0aGlzLmdldFBhdGhuYW1lKCksIHF1ZXJ5KTtcbiAgICAgICAgICAgICAgICAvLyByZWdpc3RlciB0cmFpbCBvbiB0aGUgY3VycmVudCBwYXRobmFtZSBiZWNhdXNlIHRoZSBQcm9kdWN0Q2xpY2sgY29sbGVjdG9yIGRvZXNuJ3Qga25vdyBhYm91dCB0aGUgbWF4UGF0aFNlZ21lbnRzIHByb3BlcnR5XG4gICAgICAgICAgICAgICAgdGhpcy5yZWRpcmVjdFRyYWlsLnJlZ2lzdGVyKHBhdGhuYW1lLCBUcmFpbFR5cGUuTWFpbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhpcyBpcyBvbmx5ICB0cmlnZ2VyZWQgd2hlbiBhIHN1YlNlbGVjdG9yIGl0ZW0gd2FzIGNsaWNrZWQgaS5lLiBhIG5lc3RlZCByZWRpcmVjdFxuICAgICAgICBjb25zdCBsYXN0U2VhcmNoTmVzdGVkUmVkaXJlY3QgPSB0aGlzLmdldE5lc3RlZFJlZGlyZWN0KCk7XG4gICAgICAgIGlmIChsYXN0U2VhcmNoTmVzdGVkUmVkaXJlY3QpIHtcbiAgICAgICAgICAgIGNvbnN0IHF1ZXJ5ID0gdGhpcy5xdWVyeVJlc29sdmVyKGxhc3RTZWFyY2hOZXN0ZWRSZWRpcmVjdC5xdWVyeSkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIFJlZGlyZWN0Q29sbGVjdG9yLnNldFJlZGlyZWN0UGF0aCh0aGlzLmdldFBhdGhuYW1lKCksIHF1ZXJ5KTtcbiAgICAgICAgICAgIC8vIHJlZ2lzdGVyIHRyYWlsIG9uIHRoZSBjdXJyZW50IHBhdGhuYW1lIGJlY2F1c2UgdGhlIFByb2R1Y3RDbGljayBjb2xsZWN0b3IgZG9lc24ndCBrbm93IGFib3V0IHRoZSBtYXhQYXRoU2VnbWVudHMgcHJvcGVydHlcbiAgICAgICAgICAgIHRoaXMucmVkaXJlY3RUcmFpbC5yZWdpc3RlcihwYXRobmFtZSwgVHJhaWxUeXBlLk1haW4pO1xuICAgICAgICAgICAgZ2V0U2Vzc2lvblN0b3JhZ2UoKS5yZW1vdmVJdGVtKFJlZGlyZWN0Q29sbGVjdG9yLk5FU1RFRF9SRURJUkVDVF9LRVlXT1JEU19TVE9SQUdFX0tFWSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENoZWNrIGlmIHdlIGhhdmUgdHJhY2tlZCB0aGlzIHBhdGggYmVmb3JlIGFuZCBpZiBpdCBpcyBzdGlsbCB2YWxpZC5cbiAgICAgICAgICogSWYgdmFsaWQsIHdlIGhhdmUgdG8gYXR0YWNoIHRoZSBLUEkgY29sbGVjdG9ycyB0byBnYXRoZXIgS1BJcyBmb3IgdGhpcyBsYW5kaW5nIHBhZ2UuXG4gICAgICAgICAqIFdlIGhhdmUgdG8gZG8gdGhpcyBiZWNhdXNlIHBlb3BsZSBjYW4gbmF2aWdhdGUgYXdheSBmcm9tIHRoZSBsYW5kaW5nIHBhZ2UgYW5kIGJhY2sgYWdhaW4gYW5kIHdlIGRvbid0IHdhbnQgdG8gbG9zZSBhbGwgc3Vic2VxdWVudCBjbGlja3MgZXRjLlxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3QgcGF0aEluZm8gPSB0aGlzLnJlZGlyZWN0VHJhaWwuZmV0Y2godGhpcy5nZXRQYXRobmFtZSgpKTtcbiAgICAgICAgaWYgKHBhdGhJbmZvICYmIHRoaXMuaXNDb2xsZWN0b3JzQXR0YWNoZWQgIT09IHRydWUpIHtcbiAgICAgICAgICAgIHRoaXMuYXR0YWNoQ29sbGVjdG9ycyh3cml0ZXIsIGxvZywgcGF0aEluZm8ucXVlcnkpO1xuICAgICAgICAgICAgdGhpcy5pc0NvbGxlY3RvcnNBdHRhY2hlZCA9IHRydWU7XG4gICAgICAgICAgICAvLyByZWdpc3RlciB0cmFpbCBvbiB0aGUgY3VycmVudCBwYXRobmFtZSBiZWNhdXNlIHRoZSBQcm9kdWN0Q2xpY2sgY29sbGVjdG9yIGRvZXNuJ3Qga25vdyBhYm91dCB0aGUgbWF4UGF0aFNlZ21lbnRzIHByb3BlcnR5XG4gICAgICAgICAgICB0aGlzLnJlZGlyZWN0VHJhaWwucmVnaXN0ZXIocGF0aG5hbWUsIFRyYWlsVHlwZS5NYWluKTtcbiAgICAgICAgICAgIC8vIGlmIHdlIGhhdmUgbmVzdGVkIHJlZGlyZWN0cywgd2UgaGF2ZSB0byBjYXJyeSB0aGUgcXVlcnkgcGFyYW1ldGVycyBvdmVyIHRvIHRoZSBuZXh0IHBhZ2VcbiAgICAgICAgICAgIHRoaXMuYXR0YWNoU3ViU2VsZWN0b3JzKHBhdGhJbmZvLCAobGFzdFNlYXJjaE5lc3RlZFJlZGlyZWN0ID09PSBudWxsIHx8IGxhc3RTZWFyY2hOZXN0ZWRSZWRpcmVjdCA9PT0gdm9pZCAwID8gdm9pZCAwIDogbGFzdFNlYXJjaE5lc3RlZFJlZGlyZWN0LmRlcHRoKSB8fCAwKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXROZXN0ZWRSZWRpcmVjdCgpIHtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IGdldFNlc3Npb25TdG9yYWdlKCkuZ2V0SXRlbShSZWRpcmVjdENvbGxlY3Rvci5ORVNURURfUkVESVJFQ1RfS0VZV09SRFNfU1RPUkFHRV9LRVkpO1xuICAgICAgICBpZiAocGF5bG9hZCkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UocGF5bG9hZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgaXNNYXhEZXB0aEV4Y2VlZGVkKGN1cnJlbnREZXB0aCA9IDApIHtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnREZXB0aCA+PSB0aGlzLmRlcHRoO1xuICAgIH1cbiAgICByZWdpc3Rlck5lc3RlZFJlZGlyZWN0KHF1ZXJ5LCBjdXJyZW50RGVwdGggPSAwKSB7XG4gICAgICAgIGlmICh0aGlzLmlzTWF4RGVwdGhFeGNlZWRlZChjdXJyZW50RGVwdGgpKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICAgICAgcXVlcnk6IHF1ZXJ5LFxuICAgICAgICAgICAgZGVwdGg6IGN1cnJlbnREZXB0aCArIDFcbiAgICAgICAgfTtcbiAgICAgICAgZ2V0U2Vzc2lvblN0b3JhZ2UoKS5zZXRJdGVtKFJlZGlyZWN0Q29sbGVjdG9yLk5FU1RFRF9SRURJUkVDVF9LRVlXT1JEU19TVE9SQUdFX0tFWSwgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xuICAgIH1cbiAgICBhdHRhY2hTdWJTZWxlY3RvcnMocGF0aEluZm8sIGN1cnJlbnREZXB0aCkge1xuICAgICAgICBpZiAodGhpcy5pc01heERlcHRoRXhjZWVkZWQoY3VycmVudERlcHRoKSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgdGhpcy5zdWJTZWxlY3RvcnMuZm9yRWFjaChzZWxlY3RvciA9PiB7XG4gICAgICAgICAgICBjb25zdCBoYW5kbGVDbGljayA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlZ2lzdGVyTmVzdGVkUmVkaXJlY3QocGF0aEluZm8ucXVlcnksIGN1cnJlbnREZXB0aCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKHRoaXMubGlzdGVuZXJUeXBlID09PSBMaXN0ZW5lclR5cGUuU2VudGluZWwpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzZW50aW5lbCA9IG5ldyBTZW50aW5lbCh0aGlzLmdldERvY3VtZW50KCkpO1xuICAgICAgICAgICAgICAgIHNlbnRpbmVsLm9uKHNlbGVjdG9yLCBlbGVtZW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5mbyA9IHRoaXMucmVkaXJlY3RUcmFpbC5mZXRjaCh0aGlzLmdldFBhdGhuYW1lKCkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5mbykgeyAvLyB0aGUgc2VudGluZWwgY2FuIHRyaWdnZXIgb24gYW55IHBhZ2UsIHdlIG5lZWQgdG8gbWFrZSBzdXJlIHdlIGF0dGFjaCBzdWJTZWxlY3RvcnMgb25seSBvbiB2YWxpZCByZWRpcmVjdCBwYXRoc1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgaGFuZGxlQ2xpY2spO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBoYW5kbGVDbGljayk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBnZXRQYXRobmFtZSgpIHtcbiAgICAgICAgY29uc3QgcGF0aG5hbWUgPSBub3JtYWxpemVQYXRobmFtZSh0aGlzLmdldFdpbmRvdygpLmxvY2F0aW9uLnBhdGhuYW1lKTtcbiAgICAgICAgaWYgKHRoaXMubWF4UGF0aFNlZ21lbnRzID4gMCkge1xuICAgICAgICAgICAgY29uc3QgcGF0aFNlZ21lbnRzID0gcGF0aG5hbWUuc3BsaXQoXCIvXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZVBhdGhuYW1lKHBhdGhTZWdtZW50cy5maWx0ZXIocyA9PiAhIXMpLnNsaWNlKDAsIHRoaXMubWF4UGF0aFNlZ21lbnRzKS5qb2luKFwiL1wiKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBhdGhuYW1lO1xuICAgIH1cbiAgICBhdHRhY2hDb2xsZWN0b3JzKHdyaXRlciwgbG9nLCBxdWVyeSkge1xuICAgICAgICAvLyBhdHRhY2ggYWxsIGNvbGxlY3RvcnMgd2hpY2ggYXJlIHJlc3BvbnNpYmxlIHRvIGdhdGhlciBrcGkncyBhZnRlciB0aGUgcmVkaXJlY3RcbiAgICAgICAgdGhpcy5jb2xsZWN0b3JzLmZvckVhY2goY29sbGVjdG9yID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29sbGVjdG9yLmF0dGFjaCh7XG4gICAgICAgICAgICAgICAgICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlci53cml0ZSh7IC4uLmRhdGEsIHF1ZXJ5OiBkYXRhLnF1ZXJ5IHx8IHF1ZXJ5IH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgbG9nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvZylcbiAgICAgICAgICAgICAgICAgICAgbG9nLmVycm9yKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59XG4vKipcbiAqIEtleSB1c2VkIHRvIHN0b3JlIHRoZSBrZXl3b3JkcyBvZiB0aGUgbGFzdCBleGVjdXRlZCBzZWFyY2hcbiAqL1xuUmVkaXJlY3RDb2xsZWN0b3IuTEFTVF9TRUFSQ0hfU1RPUkFHRV9LRVkgPSBcIl9fbGFzdFNlYXJjaFwiO1xuLyoqXG4gKiBLZXkgdXNlZCB0byBzdG9yZSBxdWVyeSBpbmZvcm1hdGlvbiBmb3IgYSBnaXZlbiByZWRpcmVjdCBsYW5kaW5nIHBhZ2UgKHBhdGggb2YgdGhlIHVybClcbiAqL1xuUmVkaXJlY3RDb2xsZWN0b3IuUEFUSF9TVE9SQUdFX0tFWSA9IFwiX19fcGF0aFN0b3JhZ2VcIjtcblJlZGlyZWN0Q29sbGVjdG9yLk5FU1RFRF9SRURJUkVDVF9LRVlXT1JEU19TVE9SQUdFX0tFWSA9IFwiX19fbmVzdGVkUmVkaXJlY3RLZXl3b3Jkc1N0b3JhZ2VcIjtcbmZ1bmN0aW9uIHNob3VsZFRyYWNrUmVkaXJlY3QocmVmZXJlcikge1xuICAgIGlmIChyZWZlcmVyKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZWZVcmwgPSBuZXcgVVJMKHJlZmVyZXIpO1xuICAgICAgICAgICAgY29uc3QgY3VycmVudFVybCA9IG5ldyBVUkwod2luZG93LmxvY2F0aW9uLmhyZWYpO1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRVcmwub3JpZ2luICYmIHJlZlVybC5vcmlnaW4pXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlZlVybC5vcmlnaW4gPT09IGN1cnJlbnRVcmwub3JpZ2luO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb2xsZWN0b3IgfSBmcm9tIFwiLi9BYnN0cmFjdENvbGxlY3RvclwiO1xuLyoqXG4gKiBDb2xsZWN0IHRoZSBiYXNpYyBzZWFyY2ggaW5mb3JtYXRpb24gLSB0aGUga2V5d29yZHMgdXNlZCBmb3IgdGhlIHNlYXJjaCBhbmRcbiAqIHRoZSBudW1iZXIgb2YgcmVzdWx0cy4gU3luY2hyb25vdXMgaS5lLiB0aGUgd3JpdGluZyBoYXBwZW5zIGRpcmVjdGx5IHdoZW4gYSB3cml0ZXIgaXMgYXR0YWNoZWQuXG4gKiBTZWUgdGhlIG90aGVyIHNlYXJjaCBjb2xsZWN0b3JzIGZvciBkeW5hbWljIG9uZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBTZWFyY2hSZXN1bHRDb2xsZWN0b3IgZXh0ZW5kcyBBYnN0cmFjdENvbGxlY3RvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0IHNlYXJjaCByZXN1bHQgY29sbGVjdG9yXG4gICAgICpcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBwaHJhc2VSZXNvbHZlciAtIEZ1bmN0aW9uIHRoYXQgc2hvdWxkIHJldHVybiB0aGUgc2VhcmNoIHBocmFzZSB1c2VkIGZvciB0aGUgc2VhcmNoXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY291bnRSZXNvbHZlciAtIEZ1bmN0aW9uIHRoYXQgc2hvdWxkIHJldHVybiB0aGUgbnVtbmJlciBvZiByZXN1bHRzIGluIHRoZSBzZWFyY2hcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBhY3Rpb25SZXNvbHZlciAtIEEgc2VhcmNoIHJlc3VsdCBtYXkgYmUgcmVmaW5lZCBvciBhIGNsaWVudCBtYXkgYnJvd3NlIDIsMyw0IHBhZ2UuXG4gICAgICogVGhpcyBmdW5jdGlvbiBzaG91bGQgcHJvdmlkZSBhIHRleHQgcmVwcmVzYW50aW9uIG9mIHRoZSBhY3Rpb25cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihwaHJhc2VSZXNvbHZlciwgY291bnRSZXNvbHZlciwgYWN0aW9uUmVzb2x2ZXIpIHtcbiAgICAgICAgc3VwZXIoXCJzZWFyY2hcIik7XG4gICAgICAgIHRoaXMucGhyYXNlUmVzb2x2ZXIgPSBwaHJhc2VSZXNvbHZlcjtcbiAgICAgICAgdGhpcy5jb3VudFJlc29sdmVyID0gY291bnRSZXNvbHZlcjtcbiAgICAgICAgdGhpcy5hY3Rpb25SZXNvbHZlciA9IGFjdGlvblJlc29sdmVyO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBdHRhY2ggYSB3cml0ZXIsIG5vdGUgdGhhdCB0aGlzIGNvbGxlY3RvciBpcyBub3QgYXN5bmNocm9ub3VzIGFuZCB3aWxsIHdyaXRlXG4gICAgICogdGhlIGRhdGEgaW1tZWRpYXRlbGx5XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gd3JpdGVyIC0gVGhlIHdyaXRlciB0byBzZW5kIHRoZSBkYXRhIHRvXG4gICAgICogQHBhcmFtIHtvYmplY3R9IGxvZyAtIFRoZSBsb2dnZXJcbiAgICAgKi9cbiAgICBhdHRhY2god3JpdGVyLCBsb2cpIHtcbiAgICAgICAgd3JpdGVyLndyaXRlKHtcbiAgICAgICAgICAgIHR5cGU6IFwic2VhcmNoXCIsXG4gICAgICAgICAgICBrZXl3b3JkczogdGhpcy5yZXNvbHZlKHRoaXMucGhyYXNlUmVzb2x2ZXIsIGxvZywge30pLFxuICAgICAgICAgICAgY291bnQ6IHRoaXMucmVzb2x2ZSh0aGlzLmNvdW50UmVzb2x2ZXIsIGxvZywge30pLFxuICAgICAgICAgICAgYWN0aW9uOiB0aGlzLnJlc29sdmUodGhpcy5hY3Rpb25SZXNvbHZlciwgbG9nLCB7fSkgfHwgXCJzZWFyY2hcIlxuICAgICAgICB9KTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBXcml0ZXJSZXNvbHZlckNvbGxlY3RvciB9IGZyb20gXCIuL1dyaXRlclJlc29sdmVyQ29sbGVjdG9yXCI7XG4vKipcbiAqIENvbGxlY3Qgc3VnZ2VzdCBzZWFyY2ggaW5mb3JtYXRpb24gLSBrZXl3b3JkIHNlYXJjaGVzIGNvbWluZyBmcm9tIGEgc3VnZ2VzdGlvbiB3aWRnZXQvZnVuY3Rpb25hbGl0eVxuICovXG5leHBvcnQgY2xhc3MgU3VnZ2VzdFNlYXJjaENvbGxlY3RvciBleHRlbmRzIFdyaXRlclJlc29sdmVyQ29sbGVjdG9yIHtcbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3Qgc3VnZ2VzdCBzZWFyY2ggY29sbGVjdG9yXG4gICAgICpcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSByZXNvbHZlciAtIEZ1bmN0aW9uIHRoYXQgdHJpZ2dlcnMgdGhlIHdyaXRpbmcuIFN1Z2dlc3QgbWlnaHQgYmUgY29tcGxleCwgbGVhdmUgdG8gdGhlIGltcGxlbWVudGF0aW9uIHRvIGRldGVybWluZSB3aGVuL2hvd1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHJlc29sdmVyKSB7XG4gICAgICAgIHN1cGVyKFwic3VnZ2VzdC1zZWFyY2hcIiwgcmVzb2x2ZXIpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IEFic3RyYWN0Q29sbGVjdG9yIH0gZnJvbSBcIi4vQWJzdHJhY3RDb2xsZWN0b3JcIjtcbi8qKlxuICogUmVzb2x2ZXMgaW1tZWRpYXRlbHkgYW5kIHBhc3NpbmcgdGhlIHdyaXRlciwgdGhlIHR5cGUgb2YgdGhlIGV2ZW50ICsgY29udGV4dCB0byB0aGUgcHJvdmlkZWQgcmVzb2x2ZXIgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBXcml0ZXJSZXNvbHZlckNvbGxlY3RvciBleHRlbmRzIEFic3RyYWN0Q29sbGVjdG9yIHtcbiAgICBjb25zdHJ1Y3Rvcih0eXBlLCByZXNvbHZlcikge1xuICAgICAgICBzdXBlcih0eXBlKTtcbiAgICAgICAgdGhpcy5yZXNvbHZlciA9IHJlc29sdmVyO1xuICAgIH1cbiAgICBhdHRhY2god3JpdGVyLCBsb2cpIHtcbiAgICAgICAgdGhpcy5yZXNvbHZlKHRoaXMucmVzb2x2ZXIsIGxvZywgd3JpdGVyLCB0aGlzLmdldFR5cGUoKSwgdGhpcy5nZXRDb250ZXh0KCkpO1xuICAgIH1cbn1cbiIsImV4cG9ydCAqIGZyb20gXCIuL0Fic3RyYWN0Q29sbGVjdG9yXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9Bc3NvY2lhdGVkUHJvZHVjdENvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vQmFza2V0Q2xpY2tDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0Jyb3dzZXJDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0NoZWNrb3V0Q2xpY2tDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0NsaWNrQ29sbGVjdG9yXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9DbGlja1dyaXRlclJlc29sdmVyQ29sbGVjdG9yXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9GaWx0ZXJDbGlja0NvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vRmlyZWRTZWFyY2hDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0dlbmVyaWNFdmVudENvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vSW1wcmVzc2lvbkNvbGxlY3RvclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vSW5zdGFudFNlYXJjaFF1ZXJ5Q29sbGVjdG9yXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9Qcm9kdWN0Q2xpY2tDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1JlZGlyZWN0Q29sbGVjdG9yXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9TZWFyY2hSZXN1bHRDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1N1Z2dlc3RTZWFyY2hDb2xsZWN0b3JcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1dyaXRlclJlc29sdmVyQ29sbGVjdG9yXCI7XG4iLCJleHBvcnQge307XG4iLCJleHBvcnQge307XG4iLCIvKipcbiAqIFBhc3NlcyBhbGwgbG9nIG1lc3NhZ2VzIHRvIHRoZSBwcm92aWRlZCB0cmFuc3BvcnRzXG4gKi9cbmV4cG9ydCBjbGFzcyBUcmFuc3BvcnRMb2dnZXIge1xuICAgIGNvbnN0cnVjdG9yKHRyYW5zcG9ydHMsIGlzRGVidWdFbmFibGVkID0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy50cmFuc3BvcnRzID0gdHJhbnNwb3J0cztcbiAgICAgICAgdGhpcy5pc0RlYnVnRW5hYmxlZCA9IGlzRGVidWdFbmFibGVkO1xuICAgIH1cbiAgICBkZWJ1Zyhtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIHRoaXMudHJhbnNwb3J0cy5mb3JFYWNoKHRyYW5zcG9ydCA9PiB0aGlzLmNhbGxUcmFuc3BvcnQodHJhbnNwb3J0LCBcImRlYnVnXCIsIG1zZywgLi4uZGF0YUFyZ3MpKTtcbiAgICB9XG4gICAgZXJyb3IobXNnLCAuLi5kYXRhQXJncykge1xuICAgICAgICB0aGlzLnRyYW5zcG9ydHMuZm9yRWFjaCh0cmFuc3BvcnQgPT4gdGhpcy5jYWxsVHJhbnNwb3J0KHRyYW5zcG9ydCwgXCJlcnJvclwiLCBtc2csIC4uLmRhdGFBcmdzKSk7XG4gICAgfVxuICAgIGluZm8obXNnLCAuLi5kYXRhQXJncykge1xuICAgICAgICB0aGlzLnRyYW5zcG9ydHMuZm9yRWFjaCh0cmFuc3BvcnQgPT4gdGhpcy5jYWxsVHJhbnNwb3J0KHRyYW5zcG9ydCwgXCJpbmZvXCIsIG1zZywgLi4uZGF0YUFyZ3MpKTtcbiAgICB9XG4gICAgd2Fybihtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIHRoaXMudHJhbnNwb3J0cy5mb3JFYWNoKHRyYW5zcG9ydCA9PiB0aGlzLmNhbGxUcmFuc3BvcnQodHJhbnNwb3J0LCBcIndhcm5cIiwgbXNnLCAuLi5kYXRhQXJncykpO1xuICAgIH1cbiAgICBjYWxsVHJhbnNwb3J0KHRyYW5zcG9ydCwgbGV2ZWwsIG1zZywgLi4uZGF0YUFyZ3MpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0cmFuc3BvcnRbbGV2ZWxdICYmIHR5cGVvZiB0cmFuc3BvcnRbbGV2ZWxdID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgICAgICAgICAgdHJhbnNwb3J0W2xldmVsXShtc2csIC4uLmRhdGFBcmdzKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEZWJ1Z0VuYWJsZWQpXG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCBjYWxsIHRyYW5zcG9ydDogXCIsIGUpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiZXhwb3J0ICogZnJvbSBcIi4vTG9nZ2VyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9Mb2dnZXJUcmFuc3BvcnRcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1RyYW5zcG9ydExvZ2dlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdHJhbnNwb3J0XCI7XG4iLCJleHBvcnQgY2xhc3MgQ29uc29sZVRyYW5zcG9ydCB7XG4gICAgZGVidWcobXNnLCAuLi5kYXRhQXJncykge1xuICAgICAgICBjb25zb2xlLmRlYnVnKG1zZywgLi4uZGF0YUFyZ3MpO1xuICAgIH1cbiAgICA7XG4gICAgaW5mbyhtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhtc2csIC4uLmRhdGFBcmdzKTtcbiAgICB9XG4gICAgO1xuICAgIHdhcm4obXNnLCAuLi5kYXRhQXJncykge1xuICAgICAgICBjb25zb2xlLndhcm4obXNnLCAuLi5kYXRhQXJncyk7XG4gICAgfVxuICAgIDtcbiAgICBlcnJvcihtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IobXNnLCAuLi5kYXRhQXJncyk7XG4gICAgfVxuICAgIDtcbn1cbiIsImltcG9ydCB7IGJhc2U2NEVuY29kZSB9IGZyb20gXCIuLi8uLi91dGlsc1wiO1xuLyoqXG4gKiBPbmx5IGFkZHMgZXJyb3IgbWVzc2FnZXMgdG8gYW4gc3FzIHF1ZXVlXG4gKi9cbmV4cG9ydCBjbGFzcyBTUVNFcnJvclRyYW5zcG9ydCB7XG4gICAgY29uc3RydWN0b3IocXVldWUsIGNoYW5uZWwsIHNlc3Npb25SZXNvbHZlciwgZmlmbyA9IGZhbHNlKSB7XG4gICAgICAgIHRoaXMucXVldWUgPSBxdWV1ZTtcbiAgICAgICAgdGhpcy5jaGFubmVsID0gY2hhbm5lbDtcbiAgICAgICAgdGhpcy5zZXNzaW9uUmVzb2x2ZXIgPSBzZXNzaW9uUmVzb2x2ZXI7XG4gICAgICAgIHRoaXMuZmlmbyA9IGZpZm87XG4gICAgfVxuICAgIHNlbmQoZGF0YSkge1xuICAgICAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgbGV0IHNyYyA9IHRoaXMucXVldWUgKyBcIj9WZXJzaW9uPTIwMTItMTEtMDUmQWN0aW9uPVNlbmRNZXNzYWdlXCI7XG4gICAgICAgIC8vIFNRUyBzdXBwb3J0cyBGSUZPIHF1ZXVlcyBpbiBzb21lIHJlZ2lvbnMgdGhhdCBjYW4gYWxzbyBndWFyYW50ZWUgdGhlIG9yZGVyXG4gICAgICAgIC8vIG9mIHRoZSBtZXNzYWdlcy5cbiAgICAgICAgaWYgKHRoaXMuZmlmbykge1xuICAgICAgICAgICAgLy8gVE9ETyB3aGVuIGVub3VnaCBpbmZvcm1hdGlvbiBpcyBwcmVzZW50IHRvIHVuaXF1ZWx5IGlkZW50aWZ5IGEgbWVzc2FnZSwgc3dpdGNoIHRoZSBkZWR1cGxpY2F0aW9uIGlkIHRvIGEgbWVzc2FnZSBoYXNoXG4gICAgICAgICAgICBzcmMgKz0gXCImTWVzc2FnZUdyb3VwSWQ9MSZNZXNzYWdlRGVkdXBsaWNhdGlvbklkPVwiICsgTWF0aC5yYW5kb20oKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkgJiYgdHlwZW9mIGRhdGEgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIGRhdGEgPSBbZGF0YV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICBkYXRhID0gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgc3JjICs9IFwiJk1lc3NhZ2VCb2R5PVwiICsgYmFzZTY0RW5jb2RlKGVuY29kZVVSSUNvbXBvbmVudChkYXRhKSk7XG4gICAgICAgIGltZy5zcmMgPSBzcmM7XG4gICAgfVxuICAgIGVycm9yKG1zZywgLi4uZGF0YUFyZ3MpIHtcbiAgICAgICAgdGhpcy5zZW5kKHtcbiAgICAgICAgICAgIHR5cGU6IFwiZXJyb3JcIixcbiAgICAgICAgICAgIG1zZyxcbiAgICAgICAgICAgIGNoYW5uZWw6IHRoaXMuY2hhbm5lbCxcbiAgICAgICAgICAgIHNlc3Npb246IHRoaXMuc2Vzc2lvblJlc29sdmVyKCksXG4gICAgICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkuZ2V0VGltZSgpLFxuICAgICAgICAgICAgLi4uZGF0YUFyZ3NcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIDtcbn1cbiIsImltcG9ydCB7IFNRU0Vycm9yVHJhbnNwb3J0IH0gZnJvbSBcIi4vU1FTRXJyb3JUcmFuc3BvcnRcIjtcbi8qKlxuICogQWRkcyBhbGwgbG9nIGxldmVscyB0byBhbiBTUVMgcXVldWVcbiAqL1xuZXhwb3J0IGNsYXNzIFNRU1RyYW5zcG9ydCBleHRlbmRzIFNRU0Vycm9yVHJhbnNwb3J0IHtcbiAgICBkZWJ1Zyhtc2csIC4uLmRhdGFBcmdzKSB7XG4gICAgICAgIHRoaXMuc2VuZCh7XG4gICAgICAgICAgICB0eXBlOiBcImRlYnVnXCIsXG4gICAgICAgICAgICBtc2csXG4gICAgICAgICAgICAuLi5kYXRhQXJnc1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgO1xuICAgIGluZm8obXNnLCAuLi5kYXRhQXJncykge1xuICAgICAgICB0aGlzLnNlbmQoe1xuICAgICAgICAgICAgdHlwZTogXCJpbmZvXCIsXG4gICAgICAgICAgICBtc2csXG4gICAgICAgICAgICAuLi5kYXRhQXJnc1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgO1xuICAgIHdhcm4obXNnLCAuLi5kYXRhQXJncykge1xuICAgICAgICB0aGlzLnNlbmQoe1xuICAgICAgICAgICAgdHlwZTogXCJ3YXJuaW5nXCIsXG4gICAgICAgICAgICBtc2csXG4gICAgICAgICAgICAuLi5kYXRhQXJnc1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgO1xufVxuIiwiZXhwb3J0ICogZnJvbSBcIi4vQ29uc29sZVRyYW5zcG9ydFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vU1FTRXJyb3JUcmFuc3BvcnRcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1NRU1RyYW5zcG9ydFwiO1xuIiwiZXhwb3J0IGNsYXNzIFF1ZXJ5IHtcbiAgICBjb25zdHJ1Y3RvcihxdWVyeVN0cmluZykge1xuICAgICAgICAvKipcbiAgICAgICAgICogUmVtb3ZlIGFsbCBzZWxlY3Rpb25zIG9uIHRoaXMgZmllbGRcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucmVtb3ZlU2VsZWN0aW9uQXQgPSBmdW5jdGlvbiAocG9zKSB7XG4gICAgICAgICAgICBhcnJheVJlbW92ZSh0aGlzLmNyaXRlcmlhLCBwb3MsIHBvcyk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY3JpdGVyaWEgPSBbXTtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAocXVlcnlTdHJpbmcpIHtcbiAgICAgICAgICAgIHZhciBjcml0ZXJpYSA9IFtdO1xuICAgICAgICAgICAgdmFyIGFuZHMgPSBxdWVyeVN0cmluZy5zcGxpdChcIi9cIik7XG4gICAgICAgICAgICBhbmRzLmZvckVhY2goZnVuY3Rpb24gKGFuZCkge1xuICAgICAgICAgICAgICAgIGlmIChhbmQuaW5kZXhPZihcInxcIikgIT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG9ycyA9IGFuZC5zcGxpdChcInxcIik7XG4gICAgICAgICAgICAgICAgICAgIG9ycy5mb3JFYWNoKGZ1bmN0aW9uIChvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3JpdGVyaWEucHVzaCh7IFwic2VsZWN0aW9uXCI6IG9yLCBcInR5cGVcIjogXCJvclwiIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNyaXRlcmlhLnB1c2goeyBcInNlbGVjdGlvblwiOiBhbmQsIFwidHlwZVwiOiBcImFuZFwiIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY3JpdGVyaWEuZm9yRWFjaChmdW5jdGlvbiAoY3JpdGVyaW9uKSB7XG4gICAgICAgICAgICAgICAgdmFyIGMgPSB1bmVzY2FwZShjcml0ZXJpb24uc2VsZWN0aW9uKTtcbiAgICAgICAgICAgICAgICBpZiAoYy5pbmRleE9mKFwiPVwiKSAhPSAtMSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVTcGxpdCA9IGMuc3BsaXQoXCI9XCIpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmNyaXRlcmlhLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJmaWVsZFwiOiB2YWx1ZVNwbGl0WzBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJvcGVyYXRpb25cIjogXCI9XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcInZhbHVlXCI6IHZhbHVlU3BsaXRbMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBcImFnZ3JlZ2F0aW9uXCI6IGNyaXRlcmlvbi50eXBlXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChjLmluZGV4T2YoXCI8XCIpICE9IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZVNwbGl0ID0gYy5zcGxpdChcIjxcIik7XG4gICAgICAgICAgICAgICAgICAgIGlmICgyID09IHZhbHVlU3BsaXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNyaXRlcmlhLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZmllbGRcIjogdmFsdWVTcGxpdFswXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIm9wZXJhdGlvblwiOiBcIjxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInZhbHVlXCI6IHZhbHVlU3BsaXRbMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJhZ2dyZWdhdGlvblwiOiBjcml0ZXJpb24udHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoMyA9PSB2YWx1ZVNwbGl0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jcml0ZXJpYS5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImZpZWxkXCI6IHZhbHVlU3BsaXRbMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJvcGVyYXRpb25cIjogXCI+PFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwibG93ZXJWYWx1ZVwiOiB2YWx1ZVNwbGl0WzBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidXBwZXJWYWx1ZVwiOiB2YWx1ZVNwbGl0WzJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYWdncmVnYXRpb25cIjogY3JpdGVyaW9uLnR5cGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGMuaW5kZXhPZihcIj5cIikgIT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlU3BsaXQgPSBjLnNwbGl0KFwiPlwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKDIgPT0gdmFsdWVTcGxpdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuY3JpdGVyaWEucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJmaWVsZFwiOiB2YWx1ZVNwbGl0WzBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwib3BlcmF0aW9uXCI6IFwiPlwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidmFsdWVcIjogdmFsdWVTcGxpdFsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImFnZ3JlZ2F0aW9uXCI6IGNyaXRlcmlvbi50eXBlXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICgzID09IHZhbHVlU3BsaXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNyaXRlcmlhLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZmllbGRcIjogdmFsdWVTcGxpdFsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIm9wZXJhdGlvblwiOiBcIj48XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJsb3dlclZhbHVlXCI6IHZhbHVlU3BsaXRbMl0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ1cHBlclZhbHVlXCI6IHZhbHVlU3BsaXRbMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJhZ2dyZWdhdGlvblwiOiBjcml0ZXJpb24udHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBQdXQgYmFjayB0byBzdHJpbmcgdGhlIHF1ZXJ5IG9iamVjdFxuICAgICAqXG4gICAgICogQHJldHVybnMgYSBzdHJpbmcgaW4gdGhlIGZvcm0gb2YgL2JyYW5kPWRlYnV0L3ByaWNlPjEwMC9cbiAgICAgKi9cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFwiXCI7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jcml0ZXJpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGNyaXRlcmlvbiA9IHRoaXMuY3JpdGVyaWFbaV07XG4gICAgICAgICAgICB2YXIgc2VwYXJhdG9yID0gXCIvXCI7XG4gICAgICAgICAgICBpZiAoXCJvclwiID09IGNyaXRlcmlvbi5hZ2dyZWdhdGlvbikge1xuICAgICAgICAgICAgICAgIHZhciBuZXh0ID0gdGhpcy5jcml0ZXJpYVtpICsgMV07XG4gICAgICAgICAgICAgICAgaWYgKG5leHQgJiYgXCJvclwiID09IG5leHQuYWdncmVnYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gXCJ8XCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNyaXRlcmlvbi5vcGVyYXRpb24gPT0gXCI+PFwiKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IGNyaXRlcmlvbi5sb3dlclZhbHVlICsgXCI8XCIgKyBjcml0ZXJpb24uZmllbGQgKyBcIjxcIiArIGNyaXRlcmlvbi51cHBlclZhbHVlICsgc2VwYXJhdG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IGNyaXRlcmlvbi5maWVsZCArIGNyaXRlcmlvbi5vcGVyYXRpb24gKyBjcml0ZXJpb24udmFsdWUgKyBzZXBhcmF0b3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkIGEgc2VsZWN0aW9uIHRvIHRoaXMgcXVlcnkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZmllbGQgdGhlIG5hbWUgb2YgdGhlIGZpZWxkIHdlJ3JlIGRyaWxsaW5nIGRvd24gd2l0aFxuICAgICAqIEBwYXJhbSBvcGVyYXRpb24gdGhlIG9wZXJhdGlvbiwgZXggPSw+LDxcbiAgICAgKiBAcGFyYW0gdmFsdWUgdGhlIHZhbHVlIGZvciB0aGUgb3BlcmF0aW9uXG4gICAgICogQHBhcmFtIHZhbHVlMSBvcHRpb25hbCBzZWNvbmQgdmFsdWUgZm9yIGNvbnN0cnVjdGluZyByYW5nZXMgbGlrZSAxMDA8cHJpY2U8MjAwXG4gICAgICovXG4gICAgYWRkU2VsZWN0aW9uKGZpZWxkLCBvcGVyYXRpb24sIHZhbHVlLCB2YWx1ZTEsIGFnZ3JlZ2F0aW9uKSB7XG4gICAgICAgIGNvbnN0IGFnZyA9IGFnZ3JlZ2F0aW9uID8gYWdncmVnYXRpb24gOiBcImFuZFwiO1xuICAgICAgICBpZiAodmFsdWUxICYmIFwiPjxcIiA9PSBvcGVyYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuY3JpdGVyaWEucHVzaCh7XG4gICAgICAgICAgICAgICAgXCJmaWVsZFwiOiBmaWVsZCxcbiAgICAgICAgICAgICAgICBcIm9wZXJhdGlvblwiOiBcIj48XCIsXG4gICAgICAgICAgICAgICAgXCJsb3dlclZhbHVlXCI6IHZhbHVlLFxuICAgICAgICAgICAgICAgIFwidXBwZXJWYWx1ZVwiOiB2YWx1ZTEsXG4gICAgICAgICAgICAgICAgXCJhZ2dyZWdhdGlvblwiOiBhZ2dcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5jcml0ZXJpYS5wdXNoKHtcbiAgICAgICAgICAgICAgICBcImZpZWxkXCI6IGZpZWxkLFxuICAgICAgICAgICAgICAgIFwib3BlcmF0aW9uXCI6IG9wZXJhdGlvbixcbiAgICAgICAgICAgICAgICBcInZhbHVlXCI6IHZhbHVlLFxuICAgICAgICAgICAgICAgIFwiYWdncmVnYXRpb25cIjogYWdnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBQYXJzZSBhbmQgY29uc3RydWN0IGEgbmV3IG9iamVjdCByZXByZXNlbnRhdGlvbiBvZiB0aGUgcXVlcnkgc3RyaW5nIGZvcm1cbiAgICAgKlxuICAgICAqIEBwYXJhbSBxdWVyeVN0cmluZyB0aGUgcXVlcnkgc3RyaW5nIGluIHRoZSBmb3JtIG9mIFwiL1wiIGpvaW5lZCBjcml0ZXJpYS4gZXguIC9icmFuZD1kZWJ1dC9wcmljZT4xMDAvXG4gICAgICogQHJldHVybnNcbiAgICAgKi9cbiAgICBnZXRTZWxlY3Rpb25zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jcml0ZXJpYTtcbiAgICB9XG4gICAgZ2V0U2VsZWN0aW9uKGZpZWxkKSB7XG4gICAgICAgIGZvciAodmFyIGMgaW4gdGhpcy5jcml0ZXJpYSkge1xuICAgICAgICAgICAgdmFyIGNyaXQgPSB0aGlzLmNyaXRlcmlhW2NdO1xuICAgICAgICAgICAgaWYgKGNyaXQuZmllbGQgPT0gZmllbGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY3JpdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGlzIHF1ZXJ5IGFscmVhZHkgaGFzIGEgc2VsZWN0aW9uIGZvciB0aGUgZ2l2ZW4gZmllbGRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHRydWUgaWYgd2UgaGF2ZSBhIHNlbGVjdGlvbiBvZiB0aGlzIGZpZWxkLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBoYXNTZWxlY3Rpb24oZmllbGQpIHtcbiAgICAgICAgZm9yICh2YXIgYyBpbiB0aGlzLmNyaXRlcmlhKSB7XG4gICAgICAgICAgICB2YXIgY3JpdCA9IHRoaXMuY3JpdGVyaWFbY107XG4gICAgICAgICAgICBpZiAoY3JpdC5maWVsZCA9PSBmaWVsZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhpcyBxdWVyeSBhbHJlYWR5IGhhcyBhIHNlbGVjdGlvbiBmb3IgdGhlIGdpdmVuIGZpZWxkXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB0cnVlIGlmIHdlIGhhdmUgYSBzZWxlY3Rpb24gb2YgdGhpcyBmaWVsZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgaGFzRXhhY3RTZWxlY3Rpb24oZmllbGQpIHtcbiAgICAgICAgZm9yICh2YXIgYyBpbiB0aGlzLmNyaXRlcmlhKSB7XG4gICAgICAgICAgICB2YXIgY3JpdCA9IHRoaXMuY3JpdGVyaWFbY107XG4gICAgICAgICAgICBpZiAoY3JpdC5maWVsZCA9PSBmaWVsZCAmJiBjcml0Lm9wZXJhdGlvbiA9PSBcIj1cIikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFsbCBzZWxlY3Rpb25zIG9uIHRoaXMgZmllbGRcbiAgICAgKi9cbiAgICByZW1vdmVTZWxlY3Rpb24oZmllbGQpIHtcbiAgICAgICAgdmFyIGNyaXRlcmlhID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jcml0ZXJpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGNyaXQgPSB0aGlzLmNyaXRlcmlhW2ldO1xuICAgICAgICAgICAgaWYgKGNyaXQuZmllbGQgPT0gZmllbGQpIHtcbiAgICAgICAgICAgICAgICBjcml0ZXJpYS5wdXNoKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChjcml0ZXJpYS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB2YXIgYyA9IGNyaXRlcmlhLnBvcCgpO1xuICAgICAgICAgICAgYXJyYXlSZW1vdmUodGhpcy5jcml0ZXJpYSwgYywgYyk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNyaXRlcmlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY3VycmVudCA9IHRoaXMuY3JpdGVyaWFbaV07XG4gICAgICAgICAgICB2YXIgcHJldmlvdXMgPSB0aGlzLmNyaXRlcmlhW2kgLSAxXTtcbiAgICAgICAgICAgIHZhciBuZXh0ID0gdGhpcy5jcml0ZXJpYVtpICsgMV07XG4gICAgICAgICAgICBpZiAoXCJvclwiID09IGN1cnJlbnQuYWdncmVnYXRpb24pIHtcbiAgICAgICAgICAgICAgICBpZiAoKCFuZXh0IHx8IFwiYW5kXCIgPT0gbmV4dC5hZ2dyZWdhdGlvbikgJiYgKCFwcmV2aW91cyB8fCBcImFuZFwiID09IHByZXZpb3VzLmFnZ3JlZ2F0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmFnZ3JlZ2F0aW9uID0gXCJhbmRcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2V0U2VhcmNoKHRlcm0pIHtcbiAgICAgICAgaWYgKHRlcm0pIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlU2VsZWN0aW9uKFwiJHNcIik7XG4gICAgICAgICAgICB0aGlzLmNyaXRlcmlhLnVuc2hpZnQoe1xuICAgICAgICAgICAgICAgIFwiZmllbGRcIjogXCIkc1wiLFxuICAgICAgICAgICAgICAgIFwib3BlcmF0aW9uXCI6IFwiPVwiLFxuICAgICAgICAgICAgICAgIFwidmFsdWVcIjogdGVybVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZ2V0U2VhcmNoKCkge1xuICAgICAgICBjb25zdCBzID0gdGhpcy5nZXRTZWxlY3Rpb24oXCIkc1wiKTtcbiAgICAgICAgcmV0dXJuIHMgPyBzLnZhbHVlIDogdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpc1ZhbGlkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jcml0ZXJpYS5sZW5ndGggPiAwO1xuICAgIH1cbn1cbi8qKlxuICogV2UgaGF2ZSB0aGUgc2FtZSBmdW5jdGlvbiBpbiB1dGlsIGJ1dCB3ZSB3YW50IHRvIGhhdmUgcXVlcnkuanMgd2l0aG91dCBhbnkgZGVwZW5kZW5jaWVzXG4gKlxuICogQHBhcmFtIGFycmF5XG4gKiBAcGFyYW0gZnJvbVxuICogQHBhcmFtIHRvXG4gKiBAcmV0dXJucyB7TnVtYmVyfCp9XG4gKi9cbmZ1bmN0aW9uIGFycmF5UmVtb3ZlKGFycmF5LCBmcm9tLCB0bykge1xuICAgIHZhciByZXN0ID0gYXJyYXkuc2xpY2UoKHRvIHx8IGZyb20pICsgMSB8fCBhcnJheS5sZW5ndGgpO1xuICAgIGFycmF5Lmxlbmd0aCA9IGZyb20gPCAwID8gYXJyYXkubGVuZ3RoICsgZnJvbSA6IGZyb207XG4gICAgcmV0dXJuIGFycmF5LnB1c2guYXBwbHkoYXJyYXksIHJlc3QpO1xufVxuIiwiaW1wb3J0IHsgZ2V0TG9jYWxTdG9yYWdlLCBnZXRTZXNzaW9uU3RvcmFnZSB9IGZyb20gXCIuLi91dGlscy9VdGlsXCI7XG5pbXBvcnQgeyBUcmFpbFR5cGUgfSBmcm9tIFwiLi9UcmFpbFR5cGVcIjtcbmNvbnN0IFRUTCA9IDEwMDAgKiA2MCAqIDYwICogMjQgKiAyO1xuZXhwb3J0IGNsYXNzIFRyYWlsIHtcbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBxdWVyeVJlc29sdmVyXG4gICAgICogQHBhcmFtIHNlc3Npb25SZXNvbHZlclxuICAgICAqIEBwYXJhbSB1aWQgdGhlIHVuaXF1ZSBpZCBvZiB0aGlzIHRyYWlsLiBVc2VkIGFzIHBhcnQgb2YgdGhlIGtleSB0byBzYXZlIGFsbCBUcmFpbCBzdGVwcy9wYXJ0c1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHF1ZXJ5UmVzb2x2ZXIsIHNlc3Npb25SZXNvbHZlciwgdWlkKSB7XG4gICAgICAgIHRoaXMucXVlcnlSZXNvbHZlciA9IHF1ZXJ5UmVzb2x2ZXI7XG4gICAgICAgIHRoaXMuc2Vzc2lvblJlc29sdmVyID0gc2Vzc2lvblJlc29sdmVyO1xuICAgICAgICB0aGlzLmtleSA9IFwic2VhcmNoLWNvbGxlY3Rvci10cmFpbFwiICsgKHVpZCA/IFwiLVwiICsgdWlkIDogXCJcIik7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBsb2NhbFRyYWlscyA9IHRoaXMuX2xvYWQoZ2V0TG9jYWxTdG9yYWdlKCkpO1xuICAgICAgICAgICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICAgICAgICAvLyBEcm9wIGFsbCBleHBpcmVkIHRyYWlscywgVFRMIGluIHN5bmMgd2l0aCBzZXNzaW9uIGR1cmF0aW9uIG9mIDMwIG1pblxuICAgICAgICAgICAgZm9yIChsZXQgaWQgb2YgT2JqZWN0LmtleXMobG9jYWxUcmFpbHMpKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vdyA+IGxvY2FsVHJhaWxzW2lkXS50aW1lc3RhbXAgKyBUVEwpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGxvY2FsVHJhaWxzW2lkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9zYXZlKGdldExvY2FsU3RvcmFnZSgpLCBsb2NhbFRyYWlscyk7XG4gICAgICAgICAgICAvLyBMb2FkIGV4aXN0aW5nIHNlc3Npb24gdHJhaWxzIGFuZCBtZXJnZSBpdCB3aXRoIHRoZSBsb2NhbCBzdG9yYWdlIHRyYWlscy5cbiAgICAgICAgICAgIC8vIFRoaXMgc2hvdWxkIGd1YXJhbnRlZSB0aGF0IHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGUgcGFnZXMgZnVydGhlciBkb3duIHRoZSB0cmFpbFxuICAgICAgICAgICAgLy8gKGJhc2tldCwgY2hlY2tvdXQpIHdlcmUgb3BlbiBpbiBhIG5ldyB0YWIgb3Igbm90LCB3ZSBoYXZlIGEgZnVsbCByZXByZXNlbnRhdGlvblxuICAgICAgICAgICAgLy8gb2YgYWxsIHByb2R1Y3QgY2xpY2tzIHdpdGhpbiB0aGUgc2Vzc2lvbi4gUmVtaW5kZXIsIHNlc3Npb25TdG9yYWdlIGlzIG1haW50YWluZWRcbiAgICAgICAgICAgIC8vIHBlciB0YWIvd2luZG93IGFuZCBpcyBkZWxldGVkIHVwb24gY2xvc2luZywgbG9jYWxTdG9yYWdlIGlzIHBlciB3ZWJzaXRlIHdpdGggbm9cbiAgICAgICAgICAgIC8vIGRlZmF1bHQgZXhwaXJ5LlxuICAgICAgICAgICAgY29uc3Qgc2Vzc2lvblRyYWlscyA9IHRoaXMuX2xvYWQoZ2V0U2Vzc2lvblN0b3JhZ2UoKSk7XG4gICAgICAgICAgICBjb25zdCB0cmFpbHMgPSBPYmplY3QuYXNzaWduKGxvY2FsVHJhaWxzLCBzZXNzaW9uVHJhaWxzKTtcbiAgICAgICAgICAgIHRoaXMuX3NhdmUoZ2V0U2Vzc2lvblN0b3JhZ2UoKSwgdHJhaWxzKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJFcnJvciBwYXJzaW5nIHN0b3JlZCBldmVudCBxdWV1ZSBcIiArIGUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIHRoaXMgcHJvZHVjdCBpZCBhcyBzdGFydGluZyBhIHB1cmNoYXNlIGpvdXJuZXkgYXQgdGhpcyBzZXNzaW9uL3F1ZXJ5XG4gICAgICogUG9zc2libGUgdHJhaWwgdHlwZXMgYXJlIFwibWFpblwiIGFuZCBcImFzc29jaWF0ZWRcIlxuICAgICAqL1xuICAgIHJlZ2lzdGVyKGlkLCB0cmFpbFR5cGUgPSBUcmFpbFR5cGUuTWFpbiwgcXVlcnlTdHJpbmcpIHtcbiAgICAgICAgY29uc3QgdHJhaWwgPSB7XG4gICAgICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkuZ2V0VGltZSgpLFxuICAgICAgICAgICAgcXVlcnk6IHF1ZXJ5U3RyaW5nIHx8IHRoaXMucXVlcnlSZXNvbHZlcigpLnRvU3RyaW5nKCksXG4gICAgICAgICAgICB0eXBlOiB0cmFpbFR5cGVcbiAgICAgICAgfTtcbiAgICAgICAgZm9yIChsZXQgc3RvcmFnZSBvZiBbZ2V0TG9jYWxTdG9yYWdlKCksIGdldFNlc3Npb25TdG9yYWdlKCldKSB7XG4gICAgICAgICAgICBjb25zdCB0cmFpbHMgPSB0aGlzLl9sb2FkKHN0b3JhZ2UpO1xuICAgICAgICAgICAgdHJhaWxzW2lkXSA9IHRyYWlsO1xuICAgICAgICAgICAgdGhpcy5fc2F2ZShzdG9yYWdlLCB0cmFpbHMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZldGNoKGlkKSB7XG4gICAgICAgIGNvbnN0IHRyYWlscyA9IHRoaXMuX2xvYWQoZ2V0U2Vzc2lvblN0b3JhZ2UoKSk7XG4gICAgICAgIHJldHVybiB0cmFpbHNbaWRdO1xuICAgIH1cbiAgICBfbG9hZChzdG9yYWdlKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBzdG9yYWdlLmdldEl0ZW0odGhpcy5rZXkpO1xuICAgICAgICByZXR1cm4gZGF0YSA/IEpTT04ucGFyc2UoZGF0YSkgOiB7fTtcbiAgICB9XG4gICAgX3NhdmUoc3RvcmFnZSwgZGF0YSkge1xuICAgICAgICBzdG9yYWdlLnNldEl0ZW0odGhpcy5rZXksIEpTT04uc3RyaW5naWZ5KGRhdGEpKTtcbiAgICB9XG59XG4iLCJleHBvcnQgdmFyIFRyYWlsVHlwZTtcbihmdW5jdGlvbiAoVHJhaWxUeXBlKSB7XG4gICAgVHJhaWxUeXBlW1wiTWFpblwiXSA9IFwibWFpblwiO1xuICAgIFRyYWlsVHlwZVtcIkFzc29jaWF0ZWRcIl0gPSBcImFzc29jaWF0ZWRcIjtcbn0pKFRyYWlsVHlwZSB8fCAoVHJhaWxUeXBlID0ge30pKTtcbiIsImV4cG9ydCAqIGZyb20gXCIuL1F1ZXJ5XCI7XG5leHBvcnQgKiBmcm9tIFwiLi9UcmFpbFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vVHJhaWxUeXBlXCI7XG4iLCJpbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4uL3V0aWxzL0NvbnRleHRcIjtcbmltcG9ydCB7IGdlbmVyYXRlSWQsIGdldENvb2tpZSwgZ2V0TG9jYWxTdG9yYWdlLCBzZXRDb29raWUgfSBmcm9tIFwiLi4vdXRpbHMvVXRpbFwiO1xuY29uc3QgTUlOVVRFU19PTkVfREFZID0gNjAgKiAyNDtcbmNvbnN0IE1JTlVURVNfVFdPX0RBWVMgPSA2MCAqIDI0ICogMjtcbmNvbnN0IE1JTlVURVNfSEFMRl9IT1VSID0gMzA7XG4vKipcbiAqIFJlYWQgdGhlIGNvb2tpZSB3aXRoIHRoZSBwcm92aWRlZCBuYW1lXG4gKiBAcGFyYW0gbmFtZSB0aGUgbmFtZSBvZiB0aGUgY29va2llXG4gKi9cbmV4cG9ydCBjb25zdCBjb29raWVSZXNvbHZlciA9IChuYW1lID0gXCJcIikgPT4gZ2V0Q29va2llKG5hbWUpO1xuLyoqXG4gKiBSZXNvbHZlIHRoZSBpZCBvZiB0aGUgY3VycmVudCBzZWFyY2ggc2Vzc2lvbi4gQSBzZWFyY2ggc2Vzc2lvbiBpcyBkZWZpbmVkIGFzXG4gKiBsaW1pdGVkIHRpbWUgc2xpY2Ugb2Ygc2VhcmNoIGFjdGl2aXR5IGFjcm9zcyBtdWx0aXBsZSB0YWJzLiBCeSBkZWZhdWx0IGEgc2Vzc2lvblxuICogd291bGQgYmUgY29uc2lkZXJlZCBleHBpcmVkIGFmdGVyIDMwIG1pbiBvZiBpbmFjdGl2aXR5LlxuICpcbiAqIEluIGNhc2UgdGhlIHJlc29sdmVyIGlzIGNvbnN0cnVjdGVkIHdpdGggYSBjb29raWUgbmFtZSwgdGhlIHNlc3Npb24gbGlmZWN5Y2xlXG4gKiB3aWxsIGJlIGdvdmVybmVkIGJ5IHRoZSBsaWZlY3ljbGUgb2YgdGhhdCBjb29raWUuIE90aGVyd2lzZSB0aGUgcmVzb2x2ZXIgd2lsbFxuICogc2V0IGl0cyBvd24gY29va2llLlxuICpcbiAqIEBwYXJhbSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBzZXNzaW9uIGNvb2tpZVxuICovXG5leHBvcnQgY29uc3QgY29va2llU2Vzc2lvblJlc29sdmVyID0gKG5hbWUgPSBcIlNlYXJjaENvbGxlY3RvclNlc3Npb25cIikgPT4gc2V0Q29va2llKG5hbWUsIGNvb2tpZVJlc29sdmVyKG5hbWUpIHx8IGdlbmVyYXRlSWQoKSwgTUlOVVRFU19UV09fREFZUyk7XG4vKipcbiAqIEZpbmQgdGhlIHBvc2l0aW9uIG9mIGEgRE9NIGVsZW1lbnQgcmVsYXRpdmUgdG8gb3RoZXIgRE9NIGVsZW1lbnRzIG9mIHRoZSBzYW1lIHR5cGUuXG4gKiBUbyBiZSB1c2VkIHRvIGZpbmQgdGhlIHBvc2l0aW9uIG9mIGFuIGl0ZW0gaW4gYSBzZWFyY2ggcmVzdWx0LlxuICpcbiAqIEBwYXJhbSBzZWxlY3RvckV4cHJlc3Npb24gdGhlIGNzcyBleHByZXNzaW9uIHRvIHF1ZXJ5IGZvciBvdGhlciBlbGVtZW50c1xuICogQHBhcmFtIGVsZW1lbnQgdGhlIGVsZW1lbnQgZm9yIHdoaWNoIHdlIHdhbnQgdG8ga25vdyB0aGUgcG9zaXRpb24gcmVsYXRpdmUgdG8gdGhlIGVsZW1lbnRzIHNlbGVjdGVkIGJ5IHNlbGVjdG9yRXhwcmVzc2lvblxuICogQHBhcmFtIGN0eCB0aGUgY29udGV4dCB0byB1c2UuIGRlZmF1bHRzIHRvIG5ldyBDb250ZXh0KHdpbmRvdywgZG9jdW1lbnQpXG4gKi9cbmV4cG9ydCBjb25zdCBwb3NpdGlvblJlc29sdmVyID0gKHNlbGVjdG9yRXhwcmVzc2lvbiwgZWxlbWVudCwgY3R4ID0gbmV3IENvbnRleHQod2luZG93LCBkb2N1bWVudCkpID0+IHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbShjdHguZ2V0RG9jdW1lbnQoKS5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yRXhwcmVzc2lvbikpXG4gICAgICAgIC5yZWR1Y2UoKGFjYywgbm9kZSwgaW5kZXgpID0+IG5vZGUgPT09IGVsZW1lbnQgPyBpbmRleCA6IGFjYywgdW5kZWZpbmVkKTtcbn07XG4vKipcbiAqIFRoaXMgaXMgYSBwZXJzaXN0ZW50IGRlYnVnIHJlc29sdmVyIHdoaWNoIHN0b3JlcyB0aGUgZGVidWcgcXVlcnkgcGFyYW1ldGVyIGFjcm9zcyByZXF1ZXN0cy5cbiAqL1xuZXhwb3J0IGNvbnN0IGRlYnVnUmVzb2x2ZXIgPSAoKSA9PiB7XG4gICAgY29uc3QgREVCVUdfS0VZID0gXCJfX2NvbGxlY3RvckRlYnVnXCI7XG4gICAgY29uc3QgZGVidWdQYXJhbSA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaCkuZ2V0KFwiZGVidWdcIik7XG4gICAgY29uc3QgaXNEZWJ1Z1BhcmFtRXhpc3RzID0gZGVidWdQYXJhbSAhPSBudWxsO1xuICAgIGlmIChpc0RlYnVnUGFyYW1FeGlzdHMpIHtcbiAgICAgICAgY29uc3QgZGVidWcgPSBkZWJ1Z1BhcmFtID09PSBcInRydWVcIjtcbiAgICAgICAgZ2V0TG9jYWxTdG9yYWdlKCkuc2V0SXRlbShERUJVR19LRVksIFN0cmluZyhkZWJ1ZykpO1xuICAgIH1cbiAgICByZXR1cm4gZ2V0TG9jYWxTdG9yYWdlKCkuZ2V0SXRlbShERUJVR19LRVkpID09PSBcInRydWVcIjtcbn07XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9SZXNvbHZlclwiO1xuIiwiZXhwb3J0IGNsYXNzIENvbnRleHQge1xuICAgIGNvbnN0cnVjdG9yKHdpbmRvdywgZG9jdW1lbnQpIHtcbiAgICAgICAgdGhpcy53aW5kb3cgPSB3aW5kb3c7XG4gICAgICAgIHRoaXMuZG9jdW1lbnQgPSBkb2N1bWVudDtcbiAgICB9XG4gICAgZ2V0V2luZG93KCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aW5kb3c7XG4gICAgfVxuICAgIGdldERvY3VtZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kb2N1bWVudDtcbiAgICB9XG59XG4iLCJleHBvcnQgdmFyIExpc3RlbmVyVHlwZTtcbihmdW5jdGlvbiAoTGlzdGVuZXJUeXBlKSB7XG4gICAgTGlzdGVuZXJUeXBlW1wiRG9tXCJdID0gXCJkb21cIjtcbiAgICBMaXN0ZW5lclR5cGVbXCJTZW50aW5lbFwiXSA9IFwic2VudGluZWxcIjtcbn0pKExpc3RlbmVyVHlwZSB8fCAoTGlzdGVuZXJUeXBlID0ge30pKTtcbiIsImltcG9ydCB7IGdldExvY2FsU3RvcmFnZSB9IGZyb20gXCIuL1V0aWxcIjtcbmV4cG9ydCBjbGFzcyBMb2NhbFN0b3JhZ2VRdWV1ZSB7XG4gICAgY29uc3RydWN0b3IoaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gXCJzZWFyY2gtY29sbGVjdG9yLXF1ZXVlXCIgKyAoaWQgPyBcIi1cIiArIGlkIDogXCJcIik7XG4gICAgICAgIHRoaXMucXVldWUgPSBbXTtcbiAgICAgICAgY29uc3Qgc3RvcmVkUXVldWUgPSBnZXRMb2NhbFN0b3JhZ2UoKS5nZXRJdGVtKHRoaXMubmFtZSk7XG4gICAgICAgIGlmIChzdG9yZWRRdWV1ZSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aGlzLnF1ZXVlID0gSlNPTi5wYXJzZShzdG9yZWRRdWV1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBwYXJzaW5nIHN0b3JlZCBldmVudCBxdWV1ZSBcIiArIGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHB1c2goZGF0YSkge1xuICAgICAgICB0aGlzLnF1ZXVlLnB1c2goZGF0YSk7XG4gICAgICAgIHRoaXMuX3NhdmUoKTtcbiAgICB9XG4gICAgZHJhaW4oKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMucXVldWU7XG4gICAgICAgIHRoaXMucXVldWUgPSBbXTtcbiAgICAgICAgdGhpcy5fc2F2ZSgpO1xuICAgICAgICByZXR1cm4gYnVmZmVyO1xuICAgIH1cbiAgICB0cmFuc2FjdGlvbmFsRHJhaW4oYXN5bmNDYWxsYmFjaykge1xuICAgICAgICBjb25zdCBidWZmZXIgPSB0aGlzLnF1ZXVlO1xuICAgICAgICByZXR1cm4gYXN5bmNDYWxsYmFjayh0aGlzLnF1ZXVlKVxuICAgICAgICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgICAgIHRoaXMucXVldWUgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3NhdmUoKTtcbiAgICAgICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzaXplKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5xdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIF9zYXZlKCkge1xuICAgICAgICBnZXRMb2NhbFN0b3JhZ2UoKS5zZXRJdGVtKHRoaXMubmFtZSwgSlNPTi5zdHJpbmdpZnkodGhpcy5xdWV1ZSkpO1xuICAgIH1cbn1cbiIsIi8qKlxuICogQ2xvbmVkIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL211aWNzcy9zZW50aW5lbGpzIHVudGlsIGEgcGF0Y2hlZCB2ZXJzaW9uXG4gKiBzdXBwb3JpbmcgaWZyYW1lcyBnZXRzIGF2YWlsYWJsZVxuICogTGljZW5zZSB1bmRlciBNSVRcbiAqL1xudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5LCBzZWxlY3RvclRvQW5pbWF0aW9uTWFwID0ge30sIGFuaW1hdGlvbkNhbGxiYWNrcyA9IHt9LCBzdHlsZUVsLCBzdHlsZVNoZWV0LCBjc3NSdWxlcztcbmV4cG9ydCBjbGFzcyBTZW50aW5lbCB7XG4gICAgY29uc3RydWN0b3IoZG9jID0gZG9jdW1lbnQpIHtcbiAgICAgICAgdGhpcy5kb2N1bWVudCA9IGRvYztcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkIHdhdGNoZXIuXG4gICAgICogQHBhcmFtIHthcnJheX0gY3NzU2VsZWN0b3JzIC0gTGlzdCBvZiBDU1Mgc2VsZWN0b3Igc3RyaW5nc1xuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uXG4gICAgICovXG4gICAgb24oY3NzU2VsZWN0b3JzLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAoIWNhbGxiYWNrKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBpbml0aWFsaXplIGFuaW1hdGlvbnN0YXJ0IGV2ZW50IGxpc3RlbmVyXG4gICAgICAgIGlmICghc3R5bGVFbCkge1xuICAgICAgICAgICAgdmFyIGRvYyA9IHRoaXMuZG9jdW1lbnQsIGhlYWQgPSBkb2MuaGVhZDtcbiAgICAgICAgICAgIC8vIGFkZCBhbmltYXRpb25zdGFydCBldmVudCBsaXN0ZW5lclxuICAgICAgICAgICAgLy9AdHMtaWdub3JlXG4gICAgICAgICAgICBkb2MuYWRkRXZlbnRMaXN0ZW5lcignYW5pbWF0aW9uc3RhcnQnLCBmdW5jdGlvbiAoZXYsIGNhbGxiYWNrcywgbCwgaSkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrcyA9IGFuaW1hdGlvbkNhbGxiYWNrc1tldi5hbmltYXRpb25OYW1lXTtcbiAgICAgICAgICAgICAgICAvLyBleGl0IGlmIGNhbGxiYWNrcyBoYXZlbid0IGJlZW4gcmVnaXN0ZXJlZFxuICAgICAgICAgICAgICAgIGlmICghY2FsbGJhY2tzKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgLy8gc3RvcCBvdGhlciBjYWxsYmFja3MgZnJvbSBmaXJpbmdcbiAgICAgICAgICAgICAgICBldi5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAvLyBpdGVyYXRlIHRocm91Z2ggY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgbCA9IGNhbGxiYWNrcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGw7IGkrKylcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tzW2ldKGV2LnRhcmdldCk7XG4gICAgICAgICAgICB9LCB0cnVlKTtcbiAgICAgICAgICAgIC8vIGFkZCBzdHlsZXNoZWV0IHRvIGRvY3VtZW50XG4gICAgICAgICAgICBzdHlsZUVsID0gZG9jLmNyZWF0ZUVsZW1lbnQoJ3N0eWxlJyk7XG4gICAgICAgICAgICBoZWFkLmluc2VydEJlZm9yZShzdHlsZUVsLCBoZWFkLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgc3R5bGVTaGVldCA9IHN0eWxlRWwuc2hlZXQ7XG4gICAgICAgICAgICBjc3NSdWxlcyA9IHN0eWxlU2hlZXQuY3NzUnVsZXM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbGlzdGlmeSBhcmd1bWVudCBhbmQgYWRkIGNzcyBydWxlcy8gY2FjaGUgY2FsbGJhY2tzXG4gICAgICAgIChpc0FycmF5KGNzc1NlbGVjdG9ycykgPyBjc3NTZWxlY3RvcnMgOiBbY3NzU2VsZWN0b3JzXSlcbiAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24gKHNlbGVjdG9yLCBhbmltSWQsIGlzQ3VzdG9tTmFtZSkge1xuICAgICAgICAgICAgYW5pbUlkID0gc2VsZWN0b3JUb0FuaW1hdGlvbk1hcFtzZWxlY3Rvcl07XG4gICAgICAgICAgICBpZiAoIWFuaW1JZCkge1xuICAgICAgICAgICAgICAgIC8vQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgIGlzQ3VzdG9tTmFtZSA9IHNlbGVjdG9yWzBdID09ICchJztcbiAgICAgICAgICAgICAgICAvLyBkZWZpbmUgYW5pbWF0aW9uIG5hbWUgYW5kIGFkZCB0byBtYXBcbiAgICAgICAgICAgICAgICBzZWxlY3RvclRvQW5pbWF0aW9uTWFwW3NlbGVjdG9yXSA9IGFuaW1JZCA9XG4gICAgICAgICAgICAgICAgICAgIGlzQ3VzdG9tTmFtZSA/IHNlbGVjdG9yLnNsaWNlKDEpIDogJ3NlbnRpbmVsLScgK1xuICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5yYW5kb20oKS50b1N0cmluZygxNikuc2xpY2UoMik7XG4gICAgICAgICAgICAgICAgLy8gYWRkIGtleWZyYW1lIHJ1bGVcbiAgICAgICAgICAgICAgICBjc3NSdWxlc1tzdHlsZVNoZWV0Lmluc2VydFJ1bGUoJ0BrZXlmcmFtZXMgJyArIGFuaW1JZCArXG4gICAgICAgICAgICAgICAgICAgICd7ZnJvbXt0cmFuc2Zvcm06bm9uZTt9dG97dHJhbnNmb3JtOm5vbmU7fX0nLCBjc3NSdWxlcy5sZW5ndGgpXVxuICAgICAgICAgICAgICAgICAgICAuX2lkID0gc2VsZWN0b3I7XG4gICAgICAgICAgICAgICAgLy8gYWRkIHNlbGVjdG9yIGFuaW1hdGlvbiBydWxlXG4gICAgICAgICAgICAgICAgaWYgKCFpc0N1c3RvbU5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgY3NzUnVsZXNbc3R5bGVTaGVldC5pbnNlcnRSdWxlKHNlbGVjdG9yICsgJ3thbmltYXRpb24tZHVyYXRpb246MC4wMDAxczthbmltYXRpb24tbmFtZTonICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuaW1JZCArICc7fScsIGNzc1J1bGVzLmxlbmd0aCldXG4gICAgICAgICAgICAgICAgICAgICAgICAuX2lkID0gc2VsZWN0b3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGFkZCB0byBtYXBcbiAgICAgICAgICAgICAgICBzZWxlY3RvclRvQW5pbWF0aW9uTWFwW3NlbGVjdG9yXSA9IGFuaW1JZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGFkZCB0byBjYWxsYmFja3NcbiAgICAgICAgICAgIChhbmltYXRpb25DYWxsYmFja3NbYW5pbUlkXSA9IGFuaW1hdGlvbkNhbGxiYWNrc1thbmltSWRdIHx8IFtdKVxuICAgICAgICAgICAgICAgIC5wdXNoKGNhbGxiYWNrKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB3YXRjaGVyLlxuICAgICAqIEBwYXJhbSB7YXJyYXl9IGNzc1NlbGVjdG9ycyAtIExpc3Qgb2YgQ1NTIHNlbGVjdG9yIHN0cmluZ3NcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiAob3B0aW9uYWwpXG4gICAgICovXG4gICAgb2ZmKGNzc1NlbGVjdG9ycywgY2FsbGJhY2spIHtcbiAgICAgICAgLy8gbGlzdGlmeSBhcmd1bWVudCBhbmQgaXRlcmF0ZSB0aHJvdWdoIHJ1bGVzXG4gICAgICAgIChpc0FycmF5KGNzc1NlbGVjdG9ycykgPyBjc3NTZWxlY3RvcnMgOiBbY3NzU2VsZWN0b3JzXSlcbiAgICAgICAgICAgIC8vQHRzLWlnbm9yZVxuICAgICAgICAgICAgLm1hcChmdW5jdGlvbiAoc2VsZWN0b3IsIGFuaW1JZCwgY2FsbGJhY2tMaXN0LCBpKSB7XG4gICAgICAgICAgICAvLyBnZXQgYW5pbUlkXG4gICAgICAgICAgICBpZiAoIShhbmltSWQgPSBzZWxlY3RvclRvQW5pbWF0aW9uTWFwW3NlbGVjdG9yXSkpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgLy8gZ2V0IGNhbGxiYWNrc1xuICAgICAgICAgICAgY2FsbGJhY2tMaXN0ID0gYW5pbWF0aW9uQ2FsbGJhY2tzW2FuaW1JZF07XG4gICAgICAgICAgICAvLyByZW1vdmUgY2FsbGJhY2sgZnJvbSBsaXN0XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpID0gY2FsbGJhY2tMaXN0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjYWxsYmFja0xpc3RbaV0gPT09IGNhbGxiYWNrKVxuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tMaXN0LnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFja0xpc3QgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGV4aXQgaWYgY2FsbGJhY2tzIHN0aWxsIGV4aXN0XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2tMaXN0Lmxlbmd0aClcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAvLyBjbGVhciBjYWNoZSBhbmQgcmVtb3ZlIGNzcyBydWxlc1xuICAgICAgICAgICAgaSA9IGNzc1J1bGVzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICBpZiAoY3NzUnVsZXNbaV0uX2lkID09IHNlbGVjdG9yKVxuICAgICAgICAgICAgICAgICAgICBzdHlsZVNoZWV0LmRlbGV0ZVJ1bGUoaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgc2VsZWN0b3JUb0FuaW1hdGlvbk1hcFtzZWxlY3Rvcl07XG4gICAgICAgICAgICBkZWxldGUgYW5pbWF0aW9uQ2FsbGJhY2tzW2FuaW1JZF07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNldCB3YXRjaGVycyBhbmQgY2FjaGVcbiAgICAgKi9cbiAgICByZXNldCgpIHtcbiAgICAgICAgc2VsZWN0b3JUb0FuaW1hdGlvbk1hcCA9IHt9O1xuICAgICAgICBhbmltYXRpb25DYWxsYmFja3MgPSB7fTtcbiAgICAgICAgaWYgKHN0eWxlRWwpXG4gICAgICAgICAgICBzdHlsZUVsLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc3R5bGVFbCk7XG4gICAgICAgIHN0eWxlRWwgPSAwO1xuICAgIH1cbn1cbiIsIi8qKlxuICogUGFyc2UgdGhlIGJyb3dzZXIgcXVlcnkgc3RyaW5nIG9yIHRoZSBwYXNzZWQgc3RyaW5nIGludG8gYSBqYXZhc2NyaXB0IG9iamVjdFxuICogd2l0aCBrZXlzIHRoZSBxdWVyeSBwYXJhbWV0ZXIgbmFtZXMgYW5kIHZhbHVlcyB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHF1ZXJ5U3RyaW5nIC0gdGhlIHF1ZXJ5IHN0cmluZyB0byBwYXJzZSwgd2luZG93LmxvY2F0aW9uLnNlYXJjaCBpZiBub3QgYXZhaWxhYmxlXG4gKiBAcmV0dXJuIHtvYmplY3R9XG4gKi9cbmV4cG9ydCBjb25zdCBwYXJzZVF1ZXJ5U3RyaW5nID0gKHF1ZXJ5U3RyaW5nID0gd2luZG93LmxvY2F0aW9uLnNlYXJjaCkgPT4ge1xuICAgIHJldHVybiBuZXcgVVJMU2VhcmNoUGFyYW1zKHF1ZXJ5U3RyaW5nKTtcbn07XG5leHBvcnQgY29uc3Qgbm9ybWFsaXplUGF0aG5hbWUgPSAocGF0aCkgPT4ge1xuICAgIGlmICghcGF0aC5zdGFydHNXaXRoKFwiL1wiKSlcbiAgICAgICAgcGF0aCA9IFwiL1wiICsgcGF0aDtcbiAgICBpZiAocGF0aC5lbmRzV2l0aChcIi9cIikpXG4gICAgICAgIHBhdGggPSBwYXRoLnN1YnN0cmluZygwLCBwYXRoLmxlbmd0aCAtIDEpO1xuICAgIHJldHVybiBwYXRoO1xufTtcbi8qKlxuICogU29tZSBicm93c2VyIGxpa2UgU2FmYXJpIHByZXZlbnQgYWNjZXNzaW5nIGxvY2FsU3RvcmFnZSBpbiBwcml2YXRlIG1vZGUgYnkgdGhyb3dpbmcgZXhjZXB0aW9ucy5cbiAqIFVzZSB0aGlzIG1ldGhvZCB0byByZXRyaWV2ZSBhIG1vY2sgaW1wbCB3aGljaCB3aWxsIGF0IGxlYXN0IHByZXZlbnQgZXJyb3JzLlxuICovXG5leHBvcnQgY29uc3QgZ2V0TG9jYWxTdG9yYWdlID0gKCkgPT4ge1xuICAgIGlmIChcImxvY2FsU3RvcmFnZVwiIGluIHdpbmRvdykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJhYmNcIik7IC8vIGFjY2VzcyBsb2NhbFN0b3JhZ2UgdG8gdHJpZ2dlciBpbmNvZ25pdG8gbW9kZSBleGNlcHRpb25zXG4gICAgICAgICAgICByZXR1cm4gbG9jYWxTdG9yYWdlO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjb29raWVTdG9yYWdlKDUyNTYwMCwgXCJfX2xvY2FsU3RvcmFnZU1vY2tfX19cIik7XG59O1xuLyoqXG4gKiBVUkwgc2FmZSBiYXNlNjQgZW5jb2RpbmdcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gVGhlIHN0cmluZyB0byBiZSBlbmNvZGVkLCBvbmx5IEFTQ0lJL0lTTy04ODU5LTEgc3VwcG9ydGVkXG4gKi9cbmV4cG9ydCBjb25zdCBiYXNlNjRFbmNvZGUgPSAoc3RyKSA9PiB7XG4gICAgLy8gTm90ZSwgKyByZXBsYWNlZCB3aXRoIC0sIC8gcmVwbGFjZWQgd2l0aCBfXG4gICAgY29uc3QgYjY0ID0gXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OS1fPVwiO1xuICAgIGxldCBvMSwgbzIsIG8zLCBiaXRzLCBoMSwgaDIsIGgzLCBoNCwgZSA9IFtdLCBwYWQgPSAnJywgYztcbiAgICBjID0gc3RyLmxlbmd0aCAlIDM7IC8vIHBhZCBzdHJpbmcgdG8gbGVuZ3RoIG9mIG11bHRpcGxlIG9mIDNcbiAgICBpZiAoYyA+IDApIHtcbiAgICAgICAgd2hpbGUgKGMrKyA8IDMpIHtcbiAgICAgICAgICAgIHBhZCArPSAnPSc7XG4gICAgICAgICAgICBzdHIgKz0gJ1xcMCc7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gbm90ZTogZG9pbmcgcGFkZGluZyBoZXJlIHNhdmVzIHVzIGRvaW5nIHNwZWNpYWwtY2FzZSBwYWNraW5nIGZvciB0cmFpbGluZyAxIG9yIDIgY2hhcnNcbiAgICBmb3IgKGMgPSAwOyBjIDwgc3RyLmxlbmd0aDsgYyArPSAzKSB7IC8vIHBhY2sgdGhyZWUgb2N0ZXRzIGludG8gZm91ciBoZXhldHNcbiAgICAgICAgbzEgPSBzdHIuY2hhckNvZGVBdChjKTtcbiAgICAgICAgbzIgPSBzdHIuY2hhckNvZGVBdChjICsgMSk7XG4gICAgICAgIG8zID0gc3RyLmNoYXJDb2RlQXQoYyArIDIpO1xuICAgICAgICBiaXRzID0gbzEgPDwgMTYgfCBvMiA8PCA4IHwgbzM7XG4gICAgICAgIGgxID0gYml0cyA+PiAxOCAmIDB4M2Y7XG4gICAgICAgIGgyID0gYml0cyA+PiAxMiAmIDB4M2Y7XG4gICAgICAgIGgzID0gYml0cyA+PiA2ICYgMHgzZjtcbiAgICAgICAgaDQgPSBiaXRzICYgMHgzZjtcbiAgICAgICAgLy8gdXNlIGhleHRldHMgdG8gaW5kZXggaW50byBjb2RlIHN0cmluZ1xuICAgICAgICBlW2MgLyAzXSA9IGI2NC5jaGFyQXQoaDEpICsgYjY0LmNoYXJBdChoMikgKyBiNjQuY2hhckF0KGgzKSArIGI2NC5jaGFyQXQoaDQpO1xuICAgIH1cbiAgICBzdHIgPSBlLmpvaW4oJycpOyAvLyB1c2UgQXJyYXkuam9pbigpIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2UgdGhhbiByZXBlYXRlZCBzdHJpbmcgYXBwZW5kc1xuICAgIC8vIHJlcGxhY2UgJ0EncyBmcm9tIHBhZGRlZCBudWxscyB3aXRoICc9J3NcbiAgICBzdHIgPSBzdHIuc2xpY2UoMCwgc3RyLmxlbmd0aCAtIHBhZC5sZW5ndGgpICsgcGFkO1xuICAgIHJldHVybiBzdHI7XG59O1xuZXhwb3J0IGNvbnN0IGdlbmVyYXRlSWQgPSAoKSA9PiB7XG4gICAgY29uc3QgcG9zc2libGUgPSBcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5XCI7XG4gICAgbGV0IHRleHQgPSBcIlwiO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgIHRleHQgKz0gcG9zc2libGUuY2hhckF0KE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHBvc3NpYmxlLmxlbmd0aCkpO1xuICAgIH1cbiAgICByZXR1cm4gdGV4dDtcbn07XG5leHBvcnQgY29uc3QgZ2V0U2Vzc2lvblN0b3JhZ2UgPSAoKSA9PiB7XG4gICAgaWYgKFwic2Vzc2lvblN0b3JhZ2VcIiBpbiB3aW5kb3cpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oXCJhYmNcIik7IC8vIGFjY2VzcyBzZXNzaW9uU3RvcmFnZSB0byB0cmlnZ2VyIGluY29nbml0byBtb2RlIGV4Y2VwdGlvbnNcbiAgICAgICAgICAgIHJldHVybiBzZXNzaW9uU3RvcmFnZTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY29va2llU3RvcmFnZSh2b2lkIDAsIFwiX19zZXNzaW9uU3RvcmFnZU1vY2tfX19cIik7XG59O1xuZnVuY3Rpb24gY29va2llU3RvcmFnZSh0dGxNaW51dGVzLCBzdG9yYWdlTmFtZSkge1xuICAgIGNvbnN0IExPQ0FMX1NUT1JBR0VfQ09PS0lFX05BTUUgPSBzdG9yYWdlTmFtZTtcbiAgICBmdW5jdGlvbiBnZXRTdG9yYWdlRnJvbUNvb2tpZSgpIHtcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZ2V0Q29va2llKExPQ0FMX1NUT1JBR0VfQ09PS0lFX05BTUUpIHx8IFwie31cIik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNhdmVTdG9yYWdlVG9Db29raWUoZGF0YSkge1xuICAgICAgICBzZXRDb29raWUoTE9DQUxfU1RPUkFHRV9DT09LSUVfTkFNRSwgZGF0YSwgdHRsTWludXRlcyk7IC8vIG9uZSB5ZWFyXG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGdldEl0ZW0oa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0U3RvcmFnZUZyb21Db29raWUoKVtrZXldIHx8IG51bGw7XG4gICAgICAgIH0sXG4gICAgICAgIHNldEl0ZW0oa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgY29uc3QgbG9jYWxTdG9yYWdlU3RhdGUgPSBnZXRTdG9yYWdlRnJvbUNvb2tpZSgpO1xuICAgICAgICAgICAgbG9jYWxTdG9yYWdlU3RhdGVba2V5XSA9IHZhbHVlO1xuICAgICAgICAgICAgc2F2ZVN0b3JhZ2VUb0Nvb2tpZShKU09OLnN0cmluZ2lmeShsb2NhbFN0b3JhZ2VTdGF0ZSkpO1xuICAgICAgICB9LFxuICAgICAgICByZW1vdmVJdGVtKGtleSkge1xuICAgICAgICAgICAgY29uc3QgbG9jYWxTdG9yYWdlU3RhdGUgPSBnZXRTdG9yYWdlRnJvbUNvb2tpZSgpO1xuICAgICAgICAgICAgZGVsZXRlIGxvY2FsU3RvcmFnZVN0YXRlW2tleV07XG4gICAgICAgICAgICBzYXZlU3RvcmFnZVRvQ29va2llKEpTT04uc3RyaW5naWZ5KGxvY2FsU3RvcmFnZVN0YXRlKSk7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFyKCkge1xuICAgICAgICAgICAgY29uc3QgbG9jYWxTdG9yYWdlU3RhdGUgPSB7fTtcbiAgICAgICAgICAgIHNhdmVTdG9yYWdlVG9Db29raWUoSlNPTi5zdHJpbmdpZnkobG9jYWxTdG9yYWdlU3RhdGUpKTtcbiAgICAgICAgfSxcbiAgICAgICAga2V5KG4pIHtcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsU3RvcmFnZVN0YXRlID0gZ2V0U3RvcmFnZUZyb21Db29raWUoKTtcbiAgICAgICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhsb2NhbFN0b3JhZ2VTdGF0ZSk7XG4gICAgICAgICAgICBpZiAobiA+IGtleXMubGVuZ3RoIC0gMSlcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBrZXlzW25dO1xuICAgICAgICB9LFxuICAgICAgICBnZXQgbGVuZ3RoKCkge1xuICAgICAgICAgICAgY29uc3QgbG9jYWxTdG9yYWdlU3RhdGUgPSBnZXRTdG9yYWdlRnJvbUNvb2tpZSgpO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGxvY2FsU3RvcmFnZVN0YXRlKS5sZW5ndGg7XG4gICAgICAgIH1cbiAgICB9O1xufVxuZXhwb3J0IGNvbnN0IHNldENvb2tpZSA9IChuYW1lLCB2YWx1ZSwgdHRsTWludXRlcykgPT4ge1xuICAgIGxldCBleHBpcmVzID0gXCJcIjtcbiAgICBpZiAodHRsTWludXRlcykge1xuICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpICsgKHR0bE1pbnV0ZXMgKiA2MCAqIDEwMDApKTtcbiAgICAgICAgZXhwaXJlcyA9IFwiOyBleHBpcmVzPVwiICsgZGF0ZS50b1VUQ1N0cmluZygpO1xuICAgIH1cbiAgICAvLyBIYW5kbGUgdGhlIHVwY29taW5nIGZvcmNlZCBzd2l0Y2ggdG8gU2FtZVNpdGUgJiBTZWN1cmUgcGFyYW1zIGh0dHBzOi8vd3d3LmNocm9tZXN0YXR1cy5jb20vZmVhdHVyZS81NjMzNTIxNjIyMTg4MDMyXG4gICAgLy8gU2luY2UgdGhpcyBpcyBhIGdlbmVyaWMgbGlicmFyeSwgd2UgY2FuJ3QgcmVzdHJpY3QgdGhlIGRvbWFpbiB1bmRlciB3aGljaCBpdCdzIGJlZWluZyBzZXJ2ZWQsIHRodXMgbm90IHNldHRpbmcgZG9tYWluXG4gICAgLy8gZm9yIHRoZSBjb29raWUuIEl0J3MgdXN1YWxseSBsb2FkZWQgYW5kIHN1YnNlcXVlbnRseSByZXF1ZXN0ZWQgZnJvbSBhIHRoaXJkLXBhcnR5IGRvbWFpbiwgdGh1cyB3ZSBuZWVkIHRvIHNwZWNpZnkgU2FtZVNpdGU9Tm9uZSB3aGljaFxuICAgIC8vIHBlciB0aGUgbGF0ZXN0IHNwZWNpZmljYXRpb25zIHJlcXVpcmVzIHRoZSBTZWN1cmUgYXR0cmlidXRlLlxuICAgIC8vXG4gICAgLy8gVG8gYWxsb3cgbG9jYWwgZGVidWdnaW5nLCB3ZSB3b24ndCBzZXQgdGhlc2Ugd2hlbiBsb2FkZWQgb24gbG9jYWxob3N0LiBOb3RlLCBhZnRlciB0aGlzIGNoYW5nZSwgeW91IHdvbid0IGJlIGFibGUgdG8gc2VydmVcbiAgICAvLyB0aGUgY29sbGVjdG9yIHRvIHJlYWwgY2xpZW50cyBvdmVyIG5vbi1odHRwcyBjb25uZWN0aW9ucyAtIHRoZSBzZXNzaW9uIGNvb2tpZXMgd29uJ3QgbWF0Y2hcbiAgICBjb25zdCBzYW1lU2l0ZSA9IHdpbmRvdy5sb2NhdGlvbi5ob3N0bmFtZSA9PT0gXCJsb2NhbGhvc3RcIiA/IFwiXCIgOiBcIjsgU2FtZVNpdGU9Tm9uZTsgU2VjdXJlXCI7XG4gICAgZG9jdW1lbnQuY29va2llID0gbmFtZSArIFwiPVwiICsgKHZhbHVlIHx8IFwiXCIpICsgZXhwaXJlcyArIFwiOyBwYXRoPS9cIiArIHNhbWVTaXRlO1xuICAgIHJldHVybiB2YWx1ZTtcbn07XG5leHBvcnQgY29uc3QgZ2V0Q29va2llID0gKGNuYW1lKSA9PiB7XG4gICAgY29uc3QgbmFtZSA9IGNuYW1lICsgXCI9XCI7XG4gICAgY29uc3QgZGVjb2RlZENvb2tpZSA9IGRlY29kZVVSSUNvbXBvbmVudChkb2N1bWVudC5jb29raWUpO1xuICAgIGNvbnN0IGNhID0gZGVjb2RlZENvb2tpZS5zcGxpdCgnOycpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2EubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IGMgPSBjYVtpXTtcbiAgICAgICAgd2hpbGUgKGMuY2hhckF0KDApID09ICcgJykge1xuICAgICAgICAgICAgYyA9IGMuc3Vic3RyaW5nKDEpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjLmluZGV4T2YobmFtZSkgPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGMuc3Vic3RyaW5nKG5hbWUubGVuZ3RoLCBjLmxlbmd0aCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFwiXCI7XG59O1xuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIGFzIGxvbmcgYXMgaXQgY29udGludWVzIHRvIGJlIGludm9rZWQsIHdpbGwgbm90XG4gKiBiZSB0cmlnZ2VyZWQuIFRoZSBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBhZnRlciBpdCBzdG9wcyBiZWluZyBjYWxsZWQgZm9yXG4gKiBOIG1pbGxpc2Vjb25kcy4gSWYgYGltbWVkaWF0ZWAgaXMgcGFzc2VkLCB0cmlnZ2VyIHRoZSBmdW5jdGlvbiBvbiB0aGVcbiAqIGxlYWRpbmcgZWRnZSwgaW5zdGVhZCBvZiB0aGUgdHJhaWxpbmcuIFRoZSBmdW5jdGlvbiBhbHNvIGhhcyBhIHByb3BlcnR5ICdjbGVhcidcbiAqIHRoYXQgaXMgYSBmdW5jdGlvbiB3aGljaCB3aWxsIGNsZWFyIHRoZSB0aW1lciB0byBwcmV2ZW50IHByZXZpb3VzbHkgc2NoZWR1bGVkIGV4ZWN1dGlvbnMuXG4gKlxuICogQHNvdXJjZSB1bmRlcnNjb3JlLmpzXG4gKiBAc2VlIGh0dHA6Ly91bnNjcmlwdGFibGUuY29tLzIwMDkvMDMvMjAvZGVib3VuY2luZy1qYXZhc2NyaXB0LW1ldGhvZHMvXG4gKiBAcGFyYW0gZnVuYyB7RnVuY3Rpb259IGZ1bmN0aW9uIHRvIHdyYXBcbiAqIEBwYXJhbSB3YWl0IHtOdW1iZXJ9IHRpbWVvdXQgaW4gbXMgKGAxMDBgKVxuICogQHBhcmFtIGltbWVkaWF0ZSB7Qm9vbGVhbn0gd2hldGhlciB0byBleGVjdXRlIGF0IHRoZSBiZWdpbm5pbmcgKGBmYWxzZWApXG4gKiBAYXBpIHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgZGVib3VuY2UgPSAoZnVuYywgd2FpdCA9IDEwMCwgaW1tZWRpYXRlID0gZmFsc2UpID0+IHtcbiAgICB2YXIgdGltZW91dCwgYXJncywgY29udGV4dCwgdGltZXN0YW1wLCByZXN1bHQ7XG4gICAgZnVuY3Rpb24gbGF0ZXIoKSB7XG4gICAgICAgIHZhciBsYXN0ID0gRGF0ZS5ub3coKSAtIHRpbWVzdGFtcDtcbiAgICAgICAgaWYgKGxhc3QgPCB3YWl0ICYmIGxhc3QgPj0gMCkge1xuICAgICAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQgLSBsYXN0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgaWYgKCFpbW1lZGlhdGUpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBkZWJvdW5jZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnRleHQgPSB0aGlzO1xuICAgICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICB2YXIgY2FsbE5vdyA9IGltbWVkaWF0ZSAmJiAhdGltZW91dDtcbiAgICAgICAgaWYgKCF0aW1lb3V0KVxuICAgICAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQpO1xuICAgICAgICBpZiAoY2FsbE5vdykge1xuICAgICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgZGVib3VuY2VkLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGltZW91dCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGRlYm91bmNlZC5mbHVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRpbWVvdXQpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIGRlYm91bmNlZDtcbn07XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9Db250ZXh0XCI7XG5leHBvcnQgKiBmcm9tIFwiLi9MaXN0ZW5lclR5cGVcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0xvY2FsU3RvcmFnZVF1ZXVlXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9TZW50aW5lbFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vVXRpbFwiO1xuIiwiaW1wb3J0IHsgYmFzZTY0RW5jb2RlIH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5leHBvcnQgY2xhc3MgQmFzZTY0RW5jb2RlV3JpdGVyIHtcbiAgICBjb25zdHJ1Y3RvcihkZWxlZ2F0ZSkge1xuICAgICAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7XG4gICAgfVxuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgY29uc3QgZCA9IEpTT04uc3RyaW5naWZ5KGRhdGEpO1xuICAgICAgICB0aGlzLmRlbGVnYXRlLndyaXRlKGJhc2U2NEVuY29kZShlbmNvZGVVUklDb21wb25lbnQoZCkpKTtcbiAgICB9XG59XG4iLCJleHBvcnQgY2xhc3MgQnJvd3NlclRyYWNraW5nV3JpdGVyIHtcbiAgICBjb25zdHJ1Y3RvcihkZWxlZ2F0ZSwgb3B0aW9ucykge1xuICAgICAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgfVxuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgY29uc3QgeyByZWNvcmRVcmwsIHJlY29yZFJlZmVycmVyLCByZWNvcmRMYW5ndWFnZSB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAocmVjb3JkVXJsICYmICFkYXRhLnVybClcbiAgICAgICAgICAgIGRhdGEudXJsID0gdGhpcy5nZXRXaW5kb3coKS5sb2NhdGlvbi5ocmVmO1xuICAgICAgICBpZiAocmVjb3JkUmVmZXJyZXIgJiYgIWRhdGEucmVmKVxuICAgICAgICAgICAgZGF0YS5yZWYgPSB0aGlzLmdldERvY3VtZW50KCkucmVmZXJyZXI7XG4gICAgICAgIGlmIChyZWNvcmRMYW5ndWFnZSAmJiAhZGF0YS5sYW5nKVxuICAgICAgICAgICAgZGF0YS5sYW5nID0gdGhpcy5nZXRXaW5kb3coKS5uYXZpZ2F0b3IubGFuZ3VhZ2U7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUud3JpdGUoZGF0YSk7XG4gICAgfVxuICAgIGdldERvY3VtZW50KCkge1xuICAgICAgICBjb25zdCB7IGNvbnRleHQgfSA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgcmV0dXJuIGNvbnRleHQgPyBjb250ZXh0LmdldERvY3VtZW50KCkgOiBkb2N1bWVudDtcbiAgICB9XG4gICAgZ2V0V2luZG93KCkge1xuICAgICAgICBjb25zdCB7IGNvbnRleHQgfSA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgcmV0dXJuIGNvbnRleHQgPyBjb250ZXh0LmdldFdpbmRvdygpIDogd2luZG93O1xuICAgIH1cbn1cbiIsImltcG9ydCB7IExvY2FsU3RvcmFnZVF1ZXVlIH0gZnJvbSBcIi4uL3V0aWxzL0xvY2FsU3RvcmFnZVF1ZXVlXCI7XG4vKipcbiAqIEEgd3JpdGVyIHRoYXQgYnVmZmVycyB0aGUgaW5jb21pbmcgZXZlbnRzIGluIGEgbG9jYWwgc3RvcmFnZSBxdWV1ZSBhbmQgd3JpdGVzXG4gKiB0aGVtIG91dCBpbiBiYXRjaGVzIGV2ZXJ5IHNlY29uZC4gSWYgdGhlIHF1ZXVlIGlzIG5vdCBlbXB0eSwgd2hlbiB0aGUgdGltZXIgdGlja3NcbiAqIHRoZSB3cml0ZXIgd2lsbCBzZW5kIHRoZSBhdmFpbGFibGUgZGF0YSByZWdhcmRsZXNzIG9mIHdoZXRoZXIgdGhlcmUgYXJlIGNvbGxlY3RvciBldmVudHMgaS5lLlxuICogZXZlbiBpbiB0aW1lcyBvZiBpbmFjdGl2aXR5IG9yIHdoZW4gbG9hZGluZyB0aGUgcGFnZSBhbmQgcHJldmlvdXMgc3RhdGUgaXMgYXZhaWxhYmxlLlxuICpcbiAqIFRoZSB3cml0ZXIgd2lsbCBhbHNvIHRyeSB0byBzZW5kIHRoZSBhdmFpbGFibGUgZGF0YSBvbiBicm93c2VyIHVubG9hZCBldmVudC5cbiAqL1xuZXhwb3J0IGNsYXNzIEJ1ZmZlcmluZ1dyaXRlciB7XG4gICAgY29uc3RydWN0b3IoZGVsZWdhdGUsIGlkLCB0aW1lck1zID0gMTAwMCkge1xuICAgICAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7XG4gICAgICAgIHRoaXMucXVldWUgPSBuZXcgTG9jYWxTdG9yYWdlUXVldWUoaWQpO1xuICAgICAgICB0aGlzLnRpbWVyTXMgPSB0aW1lck1zO1xuICAgICAgICB0aGlzLnRpbWVyID0gc2V0VGltZW91dCh0aGlzLmZsdXNoLmJpbmQodGhpcyksIHRpbWVyTXMpO1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgfVxuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgdGhpcy5xdWV1ZS5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICBmbHVzaChjYW5jZWxUaW1lcikge1xuICAgICAgICBpZiAodGhpcy5xdWV1ZS5zaXplKCkgPiAwKSB7XG4gICAgICAgICAgICAvLyBpZiB0aGUgYnJvd3NlciBzaHV0c2Rvd24gYmVmb3JlIHRoZSB3cml0ZSBpcyBjb21wbGV0ZVxuICAgICAgICAgICAgdGhpcy5xdWV1ZS50cmFuc2FjdGlvbmFsRHJhaW4ocXVldWUgPT4gbmV3IFByb21pc2UocmVzID0+IHJlcyh0aGlzLmRlbGVnYXRlLndyaXRlKHF1ZXVlKSkpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5lcnJvcihcImNvdWxkIG5vdCBkcmFpbiBxdWV1ZTogXCIsIGVycikpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghY2FuY2VsVGltZXIpIHtcbiAgICAgICAgICAgIHRoaXMudGltZXIgPSBzZXRUaW1lb3V0KHRoaXMuZmx1c2guYmluZCh0aGlzKSwgdGhpcy50aW1lck1zKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsImV4cG9ydCBjbGFzcyBDb25zb2xlV3JpdGVyIHtcbiAgICB3cml0ZShkYXRhKSB7XG4gICAgICAgIGNvbnNvbGUuZGVidWcoXCJDb25zb2xlV3JpdGVyIHJlY2VpdmluZyBuZXcgZGF0YTogXCIpO1xuICAgICAgICBjb25zb2xlLmxvZyhkYXRhKTtcbiAgICB9XG59XG4iLCIvKipcbiAqIExvZ3MgdGhlIGRhdGEgdG8gdGhlIGJyb3dzZXIgY29uc29sZSB1c2luZyBjb25zb2xlLmRlYnVnXG4gKi9cbmV4cG9ydCBjbGFzcyBEZWJ1Z1dyaXRlciB7XG4gICAgY29uc3RydWN0b3IoZGVsZWdhdGUsIGRlYnVnKSB7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTtcbiAgICAgICAgdGhpcy5kZWJ1ZyA9IGRlYnVnO1xuICAgIH1cbiAgICB3cml0ZShkYXRhKSB7XG4gICAgICAgIGlmICh0aGlzLmRlYnVnKVxuICAgICAgICAgICAgY29uc29sZS5sb2coZGF0YSk7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUud3JpdGUoZGF0YSk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgU1FTRXZlbnRXcml0ZXIgfSBmcm9tIFwiLi9TUVNFdmVudFdyaXRlclwiO1xuaW1wb3J0IHsgUmVzdEV2ZW50V3JpdGVyIH0gZnJvbSBcIi4vUmVzdEV2ZW50V3JpdGVyXCI7XG5pbXBvcnQgeyBCdWZmZXJpbmdXcml0ZXIgfSBmcm9tIFwiLi9CdWZmZXJpbmdXcml0ZXJcIjtcbmltcG9ydCB7IEJhc2U2NEVuY29kZVdyaXRlciB9IGZyb20gXCIuL0Jhc2U2NEVuY29kZVdyaXRlclwiO1xuaW1wb3J0IHsgSlNPTkVudmVsb3BlV3JpdGVyIH0gZnJvbSBcIi4vSlNPTkVudmVsb3BlV3JpdGVyXCI7XG5pbXBvcnQgeyBUcmFpbFdyaXRlciB9IGZyb20gXCIuL1RyYWlsV3JpdGVyXCI7XG5pbXBvcnQgeyBCcm93c2VyVHJhY2tpbmdXcml0ZXIgfSBmcm9tIFwiLi9Ccm93c2VyVHJhY2tpbmdXcml0ZXJcIjtcbmltcG9ydCB7IERlYnVnV3JpdGVyIH0gZnJvbSBcIi4vRGVidWdXcml0ZXJcIjtcbmltcG9ydCB7IFF1ZXJ5V3JpdGVyIH0gZnJvbSBcIi4vUXVlcnlXcml0ZXJcIjtcbmltcG9ydCB7IFRyYWlsIH0gZnJvbSBcIi4uL3F1ZXJ5L1RyYWlsXCI7XG5leHBvcnQgY2xhc3MgRGVmYXVsdFdyaXRlciB7XG4gICAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgICAgICBjb25zdCB7IGVuZHBvaW50LCBzcXMgfSA9IG9wdGlvbnM7XG4gICAgICAgIC8vIFdyaXRlciBwaXBlbGluZSwgYWRkL3JlbW92ZSBwaWVjZXMgYWNjb3JkaW5nIHRvIHVzZSBjYXNlXG4gICAgICAgIC8vIFRoaXMgd3JpdGVyIHBpcGVsaW5lIHdpbGwgc2VuZCBCYXNlNjQgZW5jb2RlZCBhcnJheSBvZiBqc29uIGV2ZW50c1xuICAgICAgICBsZXQgd3JpdGVyID0gaXNTUVMoZW5kcG9pbnQsIHNxcykgPyBuZXcgU1FTRXZlbnRXcml0ZXIoZW5kcG9pbnQpIDogbmV3IFJlc3RFdmVudFdyaXRlcihlbmRwb2ludCk7XG4gICAgICAgIHdyaXRlciA9IG5ldyBCYXNlNjRFbmNvZGVXcml0ZXIod3JpdGVyKTtcbiAgICAgICAgd3JpdGVyID0gbmV3IEJ1ZmZlcmluZ1dyaXRlcih3cml0ZXIsIFwiYnVmZmVyOlwiICsgb3B0aW9ucy5lbmRwb2ludCk7XG4gICAgICAgIHdyaXRlciA9IG5ldyBEZWJ1Z1dyaXRlcih3cml0ZXIsIG9wdGlvbnMuZGVidWcpO1xuICAgICAgICB3cml0ZXIgPSBuZXcgUXVlcnlXcml0ZXIod3JpdGVyLCBvcHRpb25zLnJlc29sdmVyLnF1ZXJ5UmVzb2x2ZXIpO1xuICAgICAgICB3cml0ZXIgPSBuZXcgVHJhaWxXcml0ZXIod3JpdGVyLCBvcHRpb25zLnRyYWlsIHx8IG5ldyBUcmFpbChvcHRpb25zLnJlc29sdmVyLnF1ZXJ5UmVzb2x2ZXIsIG9wdGlvbnMucmVzb2x2ZXIuc2Vzc2lvblJlc29sdmVyKSwgb3B0aW9ucy5yZXNvbHZlci5xdWVyeVJlc29sdmVyKTtcbiAgICAgICAgd3JpdGVyID0gbmV3IEpTT05FbnZlbG9wZVdyaXRlcih3cml0ZXIsIG9wdGlvbnMucmVzb2x2ZXIuc2Vzc2lvblJlc29sdmVyLCBvcHRpb25zLmNoYW5uZWwpO1xuICAgICAgICB3cml0ZXIgPSBuZXcgQnJvd3NlclRyYWNraW5nV3JpdGVyKHdyaXRlciwge1xuICAgICAgICAgICAgcmVjb3JkUmVmZXJyZXI6IG9wdGlvbnMucmVjb3JkUmVmZXJyZXIsXG4gICAgICAgICAgICByZWNvcmRVcmw6IG9wdGlvbnMucmVjb3JkVXJsLFxuICAgICAgICAgICAgcmVjb3JkTGFuZ3VhZ2U6IG9wdGlvbnMucmVjb3JkTGFuZ3VhZ2VcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMud3JpdGVyID0gd3JpdGVyO1xuICAgIH1cbiAgICB3cml0ZShkYXRhKSB7XG4gICAgICAgIHRoaXMud3JpdGVyLndyaXRlKGRhdGEpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGlzU1FTKGVuZHBvaW50LCBmb3JjZVNRUykge1xuICAgIHJldHVybiBmb3JjZVNRUyB8fCAoZW5kcG9pbnQuaW5kZXhPZihcInNxc1wiKSAhPSAtMSAmJiBlbmRwb2ludC5pbmRleE9mKFwiYW1hem9uYXdzLmNvbVwiKSAhPSAtMSk7XG59XG4iLCIvKipcbiAqIFdyYXAgdGhlIGV2ZW50cyBpbiBhIEpTT04gZW52ZWxvcGUsIGVucmljaCBlYWNoIHJlY29yZCB3aXRoIHRpbWVzdGFtcCwgc2Vzc2lvbiBhbmQgY2hhbm5lbCBpbmZvcm1hdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIEpTT05FbnZlbG9wZVdyaXRlciB7XG4gICAgY29uc3RydWN0b3IoZGVsZWdhdGUsIHNlc3Npb25SZXNvbHZlciwgY2hhbm5lbCkge1xuICAgICAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7XG4gICAgICAgIHRoaXMuc2Vzc2lvblJlc29sdmVyID0gc2Vzc2lvblJlc29sdmVyO1xuICAgICAgICB0aGlzLmNoYW5uZWwgPSBjaGFubmVsO1xuICAgIH1cbiAgICB3cml0ZShkYXRhKSB7XG4gICAgICAgIGlmICghZGF0YS50aW1lc3RhbXApXG4gICAgICAgICAgICBkYXRhLnRpbWVzdGFtcCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICBkYXRhLnNlc3Npb24gPSB0aGlzLnNlc3Npb25SZXNvbHZlcigpO1xuICAgICAgICBkYXRhLmNoYW5uZWwgPSB0aGlzLmNoYW5uZWw7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUud3JpdGUoZGF0YSk7XG4gICAgfVxufVxuIiwiLyoqXG4gKiBBcHBlbmRzIHRoZSBxdWVyeSB0byB0aGUgZGF0YSBpZiBubyBxdWVyeSBwcm9wZXJ0eSBleGlzdHNcbiAqL1xuZXhwb3J0IGNsYXNzIFF1ZXJ5V3JpdGVyIHtcbiAgICBjb25zdHJ1Y3RvcihkZWxlZ2F0ZSwgcXVlcnlSZXNvbHZlcikge1xuICAgICAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7XG4gICAgICAgIHRoaXMucXVlcnlSZXNvbHZlciA9IHF1ZXJ5UmVzb2x2ZXI7XG4gICAgfVxuICAgIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgaWYgKCFkYXRhLnF1ZXJ5KVxuICAgICAgICAgICAgZGF0YS5xdWVyeSA9IHRoaXMucXVlcnlSZXNvbHZlcigpLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUud3JpdGUoZGF0YSk7XG4gICAgfVxufVxuIiwiLyoqXG4gKiBTdHJhaWdodC1mb3J3YXJkIFJFU1Qgd3JpdGUgdmlhIEdFVCByZXF1ZXN0XG4gKi9cbmV4cG9ydCBjbGFzcyBSZXN0RXZlbnRXcml0ZXIge1xuICAgIGNvbnN0cnVjdG9yKGVuZHBvaW50KSB7XG4gICAgICAgIHRoaXMuZW5kcG9pbnQgPSBlbmRwb2ludDtcbiAgICB9XG4gICAgd3JpdGUoZGF0YSkge1xuICAgICAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgaW1nLnNyYyA9IHRoaXMuZW5kcG9pbnQgKyBcIj9kYXRhPVwiICsgSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgfVxufVxuIiwiZXhwb3J0IGNsYXNzIFNRU0V2ZW50V3JpdGVyIHtcbiAgICBjb25zdHJ1Y3RvcihxdWV1ZSwgZmlmbyA9IGZhbHNlKSB7XG4gICAgICAgIHRoaXMucXVldWUgPSBxdWV1ZTtcbiAgICAgICAgdGhpcy5maWZvID0gZmlmbztcbiAgICB9XG4gICAgd3JpdGUoZGF0YSkge1xuICAgICAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgbGV0IHNyYyA9IHRoaXMucXVldWUgKyBcIj9WZXJzaW9uPTIwMTItMTEtMDUmQWN0aW9uPVNlbmRNZXNzYWdlXCI7XG4gICAgICAgIC8vIFNRUyBzdXBwb3J0cyBGSUZPIHF1ZXVlcyBpbiBzb21lIHJlZ2lvbnMgdGhhdCBjYW4gYWxzbyBndWFyYW50ZWUgdGhlIG9yZGVyXG4gICAgICAgIC8vIG9mIHRoZSBtZXNzYWdlcy5cbiAgICAgICAgaWYgKHRoaXMuZmlmbykge1xuICAgICAgICAgICAgLy8gVE9ETyB3aGVuIGVub3VnaCBpbmZvcm1hdGlvbiBpcyBwcmVzZW50IHRvIHVuaXF1ZWx5IGlkZW50aWZ5IGEgbWVzc2FnZSwgc3dpdGNoIHRoZSBkZWR1cGxpY2F0aW9uIGlkIHRvIGEgbWVzc2FnZSBoYXNoXG4gICAgICAgICAgICBzcmMgKz0gXCImTWVzc2FnZUdyb3VwSWQ9MSZNZXNzYWdlRGVkdXBsaWNhdGlvbklkPVwiICsgTWF0aC5yYW5kb20oKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGRhdGEgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIGRhdGEgPSBKU09OLnN0cmluZ2lmeShkYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBzcmMgKz0gXCImTWVzc2FnZUJvZHk9XCIgKyBkYXRhO1xuICAgICAgICBpbWcuc3JjID0gc3JjO1xuICAgIH1cbn1cbiIsIi8qKlxuICogQ2FsbHMgYWxsIHdyaXRlcnMgcGFzc2VkIHRvIHRoZSBjb25zdHJ1Y3RvciBlcnJvciBzYWZlXG4gKi9cbmV4cG9ydCBjbGFzcyBTcGxpdFN0cmVhbVdyaXRlciB7XG4gICAgY29uc3RydWN0b3Iod3JpdGVycykge1xuICAgICAgICB0aGlzLndyaXRlcnMgPSB3cml0ZXJzO1xuICAgIH1cbiAgICB3cml0ZShkYXRhKSB7XG4gICAgICAgIGZvciAobGV0IHdyaXRlciBvZiB0aGlzLndyaXRlcnMpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgd3JpdGVyLndyaXRlKGRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiQ291bGQgbm90IHdyaXRlIGRhdGE6IFwiLCBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbiIsImV4cG9ydCBjbGFzcyBUcmFpbFdyaXRlciB7XG4gICAgY29uc3RydWN0b3IoZGVsZWdhdGUsIHRyYWlsLCBxdWVyeVJlc29sdmVyKSB7XG4gICAgICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTtcbiAgICAgICAgdGhpcy50cmFpbCA9IHRyYWlsO1xuICAgICAgICB0aGlzLnF1ZXJ5UmVzb2x2ZXIgPSBxdWVyeVJlc29sdmVyO1xuICAgIH1cbiAgICB3cml0ZShkYXRhKSB7XG4gICAgICAgIGNvbnN0IHEgPSB0aGlzLnF1ZXJ5UmVzb2x2ZXIoKTtcbiAgICAgICAgaWYgKCghcSB8fCAhcS5pc1ZhbGlkKCkpICYmICFkYXRhLnF1ZXJ5ICYmIHRoaXMuaXNBcHBlbmRUcmFpbChkYXRhKSkge1xuICAgICAgICAgICAgLy8gU2VlIGlmIHdlIGhhdmUgYSBwYXlsb2FkIGlkIGFuZCBhIHRyYWlsIGZvciBpdC4gVGhpcyBtZWFucyB3ZVxuICAgICAgICAgICAgLy8gYXJlIGNvbGxlY3RpbmcgZGF0YSBmb3IgYW4gZXZlbnQgdGhhdCBkb2VzIG5vdCBoYXZlIGEgcXVlcnkgY29udGV4dFxuICAgICAgICAgICAgLy8gb24gdGhlIHBhZ2UgYW55bW9yZSBidXQgd2Ugd2FudCB0byBhc3NvY2lhdGUgdGhlIGV2ZW50IHdpdGggdGhlIHF1ZXJ5XG4gICAgICAgICAgICAvLyBjb250ZXh0IG9mIHRoZSBvcmlnaW5hbCBzZWFyY2ggcmVzdWx0XG4gICAgICAgICAgICB0aGlzLmFwcGVuZFRyYWlsKGRhdGEpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGVsZWdhdGUud3JpdGUoZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFwcGVuZCB0aGUgVHJhaWwgaWYgYW55XG4gICAgICogQHBhcmFtIGRhdGFcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGFwcGVuZFRyYWlsKGRhdGEpIHtcbiAgICAgICAgY29uc3QgdHJhaWwgPSB0aGlzLnRyYWlsLmZldGNoKHRoaXMuZ2V0SWQoZGF0YSkpO1xuICAgICAgICBpZiAodHJhaWwgJiYgdHJhaWwucXVlcnkpIHtcbiAgICAgICAgICAgIGRhdGEucXVlcnkgPSB0cmFpbC5xdWVyeTtcbiAgICAgICAgICAgIGRhdGEucXVlcnlUaW1lID0gdHJhaWwudGltZXN0YW1wO1xuICAgICAgICAgICAgZGF0YS50cmFpbFR5cGUgPSB0cmFpbC50eXBlO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIGZvciBsZWdhY3kgc3VwcG9ydDogc29tZXRpbWVzIGRhdGEgd2FzIHdyYXBwZWQgaW4gcHJvcGVydHkgY2FsbGVkIFwiZGF0YVwiXG4gICAgICogQHBhcmFtIGRhdGFcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldElkKGRhdGEpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICBpZiAoZGF0YSlcbiAgICAgICAgICAgIHJldHVybiBkYXRhLmlkIHx8ICgoX2EgPSBkYXRhLmRhdGEpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5pZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEV2YWx1YXRlcyBpZiB0aGUgVHJhaWwgc2hvdWxkIGJlIGFwcGVuZGVkIHRvIHRoaXMgZXZlbnRcbiAgICAgKiBAcGFyYW0gZGF0YVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgaXNBcHBlbmRUcmFpbChkYXRhKSB7XG4gICAgICAgIHJldHVybiBkYXRhICYmIFtcImNoZWNrb3V0XCIsIFwiYmFza2V0XCIsIFwiZmlsdGVyXCJdLmluZGV4T2YoZGF0YS50eXBlKSA+IC0xO1xuICAgICAgICAvLyBUQTogVGhpcyB3YXMgcHJldmlvdXNseSBcImRhdGEuZGF0YSAmJiBkYXRhLmRhdGEuaWQgJiYgdGhpcy50cmFpbFwiXG4gICAgICAgIC8vIHRoZSBvbmx5IENvbGxlY3RvcnMgYXBwZW5kaW5nIGEgcHJvcGVydHkgY2FsbGVkIFwiZGF0YVwiIHRvIGl0cyBldmVudCBhcmUgQ2xpY2tDb2xsZWN0b3IgaS5lLlxuICAgICAgICAvLyBDaGVja291dENsaWNrQ29sbGVjdG9yLCBCYXNrZXRDbGlja0NvbGxlY3RvciwgRmlsdGVyQ2xpY2tDb2xsZWN0b3JcbiAgICAgICAgLy8gSSd2ZSByZWZhY3RvcmVkIHRoaXMgaW1wbGljaXQgY29uZGl0aW9uIHRvIHRoaXMgZnVuY3Rpb25cbiAgICAgICAgLy8gVE9ETyB2YWxpZGF0ZSBpZiB0aGluZ3Mgd2lsbCBicmVhayB3aXRoIG5ldyBpbXBsXG4gICAgfVxufVxuIiwiZXhwb3J0ICogZnJvbSBcIi4vQmFzZTY0RW5jb2RlV3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9CdWZmZXJpbmdXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0RlZmF1bHRXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0pTT05FbnZlbG9wZVdyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vUmVzdEV2ZW50V3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9TcGxpdFN0cmVhbVdyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vU1FTRXZlbnRXcml0ZXJcIjtcbiIsImV4cG9ydCAqIGZyb20gXCIuL0Jhc2U2NEVuY29kZVdyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vQnJvd3NlclRyYWNraW5nV3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9CdWZmZXJpbmdXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0NvbnNvbGVXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL0RlYnVnV3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9EZWZhdWx0V3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9KU09ORW52ZWxvcGVXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1F1ZXJ5V3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9SZXN0RXZlbnRXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1NwbGl0U3RyZWFtV3JpdGVyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9TUVNFdmVudFdyaXRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vVHJhaWxXcml0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1dyaXRlclwiO1xuIiwiLy8gVGhlIG1vZHVsZSBjYWNoZVxudmFyIF9fd2VicGFja19tb2R1bGVfY2FjaGVfXyA9IHt9O1xuXG4vLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcblx0dmFyIGNhY2hlZE1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF07XG5cdGlmIChjYWNoZWRNb2R1bGUgIT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiBjYWNoZWRNb2R1bGUuZXhwb3J0cztcblx0fVxuXHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuXHR2YXIgbW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXSA9IHtcblx0XHQvLyBubyBtb2R1bGUuaWQgbmVlZGVkXG5cdFx0Ly8gbm8gbW9kdWxlLmxvYWRlZCBuZWVkZWRcblx0XHRleHBvcnRzOiB7fVxuXHR9O1xuXG5cdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuXHRfX3dlYnBhY2tfbW9kdWxlc19fW21vZHVsZUlkXShtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuXHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuXHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG59XG5cbiIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJleHBvcnQgKiBmcm9tIFwiLi9Db2xsZWN0b3JNb2R1bGVcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2NvbGxlY3RvcnMvXCI7XG5leHBvcnQgKiBmcm9tIFwiLi93cml0ZXJzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9xdWVyeVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbG9nZ2VyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9yZXNvbHZlcnNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3V0aWxzXCI7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=
\ No newline at end of file
diff --git a/demo/js/util.js b/demo/js/util.js
index 5035e7b..f16d965 100644
--- a/demo/js/util.js
+++ b/demo/js/util.js
@@ -43,8 +43,12 @@ document.addEventListener("DOMContentLoaded", () => {
event.preventDefault();
const query = document.querySelector("input").value;
- if (query)
+ if (query === "redirect" || query === '"redirect"') {
+ redirect(`/redirect-landing-page.html?query=${query}`);
+
+ } else if (query) {
redirect(`/product-listing.html?query=${query}`);
+ }
});
document.querySelector('[data-track-id="searchButton"]').addEventListener("click", event => {
const query = document.querySelector("input").value;
@@ -67,7 +71,7 @@ document.addEventListener("DOMContentLoaded", () => {
Array.from(document.querySelectorAll("main.products a")).forEach(anchor => {
anchor.addEventListener("click", (e) => {
e.preventDefault();
- redirect(`/product-detail.html?id=${e.currentTarget.getAttribute("data-product-id")}`)
+ redirect(`/product-detail.html?id=${e.currentTarget.parentElement.getAttribute("data-product-id")}`)
});
});
@@ -85,10 +89,14 @@ document.addEventListener("DOMContentLoaded", () => {
/**
* AddToBasket Click
*/
- Array.from(document.querySelectorAll("main.pdp button")).forEach(anchor => {
+ Array.from(document.querySelectorAll("main.pdp button, main.products button")).forEach(anchor => {
anchor.addEventListener("click", (e) => {
e.preventDefault();
- basket.add(e.currentTarget.getAttribute("data-product-id"));
+ if (e.currentTarget.hasAttribute("data-product-id")) {
+ basket.add(e.currentTarget.getAttribute("data-product-id"));
+ } else {
+ basket.add(e.currentTarget.parentElement.getAttribute("data-product-id"));
+ }
redirect(`/basket.html`)
});
});
diff --git a/demo/product-listing.html b/demo/product-listing.html
index ed0d778..6ed8a1b 100644
--- a/demo/product-listing.html
+++ b/demo/product-listing.html
@@ -64,77 +64,95 @@ Search Terms
document.querySelector("#searchPhrase").textContent = new URLSearchParams(window.location.search).get("query");
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
diff --git a/demo/redirect-landing-page.html b/demo/redirect-landing-page.html
new file mode 100644
index 0000000..ad0b67e
--- /dev/null
+++ b/demo/redirect-landing-page.html
@@ -0,0 +1,159 @@
+
+
+
+
+ Product Listing Page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
0
+
+
+
+
+
+
+
+
Search Terms
+
+
Jeans
+
Shoes
+
Shirts
+
Boots
+
Trousers
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Your search for produced 9 results
+
+
+
+
+
+
diff --git a/demo/sub-landing-page-one.html b/demo/sub-landing-page-one.html
new file mode 100644
index 0000000..69c8409
--- /dev/null
+++ b/demo/sub-landing-page-one.html
@@ -0,0 +1,145 @@
+
+
+
+
+ Product Listing Page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
0
+
+
+
+
+
+
+
+
Search Terms
+
+
Jeans
+
Shoes
+
Shirts
+
Boots
+
Trousers
+
+
+
+
+
+
+
+
+ Special Campaign Category Page 1
+
+
+ Your search for produced 9 results
+
+
+
+
+
+
diff --git a/demo/sub-landing-page-three.html b/demo/sub-landing-page-three.html
new file mode 100644
index 0000000..cb8168b
--- /dev/null
+++ b/demo/sub-landing-page-three.html
@@ -0,0 +1,145 @@
+
+
+
+
+ Product Listing Page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
0
+
+
+
+
+
+
+
+
Search Terms
+
+
Jeans
+
Shoes
+
Shirts
+
Boots
+
Trousers
+
+
+
+
+
+
+
+
+ Special Campaign Category Page 3
+
+
+ Your search for produced 9 results
+
+
+
+
+
+
diff --git a/demo/sub-landing-page-two.html b/demo/sub-landing-page-two.html
new file mode 100644
index 0000000..0da9837
--- /dev/null
+++ b/demo/sub-landing-page-two.html
@@ -0,0 +1,145 @@
+
+
+
+
+ Product Listing Page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
0
+
+
+
+
+
+
+
+
Search Terms
+
+
Jeans
+
Shoes
+
Shirts
+
Boots
+
Trousers
+
+
+
+
+
+
+
+
+ Special Campaign Category Page 2
+
+
+ Your search for produced 9 results
+
+
+
+
+
+
diff --git a/src/main/collectors/ProductClickCollector.ts b/src/main/collectors/ProductClickCollector.ts
index 7361b63..34f953e 100644
--- a/src/main/collectors/ProductClickCollector.ts
+++ b/src/main/collectors/ProductClickCollector.ts
@@ -3,6 +3,7 @@ import {ListenerType} from "../utils/ListenerType";
import {AnyResolver, NumberResolver, StringResolver} from "../resolvers/Resolver";
import {Trail} from "../query/Trail";
import {TrailType} from "../query";
+import {normalizePathname} from "../utils";
export type ProductClickCollectorResolver = {
idResolver: StringResolver,
@@ -52,7 +53,7 @@ export class ProductClickCollector extends ClickCollector {
if (this.trail) {
// After a redirect a trail with the pathname is registered containing the query which triggered the redirect.
// If we have such a query we use it to build the trail.
- const trailData = this.trail.fetch(location.pathname);
+ const trailData = this.trail.fetch(normalizePathname(location.pathname));
if (trailData) {
clickData.query = trailData.query;
}
diff --git a/src/main/collectors/RedirectCollector.ts b/src/main/collectors/RedirectCollector.ts
index f2cb6e0..b4a41fd 100644
--- a/src/main/collectors/RedirectCollector.ts
+++ b/src/main/collectors/RedirectCollector.ts
@@ -7,29 +7,73 @@ import {
NumberResolver,
StringResolver
} from "../resolvers/Resolver";
-import {getSessionStorage} from "../utils";
+import {getSessionStorage, ListenerType, normalizePathname, Sentinel} from "../utils";
import {Query, Trail, TrailType} from "../query";
export type RedirectKpiCollectorParams = {
resultCountResolver?: NumberResolver
collectors?: Array,
+ maxPathSegments?: number,
+ nestedRedirects?: {
+ subSelectors?: string[],
+ depth?: number
+ },
redirectTTLMillis?: number
}
+interface NestedRedirect {
+ query: string,
+ depth: number
+}
+
/**
* Keep track of human triggered searches followed by a redirect to a page different than the search result page
*/
export class RedirectCollector extends AbstractCollector {
- private static STORAGE_KEY = "__lastSearch";
+ /**
+ * Key used to store the keywords of the last executed search
+ */
+ private static LAST_SEARCH_STORAGE_KEY = "__lastSearch";
+
+ /**
+ * Key used to store query information for a given redirect landing page (path of the url)
+ */
private static PATH_STORAGE_KEY = "___pathStorage";
+ private static NESTED_REDIRECT_KEYWORDS_STORAGE_KEY = "___nestedRedirectKeywordsStorage";
+
private readonly resultCountResolver: NumberResolver;
private readonly collectors: Array;
private readonly queryResolver: (phrase) => Query;
private readonly sessionResolver: StringResolver;
private readonly redirectTTL: number;
private readonly redirectTrail: Trail;
+
+ /**
+ * Sub selectors to use when searching for elements which trigger redirects that are associated to the initial search query
+ * @private
+ */
+ private readonly subSelectors: string[];
+
+ /**
+ * Maximum number of path segments to store in the path storage
+ * @default -1 (unlimited)
+ * @private
+ */
+ private readonly maxPathSegments: number;
+
+ /**
+ * Maximum depth of nested redirects to track
+ * @default 1
+ * @private
+ */
+ private readonly depth: number;
+
+ /**
+ * Used to track if the collectors have been attached already in case attached is called multiple times
+ * @private
+ */
private isCollectorsAttached = false;
/**
@@ -37,6 +81,12 @@ export class RedirectCollector extends AbstractCollector {
*/
private isTriggerInstalled = false;
+ /**
+ * Used to skip the referer test for single page applications.
+ * @private
+ */
+ private initialHistoryLength = window.history.length;
+
/**
* Construct redirect collector
*
@@ -44,21 +94,31 @@ export class RedirectCollector extends AbstractCollector {
* @param {function} triggerResolver - Function that fires when a search happens, should return the keyword
* @param {function} expectedPageResolver - Function that should return whether the page we load is the expected one
* @param redirectKpiParams - Parameters for collecting KPI's after a redirect
+ * @param listenerType
* @param context
*/
constructor(private readonly triggerResolver: CallbackResolver,
private readonly expectedPageResolver: BooleanResolver,
private readonly redirectKpiParams: RedirectKpiCollectorParams = {},
+ private readonly listenerType = ListenerType.Sentinel,
context?: Context) {
super("redirect", context);
this.triggerResolver = triggerResolver;
this.expectedPageResolver = expectedPageResolver;
+ this.listenerType = listenerType;
this.collectors = redirectKpiParams.collectors || [];
this.resultCountResolver = redirectKpiParams.resultCountResolver || (_ => void 0);
this.redirectTTL = this.redirectKpiParams.redirectTTLMillis || 86400000;
+ this.maxPathSegments = this.redirectKpiParams.maxPathSegments || -1;
+
+ this.subSelectors = this.redirectKpiParams.nestedRedirects?.subSelectors || [];
+ this.depth = this.redirectKpiParams.nestedRedirects?.depth || 1;
- this.queryResolver = (phrase) => {
+ this.queryResolver = (phrase: string) => {
+ if (phrase.indexOf("$s=") > -1) {
+ return new Query(phrase);
+ }
const query = new Query();
query.setSearch(phrase);
return query;
@@ -67,7 +127,7 @@ export class RedirectCollector extends AbstractCollector {
this.sessionResolver = () => cookieSessionResolver();
this.redirectTrail = new Trail(() => {
- const pathInfo = RedirectCollector.getRedirectPathInfo(window.location.pathname);
+ const pathInfo = RedirectCollector.getRedirectPathInfo(this.getPathname());
return new Query(pathInfo?.query);
}, this.sessionResolver);
}
@@ -81,41 +141,43 @@ export class RedirectCollector extends AbstractCollector {
* Marks this path as a redirect landing page.
* @param path the pathname e.g. /some-path
* @param query the query which lead to this path
+ * @param key the key to store the redirect path in
* @private
*/
- private static setRedirectPath(path: string, query: string) {
+ private static setRedirectPath(path: string, query: string, key: string = RedirectCollector.PATH_STORAGE_KEY) {
const redirectPaths = this.getRedirectPaths();
redirectPaths[path] = {
query,
timestamp: new Date().getTime()
};
- getSessionStorage().setItem(RedirectCollector.PATH_STORAGE_KEY, JSON.stringify(redirectPaths));
+ getSessionStorage().setItem(key, JSON.stringify(redirectPaths));
}
/**
* Get all marked paths
* @private
*/
- private static getRedirectPaths() {
- return JSON.parse(getSessionStorage().getItem(RedirectCollector.PATH_STORAGE_KEY) || "{}");
+ private static getRedirectPaths(key: string = RedirectCollector.PATH_STORAGE_KEY) {
+ return JSON.parse(getSessionStorage().getItem(key) || "{}");
}
/**
* Retrieve data for the given path
* @param path
+ * @param key
* @private
*/
- private static getRedirectPathInfo(path: string) {
- return this.getRedirectPaths()[path];
+ private static getRedirectPathInfo(path: string, key: string = RedirectCollector.PATH_STORAGE_KEY) {
+ return this.getRedirectPaths(key)[path];
}
/**
* Delete all expired redirect paths
* @private
*/
- private expireRedirectPaths() {
- const redirectPaths = RedirectCollector.getRedirectPaths();
+ private expireRedirectPaths(key: string = RedirectCollector.PATH_STORAGE_KEY) {
+ const redirectPaths = RedirectCollector.getRedirectPaths(key);
const now = new Date().getTime();
Object.keys(redirectPaths).forEach(path => {
const pathInfo = redirectPaths[path];
@@ -123,7 +185,7 @@ export class RedirectCollector extends AbstractCollector {
delete redirectPaths[path];
}
});
- getSessionStorage().setItem(RedirectCollector.PATH_STORAGE_KEY, JSON.stringify(redirectPaths));
+ getSessionStorage().setItem(key, JSON.stringify(redirectPaths));
}
/**
@@ -134,20 +196,21 @@ export class RedirectCollector extends AbstractCollector {
*/
attach(writer, log) {
if (this.isTriggerInstalled === false) {
- this.resolve(this.triggerResolver, log, keyword => getSessionStorage().setItem(RedirectCollector.STORAGE_KEY, keyword));
+ this.resolve(this.triggerResolver, log, keyword => getSessionStorage().setItem(RedirectCollector.LAST_SEARCH_STORAGE_KEY, keyword));
this.isTriggerInstalled = true;
}
this.expireRedirectPaths();
// Fetch the latest search if any
- const lastSearch = getSessionStorage().getItem(RedirectCollector.STORAGE_KEY);
+ const lastSearch = getSessionStorage().getItem(RedirectCollector.LAST_SEARCH_STORAGE_KEY);
+ const pathname = normalizePathname(this.getWindow().location.pathname);
if (lastSearch) {
- getSessionStorage().removeItem(RedirectCollector.STORAGE_KEY);
+ getSessionStorage().removeItem(RedirectCollector.LAST_SEARCH_STORAGE_KEY);
// If we have not landed on the expected search page, it must have been a redirect
- if (shouldTrackRedirect(document.referrer) && !this.resolve(this.expectedPageResolver, log)) {
+ if (shouldTrackRedirect(document.referrer, this.initialHistoryLength) && !this.resolve(this.expectedPageResolver, log)) {
const query = this.queryResolver(lastSearch).toString()
writer.write({
type: "redirect",
@@ -158,31 +221,111 @@ export class RedirectCollector extends AbstractCollector {
});
// mark as redirect landing page
- RedirectCollector.setRedirectPath(window.location.pathname, query);
- // register a trail with the pathname for subsequent click events. See ProductClickCollector.ts
- this.redirectTrail.register(window.location.pathname, TrailType.Main, query);
+ RedirectCollector.setRedirectPath(this.getPathname(), query);
+
+ // register trail on the current pathname because the ProductClick collector doesn't know about the maxPathSegments property
+ this.redirectTrail.register(pathname, TrailType.Main);
}
}
+ // this is only triggered when a subSelector item was clicked i.e. a nested redirect
+ const lastSearchNestedRedirect = this.getNestedRedirect();
+ if (lastSearchNestedRedirect) {
+ const query = this.queryResolver(lastSearchNestedRedirect.query).toString();
+ RedirectCollector.setRedirectPath(this.getPathname(), query);
+ // register trail on the current pathname because the ProductClick collector doesn't know about the maxPathSegments property
+ this.redirectTrail.register(pathname, TrailType.Main);
+
+ getSessionStorage().removeItem(RedirectCollector.NESTED_REDIRECT_KEYWORDS_STORAGE_KEY);
+ }
+
/**
* Check if we have tracked this path before and if it is still valid.
* If valid, we have to attach the KPI collectors to gather KPIs for this landing page.
* We have to do this because people can navigate away from the landing page and back again and we don't want to lose all subsequent clicks etc.
*/
- const pathInfo = RedirectCollector.getRedirectPathInfo(this.getWindow().location.pathname);
+ const pathInfo = this.redirectTrail.fetch(this.getPathname());
if (pathInfo && this.isCollectorsAttached !== true) {
this.attachCollectors(writer, log, pathInfo.query);
this.isCollectorsAttached = true;
+
+ // register trail on the current pathname because the ProductClick collector doesn't know about the maxPathSegments property
+ this.redirectTrail.register(pathname, TrailType.Main);
+
+ // if we have nested redirects, we have to carry the query parameters over to the next page
+ this.attachSubSelectors(pathInfo, lastSearchNestedRedirect?.depth || 0);
+ }
+ }
+
+ private getNestedRedirect(): NestedRedirect | undefined {
+ const payload = getSessionStorage().getItem(RedirectCollector.NESTED_REDIRECT_KEYWORDS_STORAGE_KEY);
+ if (payload) {
+ return JSON.parse(payload) as NestedRedirect;
+ }
+ return undefined;
+ }
+
+ private isMaxDepthExceeded(currentDepth: number = 0) {
+ return currentDepth >= this.depth;
+ }
+
+ private registerNestedRedirect(query: string, currentDepth: number = 0) {
+ if (this.isMaxDepthExceeded(currentDepth))
+ return;
+
+ const payload = {
+ query: query,
+ depth: currentDepth + 1
+ };
+
+ getSessionStorage().setItem(RedirectCollector.NESTED_REDIRECT_KEYWORDS_STORAGE_KEY, JSON.stringify(payload));
+ }
+
+ private attachSubSelectors(pathInfo, currentDepth: number) {
+ if (this.isMaxDepthExceeded(currentDepth))
+ return;
+
+ this.subSelectors.forEach(selector => {
+ const handleClick = () => {
+ this.registerNestedRedirect(pathInfo.query, currentDepth);
+ }
+
+ if (this.listenerType === ListenerType.Sentinel) {
+ const sentinel = new Sentinel(this.getDocument());
+ sentinel.on(selector, element => {
+ const info = this.redirectTrail.fetch(this.getPathname());
+ if (info) { // the sentinel can trigger on any page, we need to make sure we attach subSelectors only on valid redirect paths
+ element.addEventListener("click", handleClick);
+ }
+ })
+ } else {
+ document.querySelectorAll(selector).forEach(element => {
+ element.addEventListener("click", handleClick);
+ });
+ }
+ });
+ }
+
+ private getPathname(): string {
+ const pathname = normalizePathname(this.getWindow().location.pathname);
+ if (this.maxPathSegments > 0) {
+ const pathSegments = pathname.split("/");
+ return normalizePathname(pathSegments.filter(s => !!s).slice(0, this.maxPathSegments).join("/"));
}
+ return pathname;
}
private attachCollectors(writer, log, query) {
+ const instance = this;
// attach all collectors which are responsible to gather kpi's after the redirect
this.collectors.forEach(collector => {
try {
collector.attach({
write(data) {
- writer.write({...data, query: data.query || query});
+ const pathInfo = instance.redirectTrail.fetch(instance.getPathname());
+ if (pathInfo) { // check if this url path is marked as a redirect page to prevent wrongly tracked events
+ writer.write({...data, query: data.query || query});
+ }
}
}, log)
} catch (e) {
@@ -194,12 +337,13 @@ export class RedirectCollector extends AbstractCollector {
}
-function shouldTrackRedirect(referer: string) {
+function shouldTrackRedirect(referer: string, initialHistoryLength: number) {
if (referer) {
try {
const refUrl = new URL(referer);
const currentUrl = new URL(window.location.href);
- if (currentUrl.origin && refUrl.origin)
+ // compare the history length, if it does not equal we are on a an SPA and cant compare the referer
+ if (initialHistoryLength === history.length && currentUrl.origin && refUrl.origin)
return refUrl.origin === currentUrl.origin;
} catch (e) {
console.error(e);
diff --git a/src/main/utils/Util.ts b/src/main/utils/Util.ts
index 0f47c76..7589693 100644
--- a/src/main/utils/Util.ts
+++ b/src/main/utils/Util.ts
@@ -9,6 +9,15 @@ export const parseQueryString = (queryString = window.location.search) => {
return new URLSearchParams(queryString);
}
+export const normalizePathname = (path: string) => {
+ if (!path.startsWith("/"))
+ path = "/" + path;
+ if (path.endsWith("/"))
+ path = path.substring(0, path.length - 1);
+
+ return path;
+}
+
/**
* Some browser like Safari prevent accessing localStorage in private mode by throwing exceptions.
* Use this method to retrieve a mock impl which will at least prevent errors.
diff --git a/src/test/collectors/RedirectCollector.test.ts b/src/test/collectors/RedirectCollector.test.ts
index ffcbafe..ed209f9 100644
--- a/src/test/collectors/RedirectCollector.test.ts
+++ b/src/test/collectors/RedirectCollector.test.ts
@@ -26,6 +26,38 @@ describe('RedirectCollector Suite', () => {
await verifyNoUnmatchedRequests();
})
+ test('track redirect data maxPathSegments', async () => {
+ const redirectStubAsserter = await createStubAsserter("RedirectCollectorTracking.json");
+ const clickStubAsserter = await createStubAsserter("RedirectProductClickCollectorTracking.json");
+
+ await page.goto(getHost() + "/nested/path/RedirectCollector.page.html?isSearchPage=true", {waitUntil: 'networkidle0'});
+
+ await Promise.all([page.waitForNavigation({waitUntil: "networkidle0"}), page.click("#searchButton")]);
+
+ await wait(100);
+
+ await redirectStubAsserter.verifyCallCount(1)
+ .verifyQueryParams(params => {
+ const trackingData = JSON.parse(params.data.values[0]);
+ expect(trackingData.type).toBe("redirect");
+ expect(trackingData.keywords).toBe("THE REDIRECT QUERY");
+ expect(trackingData.query).toBe("$s=THE REDIRECT QUERY/");
+ expect(trackingData.url).toBe(getHost() + "/nested/path/RedirectCollector.page.html?isSearchPage=false");
+ })
+ .verify();
+
+ await clickStubAsserter.verifyCallCount(0)
+ .verify();
+
+ const trail = await page.evaluate(() => {
+ return sessionStorage.getItem("___pathStorage");
+ });
+
+ const redirectPaths = JSON.parse(trail);
+ expect(redirectPaths["/nested"]).toBeDefined();
+ expect(redirectPaths["/nested"].query).toBe("$s=THE REDIRECT QUERY/");
+ });
+
test('track redirect data', async () => {
const redirectStubAsserter = await createStubAsserter("RedirectCollectorTracking.json");
const clickStubAsserter = await createStubAsserter("RedirectProductClickCollectorTracking.json");
@@ -96,6 +128,66 @@ describe('RedirectCollector Suite', () => {
.verify();
});
+ test('track redirect product clicks after a subSelector click', async () => {
+ const redirectStubAsserter = await createStubAsserter("RedirectCollectorTracking.json");
+ const clickStubAsserter = await createStubAsserter("RedirectProductClickCollectorTracking.json");
+
+ await page.goto(getHost() + "/RedirectCollectorWithProductClicks.page.html?isSearchPage=true", {waitUntil: 'networkidle0'});
+
+ await Promise.all([page.waitForNavigation({waitUntil: "networkidle0"}), page.click("#searchButton")]);
+
+ await wait(100);
+
+ await page.click("#clickMe");
+
+ await wait(100);
+
+ // make sure a trail for that path exists
+ const trail = await page.evaluate(() => {
+ return localStorage.getItem("search-collector-trail");
+ });
+ const pathInfo = JSON.parse(trail)["/RedirectCollectorWithProductClicks.page.html"];
+ expect(pathInfo.query).toBe("$s=THE REDIRECT QUERY/");
+
+ await redirectStubAsserter.verifyCallCount(1)
+ .verifyQueryParams(params => {
+ const trackingData = JSON.parse(params.data.values[0]);
+ expect(trackingData.type).toBe("redirect");
+ expect(trackingData.keywords).toBe("THE REDIRECT QUERY");
+ expect(trackingData.query).toBe("$s=THE REDIRECT QUERY/");
+ expect(trackingData.url).toBe(getHost() + "/RedirectCollectorWithProductClicks.page.html?isSearchPage=false");
+ expect(trackingData.resultCount).toBe(5);
+ })
+ .verify();
+
+ await Promise.all([page.waitForNavigation({waitUntil: "networkidle0"}), page.click("#subSelector")]);
+
+ await wait(100);
+
+ await page.click("#clickMe");
+
+ await wait(100);
+
+
+ await clickStubAsserter.verifyCallCount(2)
+ .verifyQueryParams((params, i) => {
+ const trackingData = JSON.parse(params.data.values[0]);
+ expect(trackingData.type).toBe("product");
+ expect(trackingData.id).toBe("5");
+ expect(trackingData.position).toBe(4);
+ expect(trackingData.price).toBe(5.99);
+ expect(trackingData.query).toBe("$s=THE REDIRECT QUERY/");
+ expect(trackingData.image).toBe("image.jpg");
+ expect(trackingData.metadata).toBe("DIV");
+ if (i === 0)
+ expect(trackingData.url).toBe(getHost() + "/RedirectCollectorSubSelectorPage.page.html?isSearchPage=false");
+
+ if (i === 1)
+ expect(trackingData.url).toBe(getHost() + "/RedirectCollectorWithProductClicks.page.html?isSearchPage=false");
+ })
+ .verify();
+ });
+
test('track redirect data different origin', async () => {
const stubAsserter = await createStubAsserter("RedirectCollectorTracking.json");
diff --git a/src/test/mock/__files/RedirectCollectorSubSelectorPage.page.html b/src/test/mock/__files/RedirectCollectorSubSelectorPage.page.html
new file mode 100644
index 0000000..fec856e
--- /dev/null
+++ b/src/test/mock/__files/RedirectCollectorSubSelectorPage.page.html
@@ -0,0 +1,90 @@
+
+
+
+
+ E2E Testing
+
+
+
+
+
+
+
+
+
+
+
+
+Product
+Product
+Product
+Product
+
+Product
+Product
+Product
+Product
+Product
+
+
+
diff --git a/src/test/mock/__files/RedirectCollectorWithProductClicks.page.html b/src/test/mock/__files/RedirectCollectorWithProductClicks.page.html
index 43d0089..2431094 100644
--- a/src/test/mock/__files/RedirectCollectorWithProductClicks.page.html
+++ b/src/test/mock/__files/RedirectCollectorWithProductClicks.page.html
@@ -11,11 +11,16 @@
RedirectCollector,
RestEventWriter,
positionResolver,
- ProductClickCollector
+ ProductClickCollector,
+ BrowserTrackingWriter
} = window.SearchCollector;
const collector = new CollectorModule({
- writer: new RestEventWriter(location.origin + "/redirect-collector-channel")
+ writer: new BrowserTrackingWriter(new RestEventWriter(location.origin + "/redirect-collector-channel"), {
+ recordUrl: true,
+ recordReferrer: true,
+ recordLanguage: true
+ })
});
const firedSearchCallback = (callback) => {
@@ -34,6 +39,9 @@
},
{
resultCountResolver: () => 5,
+ nestedRedirects: {
+ subSelectors: ["#subSelector"],
+ },
collectors: [new ProductClickCollector(".product", {
idResolver: element => element.getAttribute("data-id"),
positionResolver: element => positionResolver(".product", element),
@@ -50,10 +58,15 @@
document.location.href = document.location.origin + window.location.pathname + "?" + params.toString();
});
+ document.querySelector("#subSelector").addEventListener("click", () => {
+ const params = new URLSearchParams(document.location.search);
+ params.delete("isSearchPage");
+ params.append("isSearchPage", "false");
+ document.location.href = document.location.origin + window.location.pathname.replace("RedirectCollectorWithProductClicks.page.html", "RedirectCollectorSubSelectorPage.page.html") + "?" + params.toString();
+ });
+
collector.start();
});
-
-
@@ -62,7 +75,7 @@
-
+
Product
diff --git a/src/test/mock/__files/nested/path/RedirectCollector.page.html b/src/test/mock/__files/nested/path/RedirectCollector.page.html
new file mode 100644
index 0000000..b9308c0
--- /dev/null
+++ b/src/test/mock/__files/nested/path/RedirectCollector.page.html
@@ -0,0 +1,72 @@
+
+
+
+
+ E2E Testing
+
+
+
+
+
+
+
+
+
+
+
+
+Product
+Product
+Product
+Product
+
+Product
+Product
+Product
+Product
+Product
+
+
+
diff --git a/src/test/wiremock.ts b/src/test/wiremock.ts
index 7382a52..d76f6d3 100644
--- a/src/test/wiremock.ts
+++ b/src/test/wiremock.ts
@@ -3,7 +3,6 @@ import fetch from "node-fetch";
import {join} from "path";
import {getRandomInt, wait} from "./util";
-
export class StubAsserter {
private disposed: boolean;
@@ -44,9 +43,11 @@ export class StubAsserter {
return this;
}
- private async _verifyBody(assertFn: (body: any) => void) {
- const entry = await this.fetchJournalEntry();
- await assertFn(entry.request.body);
+ private async _verifyBody(assertFn: (body: any, i: number) => void) {
+ const entries = await this.fetchJournalEntry();
+ for (let i = 0; i < entries.length; i++) {
+ await assertFn(entries[i].request.body, i);
+ }
}
verifyHeaders(assertFn: (headers: { [key: string]: string }) => void) {
@@ -56,9 +57,11 @@ export class StubAsserter {
return this;
}
- private async _verifyHeaders(assertFn: (headers: { [key: string]: string }) => void) {
- const entry = await this.fetchJournalEntry();
- await assertFn(entry.request.headers);
+ private async _verifyHeaders(assertFn: (headers: { [key: string]: string }, i: number) => void) {
+ const entries = await this.fetchJournalEntry();
+ for (let i = 0; i < entries.length; i++) {
+ await assertFn(entries[i].request.headers, i);
+ }
}
verifyCookies(assertFn: (cookies: { [key: string]: string }) => void) {
@@ -68,9 +71,11 @@ export class StubAsserter {
return this;
}
- private async _verifyCookies(assertFn: (cookies: { [key: string]: string }) => void) {
- const entry = await this.fetchJournalEntry();
- await assertFn(entry.request.cookies);
+ private async _verifyCookies(assertFn: (cookies: { [key: string]: string }, i: number) => void) {
+ const entries = await this.fetchJournalEntry();
+ for (let i = 0; i < entries.length; i++) {
+ await assertFn(entries[i].request.cookies, i);
+ }
}
verifyRequest(assertFn: (request: any) => void) {
@@ -80,32 +85,39 @@ export class StubAsserter {
return this;
}
- private async _verifyRequest(assertFn: (request: any) => void) {
- const entry = await this.fetchJournalEntry();
- await assertFn(entry.request);
+ private async _verifyRequest(assertFn: (request: any, i: number) => void) {
+ const entries = await this.fetchJournalEntry();
+ for (let i = 0; i < entries.length; i++) {
+ await assertFn(entries[i].request, i);
+ }
}
- verifyQueryParams(assertFn: (queryParams: { [key: string]: { key: string, values: Array } }) => void) {
+ verifyQueryParams(assertFn: (queryParams: { [key: string]: { key: string, values: Array } }, i:number) => void) {
this.testFunctions.push(async () => {
await this._verifyQueryParams(assertFn);
});
return this;
}
- private async _verifyQueryParams(assertFn: (queryParams: { [key: string]: { key: string, values: Array } }) => void) {
- const entry = await this.fetchJournalEntry();
- await assertFn(entry.request.queryParams);
+ private async _verifyQueryParams(assertFn: (queryParams: {
+ [key: string]: { key: string, values: Array }
+ }, i: number) => void) {
+ const entries = await this.fetchJournalEntry();
+ for (let i = 0; i < entries.length; i++) {
+ await assertFn(entries[i].request.queryParams, i);
+ }
}
private async fetchJournalEntry() {
- const entry = (await this.getJournal()).requests.find(entry => entry.stubMapping.id === this.stub.id);
- if (!entry)
+ const requests = (await this.getJournal()).requests;
+ const entries = requests.filter(entry => entry.stubMapping.id === this.stub.id);
+ if (entries?.length == 0)
throw Error(`Could not find stub for id ${this.stub.id} with filename ${this.stub.__filename},
probably (1) your api-stub did not match your request or \n
(2) there were no request at all or \n
(3) another stub matched your request.`);
- return entry;
+ return entries;
}
private async dispose() {
@@ -233,6 +245,8 @@ export const createMockServer = (port = getRandomInt(49152, 65535)) => {
throw Error("mock server already started");
process = exec(`npx wiremock --port ${port} --verbose --root-dir ${__dirname + "/mock"}`);
+ process.stderr.on("data", data => console.error(data));
+ process.stdout.on("data", data => console.debug(data));
const readyTime = await waitForReadiness();
// console.debug(`wiremock ready after ${readyTime}ms`);
},