diff --git a/build/amd/senna/src/app/App-min.js b/build/amd/senna/src/app/App-min.js index d544afc..7de5104 100644 --- a/build/amd/senna/src/app/App-min.js +++ b/build/amd/senna/src/app/App-min.js @@ -1 +1 @@ -define(["exports","metal-dom/src/all/dom","metal/src/metal","metal-events/src/events","metal-promise/src/promise/Promise","metal-debounce/src/debounce","../globals/globals","../route/Route","../screen/Screen","../surface/Surface","metal-uri/src/Uri","../utils/utils"],function(e,t,a,n,r,i,o,l,s,u,c,f){"use strict";function d(e){return e&&e.__esModule?e:{"default":e}}function h(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function v(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function g(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(e,"__esModule",{value:!0});var p=d(r),y=d(i),m=d(o),S=d(l),P=d(s),w=d(u),b=d(c),_=d(f),k=function(){function e(e,t){for(var a=0;a0}},{key:"isLinkSameOrigin_",value:function(e){var t=new b["default"](e),a=new b["default"](m["default"].window.location.host);return t.getPort()===a.getPort()&&t.getHostname()===a.getHostname()}},{key:"isSameBasePath_",value:function(e){return 0===e.indexOf(this.basePath)}},{key:"lockHistoryScrollPosition_",value:function(){var e=m["default"].window.history.state;if(e){var t=!1,n=function r(){m["default"].document.removeEventListener("scroll",r,!1),t||(m["default"].window.scrollTo(e.scrollLeft,e.scrollTop),t=!0)};a.async.nextTick(n),m["default"].document.addEventListener("scroll",n,!1)}}},{key:"maybeDisableNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&(this.nativeScrollRestoration_=m["default"].window.history.scrollRestoration,m["default"].window.history.scrollRestoration="manual")}},{key:"maybeScheduleNavigation_",value:function(e,t){return!(!this.isNavigationPending||this.navigationStrategy!==E.SCHEDULE_LAST)&&(this.scheduledNavigationQueue=[a.object.mixin({href:e,isScheduledNavigation:!0},t)],!0)}},{key:"maybeNavigate_",value:function(e,t){if(this.canNavigate(e)){var a=this.maybeScheduleNavigation_(e,t);if(a)return void t.preventDefault();var n=!1;try{this.navigate(_["default"].getUrlPath(e),!1,t)}catch(r){n=!0}n||t.isScheduledNavigation||t.preventDefault()}}},{key:"maybeOverloadBeforeUnload_",value:function(){var e=this;"function"==typeof window.onbeforeunload&&(window._onbeforeunload=window.onbeforeunload,window.onbeforeunload=function(t){if(e.emit("beforeUnload",t),t&&t.defaultPrevented)return!0},window.onbeforeunload._overloaded=!0)}},{key:"maybePreventActivate_",value:function(e){var t=this;return p["default"].resolve().then(function(){return e.beforeActivate()}).then(function(e){if(e)return t.pendingNavigate=p["default"].reject(new p["default"].CancellationError("Cancelled by next screen")),t.pendingNavigate})}},{key:"maybePreventDeactivate_",value:function(){var e=this;return p["default"].resolve().then(function(){if(e.activeScreen)return e.activeScreen.beforeDeactivate()}).then(function(t){if(t)return e.pendingNavigate=p["default"].reject(new p["default"].CancellationError("Cancelled by active screen")),e.pendingNavigate})}},{key:"maybeRepositionScrollToHashedAnchor",value:function(){var e=m["default"].window.location.hash;if(e){var t=m["default"].document.getElementById(e.substring(1));if(t){var a=_["default"].getNodeOffset(t),n=a.offsetLeft,r=a.offsetTop;m["default"].window.scrollTo(n,r)}}}},{key:"maybeRestoreNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&this.nativeScrollRestoration_&&(m["default"].window.history.scrollRestoration=this.nativeScrollRestoration_)}},{key:"maybeRestoreRedirectPathHash_",value:function(e,t,a){return t===_["default"].getUrlPathWithoutHash(e)?t+a:t}},{key:"maybeUpdateScrollPositionState_",value:function(){var e=m["default"].window.location.hash,t=m["default"].document.getElementById(e.substring(1));if(t){var a=_["default"].getNodeOffset(t),n=a.offsetLeft,r=a.offsetTop;this.saveHistoryCurrentPageScrollPosition_(r,n)}}},{key:"navigate",value:function(e,t,a){if(!_["default"].isHtml5HistorySupported())throw new Error("HTML5 History is not supported. Senna will not intercept navigation.");return a&&(m["default"].capturedFormElement=a.capturedFormElement,m["default"].capturedFormButtonElement=a.capturedFormButtonElement),e===this.activePath&&(t=!0),this.emit("beforeNavigate",{event:a,path:e,replaceHistory:!!t}),this.pendingNavigate}},{key:"onBeforeNavigate_",value:function(e){m["default"].capturedFormElement&&(e.form=m["default"].capturedFormElement)}},{key:"onBeforeNavigateDefault_",value:function(e){(!this.pendingNavigate||this.pendingNavigate.path!==e.path&&this.navigationStrategy!==E.SCHEDULE_LAST)&&(this.emit("beforeUnload",e),this.emit("startNavigate",{form:e.form,path:e.path,replaceHistory:e.replaceHistory}))}},{key:"onBeforeUnloadDefault_",value:function(e){var t=window._onbeforeunload;t&&!t._overloaded&&t()&&e.preventDefault()}},{key:"onDocClickDelegate_",value:function(e){e.altKey||e.ctrlKey||e.metaKey||e.shiftKey||e.button||this.maybeNavigate_(e.delegateTarget.href,e)}},{key:"onDocSubmitDelegate_",value:function(e){var a=e.delegateTarget;if("get"!==a.method){e.capturedFormElement=a;var n="button:not([type]),button[type=submit],input[type=submit]";(0,t.match)(m["default"].document.activeElement,n)?e.capturedFormButtonElement=m["default"].document.activeElement:e.capturedFormButtonElement=a.querySelector(n),this.maybeNavigate_(a.action,e)}}},{key:"onLoad_",value:function(){var e=this;this.skipLoadPopstate=!0,setTimeout(function(){e.skipLoadPopstate=!1},0),this.maybeRepositionScrollToHashedAnchor()}},{key:"onPopstate_",value:function(e){if(!this.skipLoadPopstate){if(_["default"].isCurrentBrowserPath(this.browserPathBeforeNavigate))return void this.maybeRepositionScrollToHashedAnchor();var t=e.state;if(!t)return void(m["default"].window.location.hash?(this.redirectPath&&!_["default"].isCurrentBrowserPath(this.redirectPath)&&this.reloadPage(),this.maybeRepositionScrollToHashedAnchor()):this.reloadPage());if(t.senna){this.popstateScrollTop=t.scrollTop,this.popstateScrollLeft=t.scrollLeft,this.nativeScrollRestorationSupported||this.lockHistoryScrollPosition_(),this.once("endNavigate",function(){t.referrer&&_["default"].setReferrer(t.referrer)});var a=new b["default"](t.path);a.setHostname(m["default"].window.location.hostname),a.setPort(m["default"].window.location.port);var n=this.maybeScheduleNavigation_(a.toString(),{});if(n)return;this.navigate(t.path,!0)}}}},{key:"onScroll_",value:function(){this.captureScrollPositionFromScrollEvent&&this.saveHistoryCurrentPageScrollPosition_(m["default"].window.pageYOffset,m["default"].window.pageXOffset)}},{key:"onStartNavigate_",value:function(e){var a=this;this.maybeDisableNativeScrollRestoration(),this.captureScrollPositionFromScrollEvent=!1,(0,t.addClasses)(m["default"].document.documentElement,this.loadingCssClass);var n={form:e.form,path:e.path};this.pendingNavigate=this.doNavigate_(e.path,e.replaceHistory)["catch"](function(e){throw n.error=e,e}).thenAlways(function(){a.pendingNavigate||a.scheduledNavigationQueue.length||((0,t.removeClasses)(m["default"].document.documentElement,a.loadingCssClass),a.maybeRestoreNativeScrollRestoration(),a.captureScrollPositionFromScrollEvent=!0),a.emit("endNavigate",n)}),this.pendingNavigate.path=e.path}},{key:"prefetch",value:function(e){var t=this,a=this.findRoute(e);if(!a)return p["default"].reject(new p["default"].CancellationError("No route for "+e));var n=this.createScreenInstance(e,a);return n.load(e).then(function(){return t.screens[e]=n})["catch"](function(a){throw t.handleNavigateError_(e,n,a),a})}},{key:"prepareNavigateHistory_",value:function(e,t,n){var r=t.getTitle();(0,a.isString)(r)||(r=this.getDefaultTitle());var i=t.beforeUpdateHistoryPath(e),o={form:(0,a.isDefAndNotNull)(m["default"].capturedFormElement),path:e,redirectPath:i,scrollLeft:0,scrollTop:0,senna:!0};n&&(o.scrollTop=this.popstateScrollTop,o.scrollLeft=this.popstateScrollLeft);var l=new b["default"](e).getHash();i=this.maybeRestoreRedirectPathHash_(e,i,l),this.updateHistory_(r,i,t.beforeUpdateHistoryState(o),n),this.redirectPath=i}},{key:"prepareNavigateSurfaces_",value:function(e,t,a){Object.keys(t).forEach(function(n){var r=e.getSurfaceContent(n,a);t[n].addContent(e.getId(),r)})}},{key:"reloadPage",value:function(){m["default"].window.location.reload()}},{key:"removeRoute",value:function(e){return a.array.remove(this.routes,e)}},{key:"removeScreen",value:function(e){var t=this,a=this.screens[e];a&&(Object.keys(this.surfaces).forEach(function(e){return t.surfaces[e].remove(a.getId())}),a.dispose(),delete this.screens[e])}},{key:"saveHistoryCurrentPageScrollPosition_",value:function(e,t){var a=m["default"].window.history.state;if(a&&a.senna){var n=[e,t];a.scrollTop=n[0],a.scrollLeft=n[1],m["default"].window.history.replaceState(a,null,null)}}},{key:"setAllowPreventNavigate",value:function(e){this.allowPreventNavigate=e}},{key:"setBasePath",value:function(e){this.basePath=_["default"].removePathTrailingSlash(e)}},{key:"setDefaultTitle",value:function(e){this.defaultTitle=e}},{key:"setFormSelector",value:function(e){this.formSelector=e,this.formEventHandler_&&this.formEventHandler_.removeListener(),this.formEventHandler_=(0,t.delegate)(document,"submit",this.formSelector,this.onDocSubmitDelegate_.bind(this),this.allowPreventNavigate)}},{key:"setIgnoreQueryStringFromRoutePath",value:function(e){this.ignoreQueryStringFromRoutePath=e}},{key:"setLinkSelector",value:function(e){this.linkSelector=e,this.linkEventHandler_&&this.linkEventHandler_.removeListener(),this.linkEventHandler_=(0,t.delegate)(document,"click",this.linkSelector,this.onDocClickDelegate_.bind(this),this.allowPreventNavigate)}},{key:"setLoadingCssClass",value:function(e){this.loadingCssClass=e}},{key:"setUpdateScrollPosition",value:function(e){this.updateScrollPosition=e}},{key:"stopPendingNavigate_",value:function(){this.pendingNavigate&&this.pendingNavigate.cancel("Cancel pending navigation"),this.pendingNavigate=null}},{key:"syncScrollPositionSyncThenAsync_",value:function(){var e=this,t=m["default"].window.history.state;if(t){var n=t.scrollTop,r=t.scrollLeft,i=function(){e.updateScrollPosition&&m["default"].window.scrollTo(r,n)};return new p["default"](function(e){return i()&a.async.nextTick(function(){return i()&e()})})}}},{key:"updateHistory_",value:function(e,t,a,n){var r=m["default"].window.location.href;a&&(a.referrer=r),n?m["default"].window.history.replaceState(a,e,t):m["default"].window.history.pushState(a,e,t),_["default"].setReferrer(r);var i=m["default"].document.querySelector("title");i?i.innerHTML=e:m["default"].document.title=e}}]),r}(n.EventEmitter);e["default"]=H}); \ No newline at end of file +define(["exports","metal-dom/src/all/dom","metal/src/metal","metal-events/src/events","metal-promise/src/promise/Promise","metal-debounce/src/debounce","../globals/globals","../route/Route","../screen/Screen","../surface/Surface","metal-uri/src/Uri","../utils/utils"],function(e,t,a,n,r,i,o,l,s,u,c,f){"use strict";function d(e){return e&&e.__esModule?e:{"default":e}}function h(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function v(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function g(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(e,"__esModule",{value:!0});var p=d(r),y=d(i),m=d(o),S=d(l),P=d(s),w=d(u),b=d(c),_=d(f),k=function(){function e(e,t){for(var a=0;a0}},{key:"isLinkSameOrigin_",value:function(e){var t=new b["default"](e),a=new b["default"](m["default"].window.location.host);return t.getPort()===a.getPort()&&t.getHostname()===a.getHostname()}},{key:"isSameBasePath_",value:function(e){return 0===e.indexOf(this.basePath)}},{key:"lockHistoryScrollPosition_",value:function(){var e=m["default"].window.history.state;if(e){var t=!1,n=function r(){m["default"].document.removeEventListener("scroll",r,!1),t||(m["default"].window.scrollTo(e.scrollLeft,e.scrollTop),t=!0)};a.async.nextTick(n),m["default"].document.addEventListener("scroll",n,!1)}}},{key:"maybeDisableNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&(this.nativeScrollRestoration_=m["default"].window.history.scrollRestoration,m["default"].window.history.scrollRestoration="manual")}},{key:"maybeScheduleNavigation_",value:function(e,t){return!(!this.isNavigationPending||this.navigationStrategy!==E.SCHEDULE_LAST)&&(this.scheduledNavigationQueue=[a.object.mixin({href:e,isScheduledNavigation:!0},t)],!0)}},{key:"maybeNavigate_",value:function(e,t){if(this.canNavigate(e)){var a=this.maybeScheduleNavigation_(e,t);if(a)return void t.preventDefault();var n=!1;try{this.navigate(_["default"].getUrlPath(e),!1,t)}catch(r){n=!0}n||t.isScheduledNavigation||t.preventDefault()}}},{key:"maybeOverloadBeforeUnload_",value:function(){var e=this;"function"==typeof window.onbeforeunload&&(window._onbeforeunload=window.onbeforeunload,window.onbeforeunload=function(t){if(e.emit("beforeUnload",t),t&&t.defaultPrevented)return!0},window.onbeforeunload._overloaded=!0)}},{key:"maybePreventActivate_",value:function(e){var t=this;return p["default"].resolve().then(function(){return e.beforeActivate()}).then(function(e){if(e)return t.pendingNavigate=p["default"].reject(new p["default"].CancellationError("Cancelled by next screen")),t.pendingNavigate})}},{key:"maybePreventDeactivate_",value:function(){var e=this;return p["default"].resolve().then(function(){if(e.activeScreen)return e.activeScreen.beforeDeactivate()}).then(function(t){if(t)return e.pendingNavigate=p["default"].reject(new p["default"].CancellationError("Cancelled by active screen")),e.pendingNavigate})}},{key:"maybeRepositionScrollToHashedAnchor",value:function(){var e=m["default"].window.location.hash;if(e){var t=m["default"].document.getElementById(e.substring(1));if(t){var a=_["default"].getNodeOffset(t),n=a.offsetLeft,r=a.offsetTop;m["default"].window.scrollTo(n,r)}}}},{key:"maybeRestoreNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&this.nativeScrollRestoration_&&(m["default"].window.history.scrollRestoration=this.nativeScrollRestoration_)}},{key:"maybeRestoreRedirectPathHash_",value:function(e,t,a){return t===_["default"].getUrlPathWithoutHash(e)?t+a:t}},{key:"maybeUpdateScrollPositionState_",value:function(){var e=m["default"].window.location.hash,t=m["default"].document.getElementById(e.substring(1));if(t){var a=_["default"].getNodeOffset(t),n=a.offsetLeft,r=a.offsetTop;this.saveHistoryCurrentPageScrollPosition_(r,n)}}},{key:"navigate",value:function(e,t,a){if(!_["default"].isHtml5HistorySupported())throw new Error("HTML5 History is not supported. Senna will not intercept navigation.");return a&&(m["default"].capturedFormElement=a.capturedFormElement,m["default"].capturedFormButtonElement=a.capturedFormButtonElement),e===this.activePath&&(t=!0),this.emit("beforeNavigate",{event:a,path:e,replaceHistory:!!t}),this.pendingNavigate}},{key:"onBeforeNavigate_",value:function(e){m["default"].capturedFormElement&&(e.form=m["default"].capturedFormElement)}},{key:"onBeforeNavigateDefault_",value:function(e){(!this.pendingNavigate||this.pendingNavigate.path!==e.path&&this.navigationStrategy!==E.SCHEDULE_LAST)&&(this.emit("beforeUnload",e),this.emit("startNavigate",{form:e.form,path:e.path,replaceHistory:e.replaceHistory}))}},{key:"onBeforeUnloadDefault_",value:function(e){var t=window._onbeforeunload;t&&!t._overloaded&&t()&&e.preventDefault()}},{key:"onDocClickDelegate_",value:function(e){e.altKey||e.ctrlKey||e.metaKey||e.shiftKey||e.button||this.maybeNavigate_(e.delegateTarget.href,e)}},{key:"onDocSubmitDelegate_",value:function(e){var a=e.delegateTarget;if("get"!==a.method){e.capturedFormElement=a;var n="button:not([type]),button[type=submit],input[type=submit]";(0,t.match)(m["default"].document.activeElement,n)?e.capturedFormButtonElement=m["default"].document.activeElement:e.capturedFormButtonElement=a.querySelector(n),this.maybeNavigate_(a.action,e)}}},{key:"onLoad_",value:function(){var e=this;this.skipLoadPopstate=!0,setTimeout(function(){e.skipLoadPopstate=!1},0),this.maybeRepositionScrollToHashedAnchor()}},{key:"onPopstate_",value:function(e){if(!this.skipLoadPopstate){if(_["default"].isCurrentBrowserPath(this.browserPathBeforeNavigate))return void this.maybeRepositionScrollToHashedAnchor();var t=e.state;if(!t)return void(m["default"].window.location.hash?(this.redirectPath&&!_["default"].isCurrentBrowserPath(this.redirectPath)&&this.reloadPage(),this.maybeRepositionScrollToHashedAnchor()):this.reloadPage());if(t.senna){this.popstateScrollTop=t.scrollTop,this.popstateScrollLeft=t.scrollLeft,this.nativeScrollRestorationSupported||this.lockHistoryScrollPosition_(),this.once("endNavigate",function(){t.referrer&&_["default"].setReferrer(t.referrer)});var a=new b["default"](t.path);a.setHostname(m["default"].window.location.hostname),a.setPort(m["default"].window.location.port);var n=this.maybeScheduleNavigation_(a.toString(),{});if(n)return;this.navigate(t.path,!0)}}}},{key:"onScroll_",value:function(){this.captureScrollPositionFromScrollEvent&&this.saveHistoryCurrentPageScrollPosition_(m["default"].window.pageYOffset,m["default"].window.pageXOffset)}},{key:"onStartNavigate_",value:function(e){var a=this;this.maybeDisableNativeScrollRestoration(),this.captureScrollPositionFromScrollEvent=!1,(0,t.addClasses)(m["default"].document.documentElement,this.loadingCssClass);var n={form:e.form,path:e.path};this.pendingNavigate=this.doNavigate_(e.path,e.replaceHistory)["catch"](function(e){throw n.error=e,e}).thenAlways(function(){a.pendingNavigate||a.scheduledNavigationQueue.length||((0,t.removeClasses)(m["default"].document.documentElement,a.loadingCssClass),a.maybeRestoreNativeScrollRestoration(),a.captureScrollPositionFromScrollEvent=!0),a.emit("endNavigate",n)}),this.pendingNavigate.path=e.path}},{key:"prefetch",value:function(e){var t=this,a=this.findRoute(e);if(!a)return p["default"].reject(new p["default"].CancellationError("No route for "+e));var n=this.createScreenInstance(e,a);return n.load(e).then(function(){return t.screens[e]=n})["catch"](function(a){throw t.handleNavigateError_(e,n,a),a})}},{key:"prepareNavigateHistory_",value:function(e,t,n){var r=t.getTitle();(0,a.isString)(r)||(r=this.getDefaultTitle());var i=t.beforeUpdateHistoryPath(e),o=new b["default"](e).getHash();i=this.maybeRestoreRedirectPathHash_(e,i,o);var l={form:(0,a.isDefAndNotNull)(m["default"].capturedFormElement),path:e,redirectPath:i,scrollLeft:0,scrollTop:0,senna:!0};n&&(l.scrollTop=this.popstateScrollTop,l.scrollLeft=this.popstateScrollLeft),this.updateHistory_(r,i,t.beforeUpdateHistoryState(l),n),this.redirectPath=i}},{key:"prepareNavigateSurfaces_",value:function(e,t,a){Object.keys(t).forEach(function(n){var r=e.getSurfaceContent(n,a);t[n].addContent(e.getId(),r)})}},{key:"reloadPage",value:function(){m["default"].window.location.reload()}},{key:"removeRoute",value:function(e){return a.array.remove(this.routes,e)}},{key:"removeScreen",value:function(e){var t=this,a=this.screens[e];a&&(Object.keys(this.surfaces).forEach(function(e){return t.surfaces[e].remove(a.getId())}),a.dispose(),delete this.screens[e])}},{key:"saveHistoryCurrentPageScrollPosition_",value:function(e,t){var a=m["default"].window.history.state;if(a&&a.senna){var n=[e,t];a.scrollTop=n[0],a.scrollLeft=n[1],m["default"].window.history.replaceState(a,null,null)}}},{key:"setAllowPreventNavigate",value:function(e){this.allowPreventNavigate=e}},{key:"setBasePath",value:function(e){this.basePath=_["default"].removePathTrailingSlash(e)}},{key:"setDefaultTitle",value:function(e){this.defaultTitle=e}},{key:"setFormSelector",value:function(e){this.formSelector=e,this.formEventHandler_&&this.formEventHandler_.removeListener(),this.formEventHandler_=(0,t.delegate)(document,"submit",this.formSelector,this.onDocSubmitDelegate_.bind(this),this.allowPreventNavigate)}},{key:"setIgnoreQueryStringFromRoutePath",value:function(e){this.ignoreQueryStringFromRoutePath=e}},{key:"setLinkSelector",value:function(e){this.linkSelector=e,this.linkEventHandler_&&this.linkEventHandler_.removeListener(),this.linkEventHandler_=(0,t.delegate)(document,"click",this.linkSelector,this.onDocClickDelegate_.bind(this),this.allowPreventNavigate)}},{key:"setLoadingCssClass",value:function(e){this.loadingCssClass=e}},{key:"setUpdateScrollPosition",value:function(e){this.updateScrollPosition=e}},{key:"stopPendingNavigate_",value:function(){this.pendingNavigate&&this.pendingNavigate.cancel("Cancel pending navigation"),this.pendingNavigate=null}},{key:"syncScrollPositionSyncThenAsync_",value:function(){var e=this,t=m["default"].window.history.state;if(t){var n=t.scrollTop,r=t.scrollLeft,i=function(){e.updateScrollPosition&&m["default"].window.scrollTo(r,n)};return new p["default"](function(e){return i()&a.async.nextTick(function(){return i()&e()})})}}},{key:"updateHistory_",value:function(e,t,a,n){var r=m["default"].window.location.href;a&&(a.referrer=r),n?m["default"].window.history.replaceState(a,e,t):m["default"].window.history.pushState(a,e,t),_["default"].setReferrer(r);var i=m["default"].document.querySelector("title");i?i.innerHTML=e:m["default"].document.title=e}}]),r}(n.EventEmitter);e["default"]=H}); \ No newline at end of file diff --git a/build/amd/senna/src/app/App.js b/build/amd/senna/src/app/App.js index 1df5f6a..32c3cf7 100644 --- a/build/amd/senna/src/app/App.js +++ b/build/amd/senna/src/app/App.js @@ -1043,6 +1043,8 @@ define(['exports', 'metal-dom/src/all/dom', 'metal/src/metal', 'metal-events/src title = this.getDefaultTitle(); } var redirectPath = nextScreen.beforeUpdateHistoryPath(path); + var hash = new _Uri2.default(path).getHash(); + redirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash); var historyState = { form: (0, _metal.isDefAndNotNull)(_globals2.default.capturedFormElement), path: path, @@ -1055,8 +1057,6 @@ define(['exports', 'metal-dom/src/all/dom', 'metal/src/metal', 'metal-events/src historyState.scrollTop = this.popstateScrollTop; historyState.scrollLeft = this.popstateScrollLeft; } - var hash = new _Uri2.default(path).getHash(); - redirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash); this.updateHistory_(title, redirectPath, nextScreen.beforeUpdateHistoryState(historyState), opt_replaceHistory); this.redirectPath = redirectPath; } diff --git a/build/amd/senna/src/app/App.js.map b/build/amd/senna/src/app/App.js.map index 85ea7f6..f9702dc 100644 --- a/build/amd/senna/src/app/App.js.map +++ b/build/amd/senna/src/app/App.js.map @@ -1 +1 @@ -{"version":3,"sources":["App.js"],"names":["NavigationStrategy","IMMEDIATE","SCHEDULE_LAST","App","activeScreen","activePath","allowPreventNavigate","basePath","browserPathBeforeNavigate","getCurrentBrowserPathWithoutHash","captureScrollPositionFromScrollEvent","defaultTitle","document","title","formSelector","ignoreQueryStringFromRoutePath","linkSelector","loadingCssClass","nativeScrollRestorationSupported","window","history","navigationStrategy","isNavigationPending","pendingNavigate","popstateScrollLeft","popstateScrollTop","redirectPath","routes","scheduledNavigationQueue","screens","skipLoadPopstate","surfaces","updateScrollPosition","appEventHandlers_","add","onScroll_","bind","onLoad_","onPopstate_","on","onStartNavigate_","onBeforeNavigate_","onBeforeNavigateDefault_","onBeforeUnloadDefault_","setLinkSelector","setFormSelector","maybeOverloadBeforeUnload_","Array","isArray","forEach","route","path","handler","push","surface","getId","url","uri","isWebUri","getUrlPath","isLinkSameOrigin_","getHost","console","log","isSameBasePath_","getHash","isCurrentBrowserPath","findRoute","Object","keys","clearCache","removeScreen","screen","getHandler","isImplementedBy","prototype","clearScreensCache","formEventHandler_","removeListener","linkEventHandler_","removeAllListeners","navigate","getCurrentBrowserPath","opt_replaceHistory","reject","CancellationError","stopPendingNavigate_","nextScreen","createScreenInstance","maybePreventDeactivate_","then","maybePreventActivate_","load","deactivate","prepareNavigateHistory_","prepareNavigateSurfaces_","extractParams","evaluateStyles","flip","evaluateScripts","maybeUpdateScrollPositionState_","syncScrollPositionSyncThenAsync_","finalizeNavigate_","catch","reason","handleNavigateError_","thenAlways","length","scheduledNavigation","shift","maybeNavigate_","href","getRoutePath","activate","isCacheable","capturedFormElement","capturedFormButtonElement","i","matchesPath","getIgnoreQueryStringFromRoutePath","getUrlPathWithoutHashAndSearch","substr","getUrlPathWithoutHash","error","stack","emit","host","hostUri","locationHostUri","location","getPort","getHostname","indexOf","state","winner","switchScrollPositionRace","removeEventListener","scrollTo","scrollLeft","scrollTop","nextTick","addEventListener","nativeScrollRestoration_","scrollRestoration","event","mixin","isScheduledNavigation","canNavigate","isNavigationScheduled","maybeScheduleNavigation_","preventDefault","navigateFailed","err","onbeforeunload","_onbeforeunload","defaultPrevented","_overloaded","resolve","beforeActivate","prevent","beforeDeactivate","hash","anchorElement","getElementById","substring","getNodeOffset","offsetLeft","offsetTop","saveHistoryCurrentPageScrollPosition_","opt_event","isHtml5HistorySupported","Error","replaceHistory","form","func","altKey","ctrlKey","metaKey","shiftKey","button","delegateTarget","method","buttonSelector","activeElement","querySelector","action","setTimeout","maybeRepositionScrollToHashedAnchor","reloadPage","senna","lockHistoryScrollPosition_","once","referrer","setReferrer","setHostname","hostname","setPort","port","toString","pageYOffset","pageXOffset","maybeDisableNativeScrollRestoration","documentElement","endNavigatePayload","doNavigate_","maybeRestoreNativeScrollRestoration","getTitle","getDefaultTitle","beforeUpdateHistoryPath","historyState","maybeRestoreRedirectPathHash_","updateHistory_","beforeUpdateHistoryState","params","id","surfaceContent","getSurfaceContent","addContent","reload","remove","surfaceId","dispose","replaceState","removePathTrailingSlash","onDocSubmitDelegate_","onDocClickDelegate_","cancel","sync","pushState","titleNode","innerHTML"],"mappings":"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","file":"src/app/App.js","sourcesContent":["'use strict';\n\nimport { addClasses, delegate, match, on, removeClasses } from 'metal-dom';\nimport { array, async, isDefAndNotNull, isString, object } from 'metal';\nimport { EventEmitter, EventHandler } from 'metal-events';\nimport CancellablePromise from 'metal-promise';\nimport debounce from 'metal-debounce';\nimport globals from '../globals/globals';\nimport Route from '../route/Route';\nimport Screen from '../screen/Screen';\nimport Surface from '../surface/Surface';\nimport Uri from 'metal-uri';\nimport utils from '../utils/utils';\n\nconst NavigationStrategy = {\n\tIMMEDIATE: 'immediate',\n\tSCHEDULE_LAST: 'scheduleLast'\n};\n\nclass App extends EventEmitter {\n\n\t/**\n\t * App class that handle routes and screens lifecycle.\n\t * @constructor\n\t * @extends {EventEmitter}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the active screen.\n\t\t * @type {?Screen}\n\t\t * @protected\n\t\t */\n\t\tthis.activeScreen = null;\n\n\t\t/**\n\t\t * Holds the active path containing the query parameters.\n\t\t * @type {?string}\n\t\t * @protected\n\t\t */\n\t\tthis.activePath = null;\n\n\t\t/**\n\t\t * Allows prevent navigate from dom prevented event.\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.allowPreventNavigate = true;\n\n\t\t/**\n\t\t * Holds link base path.\n\t\t * @type {!string}\n\t\t * @default ''\n\t\t * @protected\n\t\t */\n\t\tthis.basePath = '';\n\n\t\t/**\n\t\t * Holds the value of the browser path before a navigation is performed.\n\t\t * @type {!string}\n\t\t * @default the current browser path.\n\t\t * @protected\n\t\t */\n\t\tthis.browserPathBeforeNavigate = utils.getCurrentBrowserPathWithoutHash();\n\n\t\t/**\n\t\t * Captures scroll position from scroll event.\n\t\t * @type {!boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.captureScrollPositionFromScrollEvent = true;\n\n\t\t/**\n\t\t * Holds the default page title.\n\t\t * @type {string}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.defaultTitle = globals.document.title;\n\n\t\t/**\n\t\t * Holds the form selector to define forms that are routed.\n\t\t * @type {!string}\n\t\t * @default form[enctype=\"multipart/form-data\"]:not([data-senna-off])\n\t\t * @protected\n\t\t */\n\t\tthis.formSelector = 'form[enctype=\"multipart/form-data\"]:not([data-senna-off])';\n\n\t\t/**\n\t\t * When enabled, the route matching ignores query string from the path.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.ignoreQueryStringFromRoutePath = false;\n\n\t\t/**\n\t\t * Holds the link selector to define links that are routed.\n\t\t * @type {!string}\n\t\t * @default a:not([data-senna-off])\n\t\t * @protected\n\t\t */\n\t\tthis.linkSelector = 'a:not([data-senna-off]):not([target=\"_blank\"])';\n\n\t\t/**\n\t\t * Holds the loading css class.\n\t\t * @type {!string}\n\t\t * @default senna-loading\n\t\t * @protected\n\t\t */\n\t\tthis.loadingCssClass = 'senna-loading';\n\n\t\t/**\n\t\t * Using the History API to manage your URLs is awesome and, as it happens,\n\t\t * a crucial feature of good web apps. One of its downsides, however, is\n\t\t * that scroll positions are stored and then, more importantly, restored\n\t\t * whenever you traverse the history. This often means unsightly jumps as\n\t\t * the scroll position changes automatically, and especially so if your app\n\t\t * does transitions, or changes the contents of the page in any way.\n\t\t * Ultimately this leads to an horrible user experience. The good news is,\n\t\t * however, that there’s a potential fix: history.scrollRestoration.\n\t\t * https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.nativeScrollRestorationSupported = ('scrollRestoration' in globals.window.history);\n\n\t\t/**\n\t\t * When set to NavigationStrategy.SCHEDULE_LAST means that the current navigation\n\t\t * cannot be Cancelled to start another and will be queued in\n\t\t * scheduledNavigationQueue. When NavigationStrategy.IMMEDIATE means that all\n\t\t * navigation will be cancelled to start another.\n\t\t * @type {!string}\n\t\t * @default immediate\n\t\t * @protected\n\t\t */\n\t\tthis.navigationStrategy = NavigationStrategy.IMMEDIATE;\n\n\t\t/**\n\t\t * When set to true there is a pendingNavigate that has not yet been\n\t\t * resolved or rejected.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.isNavigationPending = false;\n\n\t\t/**\n\t\t * Holds a deferred with the current navigation.\n\t\t * @type {?CancellablePromise}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.pendingNavigate = null;\n\n\t\t/**\n\t\t * Holds the window horizontal scroll position when the navigation using\n\t\t * back or forward happens to be restored after the surfaces are updated.\n\t\t * @type {!Number}\n\t\t * @default 0\n\t\t * @protected\n\t\t */\n\t\tthis.popstateScrollLeft = 0;\n\n\t\t/**\n\t\t * Holds the window vertical scroll position when the navigation using\n\t\t * back or forward happens to be restored after the surfaces are updated.\n\t\t * @type {!Number}\n\t\t * @default 0\n\t\t * @protected\n\t\t */\n\t\tthis.popstateScrollTop = 0;\n\n\t\t/**\n\t\t * Holds the redirect path containing the query parameters.\n\t\t * @type {?string}\n\t\t * @protected\n\t\t */\n\t\tthis.redirectPath = null;\n\n\t\t/**\n\t\t * Holds the screen routes configuration.\n\t\t * @type {?Array}\n\t\t * @default []\n\t\t * @protected\n\t\t */\n\t\tthis.routes = [];\n\n\t\t/**\n\t\t * Holds a queue that stores every DOM event that can initiate a navigation.\n\t\t * @type {!Event}\n\t\t * @default []\n\t\t * @protected\n\t\t */\n\t\tthis.scheduledNavigationQueue = [];\n\n\t\t/**\n\t\t * Maps the screen instances by the url containing the parameters.\n\t\t * @type {?Object}\n\t\t * @default {}\n\t\t * @protected\n\t\t */\n\t\tthis.screens = {};\n\n\t\t/**\n\t\t * When set to true the first erroneous popstate fired on page load will be\n\t\t * ignored, only if globals.window.history.state is also\n\t\t * null.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.skipLoadPopstate = false;\n\n\t\t/**\n\t\t * Maps that index the surfaces instances by the surface id.\n\t\t * @type {?Object}\n\t\t * @default {}\n\t\t * @protected\n\t\t */\n\t\tthis.surfaces = {};\n\n\t\t/**\n\t\t * When set to true, moves the scroll position after popstate, or to the\n\t\t * top of the viewport for new navigation. If false, the browser will\n\t\t * take care of scroll restoration.\n\t\t * @type {!boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.updateScrollPosition = true;\n\n\t\tthis.appEventHandlers_ = new EventHandler();\n\n\t\tthis.appEventHandlers_.add(\n\t\t\ton(globals.window, 'scroll', debounce(this.onScroll_.bind(this), 100)),\n\t\t\ton(globals.window, 'load', this.onLoad_.bind(this)),\n\t\t\ton(globals.window, 'popstate', this.onPopstate_.bind(this))\n\t\t);\n\n\t\tthis.on('startNavigate', this.onStartNavigate_);\n\t\tthis.on('beforeNavigate', this.onBeforeNavigate_);\n\t\tthis.on('beforeNavigate', this.onBeforeNavigateDefault_, true);\n\t\tthis.on('beforeUnload', this.onBeforeUnloadDefault_);\n\n\t\tthis.setLinkSelector(this.linkSelector);\n\t\tthis.setFormSelector(this.formSelector);\n\n\t\tthis.maybeOverloadBeforeUnload_();\n\t}\n\n\t/**\n\t * Adds one or more screens to the application.\n\t *\n\t * Example:\n\t *\n\t * \n\t * app.addRoutes({ path: '/foo', handler: FooScreen });\n\t * or\n\t * app.addRoutes([{ path: '/foo', handler: function(route) { return new FooScreen(); } }]);\n\t * \n\t *\n\t * @param {Object} or {Array} routes Single object or an array of object.\n\t * Each object should contain path and screen.\n\t * The path should be a string or a regex that maps the\n\t * navigation route to a screen class definition (not an instance), e.g:\n\t * { path: \"/home:param1\", handler: MyScreen }\n\t * { path: /foo.+/, handler: MyScreen }\n\t * @chainable\n\t */\n\taddRoutes(routes) {\n\t\tif (!Array.isArray(routes)) {\n\t\t\troutes = [routes];\n\t\t}\n\t\troutes.forEach((route) => {\n\t\t\tif (!(route instanceof Route)) {\n\t\t\t\troute = new Route(route.path, route.handler);\n\t\t\t}\n\t\t\tthis.routes.push(route);\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds one or more surfaces to the application.\n\t * @param {Surface|String|Array.} surfaces\n\t * Surface element id or surface instance. You can also pass an Array\n\t * whichcontains surface instances or id. In case of ID, these should be\n\t * the id of surface element.\n\t * @chainable\n\t */\n\taddSurfaces(surfaces) {\n\t\tif (!Array.isArray(surfaces)) {\n\t\t\tsurfaces = [surfaces];\n\t\t}\n\t\tsurfaces.forEach((surface) => {\n\t\t\tif (isString(surface)) {\n\t\t\t\tsurface = new Surface(surface);\n\t\t\t}\n\t\t\tthis.surfaces[surface.getId()] = surface;\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns if can navigate to path.\n\t * @param {!string} url\n\t * @return {boolean}\n\t */\n\tcanNavigate(url) {\n\t\tconst uri = utils.isWebUri(url);\n\n\t\tif (!uri) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst path = utils.getUrlPath(url);\n\n\t\tif (!this.isLinkSameOrigin_(uri.getHost())) {\n\t\t\tconsole.log('Offsite link clicked');\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.isSameBasePath_(path)) {\n\t\t\tconsole.log('Link clicked outside app\\'s base path');\n\t\t\treturn false;\n\t\t}\n\t\t// Prevents navigation if it's a hash change on the same url.\n\t\tif (uri.getHash() && utils.isCurrentBrowserPath(path)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.findRoute(path)) {\n\t\t\tconsole.log('No route for ' + path);\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Clear screens cache.\n\t * @chainable\n\t */\n\tclearScreensCache() {\n\t\tObject.keys(this.screens).forEach((path) => {\n\t\t\tif (path === this.activePath) {\n\t\t\t\tthis.activeScreen.clearCache();\n\t\t\t} else if (!(this.isNavigationPending && this.pendingNavigate.path === path)) {\n\t\t\t\tthis.removeScreen(path);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves or create a screen instance to a path.\n\t * @param {!string} path Path containing the querystring part.\n\t * @return {Screen}\n\t */\n\tcreateScreenInstance(path, route) {\n\t\tif (!this.pendingNavigate && path === this.activePath) {\n\t\t\tconsole.log('Already at destination, refresh navigation');\n\t\t\treturn this.activeScreen;\n\t\t}\n\t\t/* jshint newcap: false */\n\t\tvar screen = this.screens[path];\n\t\tif (!screen) {\n\t\t\tvar handler = route.getHandler();\n\t\t\tif (handler === Screen || Screen.isImplementedBy(handler.prototype)) {\n\t\t\t\tscreen = new handler();\n\t\t\t} else {\n\t\t\t\tscreen = handler(route) || new Screen();\n\t\t\t}\n\t\t\tconsole.log('Create screen for [' + path + '] [' + screen + ']');\n\t\t}\n\t\treturn screen;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisposeInternal() {\n\t\tif (this.activeScreen) {\n\t\t\tthis.removeScreen(this.activePath);\n\t\t}\n\t\tthis.clearScreensCache();\n\t\tthis.formEventHandler_.removeListener();\n\t\tthis.linkEventHandler_.removeListener();\n\t\tthis.appEventHandlers_.removeAllListeners();\n\t\tsuper.disposeInternal();\n\t}\n\n\t/**\n\t * Dispatches to the first route handler that matches the current path, if\n\t * any.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tdispatch() {\n\t\treturn this.navigate(utils.getCurrentBrowserPath(), true);\n\t}\n\n\t/**\n\t * Starts navigation to a path.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tdoNavigate_(path, opt_replaceHistory) {\n\t\tvar route = this.findRoute(path);\n\t\tif (!route) {\n\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('No route for ' + path));\n\t\t\treturn this.pendingNavigate;\n\t\t}\n\n\t\tconsole.log('Navigate to [' + path + ']');\n\n\t\tthis.stopPendingNavigate_();\n\t\tthis.isNavigationPending = true;\n\n\t\tvar nextScreen = this.createScreenInstance(path, route);\n\n\t\treturn this.maybePreventDeactivate_()\n\t\t\t.then(() => this.maybePreventActivate_(nextScreen))\n\t\t\t.then(() => nextScreen.load(path))\n\t\t\t.then(() => {\n\t\t\t\t// At this point we cannot stop navigation and all received\n\t\t\t\t// navigate candidates will be queued at scheduledNavigationQueue.\n\t\t\t\tthis.navigationStrategy = NavigationStrategy.SCHEDULE_LAST;\n\n\t\t\t\tif (this.activeScreen) {\n\t\t\t\t\tthis.activeScreen.deactivate();\n\t\t\t\t}\n\t\t\t\tthis.prepareNavigateHistory_(path, nextScreen, opt_replaceHistory);\n\t\t\t\tthis.prepareNavigateSurfaces_(\n\t\t\t\t\tnextScreen,\n\t\t\t\t\tthis.surfaces,\n\t\t\t\t\tthis.extractParams(route, path)\n\t\t\t\t);\n\t\t\t})\n\t\t\t.then(() => nextScreen.evaluateStyles(this.surfaces))\n\t\t\t.then(() => nextScreen.flip(this.surfaces))\n\t\t\t.then(() => nextScreen.evaluateScripts(this.surfaces))\n\t\t\t.then(() => this.maybeUpdateScrollPositionState_())\n\t\t\t.then(() => this.syncScrollPositionSyncThenAsync_())\n\t\t\t.then(() => this.finalizeNavigate_(path, nextScreen))\n\t\t\t.then(() => this.maybeOverloadBeforeUnload_())\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.isNavigationPending = false;\n\t\t\t\tthis.handleNavigateError_(path, nextScreen, reason);\n\t\t\t\tthrow reason;\n\t\t\t})\n\t\t\t.thenAlways(() => {\n\t\t\t\tthis.navigationStrategy = NavigationStrategy.IMMEDIATE;\n\n\t\t\t\tif (this.scheduledNavigationQueue.length) {\n\t\t\t\t\tconst scheduledNavigation = this.scheduledNavigationQueue.shift();\n\t\t\t\t\tthis.maybeNavigate_(scheduledNavigation.href, scheduledNavigation);\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Extracts params according to the given path and route.\n\t * @param {!Route} route\n\t * @param {string} path\n\t * @param {!Object}\n\t */\n\textractParams(route, path) {\n\t\treturn route.extractParams(this.getRoutePath(path));\n\t}\n\n\t/**\n\t * Finalizes a screen navigation.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @protected\n\t */\n\tfinalizeNavigate_(path, nextScreen) {\n\t\tnextScreen.activate();\n\n\t\tif (this.activeScreen && !this.activeScreen.isCacheable()) {\n\t\t\tif (this.activeScreen !== nextScreen) {\n\t\t\t\tthis.removeScreen(this.activePath);\n\t\t\t}\n\t\t}\n\n\t\tthis.activePath = path;\n\t\tthis.activeScreen = nextScreen;\n\t\tthis.browserPathBeforeNavigate = utils.getCurrentBrowserPathWithoutHash();\n\t\tthis.screens[path] = nextScreen;\n\t\tthis.isNavigationPending = false;\n\t\tthis.pendingNavigate = null;\n\t\tglobals.capturedFormElement = null;\n\t\tglobals.capturedFormButtonElement = null;\n\t\tconsole.log('Navigation done');\n\t}\n\n\t/**\n\t * Finds a route for the test path. Returns true if matches has a route,\n\t * otherwise returns null.\n\t * @param {!string} path Path containing the querystring part.\n\t * @return {?Object} Route handler if match any or null if the\n\t * path is the same as the current url and the path contains a fragment.\n\t */\n\tfindRoute(path) {\n\t\tpath = this.getRoutePath(path);\n\t\tfor (var i = 0; i < this.routes.length; i++) {\n\t\t\tvar route = this.routes[i];\n\t\t\tif (route.matchesPath(path)) {\n\t\t\t\treturn route;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Gets allow prevent navigate.\n\t * @return {boolean}\n\t */\n\tgetAllowPreventNavigate() {\n\t\treturn this.allowPreventNavigate;\n\t}\n\n\t/**\n\t * Gets link base path.\n\t * @return {!string}\n\t */\n\tgetBasePath() {\n\t\treturn this.basePath;\n\t}\n\n\t/**\n\t * Gets the default page title.\n\t * @return {string} defaultTitle\n\t */\n\tgetDefaultTitle() {\n\t\treturn this.defaultTitle;\n\t}\n\n\t/**\n\t * Gets the form selector.\n\t * @return {!string}\n\t */\n\tgetFormSelector() {\n\t\treturn this.formSelector;\n\t}\n\n\t/**\n\t * Check if route matching is ignoring query string from the route path.\n\t * @return {boolean}\n\t */\n\tgetIgnoreQueryStringFromRoutePath() {\n\t\treturn this.ignoreQueryStringFromRoutePath;\n\t}\n\n\t/**\n\t * Gets the link selector.\n\t * @return {!string}\n\t */\n\tgetLinkSelector() {\n\t\treturn this.linkSelector;\n\t}\n\n\t/**\n\t * Gets the loading css class.\n\t * @return {!string}\n\t */\n\tgetLoadingCssClass() {\n\t\treturn this.loadingCssClass;\n\t}\n\n\t/**\n\t * Returns the given path formatted to be matched by a route. This will,\n\t * for example, remove the base path from it, but make sure it will end\n\t * with a '/'.\n\t * @param {string} path\n\t * @return {string}\n\t */\n\tgetRoutePath(path) {\n\t\tif (this.getIgnoreQueryStringFromRoutePath()) {\n\t\t\tpath = utils.getUrlPathWithoutHashAndSearch(path);\n\t\t\treturn utils.getUrlPathWithoutHashAndSearch(path.substr(this.basePath.length));\n\t\t}\n\n\t\tpath = utils.getUrlPathWithoutHash(path);\n\t\treturn utils.getUrlPathWithoutHash(path.substr(this.basePath.length));\n\t}\n\n\t/**\n\t * Gets the update scroll position value.\n\t * @return {boolean}\n\t */\n\tgetUpdateScrollPosition() {\n\t\treturn this.updateScrollPosition;\n\t}\n\n\t/**\n\t * Handle navigation error.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @param {!Error} error\n\t * @protected\n\t */\n\thandleNavigateError_(path, nextScreen, error) {\n\t\tconsole.log('Navigation error for [' + nextScreen + '] (' + error.stack + ')');\n\t\tthis.emit('navigationError', {\n\t\t\terror,\n\t\t\tnextScreen,\n\t\t\tpath\n\t\t});\n\t\tif (!utils.isCurrentBrowserPath(path)) {\n\t\t\tif (this.isNavigationPending && this.pendingNavigate) {\n\t\t\t\tthis.pendingNavigate.thenAlways(() => this.removeScreen(path), this);\n\t\t\t} else {\n\t\t\t\tthis.removeScreen(path);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if app has routes.\n\t * @return {boolean}\n\t */\n\thasRoutes() {\n\t\treturn this.routes.length > 0;\n\t}\n\n\t/**\n\t * Tests if host is an offsite link.\n\t * @param {!string} host Link host to compare with\n\t * globals.window.location.host.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisLinkSameOrigin_(host) {\n\t\tconst hostUri = new Uri(host);\n\t\tconst locationHostUri = new Uri(globals.window.location.host);\n\n\t\treturn hostUri.getPort() === locationHostUri.getPort() && hostUri.getHostname() === locationHostUri.getHostname();\n\t}\n\n\t/**\n\t * Tests if link element has the same app's base path.\n\t * @param {!string} path Link path containing the querystring part.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisSameBasePath_(path) {\n\t\treturn path.indexOf(this.basePath) === 0;\n\t}\n\n\t/**\n\t * Lock the document scroll in order to avoid the browser native back and\n\t * forward navigation to change the scroll position. In the end of\n\t * navigation lifecycle scroll is repositioned.\n\t * @protected\n\t */\n\tlockHistoryScrollPosition_() {\n\t\tvar state = globals.window.history.state;\n\t\tif (!state) {\n\t\t\treturn;\n\t\t}\n\t\t// Browsers are inconsistent when re-positioning the scroll history on\n\t\t// popstate. At some browsers, history scroll happens before popstate, then\n\t\t// lock the scroll on the last known position as soon as possible after the\n\t\t// current JS execution context and capture the current value. Some others,\n\t\t// history scroll happens after popstate, in this case, we bind an once\n\t\t// scroll event to lock the las known position. Lastly, the previous two\n\t\t// behaviors can happen even on the same browser, hence the race will decide\n\t\t// the winner.\n\t\tvar winner = false;\n\t\tvar switchScrollPositionRace = function() {\n\t\t\tglobals.document.removeEventListener('scroll', switchScrollPositionRace, false);\n\t\t\tif (!winner) {\n\t\t\t\tglobals.window.scrollTo(state.scrollLeft, state.scrollTop);\n\t\t\t\twinner = true;\n\t\t\t}\n\t\t};\n\t\tasync.nextTick(switchScrollPositionRace);\n\t\tglobals.document.addEventListener('scroll', switchScrollPositionRace, false);\n\t}\n\n\t/**\n\t * If supported by the browser, disables native scroll restoration and\n\t * stores current value.\n\t */\n\tmaybeDisableNativeScrollRestoration() {\n\t\tif (this.nativeScrollRestorationSupported) {\n\t\t\tthis.nativeScrollRestoration_ = globals.window.history.scrollRestoration;\n\t\t\tglobals.window.history.scrollRestoration = 'manual';\n\t\t}\n\t}\n\n\t/**\n\t * This method is used to evaluate if is possible to queue received\n\t * dom event to scheduleNavigationQueue and enqueue it.\n\t * @param {string} href Information about the link's href.\n\t * @param {Event} event Dom event that initiated the navigation.\n\t */\n\tmaybeScheduleNavigation_(href, event) {\n\t\tif (this.isNavigationPending && this.navigationStrategy === NavigationStrategy.SCHEDULE_LAST) {\n\t\t\tthis.scheduledNavigationQueue = [object.mixin({\n\t\t\t\thref,\n\t\t\t\tisScheduledNavigation: true\n\t\t\t}, event)];\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Maybe navigate to a path.\n\t * @param {string} href Information about the link's href.\n\t * @param {Event} event Dom event that initiated the navigation.\n\t */\n\tmaybeNavigate_(href, event) {\n\t\tif (!this.canNavigate(href)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isNavigationScheduled = this.maybeScheduleNavigation_(href, event);\n\n\t\tif (isNavigationScheduled) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tvar navigateFailed = false;\n\t\ttry {\n\t\t\tthis.navigate(utils.getUrlPath(href), false, event);\n\t\t} catch (err) {\n\t\t\t// Do not prevent link navigation in case some synchronous error occurs\n\t\t\tnavigateFailed = true;\n\t\t}\n\n\t\tif (!navigateFailed && !event.isScheduledNavigation) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether the onbeforeunload global event handler is overloaded\n\t * by client code. If so, it replaces with a function that halts the normal\n\t * event flow in relation with the client onbeforeunload function.\n\t * This can be in most part used to prematurely terminate navigation to other pages\n\t * according to the given constrait(s).\n\t * @protected\n\t */\n\tmaybeOverloadBeforeUnload_() {\n\t\tif ('function' === typeof window.onbeforeunload) {\n\t\t\twindow._onbeforeunload = window.onbeforeunload;\n\n\t\t\twindow.onbeforeunload = event => {\n\t\t\t\tthis.emit('beforeUnload', event);\n\t\t\t\tif (event && event.defaultPrevented) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// mark the updated handler due unwanted recursion\n\t\t\twindow.onbeforeunload._overloaded = true;\n\t\t}\n\t}\n\n\t/**\n\t * Cancels navigation if nextScreen's beforeActivate lifecycle method\n\t * resolves to true.\n\t * @param {!Screen} nextScreen\n\t * @return {!CancellablePromise}\n\t */\n\tmaybePreventActivate_(nextScreen) {\n\t\treturn CancellablePromise.resolve()\n\t\t\t.then(() => {\n\t\t\t\treturn nextScreen.beforeActivate();\n\t\t\t})\n\t\t\t.then(prevent => {\n\t\t\t\tif (prevent) {\n\t\t\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by next screen'));\n\t\t\t\t\treturn this.pendingNavigate;\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Cancels navigation if activeScreen's beforeDeactivate lifecycle\n\t * method resolves to true.\n\t * @return {!CancellablePromise}\n\t */\n\tmaybePreventDeactivate_() {\n\t\treturn CancellablePromise.resolve()\n\t\t\t.then(() => {\n\t\t\t\tif (this.activeScreen) {\n\t\t\t\t\treturn this.activeScreen.beforeDeactivate();\n\t\t\t\t}\n\t\t\t})\n\t\t\t.then(prevent => {\n\t\t\t\tif (prevent) {\n\t\t\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by active screen'));\n\t\t\t\t\treturn this.pendingNavigate;\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Maybe reposition scroll to hashed anchor.\n\t */\n\tmaybeRepositionScrollToHashedAnchor() {\n\t\tconst hash = globals.window.location.hash;\n\t\tif (hash) {\n\t\t\tlet anchorElement = globals.document.getElementById(hash.substring(1));\n\t\t\tif (anchorElement) {\n\t\t\t\tconst {offsetLeft, offsetTop} = utils.getNodeOffset(anchorElement);\n\t\t\t\tglobals.window.scrollTo(offsetLeft, offsetTop);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * If supported by the browser, restores native scroll restoration to the\n\t * value captured by `maybeDisableNativeScrollRestoration`.\n\t */\n\tmaybeRestoreNativeScrollRestoration() {\n\t\tif (this.nativeScrollRestorationSupported && this.nativeScrollRestoration_) {\n\t\t\tglobals.window.history.scrollRestoration = this.nativeScrollRestoration_;\n\t\t}\n\t}\n\n\t/**\n\t * Maybe restore redirected path hash in case both the current path and\n\t * the given path are the same.\n\t * @param {!string} path Path before navigation.\n\t * @param {!string} redirectPath Path after navigation.\n\t * @param {!string} hash Hash to be added to the path.\n\t * @return {!string} Returns the path with the hash restored.\n\t */\n\tmaybeRestoreRedirectPathHash_(path, redirectPath, hash) {\n\t\tif (redirectPath === utils.getUrlPathWithoutHash(path)) {\n\t\t\treturn redirectPath + hash;\n\t\t}\n\t\treturn redirectPath;\n\t}\n\n\t/**\n\t * Maybe update scroll position in history state to anchor on path.\n\t * @param {!string} path Path containing anchor\n\t */\n\tmaybeUpdateScrollPositionState_() {\n\t\tvar hash = globals.window.location.hash;\n\t\tvar anchorElement = globals.document.getElementById(hash.substring(1));\n\t\tif (anchorElement) {\n\t\t\tconst {offsetLeft, offsetTop} = utils.getNodeOffset(anchorElement);\n\t\t\tthis.saveHistoryCurrentPageScrollPosition_(offsetTop, offsetLeft);\n\t\t}\n\t}\n\n\t/**\n\t * Navigates to the specified path if there is a route handler that matches.\n\t * @param {!string} path Path to navigate containing the base path.\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @param {Event=} event Optional event object that triggered the navigation.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tnavigate(path, opt_replaceHistory, opt_event) {\n\t\tif (!utils.isHtml5HistorySupported()) {\n\t\t\tthrow new Error('HTML5 History is not supported. Senna will not intercept navigation.');\n\t\t}\n\n\t\tif (opt_event) {\n\t\t\tglobals.capturedFormElement = opt_event.capturedFormElement;\n\t\t\tglobals.capturedFormButtonElement = opt_event.capturedFormButtonElement;\n\t\t}\n\n\t\t// When reloading the same path do replaceState instead of pushState to\n\t\t// avoid polluting history with states with the same path.\n\t\tif (path === this.activePath) {\n\t\t\topt_replaceHistory = true;\n\t\t}\n\n\t\tthis.emit('beforeNavigate', {\n\t\t\tevent: opt_event,\n\t\t\tpath: path,\n\t\t\treplaceHistory: !!opt_replaceHistory\n\t\t});\n\n\t\treturn this.pendingNavigate;\n\t}\n\n\t/**\n\t * Befores navigation to a path.\n\t * @param {!Event} event Event facade containing path and\n\t * replaceHistory.\n\t * @protected\n\t */\n\tonBeforeNavigate_(event) {\n\t\tif (globals.capturedFormElement) {\n\t\t\tevent.form = globals.capturedFormElement;\n\t\t}\n\t}\n\n\t/**\n\t * Befores navigation to a path. Runs after external listeners.\n\t * @param {!Event} event Event facade containing path and\n\t * replaceHistory.\n\t * @protected\n\t */\n\tonBeforeNavigateDefault_(event) {\n\t\tif (this.pendingNavigate) {\n\t\t\tif (this.pendingNavigate.path === event.path || this.navigationStrategy === NavigationStrategy.SCHEDULE_LAST) {\n\t\t\t\tconsole.log('Waiting...');\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.emit('beforeUnload', event);\n\n\t\tthis.emit('startNavigate', {\n\t\t\tform: event.form,\n\t\t\tpath: event.path,\n\t\t\treplaceHistory: event.replaceHistory\n\t\t});\n\t}\n\n\t/**\n\t * Custom event handler that executes the original listener that has been\n\t * added by the client code and terminates the navigation accordingly.\n\t * @param {!Event} event original Event facade.\n\t * @protected\n\t */\n\tonBeforeUnloadDefault_(event) {\n\t\tvar func = window._onbeforeunload;\n\t\tif (func && !func._overloaded && func()) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\t/**\n\t * Intercepts document clicks and test link elements in order to decide\n\t * whether Surface app can navigate.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonDocClickDelegate_(event) {\n\t\tif (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.button) {\n\t\t\tconsole.log('Navigate aborted, invalid mouse button or modifier key pressed.');\n\t\t\treturn;\n\t\t}\n\t\tthis.maybeNavigate_(event.delegateTarget.href, event);\n\t}\n\n\t/**\n\t * Intercepts document form submits and test action path in order to decide\n\t * whether Surface app can navigate.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonDocSubmitDelegate_(event) {\n\t\tvar form = event.delegateTarget;\n\t\tif (form.method === 'get') {\n\t\t\tconsole.log('GET method not supported');\n\t\t\treturn;\n\t\t}\n\t\tevent.capturedFormElement = form;\n\t\tconst buttonSelector = 'button:not([type]),button[type=submit],input[type=submit]';\n\t\tif (match(globals.document.activeElement, buttonSelector)) {\n\t\t\tevent.capturedFormButtonElement = globals.document.activeElement;\n\t\t} else {\n\t\t\tevent.capturedFormButtonElement = form.querySelector(buttonSelector);\n\t\t}\n\t\tthis.maybeNavigate_(form.action, event);\n\t}\n\n\t/**\n\t * Listens to the window's load event in order to avoid issues with some browsers\n\t * that trigger popstate calls on the first load. For more information see\n\t * http://stackoverflow.com/questions/6421769/popstate-on-pages-load-in-chrome.\n\t * @protected\n\t */\n\tonLoad_() {\n\t\tthis.skipLoadPopstate = true;\n\t\tsetTimeout(() => {\n\t\t\t// The timeout ensures that popstate events will be unblocked right\n\t\t\t// after the load event occured, but not in the same event-loop cycle.\n\t\t\tthis.skipLoadPopstate = false;\n\t\t}, 0);\n\t\t// Try to reposition scroll to the hashed anchor when page loads.\n\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t}\n\n\t/**\n\t * Handles browser history changes and fires app's navigation if the state\n\t * belows to us. If we detect a popstate and the state is null,\n\t * assume it is navigating to an external page or to a page we don't have\n\t * route, then globals.window.location.reload() is invoked in order to\n\t * reload the content to the current url.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonPopstate_(event) {\n\t\tif (this.skipLoadPopstate) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Do not navigate if the popstate was triggered by a hash change.\n\t\tif (utils.isCurrentBrowserPath(this.browserPathBeforeNavigate)) {\n\t\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t\t\treturn;\n\t\t}\n\n\t\tvar state = event.state;\n\n\t\tif (!state) {\n\t\t\tif (globals.window.location.hash) {\n\t\t\t\t// If senna is on an redirect path and a hash popstate happens\n\t\t\t\t// to a different url, reload the browser. This behavior doesn't\n\t\t\t\t// require senna to route hashed links and is closer to native\n\t\t\t\t// browser behavior.\n\t\t\t\tif (this.redirectPath && !utils.isCurrentBrowserPath(this.redirectPath)) {\n\t\t\t\t\tthis.reloadPage();\n\t\t\t\t}\n\t\t\t\t// Always try to reposition scroll to the hashed anchor when\n\t\t\t\t// hash popstate happens.\n\t\t\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t\t\t} else {\n\t\t\t\tthis.reloadPage();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (state.senna) {\n\t\t\tconsole.log('History navigation to [' + state.path + ']');\n\t\t\tthis.popstateScrollTop = state.scrollTop;\n\t\t\tthis.popstateScrollLeft = state.scrollLeft;\n\t\t\tif (!this.nativeScrollRestorationSupported) {\n\t\t\t\tthis.lockHistoryScrollPosition_();\n\t\t\t}\n\t\t\tthis.once('endNavigate', () => {\n\t\t\t\tif (state.referrer) {\n\t\t\t\t\tutils.setReferrer(state.referrer);\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst uri = new Uri(state.path);\n\t\t\turi.setHostname(globals.window.location.hostname);\n\t\t\turi.setPort(globals.window.location.port);\n\t\t\tconst isNavigationScheduled = this.maybeScheduleNavigation_(uri.toString(), {});\n\t\t\tif (isNavigationScheduled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.navigate(state.path, true);\n\t\t}\n\t}\n\n\t/**\n\t * Listens document scroll changes in order to capture the possible lock\n\t * scroll position for history scrolling.\n\t * @protected\n\t */\n\tonScroll_() {\n\t\tif (this.captureScrollPositionFromScrollEvent) {\n\t\t\tthis.saveHistoryCurrentPageScrollPosition_(globals.window.pageYOffset, globals.window.pageXOffset);\n\t\t}\n\t}\n\n\t/**\n\t * Starts navigation to a path.\n\t * @param {!Event} event Event facade containing path and\n\t * replaceHistory.\n\t * @protected\n\t */\n\tonStartNavigate_(event) {\n\t\tthis.maybeDisableNativeScrollRestoration();\n\t\tthis.captureScrollPositionFromScrollEvent = false;\n\t\taddClasses(globals.document.documentElement, this.loadingCssClass);\n\n\t\tvar endNavigatePayload = {\n\t\t\tform: event.form,\n\t\t\tpath: event.path\n\t\t};\n\n\t\tthis.pendingNavigate = this.doNavigate_(event.path, event.replaceHistory)\n\t\t\t.catch((reason) => {\n\t\t\t\tendNavigatePayload.error = reason;\n\t\t\t\tthrow reason;\n\t\t\t})\n\t\t\t.thenAlways(() => {\n\t\t\t\tif (!this.pendingNavigate && !this.scheduledNavigationQueue.length) {\n\t\t\t\t\tremoveClasses(globals.document.documentElement, this.loadingCssClass);\n\t\t\t\t\tthis.maybeRestoreNativeScrollRestoration();\n\t\t\t\t\tthis.captureScrollPositionFromScrollEvent = true;\n\t\t\t\t}\n\t\t\t\tthis.emit('endNavigate', endNavigatePayload);\n\t\t\t});\n\n\t\tthis.pendingNavigate.path = event.path;\n\t}\n\n\t/**\n\t * Prefetches the specified path if there is a route handler that matches.\n\t * @param {!string} path Path to navigate containing the base path.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tprefetch(path) {\n\t\tvar route = this.findRoute(path);\n\t\tif (!route) {\n\t\t\treturn CancellablePromise.reject(new CancellablePromise.CancellationError('No route for ' + path));\n\t\t}\n\n\t\tconsole.log('Prefetching [' + path + ']');\n\n\t\tvar nextScreen = this.createScreenInstance(path, route);\n\n\t\treturn nextScreen.load(path)\n\t\t\t.then(() => this.screens[path] = nextScreen)\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.handleNavigateError_(path, nextScreen, reason);\n\t\t\t\tthrow reason;\n\t\t\t});\n\t}\n\n\t/**\n\t * Prepares screen flip. Updates history state and surfaces content.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t */\n\tprepareNavigateHistory_(path, nextScreen, opt_replaceHistory) {\n\t\tlet title = nextScreen.getTitle();\n\t\tif (!isString(title)) {\n\t\t\ttitle = this.getDefaultTitle();\n\t\t}\n\t\tlet redirectPath = nextScreen.beforeUpdateHistoryPath(path);\n\t\tconst historyState = {\n\t\t\tform: isDefAndNotNull(globals.capturedFormElement),\n\t\t\tpath,\n\t\t\tredirectPath,\n\t\t\tscrollLeft: 0,\n\t\t\tscrollTop: 0,\n\t\t\tsenna: true\n\t\t};\n\t\tif (opt_replaceHistory) {\n\t\t\thistoryState.scrollTop = this.popstateScrollTop;\n\t\t\thistoryState.scrollLeft = this.popstateScrollLeft;\n\t\t}\n\t\tconst hash = new Uri(path).getHash();\n\t\tredirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash);\n\t\tthis.updateHistory_(title, redirectPath, nextScreen.beforeUpdateHistoryState(historyState), opt_replaceHistory);\n\t\tthis.redirectPath = redirectPath;\n\t}\n\n\t/**\n\t * Prepares screen flip. Updates history state and surfaces content.\n\t * @param {!Screen} nextScreen\n\t * @param {!Object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @param {!Object} params Params extracted from the current path.\n\t */\n\tprepareNavigateSurfaces_(nextScreen, surfaces, params) {\n\t\tObject.keys(surfaces).forEach((id) => {\n\t\t\tvar surfaceContent = nextScreen.getSurfaceContent(id, params);\n\t\t\tsurfaces[id].addContent(nextScreen.getId(), surfaceContent);\n\t\t\tconsole.log('Screen [' + nextScreen.getId() + '] add content to surface ' +\n\t\t\t\t'[' + surfaces[id] + '] [' + (isDefAndNotNull(surfaceContent) ? '...' : 'empty') + ']');\n\t\t});\n\t}\n\n\t/**\n\t * Reloads the page by performing `window.location.reload()`.\n\t */\n\treloadPage() {\n\t\tglobals.window.location.reload();\n\t}\n\n\t/**\n\t * Removes route instance from app routes.\n\t * @param {Route} route\n\t * @return {boolean} True if an element was removed.\n\t */\n\tremoveRoute(route) {\n\t\treturn array.remove(this.routes, route);\n\t}\n\n\t/**\n\t * Removes a screen.\n\t * @param {!string} path Path containing the querystring part.\n\t */\n\tremoveScreen(path) {\n\t\tvar screen = this.screens[path];\n\t\tif (screen) {\n\t\t\tObject.keys(this.surfaces).forEach((surfaceId) => this.surfaces[surfaceId].remove(screen.getId()));\n\t\t\tscreen.dispose();\n\t\t\tdelete this.screens[path];\n\t\t}\n\t}\n\n\t/**\n\t * Saves given scroll position into history state.\n\t * @param {!number} scrollTop Number containing the top scroll position to be saved.\n\t * @param {!number} scrollLeft Number containing the left scroll position to be saved.\n\t */\n\tsaveHistoryCurrentPageScrollPosition_(scrollTop, scrollLeft) {\n\t\tvar state = globals.window.history.state;\n\t\tif (state && state.senna) {\n\t\t\t[state.scrollTop, state.scrollLeft] = [scrollTop, scrollLeft];\n\t\t\tglobals.window.history.replaceState(state, null, null);\n\t\t}\n\t}\n\n\t/**\n\t * Sets allow prevent navigate.\n\t * @param {boolean} allowPreventNavigate\n\t */\n\tsetAllowPreventNavigate(allowPreventNavigate) {\n\t\tthis.allowPreventNavigate = allowPreventNavigate;\n\t}\n\n\t/**\n\t * Sets link base path.\n\t * @param {!string} path\n\t */\n\tsetBasePath(basePath) {\n\t\tthis.basePath = utils.removePathTrailingSlash(basePath);\n\t}\n\n\t/**\n\t * Sets the default page title.\n\t * @param {string} defaultTitle\n\t */\n\tsetDefaultTitle(defaultTitle) {\n\t\tthis.defaultTitle = defaultTitle;\n\t}\n\n\t/**\n\t * Sets the form selector.\n\t * @param {!string} formSelector\n\t */\n\tsetFormSelector(formSelector) {\n\t\tthis.formSelector = formSelector;\n\t\tif (this.formEventHandler_) {\n\t\t\tthis.formEventHandler_.removeListener();\n\t\t}\n\t\tthis.formEventHandler_ = delegate(document, 'submit', this.formSelector, this.onDocSubmitDelegate_.bind(this), this.allowPreventNavigate);\n\t}\n\n\t/**\n\t * Sets if route matching should ignore query string from the route path.\n\t * @param {boolean} ignoreQueryStringFromRoutePath\n\t */\n\tsetIgnoreQueryStringFromRoutePath(ignoreQueryStringFromRoutePath) {\n\t\tthis.ignoreQueryStringFromRoutePath = ignoreQueryStringFromRoutePath;\n\t}\n\n\t/**\n\t * Sets the link selector.\n\t * @param {!string} linkSelector\n\t */\n\tsetLinkSelector(linkSelector) {\n\t\tthis.linkSelector = linkSelector;\n\t\tif (this.linkEventHandler_) {\n\t\t\tthis.linkEventHandler_.removeListener();\n\t\t}\n\t\tthis.linkEventHandler_ = delegate(document, 'click', this.linkSelector, this.onDocClickDelegate_.bind(this), this.allowPreventNavigate);\n\t}\n\n\t/**\n\t * Sets the loading css class.\n\t * @param {!string} loadingCssClass\n\t */\n\tsetLoadingCssClass(loadingCssClass) {\n\t\tthis.loadingCssClass = loadingCssClass;\n\t}\n\n\t/**\n\t * Sets the update scroll position value.\n\t * @param {boolean} updateScrollPosition\n\t */\n\tsetUpdateScrollPosition(updateScrollPosition) {\n\t\tthis.updateScrollPosition = updateScrollPosition;\n\t}\n\n\t/**\n\t * Cancels pending navigate with Cancel pending navigation error.\n\t * @protected\n\t */\n\tstopPendingNavigate_() {\n\t\tif (this.pendingNavigate) {\n\t\t\tthis.pendingNavigate.cancel('Cancel pending navigation');\n\t\t}\n\t\tthis.pendingNavigate = null;\n\t}\n\n\t/**\n\t * Sync document scroll position twice, the first one synchronous and then\n\t * one inside async.nextTick. Relevant to browsers that fires\n\t * scroll restoration asynchronously after popstate.\n\t * @protected\n\t * @return {?CancellablePromise=}\n\t */\n\tsyncScrollPositionSyncThenAsync_() {\n\t\tvar state = globals.window.history.state;\n\t\tif (!state) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar scrollTop = state.scrollTop;\n\t\tvar scrollLeft = state.scrollLeft;\n\n\t\tvar sync = () => {\n\t\t\tif (this.updateScrollPosition) {\n\t\t\t\tglobals.window.scrollTo(scrollLeft, scrollTop);\n\t\t\t}\n\t\t};\n\n\t\treturn new CancellablePromise((resolve) => sync() & async.nextTick(() => sync() & resolve()));\n\t}\n\n\t/**\n\t * Updates or replace browser history.\n\t * @param {?string} title Document title.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!object} state\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @protected\n\t */\n\tupdateHistory_(title, path, state, opt_replaceHistory) {\n\t\tconst referrer = globals.window.location.href;\n\n\t\tif (state) {\n\t\t\tstate.referrer = referrer;\n\t\t}\n\n\t\tif (opt_replaceHistory) {\n\t\t\tglobals.window.history.replaceState(state, title, path);\n\t\t} else {\n\t\t\tglobals.window.history.pushState(state, title, path);\n\t\t}\n\n\t\tutils.setReferrer(referrer);\n\n\t\tlet titleNode = globals.document.querySelector('title');\n\t\tif (titleNode) {\n\t\t\ttitleNode.innerHTML = title;\n\t\t} else {\n\t\t\tglobals.document.title = title;\n\t\t}\n\t}\n\n}\n\nexport default App;\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["App.js"],"names":["NavigationStrategy","IMMEDIATE","SCHEDULE_LAST","App","activeScreen","activePath","allowPreventNavigate","basePath","browserPathBeforeNavigate","getCurrentBrowserPathWithoutHash","captureScrollPositionFromScrollEvent","defaultTitle","document","title","formSelector","ignoreQueryStringFromRoutePath","linkSelector","loadingCssClass","nativeScrollRestorationSupported","window","history","navigationStrategy","isNavigationPending","pendingNavigate","popstateScrollLeft","popstateScrollTop","redirectPath","routes","scheduledNavigationQueue","screens","skipLoadPopstate","surfaces","updateScrollPosition","appEventHandlers_","add","onScroll_","bind","onLoad_","onPopstate_","on","onStartNavigate_","onBeforeNavigate_","onBeforeNavigateDefault_","onBeforeUnloadDefault_","setLinkSelector","setFormSelector","maybeOverloadBeforeUnload_","Array","isArray","forEach","route","path","handler","push","surface","getId","url","uri","isWebUri","getUrlPath","isLinkSameOrigin_","getHost","console","log","isSameBasePath_","getHash","isCurrentBrowserPath","findRoute","Object","keys","clearCache","removeScreen","screen","getHandler","isImplementedBy","prototype","clearScreensCache","formEventHandler_","removeListener","linkEventHandler_","removeAllListeners","navigate","getCurrentBrowserPath","opt_replaceHistory","reject","CancellationError","stopPendingNavigate_","nextScreen","createScreenInstance","maybePreventDeactivate_","then","maybePreventActivate_","load","deactivate","prepareNavigateHistory_","prepareNavigateSurfaces_","extractParams","evaluateStyles","flip","evaluateScripts","maybeUpdateScrollPositionState_","syncScrollPositionSyncThenAsync_","finalizeNavigate_","catch","reason","handleNavigateError_","thenAlways","length","scheduledNavigation","shift","maybeNavigate_","href","getRoutePath","activate","isCacheable","capturedFormElement","capturedFormButtonElement","i","matchesPath","getIgnoreQueryStringFromRoutePath","getUrlPathWithoutHashAndSearch","substr","getUrlPathWithoutHash","error","stack","emit","host","hostUri","locationHostUri","location","getPort","getHostname","indexOf","state","winner","switchScrollPositionRace","removeEventListener","scrollTo","scrollLeft","scrollTop","nextTick","addEventListener","nativeScrollRestoration_","scrollRestoration","event","mixin","isScheduledNavigation","canNavigate","isNavigationScheduled","maybeScheduleNavigation_","preventDefault","navigateFailed","err","onbeforeunload","_onbeforeunload","defaultPrevented","_overloaded","resolve","beforeActivate","prevent","beforeDeactivate","hash","anchorElement","getElementById","substring","getNodeOffset","offsetLeft","offsetTop","saveHistoryCurrentPageScrollPosition_","opt_event","isHtml5HistorySupported","Error","replaceHistory","form","func","altKey","ctrlKey","metaKey","shiftKey","button","delegateTarget","method","buttonSelector","activeElement","querySelector","action","setTimeout","maybeRepositionScrollToHashedAnchor","reloadPage","senna","lockHistoryScrollPosition_","once","referrer","setReferrer","setHostname","hostname","setPort","port","toString","pageYOffset","pageXOffset","maybeDisableNativeScrollRestoration","documentElement","endNavigatePayload","doNavigate_","maybeRestoreNativeScrollRestoration","getTitle","getDefaultTitle","beforeUpdateHistoryPath","maybeRestoreRedirectPathHash_","historyState","updateHistory_","beforeUpdateHistoryState","params","id","surfaceContent","getSurfaceContent","addContent","reload","remove","surfaceId","dispose","replaceState","removePathTrailingSlash","onDocSubmitDelegate_","onDocClickDelegate_","cancel","sync","pushState","titleNode","innerHTML"],"mappings":"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","file":"src/app/App.js","sourcesContent":["'use strict';\n\nimport { addClasses, delegate, match, on, removeClasses } from 'metal-dom';\nimport { array, async, isDefAndNotNull, isString, object } from 'metal';\nimport { EventEmitter, EventHandler } from 'metal-events';\nimport CancellablePromise from 'metal-promise';\nimport debounce from 'metal-debounce';\nimport globals from '../globals/globals';\nimport Route from '../route/Route';\nimport Screen from '../screen/Screen';\nimport Surface from '../surface/Surface';\nimport Uri from 'metal-uri';\nimport utils from '../utils/utils';\n\nconst NavigationStrategy = {\n\tIMMEDIATE: 'immediate',\n\tSCHEDULE_LAST: 'scheduleLast'\n};\n\nclass App extends EventEmitter {\n\n\t/**\n\t * App class that handle routes and screens lifecycle.\n\t * @constructor\n\t * @extends {EventEmitter}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the active screen.\n\t\t * @type {?Screen}\n\t\t * @protected\n\t\t */\n\t\tthis.activeScreen = null;\n\n\t\t/**\n\t\t * Holds the active path containing the query parameters.\n\t\t * @type {?string}\n\t\t * @protected\n\t\t */\n\t\tthis.activePath = null;\n\n\t\t/**\n\t\t * Allows prevent navigate from dom prevented event.\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.allowPreventNavigate = true;\n\n\t\t/**\n\t\t * Holds link base path.\n\t\t * @type {!string}\n\t\t * @default ''\n\t\t * @protected\n\t\t */\n\t\tthis.basePath = '';\n\n\t\t/**\n\t\t * Holds the value of the browser path before a navigation is performed.\n\t\t * @type {!string}\n\t\t * @default the current browser path.\n\t\t * @protected\n\t\t */\n\t\tthis.browserPathBeforeNavigate = utils.getCurrentBrowserPathWithoutHash();\n\n\t\t/**\n\t\t * Captures scroll position from scroll event.\n\t\t * @type {!boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.captureScrollPositionFromScrollEvent = true;\n\n\t\t/**\n\t\t * Holds the default page title.\n\t\t * @type {string}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.defaultTitle = globals.document.title;\n\n\t\t/**\n\t\t * Holds the form selector to define forms that are routed.\n\t\t * @type {!string}\n\t\t * @default form[enctype=\"multipart/form-data\"]:not([data-senna-off])\n\t\t * @protected\n\t\t */\n\t\tthis.formSelector = 'form[enctype=\"multipart/form-data\"]:not([data-senna-off])';\n\n\t\t/**\n\t\t * When enabled, the route matching ignores query string from the path.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.ignoreQueryStringFromRoutePath = false;\n\n\t\t/**\n\t\t * Holds the link selector to define links that are routed.\n\t\t * @type {!string}\n\t\t * @default a:not([data-senna-off])\n\t\t * @protected\n\t\t */\n\t\tthis.linkSelector = 'a:not([data-senna-off]):not([target=\"_blank\"])';\n\n\t\t/**\n\t\t * Holds the loading css class.\n\t\t * @type {!string}\n\t\t * @default senna-loading\n\t\t * @protected\n\t\t */\n\t\tthis.loadingCssClass = 'senna-loading';\n\n\t\t/**\n\t\t * Using the History API to manage your URLs is awesome and, as it happens,\n\t\t * a crucial feature of good web apps. One of its downsides, however, is\n\t\t * that scroll positions are stored and then, more importantly, restored\n\t\t * whenever you traverse the history. This often means unsightly jumps as\n\t\t * the scroll position changes automatically, and especially so if your app\n\t\t * does transitions, or changes the contents of the page in any way.\n\t\t * Ultimately this leads to an horrible user experience. The good news is,\n\t\t * however, that there’s a potential fix: history.scrollRestoration.\n\t\t * https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.nativeScrollRestorationSupported = ('scrollRestoration' in globals.window.history);\n\n\t\t/**\n\t\t * When set to NavigationStrategy.SCHEDULE_LAST means that the current navigation\n\t\t * cannot be Cancelled to start another and will be queued in\n\t\t * scheduledNavigationQueue. When NavigationStrategy.IMMEDIATE means that all\n\t\t * navigation will be cancelled to start another.\n\t\t * @type {!string}\n\t\t * @default immediate\n\t\t * @protected\n\t\t */\n\t\tthis.navigationStrategy = NavigationStrategy.IMMEDIATE;\n\n\t\t/**\n\t\t * When set to true there is a pendingNavigate that has not yet been\n\t\t * resolved or rejected.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.isNavigationPending = false;\n\n\t\t/**\n\t\t * Holds a deferred with the current navigation.\n\t\t * @type {?CancellablePromise}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.pendingNavigate = null;\n\n\t\t/**\n\t\t * Holds the window horizontal scroll position when the navigation using\n\t\t * back or forward happens to be restored after the surfaces are updated.\n\t\t * @type {!Number}\n\t\t * @default 0\n\t\t * @protected\n\t\t */\n\t\tthis.popstateScrollLeft = 0;\n\n\t\t/**\n\t\t * Holds the window vertical scroll position when the navigation using\n\t\t * back or forward happens to be restored after the surfaces are updated.\n\t\t * @type {!Number}\n\t\t * @default 0\n\t\t * @protected\n\t\t */\n\t\tthis.popstateScrollTop = 0;\n\n\t\t/**\n\t\t * Holds the redirect path containing the query parameters.\n\t\t * @type {?string}\n\t\t * @protected\n\t\t */\n\t\tthis.redirectPath = null;\n\n\t\t/**\n\t\t * Holds the screen routes configuration.\n\t\t * @type {?Array}\n\t\t * @default []\n\t\t * @protected\n\t\t */\n\t\tthis.routes = [];\n\n\t\t/**\n\t\t * Holds a queue that stores every DOM event that can initiate a navigation.\n\t\t * @type {!Event}\n\t\t * @default []\n\t\t * @protected\n\t\t */\n\t\tthis.scheduledNavigationQueue = [];\n\n\t\t/**\n\t\t * Maps the screen instances by the url containing the parameters.\n\t\t * @type {?Object}\n\t\t * @default {}\n\t\t * @protected\n\t\t */\n\t\tthis.screens = {};\n\n\t\t/**\n\t\t * When set to true the first erroneous popstate fired on page load will be\n\t\t * ignored, only if globals.window.history.state is also\n\t\t * null.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.skipLoadPopstate = false;\n\n\t\t/**\n\t\t * Maps that index the surfaces instances by the surface id.\n\t\t * @type {?Object}\n\t\t * @default {}\n\t\t * @protected\n\t\t */\n\t\tthis.surfaces = {};\n\n\t\t/**\n\t\t * When set to true, moves the scroll position after popstate, or to the\n\t\t * top of the viewport for new navigation. If false, the browser will\n\t\t * take care of scroll restoration.\n\t\t * @type {!boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.updateScrollPosition = true;\n\n\t\tthis.appEventHandlers_ = new EventHandler();\n\n\t\tthis.appEventHandlers_.add(\n\t\t\ton(globals.window, 'scroll', debounce(this.onScroll_.bind(this), 100)),\n\t\t\ton(globals.window, 'load', this.onLoad_.bind(this)),\n\t\t\ton(globals.window, 'popstate', this.onPopstate_.bind(this))\n\t\t);\n\n\t\tthis.on('startNavigate', this.onStartNavigate_);\n\t\tthis.on('beforeNavigate', this.onBeforeNavigate_);\n\t\tthis.on('beforeNavigate', this.onBeforeNavigateDefault_, true);\n\t\tthis.on('beforeUnload', this.onBeforeUnloadDefault_);\n\n\t\tthis.setLinkSelector(this.linkSelector);\n\t\tthis.setFormSelector(this.formSelector);\n\n\t\tthis.maybeOverloadBeforeUnload_();\n\t}\n\n\t/**\n\t * Adds one or more screens to the application.\n\t *\n\t * Example:\n\t *\n\t * \n\t * app.addRoutes({ path: '/foo', handler: FooScreen });\n\t * or\n\t * app.addRoutes([{ path: '/foo', handler: function(route) { return new FooScreen(); } }]);\n\t * \n\t *\n\t * @param {Object} or {Array} routes Single object or an array of object.\n\t * Each object should contain path and screen.\n\t * The path should be a string or a regex that maps the\n\t * navigation route to a screen class definition (not an instance), e.g:\n\t * { path: \"/home:param1\", handler: MyScreen }\n\t * { path: /foo.+/, handler: MyScreen }\n\t * @chainable\n\t */\n\taddRoutes(routes) {\n\t\tif (!Array.isArray(routes)) {\n\t\t\troutes = [routes];\n\t\t}\n\t\troutes.forEach((route) => {\n\t\t\tif (!(route instanceof Route)) {\n\t\t\t\troute = new Route(route.path, route.handler);\n\t\t\t}\n\t\t\tthis.routes.push(route);\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds one or more surfaces to the application.\n\t * @param {Surface|String|Array.} surfaces\n\t * Surface element id or surface instance. You can also pass an Array\n\t * whichcontains surface instances or id. In case of ID, these should be\n\t * the id of surface element.\n\t * @chainable\n\t */\n\taddSurfaces(surfaces) {\n\t\tif (!Array.isArray(surfaces)) {\n\t\t\tsurfaces = [surfaces];\n\t\t}\n\t\tsurfaces.forEach((surface) => {\n\t\t\tif (isString(surface)) {\n\t\t\t\tsurface = new Surface(surface);\n\t\t\t}\n\t\t\tthis.surfaces[surface.getId()] = surface;\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns if can navigate to path.\n\t * @param {!string} url\n\t * @return {boolean}\n\t */\n\tcanNavigate(url) {\n\t\tconst uri = utils.isWebUri(url);\n\n\t\tif (!uri) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst path = utils.getUrlPath(url);\n\n\t\tif (!this.isLinkSameOrigin_(uri.getHost())) {\n\t\t\tconsole.log('Offsite link clicked');\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.isSameBasePath_(path)) {\n\t\t\tconsole.log('Link clicked outside app\\'s base path');\n\t\t\treturn false;\n\t\t}\n\t\t// Prevents navigation if it's a hash change on the same url.\n\t\tif (uri.getHash() && utils.isCurrentBrowserPath(path)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.findRoute(path)) {\n\t\t\tconsole.log('No route for ' + path);\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Clear screens cache.\n\t * @chainable\n\t */\n\tclearScreensCache() {\n\t\tObject.keys(this.screens).forEach((path) => {\n\t\t\tif (path === this.activePath) {\n\t\t\t\tthis.activeScreen.clearCache();\n\t\t\t} else if (!(this.isNavigationPending && this.pendingNavigate.path === path)) {\n\t\t\t\tthis.removeScreen(path);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves or create a screen instance to a path.\n\t * @param {!string} path Path containing the querystring part.\n\t * @return {Screen}\n\t */\n\tcreateScreenInstance(path, route) {\n\t\tif (!this.pendingNavigate && path === this.activePath) {\n\t\t\tconsole.log('Already at destination, refresh navigation');\n\t\t\treturn this.activeScreen;\n\t\t}\n\t\t/* jshint newcap: false */\n\t\tvar screen = this.screens[path];\n\t\tif (!screen) {\n\t\t\tvar handler = route.getHandler();\n\t\t\tif (handler === Screen || Screen.isImplementedBy(handler.prototype)) {\n\t\t\t\tscreen = new handler();\n\t\t\t} else {\n\t\t\t\tscreen = handler(route) || new Screen();\n\t\t\t}\n\t\t\tconsole.log('Create screen for [' + path + '] [' + screen + ']');\n\t\t}\n\t\treturn screen;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisposeInternal() {\n\t\tif (this.activeScreen) {\n\t\t\tthis.removeScreen(this.activePath);\n\t\t}\n\t\tthis.clearScreensCache();\n\t\tthis.formEventHandler_.removeListener();\n\t\tthis.linkEventHandler_.removeListener();\n\t\tthis.appEventHandlers_.removeAllListeners();\n\t\tsuper.disposeInternal();\n\t}\n\n\t/**\n\t * Dispatches to the first route handler that matches the current path, if\n\t * any.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tdispatch() {\n\t\treturn this.navigate(utils.getCurrentBrowserPath(), true);\n\t}\n\n\t/**\n\t * Starts navigation to a path.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tdoNavigate_(path, opt_replaceHistory) {\n\t\tvar route = this.findRoute(path);\n\t\tif (!route) {\n\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('No route for ' + path));\n\t\t\treturn this.pendingNavigate;\n\t\t}\n\n\t\tconsole.log('Navigate to [' + path + ']');\n\n\t\tthis.stopPendingNavigate_();\n\t\tthis.isNavigationPending = true;\n\n\t\tvar nextScreen = this.createScreenInstance(path, route);\n\n\t\treturn this.maybePreventDeactivate_()\n\t\t\t.then(() => this.maybePreventActivate_(nextScreen))\n\t\t\t.then(() => nextScreen.load(path))\n\t\t\t.then(() => {\n\t\t\t\t// At this point we cannot stop navigation and all received\n\t\t\t\t// navigate candidates will be queued at scheduledNavigationQueue.\n\t\t\t\tthis.navigationStrategy = NavigationStrategy.SCHEDULE_LAST;\n\n\t\t\t\tif (this.activeScreen) {\n\t\t\t\t\tthis.activeScreen.deactivate();\n\t\t\t\t}\n\t\t\t\tthis.prepareNavigateHistory_(path, nextScreen, opt_replaceHistory);\n\t\t\t\tthis.prepareNavigateSurfaces_(\n\t\t\t\t\tnextScreen,\n\t\t\t\t\tthis.surfaces,\n\t\t\t\t\tthis.extractParams(route, path)\n\t\t\t\t);\n\t\t\t})\n\t\t\t.then(() => nextScreen.evaluateStyles(this.surfaces))\n\t\t\t.then(() => nextScreen.flip(this.surfaces))\n\t\t\t.then(() => nextScreen.evaluateScripts(this.surfaces))\n\t\t\t.then(() => this.maybeUpdateScrollPositionState_())\n\t\t\t.then(() => this.syncScrollPositionSyncThenAsync_())\n\t\t\t.then(() => this.finalizeNavigate_(path, nextScreen))\n\t\t\t.then(() => this.maybeOverloadBeforeUnload_())\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.isNavigationPending = false;\n\t\t\t\tthis.handleNavigateError_(path, nextScreen, reason);\n\t\t\t\tthrow reason;\n\t\t\t})\n\t\t\t.thenAlways(() => {\n\t\t\t\tthis.navigationStrategy = NavigationStrategy.IMMEDIATE;\n\n\t\t\t\tif (this.scheduledNavigationQueue.length) {\n\t\t\t\t\tconst scheduledNavigation = this.scheduledNavigationQueue.shift();\n\t\t\t\t\tthis.maybeNavigate_(scheduledNavigation.href, scheduledNavigation);\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Extracts params according to the given path and route.\n\t * @param {!Route} route\n\t * @param {string} path\n\t * @param {!Object}\n\t */\n\textractParams(route, path) {\n\t\treturn route.extractParams(this.getRoutePath(path));\n\t}\n\n\t/**\n\t * Finalizes a screen navigation.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @protected\n\t */\n\tfinalizeNavigate_(path, nextScreen) {\n\t\tnextScreen.activate();\n\n\t\tif (this.activeScreen && !this.activeScreen.isCacheable()) {\n\t\t\tif (this.activeScreen !== nextScreen) {\n\t\t\t\tthis.removeScreen(this.activePath);\n\t\t\t}\n\t\t}\n\n\t\tthis.activePath = path;\n\t\tthis.activeScreen = nextScreen;\n\t\tthis.browserPathBeforeNavigate = utils.getCurrentBrowserPathWithoutHash();\n\t\tthis.screens[path] = nextScreen;\n\t\tthis.isNavigationPending = false;\n\t\tthis.pendingNavigate = null;\n\t\tglobals.capturedFormElement = null;\n\t\tglobals.capturedFormButtonElement = null;\n\t\tconsole.log('Navigation done');\n\t}\n\n\t/**\n\t * Finds a route for the test path. Returns true if matches has a route,\n\t * otherwise returns null.\n\t * @param {!string} path Path containing the querystring part.\n\t * @return {?Object} Route handler if match any or null if the\n\t * path is the same as the current url and the path contains a fragment.\n\t */\n\tfindRoute(path) {\n\t\tpath = this.getRoutePath(path);\n\t\tfor (var i = 0; i < this.routes.length; i++) {\n\t\t\tvar route = this.routes[i];\n\t\t\tif (route.matchesPath(path)) {\n\t\t\t\treturn route;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Gets allow prevent navigate.\n\t * @return {boolean}\n\t */\n\tgetAllowPreventNavigate() {\n\t\treturn this.allowPreventNavigate;\n\t}\n\n\t/**\n\t * Gets link base path.\n\t * @return {!string}\n\t */\n\tgetBasePath() {\n\t\treturn this.basePath;\n\t}\n\n\t/**\n\t * Gets the default page title.\n\t * @return {string} defaultTitle\n\t */\n\tgetDefaultTitle() {\n\t\treturn this.defaultTitle;\n\t}\n\n\t/**\n\t * Gets the form selector.\n\t * @return {!string}\n\t */\n\tgetFormSelector() {\n\t\treturn this.formSelector;\n\t}\n\n\t/**\n\t * Check if route matching is ignoring query string from the route path.\n\t * @return {boolean}\n\t */\n\tgetIgnoreQueryStringFromRoutePath() {\n\t\treturn this.ignoreQueryStringFromRoutePath;\n\t}\n\n\t/**\n\t * Gets the link selector.\n\t * @return {!string}\n\t */\n\tgetLinkSelector() {\n\t\treturn this.linkSelector;\n\t}\n\n\t/**\n\t * Gets the loading css class.\n\t * @return {!string}\n\t */\n\tgetLoadingCssClass() {\n\t\treturn this.loadingCssClass;\n\t}\n\n\t/**\n\t * Returns the given path formatted to be matched by a route. This will,\n\t * for example, remove the base path from it, but make sure it will end\n\t * with a '/'.\n\t * @param {string} path\n\t * @return {string}\n\t */\n\tgetRoutePath(path) {\n\t\tif (this.getIgnoreQueryStringFromRoutePath()) {\n\t\t\tpath = utils.getUrlPathWithoutHashAndSearch(path);\n\t\t\treturn utils.getUrlPathWithoutHashAndSearch(path.substr(this.basePath.length));\n\t\t}\n\n\t\tpath = utils.getUrlPathWithoutHash(path);\n\t\treturn utils.getUrlPathWithoutHash(path.substr(this.basePath.length));\n\t}\n\n\t/**\n\t * Gets the update scroll position value.\n\t * @return {boolean}\n\t */\n\tgetUpdateScrollPosition() {\n\t\treturn this.updateScrollPosition;\n\t}\n\n\t/**\n\t * Handle navigation error.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @param {!Error} error\n\t * @protected\n\t */\n\thandleNavigateError_(path, nextScreen, error) {\n\t\tconsole.log('Navigation error for [' + nextScreen + '] (' + error.stack + ')');\n\t\tthis.emit('navigationError', {\n\t\t\terror,\n\t\t\tnextScreen,\n\t\t\tpath\n\t\t});\n\t\tif (!utils.isCurrentBrowserPath(path)) {\n\t\t\tif (this.isNavigationPending && this.pendingNavigate) {\n\t\t\t\tthis.pendingNavigate.thenAlways(() => this.removeScreen(path), this);\n\t\t\t} else {\n\t\t\t\tthis.removeScreen(path);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if app has routes.\n\t * @return {boolean}\n\t */\n\thasRoutes() {\n\t\treturn this.routes.length > 0;\n\t}\n\n\t/**\n\t * Tests if host is an offsite link.\n\t * @param {!string} host Link host to compare with\n\t * globals.window.location.host.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisLinkSameOrigin_(host) {\n\t\tconst hostUri = new Uri(host);\n\t\tconst locationHostUri = new Uri(globals.window.location.host);\n\n\t\treturn hostUri.getPort() === locationHostUri.getPort() && hostUri.getHostname() === locationHostUri.getHostname();\n\t}\n\n\t/**\n\t * Tests if link element has the same app's base path.\n\t * @param {!string} path Link path containing the querystring part.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisSameBasePath_(path) {\n\t\treturn path.indexOf(this.basePath) === 0;\n\t}\n\n\t/**\n\t * Lock the document scroll in order to avoid the browser native back and\n\t * forward navigation to change the scroll position. In the end of\n\t * navigation lifecycle scroll is repositioned.\n\t * @protected\n\t */\n\tlockHistoryScrollPosition_() {\n\t\tvar state = globals.window.history.state;\n\t\tif (!state) {\n\t\t\treturn;\n\t\t}\n\t\t// Browsers are inconsistent when re-positioning the scroll history on\n\t\t// popstate. At some browsers, history scroll happens before popstate, then\n\t\t// lock the scroll on the last known position as soon as possible after the\n\t\t// current JS execution context and capture the current value. Some others,\n\t\t// history scroll happens after popstate, in this case, we bind an once\n\t\t// scroll event to lock the las known position. Lastly, the previous two\n\t\t// behaviors can happen even on the same browser, hence the race will decide\n\t\t// the winner.\n\t\tvar winner = false;\n\t\tvar switchScrollPositionRace = function() {\n\t\t\tglobals.document.removeEventListener('scroll', switchScrollPositionRace, false);\n\t\t\tif (!winner) {\n\t\t\t\tglobals.window.scrollTo(state.scrollLeft, state.scrollTop);\n\t\t\t\twinner = true;\n\t\t\t}\n\t\t};\n\t\tasync.nextTick(switchScrollPositionRace);\n\t\tglobals.document.addEventListener('scroll', switchScrollPositionRace, false);\n\t}\n\n\t/**\n\t * If supported by the browser, disables native scroll restoration and\n\t * stores current value.\n\t */\n\tmaybeDisableNativeScrollRestoration() {\n\t\tif (this.nativeScrollRestorationSupported) {\n\t\t\tthis.nativeScrollRestoration_ = globals.window.history.scrollRestoration;\n\t\t\tglobals.window.history.scrollRestoration = 'manual';\n\t\t}\n\t}\n\n\t/**\n\t * This method is used to evaluate if is possible to queue received\n\t * dom event to scheduleNavigationQueue and enqueue it.\n\t * @param {string} href Information about the link's href.\n\t * @param {Event} event Dom event that initiated the navigation.\n\t */\n\tmaybeScheduleNavigation_(href, event) {\n\t\tif (this.isNavigationPending && this.navigationStrategy === NavigationStrategy.SCHEDULE_LAST) {\n\t\t\tthis.scheduledNavigationQueue = [object.mixin({\n\t\t\t\thref,\n\t\t\t\tisScheduledNavigation: true\n\t\t\t}, event)];\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Maybe navigate to a path.\n\t * @param {string} href Information about the link's href.\n\t * @param {Event} event Dom event that initiated the navigation.\n\t */\n\tmaybeNavigate_(href, event) {\n\t\tif (!this.canNavigate(href)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isNavigationScheduled = this.maybeScheduleNavigation_(href, event);\n\n\t\tif (isNavigationScheduled) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tvar navigateFailed = false;\n\t\ttry {\n\t\t\tthis.navigate(utils.getUrlPath(href), false, event);\n\t\t} catch (err) {\n\t\t\t// Do not prevent link navigation in case some synchronous error occurs\n\t\t\tnavigateFailed = true;\n\t\t}\n\n\t\tif (!navigateFailed && !event.isScheduledNavigation) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether the onbeforeunload global event handler is overloaded\n\t * by client code. If so, it replaces with a function that halts the normal\n\t * event flow in relation with the client onbeforeunload function.\n\t * This can be in most part used to prematurely terminate navigation to other pages\n\t * according to the given constrait(s).\n\t * @protected\n\t */\n\tmaybeOverloadBeforeUnload_() {\n\t\tif ('function' === typeof window.onbeforeunload) {\n\t\t\twindow._onbeforeunload = window.onbeforeunload;\n\n\t\t\twindow.onbeforeunload = event => {\n\t\t\t\tthis.emit('beforeUnload', event);\n\t\t\t\tif (event && event.defaultPrevented) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// mark the updated handler due unwanted recursion\n\t\t\twindow.onbeforeunload._overloaded = true;\n\t\t}\n\t}\n\n\t/**\n\t * Cancels navigation if nextScreen's beforeActivate lifecycle method\n\t * resolves to true.\n\t * @param {!Screen} nextScreen\n\t * @return {!CancellablePromise}\n\t */\n\tmaybePreventActivate_(nextScreen) {\n\t\treturn CancellablePromise.resolve()\n\t\t\t.then(() => {\n\t\t\t\treturn nextScreen.beforeActivate();\n\t\t\t})\n\t\t\t.then(prevent => {\n\t\t\t\tif (prevent) {\n\t\t\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by next screen'));\n\t\t\t\t\treturn this.pendingNavigate;\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Cancels navigation if activeScreen's beforeDeactivate lifecycle\n\t * method resolves to true.\n\t * @return {!CancellablePromise}\n\t */\n\tmaybePreventDeactivate_() {\n\t\treturn CancellablePromise.resolve()\n\t\t\t.then(() => {\n\t\t\t\tif (this.activeScreen) {\n\t\t\t\t\treturn this.activeScreen.beforeDeactivate();\n\t\t\t\t}\n\t\t\t})\n\t\t\t.then(prevent => {\n\t\t\t\tif (prevent) {\n\t\t\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by active screen'));\n\t\t\t\t\treturn this.pendingNavigate;\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Maybe reposition scroll to hashed anchor.\n\t */\n\tmaybeRepositionScrollToHashedAnchor() {\n\t\tconst hash = globals.window.location.hash;\n\t\tif (hash) {\n\t\t\tlet anchorElement = globals.document.getElementById(hash.substring(1));\n\t\t\tif (anchorElement) {\n\t\t\t\tconst {offsetLeft, offsetTop} = utils.getNodeOffset(anchorElement);\n\t\t\t\tglobals.window.scrollTo(offsetLeft, offsetTop);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * If supported by the browser, restores native scroll restoration to the\n\t * value captured by `maybeDisableNativeScrollRestoration`.\n\t */\n\tmaybeRestoreNativeScrollRestoration() {\n\t\tif (this.nativeScrollRestorationSupported && this.nativeScrollRestoration_) {\n\t\t\tglobals.window.history.scrollRestoration = this.nativeScrollRestoration_;\n\t\t}\n\t}\n\n\t/**\n\t * Maybe restore redirected path hash in case both the current path and\n\t * the given path are the same.\n\t * @param {!string} path Path before navigation.\n\t * @param {!string} redirectPath Path after navigation.\n\t * @param {!string} hash Hash to be added to the path.\n\t * @return {!string} Returns the path with the hash restored.\n\t */\n\tmaybeRestoreRedirectPathHash_(path, redirectPath, hash) {\n\t\tif (redirectPath === utils.getUrlPathWithoutHash(path)) {\n\t\t\treturn redirectPath + hash;\n\t\t}\n\t\treturn redirectPath;\n\t}\n\n\t/**\n\t * Maybe update scroll position in history state to anchor on path.\n\t * @param {!string} path Path containing anchor\n\t */\n\tmaybeUpdateScrollPositionState_() {\n\t\tvar hash = globals.window.location.hash;\n\t\tvar anchorElement = globals.document.getElementById(hash.substring(1));\n\t\tif (anchorElement) {\n\t\t\tconst {offsetLeft, offsetTop} = utils.getNodeOffset(anchorElement);\n\t\t\tthis.saveHistoryCurrentPageScrollPosition_(offsetTop, offsetLeft);\n\t\t}\n\t}\n\n\t/**\n\t * Navigates to the specified path if there is a route handler that matches.\n\t * @param {!string} path Path to navigate containing the base path.\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @param {Event=} event Optional event object that triggered the navigation.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tnavigate(path, opt_replaceHistory, opt_event) {\n\t\tif (!utils.isHtml5HistorySupported()) {\n\t\t\tthrow new Error('HTML5 History is not supported. Senna will not intercept navigation.');\n\t\t}\n\n\t\tif (opt_event) {\n\t\t\tglobals.capturedFormElement = opt_event.capturedFormElement;\n\t\t\tglobals.capturedFormButtonElement = opt_event.capturedFormButtonElement;\n\t\t}\n\n\t\t// When reloading the same path do replaceState instead of pushState to\n\t\t// avoid polluting history with states with the same path.\n\t\tif (path === this.activePath) {\n\t\t\topt_replaceHistory = true;\n\t\t}\n\n\t\tthis.emit('beforeNavigate', {\n\t\t\tevent: opt_event,\n\t\t\tpath: path,\n\t\t\treplaceHistory: !!opt_replaceHistory\n\t\t});\n\n\t\treturn this.pendingNavigate;\n\t}\n\n\t/**\n\t * Befores navigation to a path.\n\t * @param {!Event} event Event facade containing path and\n\t * replaceHistory.\n\t * @protected\n\t */\n\tonBeforeNavigate_(event) {\n\t\tif (globals.capturedFormElement) {\n\t\t\tevent.form = globals.capturedFormElement;\n\t\t}\n\t}\n\n\t/**\n\t * Befores navigation to a path. Runs after external listeners.\n\t * @param {!Event} event Event facade containing path and\n\t * replaceHistory.\n\t * @protected\n\t */\n\tonBeforeNavigateDefault_(event) {\n\t\tif (this.pendingNavigate) {\n\t\t\tif (this.pendingNavigate.path === event.path || this.navigationStrategy === NavigationStrategy.SCHEDULE_LAST) {\n\t\t\t\tconsole.log('Waiting...');\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.emit('beforeUnload', event);\n\n\t\tthis.emit('startNavigate', {\n\t\t\tform: event.form,\n\t\t\tpath: event.path,\n\t\t\treplaceHistory: event.replaceHistory\n\t\t});\n\t}\n\n\t/**\n\t * Custom event handler that executes the original listener that has been\n\t * added by the client code and terminates the navigation accordingly.\n\t * @param {!Event} event original Event facade.\n\t * @protected\n\t */\n\tonBeforeUnloadDefault_(event) {\n\t\tvar func = window._onbeforeunload;\n\t\tif (func && !func._overloaded && func()) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\t/**\n\t * Intercepts document clicks and test link elements in order to decide\n\t * whether Surface app can navigate.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonDocClickDelegate_(event) {\n\t\tif (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.button) {\n\t\t\tconsole.log('Navigate aborted, invalid mouse button or modifier key pressed.');\n\t\t\treturn;\n\t\t}\n\t\tthis.maybeNavigate_(event.delegateTarget.href, event);\n\t}\n\n\t/**\n\t * Intercepts document form submits and test action path in order to decide\n\t * whether Surface app can navigate.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonDocSubmitDelegate_(event) {\n\t\tvar form = event.delegateTarget;\n\t\tif (form.method === 'get') {\n\t\t\tconsole.log('GET method not supported');\n\t\t\treturn;\n\t\t}\n\t\tevent.capturedFormElement = form;\n\t\tconst buttonSelector = 'button:not([type]),button[type=submit],input[type=submit]';\n\t\tif (match(globals.document.activeElement, buttonSelector)) {\n\t\t\tevent.capturedFormButtonElement = globals.document.activeElement;\n\t\t} else {\n\t\t\tevent.capturedFormButtonElement = form.querySelector(buttonSelector);\n\t\t}\n\t\tthis.maybeNavigate_(form.action, event);\n\t}\n\n\t/**\n\t * Listens to the window's load event in order to avoid issues with some browsers\n\t * that trigger popstate calls on the first load. For more information see\n\t * http://stackoverflow.com/questions/6421769/popstate-on-pages-load-in-chrome.\n\t * @protected\n\t */\n\tonLoad_() {\n\t\tthis.skipLoadPopstate = true;\n\t\tsetTimeout(() => {\n\t\t\t// The timeout ensures that popstate events will be unblocked right\n\t\t\t// after the load event occured, but not in the same event-loop cycle.\n\t\t\tthis.skipLoadPopstate = false;\n\t\t}, 0);\n\t\t// Try to reposition scroll to the hashed anchor when page loads.\n\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t}\n\n\t/**\n\t * Handles browser history changes and fires app's navigation if the state\n\t * belows to us. If we detect a popstate and the state is null,\n\t * assume it is navigating to an external page or to a page we don't have\n\t * route, then globals.window.location.reload() is invoked in order to\n\t * reload the content to the current url.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonPopstate_(event) {\n\t\tif (this.skipLoadPopstate) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Do not navigate if the popstate was triggered by a hash change.\n\t\tif (utils.isCurrentBrowserPath(this.browserPathBeforeNavigate)) {\n\t\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t\t\treturn;\n\t\t}\n\n\t\tvar state = event.state;\n\n\t\tif (!state) {\n\t\t\tif (globals.window.location.hash) {\n\t\t\t\t// If senna is on an redirect path and a hash popstate happens\n\t\t\t\t// to a different url, reload the browser. This behavior doesn't\n\t\t\t\t// require senna to route hashed links and is closer to native\n\t\t\t\t// browser behavior.\n\t\t\t\tif (this.redirectPath && !utils.isCurrentBrowserPath(this.redirectPath)) {\n\t\t\t\t\tthis.reloadPage();\n\t\t\t\t}\n\t\t\t\t// Always try to reposition scroll to the hashed anchor when\n\t\t\t\t// hash popstate happens.\n\t\t\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t\t\t} else {\n\t\t\t\tthis.reloadPage();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (state.senna) {\n\t\t\tconsole.log('History navigation to [' + state.path + ']');\n\t\t\tthis.popstateScrollTop = state.scrollTop;\n\t\t\tthis.popstateScrollLeft = state.scrollLeft;\n\t\t\tif (!this.nativeScrollRestorationSupported) {\n\t\t\t\tthis.lockHistoryScrollPosition_();\n\t\t\t}\n\t\t\tthis.once('endNavigate', () => {\n\t\t\t\tif (state.referrer) {\n\t\t\t\t\tutils.setReferrer(state.referrer);\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst uri = new Uri(state.path);\n\t\t\turi.setHostname(globals.window.location.hostname);\n\t\t\turi.setPort(globals.window.location.port);\n\t\t\tconst isNavigationScheduled = this.maybeScheduleNavigation_(uri.toString(), {});\n\t\t\tif (isNavigationScheduled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.navigate(state.path, true);\n\t\t}\n\t}\n\n\t/**\n\t * Listens document scroll changes in order to capture the possible lock\n\t * scroll position for history scrolling.\n\t * @protected\n\t */\n\tonScroll_() {\n\t\tif (this.captureScrollPositionFromScrollEvent) {\n\t\t\tthis.saveHistoryCurrentPageScrollPosition_(globals.window.pageYOffset, globals.window.pageXOffset);\n\t\t}\n\t}\n\n\t/**\n\t * Starts navigation to a path.\n\t * @param {!Event} event Event facade containing path and\n\t * replaceHistory.\n\t * @protected\n\t */\n\tonStartNavigate_(event) {\n\t\tthis.maybeDisableNativeScrollRestoration();\n\t\tthis.captureScrollPositionFromScrollEvent = false;\n\t\taddClasses(globals.document.documentElement, this.loadingCssClass);\n\n\t\tvar endNavigatePayload = {\n\t\t\tform: event.form,\n\t\t\tpath: event.path\n\t\t};\n\n\t\tthis.pendingNavigate = this.doNavigate_(event.path, event.replaceHistory)\n\t\t\t.catch((reason) => {\n\t\t\t\tendNavigatePayload.error = reason;\n\t\t\t\tthrow reason;\n\t\t\t})\n\t\t\t.thenAlways(() => {\n\t\t\t\tif (!this.pendingNavigate && !this.scheduledNavigationQueue.length) {\n\t\t\t\t\tremoveClasses(globals.document.documentElement, this.loadingCssClass);\n\t\t\t\t\tthis.maybeRestoreNativeScrollRestoration();\n\t\t\t\t\tthis.captureScrollPositionFromScrollEvent = true;\n\t\t\t\t}\n\t\t\t\tthis.emit('endNavigate', endNavigatePayload);\n\t\t\t});\n\n\t\tthis.pendingNavigate.path = event.path;\n\t}\n\n\t/**\n\t * Prefetches the specified path if there is a route handler that matches.\n\t * @param {!string} path Path to navigate containing the base path.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tprefetch(path) {\n\t\tvar route = this.findRoute(path);\n\t\tif (!route) {\n\t\t\treturn CancellablePromise.reject(new CancellablePromise.CancellationError('No route for ' + path));\n\t\t}\n\n\t\tconsole.log('Prefetching [' + path + ']');\n\n\t\tvar nextScreen = this.createScreenInstance(path, route);\n\n\t\treturn nextScreen.load(path)\n\t\t\t.then(() => this.screens[path] = nextScreen)\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.handleNavigateError_(path, nextScreen, reason);\n\t\t\t\tthrow reason;\n\t\t\t});\n\t}\n\n\t/**\n\t * Prepares screen flip. Updates history state and surfaces content.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t */\n\tprepareNavigateHistory_(path, nextScreen, opt_replaceHistory) {\n\t\tlet title = nextScreen.getTitle();\n\t\tif (!isString(title)) {\n\t\t\ttitle = this.getDefaultTitle();\n\t\t}\n\t\tlet redirectPath = nextScreen.beforeUpdateHistoryPath(path);\n\t\tconst hash = new Uri(path).getHash();\n\t\tredirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash);\n\t\tconst historyState = {\n\t\t\tform: isDefAndNotNull(globals.capturedFormElement),\n\t\t\tpath,\n\t\t\tredirectPath,\n\t\t\tscrollLeft: 0,\n\t\t\tscrollTop: 0,\n\t\t\tsenna: true\n\t\t};\n\t\tif (opt_replaceHistory) {\n\t\t\thistoryState.scrollTop = this.popstateScrollTop;\n\t\t\thistoryState.scrollLeft = this.popstateScrollLeft;\n\t\t}\n\t\tthis.updateHistory_(title, redirectPath, nextScreen.beforeUpdateHistoryState(historyState), opt_replaceHistory);\n\t\tthis.redirectPath = redirectPath;\n\t}\n\n\t/**\n\t * Prepares screen flip. Updates history state and surfaces content.\n\t * @param {!Screen} nextScreen\n\t * @param {!Object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @param {!Object} params Params extracted from the current path.\n\t */\n\tprepareNavigateSurfaces_(nextScreen, surfaces, params) {\n\t\tObject.keys(surfaces).forEach((id) => {\n\t\t\tvar surfaceContent = nextScreen.getSurfaceContent(id, params);\n\t\t\tsurfaces[id].addContent(nextScreen.getId(), surfaceContent);\n\t\t\tconsole.log('Screen [' + nextScreen.getId() + '] add content to surface ' +\n\t\t\t\t'[' + surfaces[id] + '] [' + (isDefAndNotNull(surfaceContent) ? '...' : 'empty') + ']');\n\t\t});\n\t}\n\n\t/**\n\t * Reloads the page by performing `window.location.reload()`.\n\t */\n\treloadPage() {\n\t\tglobals.window.location.reload();\n\t}\n\n\t/**\n\t * Removes route instance from app routes.\n\t * @param {Route} route\n\t * @return {boolean} True if an element was removed.\n\t */\n\tremoveRoute(route) {\n\t\treturn array.remove(this.routes, route);\n\t}\n\n\t/**\n\t * Removes a screen.\n\t * @param {!string} path Path containing the querystring part.\n\t */\n\tremoveScreen(path) {\n\t\tvar screen = this.screens[path];\n\t\tif (screen) {\n\t\t\tObject.keys(this.surfaces).forEach((surfaceId) => this.surfaces[surfaceId].remove(screen.getId()));\n\t\t\tscreen.dispose();\n\t\t\tdelete this.screens[path];\n\t\t}\n\t}\n\n\t/**\n\t * Saves given scroll position into history state.\n\t * @param {!number} scrollTop Number containing the top scroll position to be saved.\n\t * @param {!number} scrollLeft Number containing the left scroll position to be saved.\n\t */\n\tsaveHistoryCurrentPageScrollPosition_(scrollTop, scrollLeft) {\n\t\tvar state = globals.window.history.state;\n\t\tif (state && state.senna) {\n\t\t\t[state.scrollTop, state.scrollLeft] = [scrollTop, scrollLeft];\n\t\t\tglobals.window.history.replaceState(state, null, null);\n\t\t}\n\t}\n\n\t/**\n\t * Sets allow prevent navigate.\n\t * @param {boolean} allowPreventNavigate\n\t */\n\tsetAllowPreventNavigate(allowPreventNavigate) {\n\t\tthis.allowPreventNavigate = allowPreventNavigate;\n\t}\n\n\t/**\n\t * Sets link base path.\n\t * @param {!string} path\n\t */\n\tsetBasePath(basePath) {\n\t\tthis.basePath = utils.removePathTrailingSlash(basePath);\n\t}\n\n\t/**\n\t * Sets the default page title.\n\t * @param {string} defaultTitle\n\t */\n\tsetDefaultTitle(defaultTitle) {\n\t\tthis.defaultTitle = defaultTitle;\n\t}\n\n\t/**\n\t * Sets the form selector.\n\t * @param {!string} formSelector\n\t */\n\tsetFormSelector(formSelector) {\n\t\tthis.formSelector = formSelector;\n\t\tif (this.formEventHandler_) {\n\t\t\tthis.formEventHandler_.removeListener();\n\t\t}\n\t\tthis.formEventHandler_ = delegate(document, 'submit', this.formSelector, this.onDocSubmitDelegate_.bind(this), this.allowPreventNavigate);\n\t}\n\n\t/**\n\t * Sets if route matching should ignore query string from the route path.\n\t * @param {boolean} ignoreQueryStringFromRoutePath\n\t */\n\tsetIgnoreQueryStringFromRoutePath(ignoreQueryStringFromRoutePath) {\n\t\tthis.ignoreQueryStringFromRoutePath = ignoreQueryStringFromRoutePath;\n\t}\n\n\t/**\n\t * Sets the link selector.\n\t * @param {!string} linkSelector\n\t */\n\tsetLinkSelector(linkSelector) {\n\t\tthis.linkSelector = linkSelector;\n\t\tif (this.linkEventHandler_) {\n\t\t\tthis.linkEventHandler_.removeListener();\n\t\t}\n\t\tthis.linkEventHandler_ = delegate(document, 'click', this.linkSelector, this.onDocClickDelegate_.bind(this), this.allowPreventNavigate);\n\t}\n\n\t/**\n\t * Sets the loading css class.\n\t * @param {!string} loadingCssClass\n\t */\n\tsetLoadingCssClass(loadingCssClass) {\n\t\tthis.loadingCssClass = loadingCssClass;\n\t}\n\n\t/**\n\t * Sets the update scroll position value.\n\t * @param {boolean} updateScrollPosition\n\t */\n\tsetUpdateScrollPosition(updateScrollPosition) {\n\t\tthis.updateScrollPosition = updateScrollPosition;\n\t}\n\n\t/**\n\t * Cancels pending navigate with Cancel pending navigation error.\n\t * @protected\n\t */\n\tstopPendingNavigate_() {\n\t\tif (this.pendingNavigate) {\n\t\t\tthis.pendingNavigate.cancel('Cancel pending navigation');\n\t\t}\n\t\tthis.pendingNavigate = null;\n\t}\n\n\t/**\n\t * Sync document scroll position twice, the first one synchronous and then\n\t * one inside async.nextTick. Relevant to browsers that fires\n\t * scroll restoration asynchronously after popstate.\n\t * @protected\n\t * @return {?CancellablePromise=}\n\t */\n\tsyncScrollPositionSyncThenAsync_() {\n\t\tvar state = globals.window.history.state;\n\t\tif (!state) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar scrollTop = state.scrollTop;\n\t\tvar scrollLeft = state.scrollLeft;\n\n\t\tvar sync = () => {\n\t\t\tif (this.updateScrollPosition) {\n\t\t\t\tglobals.window.scrollTo(scrollLeft, scrollTop);\n\t\t\t}\n\t\t};\n\n\t\treturn new CancellablePromise((resolve) => sync() & async.nextTick(() => sync() & resolve()));\n\t}\n\n\t/**\n\t * Updates or replace browser history.\n\t * @param {?string} title Document title.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!object} state\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @protected\n\t */\n\tupdateHistory_(title, path, state, opt_replaceHistory) {\n\t\tconst referrer = globals.window.location.href;\n\n\t\tif (state) {\n\t\t\tstate.referrer = referrer;\n\t\t}\n\n\t\tif (opt_replaceHistory) {\n\t\t\tglobals.window.history.replaceState(state, title, path);\n\t\t} else {\n\t\t\tglobals.window.history.pushState(state, title, path);\n\t\t}\n\n\t\tutils.setReferrer(referrer);\n\n\t\tlet titleNode = globals.document.querySelector('title');\n\t\tif (titleNode) {\n\t\t\ttitleNode.innerHTML = title;\n\t\t} else {\n\t\t\tglobals.document.title = title;\n\t\t}\n\t}\n\n}\n\nexport default App;\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/amd/senna/src/app/version-min.js b/build/amd/senna/src/app/version-min.js index f0dc147..8f27a47 100644 --- a/build/amd/senna/src/app/version-min.js +++ b/build/amd/senna/src/app/version-min.js @@ -1 +1 @@ -define(["exports"],function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t="2.7.8";e["default"]=t}); \ No newline at end of file +define(["exports"],function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t="2.7.9";e["default"]=t}); \ No newline at end of file diff --git a/build/amd/senna/src/app/version.js b/build/amd/senna/src/app/version.js index 4526c2e..fd55a65 100644 --- a/build/amd/senna/src/app/version.js +++ b/build/amd/senna/src/app/version.js @@ -8,7 +8,7 @@ define(['exports'], function (exports) { * @returns String containing the current senna version */ - var version = '2.7.8'; + var version = '2.7.9'; exports.default = version; }); diff --git a/build/globals/senna-debug.js b/build/globals/senna-debug.js index 3204e8d..cc75d8e 100644 --- a/build/globals/senna-debug.js +++ b/build/globals/senna-debug.js @@ -1,7 +1,7 @@ /** * Senna.js - A blazing-fast Single Page Application engine * @author Liferay, Inc. - * @version v2.7.8 + * @version v2.7.9 * @link http://sennajs.com * @license BSD-3-Clause */ @@ -9804,6 +9804,8 @@ var App$1 = function (_EventEmitter) { title = this.getDefaultTitle(); } var redirectPath = nextScreen.beforeUpdateHistoryPath(path); + var hash = new Uri(path).getHash(); + redirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash); var historyState = { form: isDefAndNotNull$1(globals.capturedFormElement), path: path, @@ -9816,8 +9818,6 @@ var App$1 = function (_EventEmitter) { historyState.scrollTop = this.popstateScrollTop; historyState.scrollLeft = this.popstateScrollLeft; } - var hash = new Uri(path).getHash(); - redirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash); this.updateHistory_(title, redirectPath, nextScreen.beforeUpdateHistoryState(historyState), opt_replaceHistory); this.redirectPath = redirectPath; } @@ -11699,7 +11699,7 @@ globals.document.addEventListener('DOMContentLoaded', function () { * @returns String containing the current senna version */ -var version = '2.7.8'; +var version = '2.7.9'; exports['default'] = App$1; exports.dataAttributeHandler = dataAttributeHandler; diff --git a/build/globals/senna-min.js b/build/globals/senna-min.js index a28886e..a6e5f28 100644 --- a/build/globals/senna-min.js +++ b/build/globals/senna-min.js @@ -1,10 +1,10 @@ /** * Senna.js - A blazing-fast Single Page Application engine * @author Liferay, Inc. - * @version v2.7.8 + * @version v2.7.9 * @link http://sennajs.com * @license BSD-3-Clause */ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.senna={})}(this,function(e){"use strict";function t(e){return void 0!==e}function n(e){return t(e)&&!a(e)}function r(e){return e&&"object"===("undefined"==typeof e?"undefined":Te(e))&&9===e.nodeType}function i(e){return"function"==typeof e}function a(e){return null===e}function o(e){var t="undefined"==typeof e?"undefined":Te(e);return"object"===t&&null!==e||"function"===t}function s(e){return"string"==typeof e||e instanceof String}function u(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{checkEnv:!0},t="undefined"!=typeof process&&!process.browser;return t&&e.checkEnv&&(t="undefined"!=typeof process.env&&"test"!==process.env.NODE_ENV),t}function l(e){return e=e||[],Array.isArray(e)?e:[e]}function c(e,t){if(o(e)&&s(t)){e.length||(e=[e]);for(var n=0;n"+e,t.removeChild(t.firstChild);for(var n=document.createDocumentFragment();t.firstChild;)n.appendChild(t.firstChild);return n}function k(e,t){return r(e)?e.documentElement.contains(t):e.contains(t)}function E(e,t,n,r,i){var a=ze[t];return a&&a.delegate&&(t=a.originalEvent,r=a.handler.bind(a,r)),i&&(r=r.bind(),r.defaultListener_=!0),y(e,t),s(n)?v(e,t,n,r):d(n,t,r),new We(s(n)?e:n,t,r,s(n)?n:null)}function b(e,t,n){if(n&&"click"===t&&2===n.button)return!1;var r=["BUTTON","INPUT","SELECT","TEXTAREA","FIELDSET"];return!("click"===t&&r.indexOf(e.tagName)>-1)||!(e.disabled||O(e,"fieldset[disabled]"))}function S(e){return n(e)&&"number"==typeof e.length&&"function"==typeof e.item}function w(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function P(e){A(e);var t=!0,n=e.currentTarget,r=[];return t&=q(n,e,r),t&=M(r,e),e.delegateTarget=null,e[Ge]=n,t}function L(e,t){if(!e||1!==e.nodeType)return!1;var n=Element.prototype,r=n.matches||n.webkitMatchesSelector||n.mozMatchesSelector||n.msMatchesSelector||n.oMatchesSelector;return r?r.call(e,t):C(e,t)}function C(e,t){var n=e.parentNode;if(n)for(var r=n.querySelectorAll(t),i=0;i0&&void 0!==arguments[0]?arguments[0]:{};nt=e}function z(){return"undefined"!=typeof window&&window.__METAL_COMPATIBILITY__&&$(window.__METAL_COMPATIBILITY__),nt}function G(e,t){return e||t}function X(e){if(!e.name){var t=e.toString();e.name=t.substring(9,t.indexOf("("))}return e.name}function K(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:G,r=t+"_MERGED";if(!e.hasOwnProperty(r)){var i=e.hasOwnProperty(t)?e[t]:null;e.__proto__&&!e.__proto__.isPrototypeOf(Function)&&(i=n(i,K(e.__proto__,t,n))),e[r]=i}return e[r]}function Z(e,t){if(e){var n=e[it];return t&&!e.hasOwnProperty(it)&&(n=null),n||(e[it]=rt++)}return rt++}function ee(e){return e}function te(e){return"boolean"==typeof e}function ne(e){return void 0!==e}function re(e){return ne(e)&&!ue(e)}function ie(e){return e&&"object"===("undefined"==typeof e?"undefined":Te(e))&&9===e.nodeType}function ae(e){return e&&"object"===("undefined"==typeof e?"undefined":Te(e))&&11===e.nodeType}function oe(e){return e&&"object"===("undefined"==typeof e?"undefined":Te(e))&&1===e.nodeType}function se(e){return"function"==typeof e}function ue(e){return null===e}function le(e){return"number"==typeof e}function ce(e){return null!==e&&e===e.window}function he(e){var t="undefined"==typeof e?"undefined":Te(e);return"object"===t&&null!==e||"function"===t}function fe(e){return e&&"object"===("undefined"==typeof e?"undefined":Te(e))&&"function"==typeof e.then}function de(e){return"string"==typeof e||e instanceof String}function ve(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{checkEnv:!0},t="undefined"!=typeof process&&!process.browser;return t&&e.checkEnv&&(t="undefined"!=typeof process.env&&"test"!==process.env.NODE_ENV),t}function pe(){}function ye(e){var t=document.createElement("a");if(t.href=e,":"===t.protocol||!/:/.test(t.href))throw new TypeError(e+" is not a valid URL");return{hash:t.hash,hostname:t.hostname,password:t.password,pathname:"/"===t.pathname[0]?t.pathname:"/"+t.pathname,port:t.port,protocol:t.protocol,search:t.search,username:t.username}}function me(e){if(se(URL)&&URL.length){var t=new URL(e);if(t.port&&t.href.indexOf(t.port)===-1)throw new TypeError(e+" is not a valid URL");return t}return ye(e)}function _e(e){return e=e||[],Array.isArray(e)?e:[e]}function ge(e,t){return function n(){var r=arguments;ke(n),n.id=setTimeout(function(){e.apply(null,r)},t)}}function ke(e){clearTimeout(e.id)}function Ee(e){return{match:e[0],prefix:e[1],name:e[2],paramPattern:e[3],unnamedPattern:e[4],modifier:e[5]}}function be(e){for(var t="",n=0;n1&&void 0!==arguments[1]?arguments[1]:[],r=0;r=0)&&e.removeAt(t,r),i}},{key:"removeAt",value:function(e,t){return 1===Array.prototype.splice.call(e,t,1).length}},{key:"slice",value:function(e,t){for(var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e.length,r=[],i=t;i1?r-1:0),a=1;a1&&void 0!==arguments[1]?arguments[1]:window,n=e.split(".");return n.reduce(function(e,t){return e[t]},t)}},{key:"map",value:function(e,t){for(var n={},r=Object.keys(e),i=0;i0?n:null}},{key:"removeListener",value:function(){return this.off.apply(this,arguments)}},{key:"runListenerHandlers_",value:function(e){var t=this.listenerHandlers_;if(t){t=l(t);for(var n=0;n>>0),at=Object.freeze({UID_PROPERTY:it,abstractMethod:J,disableCompatibilityMode:Y,enableCompatibilityMode:$,getCompatibilityModeData:z,getFunctionName:X,getStaticProperty:K,getUid:Z,identityFunction:ee,isBoolean:te,isDef:ne,isDefAndNotNull:re,isDocument:ie,isDocumentFragment:ae,isElement:oe,isFunction:se,isNull:ue,isNumber:le,isWindow:ce,isObject:he,isPromise:fe,isString:de,isServerSide:ve,nullFunction:pe}),ot=function(){function e(){Re(this,e)}return Oe(e,null,[{key:"equal",value:function(e,t){if(e===t)return!0;if(e.length!==t.length)return!1;for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:[],r=0;r=0)&&e.removeAt(t,r),i}},{key:"removeAt",value:function(e,t){return 1===Array.prototype.splice.call(e,t,1).length}},{key:"slice",value:function(e,t){for(var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e.length,r=[],i=t;i1?r-1:0),a=1;a1&&void 0!==arguments[1]?arguments[1]:window,n=e.split(".");return n.reduce(function(e,t){return e[t]},t)}},{key:"map",value:function(e,t){for(var n={},r=Object.keys(e),i=0;i0&&void 0!==arguments[0]?arguments[0]:"";Re(this,e),this.url=e.parse(this.maybeAddProtocolAndHostname_(t))}return Oe(e,[{key:"addParametersFromMultiMap",value:function(e){var t=this;return e.names().forEach(function(n){e.getAll(n).forEach(function(e){t.addParameterValue(n,e)})}),this}},{key:"addParameterValue",value:function(e,t){return this.ensureQueryInitialized_(),ne(t)&&(t=String(t)),this.query.add(e,t),this}},{key:"addParameterValues",value:function(e,t){var n=this;return t.forEach(function(t){return n.addParameterValue(e,t)}),this}},{key:"ensureQueryInitialized_",value:function(){var t=this;if(!this.query){this.query=new ft;var n=this.url.search;n&&n.substring(1).split("&").forEach(function(n){var r=n.split("="),i=He(r,2),a=i[0],o=i[1];ne(o)&&(o=e.urlDecode(o)),t.addParameterValue(a,o)})}}},{key:"getHash",value:function(){return this.url.hash||""}},{key:"getHost",value:function(){var e=this.getHostname();if(e){var t=this.getPort();t&&"80"!==t&&(e+=":"+t)}return e}},{key:"getHostname",value:function(){var t=this.url.hostname;return t===e.HOSTNAME_PLACEHOLDER?"":t}},{key:"getOrigin",value:function(){var e=this.getHost();return e?this.getProtocol()+"//"+e:""}},{key:"getParameterValue",value:function(e){return this.ensureQueryInitialized_(),this.query.get(e)}},{key:"getParameterValues",value:function(e){return this.ensureQueryInitialized_(),this.query.getAll(e)}},{key:"getParameterNames",value:function(){return this.ensureQueryInitialized_(),this.query.names()}},{key:"getPathname",value:function(){return this.url.pathname}},{key:"getPort",value:function(){return this.url.port}},{key:"getProtocol",value:function(){return this.url.protocol}},{key:"getSearch",value:function(){var e=this,t="",n="";return this.getParameterNames().forEach(function(t){e.getParameterValues(t).forEach(function(e){n+=t,ne(e)&&(n+="="+encodeURIComponent(e)),n+="&"})}),n=n.slice(0,-1),n&&(t+="?"+n),t}},{key:"hasParameter",value:function(e){return this.ensureQueryInitialized_(),this.query.contains(e)}},{key:"makeUnique",value:function(){return this.setParameterValue(e.RANDOM_PARAM,ct.getRandomString()),this}},{key:"maybeAddProtocolAndHostname_",value:function(t){var n=t;if(t.indexOf("://")===-1&&0!==t.indexOf("javascript:"))switch(n=e.DEFAULT_PROTOCOL,"/"===t[0]&&"/"===t[1]||(n+="//"),t.charAt(0)){case".":case"?":case"#":n+=e.HOSTNAME_PLACEHOLDER,n+="/",n+=t;break;case"":case"/":"/"!==t[1]&&(n+=e.HOSTNAME_PLACEHOLDER),n+=t;break;default:n+=t}return n}},{key:"removeParameter",value:function(e){return this.ensureQueryInitialized_(),this.query.remove(e),this}},{key:"removeUnique",value:function(){return this.removeParameter(e.RANDOM_PARAM),this}},{key:"setHash",value:function(e){return this.url.hash=e,this}},{key:"setHostname",value:function(e){return this.url.hostname=e,this}},{key:"setParameterValue",value:function(e,t){return this.removeParameter(e),this.addParameterValue(e,t),this}},{key:"setParameterValues",value:function(e,t){var n=this;return this.removeParameter(e),t.forEach(function(t){return n.addParameterValue(e,t)}),this}},{key:"setPathname",value:function(e){return this.url.pathname=e,this}},{key:"setPort",value:function(e){return this.url.port=e,this}},{key:"setProtocol",value:function(e){return this.url.protocol=e,":"!==this.url.protocol[this.url.protocol.length-1]&&(this.url.protocol+=":"),this}},{key:"toString",value:function(){var e="",t=this.getHost();return t&&(e+=this.getProtocol()+"//"),e+=t+this.getPathname()+this.getSearch()+this.getHash()}}],[{key:"getParseFn",value:function(){return pt}},{key:"parse",value:function(e){return pt(e)}},{key:"setParseFn",value:function(e){pt=e}},{key:"joinPaths",value:function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r1&&"/"===e[t-1]&&(e=e.substr(0,t-1)),e}},{key:"setElementWithRandomHref",value:function(e){return e.href=e.href+"?q="+Math.random(),e}},{key:"setReferrer",value:function(e){Object.defineProperty(tt.document,"referrer",{configurable:!0,get:function(){return e}})}}]),e}(),gt={basePath:"data-senna-base-path",linkSelector:"data-senna-link-selector",loadingCssClass:"data-senna-loading-css-class",senna:"data-senna",dispatch:"data-senna-dispatch",surface:"data-senna-surface",updateScrollPosition:"data-senna-update-scroll-position"},kt=function(e){function t(e,n,r){Re(this,t);var i=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return i.emitter_=e,i.event_=n,i.listener_=r,i}return Ie(t,e),Oe(t,[{key:"disposeInternal",value:function(){this.removeListener(),this.emitter_=null,this.listener_=null}},{key:"removeListener",value:function(){this.emitter_.isDisposed()||this.emitter_.removeListener(this.event_,this.listener_)}}]),t}(ut),Et=[0],bt=function(e){function t(){Re(this,t);var e=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.events_=null,e.listenerHandlers_=null,e.shouldUseFacade_=!1,e}return Ie(t,e),Oe(t,[{key:"addHandler_",value:function(e,t){return e?(Array.isArray(e)||(e=[e]),e.push(t)):e=t,e}},{key:"addListener",value:function(e,t,n){this.validateListener_(t);for(var r=this.toEventsArray_(e),i=0;i0?n:null}},{key:"removeListener",value:function(){return this.off.apply(this,arguments)}},{key:"runListenerHandlers_",value:function(e){var t=this.listenerHandlers_;if(t){t=_e(t);for(var n=0;n0?this.unhandledRejectionId_=0:0===Vt.UNHANDLED_REJECTION_DELAY&&(this.hadUnhandledRejection_=!1);try{var n=this;e.call(t,function(e){n.resolve_(Vt.State_.FULFILLED,e)},function(e){n.resolve_(Vt.State_.REJECTED,e)})}catch(r){this.resolve_(Vt.State_.REJECTED,r)}};Lt.UNHANDLED_REJECTION_DELAY=0,Lt.State_={PENDING:0,BLOCKED:1,FULFILLED:2,REJECTED:3},Lt.CallbackEntry_=null,Lt.resolve=function(e){return new Lt(function(t){t(e)})},Lt.reject=function(e){return new Lt(function(t,n){n(e)})},Lt.race=function(e){return new Lt(function(t,n){e.length||t(void 0);for(var r,i=0;r=e[i];i++)r.then(t,n)})},Lt.all=function(e){return new Lt(function(t,n){var r=e.length,i=[];if(!r)return void t(i);for(var a,o=function(e,n){r--,i[e]=n,0===r&&t(i)},s=function(e){n(e)},u=0;a=e[u];u++)a.then(Pt(o,u),s)})},Lt.firstFulfilled=function(e){return new Lt(function(t,n){var r=e.length,i=[];if(!r)return void t(void 0);for(var a,o=function(e){t(e)},s=function(e,t){r--,i[e]=t,0===r&&n(i)},u=0;a=e[u];u++)a.then(o,Pt(s,u))})},Lt.prototype.then=function(e,t,n){return this.addChildPromise_(se(e)?e:null,se(t)?t:null,n)},wt.addImplementation(Lt),Lt.prototype.thenAlways=function(e,t){var n=function(){try{e.call(t)}catch(n){Lt.handleRejection_.call(null,n)}};return this.addCallbackEntry_({child:null,onRejected:n,onFulfilled:n}),this},Lt.prototype.thenCatch=function(e,t){return this.addChildPromise_(null,e,t)},Lt.prototype["catch"]=Lt.prototype.thenCatch,Lt.prototype.cancel=function(e){this.state_===Lt.State_.PENDING&&st.run(function(){var t=new Lt.CancellationError(e);t.IS_CANCELLATION_ERROR=!0,this.cancelInternal_(t)},this)},Lt.prototype.cancelInternal_=function(e){this.state_===Lt.State_.PENDING&&(this.parent_?this.parent_.cancelChild_(this,e):this.resolve_(Lt.State_.REJECTED,e))},Lt.prototype.cancelChild_=function(e,t){if(this.callbackEntries_){for(var n,r=0,i=-1,a=0;n=this.callbackEntries_[a];a++){var o=n.child;if(o&&(r++,o===e&&(i=a),i>=0&&r>1))break}if(i>=0)if(this.state_===Lt.State_.PENDING&&1===r)this.cancelInternal_(t);else{var s=this.callbackEntries_.splice(i,1)[0];this.executeCallback_(s,Lt.State_.REJECTED,t)}}},Lt.prototype.addCallbackEntry_=function(e){this.callbackEntries_&&this.callbackEntries_.length||this.state_!==Lt.State_.FULFILLED&&this.state_!==Lt.State_.REJECTED||this.scheduleCallbacks_(),this.callbackEntries_||(this.callbackEntries_=[]),this.callbackEntries_.push(e)},Lt.prototype.addChildPromise_=function(e,t,n){var r={child:null,onFulfilled:null,onRejected:null};return r.child=new Lt(function(i,a){r.onFulfilled=e?function(t){try{var r=e.call(n,t);i(r)}catch(o){a(o)}}:i,r.onRejected=t?function(e){try{var r=t.call(n,e);!ne(r)&&e.IS_CANCELLATION_ERROR?a(e):i(r)}catch(o){a(o)}}:a}),r.child.parent_=this,this.addCallbackEntry_(r),r.child},Lt.prototype.unblockAndFulfill_=function(e){if(this.state_!==Lt.State_.BLOCKED)throw new Error("CancellablePromise is not blocked.");this.state_=Lt.State_.PENDING,this.resolve_(Lt.State_.FULFILLED,e)},Lt.prototype.unblockAndReject_=function(e){if(this.state_!==Lt.State_.BLOCKED)throw new Error("CancellablePromise is not blocked.");this.state_=Lt.State_.PENDING,this.resolve_(Lt.State_.REJECTED,e)},Lt.prototype.resolve_=function(e,t){if(this.state_===Lt.State_.PENDING){if(this===t)e=Lt.State_.REJECTED,t=new TypeError("CancellablePromise cannot resolve to itself");else{if(wt.isImplementedBy(t))return t=t,this.state_=Lt.State_.BLOCKED,void t.then(this.unblockAndFulfill_,this.unblockAndReject_,this);if(he(t))try{var n=t.then;if(se(n))return void this.tryThen_(t,n)}catch(r){e=Lt.State_.REJECTED,t=r}}this.result_=t,this.state_=e,this.scheduleCallbacks_(),e!==Lt.State_.REJECTED||t.IS_CANCELLATION_ERROR||Lt.addUnhandledRejection_(this,t)}},Lt.prototype.tryThen_=function(e,t){this.state_=Lt.State_.BLOCKED;var n=this,r=!1,i=function(e){r||(r=!0,n.unblockAndFulfill_(e))},a=function(e){r||(r=!0,n.unblockAndReject_(e))};try{t.call(e,i,a)}catch(o){a(o)}},Lt.prototype.scheduleCallbacks_=function(){this.executing_||(this.executing_=!0,st.run(this.executeCallbacks_,this))},Lt.prototype.executeCallbacks_=function(){for(;this.callbackEntries_&&this.callbackEntries_.length;){var e=this.callbackEntries_;this.callbackEntries_=[];for(var t=0;t0)for(e=this;e&&e.unhandledRejectionId_;e=e.parent_)clearTimeout(e.unhandledRejectionId_),e.unhandledRejectionId_=0;else if(0===Lt.UNHANDLED_REJECTION_DELAY)for(e=this;e&&e.hadUnhandledRejection_;e=e.parent_)e.hadUnhandledRejection_=!1},Lt.addUnhandledRejection_=function(e,t){Lt.UNHANDLED_REJECTION_DELAY>0?e.unhandledRejectionId_=setTimeout(function(){Lt.handleRejection_.call(null,t)},Lt.UNHANDLED_REJECTION_DELAY):0===Lt.UNHANDLED_REJECTION_DELAY&&(e.hadUnhandledRejection_=!0,st.run(function(){e.hadUnhandledRejection_&&Lt.handleRejection_.call(null,t)}))},Lt.handleRejection_=st.throwException,Lt.setUnhandledRejectionHandler=function(e){Lt.handleRejection_=e},Lt.CancellationError=function(e){function t(e){Re(this,t);var n=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return e&&(n.message=e),n}return Ie(t,e),t}(Error),Lt.CancellationError.prototype.name="cancel";var Ct=/([\/])?(?:(?:\:(\w+)(?:\(((?:\\.|[^\\()])*)\))?|\(((?:\\.|[^\\()])+)\))([+*?])?)/g,At=function(){function e(t,n){if(Re(this,e),!re(t))throw new Error("Route path not specified.");if(!se(n))throw new Error("Route handler is not a function.");this.handler=n,this.path=t}return Oe(e,[{key:"buildParsedData_",value:function(){if(!this.parsedData_){var e=Le(this.path),t=Ce(e);this.parsedData_={regex:t,tokens:e}}return this.parsedData_}},{key:"extractParams",value:function(e){return de(this.path)?Ae(this.buildParsedData_().tokens,e):{}}},{key:"getHandler",value:function(){return this.handler}},{key:"getPath",value:function(){return this.path}},{key:"matchesPath",value:function(e){var t=this.path;return se(t)?t(e):(de(t)&&(t=this.buildParsedData_().regex),t instanceof RegExp&&e.search(t)>-1)}}]),e}(),Tt=function(e){function t(){Re(this,t);var e=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.cache=null,e.cacheable=!1,e}return Ie(t,e),Oe(t,[{key:"addCache",value:function(e){return this.cacheable&&(this.cache=e),this}},{key:"clearCache",value:function(){return this.cache=null,this}},{key:"disposeInternal",value:function(){this.clearCache()}},{key:"getCache",value:function(){return this.cache}},{key:"isCacheable",value:function(){return this.cacheable}},{key:"setCacheable",value:function(e){e||this.clearCache(),this.cacheable=e}}]),t}(ut),Rt=function(e){function t(){Re(this,t);var e=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.id=e.makeId_(Z()),e.metas=null,e.title=null,e}return Ie(t,e),Oe(t,[{key:"activate",value:function(){}},{key:"beforeActivate",value:function(){}},{key:"beforeDeactivate",value:function(){}},{key:"beforeUpdateHistoryPath",value:function(e){return e}},{key:"beforeUpdateHistoryState",value:function(e){return e}},{key:"deactivate",value:function(){}},{key:"disposeInternal",value:function(){Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"disposeInternal",this).call(this)}},{key:"evaluateScripts",value:function(e){return Object.keys(e).forEach(function(t){e[t].activeChild&&Ze.runScriptsInElement(e[t].activeChild)}),Lt.resolve()}},{key:"evaluateStyles",value:function(){return Lt.resolve()}},{key:"flip",value:function(e){var t=this,n=[];return Object.keys(e).forEach(function(r){var i=e[r],a=i.show(t.id);n.push(a)}),Lt.all(n)}},{key:"getId",value:function(){return this.id}},{key:"getMetas",value:function(){return this.metas}},{key:"getSurfaceContent",value:function(){}},{key:"getTitle",value:function(){return this.title}},{key:"load",value:function(){return Lt.resolve()}},{key:"makeId_",value:function(e){return"screen_"+e}},{key:"setId",value:function(e){this.id=e}},{key:"setMetas",value:function(e){this.metas=e}},{key:"setTitle",value:function(e){this.title=e}},{key:"toString",value:function(){return this.id}}]),t}(Tt);Rt.isImplementedBy=function(e){return e instanceof Rt};var Ot=function(e){function t(e){Re(this,t);var n=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));if(!e)throw new Error("Surface element id not specified. A surface element requires a valid id.");return n.activeChild=null,n.defaultChild=null,n.element=null,n.id=e,n.transitionFn=null,n.defaultChild=n.getChild(t.DEFAULT),n.maybeWrapContentAsDefault_(),n.activeChild=n.defaultChild,n}return Ie(t,e),Oe(t,[{key:"addContent",value:function(e,t){var n=this.defaultChild;re(t)&&(n=this.getChild(e),n?I(n):(n=this.createChild(e),this.transition(n,null)),_(n,t));var r=this.getElement();return r&&n&&_(r,n),n}},{key:"createChild",value:function(e){var t=tt.document.createElement("div");return t.setAttribute("id",this.makeId_(e)),t}},{key:"getChild",value:function(e){return tt.document.getElementById(this.makeId_(e))}},{key:"getElement",value:function(){return this.element?this.element:(this.element=tt.document.getElementById(this.id),this.element)}},{key:"getId",value:function(){return this.id}},{key:"getTransitionFn",value:function(){return this.transitionFn}},{key:"makeId_",value:function(e){return this.id+"-"+e}},{key:"maybeWrapContentAsDefault_",value:function(){var e=this.getElement();if(e&&!this.defaultChild){for(var n=tt.document.createDocumentFragment();e.firstChild;)n.appendChild(e.firstChild);this.defaultChild=this.addContent(t.DEFAULT,n),this.transition(null,this.defaultChild)}}},{key:"setId",value:function(e){this.id=e}},{key:"setTransitionFn",value:function(e){this.transitionFn=e}},{key:"show",value:function(e){var t=this.activeChild,n=this.getChild(e);return n||(n=this.defaultChild),this.activeChild=n,this.transition(t,n).thenAlways(function(){t&&t!==n&&w(t)})}},{key:"remove",value:function(e){var t=this.getChild(e);t&&w(t)}},{key:"toString",value:function(){return this.id}},{key:"transition",value:function(e,n){var r=this.transitionFn||t.defaultTransition;return Lt.resolve(r.call(this,e,n))}}]),t}(ut);Ot.DEFAULT="default",Ot.defaultTransition=function(e,t){e&&(e.style.display="none",e.classList.remove("flipped")),t&&(t.style.display="block",t.classList.add("flipped"))};var Nt={IMMEDIATE:"immediate",SCHEDULE_LAST:"scheduleLast"},It=function(e){function t(){Re(this,t);var e=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.activeScreen=null,e.activePath=null,e.allowPreventNavigate=!0,e.basePath="",e.browserPathBeforeNavigate=_t.getCurrentBrowserPathWithoutHash(),e.captureScrollPositionFromScrollEvent=!0,e.defaultTitle=tt.document.title,e.formSelector='form[enctype="multipart/form-data"]:not([data-senna-off])',e.ignoreQueryStringFromRoutePath=!1,e.linkSelector='a:not([data-senna-off]):not([target="_blank"])',e.loadingCssClass="senna-loading",e.nativeScrollRestorationSupported="scrollRestoration"in tt.window.history,e.navigationStrategy=Nt.IMMEDIATE,e.isNavigationPending=!1,e.pendingNavigate=null,e.popstateScrollLeft=0,e.popstateScrollTop=0,e.redirectPath=null,e.routes=[],e.scheduledNavigationQueue=[],e.screens={},e.skipLoadPopstate=!1,e.surfaces={},e.updateScrollPosition=!0,e.appEventHandlers_=new St,e.appEventHandlers_.add(T(tt.window,"scroll",ge(e.onScroll_.bind(e),100)),T(tt.window,"load",e.onLoad_.bind(e)),T(tt.window,"popstate",e.onPopstate_.bind(e))),e.on("startNavigate",e.onStartNavigate_),e.on("beforeNavigate",e.onBeforeNavigate_),e.on("beforeNavigate",e.onBeforeNavigateDefault_,!0),e.on("beforeUnload",e.onBeforeUnloadDefault_),e.setLinkSelector(e.linkSelector),e.setFormSelector(e.formSelector),e.maybeOverloadBeforeUnload_(),e}return Ie(t,e),Oe(t,[{key:"addRoutes",value:function(e){var t=this;return Array.isArray(e)||(e=[e]),e.forEach(function(e){e instanceof At||(e=new At(e.path,e.handler)),t.routes.push(e)}),this}},{key:"addSurfaces",value:function(e){var t=this;return Array.isArray(e)||(e=[e]),e.forEach(function(e){de(e)&&(e=new Ot(e)),t.surfaces[e.getId()]=e}),this}},{key:"canNavigate",value:function(e){var t=_t.isWebUri(e);if(!t)return!1;var n=_t.getUrlPath(e);return!!this.isLinkSameOrigin_(t.getHost())&&(!!this.isSameBasePath_(n)&&((!t.getHash()||!_t.isCurrentBrowserPath(n))&&!!this.findRoute(n)))}},{key:"clearScreensCache",value:function(){var e=this;Object.keys(this.screens).forEach(function(t){t===e.activePath?e.activeScreen.clearCache():e.isNavigationPending&&e.pendingNavigate.path===t||e.removeScreen(t)})}},{key:"createScreenInstance",value:function(e,t){if(!this.pendingNavigate&&e===this.activePath)return this.activeScreen;var n=this.screens[e];if(!n){var r=t.getHandler();n=r===Rt||Rt.isImplementedBy(r.prototype)?new r:r(t)||new Rt}return n}},{key:"disposeInternal",value:function(){this.activeScreen&&this.removeScreen(this.activePath),this.clearScreensCache(),this.formEventHandler_.removeListener(),this.linkEventHandler_.removeListener(),this.appEventHandlers_.removeAllListeners(),Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"disposeInternal",this).call(this)}},{key:"dispatch",value:function(){return this.navigate(_t.getCurrentBrowserPath(),!0)}},{key:"doNavigate_",value:function(e,t){var n=this,r=this.findRoute(e);if(!r)return this.pendingNavigate=Lt.reject(new Lt.CancellationError("No route for "+e)),this.pendingNavigate;this.stopPendingNavigate_(),this.isNavigationPending=!0;var i=this.createScreenInstance(e,r);return this.maybePreventDeactivate_().then(function(){return n.maybePreventActivate_(i)}).then(function(){return i.load(e)}).then(function(){n.navigationStrategy=Nt.SCHEDULE_LAST,n.activeScreen&&n.activeScreen.deactivate(),n.prepareNavigateHistory_(e,i,t),n.prepareNavigateSurfaces_(i,n.surfaces,n.extractParams(r,e))}).then(function(){return i.evaluateStyles(n.surfaces)}).then(function(){return i.flip(n.surfaces)}).then(function(){return i.evaluateScripts(n.surfaces)}).then(function(){return n.maybeUpdateScrollPositionState_()}).then(function(){return n.syncScrollPositionSyncThenAsync_()}).then(function(){return n.finalizeNavigate_(e,i)}).then(function(){return n.maybeOverloadBeforeUnload_()})["catch"](function(t){throw n.isNavigationPending=!1,n.handleNavigateError_(e,i,t),t}).thenAlways(function(){if(n.navigationStrategy=Nt.IMMEDIATE,n.scheduledNavigationQueue.length){var e=n.scheduledNavigationQueue.shift();n.maybeNavigate_(e.href,e)}})}},{key:"extractParams",value:function(e,t){return e.extractParams(this.getRoutePath(t))}},{key:"finalizeNavigate_",value:function(e,t){t.activate(),this.activeScreen&&!this.activeScreen.isCacheable()&&this.activeScreen!==t&&this.removeScreen(this.activePath),this.activePath=e,this.activeScreen=t,this.browserPathBeforeNavigate=_t.getCurrentBrowserPathWithoutHash(),this.screens[e]=t,this.isNavigationPending=!1,this.pendingNavigate=null,tt.capturedFormElement=null,tt.capturedFormButtonElement=null}},{key:"findRoute",value:function(e){e=this.getRoutePath(e);for(var t=0;t0}},{key:"isLinkSameOrigin_",value:function(e){var t=new yt(e),n=new yt(tt.window.location.host);return t.getPort()===n.getPort()&&t.getHostname()===n.getHostname()}},{key:"isSameBasePath_",value:function(e){ -return 0===e.indexOf(this.basePath)}},{key:"lockHistoryScrollPosition_",value:function(){var e=tt.window.history.state;if(e){var t=!1,n=function r(){tt.document.removeEventListener("scroll",r,!1),t||(tt.window.scrollTo(e.scrollLeft,e.scrollTop),t=!0)};st.nextTick(n),tt.document.addEventListener("scroll",n,!1)}}},{key:"maybeDisableNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&(this.nativeScrollRestoration_=tt.window.history.scrollRestoration,tt.window.history.scrollRestoration="manual")}},{key:"maybeScheduleNavigation_",value:function(e,t){return!(!this.isNavigationPending||this.navigationStrategy!==Nt.SCHEDULE_LAST)&&(this.scheduledNavigationQueue=[lt.mixin({href:e,isScheduledNavigation:!0},t)],!0)}},{key:"maybeNavigate_",value:function(e,t){if(this.canNavigate(e)){var n=this.maybeScheduleNavigation_(e,t);if(n)return void t.preventDefault();var r=!1;try{this.navigate(_t.getUrlPath(e),!1,t)}catch(i){r=!0}r||t.isScheduledNavigation||t.preventDefault()}}},{key:"maybeOverloadBeforeUnload_",value:function(){var e=this;"function"==typeof window.onbeforeunload&&(window._onbeforeunload=window.onbeforeunload,window.onbeforeunload=function(t){if(e.emit("beforeUnload",t),t&&t.defaultPrevented)return!0},window.onbeforeunload._overloaded=!0)}},{key:"maybePreventActivate_",value:function(e){var t=this;return Lt.resolve().then(function(){return e.beforeActivate()}).then(function(e){if(e)return t.pendingNavigate=Lt.reject(new Lt.CancellationError("Cancelled by next screen")),t.pendingNavigate})}},{key:"maybePreventDeactivate_",value:function(){var e=this;return Lt.resolve().then(function(){if(e.activeScreen)return e.activeScreen.beforeDeactivate()}).then(function(t){if(t)return e.pendingNavigate=Lt.reject(new Lt.CancellationError("Cancelled by active screen")),e.pendingNavigate})}},{key:"maybeRepositionScrollToHashedAnchor",value:function(){var e=tt.window.location.hash;if(e){var t=tt.document.getElementById(e.substring(1));if(t){var n=_t.getNodeOffset(t),r=n.offsetLeft,i=n.offsetTop;tt.window.scrollTo(r,i)}}}},{key:"maybeRestoreNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&this.nativeScrollRestoration_&&(tt.window.history.scrollRestoration=this.nativeScrollRestoration_)}},{key:"maybeRestoreRedirectPathHash_",value:function(e,t,n){return t===_t.getUrlPathWithoutHash(e)?t+n:t}},{key:"maybeUpdateScrollPositionState_",value:function(){var e=tt.window.location.hash,t=tt.document.getElementById(e.substring(1));if(t){var n=_t.getNodeOffset(t),r=n.offsetLeft,i=n.offsetTop;this.saveHistoryCurrentPageScrollPosition_(i,r)}}},{key:"navigate",value:function(e,t,n){if(!_t.isHtml5HistorySupported())throw new Error("HTML5 History is not supported. Senna will not intercept navigation.");return n&&(tt.capturedFormElement=n.capturedFormElement,tt.capturedFormButtonElement=n.capturedFormButtonElement),e===this.activePath&&(t=!0),this.emit("beforeNavigate",{event:n,path:e,replaceHistory:!!t}),this.pendingNavigate}},{key:"onBeforeNavigate_",value:function(e){tt.capturedFormElement&&(e.form=tt.capturedFormElement)}},{key:"onBeforeNavigateDefault_",value:function(e){(!this.pendingNavigate||this.pendingNavigate.path!==e.path&&this.navigationStrategy!==Nt.SCHEDULE_LAST)&&(this.emit("beforeUnload",e),this.emit("startNavigate",{form:e.form,path:e.path,replaceHistory:e.replaceHistory}))}},{key:"onBeforeUnloadDefault_",value:function(e){var t=window._onbeforeunload;t&&!t._overloaded&&t()&&e.preventDefault()}},{key:"onDocClickDelegate_",value:function(e){e.altKey||e.ctrlKey||e.metaKey||e.shiftKey||e.button||this.maybeNavigate_(e.delegateTarget.href,e)}},{key:"onDocSubmitDelegate_",value:function(e){var t=e.delegateTarget;if("get"!==t.method){e.capturedFormElement=t;var n="button:not([type]),button[type=submit],input[type=submit]";L(tt.document.activeElement,n)?e.capturedFormButtonElement=tt.document.activeElement:e.capturedFormButtonElement=t.querySelector(n),this.maybeNavigate_(t.action,e)}}},{key:"onLoad_",value:function(){var e=this;this.skipLoadPopstate=!0,setTimeout(function(){e.skipLoadPopstate=!1},0),this.maybeRepositionScrollToHashedAnchor()}},{key:"onPopstate_",value:function(e){if(!this.skipLoadPopstate){if(_t.isCurrentBrowserPath(this.browserPathBeforeNavigate))return void this.maybeRepositionScrollToHashedAnchor();var t=e.state;if(!t)return void(tt.window.location.hash?(this.redirectPath&&!_t.isCurrentBrowserPath(this.redirectPath)&&this.reloadPage(),this.maybeRepositionScrollToHashedAnchor()):this.reloadPage());if(t.senna){this.popstateScrollTop=t.scrollTop,this.popstateScrollLeft=t.scrollLeft,this.nativeScrollRestorationSupported||this.lockHistoryScrollPosition_(),this.once("endNavigate",function(){t.referrer&&_t.setReferrer(t.referrer)});var n=new yt(t.path);n.setHostname(tt.window.location.hostname),n.setPort(tt.window.location.port);var r=this.maybeScheduleNavigation_(n.toString(),{});if(r)return;this.navigate(t.path,!0)}}}},{key:"onScroll_",value:function(){this.captureScrollPositionFromScrollEvent&&this.saveHistoryCurrentPageScrollPosition_(tt.window.pageYOffset,tt.window.pageXOffset)}},{key:"onStartNavigate_",value:function(e){var t=this;this.maybeDisableNativeScrollRestoration(),this.captureScrollPositionFromScrollEvent=!1,c(tt.document.documentElement,this.loadingCssClass);var n={form:e.form,path:e.path};this.pendingNavigate=this.doNavigate_(e.path,e.replaceHistory)["catch"](function(e){throw n.error=e,e}).thenAlways(function(){t.pendingNavigate||t.scheduledNavigationQueue.length||(D(tt.document.documentElement,t.loadingCssClass),t.maybeRestoreNativeScrollRestoration(),t.captureScrollPositionFromScrollEvent=!0),t.emit("endNavigate",n)}),this.pendingNavigate.path=e.path}},{key:"prefetch",value:function(e){var t=this,n=this.findRoute(e);if(!n)return Lt.reject(new Lt.CancellationError("No route for "+e));var r=this.createScreenInstance(e,n);return r.load(e).then(function(){return t.screens[e]=r})["catch"](function(n){throw t.handleNavigateError_(e,r,n),n})}},{key:"prepareNavigateHistory_",value:function(e,t,n){var r=t.getTitle();de(r)||(r=this.getDefaultTitle());var i=t.beforeUpdateHistoryPath(e),a={form:re(tt.capturedFormElement),path:e,redirectPath:i,scrollLeft:0,scrollTop:0,senna:!0};n&&(a.scrollTop=this.popstateScrollTop,a.scrollLeft=this.popstateScrollLeft);var o=new yt(e).getHash();i=this.maybeRestoreRedirectPathHash_(e,i,o),this.updateHistory_(r,i,t.beforeUpdateHistoryState(a),n),this.redirectPath=i}},{key:"prepareNavigateSurfaces_",value:function(e,t,n){Object.keys(t).forEach(function(r){var i=e.getSurfaceContent(r,n);t[r].addContent(e.getId(),i)})}},{key:"reloadPage",value:function(){tt.window.location.reload()}},{key:"removeRoute",value:function(e){return ot.remove(this.routes,e)}},{key:"removeScreen",value:function(e){var t=this,n=this.screens[e];n&&(Object.keys(this.surfaces).forEach(function(e){return t.surfaces[e].remove(n.getId())}),n.dispose(),delete this.screens[e])}},{key:"saveHistoryCurrentPageScrollPosition_",value:function(e,t){var n=tt.window.history.state;if(n&&n.senna){var r=[e,t];n.scrollTop=r[0],n.scrollLeft=r[1],tt.window.history.replaceState(n,null,null)}}},{key:"setAllowPreventNavigate",value:function(e){this.allowPreventNavigate=e}},{key:"setBasePath",value:function(e){this.basePath=_t.removePathTrailingSlash(e)}},{key:"setDefaultTitle",value:function(e){this.defaultTitle=e}},{key:"setFormSelector",value:function(e){this.formSelector=e,this.formEventHandler_&&this.formEventHandler_.removeListener(),this.formEventHandler_=E(document,"submit",this.formSelector,this.onDocSubmitDelegate_.bind(this),this.allowPreventNavigate)}},{key:"setIgnoreQueryStringFromRoutePath",value:function(e){this.ignoreQueryStringFromRoutePath=e}},{key:"setLinkSelector",value:function(e){this.linkSelector=e,this.linkEventHandler_&&this.linkEventHandler_.removeListener(),this.linkEventHandler_=E(document,"click",this.linkSelector,this.onDocClickDelegate_.bind(this),this.allowPreventNavigate)}},{key:"setLoadingCssClass",value:function(e){this.loadingCssClass=e}},{key:"setUpdateScrollPosition",value:function(e){this.updateScrollPosition=e}},{key:"stopPendingNavigate_",value:function(){this.pendingNavigate&&this.pendingNavigate.cancel("Cancel pending navigation"),this.pendingNavigate=null}},{key:"syncScrollPositionSyncThenAsync_",value:function(){var e=this,t=tt.window.history.state;if(t){var n=t.scrollTop,r=t.scrollLeft,i=function(){e.updateScrollPosition&&tt.window.scrollTo(r,n)};return new Lt(function(e){return i()&st.nextTick(function(){return i()&e()})})}}},{key:"updateHistory_",value:function(e,t,n,r){var i=tt.window.location.href;n&&(n.referrer=i),r?tt.window.history.replaceState(n,e,t):tt.window.history.pushState(n,e,t),_t.setReferrer(i);var a=tt.document.querySelector("title");a?a.innerHTML=e:tt.document.title=e}}]),t}(bt),Dt=function(){function e(){Re(this,e)}return Oe(e,null,[{key:"parseResponseHeaders",value:function(e){var t=[];if(!e)return t;for(var n=e.split("\r\n"),r=0;r0){var a=n[r].substring(0,i),o=n[r].substring(i+2);t.push({name:a,value:o})}}return t}},{key:"request",value:function t(e,n,r,i,a,o,s,u){e=e||"",n=n||"GET";var t=new XMLHttpRequest,l=0,c=new Lt(function(e,n){t.onload=function(){return t.aborted?void t.onerror():void e(t)},t.onreadystatechange=function(){l&&l<3&&4===t.readyState&&(t.terminatedPrematurely=!0),l=t.readyState},t.onerror=function(){var e="Request error";t.terminatedPrematurely&&(e="Request terminated prematurely");var r=new Error(e);r.request=t,n(r)}}).thenCatch(function(e){throw t.abort(),e}).thenAlways(function(){clearTimeout(h)});if(e=new yt(e),a&&e.addParametersFromMultiMap(a).toString(),e=e.toString(),t.open(n,e,!s),u&&(t.withCredentials=!0),i&&i.names().forEach(function(e){t.setRequestHeader(e,i.getAll(e).join(", "))}),t.send(ne(r)?r:null),re(o))var h=setTimeout(function(){c.cancel("Request timeout")},o);return c}}]),e}(),Ht=function Wt(){Re(this,Wt)};Ht.INVALID_STATUS="Invalid status code",Ht.REQUEST_ERROR="Request error",Ht.REQUEST_TIMEOUT="Request timeout",Ht.REQUEST_PREMATURE_TERMINATION="Request terminated prematurely";var xt=function(){function e(){Re(this,e)}return Oe(e,null,[{key:"getNativeUserAgent",value:function(){var t=e.globals.window&&e.globals.window.navigator;if(t){var n=t.userAgent;if(n)return n}return""}},{key:"getNativePlatform",value:function(){var t=e.globals.window&&e.globals.window.navigator;if(t){var n=t.platform;if(n)return n}return""}},{key:"matchPlatform",value:function(t){return e.platform.indexOf(t)!==-1}},{key:"matchUserAgent",value:function(t){return e.userAgent.indexOf(t)!==-1}},{key:"testUserAgent",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";e.userAgent=t,e.platform=n,e.isMac=e.matchPlatform("Mac"),e.isWin=e.matchPlatform("Win"),e.isOpera=e.matchUserAgent("Opera")||e.matchUserAgent("OPR"),e.isIe=e.matchUserAgent("Trident")||e.matchUserAgent("MSIE"),e.isEdge=e.matchUserAgent("Edge"),e.isIeOrEdge=e.isIe||e.isEdge,e.isChrome=(e.matchUserAgent("Chrome")||e.matchUserAgent("CriOS"))&&!e.isOpera&&!e.isEdge,e.isSafari=e.matchUserAgent("Safari")&&!(e.isChrome||e.isOpera||e.isEdge),e.isFirefox=e.matchUserAgent("Firefox")}}]),e}();Object.defineProperty(xt,"globals",{writable:!0,value:{window:ve()?null:window}}),xt.testUserAgent(xt.getNativeUserAgent(),xt.getNativePlatform());var Ut=function(e){function t(){Re(this,t);var e=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.cacheable=!0,e.httpHeaders={"X-PJAX":"true","X-Requested-With":"XMLHttpRequest"},e.httpMethod=t.GET,e.request=null,e.timeout=3e4,e}return Ie(t,e),Oe(t,[{key:"assertValidResponseStatusCode",value:function(e){if(!this.isValidResponseStatusCode(e)){var t=new Error(Ht.INVALID_STATUS);throw t.invalidStatus=!0,t.statusCode=e,t}}},{key:"beforeUpdateHistoryPath",value:function(e){var t=this.getRequestPath();return t&&t!==e?t:e}},{key:"beforeUpdateHistoryState",value:function(e){return e.senna&&e.form&&e.redirectPath===e.path?null:e}},{key:"formatLoadPath",value:function(e){var n=new yt(e);return n.setHostname(tt.window.location.hostname),n.setProtocol(tt.window.location.protocol),tt.window.location.port&&n.setPort(tt.window.location.port),xt.isIeOrEdge&&this.httpMethod===t.GET?n.makeUnique().toString():n.toString()}},{key:"getHttpHeaders",value:function(){return this.httpHeaders}},{key:"getHttpMethod",value:function(){return this.httpMethod}},{key:"getRequestPath",value:function(){var e=this.getRequest();if(e){var n=e.requestPath,r=this.maybeExtractResponseUrlFromRequest(e);return r&&(n=r),xt.isIeOrEdge&&this.httpMethod===t.GET&&(n=new yt(n).removeUnique().toString()),_t.getUrlPath(n)}return null}},{key:"getRequest",value:function(){return this.request}},{key:"getTimeout",value:function(){return this.timeout}},{key:"isValidResponseStatusCode",value:function(e){return e>=200&&e<=399}},{key:"getFormData",value:function(e,t){var n=new FormData(e);return this.maybeAppendSubmitButtonValue_(n,t),n}},{key:"load",value:function(e){var n=this,r=this.getCache();if(re(r))return Lt.resolve(r);var i=null,a=this.httpMethod,o=new ft;Object.keys(this.httpHeaders).forEach(function(e){return o.add(e,n.httpHeaders[e])}),tt.capturedFormElement&&(this.addSafariXHRPolyfill(),i=this.getFormData(tt.capturedFormElement,tt.capturedFormButtonElement),a=t.POST,xt.isIeOrEdge&&o.add("If-None-Match",'"0"'));var s=this.formatLoadPath(e);return Dt.request(s,a,i,o,null,this.timeout).then(function(e){return n.removeSafariXHRPolyfill(),n.setRequest(e),n.assertValidResponseStatusCode(e.status),a===t.GET&&n.isCacheable()&&n.addCache(e.responseText),e.requestPath=s,e.responseText})["catch"](function(e){switch(n.removeSafariXHRPolyfill(),e.message){case Ht.REQUEST_TIMEOUT:e.timeout=!0;break;case Ht.REQUEST_ERROR:e.requestError=!0;break;case Ht.REQUEST_PREMATURE_TERMINATION:e.requestError=!0,e.requestPrematureTermination=!0}throw e})}},{key:"maybeAppendSubmitButtonValue_",value:function(e,t){t&&t.name&&e.append(t.name,t.value)}},{key:"maybeExtractResponseUrlFromRequest",value:function(e){var n=e.responseURL;return n?n:e.getResponseHeader(t.X_REQUEST_URL_HEADER)}},{key:"addSafariXHRPolyfill",value:function(){if(tt.capturedFormElement&&xt.isSafari)for(var e=tt.capturedFormElement.querySelectorAll('input[type="file"]:not([disabled])'),t=0;t0)return;n.setAttribute("data-safari-temp-disabled","true"),n.setAttribute("disabled","")}}},{key:"removeSafariXHRPolyfill",value:function(){if(tt.capturedFormElement&&xt.isSafari)for(var e=tt.capturedFormElement.querySelectorAll('input[type="file"][data-safari-temp-disabled]'),t=0;t/gi,"/senna>");var n=void 0;if(xt.isIe){var r=tt.document.createRange().createContextualFragment(e);n=r.querySelector("senna")}else t.innerHTML=e,n=t.querySelector("senna");n&&(_t.clearNodeAttributes(t),_t.copyNodeAttributes(n,t))}},{key:"disposeInternal",value:function(){this.disposePendingStyles(),Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"disposeInternal",this).call(this)}},{key:"disposePendingStyles",value:function(){this.pendingStyles&&_t.removeElementsFromDocument(this.pendingStyles)}},{key:"evaluateScripts",value:function(e){var n=this,r=this.evaluateTrackedResources_(Ze.runScriptsInElement,t.selectors.scripts,t.selectors.scriptsTemporary,t.selectors.scriptsPermanent);return r.then(function(){return Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"evaluateScripts",n).call(n,e)})}},{key:"evaluateStyles",value:function(e){var n=this;this.pendingStyles=[];var r=this.evaluateTrackedResources_(et.runStylesInElement,t.selectors.styles,t.selectors.stylesTemporary,t.selectors.stylesPermanent,this.appendStyleIntoDocument_.bind(this));return r.then(function(){return Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"evaluateStyles",n).call(n,e)})}},{key:"evaluateFavicon_",value:function(){var e=this,n=this.virtualQuerySelectorAll_(t.selectors.favicon),r=this.querySelectorAll_(t.selectors.favicon);return new Lt(function(t){_t.removeElementsFromDocument(r),e.runFaviconInElement_(n).then(function(){return t()})})}},{key:"evaluateTrackedResources_",value:function(e,n,r,i,a){var o=this,s=this.virtualQuerySelectorAll_(n),u=this.querySelectorAll_(r),l=this.querySelectorAll_(i);l.forEach(function(e){var n=o.getResourceKey_(e);n&&(t.permanentResourcesInDoc[n]=!0)});var c=g();return s.forEach(function(e){var n=o.getResourceKey_(e);t.permanentResourcesInDoc[n]||c.appendChild(e),n&&L(e,i)&&(t.permanentResourcesInDoc[n]=!0)}),new Lt(function(t){e(c,function(){_t.removeElementsFromDocument(u),t()},a)})}},{key:"flip",value:function(e){var n=this;return Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"flip",this).call(this,e).then(function(){_t.clearNodeAttributes(tt.document.documentElement),_t.copyNodeAttributes(n.virtualDocument,tt.document.documentElement),n.evaluateFavicon_(),n.updateMetaTags_()})}},{key:"updateMetaTags_",value:function(){var e=this.querySelectorAll_("meta"),t=this.metas;e&&(_t.removeElementsFromDocument(e),t&&t.forEach(function(e){return tt.document.head.appendChild(e)}))}},{key:"getResourceKey_",value:function(e){return e.id||e.href||e.src||""}},{key:"getSurfaceContent",value:function(e){var t=this.virtualDocument.querySelector("#"+e);if(t){var n=t.querySelector("#"+e+"-"+Ot.DEFAULT);return n?n.innerHTML:t.innerHTML}}},{key:"getTitleSelector",value:function(){return this.titleSelector}},{key:"load",value:function(e){var n=this;return Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"load",this).call(this,e).then(function(e){return n.allocateVirtualDocumentForContent(e),n.resolveTitleFromVirtualDocument(),n.resolveMetaTagsFromVirtualDocument(),n.assertSameBodyIdInVirtualDocument(),xt.isIe&&n.makeTemporaryStylesHrefsUnique_(),e})}},{key:"makeTemporaryStylesHrefsUnique_",value:function(){var e=this,n=this.virtualQuerySelectorAll_(t.selectors.stylesTemporary);n.forEach(function(t){return e.replaceStyleAndMakeUnique_(t)})}},{key:"replaceStyleAndMakeUnique_",value:function(e){if(e.href){var t=tt.document.createElement(e.tagName);e.href=new yt(e.href).makeUnique().toString(),_t.copyNodeAttributes(e,t),e.parentNode.replaceChild(t,e),e.disabled=!0}}},{key:"runFaviconInElement_",value:function(e){return new Lt(function(t){e.forEach(function(e){return document.head.appendChild(xt.isIe?e:_t.setElementWithRandomHref(e))}),t()})}},{key:"virtualQuerySelectorAll_",value:function(e){return Array.prototype.slice.call(this.virtualDocument.querySelectorAll(e))}},{key:"querySelectorAll_",value:function(e){return Array.prototype.slice.call(tt.document.querySelectorAll(e))}},{key:"releaseVirtualDocument",value:function(){this.virtualDocument=null}},{key:"resolveTitleFromVirtualDocument",value:function(){var e=this.virtualDocument.querySelector(this.titleSelector);e&&this.setTitle(e.textContent.trim())}},{key:"resolveMetaTagsFromVirtualDocument",value:function(){var e=this.virtualQuerySelectorAll_(this.metaTagsSelector);e&&this.setMetas(e)}},{key:"setTitleSelector",value:function(e){this.titleSelector=e}}]),t}(Ut),jt=':not([rel="Shortcut Icon"]):not([rel="shortcut icon"]):not([rel="icon"]):not([href$="favicon.icon"])';Ft.selectors={favicon:'link[rel="Shortcut Icon"],link[rel="shortcut icon"],link[rel="icon"],link[href$="favicon.icon"]',scripts:"script[data-senna-track]",scriptsPermanent:'script[data-senna-track="permanent"]',scriptsTemporary:'script[data-senna-track="temporary"]',styles:"style[data-senna-track],link[data-senna-track]"+jt,stylesPermanent:'style[data-senna-track="permanent"],link[data-senna-track="permanent"]'+jt,stylesTemporary:'style[data-senna-track="temporary"],link[data-senna-track="temporary"]'+jt},Ft.permanentResourcesInDoc={};var Mt=function(e){function t(){Re(this,t);var e=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.app=null,e.baseElement=null,e}return Ie(t,e),Oe(t,[{key:"handle",value:function(){if(!oe(this.baseElement))throw new Error("Senna data attribute handler base element not set or invalid, try setting a valid element that contains a `data-senna` attribute.");if(this.baseElement.hasAttribute(gt.senna)){if(this.app)throw new Error("Senna app was already initialized.");this.app=new It,this.maybeAddRoutes_(),this.maybeAddSurfaces_(),this.maybeSetBasePath_(),this.maybeSetLinkSelector_(),this.maybeSetLoadingCssClass_(),this.maybeSetUpdateScrollPosition_(),this.maybeDispatch_()}}},{key:"disposeInternal",value:function(){this.app&&this.app.dispose()}},{key:"getApp",value:function(){return this.app}},{key:"getBaseElement",value:function(){return this.baseElement}},{key:"maybeAddRoutes_",value:function(){var e=this,t='link[rel="senna-route"]';this.querySelectorAllAsArray_(t).forEach(function(t){return e.maybeParseLinkRoute_(t)}),this.app.hasRoutes()||this.app.addRoutes(new At(/.*/,Ft))}},{key:"maybeAddSurfaces_",value:function(){var e=this,t="["+gt.surface+"]";this.querySelectorAllAsArray_(t).forEach(function(t){e.updateElementIdIfSpecialSurface_(t),e.app.addSurfaces(t.id)})}},{key:"maybeDispatch_",value:function(){this.baseElement.hasAttribute(gt.dispatch)&&this.app.dispatch()}},{key:"maybeParseLinkRoute_",value:function(e){var t=new At(this.maybeParseLinkRoutePath_(e),this.maybeParseLinkRouteHandler_(e));this.app.addRoutes(t)}},{key:"maybeParseLinkRouteHandler_",value:function(e){var t=e.getAttribute("type");return re(t)&&(t=lt.getObjectByName(t)),t}},{key:"maybeParseLinkRoutePath_",value:function(e){var t=e.getAttribute("href");return re(t)&&0===t.indexOf("regex:")&&(t=new RegExp(t.substring(6))),t}},{key:"maybeSetBasePath_",value:function(){var e=this.baseElement.getAttribute(gt.basePath);re(e)&&this.app.setBasePath(e)}},{key:"maybeSetLinkSelector_",value:function(){var e=this.baseElement.getAttribute(gt.linkSelector);re(e)&&this.app.setLinkSelector(e)}},{key:"maybeSetLoadingCssClass_",value:function(){var e=this.baseElement.getAttribute(gt.loadingCssClass);re(e)&&this.app.setLoadingCssClass(e)}},{key:"maybeSetUpdateScrollPosition_",value:function(){var e=this.baseElement.getAttribute(gt.updateScrollPosition);re(e)&&("false"===e?this.app.setUpdateScrollPosition(!1):this.app.setUpdateScrollPosition(!0))}},{key:"querySelectorAllAsArray_",value:function(e){return Array.prototype.slice.call(tt.document.querySelectorAll(e))}},{key:"updateElementIdIfSpecialSurface_",value:function(e){e.id||e!==tt.document.body||(e.id="senna_surface_"+Z())}},{key:"setBaseElement",value:function(e){this.baseElement=e}}]),t}(ut),qt=new Mt;tt.document.addEventListener("DOMContentLoaded",function(){qt.setBaseElement(tt.document.body),qt.handle()});var Bt="2.7.8";e["default"]=It,e.dataAttributeHandler=qt,e.utils=_t,e.App=It,e.HtmlScreen=Ft,e.Route=At,e.RequestScreen=Ut,e.Screen=Rt,e.version=Bt,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file +return 0===e.indexOf(this.basePath)}},{key:"lockHistoryScrollPosition_",value:function(){var e=tt.window.history.state;if(e){var t=!1,n=function r(){tt.document.removeEventListener("scroll",r,!1),t||(tt.window.scrollTo(e.scrollLeft,e.scrollTop),t=!0)};st.nextTick(n),tt.document.addEventListener("scroll",n,!1)}}},{key:"maybeDisableNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&(this.nativeScrollRestoration_=tt.window.history.scrollRestoration,tt.window.history.scrollRestoration="manual")}},{key:"maybeScheduleNavigation_",value:function(e,t){return!(!this.isNavigationPending||this.navigationStrategy!==Nt.SCHEDULE_LAST)&&(this.scheduledNavigationQueue=[lt.mixin({href:e,isScheduledNavigation:!0},t)],!0)}},{key:"maybeNavigate_",value:function(e,t){if(this.canNavigate(e)){var n=this.maybeScheduleNavigation_(e,t);if(n)return void t.preventDefault();var r=!1;try{this.navigate(_t.getUrlPath(e),!1,t)}catch(i){r=!0}r||t.isScheduledNavigation||t.preventDefault()}}},{key:"maybeOverloadBeforeUnload_",value:function(){var e=this;"function"==typeof window.onbeforeunload&&(window._onbeforeunload=window.onbeforeunload,window.onbeforeunload=function(t){if(e.emit("beforeUnload",t),t&&t.defaultPrevented)return!0},window.onbeforeunload._overloaded=!0)}},{key:"maybePreventActivate_",value:function(e){var t=this;return Lt.resolve().then(function(){return e.beforeActivate()}).then(function(e){if(e)return t.pendingNavigate=Lt.reject(new Lt.CancellationError("Cancelled by next screen")),t.pendingNavigate})}},{key:"maybePreventDeactivate_",value:function(){var e=this;return Lt.resolve().then(function(){if(e.activeScreen)return e.activeScreen.beforeDeactivate()}).then(function(t){if(t)return e.pendingNavigate=Lt.reject(new Lt.CancellationError("Cancelled by active screen")),e.pendingNavigate})}},{key:"maybeRepositionScrollToHashedAnchor",value:function(){var e=tt.window.location.hash;if(e){var t=tt.document.getElementById(e.substring(1));if(t){var n=_t.getNodeOffset(t),r=n.offsetLeft,i=n.offsetTop;tt.window.scrollTo(r,i)}}}},{key:"maybeRestoreNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&this.nativeScrollRestoration_&&(tt.window.history.scrollRestoration=this.nativeScrollRestoration_)}},{key:"maybeRestoreRedirectPathHash_",value:function(e,t,n){return t===_t.getUrlPathWithoutHash(e)?t+n:t}},{key:"maybeUpdateScrollPositionState_",value:function(){var e=tt.window.location.hash,t=tt.document.getElementById(e.substring(1));if(t){var n=_t.getNodeOffset(t),r=n.offsetLeft,i=n.offsetTop;this.saveHistoryCurrentPageScrollPosition_(i,r)}}},{key:"navigate",value:function(e,t,n){if(!_t.isHtml5HistorySupported())throw new Error("HTML5 History is not supported. Senna will not intercept navigation.");return n&&(tt.capturedFormElement=n.capturedFormElement,tt.capturedFormButtonElement=n.capturedFormButtonElement),e===this.activePath&&(t=!0),this.emit("beforeNavigate",{event:n,path:e,replaceHistory:!!t}),this.pendingNavigate}},{key:"onBeforeNavigate_",value:function(e){tt.capturedFormElement&&(e.form=tt.capturedFormElement)}},{key:"onBeforeNavigateDefault_",value:function(e){(!this.pendingNavigate||this.pendingNavigate.path!==e.path&&this.navigationStrategy!==Nt.SCHEDULE_LAST)&&(this.emit("beforeUnload",e),this.emit("startNavigate",{form:e.form,path:e.path,replaceHistory:e.replaceHistory}))}},{key:"onBeforeUnloadDefault_",value:function(e){var t=window._onbeforeunload;t&&!t._overloaded&&t()&&e.preventDefault()}},{key:"onDocClickDelegate_",value:function(e){e.altKey||e.ctrlKey||e.metaKey||e.shiftKey||e.button||this.maybeNavigate_(e.delegateTarget.href,e)}},{key:"onDocSubmitDelegate_",value:function(e){var t=e.delegateTarget;if("get"!==t.method){e.capturedFormElement=t;var n="button:not([type]),button[type=submit],input[type=submit]";L(tt.document.activeElement,n)?e.capturedFormButtonElement=tt.document.activeElement:e.capturedFormButtonElement=t.querySelector(n),this.maybeNavigate_(t.action,e)}}},{key:"onLoad_",value:function(){var e=this;this.skipLoadPopstate=!0,setTimeout(function(){e.skipLoadPopstate=!1},0),this.maybeRepositionScrollToHashedAnchor()}},{key:"onPopstate_",value:function(e){if(!this.skipLoadPopstate){if(_t.isCurrentBrowserPath(this.browserPathBeforeNavigate))return void this.maybeRepositionScrollToHashedAnchor();var t=e.state;if(!t)return void(tt.window.location.hash?(this.redirectPath&&!_t.isCurrentBrowserPath(this.redirectPath)&&this.reloadPage(),this.maybeRepositionScrollToHashedAnchor()):this.reloadPage());if(t.senna){this.popstateScrollTop=t.scrollTop,this.popstateScrollLeft=t.scrollLeft,this.nativeScrollRestorationSupported||this.lockHistoryScrollPosition_(),this.once("endNavigate",function(){t.referrer&&_t.setReferrer(t.referrer)});var n=new yt(t.path);n.setHostname(tt.window.location.hostname),n.setPort(tt.window.location.port);var r=this.maybeScheduleNavigation_(n.toString(),{});if(r)return;this.navigate(t.path,!0)}}}},{key:"onScroll_",value:function(){this.captureScrollPositionFromScrollEvent&&this.saveHistoryCurrentPageScrollPosition_(tt.window.pageYOffset,tt.window.pageXOffset)}},{key:"onStartNavigate_",value:function(e){var t=this;this.maybeDisableNativeScrollRestoration(),this.captureScrollPositionFromScrollEvent=!1,c(tt.document.documentElement,this.loadingCssClass);var n={form:e.form,path:e.path};this.pendingNavigate=this.doNavigate_(e.path,e.replaceHistory)["catch"](function(e){throw n.error=e,e}).thenAlways(function(){t.pendingNavigate||t.scheduledNavigationQueue.length||(D(tt.document.documentElement,t.loadingCssClass),t.maybeRestoreNativeScrollRestoration(),t.captureScrollPositionFromScrollEvent=!0),t.emit("endNavigate",n)}),this.pendingNavigate.path=e.path}},{key:"prefetch",value:function(e){var t=this,n=this.findRoute(e);if(!n)return Lt.reject(new Lt.CancellationError("No route for "+e));var r=this.createScreenInstance(e,n);return r.load(e).then(function(){return t.screens[e]=r})["catch"](function(n){throw t.handleNavigateError_(e,r,n),n})}},{key:"prepareNavigateHistory_",value:function(e,t,n){var r=t.getTitle();de(r)||(r=this.getDefaultTitle());var i=t.beforeUpdateHistoryPath(e),a=new yt(e).getHash();i=this.maybeRestoreRedirectPathHash_(e,i,a);var o={form:re(tt.capturedFormElement),path:e,redirectPath:i,scrollLeft:0,scrollTop:0,senna:!0};n&&(o.scrollTop=this.popstateScrollTop,o.scrollLeft=this.popstateScrollLeft),this.updateHistory_(r,i,t.beforeUpdateHistoryState(o),n),this.redirectPath=i}},{key:"prepareNavigateSurfaces_",value:function(e,t,n){Object.keys(t).forEach(function(r){var i=e.getSurfaceContent(r,n);t[r].addContent(e.getId(),i)})}},{key:"reloadPage",value:function(){tt.window.location.reload()}},{key:"removeRoute",value:function(e){return ot.remove(this.routes,e)}},{key:"removeScreen",value:function(e){var t=this,n=this.screens[e];n&&(Object.keys(this.surfaces).forEach(function(e){return t.surfaces[e].remove(n.getId())}),n.dispose(),delete this.screens[e])}},{key:"saveHistoryCurrentPageScrollPosition_",value:function(e,t){var n=tt.window.history.state;if(n&&n.senna){var r=[e,t];n.scrollTop=r[0],n.scrollLeft=r[1],tt.window.history.replaceState(n,null,null)}}},{key:"setAllowPreventNavigate",value:function(e){this.allowPreventNavigate=e}},{key:"setBasePath",value:function(e){this.basePath=_t.removePathTrailingSlash(e)}},{key:"setDefaultTitle",value:function(e){this.defaultTitle=e}},{key:"setFormSelector",value:function(e){this.formSelector=e,this.formEventHandler_&&this.formEventHandler_.removeListener(),this.formEventHandler_=E(document,"submit",this.formSelector,this.onDocSubmitDelegate_.bind(this),this.allowPreventNavigate)}},{key:"setIgnoreQueryStringFromRoutePath",value:function(e){this.ignoreQueryStringFromRoutePath=e}},{key:"setLinkSelector",value:function(e){this.linkSelector=e,this.linkEventHandler_&&this.linkEventHandler_.removeListener(),this.linkEventHandler_=E(document,"click",this.linkSelector,this.onDocClickDelegate_.bind(this),this.allowPreventNavigate)}},{key:"setLoadingCssClass",value:function(e){this.loadingCssClass=e}},{key:"setUpdateScrollPosition",value:function(e){this.updateScrollPosition=e}},{key:"stopPendingNavigate_",value:function(){this.pendingNavigate&&this.pendingNavigate.cancel("Cancel pending navigation"),this.pendingNavigate=null}},{key:"syncScrollPositionSyncThenAsync_",value:function(){var e=this,t=tt.window.history.state;if(t){var n=t.scrollTop,r=t.scrollLeft,i=function(){e.updateScrollPosition&&tt.window.scrollTo(r,n)};return new Lt(function(e){return i()&st.nextTick(function(){return i()&e()})})}}},{key:"updateHistory_",value:function(e,t,n,r){var i=tt.window.location.href;n&&(n.referrer=i),r?tt.window.history.replaceState(n,e,t):tt.window.history.pushState(n,e,t),_t.setReferrer(i);var a=tt.document.querySelector("title");a?a.innerHTML=e:tt.document.title=e}}]),t}(bt),Dt=function(){function e(){Re(this,e)}return Oe(e,null,[{key:"parseResponseHeaders",value:function(e){var t=[];if(!e)return t;for(var n=e.split("\r\n"),r=0;r0){var a=n[r].substring(0,i),o=n[r].substring(i+2);t.push({name:a,value:o})}}return t}},{key:"request",value:function t(e,n,r,i,a,o,s,u){e=e||"",n=n||"GET";var t=new XMLHttpRequest,l=0,c=new Lt(function(e,n){t.onload=function(){return t.aborted?void t.onerror():void e(t)},t.onreadystatechange=function(){l&&l<3&&4===t.readyState&&(t.terminatedPrematurely=!0),l=t.readyState},t.onerror=function(){var e="Request error";t.terminatedPrematurely&&(e="Request terminated prematurely");var r=new Error(e);r.request=t,n(r)}}).thenCatch(function(e){throw t.abort(),e}).thenAlways(function(){clearTimeout(h)});if(e=new yt(e),a&&e.addParametersFromMultiMap(a).toString(),e=e.toString(),t.open(n,e,!s),u&&(t.withCredentials=!0),i&&i.names().forEach(function(e){t.setRequestHeader(e,i.getAll(e).join(", "))}),t.send(ne(r)?r:null),re(o))var h=setTimeout(function(){c.cancel("Request timeout")},o);return c}}]),e}(),Ht=function Wt(){Re(this,Wt)};Ht.INVALID_STATUS="Invalid status code",Ht.REQUEST_ERROR="Request error",Ht.REQUEST_TIMEOUT="Request timeout",Ht.REQUEST_PREMATURE_TERMINATION="Request terminated prematurely";var xt=function(){function e(){Re(this,e)}return Oe(e,null,[{key:"getNativeUserAgent",value:function(){var t=e.globals.window&&e.globals.window.navigator;if(t){var n=t.userAgent;if(n)return n}return""}},{key:"getNativePlatform",value:function(){var t=e.globals.window&&e.globals.window.navigator;if(t){var n=t.platform;if(n)return n}return""}},{key:"matchPlatform",value:function(t){return e.platform.indexOf(t)!==-1}},{key:"matchUserAgent",value:function(t){return e.userAgent.indexOf(t)!==-1}},{key:"testUserAgent",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";e.userAgent=t,e.platform=n,e.isMac=e.matchPlatform("Mac"),e.isWin=e.matchPlatform("Win"),e.isOpera=e.matchUserAgent("Opera")||e.matchUserAgent("OPR"),e.isIe=e.matchUserAgent("Trident")||e.matchUserAgent("MSIE"),e.isEdge=e.matchUserAgent("Edge"),e.isIeOrEdge=e.isIe||e.isEdge,e.isChrome=(e.matchUserAgent("Chrome")||e.matchUserAgent("CriOS"))&&!e.isOpera&&!e.isEdge,e.isSafari=e.matchUserAgent("Safari")&&!(e.isChrome||e.isOpera||e.isEdge),e.isFirefox=e.matchUserAgent("Firefox")}}]),e}();Object.defineProperty(xt,"globals",{writable:!0,value:{window:ve()?null:window}}),xt.testUserAgent(xt.getNativeUserAgent(),xt.getNativePlatform());var Ut=function(e){function t(){Re(this,t);var e=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.cacheable=!0,e.httpHeaders={"X-PJAX":"true","X-Requested-With":"XMLHttpRequest"},e.httpMethod=t.GET,e.request=null,e.timeout=3e4,e}return Ie(t,e),Oe(t,[{key:"assertValidResponseStatusCode",value:function(e){if(!this.isValidResponseStatusCode(e)){var t=new Error(Ht.INVALID_STATUS);throw t.invalidStatus=!0,t.statusCode=e,t}}},{key:"beforeUpdateHistoryPath",value:function(e){var t=this.getRequestPath();return t&&t!==e?t:e}},{key:"beforeUpdateHistoryState",value:function(e){return e.senna&&e.form&&e.redirectPath===e.path?null:e}},{key:"formatLoadPath",value:function(e){var n=new yt(e);return n.setHostname(tt.window.location.hostname),n.setProtocol(tt.window.location.protocol),tt.window.location.port&&n.setPort(tt.window.location.port),xt.isIeOrEdge&&this.httpMethod===t.GET?n.makeUnique().toString():n.toString()}},{key:"getHttpHeaders",value:function(){return this.httpHeaders}},{key:"getHttpMethod",value:function(){return this.httpMethod}},{key:"getRequestPath",value:function(){var e=this.getRequest();if(e){var n=e.requestPath,r=this.maybeExtractResponseUrlFromRequest(e);return r&&(n=r),xt.isIeOrEdge&&this.httpMethod===t.GET&&(n=new yt(n).removeUnique().toString()),_t.getUrlPath(n)}return null}},{key:"getRequest",value:function(){return this.request}},{key:"getTimeout",value:function(){return this.timeout}},{key:"isValidResponseStatusCode",value:function(e){return e>=200&&e<=399}},{key:"getFormData",value:function(e,t){var n=new FormData(e);return this.maybeAppendSubmitButtonValue_(n,t),n}},{key:"load",value:function(e){var n=this,r=this.getCache();if(re(r))return Lt.resolve(r);var i=null,a=this.httpMethod,o=new ft;Object.keys(this.httpHeaders).forEach(function(e){return o.add(e,n.httpHeaders[e])}),tt.capturedFormElement&&(this.addSafariXHRPolyfill(),i=this.getFormData(tt.capturedFormElement,tt.capturedFormButtonElement),a=t.POST,xt.isIeOrEdge&&o.add("If-None-Match",'"0"'));var s=this.formatLoadPath(e);return Dt.request(s,a,i,o,null,this.timeout).then(function(e){return n.removeSafariXHRPolyfill(),n.setRequest(e),n.assertValidResponseStatusCode(e.status),a===t.GET&&n.isCacheable()&&n.addCache(e.responseText),e.requestPath=s,e.responseText})["catch"](function(e){switch(n.removeSafariXHRPolyfill(),e.message){case Ht.REQUEST_TIMEOUT:e.timeout=!0;break;case Ht.REQUEST_ERROR:e.requestError=!0;break;case Ht.REQUEST_PREMATURE_TERMINATION:e.requestError=!0,e.requestPrematureTermination=!0}throw e})}},{key:"maybeAppendSubmitButtonValue_",value:function(e,t){t&&t.name&&e.append(t.name,t.value)}},{key:"maybeExtractResponseUrlFromRequest",value:function(e){var n=e.responseURL;return n?n:e.getResponseHeader(t.X_REQUEST_URL_HEADER)}},{key:"addSafariXHRPolyfill",value:function(){if(tt.capturedFormElement&&xt.isSafari)for(var e=tt.capturedFormElement.querySelectorAll('input[type="file"]:not([disabled])'),t=0;t0)return;n.setAttribute("data-safari-temp-disabled","true"),n.setAttribute("disabled","")}}},{key:"removeSafariXHRPolyfill",value:function(){if(tt.capturedFormElement&&xt.isSafari)for(var e=tt.capturedFormElement.querySelectorAll('input[type="file"][data-safari-temp-disabled]'),t=0;t/gi,"/senna>");var n=void 0;if(xt.isIe){var r=tt.document.createRange().createContextualFragment(e);n=r.querySelector("senna")}else t.innerHTML=e,n=t.querySelector("senna");n&&(_t.clearNodeAttributes(t),_t.copyNodeAttributes(n,t))}},{key:"disposeInternal",value:function(){this.disposePendingStyles(),Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"disposeInternal",this).call(this)}},{key:"disposePendingStyles",value:function(){this.pendingStyles&&_t.removeElementsFromDocument(this.pendingStyles)}},{key:"evaluateScripts",value:function(e){var n=this,r=this.evaluateTrackedResources_(Ze.runScriptsInElement,t.selectors.scripts,t.selectors.scriptsTemporary,t.selectors.scriptsPermanent);return r.then(function(){return Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"evaluateScripts",n).call(n,e)})}},{key:"evaluateStyles",value:function(e){var n=this;this.pendingStyles=[];var r=this.evaluateTrackedResources_(et.runStylesInElement,t.selectors.styles,t.selectors.stylesTemporary,t.selectors.stylesPermanent,this.appendStyleIntoDocument_.bind(this));return r.then(function(){return Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"evaluateStyles",n).call(n,e)})}},{key:"evaluateFavicon_",value:function(){var e=this,n=this.virtualQuerySelectorAll_(t.selectors.favicon),r=this.querySelectorAll_(t.selectors.favicon);return new Lt(function(t){_t.removeElementsFromDocument(r),e.runFaviconInElement_(n).then(function(){return t()})})}},{key:"evaluateTrackedResources_",value:function(e,n,r,i,a){var o=this,s=this.virtualQuerySelectorAll_(n),u=this.querySelectorAll_(r),l=this.querySelectorAll_(i);l.forEach(function(e){var n=o.getResourceKey_(e);n&&(t.permanentResourcesInDoc[n]=!0)});var c=g();return s.forEach(function(e){var n=o.getResourceKey_(e);t.permanentResourcesInDoc[n]||c.appendChild(e),n&&L(e,i)&&(t.permanentResourcesInDoc[n]=!0)}),new Lt(function(t){e(c,function(){_t.removeElementsFromDocument(u),t()},a)})}},{key:"flip",value:function(e){var n=this;return Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"flip",this).call(this,e).then(function(){_t.clearNodeAttributes(tt.document.documentElement),_t.copyNodeAttributes(n.virtualDocument,tt.document.documentElement),n.evaluateFavicon_(),n.updateMetaTags_()})}},{key:"updateMetaTags_",value:function(){var e=this.querySelectorAll_("meta"),t=this.metas;e&&(_t.removeElementsFromDocument(e),t&&t.forEach(function(e){return tt.document.head.appendChild(e)}))}},{key:"getResourceKey_",value:function(e){return e.id||e.href||e.src||""}},{key:"getSurfaceContent",value:function(e){var t=this.virtualDocument.querySelector("#"+e);if(t){var n=t.querySelector("#"+e+"-"+Ot.DEFAULT);return n?n.innerHTML:t.innerHTML}}},{key:"getTitleSelector",value:function(){return this.titleSelector}},{key:"load",value:function(e){var n=this;return Ne(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"load",this).call(this,e).then(function(e){return n.allocateVirtualDocumentForContent(e),n.resolveTitleFromVirtualDocument(),n.resolveMetaTagsFromVirtualDocument(),n.assertSameBodyIdInVirtualDocument(),xt.isIe&&n.makeTemporaryStylesHrefsUnique_(),e})}},{key:"makeTemporaryStylesHrefsUnique_",value:function(){var e=this,n=this.virtualQuerySelectorAll_(t.selectors.stylesTemporary);n.forEach(function(t){return e.replaceStyleAndMakeUnique_(t)})}},{key:"replaceStyleAndMakeUnique_",value:function(e){if(e.href){var t=tt.document.createElement(e.tagName);e.href=new yt(e.href).makeUnique().toString(),_t.copyNodeAttributes(e,t),e.parentNode.replaceChild(t,e),e.disabled=!0}}},{key:"runFaviconInElement_",value:function(e){return new Lt(function(t){e.forEach(function(e){return document.head.appendChild(xt.isIe?e:_t.setElementWithRandomHref(e))}),t()})}},{key:"virtualQuerySelectorAll_",value:function(e){return Array.prototype.slice.call(this.virtualDocument.querySelectorAll(e))}},{key:"querySelectorAll_",value:function(e){return Array.prototype.slice.call(tt.document.querySelectorAll(e))}},{key:"releaseVirtualDocument",value:function(){this.virtualDocument=null}},{key:"resolveTitleFromVirtualDocument",value:function(){var e=this.virtualDocument.querySelector(this.titleSelector);e&&this.setTitle(e.textContent.trim())}},{key:"resolveMetaTagsFromVirtualDocument",value:function(){var e=this.virtualQuerySelectorAll_(this.metaTagsSelector);e&&this.setMetas(e)}},{key:"setTitleSelector",value:function(e){this.titleSelector=e}}]),t}(Ut),jt=':not([rel="Shortcut Icon"]):not([rel="shortcut icon"]):not([rel="icon"]):not([href$="favicon.icon"])';Ft.selectors={favicon:'link[rel="Shortcut Icon"],link[rel="shortcut icon"],link[rel="icon"],link[href$="favicon.icon"]',scripts:"script[data-senna-track]",scriptsPermanent:'script[data-senna-track="permanent"]',scriptsTemporary:'script[data-senna-track="temporary"]',styles:"style[data-senna-track],link[data-senna-track]"+jt,stylesPermanent:'style[data-senna-track="permanent"],link[data-senna-track="permanent"]'+jt,stylesTemporary:'style[data-senna-track="temporary"],link[data-senna-track="temporary"]'+jt},Ft.permanentResourcesInDoc={};var Mt=function(e){function t(){Re(this,t);var e=De(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.app=null,e.baseElement=null,e}return Ie(t,e),Oe(t,[{key:"handle",value:function(){if(!oe(this.baseElement))throw new Error("Senna data attribute handler base element not set or invalid, try setting a valid element that contains a `data-senna` attribute.");if(this.baseElement.hasAttribute(gt.senna)){if(this.app)throw new Error("Senna app was already initialized.");this.app=new It,this.maybeAddRoutes_(),this.maybeAddSurfaces_(),this.maybeSetBasePath_(),this.maybeSetLinkSelector_(),this.maybeSetLoadingCssClass_(),this.maybeSetUpdateScrollPosition_(),this.maybeDispatch_()}}},{key:"disposeInternal",value:function(){this.app&&this.app.dispose()}},{key:"getApp",value:function(){return this.app}},{key:"getBaseElement",value:function(){return this.baseElement}},{key:"maybeAddRoutes_",value:function(){var e=this,t='link[rel="senna-route"]';this.querySelectorAllAsArray_(t).forEach(function(t){return e.maybeParseLinkRoute_(t)}),this.app.hasRoutes()||this.app.addRoutes(new At(/.*/,Ft))}},{key:"maybeAddSurfaces_",value:function(){var e=this,t="["+gt.surface+"]";this.querySelectorAllAsArray_(t).forEach(function(t){e.updateElementIdIfSpecialSurface_(t),e.app.addSurfaces(t.id)})}},{key:"maybeDispatch_",value:function(){this.baseElement.hasAttribute(gt.dispatch)&&this.app.dispatch()}},{key:"maybeParseLinkRoute_",value:function(e){var t=new At(this.maybeParseLinkRoutePath_(e),this.maybeParseLinkRouteHandler_(e));this.app.addRoutes(t)}},{key:"maybeParseLinkRouteHandler_",value:function(e){var t=e.getAttribute("type");return re(t)&&(t=lt.getObjectByName(t)),t}},{key:"maybeParseLinkRoutePath_",value:function(e){var t=e.getAttribute("href");return re(t)&&0===t.indexOf("regex:")&&(t=new RegExp(t.substring(6))),t}},{key:"maybeSetBasePath_",value:function(){var e=this.baseElement.getAttribute(gt.basePath);re(e)&&this.app.setBasePath(e)}},{key:"maybeSetLinkSelector_",value:function(){var e=this.baseElement.getAttribute(gt.linkSelector);re(e)&&this.app.setLinkSelector(e)}},{key:"maybeSetLoadingCssClass_",value:function(){var e=this.baseElement.getAttribute(gt.loadingCssClass);re(e)&&this.app.setLoadingCssClass(e)}},{key:"maybeSetUpdateScrollPosition_",value:function(){var e=this.baseElement.getAttribute(gt.updateScrollPosition);re(e)&&("false"===e?this.app.setUpdateScrollPosition(!1):this.app.setUpdateScrollPosition(!0))}},{key:"querySelectorAllAsArray_",value:function(e){return Array.prototype.slice.call(tt.document.querySelectorAll(e))}},{key:"updateElementIdIfSpecialSurface_",value:function(e){e.id||e!==tt.document.body||(e.id="senna_surface_"+Z())}},{key:"setBaseElement",value:function(e){this.baseElement=e}}]),t}(ut),qt=new Mt;tt.document.addEventListener("DOMContentLoaded",function(){qt.setBaseElement(tt.document.body),qt.handle()});var Bt="2.7.9";e["default"]=It,e.dataAttributeHandler=qt,e.utils=_t,e.App=It,e.HtmlScreen=Ft,e.Route=At,e.RequestScreen=Ut,e.Screen=Rt,e.version=Bt,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/build/globals/senna.js b/build/globals/senna.js index 7a56c98..0857772 100644 --- a/build/globals/senna.js +++ b/build/globals/senna.js @@ -1,7 +1,7 @@ /** * Senna.js - A blazing-fast Single Page Application engine * @author Liferay, Inc. - * @version v2.7.8 + * @version v2.7.9 * @link http://sennajs.com * @license BSD-3-Clause */ @@ -9804,6 +9804,8 @@ var App$1 = function (_EventEmitter) { title = this.getDefaultTitle(); } var redirectPath = nextScreen.beforeUpdateHistoryPath(path); + var hash = new Uri(path).getHash(); + redirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash); var historyState = { form: isDefAndNotNull$1(globals.capturedFormElement), path: path, @@ -9816,8 +9818,6 @@ var App$1 = function (_EventEmitter) { historyState.scrollTop = this.popstateScrollTop; historyState.scrollLeft = this.popstateScrollLeft; } - var hash = new Uri(path).getHash(); - redirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash); this.updateHistory_(title, redirectPath, nextScreen.beforeUpdateHistoryState(historyState), opt_replaceHistory); this.redirectPath = redirectPath; } @@ -11699,7 +11699,7 @@ globals.document.addEventListener('DOMContentLoaded', function () { * @returns String containing the current senna version */ -var version = '2.7.8'; +var version = '2.7.9'; exports['default'] = App$1; exports.dataAttributeHandler = dataAttributeHandler; diff --git a/build/globals/senna.js.map b/build/globals/senna.js.map index 27a6372..38f5209 100644 --- a/build/globals/senna.js.map +++ b/build/globals/senna.js.map @@ -1 +1 @@ -{"version":3,"file":"senna.js","sources":["node_modules/metal-dom/node_modules/metal/src/coreNamed.js","node_modules/metal-dom/node_modules/metal/src/core.js","node_modules/metal-dom/node_modules/metal/src/array/array.js","node_modules/metal-dom/node_modules/metal/src/async/async.js","node_modules/metal-dom/node_modules/metal/src/disposable/Disposable.js","node_modules/metal-dom/node_modules/metal/src/object/object.js","node_modules/metal-dom/node_modules/metal/src/string/string.js","node_modules/metal-dom/src/domData.js","node_modules/metal-dom/node_modules/metal-events/src/EventHandle.js","node_modules/metal-dom/node_modules/metal-events/src/EventEmitter.js","node_modules/metal-dom/node_modules/metal-events/src/EventEmitterProxy.js","node_modules/metal-dom/node_modules/metal-events/src/EventHandler.js","node_modules/metal-dom/src/DomDelegatedEventHandle.js","node_modules/metal-dom/src/DomEventHandle.js","node_modules/metal-dom/src/domNamed.js","node_modules/metal-dom/src/dom.js","node_modules/metal-dom/src/DomEventEmitterProxy.js","node_modules/metal-dom/src/features.js","node_modules/metal-dom/src/globalEval.js","node_modules/metal-dom/src/globalEvalStyles.js","node_modules/metal-dom/src/events.js","src/globals/globals.js","node_modules/metal/src/coreNamed.js","node_modules/metal/src/core.js","node_modules/metal/src/array/array.js","node_modules/metal/src/async/async.js","node_modules/metal/src/disposable/Disposable.js","node_modules/metal/src/object/object.js","node_modules/metal/src/string/string.js","node_modules/metal-uri/src/parseFromAnchor.js","node_modules/metal-uri/src/parse.js","node_modules/metal-structs/src/MultiMap.js","node_modules/metal-structs/src/TreeNode.js","node_modules/metal-uri/src/Uri.js","src/utils/utils.js","src/app/dataAttributes.js","node_modules/metal-events/src/EventHandle.js","node_modules/metal-events/src/EventEmitter.js","node_modules/metal-events/src/EventEmitterProxy.js","node_modules/metal-events/src/EventHandler.js","node_modules/metal-promise/src/promise/Promise.js","node_modules/metal-debounce/src/debounce.js","node_modules/metal-path-parser/src/pathParser.js","src/route/Route.js","src/cacheable/Cacheable.js","src/screen/Screen.js","src/surface/Surface.js","src/app/App.js","node_modules/metal-ajax/src/Ajax.js","src/errors/errors.js","node_modules/metal-useragent/src/UA.js","src/screen/RequestScreen.js","src/screen/HtmlScreen.js","src/app/AppDataAttributeHandler.js","src/app/dataAttributeHandler.js","src/app/version.js"],"sourcesContent":["'use strict';\n\n/**\n * A collection of core utility functions.\n * @const\n */\n\nlet compatibilityModeData_;\n\n/**\n * Counter for unique id.\n * @type {Number}\n * @private\n */\nlet uniqueIdCounter_ = 1;\n\n/**\n * Unique id property prefix.\n * @type {String}\n * @protected\n */\nexport const UID_PROPERTY = `core_${(Math.random() * 1e9) >>> 0}`;\n\n/**\n * When defining a class Foo with an abstract method bar(), you can do:\n * Foo.prototype.bar = abstractMethod\n *\n * Now if a subclass of Foo fails to override bar(), an error will be thrown\n * when bar() is invoked.\n *\n * @type {!Function}\n * @throws {Error} when invoked to indicate the method should be overridden.\n */\nexport function abstractMethod() {\n\tthrow Error('Unimplemented abstract method');\n}\n\n/**\n * Disables Metal.js's compatibility mode.\n */\nexport function disableCompatibilityMode() {\n\tcompatibilityModeData_ = undefined;\n}\n\n/**\n * Enables Metal.js's compatibility mode with the following features from rc\n * and 1.x versions:\n * - Using \"key\" to reference component instances. In the current version\n * this should be done via \"ref\" instead. This allows old code still\n * using \"key\" to keep working like before. NOTE: this may cause\n * problems, since \"key\" is meant to be used differently. Only use this\n * if it's not possible to upgrade the code to use \"ref\" instead.\n * @param {Object=} data Optional object with data to specify more\n * details, such as:\n * - renderers {Array} the template renderers that should be in\n * compatibility mode, either their constructors or strings\n * representing them (e.g. 'soy' or 'jsx'). By default, all the ones\n * that extend from IncrementalDomRenderer.\n * @type {Object}\n */\nexport function enableCompatibilityMode(data = {}) {\n\tcompatibilityModeData_ = data;\n}\n\n/**\n * Returns the data used for compatibility mode, or nothing if it hasn't been\n * enabled.\n * @return {Object}\n */\nexport function getCompatibilityModeData() {\n\t// Compatibility mode can be set via the __METAL_COMPATIBILITY__ global var.\n\tif (compatibilityModeData_ === undefined) {\n\t\tif (typeof window !== 'undefined' && window.__METAL_COMPATIBILITY__) {\n\t\t\tenableCompatibilityMode(window.__METAL_COMPATIBILITY__);\n\t\t}\n\t}\n\treturn compatibilityModeData_;\n}\n\n/**\n * Returns the first argument if it's truthy, or the second otherwise.\n * @param {*} a\n * @param {*} b\n * @return {*}\n * @protected\n */\nfunction getFirstTruthy_(a, b) {\n\treturn a || b;\n}\n\n/**\n * Gets the name of the given function. If the current browser doesn't\n * support the `name` property, like IE11, this will calculate it from the function's\n * content string.\n * @param {!function()} fn\n * @return {string}\n */\nexport function getFunctionName(fn) {\n\tif (!fn.name) {\n\t\tconst str = fn.toString();\n\t\tfn.name = str.substring(9, str.indexOf('('));\n\t}\n\treturn fn.name;\n}\n\n/**\n * Gets the value of a static property in the given class. The value will be\n * inherited from ancestors as expected, unless a custom merge function is given,\n * which can change how the super classes' value for that property will be merged\n * together.\n * The final merged value will be stored in another property, so that it won't\n * be recalculated even if this function is called multiple times.\n * @param {!function()} ctor Class constructor.\n * @param {string} propertyName Property name to be merged.\n * @param {function(*, *):*=} mergeFn Function that receives the merged\n * value of the property so far and the next value to be merged to it.\n * Should return these two merged together. If not passed the final property\n * will be the first truthy value among ancestors.\n * @return {Object}\n */\nexport function getStaticProperty(\n\tctor,\n\tpropertyName,\n\tmergeFn = getFirstTruthy_\n) {\n\tconst mergedName = propertyName + '_MERGED';\n\tif (!ctor.hasOwnProperty(mergedName)) {\n\t\t// eslint-disable-next-line\n\t\tlet merged = ctor.hasOwnProperty(propertyName)\n\t\t\t? ctor[propertyName]\n\t\t\t: null;\n\t\tif (ctor.__proto__ && !ctor.__proto__.isPrototypeOf(Function)) {\n\t\t\tmerged = mergeFn(\n\t\t\t\tmerged,\n\t\t\t\tgetStaticProperty(ctor.__proto__, propertyName, mergeFn)\n\t\t\t);\n\t\t}\n\t\tctor[mergedName] = merged;\n\t}\n\treturn ctor[mergedName];\n}\n\n/**\n * Gets an unique id. If `object` argument is passed, the object is\n * mutated with an unique id. Consecutive calls with the same object\n * reference won't mutate the object again, instead the current object uid\n * returns. See {@link UID_PROPERTY}.\n * @param {Object=} object Optional object to be mutated with the uid. If\n * not specified this method only returns the uid.\n * @param {boolean=} noInheritance Optional flag indicating if this\n * object's uid property can be inherited from parents or not.\n * @throws {Error} when invoked to indicate the method should be overridden.\n * @return {number}\n */\nexport function getUid(object, noInheritance) {\n\tif (object) {\n\t\tlet id = object[UID_PROPERTY];\n\t\tif (noInheritance && !object.hasOwnProperty(UID_PROPERTY)) {\n\t\t\tid = null;\n\t\t}\n\t\treturn id || (object[UID_PROPERTY] = uniqueIdCounter_++);\n\t}\n\treturn uniqueIdCounter_++;\n}\n\n/**\n * The identity function. Returns its first argument.\n * @param {*=} returnValue The single value that will be returned.\n * @return {?} The first argument.\n */\nexport function identityFunction(returnValue) {\n\treturn returnValue;\n}\n\n/**\n * Returns true if the specified value is a boolean.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is boolean.\n */\nexport function isBoolean(val) {\n\treturn typeof val === 'boolean';\n}\n\n/**\n * Returns true if the specified value is not undefined.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is defined.\n */\nexport function isDef(val) {\n\treturn val !== undefined;\n}\n\n/**\n * Returns true if value is not undefined or null.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDefAndNotNull(val) {\n\treturn isDef(val) && !isNull(val);\n}\n\n/**\n * Returns true if value is a document.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDocument(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 9;\n}\n\n/**\n * Returns true if value is a document-fragment.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDocumentFragment(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 11;\n}\n\n/**\n * Returns true if value is a dom element.\n * @param {*} val\n * @return {boolean}\n */\nexport function isElement(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 1;\n}\n\n/**\n * Returns true if the specified value is a function.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is a function.\n */\nexport function isFunction(val) {\n\treturn typeof val === 'function';\n}\n\n/**\n * Returns true if value is null.\n * @param {*} val\n * @return {boolean}\n */\nexport function isNull(val) {\n\treturn val === null;\n}\n\n/**\n * Returns true if the specified value is a number.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is a number.\n */\nexport function isNumber(val) {\n\treturn typeof val === 'number';\n}\n\n/**\n * Returns true if value is a window.\n * @param {*} val\n * @return {boolean}\n */\nexport function isWindow(val) {\n\treturn val !== null && val === val.window;\n}\n\n/**\n * Returns true if the specified value is an object. This includes arrays\n * and functions.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is an object.\n */\nexport function isObject(val) {\n\tconst type = typeof val;\n\treturn (type === 'object' && val !== null) || type === 'function';\n}\n\n/**\n * Returns true if value is a Promise.\n * @param {*} val\n * @return {boolean}\n */\nexport function isPromise(val) {\n\treturn val && typeof val === 'object' && typeof val.then === 'function';\n}\n\n/**\n * Returns true if value is a string.\n * @param {*} val\n * @return {boolean}\n */\nexport function isString(val) {\n\treturn typeof val === 'string' || val instanceof String;\n}\n\n/**\n * Sets to true if running inside Node.js environment with extra check for\n * `process.browser` to skip Karma runner environment. Karma environment has\n * `process` defined even though it runs on the browser.\n * @param {?Object} options Contains `checkEnv` property which if true, checks\n * the NODE_ENV variable. If NODE_ENV equals 'test', the function returns false.\n * @return {boolean}\n */\nexport function isServerSide(options = {checkEnv: true}) {\n\tlet serverSide = typeof process !== 'undefined' && !process.browser;\n\tif (serverSide && options.checkEnv) {\n\t\tserverSide =\n\t\t\ttypeof process.env !== 'undefined' &&\n\t\t\tprocess.env.NODE_ENV !== 'test';\n\t}\n\treturn serverSide;\n}\n\n/**\n * Null function used for default values of callbacks, etc.\n * @return {void} Nothing.\n */\nexport function nullFunction() {}\n","'use strict';\n\n// This file exists just for backwards compatibility, making sure that old\n// default imports for this file still work. It's best to use the named exports\n// for each function instead though, since that allows bundlers like Rollup to\n// reduce the bundle size by removing unused code.\nimport * as core from './coreNamed';\n\nexport default core;\nexport {core};\nexport * from './coreNamed';\n","'use strict';\n\n/**\n * Set of utilities for array operations\n */\nclass array {\n\t/**\n\t * Checks if the given arrays have the same content.\n\t * @param {!Array<*>} arr1\n\t * @param {!Array<*>} arr2\n\t * @return {boolean}\n\t */\n\tstatic equal(arr1, arr2) {\n\t\tif (arr1 === arr2) {\n\t\t\treturn true;\n\t\t}\n\t\tif (arr1.length !== arr2.length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0; i < arr1.length; i++) {\n\t\t\tif (arr1[i] !== arr2[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns the first value in the given array that isn't undefined.\n\t * @param {!Array} arr\n\t * @return {*}\n\t */\n\tstatic firstDefinedValue(arr) {\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tif (arr[i] !== undefined) {\n\t\t\t\treturn arr[i];\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Transforms the input nested array to become flat.\n\t * @param {Array.<*|Array.<*>>} arr Nested array to flatten.\n\t * @param {Array.<*>=} output Optional output array.\n\t * @return {Array.<*>} Flat array.\n\t */\n\tstatic flatten(arr, output = []) {\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tif (Array.isArray(arr[i])) {\n\t\t\t\tarray.flatten(arr[i], output);\n\t\t\t} else {\n\t\t\t\toutput.push(arr[i]);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Removes the first occurrence of a particular value from an array.\n\t * @param {Array.} arr Array from which to remove value.\n\t * @param {T} obj Object to remove.\n\t * @return {boolean} True if an element was removed.\n\t * @template T\n\t */\n\tstatic remove(arr, obj) {\n\t\tconst i = arr.indexOf(obj);\n\t\tlet rv;\n\t\tif ((rv = i >= 0)) {\n\t\t\tarray.removeAt(arr, i);\n\t\t}\n\t\treturn rv;\n\t}\n\n\t/**\n\t * Removes from an array the element at index i\n\t * @param {Array} arr Array or array like object from which to remove value.\n\t * @param {number} i The index to remove.\n\t * @return {boolean} True if an element was removed.\n\t */\n\tstatic removeAt(arr, i) {\n\t\treturn Array.prototype.splice.call(arr, i, 1).length === 1;\n\t}\n\n\t/**\n\t * Slices the given array, just like Array.prototype.slice, but this\n\t * is faster and working on all array-like objects (like arguments).\n\t * @param {!Object} arr Array-like object to slice.\n\t * @param {number} start The index that should start the slice.\n\t * @param {number=} end The index where the slice should end, not\n\t * included in the final array. If not given, all elements after the\n\t * start index will be included.\n\t * @return {!Array}\n\t */\n\tstatic slice(arr, start, end = arr.length) {\n\t\tconst sliced = [];\n\t\tfor (let i = start; i < end; i++) {\n\t\t\tsliced.push(arr[i]);\n\t\t}\n\t\treturn sliced;\n\t}\n}\n\nexport default array;\n","/* !\n * Polyfill from Google's Closure Library.\n * Copyright 2013 The Closure Library Authors. All Rights Reserved.\n */\n\n'use strict';\n\nimport {isServerSide} from '../coreNamed';\n\nconst async = {};\n\n/**\n * Throw an item without interrupting the current execution context. For\n * example, if processing a group of items in a loop, sometimes it is useful\n * to report an error while still allowing the rest of the batch to be\n * processed.\n * @param {*} exception\n */\nasync.throwException = function(exception) {\n\t// Each throw needs to be in its own context.\n\tasync.nextTick(function() {\n\t\tthrow exception;\n\t});\n};\n\n/**\n * Fires the provided callback just before the current callstack unwinds, or as\n * soon as possible after the current JS execution context.\n * @param {function(this:THIS)} callback\n * @param {THIS=} context Object to use as the \"this value\" when calling\n * the provided function.\n * @template THIS\n */\nasync.run = function(callback, context) {\n\tif (!async.run.workQueueScheduled_) {\n\t\t// Nothing is currently scheduled, schedule it now.\n\t\tasync.nextTick(async.run.processWorkQueue);\n\t\tasync.run.workQueueScheduled_ = true;\n\t}\n\n\tasync.run.workQueue_.push(new async.run.WorkItem_(callback, context));\n};\n\n/** @private {boolean} */\nasync.run.workQueueScheduled_ = false;\n\n/** @private {!Array.} */\nasync.run.workQueue_ = [];\n\n/**\n * Run any pending async.run work items. This function is not intended\n * for general use, but for use by entry point handlers to run items ahead of\n * async.nextTick.\n */\nasync.run.processWorkQueue = function() {\n\t// NOTE: additional work queue items may be pushed while processing.\n\twhile (async.run.workQueue_.length) {\n\t\t// Don't let the work queue grow indefinitely.\n\t\tconst workItems = async.run.workQueue_;\n\t\tasync.run.workQueue_ = [];\n\t\tfor (let i = 0; i < workItems.length; i++) {\n\t\t\tconst workItem = workItems[i];\n\t\t\ttry {\n\t\t\t\tworkItem.fn.call(workItem.scope);\n\t\t\t} catch (e) {\n\t\t\t\tasync.throwException(e);\n\t\t\t}\n\t\t}\n\t}\n\n\t// There are no more work items, reset the work queue.\n\tasync.run.workQueueScheduled_ = false;\n};\n\n/**\n * @constructor\n * @final\n * @struct\n * @private\n *\n * @param {function()} fn\n * @param {Object|null|undefined} scope\n */\nasync.run.WorkItem_ = function(fn, scope) {\n\t/** @const */\n\tthis.fn = fn;\n\t/** @const */\n\tthis.scope = scope;\n};\n\n/**\n * Fires the provided callbacks as soon as possible after the current JS\n * execution context. setTimeout(…, 0) always takes at least 5ms for legacy\n * reasons.\n * @param {function(this:SCOPE)} callback Callback function to fire as soon as\n * possible.\n * @param {SCOPE=} context Object in whose scope to call the listener.\n * @template SCOPE\n */\nasync.nextTick = function(callback, context) {\n\tlet cb = callback;\n\tif (context) {\n\t\tcb = callback.bind(context);\n\t}\n\tcb = async.nextTick.wrapCallback_(cb);\n\t// Look for and cache the custom fallback version of setImmediate.\n\tif (!async.nextTick.setImmediate_) {\n\t\tif (\n\t\t\ttypeof setImmediate === 'function' &&\n\t\t\tisServerSide({checkEnv: false})\n\t\t) {\n\t\t\tasync.nextTick.setImmediate_ = setImmediate;\n\t\t} else {\n\t\t\t// eslint-disable-next-line\n\t\t\tasync.nextTick.setImmediate_ = async.nextTick.getSetImmediateEmulator_();\n\t\t}\n\t}\n\tasync.nextTick.setImmediate_(cb);\n};\n\n/**\n * Cache for the setImmediate implementation.\n * @type {function(function())}\n * @private\n */\nasync.nextTick.setImmediate_ = null;\n\n/**\n * Determines the best possible implementation to run a function as soon as\n * the JS event loop is idle.\n * @return {function(function())} The \"setImmediate\" implementation.\n * @private\n */\nasync.nextTick.getSetImmediateEmulator_ = function() {\n\t// Create a private message channel and use it to postMessage empty messages\n\t// to ourselves.\n\tlet Channel;\n\n\t// Verify if variable is defined on the current runtime (i.e., node, browser).\n\t// Can't use typeof enclosed in a function (such as core.isFunction) or an\n\t// exception will be thrown when the function is called on an environment\n\t// where the variable is undefined.\n\tif (typeof MessageChannel === 'function') {\n\t\tChannel = MessageChannel;\n\t}\n\n\t// If MessageChannel is not available and we are in a browser, implement\n\t// an iframe based polyfill in browsers that have postMessage and\n\t// document.addEventListener. The latter excludes IE8 because it has a\n\t// synchronous postMessage implementation.\n\tif (\n\t\ttypeof Channel === 'undefined' &&\n\t\ttypeof window !== 'undefined' &&\n\t\twindow.postMessage &&\n\t\twindow.addEventListener\n\t) {\n\t\t/** @constructor */\n\t\tChannel = function() {\n\t\t\t// Make an empty, invisible iframe.\n\t\t\tconst iframe = document.createElement('iframe');\n\t\t\tiframe.style.display = 'none';\n\t\t\tiframe.src = '';\n\t\t\tiframe.title = '';\n\t\t\tdocument.documentElement.appendChild(iframe);\n\t\t\tconst win = iframe.contentWindow;\n\t\t\tconst doc = win.document;\n\t\t\tdoc.open();\n\t\t\tdoc.write('');\n\t\t\tdoc.close();\n\t\t\tconst message = 'callImmediate' + Math.random();\n\t\t\tconst origin = win.location.protocol + '//' + win.location.host;\n\t\t\tconst onmessage = function(e) {\n\t\t\t\t// Validate origin and message to make sure that this message was\n\t\t\t\t// intended for us.\n\t\t\t\tif (e.origin !== origin && e.data !== message) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.port1.onmessage();\n\t\t\t}.bind(this);\n\t\t\twin.addEventListener('message', onmessage, false);\n\t\t\tthis.port1 = {};\n\t\t\tthis.port2 = {\n\t\t\t\tpostMessage: function() {\n\t\t\t\t\twin.postMessage(message, origin);\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\t}\n\tif (typeof Channel !== 'undefined') {\n\t\tconst channel = new Channel();\n\t\t// Use a fifo linked list to call callbacks in the right order.\n\t\tlet head = {};\n\t\tlet tail = head;\n\t\tchannel.port1.onmessage = function() {\n\t\t\thead = head.next;\n\t\t\tconst cb = head.cb;\n\t\t\thead.cb = null;\n\t\t\tcb();\n\t\t};\n\t\treturn function(cb) {\n\t\t\ttail.next = {\n\t\t\t\tcb: cb,\n\t\t\t};\n\t\t\ttail = tail.next;\n\t\t\tchannel.port2.postMessage(0);\n\t\t};\n\t}\n\t// Implementation for IE6-8: Script elements fire an asynchronous\n\t// onreadystatechange event when inserted into the DOM.\n\tif (\n\t\ttypeof document !== 'undefined' &&\n\t\t'onreadystatechange' in document.createElement('script')\n\t) {\n\t\treturn function(cb) {\n\t\t\tlet script = document.createElement('script');\n\t\t\tscript.onreadystatechange = function() {\n\t\t\t\t// Clean up and call the callback.\n\t\t\t\tscript.onreadystatechange = null;\n\t\t\t\tscript.parentNode.removeChild(script);\n\t\t\t\tscript = null;\n\t\t\t\tcb();\n\t\t\t\tcb = null;\n\t\t\t};\n\t\t\tdocument.documentElement.appendChild(script);\n\t\t};\n\t}\n\t// Fall back to setTimeout with 0. In browsers this creates a delay of 5ms\n\t// or more.\n\treturn function(cb) {\n\t\tsetTimeout(cb, 0);\n\t};\n};\n\n/**\n * Helper function that is overrided to protect callbacks with entry point\n * monitor if the application monitors entry points.\n * @param {function()} callback Callback function to fire as soon as possible.\n * @return {function()} The wrapped callback.\n * @private\n */\nasync.nextTick.wrapCallback_ = function(callback) {\n\treturn callback;\n};\n\nexport default async;\n","'use strict';\n\n/**\n * Disposable utility. When inherited provides the `dispose` function to its\n * subclass, which is responsible for disposing of any object references\n * when an instance won't be used anymore. Subclasses should override\n * `disposeInternal` to implement any specific disposing logic.\n * @constructor\n */\nclass Disposable {\n\t/**\n\t * Disposable constructor\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Flag indicating if this instance has already been disposed.\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.disposed_ = false;\n\t}\n\n\t/**\n\t * Disposes of this instance's object references. Calls `disposeInternal`.\n\t */\n\tdispose() {\n\t\tif (!this.disposed_) {\n\t\t\tthis.disposeInternal();\n\t\t\tthis.disposed_ = true;\n\t\t}\n\t}\n\n\t/**\n\t * Subclasses should override this method to implement any specific\n\t * disposing logic (like clearing references and calling `dispose` on other\n\t * disposables).\n\t */\n\tdisposeInternal() {}\n\n\t/**\n\t * Checks if this instance has already been disposed.\n\t * @return {boolean}\n\t */\n\tisDisposed() {\n\t\treturn this.disposed_;\n\t}\n}\n\nexport default Disposable;\n","'use strict';\n\n/**\n * Set of utilities for object operations\n */\nclass object {\n\t/**\n\t * Copies all the members of a source object to a target object.\n\t * @param {Object} target Target object.\n\t * @param {...Object} var_args The objects from which values will be copied.\n\t * @return {Object} Returns the target object reference.\n\t */\n\tstatic mixin(target, ...args) {\n\t\tlet key;\n\t\tlet source;\n\t\tfor (let i = 0; i < args.length; i++) {\n\t\t\tsource = args[i];\n\t\t\t// Possible prototype chain leak, breaks 1 metal-dom and\n\t\t\t// 1 metal-incremental-dom test if guard-for-in rule is addressed\n\t\t\t// eslint-disable-next-line\n\t\t\tfor (key in source) {\n\t\t\t\ttarget[key] = source[key];\n\t\t\t}\n\t\t}\n\t\treturn target;\n\t}\n\n\t/**\n\t * Returns an object based on its fully qualified external name.\n\t * @param {string} name The fully qualified name.\n\t * @param {object=} scope The object within which to look; default is\n\t * window.\n\t * @return {?} The value (object or primitive) or, if not found, undefined.\n\t */\n\tstatic getObjectByName(name, scope = window) {\n\t\tconst parts = name.split('.');\n\t\treturn parts.reduce((part, key) => part[key], scope);\n\t}\n\n\t/**\n\t * Returns a new object with the same keys as the given one, but with\n\t * their values set to the return values of the specified function.\n\t * @param {!Object} obj\n\t * @param {!function(string, *)} fn\n\t * @return {!Object}\n\t */\n\tstatic map(obj, fn) {\n\t\tconst mappedObj = {};\n\t\tconst keys = Object.keys(obj);\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tmappedObj[keys[i]] = fn(keys[i], obj[keys[i]]);\n\t\t}\n\t\treturn mappedObj;\n\t}\n\n\t/**\n\t * Checks if the two given objects are equal. This is done via a shallow\n\t * check, including only the keys directly contained by the 2 objects.\n\t * @param {Object} obj1\n\t * @param {Object} obj2\n\t * @return {boolean}\n\t */\n\tstatic shallowEqual(obj1, obj2) {\n\t\tif (obj1 === obj2) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst keys1 = Object.keys(obj1);\n\t\tconst keys2 = Object.keys(obj2);\n\t\tif (keys1.length !== keys2.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < keys1.length; i++) {\n\t\t\tif (obj1[keys1[i]] !== obj2[keys1[i]]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\n\nexport default object;\n","'use strict';\n\n/**\n * Set of utilities for string operations\n */\nclass string {\n\t/**\n\t * Compares the given strings without taking the case into account.\n\t * @param {string|number} str1\n\t * @param {string|number} str2\n\t * @return {number} Either -1, 0 or 1, according to if the first string is\n\t * \"smaller\", equal or \"bigger\" than the second given string.\n\t */\n\tstatic caseInsensitiveCompare(str1, str2) {\n\t\tconst test1 = String(str1).toLowerCase();\n\t\tconst test2 = String(str2).toLowerCase();\n\n\t\tif (test1 < test2) {\n\t\t\treturn -1;\n\t\t} else if (test1 === test2) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\t/**\n\t * Removes the breaking spaces from the left and right of the string and\n\t * collapses the sequences of breaking spaces in the middle into single spaces.\n\t * The original and the result strings render the same way in HTML.\n\t * @param {string} str A string in which to collapse spaces.\n\t * @return {string} Copy of the string with normalized breaking spaces.\n\t */\n\tstatic collapseBreakingSpaces(str) {\n\t\treturn str\n\t\t\t.replace(/[\\t\\r\\n ]+/g, ' ')\n\t\t\t.replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g, '');\n\t}\n\n\t/**\n\t * Escapes characters in the string that are not safe to use in a RegExp.\n\t * @param {*} str The string to escape. If not a string, it will be casted\n\t * to one.\n\t * @return {string} A RegExp safe, escaped copy of {@code s}.\n\t */\n\tstatic escapeRegex(str) {\n\t\treturn String(str)\n\t\t\t.replace(/([-()[\\]{}+?*.$^|,:#>}\n\t\t * @protected\n\t\t */\n\t\tthis.events_ = null;\n\n\t\t/**\n\t\t * Handlers that are triggered when an event is listened to.\n\t\t * @type {Array}\n\t\t */\n\t\tthis.listenerHandlers_ = null;\n\n\t\t/**\n\t\t * Configuration option which determines if an event facade should be sent\n\t\t * as a param of listeners when emitting events. If set to true, the facade\n\t\t * will be passed as the first argument of the listener.\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.shouldUseFacade_ = false;\n\t}\n\n\t/**\n\t * Adds a handler to given holder variable. If the holder doesn't have a\n\t * value yet, it will receive the handler directly. If the holder is an array,\n\t * the value will just be added to it. Otherwise, the holder will be set to a\n\t * new array containing its previous value plus the new handler.\n\t * @param {*} holder\n\t * @param {!function()|Object} handler\n\t * @return {*} The holder's new value.\n\t * @protected\n\t */\n\taddHandler_(holder, handler) {\n\t\tif (!holder) {\n\t\t\tholder = handler;\n\t\t} else {\n\t\t\tif (!Array.isArray(holder)) {\n\t\t\t\tholder = [holder];\n\t\t\t}\n\t\t\tholder.push(handler);\n\t\t}\n\t\treturn holder;\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for the specified events.\n\t * @param {!(Array|string)} event\n\t * @param {!Function} listener\n\t * @param {boolean} defaultListener Flag indicating if this listener is a default\n\t * action for this event. Default actions are run last, and only if no previous\n\t * listener call `preventDefault()` on the received event facade.\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\taddListener(event, listener, defaultListener) {\n\t\tthis.validateListener_(listener);\n\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.addSingleListener_(events[i], listener, defaultListener);\n\t\t}\n\n\t\treturn new EventHandle(this, event, listener);\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for a single event.\n\t * @param {string} event\n\t * @param {!Function} listener\n\t * @param {boolean} defaultListener Flag indicating if this listener is a default\n\t * action for this event. Default actions are run last, and only if no previous\n\t * listener call `preventDefault()` on the received event facade.\n\t * @param {Function=} origin The original function that was added as a\n\t * listener, if there is any.\n\t * @protected\n\t */\n\taddSingleListener_(event, listener, defaultListener, origin) {\n\t\tthis.runListenerHandlers_(event);\n\t\tif (defaultListener || origin) {\n\t\t\tlistener = {\n\t\t\t\tdefault: defaultListener,\n\t\t\t\tfn: listener,\n\t\t\t\torigin: origin,\n\t\t\t};\n\t\t}\n\t\tthis.events_ = this.events_ || {};\n\t\tthis.events_[event] = this.addHandler_(this.events_[event], listener);\n\t}\n\n\t/**\n\t * Builds facade for the given event.\n\t * @param {string} event\n\t * @return {Object}\n\t * @protected\n\t */\n\tbuildFacade_(event) {\n\t\tif (this.getShouldUseFacade()) {\n\t\t\tconst facade = {\n\t\t\t\tpreventDefault: function() {\n\t\t\t\t\tfacade.preventedDefault = true;\n\t\t\t\t},\n\t\t\t\ttarget: this,\n\t\t\t\ttype: event,\n\t\t\t};\n\t\t\treturn facade;\n\t\t}\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.events_ = null;\n\t}\n\n\t/**\n\t * Execute each of the listeners in order with the supplied arguments.\n\t * @param {string} event\n\t * @param {*} opt_args [arg1], [arg2], [...]\n\t * @return {boolean} Returns true if event had listeners, false otherwise.\n\t */\n\temit(event) {\n\t\tconst listeners = this.getRawListeners_(event);\n\t\tif (listeners.length === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst args = array.slice(arguments, 1); // eslint-disable-line\n\t\tthis.runListeners_(listeners, args, this.buildFacade_(event));\n\t\treturn true;\n\t}\n\n\t/**\n\t * Gets the listener objects for the given event, if there are any.\n\t * @param {string} event\n\t * @return {!Array}\n\t * @protected\n\t */\n\tgetRawListeners_(event) {\n\t\tconst directListeners = toArray(this.events_ && this.events_[event]);\n\t\treturn directListeners.concat(\n\t\t\ttoArray(this.events_ && this.events_['*'])\n\t\t);\n\t}\n\n\t/**\n\t * Gets the configuration option which determines if an event facade should\n\t * be sent as a param of listeners when emitting events. If set to true, the\n\t * facade will be passed as the first argument of the listener.\n\t * @return {boolean}\n\t */\n\tgetShouldUseFacade() {\n\t\treturn this.shouldUseFacade_;\n\t}\n\n\t/**\n\t * Returns an array of listeners for the specified event.\n\t * @param {string} event\n\t * @return {Array} Array of listeners.\n\t */\n\tlisteners(event) {\n\t\treturn this.getRawListeners_(event).map(\n\t\t\tlistener => (listener.fn ? listener.fn : listener)\n\t\t);\n\t}\n\n\t/**\n\t * Adds a listener that will be invoked a fixed number of times for the\n\t * events. After each event is triggered the specified amount of times, the\n\t * listener is removed for it.\n\t * @param {!(Array|string)} event\n\t * @param {number} amount The amount of times this event should be listened\n\t * to.\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\tmany(event, amount, listener) {\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.many_(events[i], amount, listener);\n\t\t}\n\n\t\treturn new EventHandle(this, event, listener);\n\t}\n\n\t/**\n\t * Adds a listener that will be invoked a fixed number of times for a single\n\t * event. After the event is triggered the specified amount of times, the\n\t * listener is removed.\n\t * @param {string} event\n\t * @param {number} amount The amount of times this event should be listened\n\t * to.\n\t * @param {!Function} listener\n\t * @protected\n\t */\n\tmany_(event, amount, listener) {\n\t\tconst self = this;\n\n\t\tif (amount <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t *\n\t\t */\n\t\tfunction handlerInternal() {\n\t\t\tif (--amount === 0) {\n\t\t\t\tself.removeListener(event, handlerInternal);\n\t\t\t}\n\t\t\tlistener.apply(self, arguments); // eslint-disable-line\n\t\t}\n\n\t\tself.addSingleListener_(event, handlerInternal, false, listener);\n\t}\n\n\t/**\n\t * Checks if a listener object matches the given listener function. To match,\n\t * it needs to either point to that listener or have it as its origin.\n\t * @param {!Object} listenerObj\n\t * @param {!Function} listener\n\t * @return {boolean}\n\t * @protected\n\t */\n\tmatchesListener_(listenerObj, listener) {\n\t\tconst fn = listenerObj.fn || listenerObj;\n\t\treturn (\n\t\t\tfn === listener ||\n\t\t\t(listenerObj.origin && listenerObj.origin === listener) // eslint-disable-line\n\t\t);\n\t}\n\n\t/**\n\t * Removes a listener for the specified events.\n\t * Caution: changes array indices in the listener array behind the listener.\n\t * @param {!(Array|string)} event\n\t * @param {!Function} listener\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\toff(event, listener) {\n\t\tthis.validateListener_(listener);\n\t\tif (!this.events_) {\n\t\t\treturn this;\n\t\t}\n\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.events_[events[i]] = this.removeMatchingListenerObjs_(\n\t\t\t\ttoArray(this.events_[events[i]]),\n\t\t\t\tlistener\n\t\t\t);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for the specified events.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\ton() {\n\t\treturn this.addListener.apply(this, arguments); // eslint-disable-line\n\t}\n\n\t/**\n\t * Adds handler that gets triggered when an event is listened to on this\n\t * instance.\n\t * @param {!function()} handler\n\t */\n\tonListener(handler) {\n\t\tthis.listenerHandlers_ = this.addHandler_(\n\t\t\tthis.listenerHandlers_,\n\t\t\thandler\n\t\t); // eslint-disable-line\n\t}\n\n\t/**\n\t * Adds a one time listener for the events. This listener is invoked only the\n\t * next time each event is fired, after which it is removed.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\tonce(events, listener) {\n\t\treturn this.many(events, 1, listener);\n\t}\n\n\t/**\n\t * Removes all listeners, or those of the specified events. It's not a good\n\t * idea to remove listeners that were added elsewhere in the code,\n\t * especially when it's on an emitter that you didn't create.\n\t * @param {(Array|string)=} event\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveAllListeners(event) {\n\t\tif (this.events_) {\n\t\t\tif (event) {\n\t\t\t\tconst events = this.toEventsArray_(event);\n\t\t\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\t\t\tthis.events_[events[i]] = null;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.events_ = null;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes all listener objects from the given array that match the given\n\t * listener function.\n\t * @param {Array.} listenerObjs\n\t * @param {!Function} listener\n\t * @return {Array.|Object} The new listeners array for this event.\n\t * @protected\n\t */\n\tremoveMatchingListenerObjs_(listenerObjs, listener) {\n\t\tconst finalListeners = [];\n\t\tfor (let i = 0; i < listenerObjs.length; i++) {\n\t\t\tif (!this.matchesListener_(listenerObjs[i], listener)) {\n\t\t\t\tfinalListeners.push(listenerObjs[i]);\n\t\t\t}\n\t\t}\n\t\treturn finalListeners.length > 0 ? finalListeners : null;\n\t}\n\n\t/**\n\t * Removes a listener for the specified events.\n\t * Caution: changes array indices in the listener array behind the listener.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveListener() {\n\t\treturn this.off.apply(this, arguments); // eslint-disable-line\n\t}\n\n\t/**\n\t * Runs the handlers when an event is listened to.\n\t * @param {string} event\n\t * @protected\n\t */\n\trunListenerHandlers_(event) {\n\t\tlet handlers = this.listenerHandlers_;\n\t\tif (handlers) {\n\t\t\thandlers = toArray(handlers);\n\t\t\tfor (let i = 0; i < handlers.length; i++) {\n\t\t\t\thandlers[i](event);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Runs the given listeners.\n\t * @param {!Array} listeners\n\t * @param {!Array} args\n\t * @param {Object} facade\n\t * @protected\n\t */\n\trunListeners_(listeners, args, facade) {\n\t\tif (facade) {\n\t\t\targs.push(facade);\n\t\t}\n\n\t\tconst defaultListeners = [];\n\t\tfor (let i = 0; i < listeners.length; i++) {\n\t\t\tconst listener = listeners[i].fn || listeners[i];\n\t\t\tif (listeners[i].default) {\n\t\t\t\tdefaultListeners.push(listener);\n\t\t\t} else {\n\t\t\t\tlistener.apply(this, args);\n\t\t\t}\n\t\t}\n\t\tif (!facade || !facade.preventedDefault) {\n\t\t\tfor (let j = 0; j < defaultListeners.length; j++) {\n\t\t\t\tdefaultListeners[j].apply(this, args);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets the configuration option which determines if an event facade should\n\t * be sent as a param of listeners when emitting events. If set to true, the\n\t * facade will be passed as the first argument of the listener.\n\t * @param {boolean} shouldUseFacade\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tsetShouldUseFacade(shouldUseFacade) {\n\t\tthis.shouldUseFacade_ = shouldUseFacade;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Converts the parameter to an array if only one event is given. Reuses the\n\t * same array each time this conversion is done, to avoid using more memory\n\t * than necessary.\n\t * @param {!(Array|string)} events\n\t * @return {!Array}\n\t * @protected\n\t */\n\ttoEventsArray_(events) {\n\t\tif (isString(events)) {\n\t\t\tsingleArray_[0] = events;\n\t\t\tevents = singleArray_;\n\t\t}\n\t\treturn events;\n\t}\n\n\t/**\n\t * Checks if the given listener is valid, throwing an exception when it's not.\n\t * @param {*} listener\n\t * @protected\n\t */\n\tvalidateListener_(listener) {\n\t\tif (!isFunction(listener)) {\n\t\t\tthrow new TypeError('Listener must be a function');\n\t\t}\n\t}\n}\n\n/**\n * Converts to an array\n * @param {Object} val\n * @return {Array}\n */\nfunction toArray(val) {\n\tval = val || [];\n\treturn Array.isArray(val) ? val : [val];\n}\n\nexport default EventEmitter;\n","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventEmitterProxy utility. It's responsible for linking two EventEmitter\n * instances together, emitting events from the first emitter through the\n * second one. That means that listening to a supported event on the target\n * emitter will mean listening to it on the origin emitter as well.\n * @extends {Disposable}\n */\nclass EventEmitterProxy extends Disposable {\n\t/**\n\t * @param {EventEmitter} originEmitter Events originated on this emitter\n\t * will be fired for the target emitter's listeners as well.\n\t * @param {EventEmitter} targetEmitter Event listeners attached to this emitter\n\t * will also be triggered when the event is fired by the origin emitter.\n\t * @param {Object} blacklist Optional blacklist of events that should not be\n\t * proxied.\n\t * @param {Object} whitelist\n\t */\n\tconstructor(originEmitter, targetEmitter, blacklist, whitelist) {\n\t\tsuper();\n\n\t\t/**\n\t\t * Map of events that should not be proxied.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.blacklist_ = blacklist;\n\n\t\t/**\n\t\t * The origin emitter. This emitter's events will be proxied through the\n\t\t * target emitter.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.originEmitter_ = originEmitter;\n\n\t\t/**\n\t\t * A list of events that are pending to be listened by an actual origin\n\t\t * emitter. Events are stored here when the origin doesn't exist, so they\n\t\t * can be set on a new origin when one is set.\n\t\t * @type {Array}\n\t\t * @protected\n\t\t */\n\t\tthis.pendingEvents_ = null;\n\n\t\t/**\n\t\t * Holds a map of events from the origin emitter that are already being proxied.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.proxiedEvents_ = null;\n\n\t\t/**\n\t\t * The target emitter. This emitter will emit all events that come from\n\t\t * the origin emitter.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.targetEmitter_ = targetEmitter;\n\n\t\t/**\n\t\t * Map of events that should be proxied. If whitelist is set blacklist is ignored.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.whitelist_ = whitelist;\n\n\t\tthis.startProxy_();\n\t}\n\n\t/**\n\t * Adds the given listener for the given event.\n\t * @param {string} event\n\t * @param {!function()} listener\n\t * @return {!EventHandle} The listened event's handle.\n\t * @protected\n\t */\n\taddListener_(event, listener) {\n\t\treturn this.originEmitter_.on(event, listener);\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisposeInternal() {\n\t\tthis.removeListeners_();\n\t\tthis.proxiedEvents_ = null;\n\t\tthis.originEmitter_ = null;\n\t\tthis.targetEmitter_ = null;\n\t}\n\n\t/**\n\t * Emits the specified event type on the target emitter.\n\t * @protected\n\t */\n\temitOnTarget_(...args) {\n\t\tthis.targetEmitter_.emit(...args);\n\t}\n\n\t/**\n\t * Proxies the given event from the origin to the target emitter.\n\t * @param {string} event\n\t */\n\tproxyEvent(event) {\n\t\tif (this.shouldProxyEvent_(event)) {\n\t\t\tthis.tryToAddListener_(event);\n\t\t}\n\t}\n\n\t/**\n\t * Removes the proxy listener for all events.\n\t * @protected\n\t */\n\tremoveListeners_() {\n\t\tif (this.proxiedEvents_) {\n\t\t\tconst events = Object.keys(this.proxiedEvents_);\n\t\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\t\tthis.proxiedEvents_[events[i]].removeListener();\n\t\t\t}\n\t\t\tthis.proxiedEvents_ = null;\n\t\t}\n\t\tthis.pendingEvents_ = null;\n\t}\n\n\t/**\n\t * Changes the origin emitter. This automatically detaches any events that\n\t * were already being proxied from the previous emitter, and starts proxying\n\t * them on the new emitter instead.\n\t * @param {!EventEmitter} originEmitter\n\t */\n\tsetOriginEmitter(originEmitter) {\n\t\tconst events =\n\t\t\tthis.originEmitter_ && this.proxiedEvents_\n\t\t\t\t? Object.keys(this.proxiedEvents_)\n\t\t\t\t: this.pendingEvents_;\n\t\tthis.originEmitter_ = originEmitter;\n\t\tif (events) {\n\t\t\tthis.removeListeners_();\n\t\t\tevents.forEach(event => this.proxyEvent(event));\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given event should be proxied.\n\t * @param {string} event\n\t * @return {boolean}\n\t * @protected\n\t */\n\tshouldProxyEvent_(event) {\n\t\tif (this.whitelist_ && !this.whitelist_[event]) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.blacklist_ && this.blacklist_[event]) {\n\t\t\treturn false;\n\t\t}\n\t\treturn !this.proxiedEvents_ || !this.proxiedEvents_[event];\n\t}\n\n\t/**\n\t * Starts proxying all events from the origin to the target emitter.\n\t * @protected\n\t */\n\tstartProxy_() {\n\t\tthis.targetEmitter_.onListener(this.proxyEvent.bind(this));\n\t}\n\n\t/**\n\t * Adds a listener to the origin emitter, if it exists. Otherwise, stores\n\t * the pending listener so it can be used on a future origin emitter.\n\t * @param {string} event\n\t * @protected\n\t */\n\ttryToAddListener_(event) {\n\t\tif (this.originEmitter_) {\n\t\t\tthis.proxiedEvents_ = this.proxiedEvents_ || {};\n\t\t\tthis.proxiedEvents_[event] = this.addListener_(\n\t\t\t\tevent,\n\t\t\t\tthis.emitOnTarget_.bind(this, event)\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pendingEvents_ = this.pendingEvents_ || [];\n\t\t\tthis.pendingEvents_.push(event);\n\t\t}\n\t}\n}\n\nexport default EventEmitterProxy;\n","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventHandler utility. It's useful for easily removing a group of\n * listeners from different EventEmitter instances.\n * @extends {Disposable}\n */\nclass EventHandler extends Disposable {\n\t/**\n\t * EventHandler constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * An array that holds the added event handles, so the listeners can be\n\t\t * removed later.\n\t\t * @type {Array.}\n\t\t * @protected\n\t\t */\n\t\tthis.eventHandles_ = [];\n\t}\n\n\t/**\n\t * Adds event handles to be removed later through the `removeAllListeners`\n\t * method.\n\t * @param {...(!EventHandle)} var_args\n\t */\n\tadd(...args) {\n\t\tfor (let i = 0; i < arguments.length; i++) {\n\t\t\tthis.eventHandles_.push(args[i]);\n\t\t}\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.eventHandles_ = null;\n\t}\n\n\t/**\n\t * Removes all listeners that have been added through the `add` method.\n\t */\n\tremoveAllListeners() {\n\t\tfor (let i = 0; i < this.eventHandles_.length; i++) {\n\t\t\tthis.eventHandles_[i].removeListener();\n\t\t}\n\n\t\tthis.eventHandles_ = [];\n\t}\n}\n\nexport default EventHandler;\n","'use strict';\n\nimport {array, isString} from 'metal';\nimport domData from './domData';\nimport {EventHandle} from 'metal-events';\n\n/**\n * This is a special EventHandle, that is responsible for dom delegated events\n * (only the ones that receive a target element, not a selector string).\n * @extends {EventHandle}\n */\nclass DomDelegatedEventHandle extends EventHandle {\n\t/**\n\t * The constructor for `DomDelegatedEventHandle`.\n\t * @param {!Event} emitter Element the event was subscribed to.\n\t * @param {string} event The name of the event that was subscribed to.\n\t * @param {!Function} listener The listener subscribed to the event.\n\t * @param {string=} selector An optional selector used when delegating\n\t * the event.\n\t * @constructor\n\t */\n\tconstructor(emitter, event, listener, selector) {\n\t\tsuper(emitter, event, listener);\n\t\tthis.selector_ = selector;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tremoveListener() {\n\t\tconst delegating = domData.get(this.emitter_, 'delegating', {});\n\t\tconst listeners = domData.get(this.emitter_, 'listeners', {});\n\t\tconst selector = this.selector_;\n\t\tconst arr = isString(selector)\n\t\t\t? delegating[this.event_].selectors\n\t\t\t: listeners;\n\t\tconst key = isString(selector) ? selector : this.event_;\n\n\t\tarray.remove(arr[key] || [], this.listener_);\n\t\tif (arr[key] && arr[key].length === 0) {\n\t\t\tdelete arr[key];\n\t\t}\n\t}\n}\n\nexport default DomDelegatedEventHandle;\n","'use strict';\n\nimport {EventHandle} from 'metal-events';\n\n/**\n * This is a special EventHandle, that is responsible for dom events, instead\n * of EventEmitter events.\n * @extends {EventHandle}\n */\nclass DomEventHandle extends EventHandle {\n\t/**\n\t * The constructor for `DomEventHandle`.\n\t * @param {!EventEmitter} emitter Emitter the event was subscribed to.\n\t * @param {string} event The name of the event that was subscribed to.\n\t * @param {!Function} listener The listener subscribed to the event.\n\t * @param {boolean} capture Flag indicating if listener should be triggered\n\t * during capture phase, instead of during the bubbling phase. Defaults to false.\n\t * @constructor\n\t */\n\tconstructor(emitter, event, listener, capture) {\n\t\tsuper(emitter, event, listener);\n\t\tthis.capture_ = capture;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tremoveListener() {\n\t\tthis.emitter_.removeEventListener(\n\t\t\tthis.event_,\n\t\t\tthis.listener_,\n\t\t\tthis.capture_\n\t\t);\n\t}\n}\n\nexport default DomEventHandle;\n","'use strict';\n\nimport {\n\tisDef,\n\tisDefAndNotNull,\n\tisDocument,\n\tisDocumentFragment,\n\tisElement,\n\tisObject,\n\tisString,\n\tobject,\n} from 'metal';\nimport domData from './domData';\nimport DomDelegatedEventHandle from './DomDelegatedEventHandle';\nimport DomEventHandle from './DomEventHandle';\n\nconst elementsByTag_ = {};\nconst supportCache_ = {};\nexport const customEvents = {};\n\nconst LAST_CONTAINER = '__metal_last_container__';\nconst USE_CAPTURE = {\n\tblur: true,\n\terror: true,\n\tfocus: true,\n\tinvalid: true,\n\tload: true,\n\tscroll: true,\n};\n\n/**\n * Adds the requested CSS classes to an element.\n * @param {!Element|!Nodelist} elements The element or elements to add CSS classes to.\n * @param {string} classes CSS classes to add.\n */\nexport function addClasses(elements, classes) {\n\tif (!isObject(elements) || !isString(classes)) {\n\t\treturn;\n\t}\n\n\tif (!elements.length) {\n\t\telements = [elements];\n\t}\n\n\tfor (let i = 0; i < elements.length; i++) {\n\t\tif ('classList' in elements[i]) {\n\t\t\taddClassesWithNative_(elements[i], classes);\n\t\t} else {\n\t\t\taddClassesWithoutNative_(elements[i], classes);\n\t\t}\n\t}\n}\n\n/**\n * Adds the requested CSS classes to an element using classList.\n * @param {!Element} element The element to add CSS classes to.\n * @param {string} classes CSS classes to add.\n * @private\n */\nfunction addClassesWithNative_(element, classes) {\n\tclasses.split(' ').forEach(function(className) {\n\t\tif (className) {\n\t\t\telement.classList.add(className);\n\t\t}\n\t});\n}\n\n/**\n * IE11 doesn't support Element.classList.add function, this method\n * adds the requested CSS classes to an element without using classList.\n * @param {!Element} element The element to add CSS classes to.\n * @param {string} classes CSS classes to add.\n * @private\n */\nfunction addClassesWithoutNative_(element, classes) {\n\tconst elementClassName = ` ${element.className} `;\n\tlet classesToAppend = '';\n\n\tclasses = classes.split(' ');\n\n\tfor (let i = 0; i < classes.length; i++) {\n\t\tconst className = classes[i];\n\n\t\tif (elementClassName.indexOf(` ${className} `) === -1) {\n\t\t\tclassesToAppend += ` ${className}`;\n\t\t}\n\t}\n\n\tif (classesToAppend) {\n\t\telement.className = element.className + classesToAppend;\n\t}\n}\n\n/**\n * Adds an event listener to the given element, to be triggered via delegate.\n * @param {!Element} element\n * @param {string} eventName\n * @param {!function()} listener\n * @private\n */\nfunction addElementListener_(element, eventName, listener) {\n\taddToArr_(domData.get(element, 'listeners', {}), eventName, listener);\n}\n\n/**\n * Adds an event listener to the given element, to be triggered via delegate\n * selectors.\n * @param {!Element} element\n * @param {string} eventName\n * @param {string} selector\n * @param {!function()} listener\n * @private\n */\nfunction addSelectorListener_(element, eventName, selector, listener) {\n\tconst delegatingData = domData.get(element, 'delegating', {});\n\taddToArr_(delegatingData[eventName].selectors, selector, listener);\n}\n\n/**\n * Adds a value to an array inside an object, creating it first if it doesn't\n * yet exist.\n * @param {!Array} arr\n * @param {string} key\n * @param {*} value\n * @private\n */\nfunction addToArr_(arr, key, value) {\n\tif (!arr[key]) {\n\t\tarr[key] = [];\n\t}\n\tarr[key].push(value);\n}\n\n/**\n * Attaches a delegate listener, unless there's already one attached.\n * @param {!Element} element\n * @param {string} eventName\n * @private\n */\nfunction attachDelegateEvent_(element, eventName) {\n\tlet delegatingData = domData.get(element, 'delegating', {});\n\tif (!delegatingData[eventName]) {\n\t\tdelegatingData[eventName] = {\n\t\t\thandle: on(\n\t\t\t\telement,\n\t\t\t\teventName,\n\t\t\t\thandleDelegateEvent_,\n\t\t\t\t!!USE_CAPTURE[eventName]\n\t\t\t),\n\t\t\tselectors: {},\n\t\t};\n\t}\n}\n\n/**\n * IE11 doesn't support Element.closest function, this method\n * gets the closest element up the tree from the given element (including\n * itself) that matches the specified selector, or null if none match.\n * @param {Element} element\n * @param {string} selector\n * @return {Element}\n */\nexport function closest(element, selector) {\n\twhile (element && !match(element, selector)) {\n\t\telement = element.parentNode;\n\t}\n\treturn element;\n}\n\n/**\n * IE11 doesn't support Element.classList.add function, this method\n * appends a child node with text or other nodes to a parent node. If\n * child is a HTML string it will be automatically converted to a document\n * fragment before appending it to the parent.\n * @param {!Element} parent The node to append nodes to.\n * @param {!(Element|NodeList|string)} child The thing to append to the parent.\n * @return {!Element} The appended child.\n */\nexport function append(parent, child) {\n\tif (isString(child)) {\n\t\tchild = buildFragment(child);\n\t}\n\tif (isNodeListLike(child)) {\n\t\tconst childArr = Array.prototype.slice.call(child);\n\t\tfor (let i = 0; i < childArr.length; i++) {\n\t\t\tparent.appendChild(childArr[i]);\n\t\t}\n\t} else {\n\t\tparent.appendChild(child);\n\t}\n\treturn child;\n}\n\n/**\n * Helper for converting a HTML string into a document fragment.\n * @param {string} htmlString The HTML string to convert.\n * @return {!Element} The resulting document fragment.\n */\nexport function buildFragment(htmlString) {\n\tconst tempDiv = document.createElement('div');\n\ttempDiv.innerHTML = `
${htmlString}`;\n\ttempDiv.removeChild(tempDiv.firstChild);\n\n\tconst fragment = document.createDocumentFragment();\n\twhile (tempDiv.firstChild) {\n\t\tfragment.appendChild(tempDiv.firstChild);\n\t}\n\treturn fragment;\n}\n\n/**\n * Checks if the first element contains the second one.\n * @deprecated Use element1.contains(element2) directly instead of this method\n * @param {!Element} element1\n * @param {!Element} element2\n * @return {boolean}\n */\nexport function contains(element1, element2) {\n\tif (isDocument(element1)) {\n\t\t// document.contains is not defined on IE9, so call it on documentElement instead.\n\t\treturn element1.documentElement.contains(element2);\n\t} else {\n\t\treturn element1.contains(element2);\n\t}\n}\n\n/**\n * Listens to the specified event on the given DOM element, but only calls the\n * given callback listener when it's triggered by elements that match the\n * given selector or target element.\n * @param {!Element} element The DOM element the event should be listened on.\n * @param {string} eventName The name of the event to listen to.\n * @param {!Element|string} selectorOrTarget Either an element or css selector\n * that should match the event for the listener to be triggered.\n * @param {!function(!Object)} callback Function to be called when the event\n * is triggered. It will receive the normalized event object.\n * @param {boolean=} defaultListener Optional flag indicating if this is a default\n * listener. That means that it would only be executed after all non\n * default listeners, and only if the event isn't prevented via\n * `preventDefault`.\n * @return {!EventHandle} Can be used to remove the listener.\n */\nexport function delegate(\n\telement,\n\teventName,\n\tselectorOrTarget,\n\tcallback,\n\tdefaultListener\n) {\n\tconst customConfig = customEvents[eventName];\n\tif (customConfig && customConfig.delegate) {\n\t\teventName = customConfig.originalEvent;\n\t\tcallback = customConfig.handler.bind(customConfig, callback);\n\t}\n\n\tif (defaultListener) {\n\t\t// Wrap callback so we don't set property directly on it.\n\t\tcallback = callback.bind();\n\t\tcallback.defaultListener_ = true;\n\t}\n\n\tattachDelegateEvent_(element, eventName);\n\tif (isString(selectorOrTarget)) {\n\t\taddSelectorListener_(element, eventName, selectorOrTarget, callback);\n\t} else {\n\t\taddElementListener_(selectorOrTarget, eventName, callback);\n\t}\n\n\treturn new DomDelegatedEventHandle(\n\t\tisString(selectorOrTarget) ? element : selectorOrTarget,\n\t\teventName,\n\t\tcallback,\n\t\tisString(selectorOrTarget) ? selectorOrTarget : null\n\t);\n}\n\n/**\n * Verifies if the element is able to trigger the Click event,\n * simulating browsers behaviour, avoiding event listeners to be called by triggerEvent method.\n * @param {Element} node Element to be checked.\n * @param {string} eventName The event name.\n * @param {Object=} eventObj\n * @private\n * @return {boolean}\n */\nfunction isAbleToInteractWith_(node, eventName, eventObj) {\n\tif (eventObj && eventName === 'click' && eventObj.button === 2) {\n\t\t// Firefox triggers \"click\" events on the document for right clicks. This\n\t\t// causes our delegate logic to trigger it for regular elements too, which\n\t\t// shouldn't happen. Ignoring them here.\n\t\treturn false;\n\t}\n\n\tconst matchesSelector = [\n\t\t'BUTTON',\n\t\t'INPUT',\n\t\t'SELECT',\n\t\t'TEXTAREA',\n\t\t'FIELDSET',\n\t];\n\tif (eventName === 'click' && matchesSelector.indexOf(node.tagName) > -1) {\n\t\treturn !(node.disabled || parent(node, 'fieldset[disabled]'));\n\t}\n\treturn true;\n}\n\n/**\n * Returns true if the specified value is a NodeList or like one.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is like a NodeList.\n */\nexport function isNodeListLike(val) {\n\treturn (\n\t\tisDefAndNotNull(val) &&\n\t\ttypeof val.length === 'number' &&\n\t\ttypeof val.item === 'function'\n\t);\n}\n\n/**\n * Inserts node in document as last element.\n * @param {Element} node Element to remove children from.\n */\nexport function enterDocument(node) {\n\tnode && append(document.body, node);\n}\n\n/**\n * Removes node from document.\n * @param {Element} node Element to remove children from.\n */\nexport function exitDocument(node) {\n\tif (node && node.parentNode) {\n\t\tnode.parentNode.removeChild(node);\n\t}\n}\n\n/**\n * This is called when an event is triggered by a delegate listener. All\n * matching listeners of this event type from `target` to `currentTarget` will\n * be triggered.\n * @param {!Event} event The event payload.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction handleDelegateEvent_(event) {\n\tnormalizeDelegateEvent_(event);\n\tlet ret = true;\n\tconst container = event.currentTarget;\n\tconst defFns = [];\n\n\tret &= triggerDelegatedListeners_(container, event, defFns);\n\tret &= triggerDefaultDelegatedListeners_(defFns, event);\n\n\tevent.delegateTarget = null;\n\tevent[LAST_CONTAINER] = container;\n\treturn ret;\n}\n\n/**\n * Checks if the given element has the requested css class.\n * @param {!Element} element\n * @param {string} className\n * @return {boolean}\n */\nexport function hasClass(element, className) {\n\tif ('classList' in element) {\n\t\treturn hasClassWithNative_(element, className);\n\t} else {\n\t\treturn hasClassWithoutNative_(element, className);\n\t}\n}\n\n/**\n * Checks if the given element has the requested css class using classList.\n * @param {!Element} element\n * @param {string} className\n * @return {boolean}\n * @private\n */\nfunction hasClassWithNative_(element, className) {\n\treturn (\n\t\tclassName.indexOf(' ') === -1 && element.classList.contains(className)\n\t);\n}\n\n/**\n * Checks if the given element has the requested css class without using classList.\n * @param {!Element} element\n * @param {string} className\n * @return {boolean}\n * @private\n */\nfunction hasClassWithoutNative_(element, className) {\n\treturn (\n\t\t` ${element.className} `.indexOf(` ${className} `) >= 0 &&\n\t\tclassName.split(' ').length === 1\n\t);\n}\n\n/**\n * Checks if the given element is empty or not.\n * @param {!Element} element\n * @return {boolean}\n */\nexport function isEmpty(element) {\n\treturn element.childNodes.length === 0;\n}\n\n/**\n * IE11 doesn't support Element.matches function, this method\n * check if an element matches a given selector.\n * @param {Element} element\n * @param {string} selector\n * @return {boolean}\n */\nexport function match(element, selector) {\n\tif (!element || element.nodeType !== 1) {\n\t\treturn false;\n\t}\n\n\tconst p = Element.prototype;\n\tconst m =\n\t\tp.matches ||\n\t\tp.webkitMatchesSelector ||\n\t\tp.mozMatchesSelector ||\n\t\tp.msMatchesSelector ||\n\t\tp.oMatchesSelector;\n\tif (m) {\n\t\treturn m.call(element, selector);\n\t}\n\n\treturn matchFallback_(element, selector);\n}\n\n/**\n * Check if an element matches a given selector, using an internal implementation\n * instead of calling existing javascript functions.\n * @param {Element} element\n * @param {string} selector\n * @return {boolean}\n * @private\n */\nfunction matchFallback_(element, selector) {\n\tconst parentNode = element.parentNode;\n\n\tif (parentNode) {\n\t\tconst nodes = parentNode.querySelectorAll(selector);\n\n\t\tfor (let i = 0; i < nodes.length; ++i) {\n\t\t\tif (nodes[i] === element) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Returns the next sibling of the given element that matches the specified\n * selector, or null if there is none.\n * @param {!Element} element\n * @param {?string} selector\n * @return {Element|null}\n */\nexport function next(element, selector) {\n\tdo {\n\t\telement = element.nextSibling;\n\t\tif (element && match(element, selector)) {\n\t\t\treturn element;\n\t\t}\n\t} while (element);\n\treturn null;\n}\n\n/**\n * Normalizes the event payload for delegate listeners.\n * @param {!Event} event\n * @private\n */\nfunction normalizeDelegateEvent_(event) {\n\tevent.stopPropagation = stopPropagation_;\n\tevent.stopImmediatePropagation = stopImmediatePropagation_;\n}\n\n/**\n * Listens to the specified event on the given DOM element. This function normalizes\n * DOM event payloads and functions so they'll work the same way on all supported\n * browsers.\n * @param {!Element|string} element The DOM element to listen to the event on, or\n * a selector that should be delegated on the entire document.\n * @param {string} eventName The name of the event to listen to.\n * @param {!function(!Object)} callback Function to be called when the event is\n * triggered. It will receive the normalized event object.\n * @param {boolean} capture Flag indicating if listener should be triggered\n * during capture phase, instead of during the bubbling phase. Defaults to false.\n * @return {!DomEventHandle} Can be used to remove the listener.\n */\nexport function on(element, eventName, callback, capture) {\n\tif (isString(element)) {\n\t\treturn delegate(document, eventName, element, callback);\n\t}\n\tconst customConfig = customEvents[eventName];\n\tif (customConfig && customConfig.event) {\n\t\teventName = customConfig.originalEvent;\n\t\tcallback = customConfig.handler.bind(customConfig, callback);\n\t}\n\telement.addEventListener(eventName, callback, capture);\n\treturn new DomEventHandle(element, eventName, callback, capture);\n}\n\n/**\n * IE11 doesn't support once event listener option, this method\n * Listens to the specified event on the given DOM element once. This\n * function normalizes DOM event payloads and functions so they'll work the\n * same way on all supported browsers.\n * @param {!Element} element The DOM element to listen to the event on.\n * @param {string} eventName The name of the event to listen to.\n * @param {!function(!Object)} callback Function to be called when the event\n * is triggered. It will receive the normalized event object.\n * @return {!DomEventHandle} Can be used to remove the listener.\n */\nexport function once(element, eventName, callback) {\n\tconst domEventHandle = on(element, eventName, function() {\n\t\tdomEventHandle.removeListener();\n\t\treturn callback.apply(this, arguments); // eslint-disable-line\n\t});\n\treturn domEventHandle;\n}\n\n/**\n * Gets the first parent from the given element that matches the specified\n * selector, or null if none match.\n * @param {!Element} element\n * @param {string} selector\n * @return {Element}\n */\nexport function parent(element, selector) {\n\treturn closest(element.parentNode, selector);\n}\n\n/**\n * IE11 doesn't support Element.prepend function, this method\n * inserts a node before first child of the parent. If child is a HTML string\n * it will be converted to document fragment before prepending it to the parent.\n * @param {!Element} parent The node to prepend to.\n * @param {!(Element|NodeList|string)} child The thing to prepend to the parent.\n * @return {!Element} The prepended child.\n */\nexport function prepend(parent, child) {\n\tif (isString(child)) {\n\t\tchild = buildFragment(child);\n\t}\n\n\tif (!isNodeListLike(child) && !isDefAndNotNull(parent.firstChild)) {\n\t\treturn append(parent, child);\n\t}\n\n\tif (isNodeListLike(child)) {\n\t\tconst childArr = Array.prototype.slice.call(child);\n\t\tfor (let i = childArr.length - 1; i >= 0; i--) {\n\t\t\tparent.insertBefore(childArr[i], parent.firstChild);\n\t\t}\n\t} else {\n\t\tparent.insertBefore(child, parent.firstChild);\n\t}\n\n\treturn child;\n}\n\n/**\n * Registers a custom event.\n * @param {string} eventName The name of the custom event.\n * @param {!Object} customConfig An object with information about how the event\n * should be handled.\n */\nexport function registerCustomEvent(eventName, customConfig) {\n\tcustomEvents[eventName] = customConfig;\n}\n\n/**\n * Removes all the child nodes on a DOM node.\n * @param {Element} node Element to remove children from.\n */\nexport function removeChildren(node) {\n\tlet child;\n\twhile ((child = node.firstChild)) {\n\t\tnode.removeChild(child);\n\t}\n}\n\n/**\n * Removes the requested CSS classes from an element.\n * @param {!Element|!NodeList} elements The element or elements to remove CSS classes from.\n * @param {string} classes CSS classes to remove.\n */\nexport function removeClasses(elements, classes) {\n\tif (!isObject(elements) || !isString(classes)) {\n\t\treturn;\n\t}\n\n\tif (!elements.length) {\n\t\telements = [elements];\n\t}\n\n\tfor (let i = 0; i < elements.length; i++) {\n\t\tif ('classList' in elements[i]) {\n\t\t\tremoveClassesWithNative_(elements[i], classes);\n\t\t} else {\n\t\t\tremoveClassesWithoutNative_(elements[i], classes);\n\t\t}\n\t}\n}\n\n/**\n * Removes the requested CSS classes from an element using classList.\n * @param {!Element} element The element to remove CSS classes from.\n * @param {string} classes CSS classes to remove.\n * @private\n */\nfunction removeClassesWithNative_(element, classes) {\n\tclasses.split(' ').forEach(function(className) {\n\t\tif (className) {\n\t\t\telement.classList.remove(className);\n\t\t}\n\t});\n}\n\n/**\n * IE11 doesn't support Element.classList, this method\n * removes the requested CSS classes from an element without using classList.\n * @param {!Element} element The element to remove CSS classes from.\n * @param {string} classes CSS classes to remove.\n * @private\n */\nfunction removeClassesWithoutNative_(element, classes) {\n\tlet elementClassName = ` ${element.className} `;\n\n\tclasses = classes.split(' ');\n\n\tfor (let i = 0; i < classes.length; i++) {\n\t\telementClassName = elementClassName.replace(` ${classes[i]} `, ' ');\n\t}\n\n\telement.className = elementClassName.trim();\n}\n\n/**\n * Replaces the first element with the second.\n * @deprecated Use element1.parentNode.replaceChild(element2, element1)\n * directly instead of this method\n * @param {Element} element1\n * @param {Element} element2\n */\nexport function replace(element1, element2) {\n\tif (element1 && element2 && element1 !== element2 && element1.parentNode) {\n\t\telement1.parentNode.replaceChild(element2, element1);\n\t}\n}\n\n/**\n * The function that replaces `stopImmediatePropagation_` for events.\n * @private\n */\nfunction stopImmediatePropagation_() {\n\tconst event = this; // eslint-disable-line\n\tevent.stopped = true;\n\tevent.stoppedImmediate = true;\n\tEvent.prototype.stopImmediatePropagation.call(event);\n}\n\n/**\n * The function that replaces `stopPropagation` for events.\n * @private\n */\nfunction stopPropagation_() {\n\tconst event = this; // eslint-disable-line\n\tevent.stopped = true;\n\tEvent.prototype.stopPropagation.call(event);\n}\n\n/**\n * Checks if the given element supports the given event type.\n * @param {!Element|string} element The DOM element or element tag name to check.\n * @param {string} eventName The name of the event to check.\n * @return {boolean}\n */\nexport function supportsEvent(element, eventName) {\n\tif (customEvents[eventName]) {\n\t\treturn true;\n\t}\n\n\tif (isString(element)) {\n\t\tif (!elementsByTag_[element]) {\n\t\t\telementsByTag_[element] = document.createElement(element);\n\t\t}\n\t\telement = elementsByTag_[element];\n\t}\n\n\tconst tag = element.tagName;\n\tif (!supportCache_[tag] || !supportCache_[tag].hasOwnProperty(eventName)) {\n\t\tsupportCache_[tag] = supportCache_[tag] || {};\n\t\tsupportCache_[tag][eventName] = 'on' + eventName in element;\n\t}\n\treturn supportCache_[tag][eventName];\n}\n\n/**\n * This triggers all default matched delegated listeners of a given event type.\n * @param {!Array} defFns Array to collect default listeners in, instead\n * @param {!Event} event\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerDefaultDelegatedListeners_(defFns, event) {\n\tlet ret = true;\n\n\tfor (let i = 0; i < defFns.length && !event.defaultPrevented; i++) {\n\t\tevent.delegateTarget = defFns[i].element;\n\t\tret &= defFns[i].fn(event);\n\t}\n\n\treturn ret;\n}\n\n/**\n * This triggers all matched delegated listeners of a given event type when its\n * delegated target is able to interact.\n * @param {!Element} container\n * @param {!Event} event\n * @param {!Array} defaultFns Array to collect default listeners in, instead\n * of running them.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerDelegatedListeners_(container, event, defaultFns) {\n\tlet ret = true;\n\tlet currElement = event.target;\n\tconst limit = container.parentNode;\n\n\twhile (currElement && currElement !== limit && !event.stopped) {\n\t\tif (isAbleToInteractWith_(currElement, event.type, event)) {\n\t\t\tevent.delegateTarget = currElement;\n\t\t\tret &= triggerElementListeners_(currElement, event, defaultFns);\n\t\t\tret &= triggerSelectorListeners_(\n\t\t\t\tcontainer,\n\t\t\t\tcurrElement,\n\t\t\t\tevent,\n\t\t\t\tdefaultFns\n\t\t\t);\n\t\t}\n\t\tcurrElement = currElement.parentNode;\n\t}\n\n\treturn ret;\n}\n\n/**\n * Converts the given argument to a DOM element. Strings are assumed to\n * be selectors, and so a matched element will be returned. If the arg\n * is already a DOM element it will be the return value.\n * @param {string|Element|Document} selectorOrElement\n * @return {Element} The converted element, or null if none was found.\n */\nexport function toElement(selectorOrElement) {\n\tif (\n\t\tisElement(selectorOrElement) ||\n\t\tisDocument(selectorOrElement) ||\n\t\tisDocumentFragment(selectorOrElement)\n\t) {\n\t\treturn selectorOrElement;\n\t} else if (isString(selectorOrElement)) {\n\t\treturn document.querySelector(selectorOrElement);\n\t} else {\n\t\treturn null;\n\t}\n}\n\n/**\n * Adds or removes one or more classes from an element. If any of the classes\n * is present, it will be removed from the element, or added otherwise.\n * @param {!Element} element The element which classes will be toggled.\n * @param {string} classes The classes which have to added or removed from the element.\n */\nexport function toggleClasses(element, classes) {\n\tif (!isObject(element) || !isString(classes)) {\n\t\treturn;\n\t}\n\n\tif ('classList' in element) {\n\t\ttoggleClassesWithNative_(element, classes);\n\t} else {\n\t\ttoggleClassesWithoutNative_(element, classes);\n\t}\n}\n\n/**\n * Adds or removes one or more classes from an element using classList.\n * If any of the classes is present, it will be removed from the element,\n * or added otherwise.\n * @param {!Element} element The element which classes will be toggled.\n * @param {string} classes The classes which have to added or removed from the element.\n * @private\n */\nfunction toggleClassesWithNative_(element, classes) {\n\tclasses.split(' ').forEach(function(className) {\n\t\telement.classList.toggle(className);\n\t});\n}\n\n/**\n * IE11 doesn't support Element.classList, this method\n * adds or removes one or more classes from an element without using classList.\n * If any of the classes is present, it will be removed from the element,\n * or added otherwise.\n * @param {!Element} element The element which classes will be toggled.\n * @param {string} classes The classes which have to added or removed from the element.\n * @private\n */\nfunction toggleClassesWithoutNative_(element, classes) {\n\tlet elementClassName = ` ${element.className} `;\n\n\tclasses = classes.split(' ');\n\n\tfor (let i = 0; i < classes.length; i++) {\n\t\tconst className = ` ${classes[i]} `;\n\t\tconst classIndex = elementClassName.indexOf(className);\n\n\t\tif (classIndex === -1) {\n\t\t\telementClassName = `${elementClassName}${classes[i]} `;\n\t\t} else {\n\t\t\tconst before = elementClassName.substring(0, classIndex);\n\t\t\tconst after = elementClassName.substring(\n\t\t\t\tclassIndex + className.length\n\t\t\t); // eslint-disable-line\n\t\t\telementClassName = `${before} ${after}`;\n\t\t}\n\t}\n\n\telement.className = elementClassName.trim();\n}\n\n/**\n * Triggers all listeners for the given event type that are stored in the\n * specified element.\n * @param {!Element} element\n * @param {!Event} event\n * @param {!Array} defaultFns Array to collect default listeners in, instead\n * of running them.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerElementListeners_(element, event, defaultFns) {\n\tconst lastContainer = event[LAST_CONTAINER];\n\tif (!isDef(lastContainer) || !contains(lastContainer, element)) {\n\t\tconst listeners = domData.get(element, 'listeners', {})[event.type];\n\t\treturn triggerListeners_(listeners, event, element, defaultFns);\n\t}\n\treturn true;\n}\n\n/**\n * Triggers the specified event on the given element.\n * NOTE: This should mostly be used for testing, not on real code.\n * @param {!Element} element The node that should trigger the event.\n * @param {string} eventName The name of the event to be triggred.\n * @param {Object=} eventObj An object with data that should be on the\n * triggered event's payload.\n */\nexport function triggerEvent(element, eventName, eventObj) {\n\tif (isAbleToInteractWith_(element, eventName, eventObj)) {\n\t\tconst payload = document.createEvent('HTMLEvents');\n\t\tpayload.initEvent(eventName, true, true);\n\t\tobject.mixin(payload, eventObj);\n\t\telement.dispatchEvent(payload);\n\t}\n}\n\n/**\n * Triggers the given listeners array.\n * @param {Array} listeners\n * @param {!Event} event\n * @param {!Element} element\n * @param {!Array} defaultFns Array to collect default listeners in, instead\n * of running them.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerListeners_(listeners, event, element, defaultFns) {\n\tlet ret = true;\n\tlisteners = listeners || [];\n\tfor (let i = 0; i < listeners.length && !event.stoppedImmediate; i++) {\n\t\tif (listeners[i].defaultListener_) {\n\t\t\tdefaultFns.push({\n\t\t\t\telement,\n\t\t\t\tfn: listeners[i],\n\t\t\t});\n\t\t} else {\n\t\t\tret &= listeners[i](event);\n\t\t}\n\t}\n\treturn ret;\n}\n\n/**\n * Triggers all selector listeners for the given event.\n * @param {!Element} container\n * @param {!Element} element\n * @param {!Event} event\n * @param {!Array} defaultFns Array to collect default listeners in, instead\n * of running them.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerSelectorListeners_(container, element, event, defaultFns) {\n\tlet ret = true;\n\tconst data = domData.get(container, 'delegating', {});\n\tconst map = data[event.type].selectors;\n\tconst selectors = Object.keys(map);\n\tfor (let i = 0; i < selectors.length && !event.stoppedImmediate; i++) {\n\t\tif (match(element, selectors[i])) {\n\t\t\tconst listeners = map[selectors[i]];\n\t\t\tret &= triggerListeners_(listeners, event, element, defaultFns);\n\t\t}\n\t}\n\treturn ret;\n}\n","'use strict';\n\n// This file exists just for backwards compatibility, making sure that old\n// default imports for this file still work. It's best to use the named exports\n// for each function instead though, since that allows bundlers like Rollup to\n// reduce the bundle size by removing unused code.\nimport * as dom from './domNamed';\n\nexport default dom;\nexport {dom};\nexport * from './domNamed';\n","'use strict';\n\nimport {delegate, on, supportsEvent} from './dom';\nimport {EventEmitterProxy} from 'metal-events';\n\n/**\n * DomEventEmitterProxy utility. It extends `EventEmitterProxy` to also accept\n * dom elements as origin emitters.\n * @extends {EventEmitterProxy}\n */\nclass DomEventEmitterProxy extends EventEmitterProxy {\n\t/**\n\t * Adds the given listener for the given event.\n\t * @param {string} event\n\t * @param {!function()} listener\n\t * @return {!EventHandle} The listened event's handle.\n\t * @protected\n\t * @override\n\t */\n\taddListener_(event, listener) {\n\t\tif (this.originEmitter_.addEventListener) {\n\t\t\tif (this.isDelegateEvent_(event)) {\n\t\t\t\tconst index = event.indexOf(':', 9);\n\t\t\t\tconst eventName = event.substring(9, index);\n\t\t\t\tconst selector = event.substring(index + 1);\n\t\t\t\treturn delegate(\n\t\t\t\t\tthis.originEmitter_,\n\t\t\t\t\teventName,\n\t\t\t\t\tselector,\n\t\t\t\t\tlistener\n\t\t\t\t); // eslint-disable-line\n\t\t\t} else {\n\t\t\t\treturn on(this.originEmitter_, event, listener);\n\t\t\t}\n\t\t} else {\n\t\t\treturn super.addListener_(event, listener);\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given event is of the delegate type.\n\t * @param {string} event\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisDelegateEvent_(event) {\n\t\treturn event.substr(0, 9) === 'delegate:';\n\t}\n\n\t/**\n\t * Checks if the given event is supported by the origin element.\n\t * @param {string} event\n\t * @protected\n\t * @return {boolean}\n\t */\n\tisSupportedDomEvent_(event) {\n\t\tif (!this.originEmitter_ || !this.originEmitter_.addEventListener) {\n\t\t\treturn true;\n\t\t}\n\t\treturn (\n\t\t\t(this.isDelegateEvent_(event) && event.indexOf(':', 9) !== -1) ||\n\t\t\tsupportsEvent(this.originEmitter_, event)\n\t\t);\n\t}\n\n\t/**\n\t * Checks if the given event should be proxied.\n\t * @param {string} event\n\t * @return {boolean}\n\t * @protected\n\t * @override\n\t */\n\tshouldProxyEvent_(event) {\n\t\treturn (\n\t\t\tsuper.shouldProxyEvent_(event) && this.isSupportedDomEvent_(event)\n\t\t); // eslint-disable-line\n\t}\n}\n\nexport default DomEventEmitterProxy;\n","'use strict';\n\nimport {append} from './dom';\nimport {string} from 'metal';\n\n/**\n * Class with static methods responsible for doing browser feature checks.\n */\nclass features {\n\t/**\n\t * Some browsers still supports prefixed animation events. This method can\n\t * be used to retrieve the current browser event name for both, animation\n\t * and transition.\n\t * @return {object}\n\t */\n\tstatic checkAnimationEventName() {\n\t\tif (features.animationEventName_ === undefined) {\n\t\t\tfeatures.animationEventName_ = {\n\t\t\t\tanimation: features.checkAnimationEventName_('animation'),\n\t\t\t\ttransition: features.checkAnimationEventName_('transition'),\n\t\t\t};\n\t\t}\n\t\treturn features.animationEventName_;\n\t}\n\n\t/**\n\t * @protected\n\t * @param {string} type Type to test: animation, transition.\n\t * @return {string} Browser event name.\n\t */\n\tstatic checkAnimationEventName_(type) {\n\t\tconst prefixes = ['Webkit', 'MS', 'O', ''];\n\t\tconst typeTitleCase = string.replaceInterval(\n\t\t\ttype,\n\t\t\t0,\n\t\t\t1,\n\t\t\ttype.substring(0, 1).toUpperCase()\n\t\t);\n\t\tconst suffixes = [\n\t\t\t`${typeTitleCase}End`,\n\t\t\t`${typeTitleCase}End`,\n\t\t\t`${typeTitleCase}End`,\n\t\t\t`${type}end`,\n\t\t];\n\t\tif (!features.animationElement_) {\n\t\t\tfeatures.animationElement_ = document.createElement('div');\n\t\t}\n\t\tfor (let i = 0; i < prefixes.length; i++) {\n\t\t\tif (\n\t\t\t\tfeatures.animationElement_.style[\n\t\t\t\t\tprefixes[i] + typeTitleCase\n\t\t\t\t] !== undefined // eslint-disable-line\n\t\t\t) {\n\t\t\t\treturn prefixes[i].toLowerCase() + suffixes[i];\n\t\t\t}\n\t\t}\n\t\treturn `${type}end`;\n\t}\n\n\t/**\n\t * Some browsers (like IE11, Edge) change the order of element attributes, when html\n\t * is rendered. This method can be used to check if this behavior happens on\n\t * the current browser.\n\t * @return {boolean}\n\t */\n\tstatic checkAttrOrderChange() {\n\t\tif (features.attrOrderChange_ === undefined) {\n\t\t\tconst originalContent = '
';\n\t\t\tconst element = document.createElement('div');\n\t\t\tappend(element, originalContent);\n\t\t\tfeatures.attrOrderChange_ = originalContent !== element.innerHTML;\n\t\t}\n\t\treturn features.attrOrderChange_;\n\t}\n}\n\nfeatures.animationElement_ = undefined;\nfeatures.animationEventName_ = undefined;\nfeatures.attrOrderChange_ = undefined;\n\nexport default features;\n","'use strict';\n\nimport {async} from 'metal';\nimport {exitDocument, once} from './dom';\n\n/**\n * Utility functions for running javascript code in the global scope.\n */\nclass globalEval {\n\t/**\n\t * Evaluates the given string in the global scope.\n\t * @param {string} text\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic run(text, appendFn) {\n\t\tconst script = document.createElement('script');\n\t\tscript.text = text;\n\t\tif (appendFn) {\n\t\t\tappendFn(script);\n\t\t} else {\n\t\t\tdocument.head.appendChild(script);\n\t\t}\n\t\texitDocument(script);\n\t\treturn script;\n\t}\n\n\t/**\n\t * Evaluates the given javascript file in the global scope.\n\t * @param {string} src The file's path.\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic runFile(src, defaultFn, appendFn) {\n\t\tconst script = document.createElement('script');\n\t\tscript.src = src;\n\n\t\tconst callback = function() {\n\t\t\texitDocument(script);\n\t\t\tdefaultFn && defaultFn();\n\t\t};\n\t\tonce(script, 'load', callback);\n\t\tonce(script, 'error', callback);\n\n\t\tif (appendFn) {\n\t\t\tappendFn(script);\n\t\t} else {\n\t\t\tdocument.head.appendChild(script);\n\t\t}\n\n\t\treturn script;\n\t}\n\n\t/**\n\t * Evaluates the code referenced by the given script element.\n\t * @param {!Element} script\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic runScript(script, defaultFn, appendFn) {\n\t\tconst callback = function() {\n\t\t\tdefaultFn && defaultFn();\n\t\t};\n\t\tif (script.type && script.type !== 'text/javascript') {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn;\n\t\t}\n\t\texitDocument(script);\n\t\tif (script.src) {\n\t\t\treturn globalEval.runFile(script.src, defaultFn, appendFn);\n\t\t} else {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn globalEval.run(script.text, appendFn);\n\t\t}\n\t}\n\n\t/**\n\t * Evaluates any script tags present in the given element.\n\t * @param {!Element} element\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runScriptsInElement(element, defaultFn, appendFn) {\n\t\tconst scripts = element.querySelectorAll('script');\n\t\tif (scripts.length) {\n\t\t\tglobalEval.runScriptsInOrder(scripts, 0, defaultFn, appendFn);\n\t\t} else if (defaultFn) {\n\t\t\tasync.nextTick(defaultFn);\n\t\t}\n\t}\n\n\t/**\n\t * Runs the given scripts elements in the order that they appear.\n\t * @param {!NodeList} scripts\n\t * @param {number} index\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runScriptsInOrder(scripts, index, defaultFn, appendFn) {\n\t\tglobalEval.runScript(\n\t\t\tscripts.item(index),\n\t\t\tfunction() {\n\t\t\t\tif (index < scripts.length - 1) {\n\t\t\t\t\tglobalEval.runScriptsInOrder(\n\t\t\t\t\t\tscripts,\n\t\t\t\t\t\tindex + 1,\n\t\t\t\t\t\tdefaultFn,\n\t\t\t\t\t\tappendFn\n\t\t\t\t\t); // eslint-disable-line\n\t\t\t\t} else if (defaultFn) {\n\t\t\t\t\tasync.nextTick(defaultFn);\n\t\t\t\t}\n\t\t\t},\n\t\t\tappendFn\n\t\t);\n\t}\n}\n\nexport default globalEval;\n","'use strict';\n\nimport {async} from 'metal';\nimport {once} from './dom';\n\n/**\n * Utility functions for running styles.\n */\nclass globalEvalStyles {\n\t/**\n\t * Evaluates the given style.\n\t * @param {string} text\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic run(text, appendFn) {\n\t\tconst style = document.createElement('style');\n\t\tstyle.innerHTML = text;\n\t\tif (appendFn) {\n\t\t\tappendFn(style);\n\t\t} else {\n\t\t\tdocument.head.appendChild(style);\n\t\t}\n\t\treturn style;\n\t}\n\n\t/**\n\t * Evaluates the given style file.\n\t * @param {string} href The file's path.\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the styles has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic runFile(href, defaultFn, appendFn) {\n\t\tconst link = document.createElement('link');\n\t\tlink.rel = 'stylesheet';\n\t\tlink.href = href;\n\t\tglobalEvalStyles.runStyle(link, defaultFn, appendFn);\n\t\treturn link;\n\t}\n\n\t/**\n\t * Evaluates the code referenced by the given style/link element.\n\t * @param {!Element} style\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic runStyle(style, defaultFn, appendFn) {\n\t\tconst callback = function() {\n\t\t\tdefaultFn && defaultFn();\n\t\t};\n\t\tif (\n\t\t\tstyle.rel &&\n\t\t\tstyle.rel !== 'stylesheet' &&\n\t\t\tstyle.rel !== 'canonical' &&\n\t\t\tstyle.rel !== 'alternate'\n\t\t) {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tstyle.tagName === 'STYLE' ||\n\t\t\tstyle.rel === 'canonical' ||\n\t\t\tstyle.rel === 'alternate'\n\t\t) {\n\t\t\tasync.nextTick(callback);\n\t\t} else {\n\t\t\tonce(style, 'load', callback);\n\t\t\tonce(style, 'error', callback);\n\t\t}\n\n\t\tif (appendFn) {\n\t\t\tappendFn(style);\n\t\t} else {\n\t\t\tdocument.head.appendChild(style);\n\t\t}\n\n\t\treturn style;\n\t}\n\n\t/**\n\t * Evaluates any style present in the given element.\n\t * @param {!Element} element\n\t * @param {function()=} defaultFn Optional function to be called when the\n\t * style has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runStylesInElement(element, defaultFn, appendFn) {\n\t\tconst styles = element.querySelectorAll('style,link');\n\t\tif (styles.length === 0 && defaultFn) {\n\t\t\tasync.nextTick(defaultFn);\n\t\t\treturn;\n\t\t}\n\n\t\tlet loadCount = 0;\n\t\tconst callback = function() {\n\t\t\tif (defaultFn && ++loadCount === styles.length) {\n\t\t\t\tasync.nextTick(defaultFn);\n\t\t\t}\n\t\t};\n\t\tfor (let i = 0; i < styles.length; i++) {\n\t\t\tglobalEvalStyles.runStyle(styles[i], callback, appendFn);\n\t\t}\n\t}\n}\n\nexport default globalEvalStyles;\n","'use strict';\n\nimport {isServerSide} from 'metal';\nimport {registerCustomEvent, contains} from './dom';\nimport features from './features';\n\n/**\n * Register custom events for event delegation.\n */\nfunction registerEvents() {\n\tconst mouseEventMap = {\n\t\tmouseenter: 'mouseover',\n\t\tmouseleave: 'mouseout',\n\t\tpointerenter: 'pointerover',\n\t\tpointerleave: 'pointerout',\n\t};\n\tObject.keys(mouseEventMap).forEach(function(eventName) {\n\t\tregisterCustomEvent(eventName, {\n\t\t\tdelegate: true,\n\t\t\thandler: function(callback, event) {\n\t\t\t\tconst related = event.relatedTarget;\n\t\t\t\tconst target = event.delegateTarget;\n\t\t\t\t// eslint-disable-next-line\n\t\t\t\tif (\n\t\t\t\t\t!related ||\n\t\t\t\t\t(related !== target && !contains(target, related))\n\t\t\t\t) {\n\t\t\t\t\tevent.customType = eventName;\n\t\t\t\t\treturn callback(event);\n\t\t\t\t}\n\t\t\t},\n\t\t\toriginalEvent: mouseEventMap[eventName],\n\t\t});\n\t});\n\n\tconst animationEventMap = {\n\t\tanimation: 'animationend',\n\t\ttransition: 'transitionend',\n\t};\n\tObject.keys(animationEventMap).forEach(function(eventType) {\n\t\tconst eventName = animationEventMap[eventType];\n\t\tregisterCustomEvent(eventName, {\n\t\t\tevent: true,\n\t\t\tdelegate: true,\n\t\t\thandler: function(callback, event) {\n\t\t\t\tevent.customType = eventName;\n\t\t\t\treturn callback(event);\n\t\t\t},\n\t\t\toriginalEvent: features.checkAnimationEventName()[eventType],\n\t\t});\n\t});\n}\n\nif (!isServerSide()) {\n\tregisterEvents();\n}\n","var globals = globals || {};\n\nif (typeof window !== 'undefined') {\n\tglobals.window = window;\n}\n\nif (typeof document !== 'undefined') {\n\tglobals.document = document;\n}\n\nexport default globals;\n","'use strict';\n\n/**\n * A collection of core utility functions.\n * @const\n */\n\nlet compatibilityModeData_;\n\n/**\n * Counter for unique id.\n * @type {Number}\n * @private\n */\nlet uniqueIdCounter_ = 1;\n\n/**\n * Unique id property prefix.\n * @type {String}\n * @protected\n */\nexport const UID_PROPERTY = `core_${(Math.random() * 1e9) >>> 0}`;\n\n/**\n * When defining a class Foo with an abstract method bar(), you can do:\n * Foo.prototype.bar = abstractMethod\n *\n * Now if a subclass of Foo fails to override bar(), an error will be thrown\n * when bar() is invoked.\n *\n * @type {!Function}\n * @throws {Error} when invoked to indicate the method should be overridden.\n */\nexport function abstractMethod() {\n\tthrow Error('Unimplemented abstract method');\n}\n\n/**\n * Disables Metal.js's compatibility mode.\n */\nexport function disableCompatibilityMode() {\n\tcompatibilityModeData_ = undefined;\n}\n\n/**\n * Enables Metal.js's compatibility mode with the following features from rc\n * and 1.x versions:\n * - Using \"key\" to reference component instances. In the current version\n * this should be done via \"ref\" instead. This allows old code still\n * using \"key\" to keep working like before. NOTE: this may cause\n * problems, since \"key\" is meant to be used differently. Only use this\n * if it's not possible to upgrade the code to use \"ref\" instead.\n * @param {Object=} data Optional object with data to specify more\n * details, such as:\n * - renderers {Array} the template renderers that should be in\n * compatibility mode, either their constructors or strings\n * representing them (e.g. 'soy' or 'jsx'). By default, all the ones\n * that extend from IncrementalDomRenderer.\n * @type {Object}\n */\nexport function enableCompatibilityMode(data = {}) {\n\tcompatibilityModeData_ = data;\n}\n\n/**\n * Returns the data used for compatibility mode, or nothing if it hasn't been\n * enabled.\n * @return {Object}\n */\nexport function getCompatibilityModeData() {\n\t// Compatibility mode can be set via the __METAL_COMPATIBILITY__ global var.\n\tif (compatibilityModeData_ === undefined) {\n\t\tif (typeof window !== 'undefined' && window.__METAL_COMPATIBILITY__) {\n\t\t\tenableCompatibilityMode(window.__METAL_COMPATIBILITY__);\n\t\t}\n\t}\n\treturn compatibilityModeData_;\n}\n\n/**\n * Returns the first argument if it's truthy, or the second otherwise.\n * @param {*} a\n * @param {*} b\n * @return {*}\n * @protected\n */\nfunction getFirstTruthy_(a, b) {\n\treturn a || b;\n}\n\n/**\n * Gets the name of the given function. If the current browser doesn't\n * support the `name` property, this will calculate it from the function's\n * content string.\n * @param {!function()} fn\n * @return {string}\n */\nexport function getFunctionName(fn) {\n\tif (!fn.name) {\n\t\tconst str = fn.toString();\n\t\tfn.name = str.substring(9, str.indexOf('('));\n\t}\n\treturn fn.name;\n}\n\n/**\n * Gets the value of a static property in the given class. The value will be\n * inherited from ancestors as expected, unless a custom merge function is given,\n * which can change how the super classes' value for that property will be merged\n * together.\n * The final merged value will be stored in another property, so that it won't\n * be recalculated even if this function is called multiple times.\n * @param {!function()} ctor Class constructor.\n * @param {string} propertyName Property name to be merged.\n * @param {function(*, *):*=} mergeFn Function that receives the merged\n * value of the property so far and the next value to be merged to it.\n * Should return these two merged together. If not passed the final property\n * will be the first truthy value among ancestors.\n * @return {Object}\n */\nexport function getStaticProperty(\n\tctor,\n\tpropertyName,\n\tmergeFn = getFirstTruthy_\n) {\n\tconst mergedName = propertyName + '_MERGED';\n\tif (!ctor.hasOwnProperty(mergedName)) {\n\t\t// eslint-disable-next-line\n\t\tlet merged = ctor.hasOwnProperty(propertyName)\n\t\t\t? ctor[propertyName]\n\t\t\t: null;\n\t\tif (ctor.__proto__ && !ctor.__proto__.isPrototypeOf(Function)) {\n\t\t\tmerged = mergeFn(\n\t\t\t\tmerged,\n\t\t\t\tgetStaticProperty(ctor.__proto__, propertyName, mergeFn)\n\t\t\t);\n\t\t}\n\t\tctor[mergedName] = merged;\n\t}\n\treturn ctor[mergedName];\n}\n\n/**\n * Gets an unique id. If `object` argument is passed, the object is\n * mutated with an unique id. Consecutive calls with the same object\n * reference won't mutate the object again, instead the current object uid\n * returns. See {@link UID_PROPERTY}.\n * @param {Object=} object Optional object to be mutated with the uid. If\n * not specified this method only returns the uid.\n * @param {boolean=} noInheritance Optional flag indicating if this\n * object's uid property can be inherited from parents or not.\n * @throws {Error} when invoked to indicate the method should be overridden.\n * @return {number}\n */\nexport function getUid(object, noInheritance) {\n\tif (object) {\n\t\tlet id = object[UID_PROPERTY];\n\t\tif (noInheritance && !object.hasOwnProperty(UID_PROPERTY)) {\n\t\t\tid = null;\n\t\t}\n\t\treturn id || (object[UID_PROPERTY] = uniqueIdCounter_++);\n\t}\n\treturn uniqueIdCounter_++;\n}\n\n/**\n * The identity function. Returns its first argument.\n * @param {*=} returnValue The single value that will be returned.\n * @return {?} The first argument.\n */\nexport function identityFunction(returnValue) {\n\treturn returnValue;\n}\n\n/**\n * Returns true if the specified value is a boolean.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is boolean.\n */\nexport function isBoolean(val) {\n\treturn typeof val === 'boolean';\n}\n\n/**\n * Returns true if the specified value is not undefined.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is defined.\n */\nexport function isDef(val) {\n\treturn val !== undefined;\n}\n\n/**\n * Returns true if value is not undefined or null.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDefAndNotNull(val) {\n\treturn isDef(val) && !isNull(val);\n}\n\n/**\n * Returns true if value is a document.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDocument(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 9;\n}\n\n/**\n * Returns true if value is a document-fragment.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDocumentFragment(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 11;\n}\n\n/**\n * Returns true if value is a dom element.\n * @param {*} val\n * @return {boolean}\n */\nexport function isElement(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 1;\n}\n\n/**\n * Returns true if the specified value is a function.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is a function.\n */\nexport function isFunction(val) {\n\treturn typeof val === 'function';\n}\n\n/**\n * Returns true if value is null.\n * @param {*} val\n * @return {boolean}\n */\nexport function isNull(val) {\n\treturn val === null;\n}\n\n/**\n * Returns true if the specified value is a number.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is a number.\n */\nexport function isNumber(val) {\n\treturn typeof val === 'number';\n}\n\n/**\n * Returns true if value is a window.\n * @param {*} val\n * @return {boolean}\n */\nexport function isWindow(val) {\n\treturn val !== null && val === val.window;\n}\n\n/**\n * Returns true if the specified value is an object. This includes arrays\n * and functions.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is an object.\n */\nexport function isObject(val) {\n\tconst type = typeof val;\n\treturn (type === 'object' && val !== null) || type === 'function';\n}\n\n/**\n * Returns true if value is a Promise.\n * @param {*} val\n * @return {boolean}\n */\nexport function isPromise(val) {\n\treturn val && typeof val === 'object' && typeof val.then === 'function';\n}\n\n/**\n * Returns true if value is a string.\n * @param {*} val\n * @return {boolean}\n */\nexport function isString(val) {\n\treturn typeof val === 'string' || val instanceof String;\n}\n\n/**\n * Sets to true if running inside Node.js environment with extra check for\n * `process.browser` to skip Karma runner environment. Karma environment has\n * `process` defined even though it runs on the browser.\n * @param {?Object} options Contains `checkEnv` property which if true, checks\n * the NODE_ENV variable. If NODE_ENV equals 'test', the function returns false.\n * @return {boolean}\n */\nexport function isServerSide(options = {checkEnv: true}) {\n\tlet serverSide = typeof process !== 'undefined' && !process.browser;\n\tif (serverSide && options.checkEnv) {\n\t\tserverSide =\n\t\t\ttypeof process.env !== 'undefined' &&\n\t\t\tprocess.env.NODE_ENV !== 'test';\n\t}\n\treturn serverSide;\n}\n\n/**\n * Null function used for default values of callbacks, etc.\n * @return {void} Nothing.\n */\nexport function nullFunction() {}\n","'use strict';\n\n// This file exists just for backwards compatibility, making sure that old\n// default imports for this file still work. It's best to use the named exports\n// for each function instead though, since that allows bundlers like Rollup to\n// reduce the bundle size by removing unused code.\nimport * as core from './coreNamed';\n\nexport default core;\nexport {core};\nexport * from './coreNamed';\n","'use strict';\n\n/**\n * Set of utilities for array operations\n */\nclass array {\n\t/**\n\t * Checks if the given arrays have the same content.\n\t * @param {!Array<*>} arr1\n\t * @param {!Array<*>} arr2\n\t * @return {boolean}\n\t */\n\tstatic equal(arr1, arr2) {\n\t\tif (arr1 === arr2) {\n\t\t\treturn true;\n\t\t}\n\t\tif (arr1.length !== arr2.length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0; i < arr1.length; i++) {\n\t\t\tif (arr1[i] !== arr2[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns the first value in the given array that isn't undefined.\n\t * @param {!Array} arr\n\t * @return {*}\n\t */\n\tstatic firstDefinedValue(arr) {\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tif (arr[i] !== undefined) {\n\t\t\t\treturn arr[i];\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Transforms the input nested array to become flat.\n\t * @param {Array.<*|Array.<*>>} arr Nested array to flatten.\n\t * @param {Array.<*>=} output Optional output array.\n\t * @return {Array.<*>} Flat array.\n\t */\n\tstatic flatten(arr, output = []) {\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tif (Array.isArray(arr[i])) {\n\t\t\t\tarray.flatten(arr[i], output);\n\t\t\t} else {\n\t\t\t\toutput.push(arr[i]);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Removes the first occurrence of a particular value from an array.\n\t * @param {Array.} arr Array from which to remove value.\n\t * @param {T} obj Object to remove.\n\t * @return {boolean} True if an element was removed.\n\t * @template T\n\t */\n\tstatic remove(arr, obj) {\n\t\tconst i = arr.indexOf(obj);\n\t\tlet rv;\n\t\tif ((rv = i >= 0)) {\n\t\t\tarray.removeAt(arr, i);\n\t\t}\n\t\treturn rv;\n\t}\n\n\t/**\n\t * Removes from an array the element at index i\n\t * @param {Array} arr Array or array like object from which to remove value.\n\t * @param {number} i The index to remove.\n\t * @return {boolean} True if an element was removed.\n\t */\n\tstatic removeAt(arr, i) {\n\t\treturn Array.prototype.splice.call(arr, i, 1).length === 1;\n\t}\n\n\t/**\n\t * Slices the given array, just like Array.prototype.slice, but this\n\t * is faster and working on all array-like objects (like arguments).\n\t * @param {!Object} arr Array-like object to slice.\n\t * @param {number} start The index that should start the slice.\n\t * @param {number=} end The index where the slice should end, not\n\t * included in the final array. If not given, all elements after the\n\t * start index will be included.\n\t * @return {!Array}\n\t */\n\tstatic slice(arr, start, end = arr.length) {\n\t\tconst sliced = [];\n\t\tfor (let i = start; i < end; i++) {\n\t\t\tsliced.push(arr[i]);\n\t\t}\n\t\treturn sliced;\n\t}\n}\n\nexport default array;\n","/* !\n * Polyfill from Google's Closure Library.\n * Copyright 2013 The Closure Library Authors. All Rights Reserved.\n */\n\n'use strict';\n\nimport {isServerSide} from '../coreNamed';\n\nconst async = {};\n\n/**\n * Throw an item without interrupting the current execution context. For\n * example, if processing a group of items in a loop, sometimes it is useful\n * to report an error while still allowing the rest of the batch to be\n * processed.\n * @param {*} exception\n */\nasync.throwException = function(exception) {\n\t// Each throw needs to be in its own context.\n\tasync.nextTick(function() {\n\t\tthrow exception;\n\t});\n};\n\n/**\n * Fires the provided callback just before the current callstack unwinds, or as\n * soon as possible after the current JS execution context.\n * @param {function(this:THIS)} callback\n * @param {THIS=} context Object to use as the \"this value\" when calling\n * the provided function.\n * @template THIS\n */\nasync.run = function(callback, context) {\n\tif (!async.run.workQueueScheduled_) {\n\t\t// Nothing is currently scheduled, schedule it now.\n\t\tasync.nextTick(async.run.processWorkQueue);\n\t\tasync.run.workQueueScheduled_ = true;\n\t}\n\n\tasync.run.workQueue_.push(new async.run.WorkItem_(callback, context));\n};\n\n/** @private {boolean} */\nasync.run.workQueueScheduled_ = false;\n\n/** @private {!Array.} */\nasync.run.workQueue_ = [];\n\n/**\n * Run any pending async.run work items. This function is not intended\n * for general use, but for use by entry point handlers to run items ahead of\n * async.nextTick.\n */\nasync.run.processWorkQueue = function() {\n\t// NOTE: additional work queue items may be pushed while processing.\n\twhile (async.run.workQueue_.length) {\n\t\t// Don't let the work queue grow indefinitely.\n\t\tconst workItems = async.run.workQueue_;\n\t\tasync.run.workQueue_ = [];\n\t\tfor (let i = 0; i < workItems.length; i++) {\n\t\t\tconst workItem = workItems[i];\n\t\t\ttry {\n\t\t\t\tworkItem.fn.call(workItem.scope);\n\t\t\t} catch (e) {\n\t\t\t\tasync.throwException(e);\n\t\t\t}\n\t\t}\n\t}\n\n\t// There are no more work items, reset the work queue.\n\tasync.run.workQueueScheduled_ = false;\n};\n\n/**\n * @constructor\n * @final\n * @struct\n * @private\n *\n * @param {function()} fn\n * @param {Object|null|undefined} scope\n */\nasync.run.WorkItem_ = function(fn, scope) {\n\t/** @const */\n\tthis.fn = fn;\n\t/** @const */\n\tthis.scope = scope;\n};\n\n/**\n * Fires the provided callbacks as soon as possible after the current JS\n * execution context. setTimeout(…, 0) always takes at least 5ms for legacy\n * reasons.\n * @param {function(this:SCOPE)} callback Callback function to fire as soon as\n * possible.\n * @param {SCOPE=} context Object in whose scope to call the listener.\n * @template SCOPE\n */\nasync.nextTick = function(callback, context) {\n\tlet cb = callback;\n\tif (context) {\n\t\tcb = callback.bind(context);\n\t}\n\tcb = async.nextTick.wrapCallback_(cb);\n\t// Look for and cache the custom fallback version of setImmediate.\n\tif (!async.nextTick.setImmediate_) {\n\t\tif (\n\t\t\ttypeof setImmediate === 'function' &&\n\t\t\tisServerSide({checkEnv: false})\n\t\t) {\n\t\t\tasync.nextTick.setImmediate_ = setImmediate;\n\t\t} else {\n\t\t\t// eslint-disable-next-line\n\t\t\tasync.nextTick.setImmediate_ = async.nextTick.getSetImmediateEmulator_();\n\t\t}\n\t}\n\tasync.nextTick.setImmediate_(cb);\n};\n\n/**\n * Cache for the setImmediate implementation.\n * @type {function(function())}\n * @private\n */\nasync.nextTick.setImmediate_ = null;\n\n/**\n * Determines the best possible implementation to run a function as soon as\n * the JS event loop is idle.\n * @return {function(function())} The \"setImmediate\" implementation.\n * @private\n */\nasync.nextTick.getSetImmediateEmulator_ = function() {\n\t// Create a private message channel and use it to postMessage empty messages\n\t// to ourselves.\n\tlet Channel;\n\n\t// Verify if variable is defined on the current runtime (i.e., node, browser).\n\t// Can't use typeof enclosed in a function (such as core.isFunction) or an\n\t// exception will be thrown when the function is called on an environment\n\t// where the variable is undefined.\n\tif (typeof MessageChannel === 'function') {\n\t\tChannel = MessageChannel;\n\t}\n\n\t// If MessageChannel is not available and we are in a browser, implement\n\t// an iframe based polyfill in browsers that have postMessage and\n\t// document.addEventListener. The latter excludes IE8 because it has a\n\t// synchronous postMessage implementation.\n\tif (\n\t\ttypeof Channel === 'undefined' &&\n\t\ttypeof window !== 'undefined' &&\n\t\twindow.postMessage &&\n\t\twindow.addEventListener\n\t) {\n\t\t/** @constructor */\n\t\tChannel = function() {\n\t\t\t// Make an empty, invisible iframe.\n\t\t\tconst iframe = document.createElement('iframe');\n\t\t\tiframe.style.display = 'none';\n\t\t\tiframe.src = '';\n\t\t\tiframe.title = '';\n\t\t\tdocument.documentElement.appendChild(iframe);\n\t\t\tconst win = iframe.contentWindow;\n\t\t\tconst doc = win.document;\n\t\t\tdoc.open();\n\t\t\tdoc.write('');\n\t\t\tdoc.close();\n\t\t\tconst message = 'callImmediate' + Math.random();\n\t\t\tconst origin = win.location.protocol + '//' + win.location.host;\n\t\t\tconst onmessage = function(e) {\n\t\t\t\t// Validate origin and message to make sure that this message was\n\t\t\t\t// intended for us.\n\t\t\t\tif (e.origin !== origin && e.data !== message) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.port1.onmessage();\n\t\t\t}.bind(this);\n\t\t\twin.addEventListener('message', onmessage, false);\n\t\t\tthis.port1 = {};\n\t\t\tthis.port2 = {\n\t\t\t\tpostMessage: function() {\n\t\t\t\t\twin.postMessage(message, origin);\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\t}\n\tif (typeof Channel !== 'undefined') {\n\t\tconst channel = new Channel();\n\t\t// Use a fifo linked list to call callbacks in the right order.\n\t\tlet head = {};\n\t\tlet tail = head;\n\t\tchannel.port1.onmessage = function() {\n\t\t\thead = head.next;\n\t\t\tconst cb = head.cb;\n\t\t\thead.cb = null;\n\t\t\tcb();\n\t\t};\n\t\treturn function(cb) {\n\t\t\ttail.next = {\n\t\t\t\tcb: cb,\n\t\t\t};\n\t\t\ttail = tail.next;\n\t\t\tchannel.port2.postMessage(0);\n\t\t};\n\t}\n\t// Implementation for IE6-8: Script elements fire an asynchronous\n\t// onreadystatechange event when inserted into the DOM.\n\tif (\n\t\ttypeof document !== 'undefined' &&\n\t\t'onreadystatechange' in document.createElement('script')\n\t) {\n\t\treturn function(cb) {\n\t\t\tlet script = document.createElement('script');\n\t\t\tscript.onreadystatechange = function() {\n\t\t\t\t// Clean up and call the callback.\n\t\t\t\tscript.onreadystatechange = null;\n\t\t\t\tscript.parentNode.removeChild(script);\n\t\t\t\tscript = null;\n\t\t\t\tcb();\n\t\t\t\tcb = null;\n\t\t\t};\n\t\t\tdocument.documentElement.appendChild(script);\n\t\t};\n\t}\n\t// Fall back to setTimeout with 0. In browsers this creates a delay of 5ms\n\t// or more.\n\treturn function(cb) {\n\t\tsetTimeout(cb, 0);\n\t};\n};\n\n/**\n * Helper function that is overrided to protect callbacks with entry point\n * monitor if the application monitors entry points.\n * @param {function()} callback Callback function to fire as soon as possible.\n * @return {function()} The wrapped callback.\n * @private\n */\nasync.nextTick.wrapCallback_ = function(callback) {\n\treturn callback;\n};\n\nexport default async;\n","'use strict';\n\n/**\n * Disposable utility. When inherited provides the `dispose` function to its\n * subclass, which is responsible for disposing of any object references\n * when an instance won't be used anymore. Subclasses should override\n * `disposeInternal` to implement any specific disposing logic.\n * @constructor\n */\nclass Disposable {\n\t/**\n\t * Disposable constructor\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Flag indicating if this instance has already been disposed.\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.disposed_ = false;\n\t}\n\n\t/**\n\t * Disposes of this instance's object references. Calls `disposeInternal`.\n\t */\n\tdispose() {\n\t\tif (!this.disposed_) {\n\t\t\tthis.disposeInternal();\n\t\t\tthis.disposed_ = true;\n\t\t}\n\t}\n\n\t/**\n\t * Subclasses should override this method to implement any specific\n\t * disposing logic (like clearing references and calling `dispose` on other\n\t * disposables).\n\t */\n\tdisposeInternal() {}\n\n\t/**\n\t * Checks if this instance has already been disposed.\n\t * @return {boolean}\n\t */\n\tisDisposed() {\n\t\treturn this.disposed_;\n\t}\n}\n\nexport default Disposable;\n","'use strict';\n\n/**\n * Set of utilities for object operations\n */\nclass object {\n\t/**\n\t * Copies all the members of a source object to a target object.\n\t * @param {Object} target Target object.\n\t * @param {...Object} var_args The objects from which values will be copied.\n\t * @return {Object} Returns the target object reference.\n\t */\n\tstatic mixin(target, ...args) {\n\t\tlet key;\n\t\tlet source;\n\t\tfor (let i = 0; i < args.length; i++) {\n\t\t\tsource = args[i];\n\t\t\t// Possible prototype chain leak, breaks 1 metal-dom and\n\t\t\t// 1 metal-incremental-dom test if guard-for-in rule is addressed\n\t\t\t// eslint-disable-next-line\n\t\t\tfor (key in source) {\n\t\t\t\ttarget[key] = source[key];\n\t\t\t}\n\t\t}\n\t\treturn target;\n\t}\n\n\t/**\n\t * Returns an object based on its fully qualified external name.\n\t * @param {string} name The fully qualified name.\n\t * @param {object=} scope The object within which to look; default is\n\t * window.\n\t * @return {?} The value (object or primitive) or, if not found, undefined.\n\t */\n\tstatic getObjectByName(name, scope = window) {\n\t\tconst parts = name.split('.');\n\t\treturn parts.reduce((part, key) => part[key], scope);\n\t}\n\n\t/**\n\t * Returns a new object with the same keys as the given one, but with\n\t * their values set to the return values of the specified function.\n\t * @param {!Object} obj\n\t * @param {!function(string, *)} fn\n\t * @return {!Object}\n\t */\n\tstatic map(obj, fn) {\n\t\tconst mappedObj = {};\n\t\tconst keys = Object.keys(obj);\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tmappedObj[keys[i]] = fn(keys[i], obj[keys[i]]);\n\t\t}\n\t\treturn mappedObj;\n\t}\n\n\t/**\n\t * Checks if the two given objects are equal. This is done via a shallow\n\t * check, including only the keys directly contained by the 2 objects.\n\t * @param {Object} obj1\n\t * @param {Object} obj2\n\t * @return {boolean}\n\t */\n\tstatic shallowEqual(obj1, obj2) {\n\t\tif (obj1 === obj2) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst keys1 = Object.keys(obj1);\n\t\tconst keys2 = Object.keys(obj2);\n\t\tif (keys1.length !== keys2.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < keys1.length; i++) {\n\t\t\tif (obj1[keys1[i]] !== obj2[keys1[i]]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\n\nexport default object;\n","'use strict';\n\n/**\n * Set of utilities for string operations\n */\nclass string {\n\t/**\n\t * Compares the given strings without taking the case into account.\n\t * @param {string|number} str1\n\t * @param {string|number} str2\n\t * @return {number} Either -1, 0 or 1, according to if the first string is\n\t * \"smaller\", equal or \"bigger\" than the second given string.\n\t */\n\tstatic caseInsensitiveCompare(str1, str2) {\n\t\tconst test1 = String(str1).toLowerCase();\n\t\tconst test2 = String(str2).toLowerCase();\n\n\t\tif (test1 < test2) {\n\t\t\treturn -1;\n\t\t} else if (test1 === test2) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\t/**\n\t * Removes the breaking spaces from the left and right of the string and\n\t * collapses the sequences of breaking spaces in the middle into single spaces.\n\t * The original and the result strings render the same way in HTML.\n\t * @param {string} str A string in which to collapse spaces.\n\t * @return {string} Copy of the string with normalized breaking spaces.\n\t */\n\tstatic collapseBreakingSpaces(str) {\n\t\treturn str\n\t\t\t.replace(/[\\t\\r\\n ]+/g, ' ')\n\t\t\t.replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g, '');\n\t}\n\n\t/**\n\t * Escapes characters in the string that are not safe to use in a RegExp.\n\t * @param {*} str The string to escape. If not a string, it will be casted\n\t * to one.\n\t * @return {string} A RegExp safe, escaped copy of {@code s}.\n\t */\n\tstatic escapeRegex(str) {\n\t\treturn String(str)\n\t\t\t.replace(/([-()[\\]{}+?*.$^|,:#}\n\t */\n\tgetAll(name) {\n\t\treturn this.values[name.toLowerCase()];\n\t}\n\n\t/**\n\t * Returns true if the map is empty, false otherwise.\n\t * @return {boolean}\n\t */\n\tisEmpty() {\n\t\treturn this.size() === 0;\n\t}\n\n\t/**\n\t * Gets array of key names.\n\t * @return {Array.}\n\t */\n\tnames() {\n\t\treturn Object.keys(this.values).map((key) => this.keys[key]);\n\t}\n\n\t/**\n\t * Removes all values from a key name.\n\t * @param {string} name\n\t * @chainable\n\t */\n\tremove(name) {\n\t\tdelete this.keys[name.toLowerCase()];\n\t\tdelete this.values[name.toLowerCase()];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the value of a key name. Relevant to replace the current values with\n\t * a new one.\n\t * @param {string} name\n\t * @param {*} value\n\t * @chainable\n\t */\n\tset(name, value) {\n\t\tthis.keys[name.toLowerCase()] = name;\n\t\tthis.values[name.toLowerCase()] = [value];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets the size of the map key names.\n\t * @return {number}\n\t */\n\tsize() {\n\t\treturn this.names().length;\n\t}\n\n\t/**\n\t * Returns the parsed values as a string.\n\t * @return {string}\n\t */\n\ttoString() {\n\t\treturn JSON.stringify(this.values);\n\t}\n}\n\nexport default MultiMap;\n","'use strict';\n\nimport { array } from 'metal';\n\n/**\n * Generic tree node data structure with arbitrary number of child nodes.\n * @param {V} value Value.\n * @constructor\n */\nclass TreeNode {\n\n\tconstructor(value) {\n\t\t/**\n\t\t * The value.\n\t\t * @private {V}\n\t\t */\n\t\tthis.value_ = value;\n\n\t\t/**\n\t\t * Reference to the parent node or null if it has no parent.\n\t\t * @private {TreeNode}\n\t\t */\n\t\tthis.parent_ = null;\n\n\t\t/**\n\t\t * Child nodes or null in case of leaf node.\n\t\t * @private {Array}\n\t\t */\n\t\tthis.children_ = null;\n\t}\n\n\t/**\n\t * Appends a child node to this node.\n\t * @param {!TreeNode} child Orphan child node.\n\t */\n\taddChild(child) {\n\t\tassertChildHasNoParent(child);\n\t\tchild.setParent(this);\n\t\tthis.children_ = this.children_ || [];\n\t\tthis.children_.push(child);\n\t}\n\n\t/**\n\t * Tells whether this node is the ancestor of the given node.\n\t * @param {!TreeNode} node A node.\n\t * @return {boolean} Whether this node is the ancestor of {@code node}.\n\t */\n\tcontains(node) {\n\t\tlet current = node.getParent();\n\t\twhile (current) {\n\t\t\tif (current === this) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcurrent = current.getParent();\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * @return {!Array} All ancestor nodes in bottom-up order.\n\t */\n\tgetAncestors() {\n\t\tlet ancestors = [];\n\t\tlet node = this.getParent();\n\t\twhile (node) {\n\t\t\tancestors.push(node);\n\t\t\tnode = node.getParent();\n\t\t}\n\t\treturn ancestors;\n\t}\n\n\t/**\n\t * Gets the child node of this node at the given index.\n\t * @param {number} index Child index.\n\t * @return {?TreeNode} The node at the given index\n\t * or null if not found.\n\t */\n\tgetChildAt(index) {\n\t\treturn this.getChildren()[index] || null;\n\t}\n\n\t/**\n\t * @return {?Array} Child nodes or null in case of leaf node.\n\t */\n\tgetChildren() {\n\t\treturn this.children_ || TreeNode.EMPTY_ARRAY;\n\t}\n\n\t/**\n\t * @return {number} The number of children.\n\t */\n\tgetChildCount() {\n\t\treturn this.getChildren().length;\n\t}\n\n\t/**\n\t * @return {number} The number of ancestors of the node.\n\t */\n\tgetDepth() {\n\t\tlet depth = 0;\n\t\tlet node = this;\n\t\twhile (node.getParent()) {\n\t\t\tdepth++;\n\t\t\tnode = node.getParent();\n\t\t}\n\t\treturn depth;\n\t}\n\n\t/**\n\t * @return {?TreeNode} Parent node or null if it has no parent.\n\t */\n\tgetParent() {\n\t\treturn this.parent_;\n\t}\n\n\t/**\n\t * @return {!TreeNode} The root of the tree structure, i.e. the farthest\n\t * ancestor of the node or the node itself if it has no parents.\n\t */\n\tgetRoot() {\n\t\tlet root = this;\n\t\twhile (root.getParent()) {\n\t\t\troot = root.getParent();\n\t\t}\n\t\treturn root;\n\t}\n\n\t/**\n\t * Gets the value.\n\t * @return {V} The value.\n\t */\n\tgetValue() {\n\t\treturn this.value_;\n\t}\n\n\t/**\n\t * @return {boolean} Whether the node is a leaf node.\n\t */\n\tisLeaf() {\n\t\treturn !this.getChildCount();\n\t}\n\n\t/**\n\t * Removes the given child node of this node.\n\t * @param {TreeNode} child The node to remove.\n\t * @return {TreeNode} The removed node if any, null otherwise.\n\t */\n\tremoveChild(child) {\n\t\tif (array.remove(this.getChildren(), child)) {\n\t\t\treturn child;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Sets the parent node of this node. The callers must ensure that the\n\t * parent node and only that has this node among its children.\n\t * @param {TreeNode} parent The parent to set. If null, the node will be\n\t * detached from the tree.\n\t * @protected\n\t */\n\tsetParent(parent) {\n\t\tthis.parent_ = parent;\n\t}\n\n\t/**\n\t * Traverses the subtree. The first callback starts with this node,\n\t * and visits the descendant nodes depth-first, in preorder.\n\t * The second callback, starts with deepest child then visits\n\t * the ancestor nodes depth-first, in postorder. E.g.\n\t *\n\t * \t A\n\t * / \\\n\t * B C\n\t * / / \\\n\t * D E F\n\t *\n\t * preorder -> ['A', 'B', 'D', 'C', 'E', 'F']\n\t * postorder -> ['D', 'B', 'E', 'F', 'C', 'A']\n\t *\n\t * @param {function=} opt_preorderFn The callback to execute when visiting a node.\n\t * @param {function=} opt_postorderFn The callback to execute before leaving a node.\n\t */\n\ttraverse(opt_preorderFn, opt_postorderFn) {\n\t\tif (opt_preorderFn) {\n\t\t\topt_preorderFn(this);\n\t\t}\n\t\tthis.getChildren().forEach((child) => child.traverse(opt_preorderFn, opt_postorderFn));\n\t\tif (opt_postorderFn) {\n\t\t\topt_postorderFn(this);\n\t\t}\n\t}\n\n}\n\n/**\n * Constant for empty array to avoid unnecessary allocations.\n * @private\n */\nTreeNode.EMPTY_ARRAY = [];\n\n/**\n * Asserts that child has no parent.\n * @param {TreeNode} child A child.\n * @private\n */\nconst assertChildHasNoParent = function(child) {\n\tif (child.getParent()) {\n\t\tthrow new Error('Cannot add child with parent.');\n\t}\n};\n\nexport default TreeNode;\n","'use strict';\n\nimport { isDef, string } from 'metal';\nimport parse from './parse';\nimport { MultiMap } from 'metal-structs';\n\nvar parseFn_ = parse;\n\nclass Uri {\n\n\t/**\n\t * This class contains setters and getters for the parts of the URI.\n\t * The following figure displays an example URIs and their component parts.\n\t *\n\t * path\n\t *\t ┌───┴────┐\n\t *\t abc://example.com:123/path/data?key=value#fragid1\n\t *\t └┬┘ └────┬────┘ └┬┘ └───┬───┘ └──┬──┘\n\t * protocol hostname port search hash\n\t * └──────┬───────┘\n\t * host\n\t *\n\t * @param {*=} opt_uri Optional string URI to parse\n\t * @constructor\n\t */\n\tconstructor(opt_uri = '') {\n\t\tthis.url = Uri.parse(this.maybeAddProtocolAndHostname_(opt_uri));\n\t}\n\n\t/**\n\t * Adds parameters to uri from a MultiMap as source.\n\t * @param {MultiMap} multimap The MultiMap containing the\n\t * parameters.\n\t * @protected\n\t * @chainable\n\t */\n\taddParametersFromMultiMap(multimap) {\n\t\tmultimap.names().forEach((name) => {\n\t\t\tmultimap.getAll(name).forEach((value) => {\n\t\t\t\tthis.addParameterValue(name, value);\n\t\t\t});\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds the value of the named query parameters.\n\t * @param {string} key The parameter to set.\n\t * @param {*} value The new value. Will be explicitly casted to String.\n\t * @chainable\n\t */\n\taddParameterValue(name, value) {\n\t\tthis.ensureQueryInitialized_();\n\t\tif (isDef(value)) {\n\t\t\tvalue = String(value);\n\t\t}\n\t\tthis.query.add(name, value);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds the values of the named query parameter.\n\t * @param {string} key The parameter to set.\n\t * @param {*} value The new value.\n\t * @chainable\n\t */\n\taddParameterValues(name, values) {\n\t\tvalues.forEach((value) => this.addParameterValue(name, value));\n\t\treturn this;\n\t}\n\n\t/**\n\t * Ensures query internal map is initialized and synced with initial value\n\t * extracted from URI search part.\n\t * @protected\n\t */\n\tensureQueryInitialized_() {\n\t\tif (this.query) {\n\t\t\treturn;\n\t\t}\n\t\tthis.query = new MultiMap();\n\t\tvar search = this.url.search;\n\t\tif (search) {\n\t\t\tsearch.substring(1).split('&').forEach((param) => {\n\t\t\t\tvar [key, value] = param.split('=');\n\t\t\t\tif (isDef(value)) {\n\t\t\t\t\tvalue = Uri.urlDecode(value);\n\t\t\t\t}\n\t\t\t\tthis.addParameterValue(key, value);\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Gets the hash part of uri.\n\t * @return {string}\n\t */\n\tgetHash() {\n\t\treturn this.url.hash || '';\n\t}\n\n\t/**\n\t * Gets the host part of uri. E.g. [hostname]:[port].\n\t * @return {string}\n\t */\n\tgetHost() {\n\t\tvar host = this.getHostname();\n\t\tif (host) {\n\t\t\tvar port = this.getPort();\n\t\t\tif (port && port !== '80') {\n\t\t\t\thost += ':' + port;\n\t\t\t}\n\t\t}\n\t\treturn host;\n\t}\n\n\t/**\n\t * Gets the hostname part of uri without protocol and port.\n\t * @return {string}\n\t */\n\tgetHostname() {\n\t\tvar hostname = this.url.hostname;\n\t\tif (hostname === Uri.HOSTNAME_PLACEHOLDER) {\n\t\t\treturn '';\n\t\t}\n\t\treturn hostname;\n\t}\n\n\t/**\n\t * Gets the origin part of uri. E.g. http://[hostname]:[port].\n\t * @return {string}\n\t */\n\tgetOrigin() {\n\t\tvar host = this.getHost();\n\t\tif (host) {\n\t\t\treturn this.getProtocol() + '//' + host;\n\t\t}\n\t\treturn '';\n\t}\n\n\t/**\n\t * Returns the first value for a given parameter or undefined if the given\n\t * parameter name does not appear in the query string.\n\t * @param {string} paramName Unescaped parameter name.\n\t * @return {string|undefined} The first value for a given parameter or\n\t * undefined if the given parameter name does not appear in the query\n\t * string.\n\t */\n\tgetParameterValue(name) {\n\t\tthis.ensureQueryInitialized_();\n\t\treturn this.query.get(name);\n\t}\n\n\t/**\n\t * Returns the values for a given parameter as a list of decoded\n\t * query parameter values.\n\t * @param {string} name The parameter to get values for.\n\t * @return {!Array} The values for a given parameter as a list of decoded\n\t * query parameter values.\n\t */\n\tgetParameterValues(name) {\n\t\tthis.ensureQueryInitialized_();\n\t\treturn this.query.getAll(name);\n\t}\n\n\t/**\n\t * Returns the names of the parameters.\n\t * @return {!Array} The names for the parameters as a list of\n\t * strings.\n\t */\n\tgetParameterNames() {\n\t\tthis.ensureQueryInitialized_();\n\t\treturn this.query.names();\n\t}\n\n\t/**\n\t * Gets the function currently being used to parse URIs.\n\t * @return {!function()}\n\t */\n\tstatic getParseFn() {\n\t\treturn parseFn_;\n\t}\n\n\t/**\n\t * Gets the pathname part of uri.\n\t * @return {string}\n\t */\n\tgetPathname() {\n\t\treturn this.url.pathname;\n\t}\n\n\t/**\n\t * Gets the port number part of uri as string.\n\t * @return {string}\n\t */\n\tgetPort() {\n\t\treturn this.url.port;\n\t}\n\n\t/**\n\t * Gets the protocol part of uri. E.g. http:.\n\t * @return {string}\n\t */\n\tgetProtocol() {\n\t\treturn this.url.protocol;\n\t}\n\n\t/**\n\t * Gets the search part of uri. Search value is retrieved from query\n\t * parameters.\n\t * @return {string}\n\t */\n\tgetSearch() {\n\t\tvar search = '';\n\t\tvar querystring = '';\n\t\tthis.getParameterNames().forEach((name) => {\n\t\t\tthis.getParameterValues(name).forEach((value) => {\n\t\t\t\tquerystring += name;\n\t\t\t\tif (isDef(value)) {\n\t\t\t\t\tquerystring += '=' + encodeURIComponent(value);\n\t\t\t\t}\n\t\t\t\tquerystring += '&';\n\t\t\t});\n\t\t});\n\t\tquerystring = querystring.slice(0, -1);\n\t\tif (querystring) {\n\t\t\tsearch += '?' + querystring;\n\t\t}\n\t\treturn search;\n\t}\n\n\t/**\n\t * Checks if uri contains the parameter.\n\t * @param {string} name\n\t * @return {boolean}\n\t */\n\thasParameter(name) {\n\t\tthis.ensureQueryInitialized_();\n\t\treturn this.query.contains(name);\n\t}\n\n\t/**\n\t * Makes this URL unique by adding a random param to it. Useful for avoiding\n\t * cache.\n\t */\n\tmakeUnique() {\n\t\tthis.setParameterValue(Uri.RANDOM_PARAM, string.getRandomString());\n\t\treturn this;\n\t}\n\n\t/**\n\t * Maybe adds protocol and a hostname placeholder on a parial URI if needed.\n\t * Relevent for compatibility with URL native object.\n\t * @param {string=} opt_uri\n\t * @return {string} URI with protocol and hostname placeholder.\n\t */\n\tmaybeAddProtocolAndHostname_(opt_uri) {\n\t\tvar url = opt_uri;\n\t\tif (opt_uri.indexOf('://') === -1 &&\n\t\t\topt_uri.indexOf('javascript:') !== 0) { // jshint ignore:line\n\n\t\t\turl = Uri.DEFAULT_PROTOCOL;\n\t\t\tif (opt_uri[0] !== '/' || opt_uri[1] !== '/') {\n\t\t\t\turl += '//';\n\t\t\t}\n\n\t\t\tswitch (opt_uri.charAt(0)) {\n\t\t\t\tcase '.':\n\t\t\t\tcase '?':\n\t\t\t\tcase '#':\n\t\t\t\t\turl += Uri.HOSTNAME_PLACEHOLDER;\n\t\t\t\t\turl += '/';\n\t\t\t\t\turl += opt_uri;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '':\n\t\t\t\tcase '/':\n\t\t\t\t\tif (opt_uri[1] !== '/') {\n\t\t\t\t\t\turl += Uri.HOSTNAME_PLACEHOLDER;\n\t\t\t\t\t}\n\t\t\t\t\turl += opt_uri;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\turl += opt_uri;\n\t\t\t}\n\t\t}\n\t\treturn url;\n\t}\n\n\t/**\n\t * Parses the given uri string into an object.\n\t * @param {*=} opt_uri Optional string URI to parse\n\t */\n\tstatic parse(opt_uri) {\n\t\treturn parseFn_(opt_uri);\n\t}\n\n\t/**\n\t * Removes the named query parameter.\n\t * @param {string} name The parameter to remove.\n\t * @chainable\n\t */\n\tremoveParameter(name) {\n\t\tthis.ensureQueryInitialized_();\n\t\tthis.query.remove(name);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes uniqueness parameter of the uri.\n\t * @chainable\n\t */\n\tremoveUnique() {\n\t\tthis.removeParameter(Uri.RANDOM_PARAM);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the hash.\n\t * @param {string} hash\n\t * @chainable\n\t */\n\tsetHash(hash) {\n\t\tthis.url.hash = hash;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the hostname.\n\t * @param {string} hostname\n\t * @chainable\n\t */\n\tsetHostname(hostname) {\n\t\tthis.url.hostname = hostname;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the value of the named query parameters, clearing previous values\n\t * for that key.\n\t * @param {string} key The parameter to set.\n\t * @param {*} value The new value.\n\t * @chainable\n\t */\n\tsetParameterValue(name, value) {\n\t\tthis.removeParameter(name);\n\t\tthis.addParameterValue(name, value);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the values of the named query parameters, clearing previous values\n\t * for that key.\n\t * @param {string} key The parameter to set.\n\t * @param {*} value The new value.\n\t * @chainable\n\t */\n\tsetParameterValues(name, values) {\n\t\tthis.removeParameter(name);\n\t\tvalues.forEach((value) => this.addParameterValue(name, value));\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the pathname.\n\t * @param {string} pathname\n\t * @chainable\n\t */\n\tsetPathname(pathname) {\n\t\tthis.url.pathname = pathname;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the port number.\n\t * @param {*} port Port number.\n\t * @chainable\n\t */\n\tsetPort(port) {\n\t\tthis.url.port = port;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the function that will be used for parsing the original string uri\n\t * into an object.\n\t * @param {!function()} parseFn\n\t */\n\tstatic setParseFn(parseFn) {\n\t\tparseFn_ = parseFn;\n\t}\n\n\t/**\n\t * Sets the protocol. If missing http: is used as default.\n\t * @param {string} protocol\n\t * @chainable\n\t */\n\tsetProtocol(protocol) {\n\t\tthis.url.protocol = protocol;\n\t\tif (this.url.protocol[this.url.protocol.length - 1] !== ':') {\n\t\t\tthis.url.protocol += ':';\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * @return {string} The string form of the url.\n\t * @override\n\t */\n\ttoString() {\n\t\tvar href = '';\n\t\tvar host = this.getHost();\n\t\tif (host) {\n\t\t\thref += this.getProtocol() + '//';\n\t\t}\n\t\thref += host + this.getPathname() + this.getSearch() + this.getHash();\n\t\treturn href;\n\t}\n\n\t/**\n\t * Joins the given paths.\n\t * @param {string} basePath\n\t * @param {...string} ...paths Any number of paths to be joined with the base url.\n\t * @static\n\t */\n\tstatic joinPaths(basePath, ...paths) {\n\t\tif (basePath.charAt(basePath.length - 1) === '/') {\n\t\t\tbasePath = basePath.substring(0, basePath.length - 1);\n\t\t}\n\t\tpaths = paths.map(path => path.charAt(0) === '/' ? path.substring(1) : path);\n\t\treturn [basePath].concat(paths).join('/').replace(/\\/$/, '');\n\t}\n\n\t/**\n\t * URL-decodes the string. We need to specially handle '+'s because\n\t * the javascript library doesn't convert them to spaces.\n\t * @param {string} str The string to url decode.\n\t * @return {string} The decoded {@code str}.\n\t */\n\tstatic urlDecode(str) {\n\t\treturn decodeURIComponent(str.replace(/\\+/g, ' '));\n\t}\n\n}\n\n/**\n * Default protocol value.\n * @type {string}\n * @default http:\n * @static\n */\nconst isSecure = () =>\n\t(typeof window !== 'undefined' &&\n\t\twindow.location &&\n\t\twindow.location.protocol &&\n\t\twindow.location.protocol.indexOf('https') === 0);\n\nUri.DEFAULT_PROTOCOL = isSecure() ? 'https:' : 'http:';\n\n/**\n * Hostname placeholder. Relevant to internal usage only.\n * @type {string}\n * @static\n */\nUri.HOSTNAME_PLACEHOLDER = 'hostname' + Date.now();\n\n/**\n * Name used by the param generated by `makeUnique`.\n * @type {string}\n * @static\n */\nUri.RANDOM_PARAM = 'zx';\n\nexport default Uri;\n","'use strict';\n\nimport { exitDocument } from 'metal-dom';\nimport globals from '../globals/globals';\nimport Uri from 'metal-uri';\n\n/**\n * A collection of static utility functions.\n * @const\n */\nclass utils {\n\n\t/**\n\t * Copies attributes form source node to target node.\n\t * @return {void}\n\t * @static\n\t */\n\tstatic copyNodeAttributes(source, target) {\n\t\tArray.prototype.slice.call(source.attributes).forEach((attribute) => target.setAttribute(attribute.name, attribute.value));\n\t}\n\n\t/**\n\t * Gets the current browser path including hashbang.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getCurrentBrowserPath() {\n\t\treturn this.getCurrentBrowserPathWithoutHash() + globals.window.location.hash;\n\t}\n\n\t/**\n\t * Gets the current browser path excluding hashbang.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getCurrentBrowserPathWithoutHash() {\n\t\treturn globals.window.location.pathname + globals.window.location.search;\n\t}\n\n\t/**\n\t * Gets the given node offset coordinates.\n\t * @return {!object}\n\t * @static\n\t */\n\tstatic getNodeOffset(node) {\n\t\tlet [offsetLeft, offsetTop] = [0, 0];\n\t\tdo {\n\t\t\toffsetLeft += node.offsetLeft;\n\t\t\toffsetTop += node.offsetTop;\n\t\t\tnode = node.offsetParent;\n\t\t} while (node);\n\t\treturn {\n\t\t\toffsetLeft,\n\t\t\toffsetTop\n\t\t};\n\t}\n\n\t/**\n\t * Extracts the path part of an url.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getUrlPath(url) {\n\t\tvar uri = new Uri(url);\n\t\treturn uri.getPathname() + uri.getSearch() + uri.getHash();\n\t}\n\n\t/**\n\t * Extracts the path part of an url without hashbang.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getUrlPathWithoutHash(url) {\n\t\tvar uri = new Uri(url);\n\t\treturn uri.getPathname() + uri.getSearch();\n\t}\n\n\t/**\n\t * Extracts the path part of an url without hashbang and query search.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getUrlPathWithoutHashAndSearch(url) {\n\t\tvar uri = new Uri(url);\n\t\treturn uri.getPathname();\n\t}\n\n\t/**\n\t * Checks if url is in the same browser current url excluding the hashbang.\n\t * @param {!string} url\n\t * @return {boolean}\n\t * @static\n\t */\n\tstatic isCurrentBrowserPath(url) {\n\t\tif (url) {\n\t\t\tconst currentBrowserPath = this.getCurrentBrowserPathWithoutHash();\n\t\t\t// the getUrlPath will create a Uri and will normalize the path and\n\t\t\t// remove the trailling '/' for properly comparing paths.\n\t\t\treturn utils.getUrlPathWithoutHash(url) === this.getUrlPath(currentBrowserPath);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Returns true if HTML5 History api is supported.\n\t * @return {boolean}\n\t * @static\n\t */\n\tstatic isHtml5HistorySupported() {\n\t\treturn !!(globals.window.history && globals.window.history.pushState);\n\t}\n\n\t/**\n\t * Checks if a given url is a valid http(s) uri and returns the formed Uri\n\t * or false if the parsing failed\n\t * @return {Uri|boolean}\n\t * @static\n\t */\n\tstatic isWebUri(url) {\n\t\ttry {\n\t\t\treturn new Uri(url);\n\t\t} catch (err) {\n\t\t\tconsole.error(`${err.message} ${url}`);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Removes all attributes form node.\n\t * @return {void}\n\t * @static\n\t */\n\tstatic clearNodeAttributes(node) {\n\t\tArray.prototype.slice.call(node.attributes).forEach((attribute) => node.removeAttribute(attribute.name));\n\t}\n\n\t/**\n\t * Remove elements from the document.\n\t * @param {!Array} elements\n\t */\n\tstatic removeElementsFromDocument(elements) {\n\t\telements.forEach((element) => exitDocument(element));\n\t}\n\n\t/**\n\t* Removes trailing slash in path.\n\t* @param {!string}\n\t* @return {string}\n\t*/\n\tstatic removePathTrailingSlash(path) {\n\t\tvar length = path ? path.length : 0;\n\t\tif (length > 1 && path[length - 1] === '/') {\n\t\t\tpath = path.substr(0, length - 1);\n\t\t}\n\t\treturn path;\n\t}\n\n\t/**\n\t * Adds a random suffix to the href attribute of the element.\n\t * @param {!element} element\n\t * @return {element}\n\t */\n\tstatic setElementWithRandomHref(element) {\n\t\telement.href = element.href + '?q=' + Math.random();\n\t\treturn element;\n\t}\n\n\t/**\n\t * Overrides document referrer\n\t * @param {string} referrer\n\t * @static\n\t */\n\tstatic setReferrer(referrer) {\n\t\tObject.defineProperty(globals.document, 'referrer', {\n\t\t\tconfigurable: true,\n\t\t\tget: function() {\n\t\t\t\treturn referrer;\n\t\t\t}\n\t\t});\n\t}\n}\n\nexport default utils;\n","'use strict';\n\nexport default {\n\tbasePath: 'data-senna-base-path',\n\tlinkSelector: 'data-senna-link-selector',\n\tloadingCssClass: 'data-senna-loading-css-class',\n\tsenna: 'data-senna',\n\tdispatch: 'data-senna-dispatch',\n\tsurface: 'data-senna-surface',\n\tupdateScrollPosition: 'data-senna-update-scroll-position'\n};","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventHandle utility. Holds information about an event subscription, and\n * allows removing them easily.\n * EventHandle is a Disposable, but it's important to note that the\n * EventEmitter that created it is not the one responsible for disposing it.\n * That responsibility is for the code that holds a reference to it.\n * @extends {Disposable}\n */\nclass EventHandle extends Disposable {\n\t/**\n\t * EventHandle constructor\n\t * @param {!EventEmitter} emitter Emitter the event was subscribed to.\n\t * @param {string} event The name of the event that was subscribed to.\n\t * @param {!Function} listener The listener subscribed to the event.\n\t */\n\tconstructor(emitter, event, listener) {\n\t\tsuper();\n\n\t\t/**\n\t\t * The EventEmitter instance that the event was subscribed to.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.emitter_ = emitter;\n\n\t\t/**\n\t\t * The name of the event that was subscribed to.\n\t\t * @type {string}\n\t\t * @protected\n\t\t */\n\t\tthis.event_ = event;\n\n\t\t/**\n\t\t * The listener subscribed to the event.\n\t\t * @type {Function}\n\t\t * @protected\n\t\t */\n\t\tthis.listener_ = listener;\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.removeListener();\n\t\tthis.emitter_ = null;\n\t\tthis.listener_ = null;\n\t}\n\n\t/**\n\t * Removes the listener subscription from the emitter.\n\t */\n\tremoveListener() {\n\t\tif (!this.emitter_.isDisposed()) {\n\t\t\tthis.emitter_.removeListener(this.event_, this.listener_);\n\t\t}\n\t}\n}\n\nexport default EventHandle;\n","'use strict';\n\nimport {array, Disposable, isFunction, isString} from 'metal';\nimport EventHandle from './EventHandle';\n\nconst singleArray_ = [0];\n\n/**\n * EventEmitter utility.\n * @extends {Disposable}\n */\nclass EventEmitter extends Disposable {\n\t/**\n\t * EventEmitter constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds event listeners scoped by event type.\n\t\t * @type {Object>}\n\t\t * @protected\n\t\t */\n\t\tthis.events_ = null;\n\n\t\t/**\n\t\t * Handlers that are triggered when an event is listened to.\n\t\t * @type {Array}\n\t\t */\n\t\tthis.listenerHandlers_ = null;\n\n\t\t/**\n\t\t * Configuration option which determines if an event facade should be sent\n\t\t * as a param of listeners when emitting events. If set to true, the facade\n\t\t * will be passed as the first argument of the listener.\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.shouldUseFacade_ = false;\n\t}\n\n\t/**\n\t * Adds a handler to given holder variable. If the holder doesn't have a\n\t * value yet, it will receive the handler directly. If the holder is an array,\n\t * the value will just be added to it. Otherwise, the holder will be set to a\n\t * new array containing its previous value plus the new handler.\n\t * @param {*} holder\n\t * @param {!function()|Object} handler\n\t * @return {*} The holder's new value.\n\t * @protected\n\t */\n\taddHandler_(holder, handler) {\n\t\tif (!holder) {\n\t\t\tholder = handler;\n\t\t} else {\n\t\t\tif (!Array.isArray(holder)) {\n\t\t\t\tholder = [holder];\n\t\t\t}\n\t\t\tholder.push(handler);\n\t\t}\n\t\treturn holder;\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for the specified events.\n\t * @param {!(Array|string)} event\n\t * @param {!Function} listener\n\t * @param {boolean} defaultListener Flag indicating if this listener is a default\n\t * action for this event. Default actions are run last, and only if no previous\n\t * listener call `preventDefault()` on the received event facade.\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\taddListener(event, listener, defaultListener) {\n\t\tthis.validateListener_(listener);\n\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.addSingleListener_(events[i], listener, defaultListener);\n\t\t}\n\n\t\treturn new EventHandle(this, event, listener);\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for a single event.\n\t * @param {string} event\n\t * @param {!Function} listener\n\t * @param {boolean} defaultListener Flag indicating if this listener is a default\n\t * action for this event. Default actions are run last, and only if no previous\n\t * listener call `preventDefault()` on the received event facade.\n\t * @param {Function=} origin The original function that was added as a\n\t * listener, if there is any.\n\t * @protected\n\t */\n\taddSingleListener_(event, listener, defaultListener, origin) {\n\t\tthis.runListenerHandlers_(event);\n\t\tif (defaultListener || origin) {\n\t\t\tlistener = {\n\t\t\t\tdefault: defaultListener,\n\t\t\t\tfn: listener,\n\t\t\t\torigin: origin,\n\t\t\t};\n\t\t}\n\t\tthis.events_ = this.events_ || {};\n\t\tthis.events_[event] = this.addHandler_(this.events_[event], listener);\n\t}\n\n\t/**\n\t * Builds facade for the given event.\n\t * @param {string} event\n\t * @return {Object}\n\t * @protected\n\t */\n\tbuildFacade_(event) {\n\t\tif (this.getShouldUseFacade()) {\n\t\t\tconst facade = {\n\t\t\t\tpreventDefault: function() {\n\t\t\t\t\tfacade.preventedDefault = true;\n\t\t\t\t},\n\t\t\t\ttarget: this,\n\t\t\t\ttype: event,\n\t\t\t};\n\t\t\treturn facade;\n\t\t}\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.events_ = null;\n\t}\n\n\t/**\n\t * Execute each of the listeners in order with the supplied arguments.\n\t * @param {string} event\n\t * @param {*} opt_args [arg1], [arg2], [...]\n\t * @return {boolean} Returns true if event had listeners, false otherwise.\n\t */\n\temit(event) {\n\t\tconst listeners = this.getRawListeners_(event);\n\t\tif (listeners.length === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst args = array.slice(arguments, 1); // eslint-disable-line\n\t\tthis.runListeners_(listeners, args, this.buildFacade_(event));\n\t\treturn true;\n\t}\n\n\t/**\n\t * Gets the listener objects for the given event, if there are any.\n\t * @param {string} event\n\t * @return {!Array}\n\t * @protected\n\t */\n\tgetRawListeners_(event) {\n\t\tconst directListeners = toArray(this.events_ && this.events_[event]);\n\t\treturn directListeners.concat(\n\t\t\ttoArray(this.events_ && this.events_['*'])\n\t\t);\n\t}\n\n\t/**\n\t * Gets the configuration option which determines if an event facade should\n\t * be sent as a param of listeners when emitting events. If set to true, the\n\t * facade will be passed as the first argument of the listener.\n\t * @return {boolean}\n\t */\n\tgetShouldUseFacade() {\n\t\treturn this.shouldUseFacade_;\n\t}\n\n\t/**\n\t * Returns an array of listeners for the specified event.\n\t * @param {string} event\n\t * @return {Array} Array of listeners.\n\t */\n\tlisteners(event) {\n\t\treturn this.getRawListeners_(event).map(\n\t\t\tlistener => (listener.fn ? listener.fn : listener)\n\t\t);\n\t}\n\n\t/**\n\t * Adds a listener that will be invoked a fixed number of times for the\n\t * events. After each event is triggered the specified amount of times, the\n\t * listener is removed for it.\n\t * @param {!(Array|string)} event\n\t * @param {number} amount The amount of times this event should be listened\n\t * to.\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\tmany(event, amount, listener) {\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.many_(events[i], amount, listener);\n\t\t}\n\n\t\treturn new EventHandle(this, event, listener);\n\t}\n\n\t/**\n\t * Adds a listener that will be invoked a fixed number of times for a single\n\t * event. After the event is triggered the specified amount of times, the\n\t * listener is removed.\n\t * @param {string} event\n\t * @param {number} amount The amount of times this event should be listened\n\t * to.\n\t * @param {!Function} listener\n\t * @protected\n\t */\n\tmany_(event, amount, listener) {\n\t\tconst self = this;\n\n\t\tif (amount <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t *\n\t\t */\n\t\tfunction handlerInternal() {\n\t\t\tif (--amount === 0) {\n\t\t\t\tself.removeListener(event, handlerInternal);\n\t\t\t}\n\t\t\tlistener.apply(self, arguments); // eslint-disable-line\n\t\t}\n\n\t\tself.addSingleListener_(event, handlerInternal, false, listener);\n\t}\n\n\t/**\n\t * Checks if a listener object matches the given listener function. To match,\n\t * it needs to either point to that listener or have it as its origin.\n\t * @param {!Object} listenerObj\n\t * @param {!Function} listener\n\t * @return {boolean}\n\t * @protected\n\t */\n\tmatchesListener_(listenerObj, listener) {\n\t\tconst fn = listenerObj.fn || listenerObj;\n\t\treturn (\n\t\t\tfn === listener ||\n\t\t\t(listenerObj.origin && listenerObj.origin === listener) // eslint-disable-line\n\t\t);\n\t}\n\n\t/**\n\t * Removes a listener for the specified events.\n\t * Caution: changes array indices in the listener array behind the listener.\n\t * @param {!(Array|string)} event\n\t * @param {!Function} listener\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\toff(event, listener) {\n\t\tthis.validateListener_(listener);\n\t\tif (!this.events_) {\n\t\t\treturn this;\n\t\t}\n\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.events_[events[i]] = this.removeMatchingListenerObjs_(\n\t\t\t\ttoArray(this.events_[events[i]]),\n\t\t\t\tlistener\n\t\t\t);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for the specified events.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\ton() {\n\t\treturn this.addListener.apply(this, arguments); // eslint-disable-line\n\t}\n\n\t/**\n\t * Adds handler that gets triggered when an event is listened to on this\n\t * instance.\n\t * @param {!function()} handler\n\t */\n\tonListener(handler) {\n\t\tthis.listenerHandlers_ = this.addHandler_(\n\t\t\tthis.listenerHandlers_,\n\t\t\thandler\n\t\t); // eslint-disable-line\n\t}\n\n\t/**\n\t * Adds a one time listener for the events. This listener is invoked only the\n\t * next time each event is fired, after which it is removed.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\tonce(events, listener) {\n\t\treturn this.many(events, 1, listener);\n\t}\n\n\t/**\n\t * Removes all listeners, or those of the specified events. It's not a good\n\t * idea to remove listeners that were added elsewhere in the code,\n\t * especially when it's on an emitter that you didn't create.\n\t * @param {(Array|string)=} event\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveAllListeners(event) {\n\t\tif (this.events_) {\n\t\t\tif (event) {\n\t\t\t\tconst events = this.toEventsArray_(event);\n\t\t\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\t\t\tthis.events_[events[i]] = null;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.events_ = null;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes all listener objects from the given array that match the given\n\t * listener function.\n\t * @param {Array.} listenerObjs\n\t * @param {!Function} listener\n\t * @return {Array.|Object} The new listeners array for this event.\n\t * @protected\n\t */\n\tremoveMatchingListenerObjs_(listenerObjs, listener) {\n\t\tconst finalListeners = [];\n\t\tfor (let i = 0; i < listenerObjs.length; i++) {\n\t\t\tif (!this.matchesListener_(listenerObjs[i], listener)) {\n\t\t\t\tfinalListeners.push(listenerObjs[i]);\n\t\t\t}\n\t\t}\n\t\treturn finalListeners.length > 0 ? finalListeners : null;\n\t}\n\n\t/**\n\t * Removes a listener for the specified events.\n\t * Caution: changes array indices in the listener array behind the listener.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveListener() {\n\t\treturn this.off.apply(this, arguments); // eslint-disable-line\n\t}\n\n\t/**\n\t * Runs the handlers when an event is listened to.\n\t * @param {string} event\n\t * @protected\n\t */\n\trunListenerHandlers_(event) {\n\t\tlet handlers = this.listenerHandlers_;\n\t\tif (handlers) {\n\t\t\thandlers = toArray(handlers);\n\t\t\tfor (let i = 0; i < handlers.length; i++) {\n\t\t\t\thandlers[i](event);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Runs the given listeners.\n\t * @param {!Array} listeners\n\t * @param {!Array} args\n\t * @param {Object} facade\n\t * @protected\n\t */\n\trunListeners_(listeners, args, facade) {\n\t\tif (facade) {\n\t\t\targs.push(facade);\n\t\t}\n\n\t\tconst defaultListeners = [];\n\t\tfor (let i = 0; i < listeners.length; i++) {\n\t\t\tconst listener = listeners[i].fn || listeners[i];\n\t\t\tif (listeners[i].default) {\n\t\t\t\tdefaultListeners.push(listener);\n\t\t\t} else {\n\t\t\t\tlistener.apply(this, args);\n\t\t\t}\n\t\t}\n\t\tif (!facade || !facade.preventedDefault) {\n\t\t\tfor (let j = 0; j < defaultListeners.length; j++) {\n\t\t\t\tdefaultListeners[j].apply(this, args);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets the configuration option which determines if an event facade should\n\t * be sent as a param of listeners when emitting events. If set to true, the\n\t * facade will be passed as the first argument of the listener.\n\t * @param {boolean} shouldUseFacade\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tsetShouldUseFacade(shouldUseFacade) {\n\t\tthis.shouldUseFacade_ = shouldUseFacade;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Converts the parameter to an array if only one event is given. Reuses the\n\t * same array each time this conversion is done, to avoid using more memory\n\t * than necessary.\n\t * @param {!(Array|string)} events\n\t * @return {!Array}\n\t * @protected\n\t */\n\ttoEventsArray_(events) {\n\t\tif (isString(events)) {\n\t\t\tsingleArray_[0] = events;\n\t\t\tevents = singleArray_;\n\t\t}\n\t\treturn events;\n\t}\n\n\t/**\n\t * Checks if the given listener is valid, throwing an exception when it's not.\n\t * @param {*} listener\n\t * @protected\n\t */\n\tvalidateListener_(listener) {\n\t\tif (!isFunction(listener)) {\n\t\t\tthrow new TypeError('Listener must be a function');\n\t\t}\n\t}\n}\n\n/**\n * Converts to an array\n * @param {Object} val\n * @return {Array}\n */\nfunction toArray(val) {\n\tval = val || [];\n\treturn Array.isArray(val) ? val : [val];\n}\n\nexport default EventEmitter;\n","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventEmitterProxy utility. It's responsible for linking two EventEmitter\n * instances together, emitting events from the first emitter through the\n * second one. That means that listening to a supported event on the target\n * emitter will mean listening to it on the origin emitter as well.\n * @extends {Disposable}\n */\nclass EventEmitterProxy extends Disposable {\n\t/**\n\t * @param {EventEmitter} originEmitter Events originated on this emitter\n\t * will be fired for the target emitter's listeners as well.\n\t * @param {EventEmitter} targetEmitter Event listeners attached to this emitter\n\t * will also be triggered when the event is fired by the origin emitter.\n\t * @param {Object} blacklist Optional blacklist of events that should not be\n\t * proxied.\n\t * @param {Object} whitelist\n\t */\n\tconstructor(originEmitter, targetEmitter, blacklist, whitelist) {\n\t\tsuper();\n\n\t\t/**\n\t\t * Map of events that should not be proxied.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.blacklist_ = blacklist;\n\n\t\t/**\n\t\t * The origin emitter. This emitter's events will be proxied through the\n\t\t * target emitter.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.originEmitter_ = originEmitter;\n\n\t\t/**\n\t\t * A list of events that are pending to be listened by an actual origin\n\t\t * emitter. Events are stored here when the origin doesn't exist, so they\n\t\t * can be set on a new origin when one is set.\n\t\t * @type {Array}\n\t\t * @protected\n\t\t */\n\t\tthis.pendingEvents_ = null;\n\n\t\t/**\n\t\t * Holds a map of events from the origin emitter that are already being proxied.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.proxiedEvents_ = null;\n\n\t\t/**\n\t\t * The target emitter. This emitter will emit all events that come from\n\t\t * the origin emitter.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.targetEmitter_ = targetEmitter;\n\n\t\t/**\n\t\t * Map of events that should be proxied. If whitelist is set blacklist is ignored.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.whitelist_ = whitelist;\n\n\t\tthis.startProxy_();\n\t}\n\n\t/**\n\t * Adds the given listener for the given event.\n\t * @param {string} event\n\t * @param {!function()} listener\n\t * @return {!EventHandle} The listened event's handle.\n\t * @protected\n\t */\n\taddListener_(event, listener) {\n\t\treturn this.originEmitter_.on(event, listener);\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisposeInternal() {\n\t\tthis.removeListeners_();\n\t\tthis.proxiedEvents_ = null;\n\t\tthis.originEmitter_ = null;\n\t\tthis.targetEmitter_ = null;\n\t}\n\n\t/**\n\t * Emits the specified event type on the target emitter.\n\t * @protected\n\t */\n\temitOnTarget_(...args) {\n\t\tthis.targetEmitter_.emit(...args);\n\t}\n\n\t/**\n\t * Proxies the given event from the origin to the target emitter.\n\t * @param {string} event\n\t */\n\tproxyEvent(event) {\n\t\tif (this.shouldProxyEvent_(event)) {\n\t\t\tthis.tryToAddListener_(event);\n\t\t}\n\t}\n\n\t/**\n\t * Removes the proxy listener for all events.\n\t * @protected\n\t */\n\tremoveListeners_() {\n\t\tif (this.proxiedEvents_) {\n\t\t\tconst events = Object.keys(this.proxiedEvents_);\n\t\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\t\tthis.proxiedEvents_[events[i]].removeListener();\n\t\t\t}\n\t\t\tthis.proxiedEvents_ = null;\n\t\t}\n\t\tthis.pendingEvents_ = null;\n\t}\n\n\t/**\n\t * Changes the origin emitter. This automatically detaches any events that\n\t * were already being proxied from the previous emitter, and starts proxying\n\t * them on the new emitter instead.\n\t * @param {!EventEmitter} originEmitter\n\t */\n\tsetOriginEmitter(originEmitter) {\n\t\tconst events =\n\t\t\tthis.originEmitter_ && this.proxiedEvents_\n\t\t\t\t? Object.keys(this.proxiedEvents_)\n\t\t\t\t: this.pendingEvents_;\n\t\tthis.originEmitter_ = originEmitter;\n\t\tif (events) {\n\t\t\tthis.removeListeners_();\n\t\t\tevents.forEach(event => this.proxyEvent(event));\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given event should be proxied.\n\t * @param {string} event\n\t * @return {boolean}\n\t * @protected\n\t */\n\tshouldProxyEvent_(event) {\n\t\tif (this.whitelist_ && !this.whitelist_[event]) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.blacklist_ && this.blacklist_[event]) {\n\t\t\treturn false;\n\t\t}\n\t\treturn !this.proxiedEvents_ || !this.proxiedEvents_[event];\n\t}\n\n\t/**\n\t * Starts proxying all events from the origin to the target emitter.\n\t * @protected\n\t */\n\tstartProxy_() {\n\t\tthis.targetEmitter_.onListener(this.proxyEvent.bind(this));\n\t}\n\n\t/**\n\t * Adds a listener to the origin emitter, if it exists. Otherwise, stores\n\t * the pending listener so it can be used on a future origin emitter.\n\t * @param {string} event\n\t * @protected\n\t */\n\ttryToAddListener_(event) {\n\t\tif (this.originEmitter_) {\n\t\t\tthis.proxiedEvents_ = this.proxiedEvents_ || {};\n\t\t\tthis.proxiedEvents_[event] = this.addListener_(\n\t\t\t\tevent,\n\t\t\t\tthis.emitOnTarget_.bind(this, event)\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pendingEvents_ = this.pendingEvents_ || [];\n\t\t\tthis.pendingEvents_.push(event);\n\t\t}\n\t}\n}\n\nexport default EventEmitterProxy;\n","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventHandler utility. It's useful for easily removing a group of\n * listeners from different EventEmitter instances.\n * @extends {Disposable}\n */\nclass EventHandler extends Disposable {\n\t/**\n\t * EventHandler constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * An array that holds the added event handles, so the listeners can be\n\t\t * removed later.\n\t\t * @type {Array.}\n\t\t * @protected\n\t\t */\n\t\tthis.eventHandles_ = [];\n\t}\n\n\t/**\n\t * Adds event handles to be removed later through the `removeAllListeners`\n\t * method.\n\t * @param {...(!EventHandle)} var_args\n\t */\n\tadd(...args) {\n\t\tfor (let i = 0; i < arguments.length; i++) {\n\t\t\tthis.eventHandles_.push(args[i]);\n\t\t}\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.eventHandles_ = null;\n\t}\n\n\t/**\n\t * Removes all listeners that have been added through the `add` method.\n\t */\n\tremoveAllListeners() {\n\t\tfor (let i = 0; i < this.eventHandles_.length; i++) {\n\t\t\tthis.eventHandles_[i].removeListener();\n\t\t}\n\n\t\tthis.eventHandles_ = [];\n\t}\n}\n\nexport default EventHandler;\n","/*!\n * Promises polyfill from Google's Closure Library.\n *\n * Copyright 2013 The Closure Library Authors. All Rights Reserved.\n *\n * NOTE(eduardo): Promise support is not ready on all supported browsers,\n * therefore metal-promise is temporarily using Google's promises as polyfill.\n * It supports cancellable promises and has clean and fast implementation.\n */\n\n'use strict';\n\nimport { isDef, isFunction, isObject } from 'metal';\nimport { async } from 'metal';\n\n/**\n * Provides a more strict interface for Thenables in terms of\n * http://promisesaplus.com for interop with {@see CancellablePromise}.\n *\n * @interface\n * @extends {IThenable.}\n * @template TYPE\n */\nvar Thenable = function() {};\n\n/**\n * Adds callbacks that will operate on the result of the Thenable, returning a\n * new child Promise.\n *\n * If the Thenable is fulfilled, the {@code onFulfilled} callback will be\n * invoked with the fulfillment value as argument, and the child Promise will\n * be fulfilled with the return value of the callback. If the callback throws\n * an exception, the child Promise will be rejected with the thrown value\n * instead.\n *\n * If the Thenable is rejected, the {@code onRejected} callback will be invoked\n * with the rejection reason as argument, and the child Promise will be rejected\n * with the return value of the callback or thrown value.\n *\n * @param {?(function(this:THIS, TYPE):\n * (RESULT|IThenable.|Thenable))=} opt_onFulfilled A\n * function that will be invoked with the fulfillment value if the Promise\n * is fullfilled.\n * @param {?(function(*): *)=} opt_onRejected A function that will be invoked\n * with the rejection reason if the Promise is rejected.\n * @param {THIS=} opt_context An optional context object that will be the\n * execution context for the callbacks. By default, functions are executed\n * with the default this.\n * @return {!CancellablePromise.} A new Promise that will receive the\n * result of the fulfillment or rejection callback.\n * @template RESULT,THIS\n */\nThenable.prototype.then = function() {};\n\n\n/**\n * An expando property to indicate that an object implements\n * {@code Thenable}.\n *\n * {@see addImplementation}.\n *\n * @const\n */\nThenable.IMPLEMENTED_BY_PROP = '$goog_Thenable';\n\n\n/**\n * Marks a given class (constructor) as an implementation of Thenable, so\n * that we can query that fact at runtime. The class must have already\n * implemented the interface.\n * Exports a 'then' method on the constructor prototype, so that the objects\n * also implement the extern {@see Thenable} interface for interop with\n * other Promise implementations.\n * @param {function(new:Thenable,...[?])} ctor The class constructor. The\n * corresponding class must have already implemented the interface.\n */\nThenable.addImplementation = function(ctor) {\n ctor.prototype.then = ctor.prototype.then;\n ctor.prototype.$goog_Thenable = true;\n};\n\n\n/**\n * @param {*} object\n * @return {boolean} Whether a given instance implements {@code Thenable}.\n * The class/superclass of the instance must call {@code addImplementation}.\n */\nThenable.isImplementedBy = function(object) {\n if (!object) {\n return false;\n }\n try {\n return !!object.$goog_Thenable;\n } catch (e) {\n // Property access seems to be forbidden.\n return false;\n }\n};\n\n\n/**\n * Like bind(), except that a 'this object' is not required. Useful when the\n * target function is already bound.\n *\n * Usage:\n * var g = partial(f, arg1, arg2);\n * g(arg3, arg4);\n *\n * @param {Function} fn A function to partially apply.\n * @param {...*} var_args Additional arguments that are partially applied to fn.\n * @return {!Function} A partially-applied form of the function bind() was\n * invoked as a method of.\n */\nvar partial = function(fn) {\n var args = Array.prototype.slice.call(arguments, 1);\n return function() {\n // Clone the array (with slice()) and append additional arguments\n // to the existing arguments.\n var newArgs = args.slice();\n newArgs.push.apply(newArgs, arguments);\n return fn.apply(this, newArgs);\n };\n};\n\n/**\n * Promises provide a result that may be resolved asynchronously. A Promise may\n * be resolved by being fulfilled or rejected with a value, which will be known\n * as the fulfillment value or the rejection reason. Whether fulfilled or\n * rejected, the Promise result is immutable once it is set.\n *\n * Promises may represent results of any type, including undefined. Rejection\n * reasons are typically Errors, but may also be of any type. Closure Promises\n * allow for optional type annotations that enforce that fulfillment values are\n * of the appropriate types at compile time.\n *\n * The result of a Promise is accessible by calling {@code then} and registering\n * {@code onFulfilled} and {@code onRejected} callbacks. Once the Promise\n * resolves, the relevant callbacks are invoked with the fulfillment value or\n * rejection reason as argument. Callbacks are always invoked in the order they\n * were registered, even when additional {@code then} calls are made from inside\n * another callback. A callback is always run asynchronously sometime after the\n * scope containing the registering {@code then} invocation has returned.\n *\n * If a Promise is resolved with another Promise, the first Promise will block\n * until the second is resolved, and then assumes the same result as the second\n * Promise. This allows Promises to depend on the results of other Promises,\n * linking together multiple asynchronous operations.\n *\n * This implementation is compatible with the Promises/A+ specification and\n * passes that specification's conformance test suite. A Closure Promise may be\n * resolved with a Promise instance (or sufficiently compatible Promise-like\n * object) created by other Promise implementations. From the specification,\n * Promise-like objects are known as \"Thenables\".\n *\n * @see http://promisesaplus.com/\n *\n * @param {function(\n * this:RESOLVER_CONTEXT,\n * function((TYPE|IThenable.|Thenable)),\n * function(*)): void} resolver\n * Initialization function that is invoked immediately with {@code resolve}\n * and {@code reject} functions as arguments. The Promise is resolved or\n * rejected with the first argument passed to either function.\n * @param {RESOLVER_CONTEXT=} opt_context An optional context for executing the\n * resolver function. If unspecified, the resolver function will be executed\n * in the default scope.\n * @constructor\n * @struct\n * @final\n * @implements {Thenable.}\n * @template TYPE,RESOLVER_CONTEXT\n */\nvar CancellablePromise = function(resolver, opt_context) {\n /**\n * The internal state of this Promise. Either PENDING, FULFILLED, REJECTED, or\n * BLOCKED.\n * @private {CancellablePromise.State_}\n */\n this.state_ = CancellablePromise.State_.PENDING;\n\n /**\n * The resolved result of the Promise. Immutable once set with either a\n * fulfillment value or rejection reason.\n * @private {*}\n */\n this.result_ = undefined;\n\n /**\n * For Promises created by calling {@code then()}, the originating parent.\n * @private {CancellablePromise}\n */\n this.parent_ = null;\n\n /**\n * The list of {@code onFulfilled} and {@code onRejected} callbacks added to\n * this Promise by calls to {@code then()}.\n * @private {Array.}\n */\n this.callbackEntries_ = null;\n\n /**\n * Whether the Promise is in the queue of Promises to execute.\n * @private {boolean}\n */\n this.executing_ = false;\n\n if (CancellablePromise.UNHANDLED_REJECTION_DELAY > 0) {\n /**\n * A timeout ID used when the {@code UNHANDLED_REJECTION_DELAY} is greater\n * than 0 milliseconds. The ID is set when the Promise is rejected, and\n * cleared only if an {@code onRejected} callback is invoked for the\n * Promise (or one of its descendants) before the delay is exceeded.\n *\n * If the rejection is not handled before the timeout completes, the\n * rejection reason is passed to the unhandled rejection handler.\n * @private {number}\n */\n this.unhandledRejectionId_ = 0;\n } else if (CancellablePromise.UNHANDLED_REJECTION_DELAY === 0) {\n /**\n * When the {@code UNHANDLED_REJECTION_DELAY} is set to 0 milliseconds, a\n * boolean that is set if the Promise is rejected, and reset to false if an\n * {@code onRejected} callback is invoked for the Promise (or one of its\n * descendants). If the rejection is not handled before the next timestep,\n * the rejection reason is passed to the unhandled rejection handler.\n * @private {boolean}\n */\n this.hadUnhandledRejection_ = false;\n }\n\n try {\n var self = this;\n resolver.call(\n opt_context, function(value) {\n self.resolve_(CancellablePromise.State_.FULFILLED, value);\n }, function(reason) {\n self.resolve_(CancellablePromise.State_.REJECTED, reason);\n });\n } catch (e) {\n this.resolve_(CancellablePromise.State_.REJECTED, e);\n }\n};\n\n/**\n * The delay in milliseconds before a rejected Promise's reason is passed to\n * the rejection handler. By default, the rejection handler rethrows the\n * rejection reason so that it appears in the developer console or\n * {@code window.onerror} handler.\n * Rejections are rethrown as quickly as possible by default. A negative value\n * disables rejection handling entirely.\n * @type {number}\n */\nCancellablePromise.UNHANDLED_REJECTION_DELAY = 0;\n\n\n/**\n * The possible internal states for a Promise. These states are not directly\n * observable to external callers.\n * @enum {number}\n * @private\n */\nCancellablePromise.State_ = {\n /** The Promise is waiting for resolution. */\n PENDING: 0,\n\n /** The Promise is blocked waiting for the result of another Thenable. */\n BLOCKED: 1,\n\n /** The Promise has been resolved with a fulfillment value. */\n FULFILLED: 2,\n\n /** The Promise has been resolved with a rejection reason. */\n REJECTED: 3\n};\n\n\n/**\n * Typedef for entries in the callback chain. Each call to {@code then},\n * {@code thenCatch}, or {@code thenAlways} creates an entry containing the\n * functions that may be invoked once the Promise is resolved.\n *\n * @typedef {{\n * child: CancellablePromise,\n * onFulfilled: function(*),\n * onRejected: function(*)\n * }}\n * @private\n */\nCancellablePromise.CallbackEntry_ = null;\n\n\n/**\n * @param {(TYPE|Thenable.|Thenable)=} opt_value\n * @return {!CancellablePromise.} A new Promise that is immediately resolved\n * with the given value.\n * @template TYPE\n */\nCancellablePromise.resolve = function(opt_value) {\n return new CancellablePromise(function(resolve) {\n resolve(opt_value);\n });\n};\n\n\n/**\n * @param {*=} opt_reason\n * @return {!CancellablePromise} A new Promise that is immediately rejected with the\n * given reason.\n */\nCancellablePromise.reject = function(opt_reason) {\n return new CancellablePromise(function(resolve, reject) {\n reject(opt_reason);\n });\n};\n\n\n/**\n * @param {!Array.|Thenable)>} promises\n * @return {!CancellablePromise.} A Promise that receives the result of the\n * first Promise (or Promise-like) input to complete.\n * @template TYPE\n */\nCancellablePromise.race = function(promises) {\n return new CancellablePromise(function(resolve, reject) {\n if (!promises.length) {\n resolve(undefined);\n }\n for (var i = 0, promise; (promise = promises[i]); i++) {\n promise.then(resolve, reject);\n }\n });\n};\n\n\n/**\n * @param {!Array.|Thenable)>} promises\n * @return {!CancellablePromise.>} A Promise that receives a list of\n * every fulfilled value once every input Promise (or Promise-like) is\n * successfully fulfilled, or is rejected by the first rejection result.\n * @template TYPE\n */\nCancellablePromise.all = function(promises) {\n return new CancellablePromise(function(resolve, reject) {\n var toFulfill = promises.length;\n var values = [];\n\n if (!toFulfill) {\n resolve(values);\n return;\n }\n\n var onFulfill = function(index, value) {\n toFulfill--;\n values[index] = value;\n if (toFulfill === 0) {\n resolve(values);\n }\n };\n\n var onReject = function(reason) {\n reject(reason);\n };\n\n for (var i = 0, promise; (promise = promises[i]); i++) {\n promise.then(partial(onFulfill, i), onReject);\n }\n });\n};\n\n\n/**\n * @param {!Array.|Thenable)>} promises\n * @return {!CancellablePromise.} A Promise that receives the value of\n * the first input to be fulfilled, or is rejected with a list of every\n * rejection reason if all inputs are rejected.\n * @template TYPE\n */\nCancellablePromise.firstFulfilled = function(promises) {\n return new CancellablePromise(function(resolve, reject) {\n var toReject = promises.length;\n var reasons = [];\n\n if (!toReject) {\n resolve(undefined);\n return;\n }\n\n var onFulfill = function(value) {\n resolve(value);\n };\n\n var onReject = function(index, reason) {\n toReject--;\n reasons[index] = reason;\n if (toReject === 0) {\n reject(reasons);\n }\n };\n\n for (var i = 0, promise; (promise = promises[i]); i++) {\n promise.then(onFulfill, partial(onReject, i));\n }\n });\n};\n\n\n/**\n * Adds callbacks that will operate on the result of the Promise, returning a\n * new child Promise.\n *\n * If the Promise is fulfilled, the {@code onFulfilled} callback will be invoked\n * with the fulfillment value as argument, and the child Promise will be\n * fulfilled with the return value of the callback. If the callback throws an\n * exception, the child Promise will be rejected with the thrown value instead.\n *\n * If the Promise is rejected, the {@code onRejected} callback will be invoked\n * with the rejection reason as argument, and the child Promise will be rejected\n * with the return value (or thrown value) of the callback.\n *\n * @override\n */\nCancellablePromise.prototype.then = function(opt_onFulfilled, opt_onRejected, opt_context) {\n return this.addChildPromise_(\n isFunction(opt_onFulfilled) ? opt_onFulfilled : null,\n isFunction(opt_onRejected) ? opt_onRejected : null,\n opt_context);\n};\nThenable.addImplementation(CancellablePromise);\n\n\n/**\n * Adds a callback that will be invoked whether the Promise is fulfilled or\n * rejected. The callback receives no argument, and no new child Promise is\n * created. This is useful for ensuring that cleanup takes place after certain\n * asynchronous operations. Callbacks added with {@code thenAlways} will be\n * executed in the same order with other calls to {@code then},\n * {@code thenAlways}, or {@code thenCatch}.\n *\n * Since it does not produce a new child Promise, cancellation propagation is\n * not prevented by adding callbacks with {@code thenAlways}. A Promise that has\n * a cleanup handler added with {@code thenAlways} will be canceled if all of\n * its children created by {@code then} (or {@code thenCatch}) are canceled.\n *\n * @param {function(this:THIS): void} onResolved A function that will be invoked\n * when the Promise is resolved.\n * @param {THIS=} opt_context An optional context object that will be the\n * execution context for the callbacks. By default, functions are executed\n * in the global scope.\n * @return {!CancellablePromise.} This Promise, for chaining additional calls.\n * @template THIS\n */\nCancellablePromise.prototype.thenAlways = function(onResolved, opt_context) {\n var callback = function() {\n try {\n // Ensure that no arguments are passed to onResolved.\n onResolved.call(opt_context);\n } catch (err) {\n CancellablePromise.handleRejection_.call(null, err);\n }\n };\n\n this.addCallbackEntry_({\n child: null,\n onRejected: callback,\n onFulfilled: callback\n });\n return this;\n};\n\n\n/**\n * Adds a callback that will be invoked only if the Promise is rejected. This\n * is equivalent to {@code then(null, onRejected)}.\n *\n * @param {!function(this:THIS, *): *} onRejected A function that will be\n * invoked with the rejection reason if the Promise is rejected.\n * @param {THIS=} opt_context An optional context object that will be the\n * execution context for the callbacks. By default, functions are executed\n * in the global scope.\n * @return {!CancellablePromise} A new Promise that will receive the result of the\n * callback.\n * @template THIS\n */\nCancellablePromise.prototype.thenCatch = function(onRejected, opt_context) {\n return this.addChildPromise_(null, onRejected, opt_context);\n};\n\n/**\n * Alias of {@link CancellablePromise.prototype.thenCatch}\n */\nCancellablePromise.prototype.catch = CancellablePromise.prototype.thenCatch;\n\n\n/**\n * Cancels the Promise if it is still pending by rejecting it with a cancel\n * Error. No action is performed if the Promise is already resolved.\n *\n * All child Promises of the canceled Promise will be rejected with the same\n * cancel error, as with normal Promise rejection. If the Promise to be canceled\n * is the only child of a pending Promise, the parent Promise will also be\n * canceled. Cancellation may propagate upward through multiple generations.\n *\n * @param {string=} opt_message An optional debugging message for describing the\n * cancellation reason.\n */\nCancellablePromise.prototype.cancel = function(opt_message) {\n if (this.state_ === CancellablePromise.State_.PENDING) {\n async.run(function() {\n var err = new CancellablePromise.CancellationError(opt_message);\n err.IS_CANCELLATION_ERROR = true;\n this.cancelInternal_(err);\n }, this);\n }\n};\n\n\n/**\n * Cancels this Promise with the given error.\n *\n * @param {!Error} err The cancellation error.\n * @private\n */\nCancellablePromise.prototype.cancelInternal_ = function(err) {\n if (this.state_ === CancellablePromise.State_.PENDING) {\n if (this.parent_) {\n // Cancel the Promise and remove it from the parent's child list.\n this.parent_.cancelChild_(this, err);\n } else {\n this.resolve_(CancellablePromise.State_.REJECTED, err);\n }\n }\n};\n\n\n/**\n * Cancels a child Promise from the list of callback entries. If the Promise has\n * not already been resolved, reject it with a cancel error. If there are no\n * other children in the list of callback entries, propagate the cancellation\n * by canceling this Promise as well.\n *\n * @param {!CancellablePromise} childPromise The Promise to cancel.\n * @param {!Error} err The cancel error to use for rejecting the Promise.\n * @private\n */\nCancellablePromise.prototype.cancelChild_ = function(childPromise, err) {\n if (!this.callbackEntries_) {\n return;\n }\n var childCount = 0;\n var childIndex = -1;\n\n // Find the callback entry for the childPromise, and count whether there are\n // additional child Promises.\n for (var i = 0, entry; (entry = this.callbackEntries_[i]); i++) {\n var child = entry.child;\n if (child) {\n childCount++;\n if (child === childPromise) {\n childIndex = i;\n }\n if (childIndex >= 0 && childCount > 1) {\n break;\n }\n }\n }\n\n // If the child Promise was the only child, cancel this Promise as well.\n // Otherwise, reject only the child Promise with the cancel error.\n if (childIndex >= 0) {\n if (this.state_ === CancellablePromise.State_.PENDING && childCount === 1) {\n this.cancelInternal_(err);\n } else {\n var callbackEntry = this.callbackEntries_.splice(childIndex, 1)[0];\n this.executeCallback_(\n callbackEntry, CancellablePromise.State_.REJECTED, err);\n }\n }\n};\n\n\n/**\n * Adds a callback entry to the current Promise, and schedules callback\n * execution if the Promise has already been resolved.\n *\n * @param {CancellablePromise.CallbackEntry_} callbackEntry Record containing\n * {@code onFulfilled} and {@code onRejected} callbacks to execute after\n * the Promise is resolved.\n * @private\n */\nCancellablePromise.prototype.addCallbackEntry_ = function(callbackEntry) {\n if ((!this.callbackEntries_ || !this.callbackEntries_.length) &&\n (this.state_ === CancellablePromise.State_.FULFILLED ||\n this.state_ === CancellablePromise.State_.REJECTED)) {\n this.scheduleCallbacks_();\n }\n if (!this.callbackEntries_) {\n this.callbackEntries_ = [];\n }\n this.callbackEntries_.push(callbackEntry);\n};\n\n\n/**\n * Creates a child Promise and adds it to the callback entry list. The result of\n * the child Promise is determined by the state of the parent Promise and the\n * result of the {@code onFulfilled} or {@code onRejected} callbacks as\n * specified in the Promise resolution procedure.\n *\n * @see http://promisesaplus.com/#the__method\n *\n * @param {?function(this:THIS, TYPE):\n * (RESULT|CancellablePromise.|Thenable)} onFulfilled A callback that\n * will be invoked if the Promise is fullfilled, or null.\n * @param {?function(this:THIS, *): *} onRejected A callback that will be\n * invoked if the Promise is rejected, or null.\n * @param {THIS=} opt_context An optional execution context for the callbacks.\n * in the default calling context.\n * @return {!CancellablePromise} The child Promise.\n * @template RESULT,THIS\n * @private\n */\nCancellablePromise.prototype.addChildPromise_ = function(\nonFulfilled, onRejected, opt_context) {\n\n var callbackEntry = {\n child: null,\n onFulfilled: null,\n onRejected: null\n };\n\n callbackEntry.child = new CancellablePromise(function(resolve, reject) {\n // Invoke onFulfilled, or resolve with the parent's value if absent.\n callbackEntry.onFulfilled = onFulfilled ? function(value) {\n try {\n var result = onFulfilled.call(opt_context, value);\n resolve(result);\n } catch (err) {\n reject(err);\n }\n } : resolve;\n\n // Invoke onRejected, or reject with the parent's reason if absent.\n callbackEntry.onRejected = onRejected ? function(reason) {\n try {\n var result = onRejected.call(opt_context, reason);\n if (!isDef(result) && reason.IS_CANCELLATION_ERROR) {\n // Propagate cancellation to children if no other result is returned.\n reject(reason);\n } else {\n resolve(result);\n }\n } catch (err) {\n reject(err);\n }\n } : reject;\n });\n\n callbackEntry.child.parent_ = this;\n this.addCallbackEntry_(\n /** @type {CancellablePromise.CallbackEntry_} */ (callbackEntry));\n return callbackEntry.child;\n};\n\n\n/**\n * Unblocks the Promise and fulfills it with the given value.\n *\n * @param {TYPE} value\n * @private\n */\nCancellablePromise.prototype.unblockAndFulfill_ = function(value) {\n if (this.state_ !== CancellablePromise.State_.BLOCKED) {\n throw new Error('CancellablePromise is not blocked.');\n }\n this.state_ = CancellablePromise.State_.PENDING;\n this.resolve_(CancellablePromise.State_.FULFILLED, value);\n};\n\n\n/**\n * Unblocks the Promise and rejects it with the given rejection reason.\n *\n * @param {*} reason\n * @private\n */\nCancellablePromise.prototype.unblockAndReject_ = function(reason) {\n if (this.state_ !== CancellablePromise.State_.BLOCKED) {\n throw new Error('CancellablePromise is not blocked.');\n }\n this.state_ = CancellablePromise.State_.PENDING;\n this.resolve_(CancellablePromise.State_.REJECTED, reason);\n};\n\n\n/**\n * Attempts to resolve a Promise with a given resolution state and value. This\n * is a no-op if the given Promise has already been resolved.\n *\n * If the given result is a Thenable (such as another Promise), the Promise will\n * be resolved with the same state and result as the Thenable once it is itself\n * resolved.\n *\n * If the given result is not a Thenable, the Promise will be fulfilled or\n * rejected with that result based on the given state.\n *\n * @see http://promisesaplus.com/#the_promise_resolution_procedure\n *\n * @param {CancellablePromise.State_} state\n * @param {*} x The result to apply to the Promise.\n * @private\n */\nCancellablePromise.prototype.resolve_ = function(state, x) {\n if (this.state_ !== CancellablePromise.State_.PENDING) {\n return;\n }\n\n if (this === x) {\n state = CancellablePromise.State_.REJECTED;\n x = new TypeError('CancellablePromise cannot resolve to itself');\n\n } else if (Thenable.isImplementedBy(x)) {\n x = /** @type {!Thenable} */ (x);\n this.state_ = CancellablePromise.State_.BLOCKED;\n x.then(this.unblockAndFulfill_, this.unblockAndReject_, this);\n return;\n\n } else if (isObject(x)) {\n try {\n var then = x.then;\n if (isFunction(then)) {\n this.tryThen_(x, then);\n return;\n }\n } catch (e) {\n state = CancellablePromise.State_.REJECTED;\n x = e;\n }\n }\n\n this.result_ = x;\n this.state_ = state;\n this.scheduleCallbacks_();\n\n if (state === CancellablePromise.State_.REJECTED && !x.IS_CANCELLATION_ERROR) {\n CancellablePromise.addUnhandledRejection_(this, x);\n }\n};\n\n\n/**\n * Attempts to call the {@code then} method on an object in the hopes that it is\n * a Promise-compatible instance. This allows interoperation between different\n * Promise implementations, however a non-compliant object may cause a Promise\n * to hang indefinitely. If the {@code then} method throws an exception, the\n * dependent Promise will be rejected with the thrown value.\n *\n * @see http://promisesaplus.com/#point-70\n *\n * @param {Thenable} thenable An object with a {@code then} method that may be\n * compatible with the Promise/A+ specification.\n * @param {!Function} then The {@code then} method of the Thenable object.\n * @private\n */\nCancellablePromise.prototype.tryThen_ = function(thenable, then) {\n this.state_ = CancellablePromise.State_.BLOCKED;\n var promise = this;\n var called = false;\n\n var resolve = function(value) {\n if (!called) {\n called = true;\n promise.unblockAndFulfill_(value);\n }\n };\n\n var reject = function(reason) {\n if (!called) {\n called = true;\n promise.unblockAndReject_(reason);\n }\n };\n\n try {\n then.call(thenable, resolve, reject);\n } catch (e) {\n reject(e);\n }\n};\n\n\n/**\n * Executes the pending callbacks of a resolved Promise after a timeout.\n *\n * Section 2.2.4 of the Promises/A+ specification requires that Promise\n * callbacks must only be invoked from a call stack that only contains Promise\n * implementation code, which we accomplish by invoking callback execution after\n * a timeout. If {@code startExecution_} is called multiple times for the same\n * Promise, the callback chain will be evaluated only once. Additional callbacks\n * may be added during the evaluation phase, and will be executed in the same\n * event loop.\n *\n * All Promises added to the waiting list during the same browser event loop\n * will be executed in one batch to avoid using a separate timeout per Promise.\n *\n * @private\n */\nCancellablePromise.prototype.scheduleCallbacks_ = function() {\n if (!this.executing_) {\n this.executing_ = true;\n async.run(this.executeCallbacks_, this);\n }\n};\n\n\n/**\n * Executes all pending callbacks for this Promise.\n *\n * @private\n */\nCancellablePromise.prototype.executeCallbacks_ = function() {\n while (this.callbackEntries_ && this.callbackEntries_.length) {\n var entries = this.callbackEntries_;\n this.callbackEntries_ = [];\n\n for (var i = 0; i < entries.length; i++) {\n this.executeCallback_(entries[i], this.state_, this.result_);\n }\n }\n this.executing_ = false;\n};\n\n\n/**\n * Executes a pending callback for this Promise. Invokes an {@code onFulfilled}\n * or {@code onRejected} callback based on the resolved state of the Promise.\n *\n * @param {!CancellablePromise.CallbackEntry_} callbackEntry An entry containing the\n * onFulfilled and/or onRejected callbacks for this step.\n * @param {CancellablePromise.State_} state The resolution status of the Promise,\n * either FULFILLED or REJECTED.\n * @param {*} result The resolved result of the Promise.\n * @private\n */\nCancellablePromise.prototype.executeCallback_ = function(\ncallbackEntry, state, result) {\n if (state === CancellablePromise.State_.FULFILLED) {\n callbackEntry.onFulfilled(result);\n } else {\n this.removeUnhandledRejection_();\n callbackEntry.onRejected(result);\n }\n};\n\n\n/**\n * Marks this rejected Promise as having being handled. Also marks any parent\n * Promises in the rejected state as handled. The rejection handler will no\n * longer be invoked for this Promise (if it has not been called already).\n *\n * @private\n */\nCancellablePromise.prototype.removeUnhandledRejection_ = function() {\n var p;\n if (CancellablePromise.UNHANDLED_REJECTION_DELAY > 0) {\n for (p = this; p && p.unhandledRejectionId_; p = p.parent_) {\n clearTimeout(p.unhandledRejectionId_);\n p.unhandledRejectionId_ = 0;\n }\n } else if (CancellablePromise.UNHANDLED_REJECTION_DELAY === 0) {\n for (p = this; p && p.hadUnhandledRejection_; p = p.parent_) {\n p.hadUnhandledRejection_ = false;\n }\n }\n};\n\n\n/**\n * Marks this rejected Promise as unhandled. If no {@code onRejected} callback\n * is called for this Promise before the {@code UNHANDLED_REJECTION_DELAY}\n * expires, the reason will be passed to the unhandled rejection handler. The\n * handler typically rethrows the rejection reason so that it becomes visible in\n * the developer console.\n *\n * @param {!CancellablePromise} promise The rejected Promise.\n * @param {*} reason The Promise rejection reason.\n * @private\n */\nCancellablePromise.addUnhandledRejection_ = function(promise, reason) {\n if (CancellablePromise.UNHANDLED_REJECTION_DELAY > 0) {\n promise.unhandledRejectionId_ = setTimeout(function() {\n CancellablePromise.handleRejection_.call(null, reason);\n }, CancellablePromise.UNHANDLED_REJECTION_DELAY);\n\n } else if (CancellablePromise.UNHANDLED_REJECTION_DELAY === 0) {\n promise.hadUnhandledRejection_ = true;\n async.run(function() {\n if (promise.hadUnhandledRejection_) {\n CancellablePromise.handleRejection_.call(null, reason);\n }\n });\n }\n};\n\n\n/**\n * A method that is invoked with the rejection reasons for Promises that are\n * rejected but have no {@code onRejected} callbacks registered yet.\n * @type {function(*)}\n * @private\n */\nCancellablePromise.handleRejection_ = async.throwException;\n\n\n/**\n * Sets a handler that will be called with reasons from unhandled rejected\n * Promises. If the rejected Promise (or one of its descendants) has an\n * {@code onRejected} callback registered, the rejection will be considered\n * handled, and the rejection handler will not be called.\n *\n * By default, unhandled rejections are rethrown so that the error may be\n * captured by the developer console or a {@code window.onerror} handler.\n *\n * @param {function(*)} handler A function that will be called with reasons from\n * rejected Promises. Defaults to {@code async.throwException}.\n */\nCancellablePromise.setUnhandledRejectionHandler = function(handler) {\n CancellablePromise.handleRejection_ = handler;\n};\n\n\n\n/**\n * Error used as a rejection reason for canceled Promises.\n *\n * @param {string=} opt_message\n * @constructor\n * @extends {Error}\n * @final\n */\nCancellablePromise.CancellationError = class extends Error {\n constructor(opt_message) {\n super(opt_message);\n\n if (opt_message) {\n this.message = opt_message;\n }\n }\n};\n\n/** @override */\nCancellablePromise.CancellationError.prototype.name = 'cancel';\n\nexport {CancellablePromise};\nexport default CancellablePromise;\n","'use strict';\n\n/**\n * Debounces function execution.\n * @param {!function()} fn\n * @param {number} delay\n * @return {!function()}\n */\nfunction debounce(fn, delay) {\n\treturn function debounced() {\n\t\tvar args = arguments;\n\t\tcancelDebounce(debounced);\n\t\tdebounced.id = setTimeout(function() {\n\t\t\tfn.apply(null, args);\n\t\t}, delay);\n\t};\n}\n\n/**\n * Cancels the scheduled debounced function.\n */\nfunction cancelDebounce(debounced) {\n\tclearTimeout(debounced.id);\n}\n\nexport default debounce;\nexport { cancelDebounce, debounce };\n","'use strict';\n\nimport core from 'metal';\n\nconst REGEX = /([\\/])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])*)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?)/g;\n\n/**\n * Converts the given array of regex matches to a more readable object format.\n * @param {!Array} matches\n * @return {!Object}\n */\nfunction convertMatchesToObj(matches) {\n\treturn {\n\t\tmatch: matches[0],\n\t\tprefix: matches[1],\n\t\tname: matches[2],\n\t\tparamPattern: matches[3],\n\t\tunnamedPattern: matches[4],\n\t\tmodifier: matches[5]\n\t};\n}\n\n/**\n * Converts the given tokens parsed from a route format string to a regex.\n * @param {!Array} tokens\n * @return {!RegExp}\n */\nfunction convertTokensToRegex(tokens) {\n\tlet regex = '';\n\tfor (let i = 0; i < tokens.length; i++) {\n\t\tif (core.isString(tokens[i])) {\n\t\t\tregex += escape(tokens[i]);\n\t\t} else {\n\t\t\tlet capture = encloseNonCapturingGroup(tokens[i].pattern);\n\t\t\tif (tokens[i].repeat) {\n\t\t\t\tcapture += encloseNonCapturingGroup('\\\\/' + capture) + '*';\n\t\t\t}\n\t\t\tcapture = escape(tokens[i].prefix) + `(${capture})`;\n\t\t\tif (tokens[i].optional) {\n\t\t\t\tif (!tokens[i].partial) {\n\t\t\t\t\tcapture = encloseNonCapturingGroup(capture);\n\t\t\t\t}\n\t\t\t\tcapture += '?';\n\t\t\t}\n\t\t\tregex += capture;\n\t\t}\n\t}\n\treturn new RegExp('^' + makeTrailingSlashOptional(regex) + '$');\n}\n\n/**\n * Encloses the given regex pattern into a non capturing group.\n * @param {string} pattern\n * @return {string}\n */\nfunction encloseNonCapturingGroup(pattern) {\n\treturn `(?:${pattern})`;\n}\n\n/**\n * Escapes the given string to show up in the path regex.\n * @param {string} str\n * @return {string}\n */\nfunction escape(str) {\n\treturn str.replace(/([.+*?=^!:${}()[\\]|\\/\\\\])/g, '\\\\$1');\n}\n\n/**\n * Makes trailing slash optional on paths.\n * @param {string} regex\n * @param {string}\n */\nfunction makeTrailingSlashOptional(regex) {\n\tif (/\\/$/.test(regex)) {\n\t\tregex += '?';\n\t} else {\n\t\tregex += '\\\\/?';\n\t}\n\treturn regex;\n}\n\n/**\n * Parses the given route format string into tokens representing its contents.\n * @param {!Array|string} routeOrTokens Either a route format string or tokens\n * previously parsed via the `parse` function.\n * @return {!Array} An array of tokens that can be either plain\n * strings (part of the route) or objects containing informations on params.\n */\nexport function parse(routeOrTokens) {\n\tif (!core.isString(routeOrTokens)) {\n\t\treturn routeOrTokens;\n\t}\n\n\tconst route = routeOrTokens;\n\tlet unnamedCount = 0;\n\tconst tokens = [];\n\tlet currPath = '';\n\tlet index = 0;\n\n\tlet matches = REGEX.exec(route);\n\twhile (matches) {\n\t\tconst data = convertMatchesToObj(matches);\n\n\t\tcurrPath = route.slice(index, matches.index);\n\t\tindex = matches.index + data.match.length;\n\t\ttokens.push(currPath);\n\n\t\ttokens.push({\n\t\t\tname: data.name ? data.name : '' + unnamedCount++,\n\t\t\tpartial: route[index] && route[index] !== data.prefix,\n\t\t\tprefix: data.prefix || '',\n\t\t\tpattern: data.paramPattern || data.unnamedPattern || '[^\\\\/]+',\n\t\t\trepeat: data.modifier === '*' || data.modifier === '+',\n\t\t\toptional: data.modifier === '*' || data.modifier === '?'\n\t\t});\n\n\t\tmatches = REGEX.exec(route);\n\t}\n\n\tif (index < route.length) {\n\t\ttokens.push(route.substr(index));\n\t}\n\treturn tokens;\n}\n\n/**\n * Converts the given route format string to a regex that can extract param\n * data from paths matching it.\n * @param {!Array|string} routeOrTokens Either a route format string or tokens\n * previously parsed via the `parse` function.\n * @return {!RegExp}\n */\nexport function toRegex(routeOrTokens) {\n\treturn convertTokensToRegex(parse(routeOrTokens));\n}\n\n/**\n * Extracts data from the given path according to the specified route format.\n * @param {!Array|string} routeOrTokens Either a route format string or tokens\n * previously parsed via the `parse` function.\n * @param {string} The path to extract param data from.\n * @return {Object} The data object, or null if the path doesn't\n * match the given format.\n */\nexport function extractData(routeOrTokens, path) {\n\tconst data = {};\n\tconst tokens = parse(routeOrTokens);\n\tconst match = path.match(convertTokensToRegex(tokens));\n\n\tif (!match) {\n\t\treturn null;\n\t}\n\n\tlet paramIndex = 1;\n\tfor (let i = 0; i < tokens.length; i++) {\n\t\tif (!core.isString(tokens[i])) {\n\t\t\tlet value = match[paramIndex++];\n\t\t\tif (core.isDef(value)) {\n\t\t\t\tif (tokens[i].repeat) {\n\t\t\t\t\tvalue = value.split('/');\n\t\t\t\t}\n\t\t\t\tdata[tokens[i].name] = value;\n\t\t\t}\n\t\t}\n\t}\n\treturn data;\n}\n","'use strict';\n\nimport { isDefAndNotNull, isFunction, isString } from 'metal';\nimport { extractData, parse, toRegex } from 'metal-path-parser';\n\nclass Route {\n\n\t/**\n\t * Route class.\n\t * @param {!string|RegExp|Function} path\n\t * @param {!Function} handler\n\t * @constructor\n\t */\n\tconstructor(path, handler) {\n\t\tif (!isDefAndNotNull(path)) {\n\t\t\tthrow new Error('Route path not specified.');\n\t\t}\n\t\tif (!isFunction(handler)) {\n\t\t\tthrow new Error('Route handler is not a function.');\n\t\t}\n\n\t\t/**\n\t\t * Defines the handler which will execute once a URL in the application\n\t\t * matches the path.\n\t\t * @type {!Function}\n\t\t * @protected\n\t\t */\n\t\tthis.handler = handler;\n\n\t\t/**\n\t\t * Defines the path which will trigger the route handler.\n\t\t * @type {!string|RegExp|Function}\n\t\t * @protected\n\t\t */\n\t\tthis.path = path;\n\t}\n\n\t/**\n\t* Builds parsed data (regex and tokens) for this route.\n\t* @return {!Object}\n\t* @protected\n\t*/\n\tbuildParsedData_() {\n\t\tif (!this.parsedData_) {\n\t\t\tvar tokens = parse(this.path);\n\t\t\tvar regex = toRegex(tokens);\n\t\t\tthis.parsedData_ = {\n\t\t\t\tregex,\n\t\t\t\ttokens\n\t\t\t};\n\t\t}\n\t\treturn this.parsedData_;\n\t}\n\n\t/**\n\t * Extracts param data from the given path, according to this route.\n\t * @param {string} path The url path to extract params from.\n\t * @return {Object} The extracted data, if the path matches this route, or\n\t * null otherwise.\n\t */\n\textractParams(path) {\n\t\tif (isString(this.path)) {\n\t\t\treturn extractData(this.buildParsedData_().tokens, path);\n\t\t}\n\t\treturn {};\n\t}\n\n\t/**\n\t * Gets the route handler.\n\t * @return {!Function}\n\t */\n\tgetHandler() {\n\t\treturn this.handler;\n\t}\n\n\t/**\n\t * Gets the route path.\n\t * @return {!string|RegExp|Function}\n\t */\n\tgetPath() {\n\t\treturn this.path;\n\t}\n\n\t/**\n \t * Matches if the router can handle the tested path.\n \t * @param {!string} value Path to test (may contain the querystring part).\n\t * @return {boolean} Returns true if matches any route.\n\t */\n\tmatchesPath(value) {\n\t\tvar path = this.path;\n\n\t\tif (isFunction(path)) {\n\t\t\treturn path(value);\n\t\t}\n\t\tif (isString(path)) {\n\t\t\tpath = this.buildParsedData_().regex;\n\t\t}\n\t\tif (path instanceof RegExp) {\n\t\t\treturn value.search(path) > -1;\n\t\t}\n\n\t\treturn false;\n\t}\n\n}\n\nexport default Route;\n","'use strict';\n\nimport { Disposable } from 'metal';\n\nclass Cacheable extends Disposable {\n\n\t/**\n\t * Abstract class for defining cacheable behavior.\n\t * @constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the cached data.\n\t\t * @type {!Object}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.cache = null;\n\n\t\t/**\n\t\t * Holds whether class is cacheable.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.cacheable = false;\n\t}\n\n\t/**\n\t * Adds content to the cache.\n\t * @param {string} content Content to be cached.\n\t * @chainable\n\t */\n\taddCache(content) {\n\t\tif (this.cacheable) {\n\t\t\tthis.cache = content;\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Clears the cache.\n\t * @chainable\n\t */\n\tclearCache() {\n\t\tthis.cache = null;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.clearCache();\n\t}\n\n\t/**\n\t * Gets the cached content.\n\t * @return {Object} Cached content.\n\t * @protected\n\t */\n\tgetCache() {\n\t\treturn this.cache;\n\t}\n\n\t/**\n\t * Whether the class is cacheable.\n\t * @return {boolean} Returns true when class is cacheable, false otherwise.\n\t */\n\tisCacheable() {\n\t\treturn this.cacheable;\n\t}\n\n\t/**\n\t * Sets whether the class is cacheable.\n\t * @param {boolean} cacheable\n\t */\n\tsetCacheable(cacheable) {\n\t\tif (!cacheable) {\n\t\t\tthis.clearCache();\n\t\t}\n\t\tthis.cacheable = cacheable;\n\t}\n\n}\n\nexport default Cacheable;\n","'use strict';\n\nimport { getUid } from 'metal';\nimport { globalEval } from 'metal-dom';\nimport Cacheable from '../cacheable/Cacheable';\nimport CancellablePromise from 'metal-promise';\n\nclass Screen extends Cacheable {\n\n\t/**\n\t * Screen class is a special type of route handler that provides helper\n\t * utilities that adds lifecycle and methods to provide content to each\n\t * registered surface.\n\t * @constructor\n\t * @extends {Cacheable}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the screen id.\n\t\t * @type {string}\n\t\t * @protected\n\t\t */\n\t\tthis.id = this.makeId_(getUid());\n\n\t\t/**\n\t\t * Holds the screen meta tags. Relevant when the meta tags\n\t\t * should be updated when screen is rendered.\n\t\t */\n\t\tthis.metas = null;\n\n\t\t/**\n\t\t * Holds the screen title. Relevant when the page title should be\n\t\t * upadated when screen is rendered.\n\t\t * @type {?string=}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.title = null;\n\t}\n\n\t/**\n\t * Fires when the screen is active. Allows a screen to perform any setup\n\t * that requires its DOM to be visible. Lifecycle.\n\t */\n\tactivate() {\n\t\tconsole.log('Screen [' + this + '] activate');\n\t}\n\n\t/**\n\t * Gives the Screen a chance to cancel the navigation and stop itself from\n\t * activating. Can be used, for example, to prevent navigation if a user\n\t * is not authenticated. Lifecycle.\n\t * @return {boolean=|?CancellablePromise=} If returns or resolves to true,\n\t * the current screen is locked and the next nagivation interrupted.\n\t */\n\tbeforeActivate() {\n\t\tconsole.log('Screen [' + this + '] beforeActivate');\n\t}\n\n\t/**\n\t * Gives the Screen a chance to cancel the navigation and stop itself from\n\t * being deactivated. Can be used, for example, if the screen has unsaved\n\t * state. Lifecycle. Clean-up should not be preformed here, since the\n\t * navigation may still be cancelled. Do clean-up in deactivate.\n\t * @return {boolean=|?CancellablePromise=} If returns or resolves to true,\n\t * the current screen is locked and the next nagivation interrupted.\n\t */\n\tbeforeDeactivate() {\n\t\tconsole.log('Screen [' + this + '] beforeDeactivate');\n\t}\n\n\t/**\n\t * Gives the Screen a chance format the path before history update.\n\t * @path {!string} path Navigation path.\n\t * @return {!string} Navigation path to use on history.\n\t */\n\tbeforeUpdateHistoryPath(path) {\n\t\treturn path;\n\t}\n\n\t/**\n\t * Gives the Screen a chance format the state before history update.\n\t * @path {!object} state History state.\n\t * @return {!object} History state to use on history.\n\t */\n\tbeforeUpdateHistoryState(state) {\n\t\treturn state;\n\t}\n\n\t/**\n\t * Allows a screen to do any cleanup necessary after it has been\n\t * deactivated, for example cancelling outstanding requests or stopping\n\t * timers. Lifecycle.\n\t */\n\tdeactivate() {\n\t\tconsole.log('Screen [' + this + '] deactivate');\n\t}\n\n\t/**\n\t * Dispose a screen, either after it is deactivated (in the case of a\n\t * non-cacheable view) or when the App is itself disposed for whatever\n\t * reason. Lifecycle.\n\t */\n\tdisposeInternal() {\n\t\tsuper.disposeInternal();\n\t\tconsole.log('Screen [' + this + '] dispose');\n\t}\n\n\t/**\n\t * Allows a screen to evaluate scripts before the element is made visible.\n\t * Lifecycle.\n\t * @param {!object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @return {?CancellablePromise=} This can return a promise, which will\n\t * pause the navigation until it is resolved.\n\t */\n\tevaluateScripts(surfaces) {\n\t\tObject.keys(surfaces).forEach(sId => {\n\t\t\tif (surfaces[sId].activeChild) {\n\t\t\t\tglobalEval.runScriptsInElement(surfaces[sId].activeChild);\n\t\t\t}\n\t\t});\n\t\treturn CancellablePromise.resolve();\n\t}\n\n\t/**\n\t * Allows a screen to evaluate styles before the element is made visible.\n\t * Lifecycle.\n\t * @param {!object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @return {?CancellablePromise=} This can return a promise, which will\n\t * pause the navigation until it is resolved.\n\t */\n\tevaluateStyles() {\n\t\treturn CancellablePromise.resolve();\n\t}\n\n\t/**\n\t * Allows a screen to perform any setup immediately before the element is\n\t * made visible. Lifecycle.\n\t * @param {!object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @return {?CancellablePromise=} This can return a promise, which will pause the\n\t * navigation until it is resolved.\n\t */\n\tflip(surfaces) {\n\t\tconsole.log('Screen [' + this + '] flip');\n\n\t\tvar transitions = [];\n\n\t\tObject.keys(surfaces).forEach(sId => {\n\t\t\tvar surface = surfaces[sId];\n\t\t\tvar deferred = surface.show(this.id);\n\t\t\ttransitions.push(deferred);\n\t\t});\n\n\t\treturn CancellablePromise.all(transitions);\n\t}\n\n\t/**\n\t * Gets the screen id.\n\t * @return {string}\n\t */\n\tgetId() {\n\t\treturn this.id;\n\t}\n\n\t/**\n\t * Gets the screen meta tags.\n\t * @return {NodeList|Node}\n\t */\n\tgetMetas() {\n\t\treturn this.metas;\n\t}\n\n\t/**\n\t * Returns the content for the given surface, or null if the surface isn't\n\t * used by this screen. This will be called when a screen is initially\n\t * constructed or, if a screen is non-cacheable, when navigated.\n\t * @param {!string} surfaceId The id of the surface DOM element.\n\t * @param {!Object} params Params extracted from the current path.\n\t * @return {?string|Element=} This can return a string or node representing\n\t * the content of the surface. If returns falsy values surface default\n\t * content is restored.\n\t */\n\tgetSurfaceContent() {\n\t\tconsole.log('Screen [' + this + '] getSurfaceContent');\n\t}\n\n\t/**\n\t * Gets the screen title.\n\t * @return {?string=}\n\t */\n\tgetTitle() {\n\t\treturn this.title;\n\t}\n\n\t/**\n\t * Returns all contents for the surfaces. This will pass the loaded content\n\t * to Screen.load with all information you\n\t * need to fulfill the surfaces. Lifecycle.\n\t * @param {!string=} path The requested path.\n\t * @return {!CancellablePromise} This can return a string representing the\n\t * contents of the surfaces or a promise, which will pause the navigation\n\t * until it is resolved. This is useful for loading async content.\n\t */\n\tload() {\n\t\tconsole.log('Screen [' + this + '] load');\n\t\treturn CancellablePromise.resolve();\n\t}\n\n\t/**\n\t * Makes the id for the screen.\n\t * @param {!string} id The screen id the content belongs too.\n\t * @return {string}\n\t * @private\n\t */\n\tmakeId_(id) {\n\t\treturn 'screen_' + id;\n\t}\n\n\t/**\n\t * Sets the screen id.\n\t * @param {!string} id\n\t */\n\tsetId(id) {\n\t\tthis.id = id;\n\t}\n\n\t/**\n\t * Sets the screen meta tags.\n\t * @param {NodeList|Node} metas\n\t */\n\tsetMetas(metas) {\n\t\tthis.metas = metas;\n\t}\n\n\t/**\n\t * Sets the screen title.\n\t * @param {?string=} title\n\t */\n\tsetTitle(title) {\n\t\tthis.title = title;\n\t}\n\n\t/**\n\t * @return {string}\n\t */\n\ttoString() {\n\t\treturn this.id;\n\t}\n\n}\n\n/**\n * @param {*} object\n * @return {boolean} Whether a given instance implements\n * Screen.\n */\nScreen.isImplementedBy = function(object) {\n\treturn object instanceof Screen;\n};\n\nexport default Screen;\n","'use strict';\n\nimport globals from '../globals/globals';\nimport { Disposable, isDefAndNotNull } from 'metal';\nimport { append, removeChildren, exitDocument } from 'metal-dom';\nimport CancellablePromise from 'metal-promise';\n\nclass Surface extends Disposable {\n\n\t/**\n\t * Surface class representing the references to elements on the page that\n\t * can potentially be updated by App.\n\t * @param {string} id\n\t * @constructor\n\t */\n\tconstructor(id) {\n\t\tsuper();\n\n\t\tif (!id) {\n\t\t\tthrow new Error('Surface element id not specified. A surface element requires a valid id.');\n\t\t}\n\n\t\t/**\n\t\t * Holds the active child element.\n\t\t * @type {Element}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.activeChild = null;\n\n\t\t/**\n\t\t * Holds the default child element.\n\t\t * @type {Element}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.defaultChild = null;\n\n\t\t/**\n\t\t * Holds the element with the specified surface id, if not found creates a\n\t\t * new element with the specified id.\n\t\t * @type {Element}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.element = null;\n\n\t\t/**\n\t\t * Holds the surface id.\n\t\t * @type {String}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.id = id;\n\n\t\t/**\n\t\t * Holds the default transitionFn for the surfaces.\n\t\t * @param {?Element=} from The visible surface element.\n\t\t * @param {?Element=} to The surface element to be flipped.\n\t\t * @default null\n\t\t */\n\t\tthis.transitionFn = null;\n\n\t\tthis.defaultChild = this.getChild(Surface.DEFAULT);\n\t\tthis.maybeWrapContentAsDefault_();\n\t\tthis.activeChild = this.defaultChild;\n\t}\n\n\t/**\n\t * Adds screen content to a surface. If content hasn't been passed, see if\n\t * an element exists in the DOM that matches the id. By convention, the\n\t * element should already be nested in the right element and should have an\n\t * id that is a concatentation of the surface id + '-' + the screen id.\n\t * @param {!string} screenId The screen id the content belongs too.\n\t * @param {?string|Element=} opt_content The string content or element to\n\t * add be added as surface content.\n\t * @return {Element}\n\t */\n\taddContent(screenId, opt_content) {\n\t\tvar child = this.defaultChild;\n\n\t\tif (isDefAndNotNull(opt_content)) {\n\t\t\tchild = this.getChild(screenId);\n\t\t\tif (child) {\n\t\t\t\tremoveChildren(child);\n\t\t\t} else {\n\t\t\t\tchild = this.createChild(screenId);\n\t\t\t\tthis.transition(child, null);\n\t\t\t}\n\t\t\tappend(child, opt_content);\n\t\t}\n\n\t\tvar element = this.getElement();\n\n\t\tif (element && child) {\n\t\t\tappend(element, child);\n\t\t}\n\n\t\treturn child;\n\t}\n\n\t/**\n\t * Creates child node for the surface.\n\t * @param {!string} screenId The screen id.\n\t * @return {Element}\n\t */\n\tcreateChild(screenId) {\n\t\tvar child = globals.document.createElement('div');\n\t\tchild.setAttribute('id', this.makeId_(screenId));\n\t\treturn child;\n\t}\n\n\t/**\n\t * Gets child node of the surface.\n\t * @param {!string} screenId The screen id.\n\t * @return {?Element}\n\t */\n\tgetChild(screenId) {\n\t\treturn globals.document.getElementById(this.makeId_(screenId));\n\t}\n\n\t/**\n\t * Gets the surface element from element, and sets it to the el property of\n\t * the current instance.\n\t * this.element will be used.\n\t * @return {?Element} The current surface element.\n\t */\n\tgetElement() {\n\t\tif (this.element) {\n\t\t\treturn this.element;\n\t\t}\n\t\tthis.element = globals.document.getElementById(this.id);\n\t\treturn this.element;\n\t}\n\n\t/**\n\t * Gets the surface id.\n\t * @return {String}\n\t */\n\tgetId() {\n\t\treturn this.id;\n\t}\n\n\t/**\n\t * Gets the surface transition function.\n\t * See Surface.defaultTransition.\n\t * @return {?Function=} The transition function.\n\t */\n\tgetTransitionFn() {\n\t\treturn this.transitionFn;\n\t}\n\n\t/**\n\t * Makes the id for the element that holds content for a screen.\n\t * @param {!string} screenId The screen id the content belongs too.\n\t * @return {String}\n\t * @private\n\t */\n\tmakeId_(screenId) {\n\t\treturn this.id + '-' + screenId;\n\t}\n\n\t/**\n\t * If default child is missing, wraps surface content as default child. If\n\t * surface have static content, make sure to place a\n\t * surfaceId-default element inside surface, only contents\n\t * inside the default child will be replaced by navigation.\n\t */\n\tmaybeWrapContentAsDefault_() {\n\t\tvar element = this.getElement();\n\t\tif (element && !this.defaultChild) {\n\t\t\tvar fragment = globals.document.createDocumentFragment();\n\t\t\twhile (element.firstChild) {\n\t\t\t\tfragment.appendChild(element.firstChild);\n\t\t\t}\n\t\t\tthis.defaultChild = this.addContent(Surface.DEFAULT, fragment);\n\t\t\tthis.transition(null, this.defaultChild);\n\t\t}\n\t}\n\n\t/**\n\t * Sets the surface id.\n\t * @param {!string} id\n\t */\n\tsetId(id) {\n\t\tthis.id = id;\n\t}\n\n\t/**\n\t * Sets the surface transition function.\n\t * See Surface.defaultTransition.\n\t * @param {?Function=} transitionFn The transition function.\n\t */\n\tsetTransitionFn(transitionFn) {\n\t\tthis.transitionFn = transitionFn;\n\t}\n\n\t/**\n\t * Shows screen content from a surface.\n\t * @param {String} screenId The screen id to show.\n\t * @return {CancellablePromise} Pauses the navigation until it is resolved.\n\t */\n\tshow(screenId) {\n\t\tvar from = this.activeChild;\n\t\tvar to = this.getChild(screenId);\n\t\tif (!to) {\n\t\t\tto = this.defaultChild;\n\t\t}\n\t\tthis.activeChild = to;\n\t\treturn this.transition(from, to).thenAlways(() => {\n\t\t\tif (from && from !== to) {\n\t\t\t\texitDocument(from);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Removes screen content from a surface.\n\t * @param {!string} screenId The screen id to remove.\n\t */\n\tremove(screenId) {\n\t\tvar child = this.getChild(screenId);\n\t\tif (child) {\n\t\t\texitDocument(child);\n\t\t}\n\t}\n\n\t/**\n\t * @return {String}\n\t */\n\ttoString() {\n\t\treturn this.id;\n\t}\n\n\t/**\n\t * Invokes the transition function specified on transition attribute.\n\t * @param {?Element=} from\n\t * @param {?Element=} to\n\t * @return {?CancellablePromise=} This can return a promise, which will pause the\n\t * navigation until it is resolved.\n\t */\n\ttransition(from, to) {\n\t\tvar transitionFn = this.transitionFn || Surface.defaultTransition;\n\t\treturn CancellablePromise.resolve(transitionFn.call(this, from, to));\n\t}\n\n}\n\n/**\n * Holds the default surface name. Elements on the page must contain a child\n * element containing the default content, this element must be as following:\n *\n * Example:\n * \n *
\n *
Default surface content.
\n *
\n *
\n *\n * The default content is relevant for the initial page content. When a\n * screen doesn't provide content for the surface the default content is\n * restored into the page.\n *\n * @type {!String}\n * @default default\n * @static\n */\nSurface.DEFAULT = 'default';\n\n/**\n * Holds the default transition for all surfaces. Each surface could have its\n * own transition.\n *\n * Example:\n *\n * \n * surface.setTransitionFn(function(from, to) {\n * if (from) {\n * from.style.display = 'none';\n * from.classList.remove('flipped');\n * }\n * if (to) {\n * to.style.display = 'block';\n * to.classList.add('flipped');\n * }\n * return null;\n * });\n * \n *\n * @param {?Element=} from The visible surface element.\n * @param {?Element=} to The surface element to be flipped.\n * @static\n */\nSurface.defaultTransition = function(from, to) {\n\tif (from) {\n\t\tfrom.style.display = 'none';\n\t\tfrom.classList.remove('flipped');\n\t}\n\tif (to) {\n\t\tto.style.display = 'block';\n\t\tto.classList.add('flipped');\n\t}\n};\n\nexport default Surface;\n","'use strict';\n\nimport { addClasses, delegate, match, on, removeClasses } from 'metal-dom';\nimport { array, async, isDefAndNotNull, isString, object } from 'metal';\nimport { EventEmitter, EventHandler } from 'metal-events';\nimport CancellablePromise from 'metal-promise';\nimport debounce from 'metal-debounce';\nimport globals from '../globals/globals';\nimport Route from '../route/Route';\nimport Screen from '../screen/Screen';\nimport Surface from '../surface/Surface';\nimport Uri from 'metal-uri';\nimport utils from '../utils/utils';\n\nconst NavigationStrategy = {\n\tIMMEDIATE: 'immediate',\n\tSCHEDULE_LAST: 'scheduleLast'\n};\n\nclass App extends EventEmitter {\n\n\t/**\n\t * App class that handle routes and screens lifecycle.\n\t * @constructor\n\t * @extends {EventEmitter}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the active screen.\n\t\t * @type {?Screen}\n\t\t * @protected\n\t\t */\n\t\tthis.activeScreen = null;\n\n\t\t/**\n\t\t * Holds the active path containing the query parameters.\n\t\t * @type {?string}\n\t\t * @protected\n\t\t */\n\t\tthis.activePath = null;\n\n\t\t/**\n\t\t * Allows prevent navigate from dom prevented event.\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.allowPreventNavigate = true;\n\n\t\t/**\n\t\t * Holds link base path.\n\t\t * @type {!string}\n\t\t * @default ''\n\t\t * @protected\n\t\t */\n\t\tthis.basePath = '';\n\n\t\t/**\n\t\t * Holds the value of the browser path before a navigation is performed.\n\t\t * @type {!string}\n\t\t * @default the current browser path.\n\t\t * @protected\n\t\t */\n\t\tthis.browserPathBeforeNavigate = utils.getCurrentBrowserPathWithoutHash();\n\n\t\t/**\n\t\t * Captures scroll position from scroll event.\n\t\t * @type {!boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.captureScrollPositionFromScrollEvent = true;\n\n\t\t/**\n\t\t * Holds the default page title.\n\t\t * @type {string}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.defaultTitle = globals.document.title;\n\n\t\t/**\n\t\t * Holds the form selector to define forms that are routed.\n\t\t * @type {!string}\n\t\t * @default form[enctype=\"multipart/form-data\"]:not([data-senna-off])\n\t\t * @protected\n\t\t */\n\t\tthis.formSelector = 'form[enctype=\"multipart/form-data\"]:not([data-senna-off])';\n\n\t\t/**\n\t\t * When enabled, the route matching ignores query string from the path.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.ignoreQueryStringFromRoutePath = false;\n\n\t\t/**\n\t\t * Holds the link selector to define links that are routed.\n\t\t * @type {!string}\n\t\t * @default a:not([data-senna-off])\n\t\t * @protected\n\t\t */\n\t\tthis.linkSelector = 'a:not([data-senna-off]):not([target=\"_blank\"])';\n\n\t\t/**\n\t\t * Holds the loading css class.\n\t\t * @type {!string}\n\t\t * @default senna-loading\n\t\t * @protected\n\t\t */\n\t\tthis.loadingCssClass = 'senna-loading';\n\n\t\t/**\n\t\t * Using the History API to manage your URLs is awesome and, as it happens,\n\t\t * a crucial feature of good web apps. One of its downsides, however, is\n\t\t * that scroll positions are stored and then, more importantly, restored\n\t\t * whenever you traverse the history. This often means unsightly jumps as\n\t\t * the scroll position changes automatically, and especially so if your app\n\t\t * does transitions, or changes the contents of the page in any way.\n\t\t * Ultimately this leads to an horrible user experience. The good news is,\n\t\t * however, that there’s a potential fix: history.scrollRestoration.\n\t\t * https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.nativeScrollRestorationSupported = ('scrollRestoration' in globals.window.history);\n\n\t\t/**\n\t\t * When set to NavigationStrategy.SCHEDULE_LAST means that the current navigation\n\t\t * cannot be Cancelled to start another and will be queued in\n\t\t * scheduledNavigationQueue. When NavigationStrategy.IMMEDIATE means that all\n\t\t * navigation will be cancelled to start another.\n\t\t * @type {!string}\n\t\t * @default immediate\n\t\t * @protected\n\t\t */\n\t\tthis.navigationStrategy = NavigationStrategy.IMMEDIATE;\n\n\t\t/**\n\t\t * When set to true there is a pendingNavigate that has not yet been\n\t\t * resolved or rejected.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.isNavigationPending = false;\n\n\t\t/**\n\t\t * Holds a deferred with the current navigation.\n\t\t * @type {?CancellablePromise}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.pendingNavigate = null;\n\n\t\t/**\n\t\t * Holds the window horizontal scroll position when the navigation using\n\t\t * back or forward happens to be restored after the surfaces are updated.\n\t\t * @type {!Number}\n\t\t * @default 0\n\t\t * @protected\n\t\t */\n\t\tthis.popstateScrollLeft = 0;\n\n\t\t/**\n\t\t * Holds the window vertical scroll position when the navigation using\n\t\t * back or forward happens to be restored after the surfaces are updated.\n\t\t * @type {!Number}\n\t\t * @default 0\n\t\t * @protected\n\t\t */\n\t\tthis.popstateScrollTop = 0;\n\n\t\t/**\n\t\t * Holds the redirect path containing the query parameters.\n\t\t * @type {?string}\n\t\t * @protected\n\t\t */\n\t\tthis.redirectPath = null;\n\n\t\t/**\n\t\t * Holds the screen routes configuration.\n\t\t * @type {?Array}\n\t\t * @default []\n\t\t * @protected\n\t\t */\n\t\tthis.routes = [];\n\n\t\t/**\n\t\t * Holds a queue that stores every DOM event that can initiate a navigation.\n\t\t * @type {!Event}\n\t\t * @default []\n\t\t * @protected\n\t\t */\n\t\tthis.scheduledNavigationQueue = [];\n\n\t\t/**\n\t\t * Maps the screen instances by the url containing the parameters.\n\t\t * @type {?Object}\n\t\t * @default {}\n\t\t * @protected\n\t\t */\n\t\tthis.screens = {};\n\n\t\t/**\n\t\t * When set to true the first erroneous popstate fired on page load will be\n\t\t * ignored, only if globals.window.history.state is also\n\t\t * null.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.skipLoadPopstate = false;\n\n\t\t/**\n\t\t * Maps that index the surfaces instances by the surface id.\n\t\t * @type {?Object}\n\t\t * @default {}\n\t\t * @protected\n\t\t */\n\t\tthis.surfaces = {};\n\n\t\t/**\n\t\t * When set to true, moves the scroll position after popstate, or to the\n\t\t * top of the viewport for new navigation. If false, the browser will\n\t\t * take care of scroll restoration.\n\t\t * @type {!boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.updateScrollPosition = true;\n\n\t\tthis.appEventHandlers_ = new EventHandler();\n\n\t\tthis.appEventHandlers_.add(\n\t\t\ton(globals.window, 'scroll', debounce(this.onScroll_.bind(this), 100)),\n\t\t\ton(globals.window, 'load', this.onLoad_.bind(this)),\n\t\t\ton(globals.window, 'popstate', this.onPopstate_.bind(this))\n\t\t);\n\n\t\tthis.on('startNavigate', this.onStartNavigate_);\n\t\tthis.on('beforeNavigate', this.onBeforeNavigate_);\n\t\tthis.on('beforeNavigate', this.onBeforeNavigateDefault_, true);\n\t\tthis.on('beforeUnload', this.onBeforeUnloadDefault_);\n\n\t\tthis.setLinkSelector(this.linkSelector);\n\t\tthis.setFormSelector(this.formSelector);\n\n\t\tthis.maybeOverloadBeforeUnload_();\n\t}\n\n\t/**\n\t * Adds one or more screens to the application.\n\t *\n\t * Example:\n\t *\n\t * \n\t * app.addRoutes({ path: '/foo', handler: FooScreen });\n\t * or\n\t * app.addRoutes([{ path: '/foo', handler: function(route) { return new FooScreen(); } }]);\n\t * \n\t *\n\t * @param {Object} or {Array} routes Single object or an array of object.\n\t * Each object should contain path and screen.\n\t * The path should be a string or a regex that maps the\n\t * navigation route to a screen class definition (not an instance), e.g:\n\t * { path: \"/home:param1\", handler: MyScreen }\n\t * { path: /foo.+/, handler: MyScreen }\n\t * @chainable\n\t */\n\taddRoutes(routes) {\n\t\tif (!Array.isArray(routes)) {\n\t\t\troutes = [routes];\n\t\t}\n\t\troutes.forEach((route) => {\n\t\t\tif (!(route instanceof Route)) {\n\t\t\t\troute = new Route(route.path, route.handler);\n\t\t\t}\n\t\t\tthis.routes.push(route);\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds one or more surfaces to the application.\n\t * @param {Surface|String|Array.} surfaces\n\t * Surface element id or surface instance. You can also pass an Array\n\t * whichcontains surface instances or id. In case of ID, these should be\n\t * the id of surface element.\n\t * @chainable\n\t */\n\taddSurfaces(surfaces) {\n\t\tif (!Array.isArray(surfaces)) {\n\t\t\tsurfaces = [surfaces];\n\t\t}\n\t\tsurfaces.forEach((surface) => {\n\t\t\tif (isString(surface)) {\n\t\t\t\tsurface = new Surface(surface);\n\t\t\t}\n\t\t\tthis.surfaces[surface.getId()] = surface;\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns if can navigate to path.\n\t * @param {!string} url\n\t * @return {boolean}\n\t */\n\tcanNavigate(url) {\n\t\tconst uri = utils.isWebUri(url);\n\n\t\tif (!uri) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst path = utils.getUrlPath(url);\n\n\t\tif (!this.isLinkSameOrigin_(uri.getHost())) {\n\t\t\tconsole.log('Offsite link clicked');\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.isSameBasePath_(path)) {\n\t\t\tconsole.log('Link clicked outside app\\'s base path');\n\t\t\treturn false;\n\t\t}\n\t\t// Prevents navigation if it's a hash change on the same url.\n\t\tif (uri.getHash() && utils.isCurrentBrowserPath(path)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.findRoute(path)) {\n\t\t\tconsole.log('No route for ' + path);\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Clear screens cache.\n\t * @chainable\n\t */\n\tclearScreensCache() {\n\t\tObject.keys(this.screens).forEach((path) => {\n\t\t\tif (path === this.activePath) {\n\t\t\t\tthis.activeScreen.clearCache();\n\t\t\t} else if (!(this.isNavigationPending && this.pendingNavigate.path === path)) {\n\t\t\t\tthis.removeScreen(path);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves or create a screen instance to a path.\n\t * @param {!string} path Path containing the querystring part.\n\t * @return {Screen}\n\t */\n\tcreateScreenInstance(path, route) {\n\t\tif (!this.pendingNavigate && path === this.activePath) {\n\t\t\tconsole.log('Already at destination, refresh navigation');\n\t\t\treturn this.activeScreen;\n\t\t}\n\t\t/* jshint newcap: false */\n\t\tvar screen = this.screens[path];\n\t\tif (!screen) {\n\t\t\tvar handler = route.getHandler();\n\t\t\tif (handler === Screen || Screen.isImplementedBy(handler.prototype)) {\n\t\t\t\tscreen = new handler();\n\t\t\t} else {\n\t\t\t\tscreen = handler(route) || new Screen();\n\t\t\t}\n\t\t\tconsole.log('Create screen for [' + path + '] [' + screen + ']');\n\t\t}\n\t\treturn screen;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisposeInternal() {\n\t\tif (this.activeScreen) {\n\t\t\tthis.removeScreen(this.activePath);\n\t\t}\n\t\tthis.clearScreensCache();\n\t\tthis.formEventHandler_.removeListener();\n\t\tthis.linkEventHandler_.removeListener();\n\t\tthis.appEventHandlers_.removeAllListeners();\n\t\tsuper.disposeInternal();\n\t}\n\n\t/**\n\t * Dispatches to the first route handler that matches the current path, if\n\t * any.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tdispatch() {\n\t\treturn this.navigate(utils.getCurrentBrowserPath(), true);\n\t}\n\n\t/**\n\t * Starts navigation to a path.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tdoNavigate_(path, opt_replaceHistory) {\n\t\tvar route = this.findRoute(path);\n\t\tif (!route) {\n\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('No route for ' + path));\n\t\t\treturn this.pendingNavigate;\n\t\t}\n\n\t\tconsole.log('Navigate to [' + path + ']');\n\n\t\tthis.stopPendingNavigate_();\n\t\tthis.isNavigationPending = true;\n\n\t\tvar nextScreen = this.createScreenInstance(path, route);\n\n\t\treturn this.maybePreventDeactivate_()\n\t\t\t.then(() => this.maybePreventActivate_(nextScreen))\n\t\t\t.then(() => nextScreen.load(path))\n\t\t\t.then(() => {\n\t\t\t\t// At this point we cannot stop navigation and all received\n\t\t\t\t// navigate candidates will be queued at scheduledNavigationQueue.\n\t\t\t\tthis.navigationStrategy = NavigationStrategy.SCHEDULE_LAST;\n\n\t\t\t\tif (this.activeScreen) {\n\t\t\t\t\tthis.activeScreen.deactivate();\n\t\t\t\t}\n\t\t\t\tthis.prepareNavigateHistory_(path, nextScreen, opt_replaceHistory);\n\t\t\t\tthis.prepareNavigateSurfaces_(\n\t\t\t\t\tnextScreen,\n\t\t\t\t\tthis.surfaces,\n\t\t\t\t\tthis.extractParams(route, path)\n\t\t\t\t);\n\t\t\t})\n\t\t\t.then(() => nextScreen.evaluateStyles(this.surfaces))\n\t\t\t.then(() => nextScreen.flip(this.surfaces))\n\t\t\t.then(() => nextScreen.evaluateScripts(this.surfaces))\n\t\t\t.then(() => this.maybeUpdateScrollPositionState_())\n\t\t\t.then(() => this.syncScrollPositionSyncThenAsync_())\n\t\t\t.then(() => this.finalizeNavigate_(path, nextScreen))\n\t\t\t.then(() => this.maybeOverloadBeforeUnload_())\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.isNavigationPending = false;\n\t\t\t\tthis.handleNavigateError_(path, nextScreen, reason);\n\t\t\t\tthrow reason;\n\t\t\t})\n\t\t\t.thenAlways(() => {\n\t\t\t\tthis.navigationStrategy = NavigationStrategy.IMMEDIATE;\n\n\t\t\t\tif (this.scheduledNavigationQueue.length) {\n\t\t\t\t\tconst scheduledNavigation = this.scheduledNavigationQueue.shift();\n\t\t\t\t\tthis.maybeNavigate_(scheduledNavigation.href, scheduledNavigation);\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Extracts params according to the given path and route.\n\t * @param {!Route} route\n\t * @param {string} path\n\t * @param {!Object}\n\t */\n\textractParams(route, path) {\n\t\treturn route.extractParams(this.getRoutePath(path));\n\t}\n\n\t/**\n\t * Finalizes a screen navigation.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @protected\n\t */\n\tfinalizeNavigate_(path, nextScreen) {\n\t\tnextScreen.activate();\n\n\t\tif (this.activeScreen && !this.activeScreen.isCacheable()) {\n\t\t\tif (this.activeScreen !== nextScreen) {\n\t\t\t\tthis.removeScreen(this.activePath);\n\t\t\t}\n\t\t}\n\n\t\tthis.activePath = path;\n\t\tthis.activeScreen = nextScreen;\n\t\tthis.browserPathBeforeNavigate = utils.getCurrentBrowserPathWithoutHash();\n\t\tthis.screens[path] = nextScreen;\n\t\tthis.isNavigationPending = false;\n\t\tthis.pendingNavigate = null;\n\t\tglobals.capturedFormElement = null;\n\t\tglobals.capturedFormButtonElement = null;\n\t\tconsole.log('Navigation done');\n\t}\n\n\t/**\n\t * Finds a route for the test path. Returns true if matches has a route,\n\t * otherwise returns null.\n\t * @param {!string} path Path containing the querystring part.\n\t * @return {?Object} Route handler if match any or null if the\n\t * path is the same as the current url and the path contains a fragment.\n\t */\n\tfindRoute(path) {\n\t\tpath = this.getRoutePath(path);\n\t\tfor (var i = 0; i < this.routes.length; i++) {\n\t\t\tvar route = this.routes[i];\n\t\t\tif (route.matchesPath(path)) {\n\t\t\t\treturn route;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Gets allow prevent navigate.\n\t * @return {boolean}\n\t */\n\tgetAllowPreventNavigate() {\n\t\treturn this.allowPreventNavigate;\n\t}\n\n\t/**\n\t * Gets link base path.\n\t * @return {!string}\n\t */\n\tgetBasePath() {\n\t\treturn this.basePath;\n\t}\n\n\t/**\n\t * Gets the default page title.\n\t * @return {string} defaultTitle\n\t */\n\tgetDefaultTitle() {\n\t\treturn this.defaultTitle;\n\t}\n\n\t/**\n\t * Gets the form selector.\n\t * @return {!string}\n\t */\n\tgetFormSelector() {\n\t\treturn this.formSelector;\n\t}\n\n\t/**\n\t * Check if route matching is ignoring query string from the route path.\n\t * @return {boolean}\n\t */\n\tgetIgnoreQueryStringFromRoutePath() {\n\t\treturn this.ignoreQueryStringFromRoutePath;\n\t}\n\n\t/**\n\t * Gets the link selector.\n\t * @return {!string}\n\t */\n\tgetLinkSelector() {\n\t\treturn this.linkSelector;\n\t}\n\n\t/**\n\t * Gets the loading css class.\n\t * @return {!string}\n\t */\n\tgetLoadingCssClass() {\n\t\treturn this.loadingCssClass;\n\t}\n\n\t/**\n\t * Returns the given path formatted to be matched by a route. This will,\n\t * for example, remove the base path from it, but make sure it will end\n\t * with a '/'.\n\t * @param {string} path\n\t * @return {string}\n\t */\n\tgetRoutePath(path) {\n\t\tif (this.getIgnoreQueryStringFromRoutePath()) {\n\t\t\tpath = utils.getUrlPathWithoutHashAndSearch(path);\n\t\t\treturn utils.getUrlPathWithoutHashAndSearch(path.substr(this.basePath.length));\n\t\t}\n\n\t\tpath = utils.getUrlPathWithoutHash(path);\n\t\treturn utils.getUrlPathWithoutHash(path.substr(this.basePath.length));\n\t}\n\n\t/**\n\t * Gets the update scroll position value.\n\t * @return {boolean}\n\t */\n\tgetUpdateScrollPosition() {\n\t\treturn this.updateScrollPosition;\n\t}\n\n\t/**\n\t * Handle navigation error.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @param {!Error} error\n\t * @protected\n\t */\n\thandleNavigateError_(path, nextScreen, error) {\n\t\tconsole.log('Navigation error for [' + nextScreen + '] (' + error.stack + ')');\n\t\tthis.emit('navigationError', {\n\t\t\terror,\n\t\t\tnextScreen,\n\t\t\tpath\n\t\t});\n\t\tif (!utils.isCurrentBrowserPath(path)) {\n\t\t\tif (this.isNavigationPending && this.pendingNavigate) {\n\t\t\t\tthis.pendingNavigate.thenAlways(() => this.removeScreen(path), this);\n\t\t\t} else {\n\t\t\t\tthis.removeScreen(path);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if app has routes.\n\t * @return {boolean}\n\t */\n\thasRoutes() {\n\t\treturn this.routes.length > 0;\n\t}\n\n\t/**\n\t * Tests if host is an offsite link.\n\t * @param {!string} host Link host to compare with\n\t * globals.window.location.host.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisLinkSameOrigin_(host) {\n\t\tconst hostUri = new Uri(host);\n\t\tconst locationHostUri = new Uri(globals.window.location.host);\n\n\t\treturn hostUri.getPort() === locationHostUri.getPort() && hostUri.getHostname() === locationHostUri.getHostname();\n\t}\n\n\t/**\n\t * Tests if link element has the same app's base path.\n\t * @param {!string} path Link path containing the querystring part.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisSameBasePath_(path) {\n\t\treturn path.indexOf(this.basePath) === 0;\n\t}\n\n\t/**\n\t * Lock the document scroll in order to avoid the browser native back and\n\t * forward navigation to change the scroll position. In the end of\n\t * navigation lifecycle scroll is repositioned.\n\t * @protected\n\t */\n\tlockHistoryScrollPosition_() {\n\t\tvar state = globals.window.history.state;\n\t\tif (!state) {\n\t\t\treturn;\n\t\t}\n\t\t// Browsers are inconsistent when re-positioning the scroll history on\n\t\t// popstate. At some browsers, history scroll happens before popstate, then\n\t\t// lock the scroll on the last known position as soon as possible after the\n\t\t// current JS execution context and capture the current value. Some others,\n\t\t// history scroll happens after popstate, in this case, we bind an once\n\t\t// scroll event to lock the las known position. Lastly, the previous two\n\t\t// behaviors can happen even on the same browser, hence the race will decide\n\t\t// the winner.\n\t\tvar winner = false;\n\t\tvar switchScrollPositionRace = function() {\n\t\t\tglobals.document.removeEventListener('scroll', switchScrollPositionRace, false);\n\t\t\tif (!winner) {\n\t\t\t\tglobals.window.scrollTo(state.scrollLeft, state.scrollTop);\n\t\t\t\twinner = true;\n\t\t\t}\n\t\t};\n\t\tasync.nextTick(switchScrollPositionRace);\n\t\tglobals.document.addEventListener('scroll', switchScrollPositionRace, false);\n\t}\n\n\t/**\n\t * If supported by the browser, disables native scroll restoration and\n\t * stores current value.\n\t */\n\tmaybeDisableNativeScrollRestoration() {\n\t\tif (this.nativeScrollRestorationSupported) {\n\t\t\tthis.nativeScrollRestoration_ = globals.window.history.scrollRestoration;\n\t\t\tglobals.window.history.scrollRestoration = 'manual';\n\t\t}\n\t}\n\n\t/**\n\t * This method is used to evaluate if is possible to queue received\n\t * dom event to scheduleNavigationQueue and enqueue it.\n\t * @param {string} href Information about the link's href.\n\t * @param {Event} event Dom event that initiated the navigation.\n\t */\n\tmaybeScheduleNavigation_(href, event) {\n\t\tif (this.isNavigationPending && this.navigationStrategy === NavigationStrategy.SCHEDULE_LAST) {\n\t\t\tthis.scheduledNavigationQueue = [object.mixin({\n\t\t\t\thref,\n\t\t\t\tisScheduledNavigation: true\n\t\t\t}, event)];\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Maybe navigate to a path.\n\t * @param {string} href Information about the link's href.\n\t * @param {Event} event Dom event that initiated the navigation.\n\t */\n\tmaybeNavigate_(href, event) {\n\t\tif (!this.canNavigate(href)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isNavigationScheduled = this.maybeScheduleNavigation_(href, event);\n\n\t\tif (isNavigationScheduled) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tvar navigateFailed = false;\n\t\ttry {\n\t\t\tthis.navigate(utils.getUrlPath(href), false, event);\n\t\t} catch (err) {\n\t\t\t// Do not prevent link navigation in case some synchronous error occurs\n\t\t\tnavigateFailed = true;\n\t\t}\n\n\t\tif (!navigateFailed && !event.isScheduledNavigation) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether the onbeforeunload global event handler is overloaded\n\t * by client code. If so, it replaces with a function that halts the normal\n\t * event flow in relation with the client onbeforeunload function.\n\t * This can be in most part used to prematurely terminate navigation to other pages\n\t * according to the given constrait(s).\n\t * @protected\n\t */\n\tmaybeOverloadBeforeUnload_() {\n\t\tif ('function' === typeof window.onbeforeunload) {\n\t\t\twindow._onbeforeunload = window.onbeforeunload;\n\n\t\t\twindow.onbeforeunload = event => {\n\t\t\t\tthis.emit('beforeUnload', event);\n\t\t\t\tif (event && event.defaultPrevented) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// mark the updated handler due unwanted recursion\n\t\t\twindow.onbeforeunload._overloaded = true;\n\t\t}\n\t}\n\n\t/**\n\t * Cancels navigation if nextScreen's beforeActivate lifecycle method\n\t * resolves to true.\n\t * @param {!Screen} nextScreen\n\t * @return {!CancellablePromise}\n\t */\n\tmaybePreventActivate_(nextScreen) {\n\t\treturn CancellablePromise.resolve()\n\t\t\t.then(() => {\n\t\t\t\treturn nextScreen.beforeActivate();\n\t\t\t})\n\t\t\t.then(prevent => {\n\t\t\t\tif (prevent) {\n\t\t\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by next screen'));\n\t\t\t\t\treturn this.pendingNavigate;\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Cancels navigation if activeScreen's beforeDeactivate lifecycle\n\t * method resolves to true.\n\t * @return {!CancellablePromise}\n\t */\n\tmaybePreventDeactivate_() {\n\t\treturn CancellablePromise.resolve()\n\t\t\t.then(() => {\n\t\t\t\tif (this.activeScreen) {\n\t\t\t\t\treturn this.activeScreen.beforeDeactivate();\n\t\t\t\t}\n\t\t\t})\n\t\t\t.then(prevent => {\n\t\t\t\tif (prevent) {\n\t\t\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by active screen'));\n\t\t\t\t\treturn this.pendingNavigate;\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Maybe reposition scroll to hashed anchor.\n\t */\n\tmaybeRepositionScrollToHashedAnchor() {\n\t\tconst hash = globals.window.location.hash;\n\t\tif (hash) {\n\t\t\tlet anchorElement = globals.document.getElementById(hash.substring(1));\n\t\t\tif (anchorElement) {\n\t\t\t\tconst {offsetLeft, offsetTop} = utils.getNodeOffset(anchorElement);\n\t\t\t\tglobals.window.scrollTo(offsetLeft, offsetTop);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * If supported by the browser, restores native scroll restoration to the\n\t * value captured by `maybeDisableNativeScrollRestoration`.\n\t */\n\tmaybeRestoreNativeScrollRestoration() {\n\t\tif (this.nativeScrollRestorationSupported && this.nativeScrollRestoration_) {\n\t\t\tglobals.window.history.scrollRestoration = this.nativeScrollRestoration_;\n\t\t}\n\t}\n\n\t/**\n\t * Maybe restore redirected path hash in case both the current path and\n\t * the given path are the same.\n\t * @param {!string} path Path before navigation.\n\t * @param {!string} redirectPath Path after navigation.\n\t * @param {!string} hash Hash to be added to the path.\n\t * @return {!string} Returns the path with the hash restored.\n\t */\n\tmaybeRestoreRedirectPathHash_(path, redirectPath, hash) {\n\t\tif (redirectPath === utils.getUrlPathWithoutHash(path)) {\n\t\t\treturn redirectPath + hash;\n\t\t}\n\t\treturn redirectPath;\n\t}\n\n\t/**\n\t * Maybe update scroll position in history state to anchor on path.\n\t * @param {!string} path Path containing anchor\n\t */\n\tmaybeUpdateScrollPositionState_() {\n\t\tvar hash = globals.window.location.hash;\n\t\tvar anchorElement = globals.document.getElementById(hash.substring(1));\n\t\tif (anchorElement) {\n\t\t\tconst {offsetLeft, offsetTop} = utils.getNodeOffset(anchorElement);\n\t\t\tthis.saveHistoryCurrentPageScrollPosition_(offsetTop, offsetLeft);\n\t\t}\n\t}\n\n\t/**\n\t * Navigates to the specified path if there is a route handler that matches.\n\t * @param {!string} path Path to navigate containing the base path.\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @param {Event=} event Optional event object that triggered the navigation.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tnavigate(path, opt_replaceHistory, opt_event) {\n\t\tif (!utils.isHtml5HistorySupported()) {\n\t\t\tthrow new Error('HTML5 History is not supported. Senna will not intercept navigation.');\n\t\t}\n\n\t\tif (opt_event) {\n\t\t\tglobals.capturedFormElement = opt_event.capturedFormElement;\n\t\t\tglobals.capturedFormButtonElement = opt_event.capturedFormButtonElement;\n\t\t}\n\n\t\t// When reloading the same path do replaceState instead of pushState to\n\t\t// avoid polluting history with states with the same path.\n\t\tif (path === this.activePath) {\n\t\t\topt_replaceHistory = true;\n\t\t}\n\n\t\tthis.emit('beforeNavigate', {\n\t\t\tevent: opt_event,\n\t\t\tpath: path,\n\t\t\treplaceHistory: !!opt_replaceHistory\n\t\t});\n\n\t\treturn this.pendingNavigate;\n\t}\n\n\t/**\n\t * Befores navigation to a path.\n\t * @param {!Event} event Event facade containing path and\n\t * replaceHistory.\n\t * @protected\n\t */\n\tonBeforeNavigate_(event) {\n\t\tif (globals.capturedFormElement) {\n\t\t\tevent.form = globals.capturedFormElement;\n\t\t}\n\t}\n\n\t/**\n\t * Befores navigation to a path. Runs after external listeners.\n\t * @param {!Event} event Event facade containing path and\n\t * replaceHistory.\n\t * @protected\n\t */\n\tonBeforeNavigateDefault_(event) {\n\t\tif (this.pendingNavigate) {\n\t\t\tif (this.pendingNavigate.path === event.path || this.navigationStrategy === NavigationStrategy.SCHEDULE_LAST) {\n\t\t\t\tconsole.log('Waiting...');\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.emit('beforeUnload', event);\n\n\t\tthis.emit('startNavigate', {\n\t\t\tform: event.form,\n\t\t\tpath: event.path,\n\t\t\treplaceHistory: event.replaceHistory\n\t\t});\n\t}\n\n\t/**\n\t * Custom event handler that executes the original listener that has been\n\t * added by the client code and terminates the navigation accordingly.\n\t * @param {!Event} event original Event facade.\n\t * @protected\n\t */\n\tonBeforeUnloadDefault_(event) {\n\t\tvar func = window._onbeforeunload;\n\t\tif (func && !func._overloaded && func()) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\t/**\n\t * Intercepts document clicks and test link elements in order to decide\n\t * whether Surface app can navigate.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonDocClickDelegate_(event) {\n\t\tif (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.button) {\n\t\t\tconsole.log('Navigate aborted, invalid mouse button or modifier key pressed.');\n\t\t\treturn;\n\t\t}\n\t\tthis.maybeNavigate_(event.delegateTarget.href, event);\n\t}\n\n\t/**\n\t * Intercepts document form submits and test action path in order to decide\n\t * whether Surface app can navigate.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonDocSubmitDelegate_(event) {\n\t\tvar form = event.delegateTarget;\n\t\tif (form.method === 'get') {\n\t\t\tconsole.log('GET method not supported');\n\t\t\treturn;\n\t\t}\n\t\tevent.capturedFormElement = form;\n\t\tconst buttonSelector = 'button:not([type]),button[type=submit],input[type=submit]';\n\t\tif (match(globals.document.activeElement, buttonSelector)) {\n\t\t\tevent.capturedFormButtonElement = globals.document.activeElement;\n\t\t} else {\n\t\t\tevent.capturedFormButtonElement = form.querySelector(buttonSelector);\n\t\t}\n\t\tthis.maybeNavigate_(form.action, event);\n\t}\n\n\t/**\n\t * Listens to the window's load event in order to avoid issues with some browsers\n\t * that trigger popstate calls on the first load. For more information see\n\t * http://stackoverflow.com/questions/6421769/popstate-on-pages-load-in-chrome.\n\t * @protected\n\t */\n\tonLoad_() {\n\t\tthis.skipLoadPopstate = true;\n\t\tsetTimeout(() => {\n\t\t\t// The timeout ensures that popstate events will be unblocked right\n\t\t\t// after the load event occured, but not in the same event-loop cycle.\n\t\t\tthis.skipLoadPopstate = false;\n\t\t}, 0);\n\t\t// Try to reposition scroll to the hashed anchor when page loads.\n\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t}\n\n\t/**\n\t * Handles browser history changes and fires app's navigation if the state\n\t * belows to us. If we detect a popstate and the state is null,\n\t * assume it is navigating to an external page or to a page we don't have\n\t * route, then globals.window.location.reload() is invoked in order to\n\t * reload the content to the current url.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonPopstate_(event) {\n\t\tif (this.skipLoadPopstate) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Do not navigate if the popstate was triggered by a hash change.\n\t\tif (utils.isCurrentBrowserPath(this.browserPathBeforeNavigate)) {\n\t\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t\t\treturn;\n\t\t}\n\n\t\tvar state = event.state;\n\n\t\tif (!state) {\n\t\t\tif (globals.window.location.hash) {\n\t\t\t\t// If senna is on an redirect path and a hash popstate happens\n\t\t\t\t// to a different url, reload the browser. This behavior doesn't\n\t\t\t\t// require senna to route hashed links and is closer to native\n\t\t\t\t// browser behavior.\n\t\t\t\tif (this.redirectPath && !utils.isCurrentBrowserPath(this.redirectPath)) {\n\t\t\t\t\tthis.reloadPage();\n\t\t\t\t}\n\t\t\t\t// Always try to reposition scroll to the hashed anchor when\n\t\t\t\t// hash popstate happens.\n\t\t\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t\t\t} else {\n\t\t\t\tthis.reloadPage();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (state.senna) {\n\t\t\tconsole.log('History navigation to [' + state.path + ']');\n\t\t\tthis.popstateScrollTop = state.scrollTop;\n\t\t\tthis.popstateScrollLeft = state.scrollLeft;\n\t\t\tif (!this.nativeScrollRestorationSupported) {\n\t\t\t\tthis.lockHistoryScrollPosition_();\n\t\t\t}\n\t\t\tthis.once('endNavigate', () => {\n\t\t\t\tif (state.referrer) {\n\t\t\t\t\tutils.setReferrer(state.referrer);\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst uri = new Uri(state.path);\n\t\t\turi.setHostname(globals.window.location.hostname);\n\t\t\turi.setPort(globals.window.location.port);\n\t\t\tconst isNavigationScheduled = this.maybeScheduleNavigation_(uri.toString(), {});\n\t\t\tif (isNavigationScheduled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.navigate(state.path, true);\n\t\t}\n\t}\n\n\t/**\n\t * Listens document scroll changes in order to capture the possible lock\n\t * scroll position for history scrolling.\n\t * @protected\n\t */\n\tonScroll_() {\n\t\tif (this.captureScrollPositionFromScrollEvent) {\n\t\t\tthis.saveHistoryCurrentPageScrollPosition_(globals.window.pageYOffset, globals.window.pageXOffset);\n\t\t}\n\t}\n\n\t/**\n\t * Starts navigation to a path.\n\t * @param {!Event} event Event facade containing path and\n\t * replaceHistory.\n\t * @protected\n\t */\n\tonStartNavigate_(event) {\n\t\tthis.maybeDisableNativeScrollRestoration();\n\t\tthis.captureScrollPositionFromScrollEvent = false;\n\t\taddClasses(globals.document.documentElement, this.loadingCssClass);\n\n\t\tvar endNavigatePayload = {\n\t\t\tform: event.form,\n\t\t\tpath: event.path\n\t\t};\n\n\t\tthis.pendingNavigate = this.doNavigate_(event.path, event.replaceHistory)\n\t\t\t.catch((reason) => {\n\t\t\t\tendNavigatePayload.error = reason;\n\t\t\t\tthrow reason;\n\t\t\t})\n\t\t\t.thenAlways(() => {\n\t\t\t\tif (!this.pendingNavigate && !this.scheduledNavigationQueue.length) {\n\t\t\t\t\tremoveClasses(globals.document.documentElement, this.loadingCssClass);\n\t\t\t\t\tthis.maybeRestoreNativeScrollRestoration();\n\t\t\t\t\tthis.captureScrollPositionFromScrollEvent = true;\n\t\t\t\t}\n\t\t\t\tthis.emit('endNavigate', endNavigatePayload);\n\t\t\t});\n\n\t\tthis.pendingNavigate.path = event.path;\n\t}\n\n\t/**\n\t * Prefetches the specified path if there is a route handler that matches.\n\t * @param {!string} path Path to navigate containing the base path.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tprefetch(path) {\n\t\tvar route = this.findRoute(path);\n\t\tif (!route) {\n\t\t\treturn CancellablePromise.reject(new CancellablePromise.CancellationError('No route for ' + path));\n\t\t}\n\n\t\tconsole.log('Prefetching [' + path + ']');\n\n\t\tvar nextScreen = this.createScreenInstance(path, route);\n\n\t\treturn nextScreen.load(path)\n\t\t\t.then(() => this.screens[path] = nextScreen)\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.handleNavigateError_(path, nextScreen, reason);\n\t\t\t\tthrow reason;\n\t\t\t});\n\t}\n\n\t/**\n\t * Prepares screen flip. Updates history state and surfaces content.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t */\n\tprepareNavigateHistory_(path, nextScreen, opt_replaceHistory) {\n\t\tlet title = nextScreen.getTitle();\n\t\tif (!isString(title)) {\n\t\t\ttitle = this.getDefaultTitle();\n\t\t}\n\t\tlet redirectPath = nextScreen.beforeUpdateHistoryPath(path);\n\t\tconst historyState = {\n\t\t\tform: isDefAndNotNull(globals.capturedFormElement),\n\t\t\tpath,\n\t\t\tredirectPath,\n\t\t\tscrollLeft: 0,\n\t\t\tscrollTop: 0,\n\t\t\tsenna: true\n\t\t};\n\t\tif (opt_replaceHistory) {\n\t\t\thistoryState.scrollTop = this.popstateScrollTop;\n\t\t\thistoryState.scrollLeft = this.popstateScrollLeft;\n\t\t}\n\t\tconst hash = new Uri(path).getHash();\n\t\tredirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash);\n\t\tthis.updateHistory_(title, redirectPath, nextScreen.beforeUpdateHistoryState(historyState), opt_replaceHistory);\n\t\tthis.redirectPath = redirectPath;\n\t}\n\n\t/**\n\t * Prepares screen flip. Updates history state and surfaces content.\n\t * @param {!Screen} nextScreen\n\t * @param {!Object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @param {!Object} params Params extracted from the current path.\n\t */\n\tprepareNavigateSurfaces_(nextScreen, surfaces, params) {\n\t\tObject.keys(surfaces).forEach((id) => {\n\t\t\tvar surfaceContent = nextScreen.getSurfaceContent(id, params);\n\t\t\tsurfaces[id].addContent(nextScreen.getId(), surfaceContent);\n\t\t\tconsole.log('Screen [' + nextScreen.getId() + '] add content to surface ' +\n\t\t\t\t'[' + surfaces[id] + '] [' + (isDefAndNotNull(surfaceContent) ? '...' : 'empty') + ']');\n\t\t});\n\t}\n\n\t/**\n\t * Reloads the page by performing `window.location.reload()`.\n\t */\n\treloadPage() {\n\t\tglobals.window.location.reload();\n\t}\n\n\t/**\n\t * Removes route instance from app routes.\n\t * @param {Route} route\n\t * @return {boolean} True if an element was removed.\n\t */\n\tremoveRoute(route) {\n\t\treturn array.remove(this.routes, route);\n\t}\n\n\t/**\n\t * Removes a screen.\n\t * @param {!string} path Path containing the querystring part.\n\t */\n\tremoveScreen(path) {\n\t\tvar screen = this.screens[path];\n\t\tif (screen) {\n\t\t\tObject.keys(this.surfaces).forEach((surfaceId) => this.surfaces[surfaceId].remove(screen.getId()));\n\t\t\tscreen.dispose();\n\t\t\tdelete this.screens[path];\n\t\t}\n\t}\n\n\t/**\n\t * Saves given scroll position into history state.\n\t * @param {!number} scrollTop Number containing the top scroll position to be saved.\n\t * @param {!number} scrollLeft Number containing the left scroll position to be saved.\n\t */\n\tsaveHistoryCurrentPageScrollPosition_(scrollTop, scrollLeft) {\n\t\tvar state = globals.window.history.state;\n\t\tif (state && state.senna) {\n\t\t\t[state.scrollTop, state.scrollLeft] = [scrollTop, scrollLeft];\n\t\t\tglobals.window.history.replaceState(state, null, null);\n\t\t}\n\t}\n\n\t/**\n\t * Sets allow prevent navigate.\n\t * @param {boolean} allowPreventNavigate\n\t */\n\tsetAllowPreventNavigate(allowPreventNavigate) {\n\t\tthis.allowPreventNavigate = allowPreventNavigate;\n\t}\n\n\t/**\n\t * Sets link base path.\n\t * @param {!string} path\n\t */\n\tsetBasePath(basePath) {\n\t\tthis.basePath = utils.removePathTrailingSlash(basePath);\n\t}\n\n\t/**\n\t * Sets the default page title.\n\t * @param {string} defaultTitle\n\t */\n\tsetDefaultTitle(defaultTitle) {\n\t\tthis.defaultTitle = defaultTitle;\n\t}\n\n\t/**\n\t * Sets the form selector.\n\t * @param {!string} formSelector\n\t */\n\tsetFormSelector(formSelector) {\n\t\tthis.formSelector = formSelector;\n\t\tif (this.formEventHandler_) {\n\t\t\tthis.formEventHandler_.removeListener();\n\t\t}\n\t\tthis.formEventHandler_ = delegate(document, 'submit', this.formSelector, this.onDocSubmitDelegate_.bind(this), this.allowPreventNavigate);\n\t}\n\n\t/**\n\t * Sets if route matching should ignore query string from the route path.\n\t * @param {boolean} ignoreQueryStringFromRoutePath\n\t */\n\tsetIgnoreQueryStringFromRoutePath(ignoreQueryStringFromRoutePath) {\n\t\tthis.ignoreQueryStringFromRoutePath = ignoreQueryStringFromRoutePath;\n\t}\n\n\t/**\n\t * Sets the link selector.\n\t * @param {!string} linkSelector\n\t */\n\tsetLinkSelector(linkSelector) {\n\t\tthis.linkSelector = linkSelector;\n\t\tif (this.linkEventHandler_) {\n\t\t\tthis.linkEventHandler_.removeListener();\n\t\t}\n\t\tthis.linkEventHandler_ = delegate(document, 'click', this.linkSelector, this.onDocClickDelegate_.bind(this), this.allowPreventNavigate);\n\t}\n\n\t/**\n\t * Sets the loading css class.\n\t * @param {!string} loadingCssClass\n\t */\n\tsetLoadingCssClass(loadingCssClass) {\n\t\tthis.loadingCssClass = loadingCssClass;\n\t}\n\n\t/**\n\t * Sets the update scroll position value.\n\t * @param {boolean} updateScrollPosition\n\t */\n\tsetUpdateScrollPosition(updateScrollPosition) {\n\t\tthis.updateScrollPosition = updateScrollPosition;\n\t}\n\n\t/**\n\t * Cancels pending navigate with Cancel pending navigation error.\n\t * @protected\n\t */\n\tstopPendingNavigate_() {\n\t\tif (this.pendingNavigate) {\n\t\t\tthis.pendingNavigate.cancel('Cancel pending navigation');\n\t\t}\n\t\tthis.pendingNavigate = null;\n\t}\n\n\t/**\n\t * Sync document scroll position twice, the first one synchronous and then\n\t * one inside async.nextTick. Relevant to browsers that fires\n\t * scroll restoration asynchronously after popstate.\n\t * @protected\n\t * @return {?CancellablePromise=}\n\t */\n\tsyncScrollPositionSyncThenAsync_() {\n\t\tvar state = globals.window.history.state;\n\t\tif (!state) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar scrollTop = state.scrollTop;\n\t\tvar scrollLeft = state.scrollLeft;\n\n\t\tvar sync = () => {\n\t\t\tif (this.updateScrollPosition) {\n\t\t\t\tglobals.window.scrollTo(scrollLeft, scrollTop);\n\t\t\t}\n\t\t};\n\n\t\treturn new CancellablePromise((resolve) => sync() & async.nextTick(() => sync() & resolve()));\n\t}\n\n\t/**\n\t * Updates or replace browser history.\n\t * @param {?string} title Document title.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!object} state\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @protected\n\t */\n\tupdateHistory_(title, path, state, opt_replaceHistory) {\n\t\tconst referrer = globals.window.location.href;\n\n\t\tif (state) {\n\t\t\tstate.referrer = referrer;\n\t\t}\n\n\t\tif (opt_replaceHistory) {\n\t\t\tglobals.window.history.replaceState(state, title, path);\n\t\t} else {\n\t\t\tglobals.window.history.pushState(state, title, path);\n\t\t}\n\n\t\tutils.setReferrer(referrer);\n\n\t\tlet titleNode = globals.document.querySelector('title');\n\t\tif (titleNode) {\n\t\t\ttitleNode.innerHTML = title;\n\t\t} else {\n\t\t\tglobals.document.title = title;\n\t\t}\n\t}\n\n}\n\nexport default App;\n","'use strict';\n\nimport { isDef, isDefAndNotNull } from 'metal';\nimport Uri from 'metal-uri';\nimport { CancellablePromise as Promise } from 'metal-promise';\n\nclass Ajax {\n\n\t/**\n\t * XmlHttpRequest's getAllResponseHeaders() method returns a string of\n\t * response headers according to the format described on the spec:\n\t * {@link http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method}.\n\t * This method parses that string into a user-friendly name/value pair\n\t * object.\n\t * @param {string} allHeaders All headers as string.\n\t * @return {!Array.>}\n\t */\n\tstatic parseResponseHeaders(allHeaders) {\n\t\tvar headers = [];\n\t\tif (!allHeaders) {\n\t\t\treturn headers;\n\t\t}\n\t\tvar pairs = allHeaders.split('\\u000d\\u000a');\n\t\tfor (var i = 0; i < pairs.length; i++) {\n\t\t\tvar index = pairs[i].indexOf('\\u003a\\u0020');\n\t\t\tif (index > 0) {\n\t\t\t\tvar name = pairs[i].substring(0, index);\n\t\t\t\tvar value = pairs[i].substring(index + 2);\n\t\t\t\theaders.push({\n\t\t\t\t\tname: name,\n\t\t\t\t\tvalue: value\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn headers;\n\t}\n\n\t/**\n\t * Requests the url using XMLHttpRequest.\n\t * @param {!string} url\n\t * @param {!string} method\n\t * @param {?string} body\n\t * @param {MultiMap=} opt_headers\n\t * @param {MultiMap=} opt_params\n\t * @param {number=} opt_timeout\n\t * @param {boolean=} opt_sync\n\t * @param {boolean=} opt_withCredentials\n\t * @return {Promise} Deferred ajax request.\n\t * @protected\n\t */\n\tstatic request(url, method, body, opt_headers, opt_params, opt_timeout, opt_sync, opt_withCredentials) {\n\t\turl = url || '';\n\t\tmethod = method || 'GET';\n\n\t\tvar request = new XMLHttpRequest();\n\t\tvar previousReadyState = 0;\n\n\t\tvar promise = new Promise(function(resolve, reject) {\n\t\t\trequest.onload = function() {\n\t\t\t\tif (request.aborted) {\n\t\t\t\t\trequest.onerror();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tresolve(request);\n\t\t\t};\n\t\t\trequest.onreadystatechange = function() {\n\t\t\t\tif (previousReadyState && previousReadyState < 3 && 4 === request.readyState) {\n\t\t\t\t\trequest.terminatedPrematurely = true;\n\t\t\t\t}\n\t\t\t\tpreviousReadyState = request.readyState;\n\t\t\t};\n\t\t\trequest.onerror = function() {\n\t\t\t\tvar message = 'Request error';\n\t\t\t\tif (request.terminatedPrematurely) {\n\t\t\t\t\tmessage = 'Request terminated prematurely';\n\t\t\t\t} \n\t\t\t\tvar error = new Error(message);\n\t\t\t\terror.request = request;\n\t\t\t\treject(error);\n\t\t\t};\n\t\t}).thenCatch(function(reason) {\n\t\t\trequest.abort();\n\t\t\tthrow reason;\n\t\t}).thenAlways(function() {\n\t\t\tclearTimeout(timeout);\n\t\t});\n\n\t\turl = new Uri(url);\n\n\t\tif (opt_params) {\n\t\t\turl.addParametersFromMultiMap(opt_params).toString();\n\t\t}\n\n\t\turl = url.toString();\n\n\t\trequest.open(method, url, !opt_sync);\n\n\t\tif (opt_withCredentials) {\n\t\t\trequest.withCredentials = true;\n\t\t}\n\n\t\tif (opt_headers) {\n\t\t\topt_headers.names().forEach(function(name) {\n\t\t\t\trequest.setRequestHeader(name, opt_headers.getAll(name).join(', '));\n\t\t\t});\n\t\t}\n\n\t\trequest.send(isDef(body) ? body : null);\n\n\t\tif (isDefAndNotNull(opt_timeout)) {\n\t\t\tvar timeout = setTimeout(function() {\n\t\t\t\tpromise.cancel('Request timeout');\n\t\t\t}, opt_timeout);\n\t\t}\n\n\t\treturn promise;\n\t}\n\n}\n\nexport default Ajax;\n","'use strict';\n\n/**\n * Holds value error messages.\n * @const\n */\nclass errors {\n}\n\n/**\n * Invalid status error message.\n * @type {string}\n * @static\n */\nerrors.INVALID_STATUS = 'Invalid status code';\n\n/**\n * Request error message.\n * @type {string}\n * @static\n */\nerrors.REQUEST_ERROR = 'Request error';\n\n/**\n * Request timeout error message.\n * @type {string}\n * @static\n */\nerrors.REQUEST_TIMEOUT = 'Request timeout';\n\n/**\n * Request is blocked by CORS issue message.\n * @type {string}\n * @static\n */\nerrors.REQUEST_PREMATURE_TERMINATION = 'Request terminated prematurely';\n\nexport default errors;\n","'use strict';\n\nimport {isServerSide} from 'metal';\n\n/**\n * Metal.js browser user agent detection. It's extremely recommended the usage\n * of feature checking over browser user agent sniffing. Unfortunately, in some\n * situations feature checking can be slow or even impossible, therefore use\n * this utility with caution.\n * @see User agent strings.\n */\nclass UA {\n\t/**\n\t * Gets the native userAgent string from navigator if it exists. If\n\t * navigator or navigator.userAgent string is missing, returns an empty\n\t * string.\n\t * @return {string}\n\t * @private\n\t * @static\n\t */\n\tstatic getNativeUserAgent() {\n\t\tlet navigator = UA.globals.window && UA.globals.window.navigator;\n\t\tif (navigator) {\n\t\t\tlet userAgent = navigator.userAgent;\n\t\t\tif (userAgent) {\n\t\t\t\treturn userAgent;\n\t\t\t}\n\t\t}\n\t\treturn '';\n\t}\n\n\t/**\n\t * Gets the native platform string from navigator if it exists. If\n\t * navigator or navigator.platform string is missing, returns an empty\n\t * string.\n\t * @return {string}\n\t * @private\n\t * @static\n\t */\n\tstatic getNativePlatform() {\n\t\tlet navigator = UA.globals.window && UA.globals.window.navigator;\n\t\tif (navigator) {\n\t\t\tlet platform = navigator.platform;\n\t\t\tif (platform) {\n\t\t\t\treturn platform;\n\t\t\t}\n\t\t}\n\t\treturn '';\n\t}\n\n\t/**\n\t * Whether the platform contains the given string, ignoring case.\n\t * @param {string} str\n\t * @return {boolean}\n\t * @private\n\t * @static\n\t */\n\tstatic matchPlatform(str) {\n\t\treturn UA.platform.indexOf(str) !== -1;\n\t}\n\n\t/**\n\t * Whether the user agent contains the given string, ignoring case.\n\t * @param {string} str\n\t * @return {boolean}\n\t * @private\n\t * @static\n\t */\n\tstatic matchUserAgent(str) {\n\t\treturn UA.userAgent.indexOf(str) !== -1;\n\t}\n\n\t/**\n\t * Tests the user agent.\n\t * @param {string} userAgent The user agent string.\n\t * @param {string} platform\n\t * @static\n\t */\n\tstatic testUserAgent(userAgent = '', platform = '') {\n\t\t/**\n\t\t * Holds the user agent value extracted from browser native user agent.\n\t\t * @type {string}\n\t\t * @static\n\t\t */\n\t\tUA.userAgent = userAgent;\n\n\t\t/**\n\t\t * Holds the platform value extracted from browser native platform.\n\t\t * @type {string}\n\t\t * @static\n\t\t */\n\t\tUA.platform = platform;\n\n\t\t/**\n\t\t * Whether the user's OS is Mac.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isMac = UA.matchPlatform('Mac');\n\n\t\t/**\n\t\t * Whether the user's OS is Win.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isWin = UA.matchPlatform('Win');\n\n\t\t/**\n\t\t * Whether the user's browser is Opera.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isOpera = UA.matchUserAgent('Opera') || UA.matchUserAgent('OPR');\n\n\t\t/**\n\t\t * Whether the user's browser is IE.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isIe = UA.matchUserAgent('Trident') || UA.matchUserAgent('MSIE');\n\n\t\t/**\n\t\t * Whether the user's browser is Edge.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isEdge = UA.matchUserAgent('Edge');\n\n\t\t/**\n\t\t * Whether the user's browser is IE or Edge.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isIeOrEdge = UA.isIe || UA.isEdge;\n\n\t\t/**\n\t\t * Whether the user's browser is Chrome.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isChrome =\n\t\t\t(UA.matchUserAgent('Chrome') || UA.matchUserAgent('CriOS')) &&\n\t\t\t!UA.isOpera &&\n\t\t\t!UA.isEdge;\n\n\t\t/**\n\t\t * Whether the user's browser is Safari.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isSafari =\n\t\t\tUA.matchUserAgent('Safari') &&\n\t\t\t!(UA.isChrome || UA.isOpera || UA.isEdge);\n\n\t\t/**\n\t\t * Whether the user's browser is Firefox.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isFirefox = UA.matchUserAgent('Firefox');\n\t}\n}\n\n/**\n * Exposes global references.\n * @type {object}\n * @static\n */\nObject.defineProperty(UA, 'globals', {\n\twritable: true,\n\tvalue: {\n\t\twindow: isServerSide() ? null : window,\n\t},\n});\n\nUA.testUserAgent(UA.getNativeUserAgent(), UA.getNativePlatform());\n\nexport default UA;\n","'use strict';\n\nimport { isDefAndNotNull } from 'metal';\nimport Ajax from 'metal-ajax';\nimport { MultiMap } from 'metal-structs';\nimport CancellablePromise from 'metal-promise';\nimport errors from '../errors/errors';\nimport utils from '../utils/utils';\nimport globals from '../globals/globals';\nimport Screen from './Screen';\nimport Uri from 'metal-uri';\nimport UA from 'metal-useragent';\n\nclass RequestScreen extends Screen {\n\n\t/**\n\t * Request screen abstract class to perform io operations on descendant\n\t * screens.\n\t * @constructor\n\t * @extends {Screen}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * @inheritDoc\n\t\t * @default true\n\t\t */\n\t\tthis.cacheable = true;\n\n\t\t/**\n\t\t * Holds default http headers to set on request.\n\t\t * @type {?Object=}\n\t\t * @default {\n\t\t * 'X-PJAX': 'true',\n\t\t * 'X-Requested-With': 'XMLHttpRequest'\n\t\t * }\n\t\t * @protected\n\t\t */\n\t\tthis.httpHeaders = {\n\t\t\t'X-PJAX': 'true',\n\t\t\t'X-Requested-With': 'XMLHttpRequest'\n\t\t};\n\n\t\t/**\n\t\t * Holds default http method to perform the request.\n\t\t * @type {!string}\n\t\t * @default RequestScreen.GET\n\t\t * @protected\n\t\t */\n\t\tthis.httpMethod = RequestScreen.GET;\n\n\t\t/**\n\t\t * Holds the XHR object responsible for the request.\n\t\t * @type {XMLHttpRequest}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.request = null;\n\n\t\t/**\n\t\t * Holds the request timeout in milliseconds.\n\t\t * @type {!number}\n\t\t * @default 30000\n\t\t * @protected\n\t\t */\n\t\tthis.timeout = 30000;\n\t}\n\n\t/**\n\t * Asserts that response status code is valid.\n\t * @param {number} status\n\t * @protected\n\t */\n\tassertValidResponseStatusCode(status) {\n\t\tif (!this.isValidResponseStatusCode(status)) {\n\t\t\tvar error = new Error(errors.INVALID_STATUS);\n\t\t\terror.invalidStatus = true;\n\t\t\terror.statusCode = status;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tbeforeUpdateHistoryPath(path) {\n\t\tvar redirectPath = this.getRequestPath();\n\t\tif (redirectPath && redirectPath !== path) {\n\t\t\treturn redirectPath;\n\t\t}\n\t\treturn path;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tbeforeUpdateHistoryState(state) {\n\t\t// If state is ours and navigate to post-without-redirect-get set\n\t\t// history state to null, that way Senna will reload the page on\n\t\t// popstate since it cannot predict post data.\n\t\tif (state.senna && state.form && state.redirectPath === state.path) {\n\t\t\treturn null;\n\t\t}\n\t\treturn state;\n\t}\n\n\t/**\n\t * Formats load path before invoking ajax call.\n\t * @param {string} path\n\t * @return {string} Formatted path;\n\t * @protected\n\t */\n\tformatLoadPath(path) {\n\t\tvar uri = new Uri(path);\n\n\t\turi.setHostname(globals.window.location.hostname);\n\t\turi.setProtocol(globals.window.location.protocol);\n\n\t\tif (globals.window.location.port) {\n\t\t\turi.setPort(globals.window.location.port);\n\t\t}\n\n\t\tif (UA.isIeOrEdge && this.httpMethod === RequestScreen.GET) {\n\t\t\treturn uri.makeUnique().toString();\n\t\t}\n\n\t\treturn uri.toString();\n\t}\n\n\t/**\n\t * Gets the http headers.\n\t * @return {?Object=}\n\t */\n\tgetHttpHeaders() {\n\t\treturn this.httpHeaders;\n\t}\n\n\t/**\n\t * Gets the http method.\n\t * @return {!string}\n\t */\n\tgetHttpMethod() {\n\t\treturn this.httpMethod;\n\t}\n\n\t/**\n\t * Gets request path.\n\t * @return {string=}\n\t */\n\tgetRequestPath() {\n\t\tvar request = this.getRequest();\n\t\tif (request) {\n\t\t\tvar requestPath = request.requestPath;\n\t\t\tvar responseUrl = this.maybeExtractResponseUrlFromRequest(request);\n\t\t\tif (responseUrl) {\n\t\t\t\trequestPath = responseUrl;\n\t\t\t}\n\t\t\tif (UA.isIeOrEdge && this.httpMethod === RequestScreen.GET) {\n\t\t\t\trequestPath = new Uri(requestPath).removeUnique().toString();\n\t\t\t}\n\t\t\treturn utils.getUrlPath(requestPath);\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Gets the request object.\n\t * @return {?Object}\n\t */\n\tgetRequest() {\n\t\treturn this.request;\n\t}\n\n\t/**\n\t * Gets the request timeout.\n\t * @return {!number}\n\t */\n\tgetTimeout() {\n\t\treturn this.timeout;\n\t}\n\n\t/**\n\t * Checks if response succeeded. Any status code 2xx or 3xx is considered\n\t * valid.\n\t * @param {number} statusCode\n\t */\n\tisValidResponseStatusCode(statusCode) {\n\t\treturn statusCode >= 200 && statusCode <= 399;\n\t}\n\n /**\n * Returns the form data\n * This method can be extended in order to have a custom implementation of the form params\n * @param {!Element} formElement\n * @param {!Element} submittedButtonElement\n * @return {!FormData}\n */\n\tgetFormData(formElement, submittedButtonElement) {\n let formData = new FormData(formElement);\n this.maybeAppendSubmitButtonValue_(formData, submittedButtonElement);\n return formData;\n }\n\n\t/**\n\t * @inheritDoc\n\t */\n\tload(path) {\n\t\tconst cache = this.getCache();\n\t\tif (isDefAndNotNull(cache)) {\n\t\t\treturn CancellablePromise.resolve(cache);\n\t\t}\n\t\tlet body = null;\n\t\tlet httpMethod = this.httpMethod;\n\t\tconst headers = new MultiMap();\n\t\tObject.keys(this.httpHeaders).forEach(header => headers.add(header, this.httpHeaders[header]));\n\t\tif (globals.capturedFormElement) {\n\t\t\tthis.addSafariXHRPolyfill();\n\t\t\tbody = this.getFormData(globals.capturedFormElement, globals.capturedFormButtonElement);\n\t\t\thttpMethod = RequestScreen.POST;\n\t\t\tif (UA.isIeOrEdge) {\n\t\t\t\theaders.add('If-None-Match', '\"0\"');\n\t\t\t}\n\t\t}\n\t\tconst requestPath = this.formatLoadPath(path);\n\t\treturn Ajax\n\t\t\t.request(requestPath, httpMethod, body, headers, null, this.timeout)\n\t\t\t.then(xhr => {\n\t\t\t\tthis.removeSafariXHRPolyfill();\n\t\t\t\tthis.setRequest(xhr);\n\t\t\t\tthis.assertValidResponseStatusCode(xhr.status);\n\t\t\t\tif (httpMethod === RequestScreen.GET && this.isCacheable()) {\n\t\t\t\t\tthis.addCache(xhr.responseText);\n\t\t\t\t}\n\t\t\t\txhr.requestPath = requestPath;\n\t\t\t\treturn xhr.responseText;\n\t\t\t})\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.removeSafariXHRPolyfill();\n\t\t\t\tswitch (reason.message) {\n\t\t\t\t\tcase errors.REQUEST_TIMEOUT:\n\t\t\t\t\t\treason.timeout = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase errors.REQUEST_ERROR:\n\t\t\t\t\t\treason.requestError = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase errors.REQUEST_PREMATURE_TERMINATION:\n\t\t\t\t\t\treason.requestError = true;\n\t\t\t\t\t\treason.requestPrematureTermination = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthrow reason;\n\t\t\t});\n\t}\n\n\t/**\n\t * Adds aditional data to the body of the request in case a submit button\n\t * is captured during form submission.\n\t * @param {!FormData} body The FormData containing the request body.\n * @param {!Element} submittedButtonElement\n * @protected\n\t */\n\tmaybeAppendSubmitButtonValue_(formData, submittedButtonElement) {\n\t\tif (submittedButtonElement && submittedButtonElement.name) {\n formData.append(submittedButtonElement.name, submittedButtonElement.value);\n\t\t}\n\t}\n\n\t/**\n\t * The following method tries to extract the response url value by checking\n\t * the custom response header 'X-Request-URL' if proper value is not present\n\t * in XMLHttpRequest. The value of responseURL will be the final URL\n\t * obtained after any redirects. Internet Explorer, Edge and Safari <= 7\n\t * does not yet support the feature. For more information see:\n\t * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseURL\n\t * https://xhr.spec.whatwg.org/#the-responseurl-attribute\n\t * @param {XMLHttpRequest} request\n\t * @return {?string} Response url best match.\n\t */\n\tmaybeExtractResponseUrlFromRequest(request) {\n\t\tvar responseUrl = request.responseURL;\n\t\tif (responseUrl) {\n\t\t\treturn responseUrl;\n\t\t}\n\t\treturn request.getResponseHeader(RequestScreen.X_REQUEST_URL_HEADER);\n\t}\n\n\t/**\n\t * This function set attribute data-safari-temp-disabled to \n\t * true and set disable attribute of an input type=\"file\" tag\n\t * is used as a polyfill for iOS 11.3 Safari / macOS Safari 11.1 \n\t * empty XHR bug.\n\t * https://github.com/rails/rails/issues/32440\n\t * https://bugs.webkit.org/show_bug.cgi?id=184490\n\t */\n\taddSafariXHRPolyfill() {\n\t\tif (globals.capturedFormElement && UA.isSafari) {\n\t\t\tlet inputs = globals.capturedFormElement.querySelectorAll('input[type=\"file\"]:not([disabled])');\n\t\t\tfor (let index = 0; index < inputs.length; index++) {\n\t\t\t\tlet input = inputs[index];\n\t\t\t\tif (input.files.length > 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tinput.setAttribute('data-safari-temp-disabled', 'true');\n\t\t\t\tinput.setAttribute('disabled', '');\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * This function remove attribute data-safari-temp-disabled and disable attribute\n\t * of an input type=\"file\" tag is used as a polyfill for iOS 11.3 Safari / macOS Safari 11.1\n\t * empty XHR bug.\n\t * https://github.com/rails/rails/issues/32440\n\t * https://bugs.webkit.org/show_bug.cgi?id=184490\n\t */\n\tremoveSafariXHRPolyfill() {\n\t\tif (globals.capturedFormElement && UA.isSafari) {\n\t\t\tlet inputs = globals.capturedFormElement.querySelectorAll('input[type=\"file\"][data-safari-temp-disabled]');\n\t\t\tfor (let index = 0; index < inputs.length; index++) {\n\t\t\t\tconst input = inputs[index];\n\t\t\t\tinput.removeAttribute('data-safari-temp-disabled');\n\t\t\t\tinput.removeAttribute('disabled');\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets the http headers.\n\t * @param {?Object=} httpHeaders\n\t */\n\tsetHttpHeaders(httpHeaders) {\n\t\tthis.httpHeaders = httpHeaders;\n\t}\n\n\t/**\n\t * Sets the http method.\n\t * @param {!string} httpMethod\n\t */\n\tsetHttpMethod(httpMethod) {\n\t\tthis.httpMethod = httpMethod.toLowerCase();\n\t}\n\n\t/**\n\t * Sets the request object.\n\t * @param {?Object} request\n\t */\n\tsetRequest(request) {\n\t\tthis.request = request;\n\t}\n\n\t/**\n\t * Sets the request timeout in milliseconds.\n\t * @param {!number} timeout\n\t */\n\tsetTimeout(timeout) {\n\t\tthis.timeout = timeout;\n\t}\n\n}\n\n/**\n * Holds value for method get.\n * @type {string}\n * @default 'get'\n * @static\n */\nRequestScreen.GET = 'get';\n\n/**\n * Holds value for method post.\n * @type {string}\n * @default 'post'\n * @static\n */\nRequestScreen.POST = 'post';\n\n/**\n * Fallback http header to retrieve response request url.\n * @type {string}\n * @default 'X-Request-URL'\n * @static\n */\nRequestScreen.X_REQUEST_URL_HEADER = 'X-Request-URL';\n\nexport default RequestScreen;\n","'use strict';\n\nimport { getUid } from 'metal';\nimport { buildFragment, globalEval, globalEvalStyles, match } from 'metal-dom';\nimport CancellablePromise from 'metal-promise';\nimport globals from '../globals/globals';\nimport RequestScreen from './RequestScreen';\nimport Surface from '../surface/Surface';\nimport UA from 'metal-useragent';\nimport Uri from 'metal-uri';\nimport utils from '../utils/utils';\n\nclass HtmlScreen extends RequestScreen {\n\n\t/**\n\t * Screen class that perform a request and extracts surface contents from\n\t * the response content.\n\t * @constructor\n\t * @extends {RequestScreen}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the meta selector. Relevant to extract meta tags\n\t\t * elements from request fragments to use as the screen.\n\t\t * @type {!string}\n\t\t * @default meta\n\t\t * @protected\n\t\t */\n\t\tthis.metaTagsSelector = 'meta';\n\n\t\t/**\n\t\t * Holds the title selector. Relevant to extract the </code>\n\t\t * element from request fragments to use as the screen title.\n\t\t * @type {!string}\n\t\t * @default title\n\t\t * @protected\n\t\t */\n\t\tthis.titleSelector = 'title';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tactivate() {\n\t\tsuper.activate();\n\t\tthis.releaseVirtualDocument();\n\t\tthis.pendingStyles = null;\n\t}\n\n\t/**\n\t * Allocates virtual document for content. After allocated virtual document\n\t * can be accessed by <code>this.virtualDocument</code>.\n\t * @param {!string} htmlString\n\t */\n\tallocateVirtualDocumentForContent(htmlString) {\n\t\tif (!this.virtualDocument) {\n\t\t\tthis.virtualDocument = globals.document.createElement('html');\n\t\t}\n\n\t\tthis.copyNodeAttributesFromContent_(htmlString, this.virtualDocument);\n\n\t\tthis.virtualDocument.innerHTML = htmlString;\n\t}\n\n\t/**\n\t * Customizes logic to append styles into document. Relevant to when\n\t * tracking a style by id make sure to re-positions the new style in the\n\t * same dom order.\n\t * @param {Element} newStyle\n\t */\n\tappendStyleIntoDocument_(newStyle) {\n\t\tvar isTemporaryStyle = match(newStyle, HtmlScreen.selectors.stylesTemporary);\n\t\tif (isTemporaryStyle) {\n\t\t\tthis.pendingStyles.push(newStyle);\n\t\t}\n\t\tif (newStyle.id) {\n\t\t\tvar styleInDoc = globals.document.getElementById(newStyle.id);\n\t\t\tif (styleInDoc) {\n\t\t\t\tstyleInDoc.parentNode.insertBefore(newStyle, styleInDoc.nextSibling);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tglobals.document.head.appendChild(newStyle);\n\t}\n\n\t/**\n\t * If body is used as surface forces the requested documents to have same id\n\t * of the initial page.\n\t */\n\tassertSameBodyIdInVirtualDocument() {\n\t\tvar bodySurface = this.virtualDocument.querySelector('body');\n\t\tif (!globals.document.body.id) {\n\t\t\tglobals.document.body.id = 'senna_surface_' + getUid();\n\t\t}\n\t\tif (bodySurface) {\n\t\t\tbodySurface.id = globals.document.body.id;\n\t\t}\n\t}\n\n\t/**\n\t * Copies attributes from the <html> tag of content to the given node.\n\t */\n\tcopyNodeAttributesFromContent_(content, node) {\n\t\tcontent = content.replace(/[<]\\s*html/ig, '<senna');\n\t\tcontent = content.replace(/\\/html\\s*\\>/ig, '/senna>');\n\t\tlet placeholder;\n\t\tif (UA.isIe) {\n\t\t\tconst tempNode = globals.document.createRange().createContextualFragment(content);\n\t\t\tplaceholder = tempNode.querySelector('senna');\n\t\t} else {\n\t\t\tnode.innerHTML = content;\n\t\t\tplaceholder = node.querySelector('senna');\n\t\t}\n\n\t\tif (placeholder) {\n\t\t\tutils.clearNodeAttributes(node);\n\t\t\tutils.copyNodeAttributes(placeholder, node);\n\t\t}\n\t}\n\n\t/**\n\t * @Override\n\t */\n\tdisposeInternal() {\n\t\tthis.disposePendingStyles();\n\t\tsuper.disposeInternal();\n\t}\n\n\t/**\n\t * Disposes pending styles if screen get disposed prior to its loading.\n\t */\n\tdisposePendingStyles() {\n\t\tif (this.pendingStyles) {\n\t\t\tutils.removeElementsFromDocument(this.pendingStyles);\n\t\t}\n\t}\n\n\t/**\n\t * @Override\n\t */\n\tevaluateScripts(surfaces) {\n\t\tvar evaluateTrackedScripts = this.evaluateTrackedResources_(\n\t\t\tglobalEval.runScriptsInElement, HtmlScreen.selectors.scripts,\n\t\t\tHtmlScreen.selectors.scriptsTemporary, HtmlScreen.selectors.scriptsPermanent);\n\n\t\treturn evaluateTrackedScripts.then(() => super.evaluateScripts(surfaces));\n\t}\n\n\t/**\n\t * @Override\n\t */\n\tevaluateStyles(surfaces) {\n\t\tthis.pendingStyles = [];\n\t\tvar evaluateTrackedStyles = this.evaluateTrackedResources_(\n\t\t\tglobalEvalStyles.runStylesInElement, HtmlScreen.selectors.styles,\n\t\t\tHtmlScreen.selectors.stylesTemporary, HtmlScreen.selectors.stylesPermanent,\n\t\t\tthis.appendStyleIntoDocument_.bind(this));\n\n\t\treturn evaluateTrackedStyles.then(() => super.evaluateStyles(surfaces));\n\t}\n\n\t/**\n\t * Allows a screen to evaluate the favicon style before the screen becomes visible.\n\t * @return {CancellablePromise}\n\t */\n\tevaluateFavicon_() {\n\t\tconst resourcesInVirtual = this.virtualQuerySelectorAll_(HtmlScreen.selectors.favicon);\n\t\tconst resourcesInDocument = this.querySelectorAll_(HtmlScreen.selectors.favicon);\n\n\t\treturn new CancellablePromise((resolve) => {\n\t\t\tutils.removeElementsFromDocument(resourcesInDocument);\n\t\t\tthis.runFaviconInElement_(resourcesInVirtual).then(() => resolve());\n\t\t});\n\t}\n\n\t/**\n\t * Evaluates tracked resources inside incoming fragment and remove existing\n\t * temporary resources.\n\t * @param {?function()} appendFn Function to append the node into document.\n\t * @param {!string} selector Selector used to find resources to track.\n\t * @param {!string} selectorTemporary Selector used to find temporary\n\t * resources to track.\n\t * @param {!string} selectorPermanent Selector used to find permanent\n\t * resources to track.\n\t * @param {!function} opt_appendResourceFn Optional function used to\n\t * evaluate fragment containing resources.\n\t * @return {CancellablePromise} Deferred that waits resources evaluation to\n\t * complete.\n\t * @private\n\t */\n\tevaluateTrackedResources_(evaluatorFn, selector, selectorTemporary, selectorPermanent, opt_appendResourceFn) {\n\t\tvar tracked = this.virtualQuerySelectorAll_(selector);\n\t\tvar temporariesInDoc = this.querySelectorAll_(selectorTemporary);\n\t\tvar permanentsInDoc = this.querySelectorAll_(selectorPermanent);\n\n\t\t// Adds permanent resources in document to cache.\n\t\tpermanentsInDoc.forEach((resource) => {\n\t\t\tvar resourceKey = this.getResourceKey_(resource);\n\t\t\tif (resourceKey) {\n\t\t\t\tHtmlScreen.permanentResourcesInDoc[resourceKey] = true;\n\t\t\t}\n\t\t});\n\n\t\tvar frag = buildFragment();\n\t\ttracked.forEach((resource) => {\n\t\t\tvar resourceKey = this.getResourceKey_(resource);\n\t\t\t// Do not load permanent resources if already in document.\n\t\t\tif (!HtmlScreen.permanentResourcesInDoc[resourceKey]) {\n\t\t\t\tfrag.appendChild(resource);\n\t\t\t}\n\t\t\t// If resource has key and is permanent add to cache.\n\t\t\tif (resourceKey && match(resource, selectorPermanent)) {\n\t\t\t\tHtmlScreen.permanentResourcesInDoc[resourceKey] = true;\n\t\t\t}\n\t\t});\n\n\t\treturn new CancellablePromise((resolve) => {\n\t\t\tevaluatorFn(frag, () => {\n\t\t\t\tutils.removeElementsFromDocument(temporariesInDoc);\n\t\t\t\tresolve();\n\t\t\t}, opt_appendResourceFn);\n\t\t});\n\t}\n\n\t/**\n\t * @Override\n\t */\n\tflip(surfaces) {\n\t\treturn super.flip(surfaces).then(() => {\n\t\t\tutils.clearNodeAttributes(globals.document.documentElement);\n\t\t\tutils.copyNodeAttributes(this.virtualDocument, globals.document.documentElement);\n\t\t\tthis.evaluateFavicon_();\n\t\t\tthis.updateMetaTags_();\n\t\t});\n\t}\n\n\tupdateMetaTags_() {\n\t\tconst currentMetaNodes = this.querySelectorAll_('meta');\n\t\tconst metasFromVirtualDocument = this.metas;\n\t\tif (currentMetaNodes) {\n\t\t\tutils.removeElementsFromDocument(currentMetaNodes);\n\t\t\tif (metasFromVirtualDocument) {\n\t\t\t\tmetasFromVirtualDocument.forEach((meta) => globals.document.head.appendChild(meta));\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Extracts a key to identify the resource based on its attributes.\n\t * @param {Element} resource\n\t * @return {string} Extracted key based on resource attributes in order of\n\t * preference: id, href, src.\n\t */\n\tgetResourceKey_(resource) {\n\t\treturn resource.id || resource.href || resource.src || '';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tgetSurfaceContent(surfaceId) {\n\t\tvar surface = this.virtualDocument.querySelector('#' + surfaceId);\n\t\tif (surface) {\n\t\t\tvar defaultChild = surface.querySelector('#' + surfaceId + '-' + Surface.DEFAULT);\n\t\t\tif (defaultChild) {\n\t\t\t\treturn defaultChild.innerHTML;\n\t\t\t}\n\t\t\treturn surface.innerHTML; // If default content not found, use surface content\n\t\t}\n\t}\n\n\t/**\n\t * Gets the title selector.\n\t * @return {!string}\n\t */\n\tgetTitleSelector() {\n\t\treturn this.titleSelector;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tload(path) {\n\t\treturn super.load(path)\n\t\t\t.then(content => {\n\t\t\t\tthis.allocateVirtualDocumentForContent(content);\n\t\t\t\tthis.resolveTitleFromVirtualDocument();\n\t\t\t\tthis.resolveMetaTagsFromVirtualDocument();\n\t\t\t\tthis.assertSameBodyIdInVirtualDocument();\n\t\t\t\tif (UA.isIe) {\n\t\t\t\t\tthis.makeTemporaryStylesHrefsUnique_();\n\t\t\t\t}\n\t\t\t\treturn content;\n\t\t\t});\n\t}\n\n\t/**\n\t * Queries temporary styles from virtual document, and makes them unique.\n\t * This is necessary for caching and load event firing issues specific to\n\t * IE11. https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7940171/\n\t */\n\tmakeTemporaryStylesHrefsUnique_() {\n\t\tvar temporariesInDoc = this.virtualQuerySelectorAll_(HtmlScreen.selectors.stylesTemporary);\n\t\ttemporariesInDoc.forEach((style) => this.replaceStyleAndMakeUnique_(style));\n\t}\n\n\t/**\n\t * Creates a new element from given, copies attributes, mutates href to be\n\t * unique to prevent caching and more than one load/error event from firing.\n\t */\n\treplaceStyleAndMakeUnique_(style) {\n\t\tif (style.href) {\n\t\t\tvar newStyle = globals.document.createElement(style.tagName);\n\t\t\tstyle.href = new Uri(style.href).makeUnique().toString();\n\t\t\tutils.copyNodeAttributes(style, newStyle);\n\t\t\tstyle.parentNode.replaceChild(newStyle, style);\n\t\t\tstyle.disabled = true;\n\t\t}\n\t}\n\n\t/**\n\t * Adds the favicon elements to the document.\n\t * @param {!Array<Element>} elements\n\t * @private\n\t * @return {CancellablePromise}\n\t */\n\trunFaviconInElement_(elements) {\n\t\treturn new CancellablePromise((resolve) => {\n\t\t\telements.forEach((element) => document.head.appendChild(\n\t\t\t\tUA.isIe ? element : utils.setElementWithRandomHref(element)\n\t\t\t));\n\t\t\tresolve();\n\t\t});\n\t}\n\n\t/**\n\t * Queries elements from virtual document and returns an array of elements.\n\t * @param {!string} selector\n\t * @return {array.<Element>}\n\t */\n\tvirtualQuerySelectorAll_(selector) {\n\t\treturn Array.prototype.slice.call(this.virtualDocument.querySelectorAll(selector));\n\t}\n\n\t/**\n\t * Queries elements from document and returns an array of elements.\n\t * @param {!string} selector\n\t * @return {array.<Element>}\n\t */\n\tquerySelectorAll_(selector) {\n\t\treturn Array.prototype.slice.call(globals.document.querySelectorAll(selector));\n\t}\n\n\t/**\n\t * Releases virtual document allocated for content.\n\t */\n\treleaseVirtualDocument() {\n\t\tthis.virtualDocument = null;\n\t}\n\n\t/**\n\t * Resolves title from allocated virtual document.\n\t */\n\tresolveTitleFromVirtualDocument() {\n\t\tconst title = this.virtualDocument.querySelector(this.titleSelector);\n\t\tif (title) {\n\t\t\tthis.setTitle(title.textContent.trim());\n\t\t}\n\t}\n\n\tresolveMetaTagsFromVirtualDocument() {\n\t\tconst metas = this.virtualQuerySelectorAll_(this.metaTagsSelector);\n\t\tif (metas) {\n\t\t\tthis.setMetas(metas);\n\t\t}\n\t}\n\n\t/**\n\t * Sets the title selector.\n\t * @param {!string} titleSelector\n\t */\n\tsetTitleSelector(titleSelector) {\n\t\tthis.titleSelector = titleSelector;\n\t}\n\n}\n\n/**\n * Helper selector for ignore favicon when exist data-senna-track.\n */\nconst ignoreFavicon = ':not([rel=\"Shortcut Icon\"]):not([rel=\"shortcut icon\"]):not([rel=\"icon\"]):not([href$=\"favicon.icon\"])';\n\n/**\n * Helper selectors for tracking resources.\n * @type {object}\n * @protected\n * @static\n */\nHtmlScreen.selectors = {\n\tfavicon: 'link[rel=\"Shortcut Icon\"],link[rel=\"shortcut icon\"],link[rel=\"icon\"],link[href$=\"favicon.icon\"]',\n\tscripts: 'script[data-senna-track]',\n\tscriptsPermanent: 'script[data-senna-track=\"permanent\"]',\n\tscriptsTemporary: 'script[data-senna-track=\"temporary\"]',\n\tstyles: `style[data-senna-track],link[data-senna-track]${ignoreFavicon}`,\n\tstylesPermanent: `style[data-senna-track=\"permanent\"],link[data-senna-track=\"permanent\"]${ignoreFavicon}`,\n\tstylesTemporary: `style[data-senna-track=\"temporary\"],link[data-senna-track=\"temporary\"]${ignoreFavicon}`\n};\n\n/**\n * Caches permanent resource keys.\n * @type {object}\n * @protected\n * @static\n */\nHtmlScreen.permanentResourcesInDoc = {};\n\nexport default HtmlScreen;\n","'use strict';\n\nimport { Disposable, getUid, isDefAndNotNull, isElement, object } from 'metal';\nimport dataAttributes from './dataAttributes';\nimport globals from '../globals/globals';\nimport App from './App';\nimport HtmlScreen from '../screen/HtmlScreen';\nimport Route from '../route/Route';\n\nclass AppDataAttributeHandler extends Disposable {\n\n\t/**\n\t * Initilizes App, register surfaces and routes from data attributes.\n\t * @constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the app reference initialized by data attributes.\n\t\t * @type {App}\n\t\t * @default null\n\t\t */\n\t\tthis.app = null;\n\n\t\t/**\n\t\t * Holds the base element to search initialization data attributes. This\n\t\t * element is the container used to enable initialization based on the\n\t\t * presence of `data-senna` attribute.\n\t\t * @type {Element}\n\t\t * @default null\n\t\t */\n\t\tthis.baseElement = null;\n\t}\n\n\t/**\n\t * Inits application based on information scanned from document.\n\t */\n\thandle() {\n\t\tif (!isElement(this.baseElement)) {\n\t\t\tthrow new Error('Senna data attribute handler base element ' +\n\t\t\t\t'not set or invalid, try setting a valid element that ' +\n\t\t\t\t'contains a `data-senna` attribute.');\n\t\t}\n\n\t\tif (!this.baseElement.hasAttribute(dataAttributes.senna)) {\n\t\t\tconsole.log('Senna was not initialized from data attributes. ' +\n\t\t\t\t'In order to enable its usage from data attributes try setting ' +\n\t\t\t\t'in the base element, e.g. `<body data-senna>`.');\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.app) {\n\t\t\tthrow new Error('Senna app was already initialized.');\n\t\t}\n\n\t\tconsole.log('Senna initialized from data attribute.');\n\n\t\tthis.app = new App();\n\t\tthis.maybeAddRoutes_();\n\t\tthis.maybeAddSurfaces_();\n\t\tthis.maybeSetBasePath_();\n\t\tthis.maybeSetLinkSelector_();\n\t\tthis.maybeSetLoadingCssClass_();\n\t\tthis.maybeSetUpdateScrollPosition_();\n\t\tthis.maybeDispatch_();\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tif (this.app) {\n\t\t\tthis.app.dispose();\n\t\t}\n\t}\n\n\t/**\n\t * Gets the app reference.\n\t * @return {App}\n\t */\n\tgetApp() {\n\t\treturn this.app;\n\t}\n\n\t/**\n\t * Gets the base element.\n\t * @return {Element} baseElement\n\t */\n\tgetBaseElement() {\n\t\treturn this.baseElement;\n\t}\n\n\t/**\n\t * Maybe adds app routes from link elements that are `senna-route`.\n\t */\n\tmaybeAddRoutes_() {\n\t\tvar routesSelector = 'link[rel=\"senna-route\"]';\n\t\tthis.querySelectorAllAsArray_(routesSelector).forEach((link) => this.maybeParseLinkRoute_(link));\n\t\tif (!this.app.hasRoutes()) {\n\t\t\tthis.app.addRoutes(new Route(/.*/, HtmlScreen));\n\t\t\tconsole.log('Senna can\\'t find route elements, adding default.');\n\t\t}\n\t}\n\n\t/**\n\t * Maybe adds app surfaces by scanning `data-senna-surface` data attribute.\n\t */\n\tmaybeAddSurfaces_() {\n\t\tvar surfacesSelector = '[' + dataAttributes.surface + ']';\n\t\tthis.querySelectorAllAsArray_(surfacesSelector).forEach((surfaceElement) => {\n\t\t\tthis.updateElementIdIfSpecialSurface_(surfaceElement);\n\t\t\tthis.app.addSurfaces(surfaceElement.id);\n\t\t});\n\t}\n\n\t/**\n\t * Dispatches app navigation to the current path when initializes.\n\t */\n\tmaybeDispatch_() {\n\t\tif (this.baseElement.hasAttribute(dataAttributes.dispatch)) {\n\t\t\tthis.app.dispatch();\n\t\t}\n\t}\n\n\t/**\n\t * Adds app route by parsing valid link elements. A valid link element is of\n\t * the kind `rel=\"senna-route\"`.\n\t * @param {Element} link\n\t */\n\tmaybeParseLinkRoute_(link) {\n\t\tvar route = new Route(this.maybeParseLinkRoutePath_(link), this.maybeParseLinkRouteHandler_(link));\n\t\tthis.app.addRoutes(route);\n\t\tconsole.log('Senna scanned route ' + route.getPath());\n\t}\n\n\t/**\n\t * Maybe parse link route handler.\n\t * @param {Element} link\n\t * @return {?string}\n\t */\n\tmaybeParseLinkRouteHandler_(link) {\n\t\tvar handler = link.getAttribute('type');\n\t\tif (isDefAndNotNull(handler)) {\n\t\t\thandler = object.getObjectByName(handler);\n\t\t}\n\t\treturn handler;\n\t}\n\n\t/**\n\t * Maybe parse link route path.\n\t * @param {Element} link\n\t * @return {?string}\n\t */\n\tmaybeParseLinkRoutePath_(link) {\n\t\tvar path = link.getAttribute('href');\n\t\tif (isDefAndNotNull(path)) {\n\t\t\tif (path.indexOf('regex:') === 0) {\n\t\t\t\tpath = new RegExp(path.substring(6));\n\t\t\t}\n\t\t}\n\t\treturn path;\n\t}\n\n\t/**\n\t * Maybe sets app base path from `data-senna-base-path` data attribute.\n\t */\n\tmaybeSetBasePath_() {\n\t\tvar basePath = this.baseElement.getAttribute(dataAttributes.basePath);\n\t\tif (isDefAndNotNull(basePath)) {\n\t\t\tthis.app.setBasePath(basePath);\n\t\t\tconsole.log('Senna scanned base path ' + basePath);\n\t\t}\n\t}\n\n\t/**\n\t * Maybe sets app link selector from `data-senna-link-selector` data\n\t * attribute.\n\t */\n\tmaybeSetLinkSelector_() {\n\t\tvar linkSelector = this.baseElement.getAttribute(dataAttributes.linkSelector);\n\t\tif (isDefAndNotNull(linkSelector)) {\n\t\t\tthis.app.setLinkSelector(linkSelector);\n\t\t\tconsole.log('Senna scanned link selector ' + linkSelector);\n\t\t}\n\t}\n\n\t/**\n\t * Maybe sets app link loading css class from `data-senna-loading-css-class`\n\t * data attribute.\n\t */\n\tmaybeSetLoadingCssClass_() {\n\t\tvar loadingCssClass = this.baseElement.getAttribute(dataAttributes.loadingCssClass);\n\t\tif (isDefAndNotNull(loadingCssClass)) {\n\t\t\tthis.app.setLoadingCssClass(loadingCssClass);\n\t\t\tconsole.log('Senna scanned loading css class ' + loadingCssClass);\n\t\t}\n\t}\n\n\t/**\n\t * Maybe sets app update scroll position from\n\t * `data-senna-update-scroll-position` data attribute.\n\t */\n\tmaybeSetUpdateScrollPosition_() {\n\t\tvar updateScrollPosition = this.baseElement.getAttribute(dataAttributes.updateScrollPosition);\n\t\tif (isDefAndNotNull(updateScrollPosition)) {\n\t\t\tif (updateScrollPosition === 'false') {\n\t\t\t\tthis.app.setUpdateScrollPosition(false);\n\t\t\t} else {\n\t\t\t\tthis.app.setUpdateScrollPosition(true);\n\t\t\t}\n\t\t\tconsole.log('Senna scanned update scroll position ' + updateScrollPosition);\n\t\t}\n\t}\n\n\t/**\n\t * Queries elements from document and returns an array of elements.\n\t * @param {!string} selector\n\t * @return {array.<Element>}\n\t */\n\tquerySelectorAllAsArray_(selector) {\n\t\treturn Array.prototype.slice.call(globals.document.querySelectorAll(selector));\n\t}\n\n\t/**\n\t * Updates element id if handled as special surface element. Some surfaces\n\t * are slightly different from others, like when threating <code>body</code>\n\t * as surface.\n\t * @param {Element} element\n\t */\n\tupdateElementIdIfSpecialSurface_(element) {\n\t\tif (!element.id && element === globals.document.body) {\n\t\t\telement.id = 'senna_surface_' + getUid();\n\t\t}\n\t}\n\n\t/**\n\t * Sets the base element.\n\t * @param {Element} baseElement\n\t */\n\tsetBaseElement(baseElement) {\n\t\tthis.baseElement = baseElement;\n\t}\n\n}\n\nexport default AppDataAttributeHandler;\n","'use strict';\n\nimport globals from '../globals/globals';\nimport AppDataAttributeHandler from './AppDataAttributeHandler';\n\n/**\n * Data attribute handler.\n * @type {AppDataAttributeHandler}\n */\nvar dataAttributeHandler = new AppDataAttributeHandler();\n\nglobals.document.addEventListener('DOMContentLoaded', function() {\n\tdataAttributeHandler.setBaseElement(globals.document.body);\n\tdataAttributeHandler.handle();\n});\n\nexport default dataAttributeHandler;","/**\n * @returns String containing the current senna version\n */\n\nconst version = '<%= version %>';\n\nexport default version;"],"names":["isDef","val","undefined","isDefAndNotNull","isNull","isDocument","nodeType","isFunction","isObject","type","isString","String","isServerSide","options","checkEnv","serverSide","process","browser","env","NODE_ENV","array","arr1","arr2","length","i","arr","output","Array","isArray","flatten","push","obj","indexOf","rv","removeAt","prototype","splice","call","start","end","sliced","async","throwException","exception","nextTick","run","callback","context","workQueueScheduled_","processWorkQueue","workQueue_","WorkItem_","workItems","workItem","fn","scope","e","cb","bind","wrapCallback_","setImmediate_","setImmediate","getSetImmediateEmulator_","Channel","MessageChannel","window","postMessage","addEventListener","iframe","document","createElement","style","display","src","title","documentElement","appendChild","win","contentWindow","doc","open","write","close","message","Math","random","origin","location","protocol","host","onmessage","data","port1","port2","channel","head","tail","next","script","onreadystatechange","parentNode","removeChild","Disposable","disposed_","disposeInternal","object","target","key","source","args","name","parts","split","reduce","part","mappedObj","keys","Object","obj1","obj2","keys1","keys2","string","str1","str2","test1","toLowerCase","test2","str","replace","x","floor","toString","abs","Date","now","hash","len","charCodeAt","value","substring","METAL_DATA","domData","element","initialValue","EventHandle","emitter","event","listener","emitter_","event_","listener_","removeListener","isDisposed","singleArray_","EventEmitter","events_","listenerHandlers_","shouldUseFacade_","holder","handler","defaultListener","validateListener_","events","toEventsArray_","addSingleListener_","runListenerHandlers_","addHandler_","getShouldUseFacade","facade","preventedDefault","listeners","getRawListeners_","slice","arguments","runListeners_","buildFacade_","directListeners","toArray","concat","map","amount","many_","self","handlerInternal","apply","listenerObj","removeMatchingListenerObjs_","addListener","many","listenerObjs","finalListeners","matchesListener_","off","handlers","defaultListeners","default","j","shouldUseFacade","TypeError","EventEmitterProxy","originEmitter","targetEmitter","blacklist","whitelist","blacklist_","originEmitter_","pendingEvents_","proxiedEvents_","targetEmitter_","whitelist_","startProxy_","on","removeListeners_","emit","shouldProxyEvent_","tryToAddListener_","forEach","proxyEvent","onListener","addListener_","emitOnTarget_","EventHandler","eventHandles_","DomDelegatedEventHandle","selector","selector_","delegating","get","selectors","remove","DomEventHandle","capture","capture_","removeEventListener","elementsByTag_","supportCache_","customEvents","LAST_CONTAINER","USE_CAPTURE","addClasses","elements","classes","addClassesWithNative_","className","classList","add","addClassesWithoutNative_","elementClassName","classesToAppend","addElementListener_","eventName","addSelectorListener_","delegatingData","addToArr_","attachDelegateEvent_","handleDelegateEvent_","closest","match","append","parent","child","buildFragment","isNodeListLike","childArr","htmlString","tempDiv","innerHTML","firstChild","fragment","createDocumentFragment","contains","element1","element2","delegate","selectorOrTarget","customConfig","originalEvent","defaultListener_","isAbleToInteractWith_","node","eventObj","button","matchesSelector","tagName","disabled","item","exitDocument","ret","container","currentTarget","defFns","triggerDelegatedListeners_","triggerDefaultDelegatedListeners_","delegateTarget","p","Element","m","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector","matchFallback_","nodes","querySelectorAll","normalizeDelegateEvent_","stopPropagation","stopPropagation_","stopImmediatePropagation","stopImmediatePropagation_","once","domEventHandle","registerCustomEvent","removeChildren","removeClasses","removeClassesWithNative_","removeClassesWithoutNative_","trim","stopped","stoppedImmediate","supportsEvent","tag","hasOwnProperty","defaultPrevented","defaultFns","currElement","limit","triggerElementListeners_","triggerSelectorListeners_","lastContainer","triggerListeners_","DomEventEmitterProxy","isDelegateEvent_","index","substr","babelHelpers.get","isSupportedDomEvent_","features","animationEventName_","checkAnimationEventName_","prefixes","typeTitleCase","replaceInterval","toUpperCase","suffixes","animationElement_","attrOrderChange_","originalContent","globalEval","text","appendFn","defaultFn","runFile","scripts","runScriptsInOrder","runScript","globalEvalStyles","href","link","rel","runStyle","styles","loadCount","registerEvents","mouseEventMap","related","relatedTarget","customType","animationEventMap","eventType","checkAnimationEventName","globals","compatibilityModeData_","uniqueIdCounter_","UID_PROPERTY","abstractMethod","Error","disableCompatibilityMode","enableCompatibilityMode","getCompatibilityModeData","__METAL_COMPATIBILITY__","getFirstTruthy_","a","b","getFunctionName","getStaticProperty","ctor","propertyName","mergeFn","mergedName","merged","__proto__","isPrototypeOf","Function","getUid","noInheritance","id","identityFunction","returnValue","isBoolean","isDocumentFragment","isElement","isNumber","isWindow","isPromise","then","nullFunction","parseFromAnchor","opt_uri","test","hostname","password","pathname","port","search","username","parse","URL","url","create","MultiMap","values","size","names","JSON","stringify","set","TreeNode","value_","parent_","children_","setParent","current","getParent","ancestors","getChildren","EMPTY_ARRAY","depth","root","getChildCount","opt_preorderFn","opt_postorderFn","traverse","assertChildHasNoParent","parseFn_","Uri","maybeAddProtocolAndHostname_","multimap","getAll","addParameterValue","ensureQueryInitialized_","query","param","urlDecode","getHostname","getPort","HOSTNAME_PLACEHOLDER","getHost","getProtocol","querystring","getParameterNames","getParameterValues","encodeURIComponent","setParameterValue","RANDOM_PARAM","getRandomString","DEFAULT_PROTOCOL","charAt","removeParameter","getPathname","getSearch","getHash","parseFn","basePath","paths","path","join","decodeURIComponent","isSecure","utils","attributes","attribute","setAttribute","getCurrentBrowserPathWithoutHash","offsetLeft","offsetTop","offsetParent","uri","currentBrowserPath","getUrlPathWithoutHash","getUrlPath","history","pushState","err","error","removeAttribute","referrer","defineProperty","Thenable","IMPLEMENTED_BY_PROP","addImplementation","$goog_Thenable","isImplementedBy","partial","newArgs","CancellablePromise","resolver","opt_context","state_","State_","PENDING","result_","callbackEntries_","executing_","UNHANDLED_REJECTION_DELAY","unhandledRejectionId_","hadUnhandledRejection_","resolve_","FULFILLED","reason","REJECTED","CallbackEntry_","resolve","opt_value","reject","opt_reason","race","promises","promise","all","toFulfill","onFulfill","onReject","firstFulfilled","toReject","reasons","opt_onFulfilled","opt_onRejected","addChildPromise_","thenAlways","onResolved","handleRejection_","addCallbackEntry_","thenCatch","onRejected","catch","cancel","opt_message","CancellationError","IS_CANCELLATION_ERROR","cancelInternal_","cancelChild_","childPromise","childCount","childIndex","entry","callbackEntry","executeCallback_","scheduleCallbacks_","onFulfilled","result","unblockAndFulfill_","BLOCKED","unblockAndReject_","state","tryThen_","addUnhandledRejection_","thenable","called","executeCallbacks_","entries","removeUnhandledRejection_","setTimeout","setUnhandledRejectionHandler","debounce","delay","debounced","cancelDebounce","REGEX","convertMatchesToObj","convertTokensToRegex","tokens","regex","core","escape","encloseNonCapturingGroup","pattern","repeat","prefix","optional","RegExp","makeTrailingSlashOptional","routeOrTokens","route","unnamedCount","currPath","exec","paramPattern","unnamedPattern","modifier","toRegex","extractData","paramIndex","Route","parsedData_","buildParsedData_","Cacheable","cache","cacheable","content","clearCache","Screen","makeId_","metas","log","surfaces","sId","activeChild","runScriptsInElement","transitions","surface","deferred","show","Surface","defaultChild","transitionFn","getChild","DEFAULT","maybeWrapContentAsDefault_","screenId","opt_content","createChild","transition","getElement","getElementById","addContent","from","to","defaultTransition","NavigationStrategy","App","activeScreen","activePath","allowPreventNavigate","browserPathBeforeNavigate","captureScrollPositionFromScrollEvent","defaultTitle","formSelector","ignoreQueryStringFromRoutePath","linkSelector","loadingCssClass","nativeScrollRestorationSupported","navigationStrategy","IMMEDIATE","isNavigationPending","pendingNavigate","popstateScrollLeft","popstateScrollTop","redirectPath","routes","scheduledNavigationQueue","screens","skipLoadPopstate","updateScrollPosition","appEventHandlers_","onScroll_","onLoad_","onPopstate_","onStartNavigate_","onBeforeNavigate_","onBeforeNavigateDefault_","onBeforeUnloadDefault_","setLinkSelector","setFormSelector","maybeOverloadBeforeUnload_","getId","isWebUri","isLinkSameOrigin_","isSameBasePath_","isCurrentBrowserPath","findRoute","removeScreen","screen","getHandler","clearScreensCache","formEventHandler_","linkEventHandler_","removeAllListeners","navigate","getCurrentBrowserPath","opt_replaceHistory","stopPendingNavigate_","nextScreen","createScreenInstance","maybePreventDeactivate_","maybePreventActivate_","load","SCHEDULE_LAST","deactivate","prepareNavigateHistory_","prepareNavigateSurfaces_","extractParams","evaluateStyles","flip","evaluateScripts","maybeUpdateScrollPositionState_","syncScrollPositionSyncThenAsync_","finalizeNavigate_","handleNavigateError_","scheduledNavigation","shift","maybeNavigate_","getRoutePath","activate","isCacheable","capturedFormElement","capturedFormButtonElement","matchesPath","getIgnoreQueryStringFromRoutePath","getUrlPathWithoutHashAndSearch","stack","hostUri","locationHostUri","winner","switchScrollPositionRace","scrollTo","scrollLeft","scrollTop","nativeScrollRestoration_","scrollRestoration","mixin","canNavigate","isNavigationScheduled","maybeScheduleNavigation_","preventDefault","navigateFailed","isScheduledNavigation","onbeforeunload","_onbeforeunload","_overloaded","beforeActivate","prevent","beforeDeactivate","anchorElement","getNodeOffset","saveHistoryCurrentPageScrollPosition_","opt_event","isHtml5HistorySupported","form","replaceHistory","func","altKey","ctrlKey","metaKey","shiftKey","method","buttonSelector","activeElement","querySelector","action","maybeRepositionScrollToHashedAnchor","reloadPage","senna","lockHistoryScrollPosition_","setReferrer","setHostname","setPort","pageYOffset","pageXOffset","maybeDisableNativeScrollRestoration","endNavigatePayload","doNavigate_","maybeRestoreNativeScrollRestoration","getTitle","getDefaultTitle","beforeUpdateHistoryPath","historyState","maybeRestoreRedirectPathHash_","updateHistory_","beforeUpdateHistoryState","params","surfaceContent","getSurfaceContent","reload","surfaceId","dispose","replaceState","removePathTrailingSlash","onDocSubmitDelegate_","onDocClickDelegate_","sync","titleNode","Ajax","allHeaders","headers","pairs","body","opt_headers","opt_params","opt_timeout","opt_sync","opt_withCredentials","request","XMLHttpRequest","previousReadyState","Promise","onload","aborted","onerror","readyState","terminatedPrematurely","abort","timeout","addParametersFromMultiMap","withCredentials","setRequestHeader","send","errors","INVALID_STATUS","REQUEST_ERROR","REQUEST_TIMEOUT","REQUEST_PREMATURE_TERMINATION","UA","navigator","userAgent","platform","isMac","matchPlatform","isWin","isOpera","matchUserAgent","isIe","isEdge","isIeOrEdge","isChrome","isSafari","isFirefox","testUserAgent","getNativeUserAgent","getNativePlatform","RequestScreen","httpHeaders","httpMethod","GET","status","isValidResponseStatusCode","invalidStatus","statusCode","getRequestPath","setProtocol","makeUnique","getRequest","requestPath","responseUrl","maybeExtractResponseUrlFromRequest","removeUnique","formElement","submittedButtonElement","formData","FormData","maybeAppendSubmitButtonValue_","getCache","header","addSafariXHRPolyfill","getFormData","POST","formatLoadPath","removeSafariXHRPolyfill","setRequest","xhr","assertValidResponseStatusCode","addCache","responseText","requestError","requestPrematureTermination","responseURL","getResponseHeader","X_REQUEST_URL_HEADER","inputs","input","files","HtmlScreen","metaTagsSelector","titleSelector","releaseVirtualDocument","pendingStyles","virtualDocument","copyNodeAttributesFromContent_","newStyle","isTemporaryStyle","stylesTemporary","styleInDoc","insertBefore","nextSibling","bodySurface","placeholder","tempNode","createRange","createContextualFragment","clearNodeAttributes","copyNodeAttributes","disposePendingStyles","removeElementsFromDocument","evaluateTrackedScripts","evaluateTrackedResources_","scriptsTemporary","scriptsPermanent","evaluateTrackedStyles","runStylesInElement","stylesPermanent","appendStyleIntoDocument_","resourcesInVirtual","virtualQuerySelectorAll_","favicon","resourcesInDocument","querySelectorAll_","runFaviconInElement_","evaluatorFn","selectorTemporary","selectorPermanent","opt_appendResourceFn","tracked","temporariesInDoc","permanentsInDoc","resource","resourceKey","getResourceKey_","permanentResourcesInDoc","frag","evaluateFavicon_","updateMetaTags_","currentMetaNodes","metasFromVirtualDocument","meta","allocateVirtualDocumentForContent","resolveTitleFromVirtualDocument","resolveMetaTagsFromVirtualDocument","assertSameBodyIdInVirtualDocument","makeTemporaryStylesHrefsUnique_","replaceStyleAndMakeUnique_","replaceChild","setElementWithRandomHref","setTitle","textContent","setMetas","ignoreFavicon","AppDataAttributeHandler","app","baseElement","hasAttribute","dataAttributes","maybeAddRoutes_","maybeAddSurfaces_","maybeSetBasePath_","maybeSetLinkSelector_","maybeSetLoadingCssClass_","maybeSetUpdateScrollPosition_","maybeDispatch_","routesSelector","querySelectorAllAsArray_","maybeParseLinkRoute_","hasRoutes","addRoutes","surfacesSelector","surfaceElement","updateElementIdIfSpecialSurface_","addSurfaces","dispatch","maybeParseLinkRoutePath_","maybeParseLinkRouteHandler_","getPath","getAttribute","getObjectByName","setBasePath","setLoadingCssClass","setUpdateScrollPosition","dataAttributeHandler","setBaseElement","handle","version"],"mappings":"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","preExistingComment":"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9jb3JlTmFtZWQuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvY29yZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9hcnJheS9hcnJheS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9hc3luYy9hc3luYy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9kaXNwb3NhYmxlL0Rpc3Bvc2FibGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvb2JqZWN0L29iamVjdC5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9zdHJpbmcvc3RyaW5nLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZG9tRGF0YS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsLWV2ZW50cy9zcmMvRXZlbnRIYW5kbGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL25vZGVfbW9kdWxlcy9tZXRhbC1ldmVudHMvc3JjL0V2ZW50RW1pdHRlci5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsLWV2ZW50cy9zcmMvRXZlbnRFbWl0dGVyUHJveHkuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL25vZGVfbW9kdWxlcy9tZXRhbC1ldmVudHMvc3JjL0V2ZW50SGFuZGxlci5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL0RvbURlbGVnYXRlZEV2ZW50SGFuZGxlLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvRG9tRXZlbnRIYW5kbGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9kb21OYW1lZC5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL2RvbS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL0RvbUV2ZW50RW1pdHRlclByb3h5LmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZmVhdHVyZXMuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9nbG9iYWxFdmFsLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZ2xvYmFsRXZhbFN0eWxlcy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL2V2ZW50cy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9nbG9iYWxzL2dsb2JhbHMuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL2NvcmVOYW1lZC5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvY29yZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvYXJyYXkvYXJyYXkuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL2FzeW5jL2FzeW5jLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9kaXNwb3NhYmxlL0Rpc3Bvc2FibGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL29iamVjdC9vYmplY3QuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL3N0cmluZy9zdHJpbmcuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtdXJpL3NyYy9wYXJzZUZyb21BbmNob3IuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtdXJpL3NyYy9wYXJzZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1zdHJ1Y3RzL3NyYy9NdWx0aU1hcC5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1zdHJ1Y3RzL3NyYy9UcmVlTm9kZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC11cmkvc3JjL1VyaS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy91dGlscy91dGlscy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9hcHAvZGF0YUF0dHJpYnV0ZXMuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZXZlbnRzL3NyYy9FdmVudEhhbmRsZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1ldmVudHMvc3JjL0V2ZW50RW1pdHRlci5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1ldmVudHMvc3JjL0V2ZW50RW1pdHRlclByb3h5LmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWV2ZW50cy9zcmMvRXZlbnRIYW5kbGVyLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLXByb21pc2Uvc3JjL3Byb21pc2UvUHJvbWlzZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kZWJvdW5jZS9zcmMvZGVib3VuY2UuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtcGF0aC1wYXJzZXIvc3JjL3BhdGhQYXJzZXIuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9zcmMvcm91dGUvUm91dGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9zcmMvY2FjaGVhYmxlL0NhY2hlYWJsZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9zY3JlZW4vU2NyZWVuLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvc3JjL3N1cmZhY2UvU3VyZmFjZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9hcHAvQXBwLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWFqYXgvc3JjL0FqYXguanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9zcmMvZXJyb3JzL2Vycm9ycy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC11c2VyYWdlbnQvc3JjL1VBLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvc3JjL3NjcmVlbi9SZXF1ZXN0U2NyZWVuLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvc3JjL3NjcmVlbi9IdG1sU2NyZWVuLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvc3JjL2FwcC9BcHBEYXRhQXR0cmlidXRlSGFuZGxlci5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9hcHAvZGF0YUF0dHJpYnV0ZUhhbmRsZXIuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9zcmMvYXBwL3ZlcnNpb24uanMiXSwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIEEgY29sbGVjdGlvbiBvZiBjb3JlIHV0aWxpdHkgZnVuY3Rpb25zLlxuICogQGNvbnN0XG4gKi9cblxubGV0IGNvbXBhdGliaWxpdHlNb2RlRGF0YV87XG5cbi8qKlxuICogQ291bnRlciBmb3IgdW5pcXVlIGlkLlxuICogQHR5cGUge051bWJlcn1cbiAqIEBwcml2YXRlXG4gKi9cbmxldCB1bmlxdWVJZENvdW50ZXJfID0gMTtcblxuLyoqXG4gKiBVbmlxdWUgaWQgcHJvcGVydHkgcHJlZml4LlxuICogQHR5cGUge1N0cmluZ31cbiAqIEBwcm90ZWN0ZWRcbiAqL1xuZXhwb3J0IGNvbnN0IFVJRF9QUk9QRVJUWSA9IGBjb3JlXyR7KE1hdGgucmFuZG9tKCkgKiAxZTkpID4+PiAwfWA7XG5cbi8qKlxuICogV2hlbiBkZWZpbmluZyBhIGNsYXNzIEZvbyB3aXRoIGFuIGFic3RyYWN0IG1ldGhvZCBiYXIoKSwgeW91IGNhbiBkbzpcbiAqIEZvby5wcm90b3R5cGUuYmFyID0gYWJzdHJhY3RNZXRob2RcbiAqXG4gKiBOb3cgaWYgYSBzdWJjbGFzcyBvZiBGb28gZmFpbHMgdG8gb3ZlcnJpZGUgYmFyKCksIGFuIGVycm9yIHdpbGwgYmUgdGhyb3duXG4gKiB3aGVuIGJhcigpIGlzIGludm9rZWQuXG4gKlxuICogQHR5cGUgeyFGdW5jdGlvbn1cbiAqIEB0aHJvd3Mge0Vycm9yfSB3aGVuIGludm9rZWQgdG8gaW5kaWNhdGUgdGhlIG1ldGhvZCBzaG91bGQgYmUgb3ZlcnJpZGRlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFic3RyYWN0TWV0aG9kKCkge1xuXHR0aHJvdyBFcnJvcignVW5pbXBsZW1lbnRlZCBhYnN0cmFjdCBtZXRob2QnKTtcbn1cblxuLyoqXG4gKiBEaXNhYmxlcyBNZXRhbC5qcydzIGNvbXBhdGliaWxpdHkgbW9kZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRpc2FibGVDb21wYXRpYmlsaXR5TW9kZSgpIHtcblx0Y29tcGF0aWJpbGl0eU1vZGVEYXRhXyA9IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBFbmFibGVzIE1ldGFsLmpzJ3MgY29tcGF0aWJpbGl0eSBtb2RlIHdpdGggdGhlIGZvbGxvd2luZyBmZWF0dXJlcyBmcm9tIHJjXG4gKiBhbmQgMS54IHZlcnNpb25zOlxuICogICAgIC0gVXNpbmcgXCJrZXlcIiB0byByZWZlcmVuY2UgY29tcG9uZW50IGluc3RhbmNlcy4gSW4gdGhlIGN1cnJlbnQgdmVyc2lvblxuICogICAgICAgdGhpcyBzaG91bGQgYmUgZG9uZSB2aWEgXCJyZWZcIiBpbnN0ZWFkLiBUaGlzIGFsbG93cyBvbGQgY29kZSBzdGlsbFxuICogICAgICAgdXNpbmcgXCJrZXlcIiB0byBrZWVwIHdvcmtpbmcgbGlrZSBiZWZvcmUuIE5PVEU6IHRoaXMgbWF5IGNhdXNlXG4gKiAgICAgICBwcm9ibGVtcywgc2luY2UgXCJrZXlcIiBpcyBtZWFudCB0byBiZSB1c2VkIGRpZmZlcmVudGx5LiBPbmx5IHVzZSB0aGlzXG4gKiAgICAgICBpZiBpdCdzIG5vdCBwb3NzaWJsZSB0byB1cGdyYWRlIHRoZSBjb2RlIHRvIHVzZSBcInJlZlwiIGluc3RlYWQuXG4gKiBAcGFyYW0ge09iamVjdD19IGRhdGEgT3B0aW9uYWwgb2JqZWN0IHdpdGggZGF0YSB0byBzcGVjaWZ5IG1vcmVcbiAqICAgICBkZXRhaWxzLCBzdWNoIGFzOlxuICogICAgICAgICAtIHJlbmRlcmVycyB7QXJyYXl9IHRoZSB0ZW1wbGF0ZSByZW5kZXJlcnMgdGhhdCBzaG91bGQgYmUgaW5cbiAqICAgICAgICAgICBjb21wYXRpYmlsaXR5IG1vZGUsIGVpdGhlciB0aGVpciBjb25zdHJ1Y3RvcnMgb3Igc3RyaW5nc1xuICogICAgICAgICAgIHJlcHJlc2VudGluZyB0aGVtIChlLmcuICdzb3knIG9yICdqc3gnKS4gQnkgZGVmYXVsdCwgYWxsIHRoZSBvbmVzXG4gKiAgICAgICAgICAgdGhhdCBleHRlbmQgZnJvbSBJbmNyZW1lbnRhbERvbVJlbmRlcmVyLlxuICogQHR5cGUge09iamVjdH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuYWJsZUNvbXBhdGliaWxpdHlNb2RlKGRhdGEgPSB7fSkge1xuXHRjb21wYXRpYmlsaXR5TW9kZURhdGFfID0gZGF0YTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBkYXRhIHVzZWQgZm9yIGNvbXBhdGliaWxpdHkgbW9kZSwgb3Igbm90aGluZyBpZiBpdCBoYXNuJ3QgYmVlblxuICogZW5hYmxlZC5cbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbXBhdGliaWxpdHlNb2RlRGF0YSgpIHtcblx0Ly8gQ29tcGF0aWJpbGl0eSBtb2RlIGNhbiBiZSBzZXQgdmlhIHRoZSBfX01FVEFMX0NPTVBBVElCSUxJVFlfXyBnbG9iYWwgdmFyLlxuXHRpZiAoY29tcGF0aWJpbGl0eU1vZGVEYXRhXyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0aWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5fX01FVEFMX0NPTVBBVElCSUxJVFlfXykge1xuXHRcdFx0ZW5hYmxlQ29tcGF0aWJpbGl0eU1vZGUod2luZG93Ll9fTUVUQUxfQ09NUEFUSUJJTElUWV9fKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGNvbXBhdGliaWxpdHlNb2RlRGF0YV87XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZmlyc3QgYXJndW1lbnQgaWYgaXQncyB0cnV0aHksIG9yIHRoZSBzZWNvbmQgb3RoZXJ3aXNlLlxuICogQHBhcmFtIHsqfSBhXG4gKiBAcGFyYW0geyp9IGJcbiAqIEByZXR1cm4geyp9XG4gKiBAcHJvdGVjdGVkXG4gKi9cbmZ1bmN0aW9uIGdldEZpcnN0VHJ1dGh5XyhhLCBiKSB7XG5cdHJldHVybiBhIHx8IGI7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgbmFtZSBvZiB0aGUgZ2l2ZW4gZnVuY3Rpb24uIElmIHRoZSBjdXJyZW50IGJyb3dzZXIgZG9lc24ndFxuICogc3VwcG9ydCB0aGUgYG5hbWVgIHByb3BlcnR5LCBsaWtlIElFMTEsIHRoaXMgd2lsbCBjYWxjdWxhdGUgaXQgZnJvbSB0aGUgZnVuY3Rpb24nc1xuICogY29udGVudCBzdHJpbmcuXG4gKiBAcGFyYW0geyFmdW5jdGlvbigpfSBmblxuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RnVuY3Rpb25OYW1lKGZuKSB7XG5cdGlmICghZm4ubmFtZSkge1xuXHRcdGNvbnN0IHN0ciA9IGZuLnRvU3RyaW5nKCk7XG5cdFx0Zm4ubmFtZSA9IHN0ci5zdWJzdHJpbmcoOSwgc3RyLmluZGV4T2YoJygnKSk7XG5cdH1cblx0cmV0dXJuIGZuLm5hbWU7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgdmFsdWUgb2YgYSBzdGF0aWMgcHJvcGVydHkgaW4gdGhlIGdpdmVuIGNsYXNzLiBUaGUgdmFsdWUgd2lsbCBiZVxuICogaW5oZXJpdGVkIGZyb20gYW5jZXN0b3JzIGFzIGV4cGVjdGVkLCB1bmxlc3MgYSBjdXN0b20gbWVyZ2UgZnVuY3Rpb24gaXMgZ2l2ZW4sXG4gKiB3aGljaCBjYW4gY2hhbmdlIGhvdyB0aGUgc3VwZXIgY2xhc3NlcycgdmFsdWUgZm9yIHRoYXQgcHJvcGVydHkgd2lsbCBiZSBtZXJnZWRcbiAqIHRvZ2V0aGVyLlxuICogVGhlIGZpbmFsIG1lcmdlZCB2YWx1ZSB3aWxsIGJlIHN0b3JlZCBpbiBhbm90aGVyIHByb3BlcnR5LCBzbyB0aGF0IGl0IHdvbid0XG4gKiBiZSByZWNhbGN1bGF0ZWQgZXZlbiBpZiB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBtdWx0aXBsZSB0aW1lcy5cbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGN0b3IgQ2xhc3MgY29uc3RydWN0b3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHlOYW1lIFByb3BlcnR5IG5hbWUgdG8gYmUgbWVyZ2VkLlxuICogQHBhcmFtIHtmdW5jdGlvbigqLCAqKToqPX0gbWVyZ2VGbiBGdW5jdGlvbiB0aGF0IHJlY2VpdmVzIHRoZSBtZXJnZWRcbiAqICAgICB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgc28gZmFyIGFuZCB0aGUgbmV4dCB2YWx1ZSB0byBiZSBtZXJnZWQgdG8gaXQuXG4gKiAgICAgU2hvdWxkIHJldHVybiB0aGVzZSB0d28gbWVyZ2VkIHRvZ2V0aGVyLiBJZiBub3QgcGFzc2VkIHRoZSBmaW5hbCBwcm9wZXJ0eVxuICogICAgIHdpbGwgYmUgdGhlIGZpcnN0IHRydXRoeSB2YWx1ZSBhbW9uZyBhbmNlc3RvcnMuXG4gKiBAcmV0dXJuIHtPYmplY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGF0aWNQcm9wZXJ0eShcblx0Y3Rvcixcblx0cHJvcGVydHlOYW1lLFxuXHRtZXJnZUZuID0gZ2V0Rmlyc3RUcnV0aHlfXG4pIHtcblx0Y29uc3QgbWVyZ2VkTmFtZSA9IHByb3BlcnR5TmFtZSArICdfTUVSR0VEJztcblx0aWYgKCFjdG9yLmhhc093blByb3BlcnR5KG1lcmdlZE5hbWUpKSB7XG5cdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cdFx0bGV0IG1lcmdlZCA9IGN0b3IuaGFzT3duUHJvcGVydHkocHJvcGVydHlOYW1lKVxuXHRcdFx0PyBjdG9yW3Byb3BlcnR5TmFtZV1cblx0XHRcdDogbnVsbDtcblx0XHRpZiAoY3Rvci5fX3Byb3RvX18gJiYgIWN0b3IuX19wcm90b19fLmlzUHJvdG90eXBlT2YoRnVuY3Rpb24pKSB7XG5cdFx0XHRtZXJnZWQgPSBtZXJnZUZuKFxuXHRcdFx0XHRtZXJnZWQsXG5cdFx0XHRcdGdldFN0YXRpY1Byb3BlcnR5KGN0b3IuX19wcm90b19fLCBwcm9wZXJ0eU5hbWUsIG1lcmdlRm4pXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRjdG9yW21lcmdlZE5hbWVdID0gbWVyZ2VkO1xuXHR9XG5cdHJldHVybiBjdG9yW21lcmdlZE5hbWVdO1xufVxuXG4vKipcbiAqIEdldHMgYW4gdW5pcXVlIGlkLiBJZiBgb2JqZWN0YCBhcmd1bWVudCBpcyBwYXNzZWQsIHRoZSBvYmplY3QgaXNcbiAqIG11dGF0ZWQgd2l0aCBhbiB1bmlxdWUgaWQuIENvbnNlY3V0aXZlIGNhbGxzIHdpdGggdGhlIHNhbWUgb2JqZWN0XG4gKiByZWZlcmVuY2Ugd29uJ3QgbXV0YXRlIHRoZSBvYmplY3QgYWdhaW4sIGluc3RlYWQgdGhlIGN1cnJlbnQgb2JqZWN0IHVpZFxuICogcmV0dXJucy4gU2VlIHtAbGluayBVSURfUFJPUEVSVFl9LlxuICogQHBhcmFtIHtPYmplY3Q9fSBvYmplY3QgT3B0aW9uYWwgb2JqZWN0IHRvIGJlIG11dGF0ZWQgd2l0aCB0aGUgdWlkLiBJZlxuICogICAgIG5vdCBzcGVjaWZpZWQgdGhpcyBtZXRob2Qgb25seSByZXR1cm5zIHRoZSB1aWQuXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBub0luaGVyaXRhbmNlIE9wdGlvbmFsIGZsYWcgaW5kaWNhdGluZyBpZiB0aGlzXG4gKiAgICAgb2JqZWN0J3MgdWlkIHByb3BlcnR5IGNhbiBiZSBpbmhlcml0ZWQgZnJvbSBwYXJlbnRzIG9yIG5vdC5cbiAqIEB0aHJvd3Mge0Vycm9yfSB3aGVuIGludm9rZWQgdG8gaW5kaWNhdGUgdGhlIG1ldGhvZCBzaG91bGQgYmUgb3ZlcnJpZGRlbi5cbiAqIEByZXR1cm4ge251bWJlcn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFVpZChvYmplY3QsIG5vSW5oZXJpdGFuY2UpIHtcblx0aWYgKG9iamVjdCkge1xuXHRcdGxldCBpZCA9IG9iamVjdFtVSURfUFJPUEVSVFldO1xuXHRcdGlmIChub0luaGVyaXRhbmNlICYmICFvYmplY3QuaGFzT3duUHJvcGVydHkoVUlEX1BST1BFUlRZKSkge1xuXHRcdFx0aWQgPSBudWxsO1xuXHRcdH1cblx0XHRyZXR1cm4gaWQgfHwgKG9iamVjdFtVSURfUFJPUEVSVFldID0gdW5pcXVlSWRDb3VudGVyXysrKTtcblx0fVxuXHRyZXR1cm4gdW5pcXVlSWRDb3VudGVyXysrO1xufVxuXG4vKipcbiAqIFRoZSBpZGVudGl0eSBmdW5jdGlvbi4gUmV0dXJucyBpdHMgZmlyc3QgYXJndW1lbnQuXG4gKiBAcGFyYW0geyo9fSByZXR1cm5WYWx1ZSBUaGUgc2luZ2xlIHZhbHVlIHRoYXQgd2lsbCBiZSByZXR1cm5lZC5cbiAqIEByZXR1cm4gez99IFRoZSBmaXJzdCBhcmd1bWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlkZW50aXR5RnVuY3Rpb24ocmV0dXJuVmFsdWUpIHtcblx0cmV0dXJuIHJldHVyblZhbHVlO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGEgYm9vbGVhbi5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGJvb2xlYW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Jvb2xlYW4odmFsKSB7XG5cdHJldHVybiB0eXBlb2YgdmFsID09PSAnYm9vbGVhbic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgbm90IHVuZGVmaW5lZC5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGRlZmluZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RlZih2YWwpIHtcblx0cmV0dXJuIHZhbCAhPT0gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBub3QgdW5kZWZpbmVkIG9yIG51bGwuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGVmQW5kTm90TnVsbCh2YWwpIHtcblx0cmV0dXJuIGlzRGVmKHZhbCkgJiYgIWlzTnVsbCh2YWwpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIGRvY3VtZW50LlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RvY3VtZW50KHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbC5ub2RlVHlwZSA9PT0gOTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBkb2N1bWVudC1mcmFnbWVudC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEb2N1bWVudEZyYWdtZW50KHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbC5ub2RlVHlwZSA9PT0gMTE7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgZG9tIGVsZW1lbnQuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRWxlbWVudCh2YWwpIHtcblx0cmV0dXJuIHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB2YWwubm9kZVR5cGUgPT09IDE7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYSBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGEgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbCkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgbnVsbC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNOdWxsKHZhbCkge1xuXHRyZXR1cm4gdmFsID09PSBudWxsO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGEgbnVtYmVyLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgYSBudW1iZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc051bWJlcih2YWwpIHtcblx0cmV0dXJuIHR5cGVvZiB2YWwgPT09ICdudW1iZXInO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIHdpbmRvdy5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNXaW5kb3codmFsKSB7XG5cdHJldHVybiB2YWwgIT09IG51bGwgJiYgdmFsID09PSB2YWwud2luZG93O1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGFuIG9iamVjdC4gVGhpcyBpbmNsdWRlcyBhcnJheXNcbiAqIGFuZCBmdW5jdGlvbnMuXG4gKiBAcGFyYW0gez99IHZhbCBWYXJpYWJsZSB0byB0ZXN0LlxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB2YXJpYWJsZSBpcyBhbiBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc09iamVjdCh2YWwpIHtcblx0Y29uc3QgdHlwZSA9IHR5cGVvZiB2YWw7XG5cdHJldHVybiAodHlwZSA9PT0gJ29iamVjdCcgJiYgdmFsICE9PSBudWxsKSB8fCB0eXBlID09PSAnZnVuY3Rpb24nO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIFByb21pc2UuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUHJvbWlzZSh2YWwpIHtcblx0cmV0dXJuIHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgdmFsLnRoZW4gPT09ICdmdW5jdGlvbic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgc3RyaW5nLlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1N0cmluZyh2YWwpIHtcblx0cmV0dXJuIHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnIHx8IHZhbCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuLyoqXG4gKiBTZXRzIHRvIHRydWUgaWYgcnVubmluZyBpbnNpZGUgTm9kZS5qcyBlbnZpcm9ubWVudCB3aXRoIGV4dHJhIGNoZWNrIGZvclxuICogYHByb2Nlc3MuYnJvd3NlcmAgdG8gc2tpcCBLYXJtYSBydW5uZXIgZW52aXJvbm1lbnQuIEthcm1hIGVudmlyb25tZW50IGhhc1xuICogYHByb2Nlc3NgIGRlZmluZWQgZXZlbiB0aG91Z2ggaXQgcnVucyBvbiB0aGUgYnJvd3Nlci5cbiAqIEBwYXJhbSB7P09iamVjdH0gb3B0aW9ucyBDb250YWlucyBgY2hlY2tFbnZgIHByb3BlcnR5IHdoaWNoIGlmIHRydWUsIGNoZWNrc1xuICogdGhlIE5PREVfRU5WIHZhcmlhYmxlLiBJZiBOT0RFX0VOViBlcXVhbHMgJ3Rlc3QnLCB0aGUgZnVuY3Rpb24gcmV0dXJucyBmYWxzZS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1NlcnZlclNpZGUob3B0aW9ucyA9IHtjaGVja0VudjogdHJ1ZX0pIHtcblx0bGV0IHNlcnZlclNpZGUgPSB0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgIXByb2Nlc3MuYnJvd3Nlcjtcblx0aWYgKHNlcnZlclNpZGUgJiYgb3B0aW9ucy5jaGVja0Vudikge1xuXHRcdHNlcnZlclNpZGUgPVxuXHRcdFx0dHlwZW9mIHByb2Nlc3MuZW52ICE9PSAndW5kZWZpbmVkJyAmJlxuXHRcdFx0cHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICd0ZXN0Jztcblx0fVxuXHRyZXR1cm4gc2VydmVyU2lkZTtcbn1cblxuLyoqXG4gKiBOdWxsIGZ1bmN0aW9uIHVzZWQgZm9yIGRlZmF1bHQgdmFsdWVzIG9mIGNhbGxiYWNrcywgZXRjLlxuICogQHJldHVybiB7dm9pZH0gTm90aGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG51bGxGdW5jdGlvbigpIHt9XG4iLCIndXNlIHN0cmljdCc7XG5cbi8vIFRoaXMgZmlsZSBleGlzdHMganVzdCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHksIG1ha2luZyBzdXJlIHRoYXQgb2xkXG4vLyBkZWZhdWx0IGltcG9ydHMgZm9yIHRoaXMgZmlsZSBzdGlsbCB3b3JrLiBJdCdzIGJlc3QgdG8gdXNlIHRoZSBuYW1lZCBleHBvcnRzXG4vLyBmb3IgZWFjaCBmdW5jdGlvbiBpbnN0ZWFkIHRob3VnaCwgc2luY2UgdGhhdCBhbGxvd3MgYnVuZGxlcnMgbGlrZSBSb2xsdXAgdG9cbi8vIHJlZHVjZSB0aGUgYnVuZGxlIHNpemUgYnkgcmVtb3ZpbmcgdW51c2VkIGNvZGUuXG5pbXBvcnQgKiBhcyBjb3JlIGZyb20gJy4vY29yZU5hbWVkJztcblxuZXhwb3J0IGRlZmF1bHQgY29yZTtcbmV4cG9ydCB7Y29yZX07XG5leHBvcnQgKiBmcm9tICcuL2NvcmVOYW1lZCc7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogU2V0IG9mIHV0aWxpdGllcyBmb3IgYXJyYXkgb3BlcmF0aW9uc1xuICovXG5jbGFzcyBhcnJheSB7XG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGFycmF5cyBoYXZlIHRoZSBzYW1lIGNvbnRlbnQuXG5cdCAqIEBwYXJhbSB7IUFycmF5PCo+fSBhcnIxXG5cdCAqIEBwYXJhbSB7IUFycmF5PCo+fSBhcnIyXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRzdGF0aWMgZXF1YWwoYXJyMSwgYXJyMikge1xuXHRcdGlmIChhcnIxID09PSBhcnIyKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0aWYgKGFycjEubGVuZ3RoICE9PSBhcnIyLmxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFycjEubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChhcnIxW2ldICE9PSBhcnIyW2ldKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgZmlyc3QgdmFsdWUgaW4gdGhlIGdpdmVuIGFycmF5IHRoYXQgaXNuJ3QgdW5kZWZpbmVkLlxuXHQgKiBAcGFyYW0geyFBcnJheX0gYXJyXG5cdCAqIEByZXR1cm4geyp9XG5cdCAqL1xuXHRzdGF0aWMgZmlyc3REZWZpbmVkVmFsdWUoYXJyKSB7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChhcnJbaV0gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRyZXR1cm4gYXJyW2ldO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBUcmFuc2Zvcm1zIHRoZSBpbnB1dCBuZXN0ZWQgYXJyYXkgdG8gYmVjb21lIGZsYXQuXG5cdCAqIEBwYXJhbSB7QXJyYXkuPCp8QXJyYXkuPCo+Pn0gYXJyIE5lc3RlZCBhcnJheSB0byBmbGF0dGVuLlxuXHQgKiBAcGFyYW0ge0FycmF5LjwqPj19IG91dHB1dCBPcHRpb25hbCBvdXRwdXQgYXJyYXkuXG5cdCAqIEByZXR1cm4ge0FycmF5LjwqPn0gRmxhdCBhcnJheS5cblx0ICovXG5cdHN0YXRpYyBmbGF0dGVuKGFyciwgb3V0cHV0ID0gW10pIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKEFycmF5LmlzQXJyYXkoYXJyW2ldKSkge1xuXHRcdFx0XHRhcnJheS5mbGF0dGVuKGFycltpXSwgb3V0cHV0KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG91dHB1dC5wdXNoKGFycltpXSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBvdXRwdXQ7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBhIHBhcnRpY3VsYXIgdmFsdWUgZnJvbSBhbiBhcnJheS5cblx0ICogQHBhcmFtIHtBcnJheS48VD59IGFyciBBcnJheSBmcm9tIHdoaWNoIHRvIHJlbW92ZSB2YWx1ZS5cblx0ICogQHBhcmFtIHtUfSBvYmogT2JqZWN0IHRvIHJlbW92ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhbiBlbGVtZW50IHdhcyByZW1vdmVkLlxuXHQgKiBAdGVtcGxhdGUgVFxuXHQgKi9cblx0c3RhdGljIHJlbW92ZShhcnIsIG9iaikge1xuXHRcdGNvbnN0IGkgPSBhcnIuaW5kZXhPZihvYmopO1xuXHRcdGxldCBydjtcblx0XHRpZiAoKHJ2ID0gaSA+PSAwKSkge1xuXHRcdFx0YXJyYXkucmVtb3ZlQXQoYXJyLCBpKTtcblx0XHR9XG5cdFx0cmV0dXJuIHJ2O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgZnJvbSBhbiBhcnJheSB0aGUgZWxlbWVudCBhdCBpbmRleCBpXG5cdCAqIEBwYXJhbSB7QXJyYXl9IGFyciBBcnJheSBvciBhcnJheSBsaWtlIG9iamVjdCBmcm9tIHdoaWNoIHRvIHJlbW92ZSB2YWx1ZS5cblx0ICogQHBhcmFtIHtudW1iZXJ9IGkgVGhlIGluZGV4IHRvIHJlbW92ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhbiBlbGVtZW50IHdhcyByZW1vdmVkLlxuXHQgKi9cblx0c3RhdGljIHJlbW92ZUF0KGFyciwgaSkge1xuXHRcdHJldHVybiBBcnJheS5wcm90b3R5cGUuc3BsaWNlLmNhbGwoYXJyLCBpLCAxKS5sZW5ndGggPT09IDE7XG5cdH1cblxuXHQvKipcblx0ICogU2xpY2VzIHRoZSBnaXZlbiBhcnJheSwganVzdCBsaWtlIEFycmF5LnByb3RvdHlwZS5zbGljZSwgYnV0IHRoaXNcblx0ICogaXMgZmFzdGVyIGFuZCB3b3JraW5nIG9uIGFsbCBhcnJheS1saWtlIG9iamVjdHMgKGxpa2UgYXJndW1lbnRzKS5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBhcnIgQXJyYXktbGlrZSBvYmplY3QgdG8gc2xpY2UuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydCBUaGUgaW5kZXggdGhhdCBzaG91bGQgc3RhcnQgdGhlIHNsaWNlLlxuXHQgKiBAcGFyYW0ge251bWJlcj19IGVuZCBUaGUgaW5kZXggd2hlcmUgdGhlIHNsaWNlIHNob3VsZCBlbmQsIG5vdFxuXHQgKiAgIGluY2x1ZGVkIGluIHRoZSBmaW5hbCBhcnJheS4gSWYgbm90IGdpdmVuLCBhbGwgZWxlbWVudHMgYWZ0ZXIgdGhlXG5cdCAqICAgc3RhcnQgaW5kZXggd2lsbCBiZSBpbmNsdWRlZC5cblx0ICogQHJldHVybiB7IUFycmF5fVxuXHQgKi9cblx0c3RhdGljIHNsaWNlKGFyciwgc3RhcnQsIGVuZCA9IGFyci5sZW5ndGgpIHtcblx0XHRjb25zdCBzbGljZWQgPSBbXTtcblx0XHRmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuXHRcdFx0c2xpY2VkLnB1c2goYXJyW2ldKTtcblx0XHR9XG5cdFx0cmV0dXJuIHNsaWNlZDtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBhcnJheTtcbiIsIi8qICFcbiAqIFBvbHlmaWxsIGZyb20gR29vZ2xlJ3MgQ2xvc3VyZSBMaWJyYXJ5LlxuICogQ29weXJpZ2h0IDIwMTMgVGhlIENsb3N1cmUgTGlicmFyeSBBdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHtpc1NlcnZlclNpZGV9IGZyb20gJy4uL2NvcmVOYW1lZCc7XG5cbmNvbnN0IGFzeW5jID0ge307XG5cbi8qKlxuICogVGhyb3cgYW4gaXRlbSB3aXRob3V0IGludGVycnVwdGluZyB0aGUgY3VycmVudCBleGVjdXRpb24gY29udGV4dC4gIEZvclxuICogZXhhbXBsZSwgaWYgcHJvY2Vzc2luZyBhIGdyb3VwIG9mIGl0ZW1zIGluIGEgbG9vcCwgc29tZXRpbWVzIGl0IGlzIHVzZWZ1bFxuICogdG8gcmVwb3J0IGFuIGVycm9yIHdoaWxlIHN0aWxsIGFsbG93aW5nIHRoZSByZXN0IG9mIHRoZSBiYXRjaCB0byBiZVxuICogcHJvY2Vzc2VkLlxuICogQHBhcmFtIHsqfSBleGNlcHRpb25cbiAqL1xuYXN5bmMudGhyb3dFeGNlcHRpb24gPSBmdW5jdGlvbihleGNlcHRpb24pIHtcblx0Ly8gRWFjaCB0aHJvdyBuZWVkcyB0byBiZSBpbiBpdHMgb3duIGNvbnRleHQuXG5cdGFzeW5jLm5leHRUaWNrKGZ1bmN0aW9uKCkge1xuXHRcdHRocm93IGV4Y2VwdGlvbjtcblx0fSk7XG59O1xuXG4vKipcbiAqIEZpcmVzIHRoZSBwcm92aWRlZCBjYWxsYmFjayBqdXN0IGJlZm9yZSB0aGUgY3VycmVudCBjYWxsc3RhY2sgdW53aW5kcywgb3IgYXNcbiAqIHNvb24gYXMgcG9zc2libGUgYWZ0ZXIgdGhlIGN1cnJlbnQgSlMgZXhlY3V0aW9uIGNvbnRleHQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKHRoaXM6VEhJUyl9IGNhbGxiYWNrXG4gKiBAcGFyYW0ge1RISVM9fSBjb250ZXh0IE9iamVjdCB0byB1c2UgYXMgdGhlIFwidGhpcyB2YWx1ZVwiIHdoZW4gY2FsbGluZ1xuICogICAgIHRoZSBwcm92aWRlZCBmdW5jdGlvbi5cbiAqIEB0ZW1wbGF0ZSBUSElTXG4gKi9cbmFzeW5jLnJ1biA9IGZ1bmN0aW9uKGNhbGxiYWNrLCBjb250ZXh0KSB7XG5cdGlmICghYXN5bmMucnVuLndvcmtRdWV1ZVNjaGVkdWxlZF8pIHtcblx0XHQvLyBOb3RoaW5nIGlzIGN1cnJlbnRseSBzY2hlZHVsZWQsIHNjaGVkdWxlIGl0IG5vdy5cblx0XHRhc3luYy5uZXh0VGljayhhc3luYy5ydW4ucHJvY2Vzc1dvcmtRdWV1ZSk7XG5cdFx0YXN5bmMucnVuLndvcmtRdWV1ZVNjaGVkdWxlZF8gPSB0cnVlO1xuXHR9XG5cblx0YXN5bmMucnVuLndvcmtRdWV1ZV8ucHVzaChuZXcgYXN5bmMucnVuLldvcmtJdGVtXyhjYWxsYmFjaywgY29udGV4dCkpO1xufTtcblxuLyoqIEBwcml2YXRlIHtib29sZWFufSAqL1xuYXN5bmMucnVuLndvcmtRdWV1ZVNjaGVkdWxlZF8gPSBmYWxzZTtcblxuLyoqIEBwcml2YXRlIHshQXJyYXkuPCFhc3luYy5ydW4uV29ya0l0ZW1fPn0gKi9cbmFzeW5jLnJ1bi53b3JrUXVldWVfID0gW107XG5cbi8qKlxuICogUnVuIGFueSBwZW5kaW5nIGFzeW5jLnJ1biB3b3JrIGl0ZW1zLiBUaGlzIGZ1bmN0aW9uIGlzIG5vdCBpbnRlbmRlZFxuICogZm9yIGdlbmVyYWwgdXNlLCBidXQgZm9yIHVzZSBieSBlbnRyeSBwb2ludCBoYW5kbGVycyB0byBydW4gaXRlbXMgYWhlYWQgb2ZcbiAqIGFzeW5jLm5leHRUaWNrLlxuICovXG5hc3luYy5ydW4ucHJvY2Vzc1dvcmtRdWV1ZSA9IGZ1bmN0aW9uKCkge1xuXHQvLyBOT1RFOiBhZGRpdGlvbmFsIHdvcmsgcXVldWUgaXRlbXMgbWF5IGJlIHB1c2hlZCB3aGlsZSBwcm9jZXNzaW5nLlxuXHR3aGlsZSAoYXN5bmMucnVuLndvcmtRdWV1ZV8ubGVuZ3RoKSB7XG5cdFx0Ly8gRG9uJ3QgbGV0IHRoZSB3b3JrIHF1ZXVlIGdyb3cgaW5kZWZpbml0ZWx5LlxuXHRcdGNvbnN0IHdvcmtJdGVtcyA9IGFzeW5jLnJ1bi53b3JrUXVldWVfO1xuXHRcdGFzeW5jLnJ1bi53b3JrUXVldWVfID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB3b3JrSXRlbXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IHdvcmtJdGVtID0gd29ya0l0ZW1zW2ldO1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0d29ya0l0ZW0uZm4uY2FsbCh3b3JrSXRlbS5zY29wZSk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdGFzeW5jLnRocm93RXhjZXB0aW9uKGUpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIFRoZXJlIGFyZSBubyBtb3JlIHdvcmsgaXRlbXMsIHJlc2V0IHRoZSB3b3JrIHF1ZXVlLlxuXHRhc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXyA9IGZhbHNlO1xufTtcblxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqIEBmaW5hbFxuICogQHN0cnVjdFxuICogQHByaXZhdGVcbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGZuXG4gKiBAcGFyYW0ge09iamVjdHxudWxsfHVuZGVmaW5lZH0gc2NvcGVcbiAqL1xuYXN5bmMucnVuLldvcmtJdGVtXyA9IGZ1bmN0aW9uKGZuLCBzY29wZSkge1xuXHQvKiogQGNvbnN0ICovXG5cdHRoaXMuZm4gPSBmbjtcblx0LyoqIEBjb25zdCAqL1xuXHR0aGlzLnNjb3BlID0gc2NvcGU7XG59O1xuXG4vKipcbiAqIEZpcmVzIHRoZSBwcm92aWRlZCBjYWxsYmFja3MgYXMgc29vbiBhcyBwb3NzaWJsZSBhZnRlciB0aGUgY3VycmVudCBKU1xuICogZXhlY3V0aW9uIGNvbnRleHQuIHNldFRpbWVvdXQo4oCmLCAwKSBhbHdheXMgdGFrZXMgYXQgbGVhc3QgNW1zIGZvciBsZWdhY3lcbiAqIHJlYXNvbnMuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKHRoaXM6U0NPUEUpfSBjYWxsYmFjayBDYWxsYmFjayBmdW5jdGlvbiB0byBmaXJlIGFzIHNvb24gYXNcbiAqICAgICBwb3NzaWJsZS5cbiAqIEBwYXJhbSB7U0NPUEU9fSBjb250ZXh0IE9iamVjdCBpbiB3aG9zZSBzY29wZSB0byBjYWxsIHRoZSBsaXN0ZW5lci5cbiAqIEB0ZW1wbGF0ZSBTQ09QRVxuICovXG5hc3luYy5uZXh0VGljayA9IGZ1bmN0aW9uKGNhbGxiYWNrLCBjb250ZXh0KSB7XG5cdGxldCBjYiA9IGNhbGxiYWNrO1xuXHRpZiAoY29udGV4dCkge1xuXHRcdGNiID0gY2FsbGJhY2suYmluZChjb250ZXh0KTtcblx0fVxuXHRjYiA9IGFzeW5jLm5leHRUaWNrLndyYXBDYWxsYmFja18oY2IpO1xuXHQvLyBMb29rIGZvciBhbmQgY2FjaGUgdGhlIGN1c3RvbSBmYWxsYmFjayB2ZXJzaW9uIG9mIHNldEltbWVkaWF0ZS5cblx0aWYgKCFhc3luYy5uZXh0VGljay5zZXRJbW1lZGlhdGVfKSB7XG5cdFx0aWYgKFxuXHRcdFx0dHlwZW9mIHNldEltbWVkaWF0ZSA9PT0gJ2Z1bmN0aW9uJyAmJlxuXHRcdFx0aXNTZXJ2ZXJTaWRlKHtjaGVja0VudjogZmFsc2V9KVxuXHRcdCkge1xuXHRcdFx0YXN5bmMubmV4dFRpY2suc2V0SW1tZWRpYXRlXyA9IHNldEltbWVkaWF0ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cdFx0XHRhc3luYy5uZXh0VGljay5zZXRJbW1lZGlhdGVfID0gYXN5bmMubmV4dFRpY2suZ2V0U2V0SW1tZWRpYXRlRW11bGF0b3JfKCk7XG5cdFx0fVxuXHR9XG5cdGFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8oY2IpO1xufTtcblxuLyoqXG4gKiBDYWNoZSBmb3IgdGhlIHNldEltbWVkaWF0ZSBpbXBsZW1lbnRhdGlvbi5cbiAqIEB0eXBlIHtmdW5jdGlvbihmdW5jdGlvbigpKX1cbiAqIEBwcml2YXRlXG4gKi9cbmFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8gPSBudWxsO1xuXG4vKipcbiAqIERldGVybWluZXMgdGhlIGJlc3QgcG9zc2libGUgaW1wbGVtZW50YXRpb24gdG8gcnVuIGEgZnVuY3Rpb24gYXMgc29vbiBhc1xuICogdGhlIEpTIGV2ZW50IGxvb3AgaXMgaWRsZS5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGZ1bmN0aW9uKCkpfSBUaGUgXCJzZXRJbW1lZGlhdGVcIiBpbXBsZW1lbnRhdGlvbi5cbiAqIEBwcml2YXRlXG4gKi9cbmFzeW5jLm5leHRUaWNrLmdldFNldEltbWVkaWF0ZUVtdWxhdG9yXyA9IGZ1bmN0aW9uKCkge1xuXHQvLyBDcmVhdGUgYSBwcml2YXRlIG1lc3NhZ2UgY2hhbm5lbCBhbmQgdXNlIGl0IHRvIHBvc3RNZXNzYWdlIGVtcHR5IG1lc3NhZ2VzXG5cdC8vIHRvIG91cnNlbHZlcy5cblx0bGV0IENoYW5uZWw7XG5cblx0Ly8gVmVyaWZ5IGlmIHZhcmlhYmxlIGlzIGRlZmluZWQgb24gdGhlIGN1cnJlbnQgcnVudGltZSAoaS5lLiwgbm9kZSwgYnJvd3NlcikuXG5cdC8vIENhbid0IHVzZSB0eXBlb2YgZW5jbG9zZWQgaW4gYSBmdW5jdGlvbiAoc3VjaCBhcyBjb3JlLmlzRnVuY3Rpb24pIG9yIGFuXG5cdC8vIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93biB3aGVuIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQgb24gYW4gZW52aXJvbm1lbnRcblx0Ly8gd2hlcmUgdGhlIHZhcmlhYmxlIGlzIHVuZGVmaW5lZC5cblx0aWYgKHR5cGVvZiBNZXNzYWdlQ2hhbm5lbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdENoYW5uZWwgPSBNZXNzYWdlQ2hhbm5lbDtcblx0fVxuXG5cdC8vIElmIE1lc3NhZ2VDaGFubmVsIGlzIG5vdCBhdmFpbGFibGUgYW5kIHdlIGFyZSBpbiBhIGJyb3dzZXIsIGltcGxlbWVudFxuXHQvLyBhbiBpZnJhbWUgYmFzZWQgcG9seWZpbGwgaW4gYnJvd3NlcnMgdGhhdCBoYXZlIHBvc3RNZXNzYWdlIGFuZFxuXHQvLyBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyLiBUaGUgbGF0dGVyIGV4Y2x1ZGVzIElFOCBiZWNhdXNlIGl0IGhhcyBhXG5cdC8vIHN5bmNocm9ub3VzIHBvc3RNZXNzYWdlIGltcGxlbWVudGF0aW9uLlxuXHRpZiAoXG5cdFx0dHlwZW9mIENoYW5uZWwgPT09ICd1bmRlZmluZWQnICYmXG5cdFx0dHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiZcblx0XHR3aW5kb3cucG9zdE1lc3NhZ2UgJiZcblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lclxuXHQpIHtcblx0XHQvKiogQGNvbnN0cnVjdG9yICovXG5cdFx0Q2hhbm5lbCA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0Ly8gTWFrZSBhbiBlbXB0eSwgaW52aXNpYmxlIGlmcmFtZS5cblx0XHRcdGNvbnN0IGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO1xuXHRcdFx0aWZyYW1lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0XHRpZnJhbWUuc3JjID0gJyc7XG5cdFx0XHRpZnJhbWUudGl0bGUgPSAnJztcblx0XHRcdGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZChpZnJhbWUpO1xuXHRcdFx0Y29uc3Qgd2luID0gaWZyYW1lLmNvbnRlbnRXaW5kb3c7XG5cdFx0XHRjb25zdCBkb2MgPSB3aW4uZG9jdW1lbnQ7XG5cdFx0XHRkb2Mub3BlbigpO1xuXHRcdFx0ZG9jLndyaXRlKCcnKTtcblx0XHRcdGRvYy5jbG9zZSgpO1xuXHRcdFx0Y29uc3QgbWVzc2FnZSA9ICdjYWxsSW1tZWRpYXRlJyArIE1hdGgucmFuZG9tKCk7XG5cdFx0XHRjb25zdCBvcmlnaW4gPSB3aW4ubG9jYXRpb24ucHJvdG9jb2wgKyAnLy8nICsgd2luLmxvY2F0aW9uLmhvc3Q7XG5cdFx0XHRjb25zdCBvbm1lc3NhZ2UgPSBmdW5jdGlvbihlKSB7XG5cdFx0XHRcdC8vIFZhbGlkYXRlIG9yaWdpbiBhbmQgbWVzc2FnZSB0byBtYWtlIHN1cmUgdGhhdCB0aGlzIG1lc3NhZ2Ugd2FzXG5cdFx0XHRcdC8vIGludGVuZGVkIGZvciB1cy5cblx0XHRcdFx0aWYgKGUub3JpZ2luICE9PSBvcmlnaW4gJiYgZS5kYXRhICE9PSBtZXNzYWdlKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMucG9ydDEub25tZXNzYWdlKCk7XG5cdFx0XHR9LmJpbmQodGhpcyk7XG5cdFx0XHR3aW4uYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9ubWVzc2FnZSwgZmFsc2UpO1xuXHRcdFx0dGhpcy5wb3J0MSA9IHt9O1xuXHRcdFx0dGhpcy5wb3J0MiA9IHtcblx0XHRcdFx0cG9zdE1lc3NhZ2U6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHdpbi5wb3N0TWVzc2FnZShtZXNzYWdlLCBvcmlnaW4pO1xuXHRcdFx0XHR9LFxuXHRcdFx0fTtcblx0XHR9O1xuXHR9XG5cdGlmICh0eXBlb2YgQ2hhbm5lbCAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRjb25zdCBjaGFubmVsID0gbmV3IENoYW5uZWwoKTtcblx0XHQvLyBVc2UgYSBmaWZvIGxpbmtlZCBsaXN0IHRvIGNhbGwgY2FsbGJhY2tzIGluIHRoZSByaWdodCBvcmRlci5cblx0XHRsZXQgaGVhZCA9IHt9O1xuXHRcdGxldCB0YWlsID0gaGVhZDtcblx0XHRjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0aGVhZCA9IGhlYWQubmV4dDtcblx0XHRcdGNvbnN0IGNiID0gaGVhZC5jYjtcblx0XHRcdGhlYWQuY2IgPSBudWxsO1xuXHRcdFx0Y2IoKTtcblx0XHR9O1xuXHRcdHJldHVybiBmdW5jdGlvbihjYikge1xuXHRcdFx0dGFpbC5uZXh0ID0ge1xuXHRcdFx0XHRjYjogY2IsXG5cdFx0XHR9O1xuXHRcdFx0dGFpbCA9IHRhaWwubmV4dDtcblx0XHRcdGNoYW5uZWwucG9ydDIucG9zdE1lc3NhZ2UoMCk7XG5cdFx0fTtcblx0fVxuXHQvLyBJbXBsZW1lbnRhdGlvbiBmb3IgSUU2LTg6IFNjcmlwdCBlbGVtZW50cyBmaXJlIGFuIGFzeW5jaHJvbm91c1xuXHQvLyBvbnJlYWR5c3RhdGVjaGFuZ2UgZXZlbnQgd2hlbiBpbnNlcnRlZCBpbnRvIHRoZSBET00uXG5cdGlmIChcblx0XHR0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnICYmXG5cdFx0J29ucmVhZHlzdGF0ZWNoYW5nZScgaW4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jylcblx0KSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uKGNiKSB7XG5cdFx0XHRsZXQgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG5cdFx0XHRzY3JpcHQub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdC8vIENsZWFuIHVwIGFuZCBjYWxsIHRoZSBjYWxsYmFjay5cblx0XHRcdFx0c2NyaXB0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG5cdFx0XHRcdHNjcmlwdC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHNjcmlwdCk7XG5cdFx0XHRcdHNjcmlwdCA9IG51bGw7XG5cdFx0XHRcdGNiKCk7XG5cdFx0XHRcdGNiID0gbnVsbDtcblx0XHRcdH07XG5cdFx0XHRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcblx0XHR9O1xuXHR9XG5cdC8vIEZhbGwgYmFjayB0byBzZXRUaW1lb3V0IHdpdGggMC4gSW4gYnJvd3NlcnMgdGhpcyBjcmVhdGVzIGEgZGVsYXkgb2YgNW1zXG5cdC8vIG9yIG1vcmUuXG5cdHJldHVybiBmdW5jdGlvbihjYikge1xuXHRcdHNldFRpbWVvdXQoY2IsIDApO1xuXHR9O1xufTtcblxuLyoqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdGhhdCBpcyBvdmVycmlkZWQgdG8gcHJvdGVjdCBjYWxsYmFja3Mgd2l0aCBlbnRyeSBwb2ludFxuICogbW9uaXRvciBpZiB0aGUgYXBwbGljYXRpb24gbW9uaXRvcnMgZW50cnkgcG9pbnRzLlxuICogQHBhcmFtIHtmdW5jdGlvbigpfSBjYWxsYmFjayBDYWxsYmFjayBmdW5jdGlvbiB0byBmaXJlIGFzIHNvb24gYXMgcG9zc2libGUuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbigpfSBUaGUgd3JhcHBlZCBjYWxsYmFjay5cbiAqIEBwcml2YXRlXG4gKi9cbmFzeW5jLm5leHRUaWNrLndyYXBDYWxsYmFja18gPSBmdW5jdGlvbihjYWxsYmFjaykge1xuXHRyZXR1cm4gY2FsbGJhY2s7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYztcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBEaXNwb3NhYmxlIHV0aWxpdHkuIFdoZW4gaW5oZXJpdGVkIHByb3ZpZGVzIHRoZSBgZGlzcG9zZWAgZnVuY3Rpb24gdG8gaXRzXG4gKiBzdWJjbGFzcywgd2hpY2ggaXMgcmVzcG9uc2libGUgZm9yIGRpc3Bvc2luZyBvZiBhbnkgb2JqZWN0IHJlZmVyZW5jZXNcbiAqIHdoZW4gYW4gaW5zdGFuY2Ugd29uJ3QgYmUgdXNlZCBhbnltb3JlLiBTdWJjbGFzc2VzIHNob3VsZCBvdmVycmlkZVxuICogYGRpc3Bvc2VJbnRlcm5hbGAgdG8gaW1wbGVtZW50IGFueSBzcGVjaWZpYyBkaXNwb3NpbmcgbG9naWMuXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuY2xhc3MgRGlzcG9zYWJsZSB7XG5cdC8qKlxuXHQgKiBEaXNwb3NhYmxlIGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHQvKipcblx0XHQgKiBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBpbnN0YW5jZSBoYXMgYWxyZWFkeSBiZWVuIGRpc3Bvc2VkLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmRpc3Bvc2VkXyA9IGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy4gQ2FsbHMgYGRpc3Bvc2VJbnRlcm5hbGAuXG5cdCAqL1xuXHRkaXNwb3NlKCkge1xuXHRcdGlmICghdGhpcy5kaXNwb3NlZF8pIHtcblx0XHRcdHRoaXMuZGlzcG9zZUludGVybmFsKCk7XG5cdFx0XHR0aGlzLmRpc3Bvc2VkXyA9IHRydWU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFN1YmNsYXNzZXMgc2hvdWxkIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGltcGxlbWVudCBhbnkgc3BlY2lmaWNcblx0ICogZGlzcG9zaW5nIGxvZ2ljIChsaWtlIGNsZWFyaW5nIHJlZmVyZW5jZXMgYW5kIGNhbGxpbmcgYGRpc3Bvc2VgIG9uIG90aGVyXG5cdCAqIGRpc3Bvc2FibGVzKS5cblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHt9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGlzIGluc3RhbmNlIGhhcyBhbHJlYWR5IGJlZW4gZGlzcG9zZWQuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRpc0Rpc3Bvc2VkKCkge1xuXHRcdHJldHVybiB0aGlzLmRpc3Bvc2VkXztcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBEaXNwb3NhYmxlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFNldCBvZiB1dGlsaXRpZXMgZm9yIG9iamVjdCBvcGVyYXRpb25zXG4gKi9cbmNsYXNzIG9iamVjdCB7XG5cdC8qKlxuXHQgKiBDb3BpZXMgYWxsIHRoZSBtZW1iZXJzIG9mIGEgc291cmNlIG9iamVjdCB0byBhIHRhcmdldCBvYmplY3QuXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSB0YXJnZXQgVGFyZ2V0IG9iamVjdC5cblx0ICogQHBhcmFtIHsuLi5PYmplY3R9IHZhcl9hcmdzIFRoZSBvYmplY3RzIGZyb20gd2hpY2ggdmFsdWVzIHdpbGwgYmUgY29waWVkLlxuXHQgKiBAcmV0dXJuIHtPYmplY3R9IFJldHVybnMgdGhlIHRhcmdldCBvYmplY3QgcmVmZXJlbmNlLlxuXHQgKi9cblx0c3RhdGljIG1peGluKHRhcmdldCwgLi4uYXJncykge1xuXHRcdGxldCBrZXk7XG5cdFx0bGV0IHNvdXJjZTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdHNvdXJjZSA9IGFyZ3NbaV07XG5cdFx0XHQvLyBQb3NzaWJsZSBwcm90b3R5cGUgY2hhaW4gbGVhaywgYnJlYWtzIDEgbWV0YWwtZG9tIGFuZFxuXHRcdFx0Ly8gMSBtZXRhbC1pbmNyZW1lbnRhbC1kb20gdGVzdCBpZiBndWFyZC1mb3ItaW4gcnVsZSBpcyBhZGRyZXNzZWRcblx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuXHRcdFx0Zm9yIChrZXkgaW4gc291cmNlKSB7XG5cdFx0XHRcdHRhcmdldFtrZXldID0gc291cmNlW2tleV07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0YXJnZXQ7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbiBvYmplY3QgYmFzZWQgb24gaXRzIGZ1bGx5IHF1YWxpZmllZCBleHRlcm5hbCBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUuXG5cdCAqIEBwYXJhbSB7b2JqZWN0PX0gc2NvcGUgVGhlIG9iamVjdCB3aXRoaW4gd2hpY2ggdG8gbG9vazsgZGVmYXVsdCBpc1xuXHQgKiAgICAgPGNvZGU+d2luZG93PC9jb2RlPi5cblx0ICogQHJldHVybiB7P30gVGhlIHZhbHVlIChvYmplY3Qgb3IgcHJpbWl0aXZlKSBvciwgaWYgbm90IGZvdW5kLCB1bmRlZmluZWQuXG5cdCAqL1xuXHRzdGF0aWMgZ2V0T2JqZWN0QnlOYW1lKG5hbWUsIHNjb3BlID0gd2luZG93KSB7XG5cdFx0Y29uc3QgcGFydHMgPSBuYW1lLnNwbGl0KCcuJyk7XG5cdFx0cmV0dXJuIHBhcnRzLnJlZHVjZSgocGFydCwga2V5KSA9PiBwYXJ0W2tleV0sIHNjb3BlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgbmV3IG9iamVjdCB3aXRoIHRoZSBzYW1lIGtleXMgYXMgdGhlIGdpdmVuIG9uZSwgYnV0IHdpdGhcblx0ICogdGhlaXIgdmFsdWVzIHNldCB0byB0aGUgcmV0dXJuIHZhbHVlcyBvZiB0aGUgc3BlY2lmaWVkIGZ1bmN0aW9uLlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IG9ialxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbihzdHJpbmcsICopfSBmblxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fVxuXHQgKi9cblx0c3RhdGljIG1hcChvYmosIGZuKSB7XG5cdFx0Y29uc3QgbWFwcGVkT2JqID0ge307XG5cdFx0Y29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRtYXBwZWRPYmpba2V5c1tpXV0gPSBmbihrZXlzW2ldLCBvYmpba2V5c1tpXV0pO1xuXHRcdH1cblx0XHRyZXR1cm4gbWFwcGVkT2JqO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgdHdvIGdpdmVuIG9iamVjdHMgYXJlIGVxdWFsLiBUaGlzIGlzIGRvbmUgdmlhIGEgc2hhbGxvd1xuXHQgKiBjaGVjaywgaW5jbHVkaW5nIG9ubHkgdGhlIGtleXMgZGlyZWN0bHkgY29udGFpbmVkIGJ5IHRoZSAyIG9iamVjdHMuXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBvYmoxXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBvYmoyXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRzdGF0aWMgc2hhbGxvd0VxdWFsKG9iajEsIG9iajIpIHtcblx0XHRpZiAob2JqMSA9PT0gb2JqMikge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Y29uc3Qga2V5czEgPSBPYmplY3Qua2V5cyhvYmoxKTtcblx0XHRjb25zdCBrZXlzMiA9IE9iamVjdC5rZXlzKG9iajIpO1xuXHRcdGlmIChrZXlzMS5sZW5ndGggIT09IGtleXMyLmxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwga2V5czEubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChvYmoxW2tleXMxW2ldXSAhPT0gb2JqMltrZXlzMVtpXV0pIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBvYmplY3Q7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogU2V0IG9mIHV0aWxpdGllcyBmb3Igc3RyaW5nIG9wZXJhdGlvbnNcbiAqL1xuY2xhc3Mgc3RyaW5nIHtcblx0LyoqXG5cdCAqIENvbXBhcmVzIHRoZSBnaXZlbiBzdHJpbmdzIHdpdGhvdXQgdGFraW5nIHRoZSBjYXNlIGludG8gYWNjb3VudC5cblx0ICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBzdHIxXG5cdCAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gc3RyMlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9IEVpdGhlciAtMSwgMCBvciAxLCBhY2NvcmRpbmcgdG8gaWYgdGhlIGZpcnN0IHN0cmluZyBpc1xuXHQgKiAgICAgXCJzbWFsbGVyXCIsIGVxdWFsIG9yIFwiYmlnZ2VyXCIgdGhhbiB0aGUgc2Vjb25kIGdpdmVuIHN0cmluZy5cblx0ICovXG5cdHN0YXRpYyBjYXNlSW5zZW5zaXRpdmVDb21wYXJlKHN0cjEsIHN0cjIpIHtcblx0XHRjb25zdCB0ZXN0MSA9IFN0cmluZyhzdHIxKS50b0xvd2VyQ2FzZSgpO1xuXHRcdGNvbnN0IHRlc3QyID0gU3RyaW5nKHN0cjIpLnRvTG93ZXJDYXNlKCk7XG5cblx0XHRpZiAodGVzdDEgPCB0ZXN0Mikge1xuXHRcdFx0cmV0dXJuIC0xO1xuXHRcdH0gZWxzZSBpZiAodGVzdDEgPT09IHRlc3QyKSB7XG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIDE7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGJyZWFraW5nIHNwYWNlcyBmcm9tIHRoZSBsZWZ0IGFuZCByaWdodCBvZiB0aGUgc3RyaW5nIGFuZFxuXHQgKiBjb2xsYXBzZXMgdGhlIHNlcXVlbmNlcyBvZiBicmVha2luZyBzcGFjZXMgaW4gdGhlIG1pZGRsZSBpbnRvIHNpbmdsZSBzcGFjZXMuXG5cdCAqIFRoZSBvcmlnaW5hbCBhbmQgdGhlIHJlc3VsdCBzdHJpbmdzIHJlbmRlciB0aGUgc2FtZSB3YXkgaW4gSFRNTC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHN0ciBBIHN0cmluZyBpbiB3aGljaCB0byBjb2xsYXBzZSBzcGFjZXMuXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gQ29weSBvZiB0aGUgc3RyaW5nIHdpdGggbm9ybWFsaXplZCBicmVha2luZyBzcGFjZXMuXG5cdCAqL1xuXHRzdGF0aWMgY29sbGFwc2VCcmVha2luZ1NwYWNlcyhzdHIpIHtcblx0XHRyZXR1cm4gc3RyXG5cdFx0XHQucmVwbGFjZSgvW1xcdFxcclxcbiBdKy9nLCAnICcpXG5cdFx0XHQucmVwbGFjZSgvXltcXHRcXHJcXG4gXSt8W1xcdFxcclxcbiBdKyQvZywgJycpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEVzY2FwZXMgY2hhcmFjdGVycyBpbiB0aGUgc3RyaW5nIHRoYXQgYXJlIG5vdCBzYWZlIHRvIHVzZSBpbiBhIFJlZ0V4cC5cblx0ICogQHBhcmFtIHsqfSBzdHIgVGhlIHN0cmluZyB0byBlc2NhcGUuIElmIG5vdCBhIHN0cmluZywgaXQgd2lsbCBiZSBjYXN0ZWRcblx0ICogICAgIHRvIG9uZS5cblx0ICogQHJldHVybiB7c3RyaW5nfSBBIFJlZ0V4cCBzYWZlLCBlc2NhcGVkIGNvcHkgb2Yge0Bjb2RlIHN9LlxuXHQgKi9cblx0c3RhdGljIGVzY2FwZVJlZ2V4KHN0cikge1xuXHRcdHJldHVybiBTdHJpbmcoc3RyKVxuXHRcdFx0LnJlcGxhY2UoLyhbLSgpW1xcXXt9Kz8qLiRefCw6IzwhXFxcXF0pL2csICdcXFxcJDEnKVxuXHRcdFx0LnJlcGxhY2UoL1xceDA4L2csICdcXFxceDA4Jyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgc3RyaW5nIHdpdGggYXQgbGVhc3QgNjQtYml0cyBvZiByYW5kb21uZXNzLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IEEgcmFuZG9tIHN0cmluZywgZS5nLiBzbjFzN3ZiNGdjaWMuXG5cdCAqL1xuXHRzdGF0aWMgZ2V0UmFuZG9tU3RyaW5nKCkge1xuXHRcdGNvbnN0IHggPSAyMTQ3NDgzNjQ4O1xuXHRcdHJldHVybiAoXG5cdFx0XHRNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB4KS50b1N0cmluZygzNikgK1xuXHRcdFx0TWF0aC5hYnMoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogeCkgXiBEYXRlLm5vdygpKS50b1N0cmluZygzNilcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGN1bGF0ZXMgdGhlIGhhc2hjb2RlIGZvciBhIHN0cmluZy4gVGhlIGhhc2hjb2RlIHZhbHVlIGlzIGNvbXB1dGVkIGJ5XG5cdCAqIHRoZSBzdW0gYWxnb3JpdGhtOiBzWzBdKjMxXihuLTEpICsgc1sxXSozMV4obi0yKSArIC4uLiArIHNbbi0xXS4gQSBuaWNlXG5cdCAqIHByb3BlcnR5IG9mIHVzaW5nIDMxIHByaW1lIGlzIHRoYXQgdGhlIG11bHRpcGxpY2F0aW9uIGNhbiBiZSByZXBsYWNlZCBieVxuXHQgKiBhIHNoaWZ0IGFuZCBhIHN1YnRyYWN0aW9uIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2U6IDMxKmkgPT0gKGk8PDUpLWkuXG5cdCAqIE1vZGVybiBWTXMgZG8gdGhpcyBzb3J0IG9mIG9wdGltaXphdGlvbiBhdXRvbWF0aWNhbGx5LlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdmFsIFRhcmdldCBzdHJpbmcuXG5cdCAqIEByZXR1cm4ge051bWJlcn0gUmV0dXJucyB0aGUgc3RyaW5nIGhhc2hjb2RlLlxuXHQgKi9cblx0c3RhdGljIGhhc2hDb2RlKHZhbCkge1xuXHRcdGxldCBoYXNoID0gMDtcblx0XHRmb3IgKGxldCBpID0gMCwgbGVuID0gdmFsLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRoYXNoID0gMzEgKiBoYXNoICsgdmFsLmNoYXJDb2RlQXQoaSk7XG5cdFx0XHRoYXNoICU9IDB4MTAwMDAwMDAwO1xuXHRcdH1cblx0XHRyZXR1cm4gaGFzaDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXBsYWNlcyBpbnRlcnZhbCBpbnRvIHRoZSBzdHJpbmcgd2l0aCBzcGVjaWZpZWQgdmFsdWUsIGUuZy5cblx0ICogYHJlcGxhY2VJbnRlcnZhbChcImFiY2RlXCIsIDEsIDQsIFwiXCIpYCByZXR1cm5zIFwiYWVcIi5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHN0ciBUaGUgaW5wdXQgc3RyaW5nLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gc3RhcnQgU3RhcnQgaW50ZXJ2YWwgcG9zaXRpb24gdG8gYmUgcmVwbGFjZWQuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBlbmQgRW5kIGludGVydmFsIHBvc2l0aW9uIHRvIGJlIHJlcGxhY2VkLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVGhlIHZhbHVlIHRoYXQgcmVwbGFjZXMgdGhlIHNwZWNpZmllZCBpbnRlcnZhbC5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0c3RhdGljIHJlcGxhY2VJbnRlcnZhbChzdHIsIHN0YXJ0LCBlbmQsIHZhbHVlKSB7XG5cdFx0cmV0dXJuIHN0ci5zdWJzdHJpbmcoMCwgc3RhcnQpICsgdmFsdWUgKyBzdHIuc3Vic3RyaW5nKGVuZCk7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgc3RyaW5nO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2lzRGVmfSBmcm9tICdtZXRhbCc7XG5cbmNvbnN0IE1FVEFMX0RBVEEgPSAnX19tZXRhbF9kYXRhX18nO1xuXG4vKipcbiAqIFNldCBvZiB1dGlsaXRpZXMgZm9yIGRvbSBkYXRhIG9wZXJhdGlvbnNcbiAqL1xuY2xhc3MgZG9tRGF0YSB7XG5cdC8qKlxuXHQgKiBHZXRzIE1ldGFsLmpzJ3MgZGF0YSBmb3IgdGhlIGdpdmVuIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHBhcmFtIHtzdHJpbmc9fSBuYW1lIE9wdGlvbmFsIHByb3BlcnR5IGZyb20gdGhlIGRhdGEgdG8gYmUgcmV0dXJuZWQuXG5cdCAqIEBwYXJhbSB7Kj19IGluaXRpYWxWYWx1ZSBPcHRpb25hbCB2YWx1ZSB0byB0aGUgc2V0IHRoZSByZXF1ZXN0ZWQgcHJvcGVydHlcblx0ICogICAgIHRvIGlmIGl0IGRvZXNuJ3QgZXhpc3QgeWV0IGluIHRoZSBkYXRhLlxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fVxuXHQgKi9cblx0c3RhdGljIGdldChlbGVtZW50LCBuYW1lLCBpbml0aWFsVmFsdWUpIHtcblx0XHRpZiAoIWVsZW1lbnRbTUVUQUxfREFUQV0pIHtcblx0XHRcdGVsZW1lbnRbTUVUQUxfREFUQV0gPSB7fTtcblx0XHR9XG5cdFx0aWYgKCFuYW1lKSB7XG5cdFx0XHRyZXR1cm4gZWxlbWVudFtNRVRBTF9EQVRBXTtcblx0XHR9XG5cdFx0aWYgKCFpc0RlZihlbGVtZW50W01FVEFMX0RBVEFdW25hbWVdKSAmJiBpc0RlZihpbml0aWFsVmFsdWUpKSB7XG5cdFx0XHRlbGVtZW50W01FVEFMX0RBVEFdW25hbWVdID0gaW5pdGlhbFZhbHVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZWxlbWVudFtNRVRBTF9EQVRBXVtuYW1lXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGVsZW1lbnQgaGFzIGRhdGEgc3RvcmVkIGluIGl0LlxuXHQgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRzdGF0aWMgaGFzKGVsZW1lbnQpIHtcblx0XHRyZXR1cm4gISFlbGVtZW50W01FVEFMX0RBVEFdO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgTWV0YWwuanMncyBkYXRhIGZvciB0aGUgZ2l2ZW4gZWxlbWVudC5cblx0ICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuXHQgKiBAcGFyYW0ge3N0cmluZz19IG5hbWUgUHJvcGVydHkgZnJvbSB0aGUgZGF0YSB0byBiZSBzZXQuXG5cdCAqIEBwYXJhbSB7Kj19IHZhbHVlIFZhbHVlIHRvIGJlIHNldCBvbiB0aGUgZWxlbWVudC5cblx0ICogQHJldHVybiB7IU9iamVjdHwqfVxuXHQgKi9cblx0c3RhdGljIHNldChlbGVtZW50LCBuYW1lLCB2YWx1ZSkge1xuXHRcdGlmICghZWxlbWVudFtNRVRBTF9EQVRBXSkge1xuXHRcdFx0ZWxlbWVudFtNRVRBTF9EQVRBXSA9IHt9O1xuXHRcdH1cblx0XHRpZiAoIW5hbWUgfHwgIWlzRGVmKHZhbHVlKSkge1xuXHRcdFx0cmV0dXJuIGVsZW1lbnRbTUVUQUxfREFUQV07XG5cdFx0fVxuXHRcdGVsZW1lbnRbTUVUQUxfREFUQV1bbmFtZV0gPSB2YWx1ZTtcblx0XHRyZXR1cm4gZWxlbWVudFtNRVRBTF9EQVRBXVtuYW1lXTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBkb21EYXRhO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge0Rpc3Bvc2FibGV9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBFdmVudEhhbmRsZSB1dGlsaXR5LiBIb2xkcyBpbmZvcm1hdGlvbiBhYm91dCBhbiBldmVudCBzdWJzY3JpcHRpb24sIGFuZFxuICogYWxsb3dzIHJlbW92aW5nIHRoZW0gZWFzaWx5LlxuICogRXZlbnRIYW5kbGUgaXMgYSBEaXNwb3NhYmxlLCBidXQgaXQncyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHRoZVxuICogRXZlbnRFbWl0dGVyIHRoYXQgY3JlYXRlZCBpdCBpcyBub3QgdGhlIG9uZSByZXNwb25zaWJsZSBmb3IgZGlzcG9zaW5nIGl0LlxuICogVGhhdCByZXNwb25zaWJpbGl0eSBpcyBmb3IgdGhlIGNvZGUgdGhhdCBob2xkcyBhIHJlZmVyZW5jZSB0byBpdC5cbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEhhbmRsZSBleHRlbmRzIERpc3Bvc2FibGUge1xuXHQvKipcblx0ICogRXZlbnRIYW5kbGUgY29uc3RydWN0b3Jcblx0ICogQHBhcmFtIHshRXZlbnRFbWl0dGVyfSBlbWl0dGVyIEVtaXR0ZXIgdGhlIGV2ZW50IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnQgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRoYXQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lciBUaGUgbGlzdGVuZXIgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnQuXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihlbWl0dGVyLCBldmVudCwgbGlzdGVuZXIpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIEV2ZW50RW1pdHRlciBpbnN0YW5jZSB0aGF0IHRoZSBldmVudCB3YXMgc3Vic2NyaWJlZCB0by5cblx0XHQgKiBAdHlwZSB7RXZlbnRFbWl0dGVyfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmVtaXR0ZXJfID0gZW1pdHRlcjtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0aGF0IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHRcdCAqIEB0eXBlIHtzdHJpbmd9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZXZlbnRfID0gZXZlbnQ7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgbGlzdGVuZXIgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnQuXG5cdFx0ICogQHR5cGUge0Z1bmN0aW9ufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmxpc3RlbmVyXyA9IGxpc3RlbmVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy5cblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdHRoaXMuZW1pdHRlcl8gPSBudWxsO1xuXHRcdHRoaXMubGlzdGVuZXJfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHRoZSBsaXN0ZW5lciBzdWJzY3JpcHRpb24gZnJvbSB0aGUgZW1pdHRlci5cblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyKCkge1xuXHRcdGlmICghdGhpcy5lbWl0dGVyXy5pc0Rpc3Bvc2VkKCkpIHtcblx0XHRcdHRoaXMuZW1pdHRlcl8ucmVtb3ZlTGlzdGVuZXIodGhpcy5ldmVudF8sIHRoaXMubGlzdGVuZXJfKTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRXZlbnRIYW5kbGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXJyYXksIERpc3Bvc2FibGUsIGlzRnVuY3Rpb24sIGlzU3RyaW5nfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgRXZlbnRIYW5kbGUgZnJvbSAnLi9FdmVudEhhbmRsZSc7XG5cbmNvbnN0IHNpbmdsZUFycmF5XyA9IFswXTtcblxuLyoqXG4gKiBFdmVudEVtaXR0ZXIgdXRpbGl0eS5cbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEVtaXR0ZXIgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblx0LyoqXG5cdCAqIEV2ZW50RW1pdHRlciBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGV2ZW50IGxpc3RlbmVycyBzY29wZWQgYnkgZXZlbnQgdHlwZS5cblx0XHQgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgIUFycmF5PCFmdW5jdGlvbigpPj59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZXZlbnRzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIYW5kbGVycyB0aGF0IGFyZSB0cmlnZ2VyZWQgd2hlbiBhbiBldmVudCBpcyBsaXN0ZW5lZCB0by5cblx0XHQgKiBAdHlwZSB7QXJyYXl9XG5cdFx0ICovXG5cdFx0dGhpcy5saXN0ZW5lckhhbmRsZXJzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBDb25maWd1cmF0aW9uIG9wdGlvbiB3aGljaCBkZXRlcm1pbmVzIGlmIGFuIGV2ZW50IGZhY2FkZSBzaG91bGQgYmUgc2VudFxuXHRcdCAqIGFzIGEgcGFyYW0gb2YgbGlzdGVuZXJzIHdoZW4gZW1pdHRpbmcgZXZlbnRzLiBJZiBzZXQgdG8gdHJ1ZSwgdGhlIGZhY2FkZVxuXHRcdCAqIHdpbGwgYmUgcGFzc2VkIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBvZiB0aGUgbGlzdGVuZXIuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuc2hvdWxkVXNlRmFjYWRlXyA9IGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBoYW5kbGVyIHRvIGdpdmVuIGhvbGRlciB2YXJpYWJsZS4gSWYgdGhlIGhvbGRlciBkb2Vzbid0IGhhdmUgYVxuXHQgKiB2YWx1ZSB5ZXQsIGl0IHdpbGwgcmVjZWl2ZSB0aGUgaGFuZGxlciBkaXJlY3RseS4gSWYgdGhlIGhvbGRlciBpcyBhbiBhcnJheSxcblx0ICogdGhlIHZhbHVlIHdpbGwganVzdCBiZSBhZGRlZCB0byBpdC4gT3RoZXJ3aXNlLCB0aGUgaG9sZGVyIHdpbGwgYmUgc2V0IHRvIGFcblx0ICogbmV3IGFycmF5IGNvbnRhaW5pbmcgaXRzIHByZXZpb3VzIHZhbHVlIHBsdXMgdGhlIG5ldyBoYW5kbGVyLlxuXHQgKiBAcGFyYW0geyp9IGhvbGRlclxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbigpfE9iamVjdH0gaGFuZGxlclxuXHQgKiBAcmV0dXJuIHsqfSBUaGUgaG9sZGVyJ3MgbmV3IHZhbHVlLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRhZGRIYW5kbGVyXyhob2xkZXIsIGhhbmRsZXIpIHtcblx0XHRpZiAoIWhvbGRlcikge1xuXHRcdFx0aG9sZGVyID0gaGFuZGxlcjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCFBcnJheS5pc0FycmF5KGhvbGRlcikpIHtcblx0XHRcdFx0aG9sZGVyID0gW2hvbGRlcl07XG5cdFx0XHR9XG5cdFx0XHRob2xkZXIucHVzaChoYW5kbGVyKTtcblx0XHR9XG5cdFx0cmV0dXJuIGhvbGRlcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQHBhcmFtIHshKEFycmF5fHN0cmluZyl9IGV2ZW50XG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IGRlZmF1bHRMaXN0ZW5lciBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBsaXN0ZW5lciBpcyBhIGRlZmF1bHRcblx0ICogICBhY3Rpb24gZm9yIHRoaXMgZXZlbnQuIERlZmF1bHQgYWN0aW9ucyBhcmUgcnVuIGxhc3QsIGFuZCBvbmx5IGlmIG5vIHByZXZpb3VzXG5cdCAqICAgbGlzdGVuZXIgY2FsbCBgcHJldmVudERlZmF1bHQoKWAgb24gdGhlIHJlY2VpdmVkIGV2ZW50IGZhY2FkZS5cblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuXHQgKi9cblx0YWRkTGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyLCBkZWZhdWx0TGlzdGVuZXIpIHtcblx0XHR0aGlzLnZhbGlkYXRlTGlzdGVuZXJfKGxpc3RlbmVyKTtcblxuXHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMudG9FdmVudHNBcnJheV8oZXZlbnQpO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmFkZFNpbmdsZUxpc3RlbmVyXyhldmVudHNbaV0sIGxpc3RlbmVyLCBkZWZhdWx0TGlzdGVuZXIpO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgRXZlbnRIYW5kbGUodGhpcywgZXZlbnQsIGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciBhIHNpbmdsZSBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IGRlZmF1bHRMaXN0ZW5lciBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBsaXN0ZW5lciBpcyBhIGRlZmF1bHRcblx0ICogICBhY3Rpb24gZm9yIHRoaXMgZXZlbnQuIERlZmF1bHQgYWN0aW9ucyBhcmUgcnVuIGxhc3QsIGFuZCBvbmx5IGlmIG5vIHByZXZpb3VzXG5cdCAqICAgbGlzdGVuZXIgY2FsbCBgcHJldmVudERlZmF1bHQoKWAgb24gdGhlIHJlY2VpdmVkIGV2ZW50IGZhY2FkZS5cblx0ICogQHBhcmFtIHtGdW5jdGlvbj19IG9yaWdpbiBUaGUgb3JpZ2luYWwgZnVuY3Rpb24gdGhhdCB3YXMgYWRkZWQgYXMgYVxuXHQgKiAgIGxpc3RlbmVyLCBpZiB0aGVyZSBpcyBhbnkuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFkZFNpbmdsZUxpc3RlbmVyXyhldmVudCwgbGlzdGVuZXIsIGRlZmF1bHRMaXN0ZW5lciwgb3JpZ2luKSB7XG5cdFx0dGhpcy5ydW5MaXN0ZW5lckhhbmRsZXJzXyhldmVudCk7XG5cdFx0aWYgKGRlZmF1bHRMaXN0ZW5lciB8fCBvcmlnaW4pIHtcblx0XHRcdGxpc3RlbmVyID0ge1xuXHRcdFx0XHRkZWZhdWx0OiBkZWZhdWx0TGlzdGVuZXIsXG5cdFx0XHRcdGZuOiBsaXN0ZW5lcixcblx0XHRcdFx0b3JpZ2luOiBvcmlnaW4sXG5cdFx0XHR9O1xuXHRcdH1cblx0XHR0aGlzLmV2ZW50c18gPSB0aGlzLmV2ZW50c18gfHwge307XG5cdFx0dGhpcy5ldmVudHNfW2V2ZW50XSA9IHRoaXMuYWRkSGFuZGxlcl8odGhpcy5ldmVudHNfW2V2ZW50XSwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEJ1aWxkcyBmYWNhZGUgZm9yIHRoZSBnaXZlbiBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4ge09iamVjdH1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0YnVpbGRGYWNhZGVfKGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuZ2V0U2hvdWxkVXNlRmFjYWRlKCkpIHtcblx0XHRcdGNvbnN0IGZhY2FkZSA9IHtcblx0XHRcdFx0cHJldmVudERlZmF1bHQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGZhY2FkZS5wcmV2ZW50ZWREZWZhdWx0ID0gdHJ1ZTtcblx0XHRcdFx0fSxcblx0XHRcdFx0dGFyZ2V0OiB0aGlzLFxuXHRcdFx0XHR0eXBlOiBldmVudCxcblx0XHRcdH07XG5cdFx0XHRyZXR1cm4gZmFjYWRlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwb3NlcyBvZiB0aGlzIGluc3RhbmNlJ3Mgb2JqZWN0IHJlZmVyZW5jZXMuXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHRoaXMuZXZlbnRzXyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogRXhlY3V0ZSBlYWNoIG9mIHRoZSBsaXN0ZW5lcnMgaW4gb3JkZXIgd2l0aCB0aGUgc3VwcGxpZWQgYXJndW1lbnRzLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHBhcmFtIHsqfSBvcHRfYXJncyBbYXJnMV0sIFthcmcyXSwgWy4uLl1cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIGV2ZW50IGhhZCBsaXN0ZW5lcnMsIGZhbHNlIG90aGVyd2lzZS5cblx0ICovXG5cdGVtaXQoZXZlbnQpIHtcblx0XHRjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLmdldFJhd0xpc3RlbmVyc18oZXZlbnQpO1xuXHRcdGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Y29uc3QgYXJncyA9IGFycmF5LnNsaWNlKGFyZ3VtZW50cywgMSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0XHR0aGlzLnJ1bkxpc3RlbmVyc18obGlzdGVuZXJzLCBhcmdzLCB0aGlzLmJ1aWxkRmFjYWRlXyhldmVudCkpO1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGxpc3RlbmVyIG9iamVjdHMgZm9yIHRoZSBnaXZlbiBldmVudCwgaWYgdGhlcmUgYXJlIGFueS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4geyFBcnJheX1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0Z2V0UmF3TGlzdGVuZXJzXyhldmVudCkge1xuXHRcdGNvbnN0IGRpcmVjdExpc3RlbmVycyA9IHRvQXJyYXkodGhpcy5ldmVudHNfICYmIHRoaXMuZXZlbnRzX1tldmVudF0pO1xuXHRcdHJldHVybiBkaXJlY3RMaXN0ZW5lcnMuY29uY2F0KFxuXHRcdFx0dG9BcnJheSh0aGlzLmV2ZW50c18gJiYgdGhpcy5ldmVudHNfWycqJ10pXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjb25maWd1cmF0aW9uIG9wdGlvbiB3aGljaCBkZXRlcm1pbmVzIGlmIGFuIGV2ZW50IGZhY2FkZSBzaG91bGRcblx0ICogYmUgc2VudCBhcyBhIHBhcmFtIG9mIGxpc3RlbmVycyB3aGVuIGVtaXR0aW5nIGV2ZW50cy4gSWYgc2V0IHRvIHRydWUsIHRoZVxuXHQgKiBmYWNhZGUgd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIHRoZSBsaXN0ZW5lci5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldFNob3VsZFVzZUZhY2FkZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5zaG91bGRVc2VGYWNhZGVfO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7QXJyYXl9IEFycmF5IG9mIGxpc3RlbmVycy5cblx0ICovXG5cdGxpc3RlbmVycyhldmVudCkge1xuXHRcdHJldHVybiB0aGlzLmdldFJhd0xpc3RlbmVyc18oZXZlbnQpLm1hcChcblx0XHRcdGxpc3RlbmVyID0+IChsaXN0ZW5lci5mbiA/IGxpc3RlbmVyLmZuIDogbGlzdGVuZXIpXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBmaXhlZCBudW1iZXIgb2YgdGltZXMgZm9yIHRoZVxuXHQgKiBldmVudHMuIEFmdGVyIGVhY2ggZXZlbnQgaXMgdHJpZ2dlcmVkIHRoZSBzcGVjaWZpZWQgYW1vdW50IG9mIHRpbWVzLCB0aGVcblx0ICogbGlzdGVuZXIgaXMgcmVtb3ZlZCBmb3IgaXQuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudFxuXHQgKiBAcGFyYW0ge251bWJlcn0gYW1vdW50IFRoZSBhbW91bnQgb2YgdGltZXMgdGhpcyBldmVudCBzaG91bGQgYmUgbGlzdGVuZWRcblx0ICogdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG5cdCAqL1xuXHRtYW55KGV2ZW50LCBhbW91bnQsIGxpc3RlbmVyKSB7XG5cdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMubWFueV8oZXZlbnRzW2ldLCBhbW91bnQsIGxpc3RlbmVyKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IEV2ZW50SGFuZGxlKHRoaXMsIGV2ZW50LCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGEgZml4ZWQgbnVtYmVyIG9mIHRpbWVzIGZvciBhIHNpbmdsZVxuXHQgKiBldmVudC4gQWZ0ZXIgdGhlIGV2ZW50IGlzIHRyaWdnZXJlZCB0aGUgc3BlY2lmaWVkIGFtb3VudCBvZiB0aW1lcywgdGhlXG5cdCAqIGxpc3RlbmVyIGlzIHJlbW92ZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0ge251bWJlcn0gYW1vdW50IFRoZSBhbW91bnQgb2YgdGltZXMgdGhpcyBldmVudCBzaG91bGQgYmUgbGlzdGVuZWRcblx0ICogdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRtYW55XyhldmVudCwgYW1vdW50LCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IHNlbGYgPSB0aGlzO1xuXG5cdFx0aWYgKGFtb3VudCA8PSAwKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0LyoqXG5cdFx0ICpcblx0XHQgKi9cblx0XHRmdW5jdGlvbiBoYW5kbGVySW50ZXJuYWwoKSB7XG5cdFx0XHRpZiAoLS1hbW91bnQgPT09IDApIHtcblx0XHRcdFx0c2VsZi5yZW1vdmVMaXN0ZW5lcihldmVudCwgaGFuZGxlckludGVybmFsKTtcblx0XHRcdH1cblx0XHRcdGxpc3RlbmVyLmFwcGx5KHNlbGYsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0XHR9XG5cblx0XHRzZWxmLmFkZFNpbmdsZUxpc3RlbmVyXyhldmVudCwgaGFuZGxlckludGVybmFsLCBmYWxzZSwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBhIGxpc3RlbmVyIG9iamVjdCBtYXRjaGVzIHRoZSBnaXZlbiBsaXN0ZW5lciBmdW5jdGlvbi4gVG8gbWF0Y2gsXG5cdCAqIGl0IG5lZWRzIHRvIGVpdGhlciBwb2ludCB0byB0aGF0IGxpc3RlbmVyIG9yIGhhdmUgaXQgYXMgaXRzIG9yaWdpbi5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBsaXN0ZW5lck9ialxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0bWF0Y2hlc0xpc3RlbmVyXyhsaXN0ZW5lck9iaiwgbGlzdGVuZXIpIHtcblx0XHRjb25zdCBmbiA9IGxpc3RlbmVyT2JqLmZuIHx8IGxpc3RlbmVyT2JqO1xuXHRcdHJldHVybiAoXG5cdFx0XHRmbiA9PT0gbGlzdGVuZXIgfHxcblx0XHRcdChsaXN0ZW5lck9iai5vcmlnaW4gJiYgbGlzdGVuZXJPYmoub3JpZ2luID09PSBsaXN0ZW5lcikgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQ2F1dGlvbjogY2hhbmdlcyBhcnJheSBpbmRpY2VzIGluIHRoZSBsaXN0ZW5lciBhcnJheSBiZWhpbmQgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRvZmYoZXZlbnQsIGxpc3RlbmVyKSB7XG5cdFx0dGhpcy52YWxpZGF0ZUxpc3RlbmVyXyhsaXN0ZW5lcik7XG5cdFx0aWYgKCF0aGlzLmV2ZW50c18pIHtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblxuXHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMudG9FdmVudHNBcnJheV8oZXZlbnQpO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmV2ZW50c19bZXZlbnRzW2ldXSA9IHRoaXMucmVtb3ZlTWF0Y2hpbmdMaXN0ZW5lck9ianNfKFxuXHRcdFx0XHR0b0FycmF5KHRoaXMuZXZlbnRzX1tldmVudHNbaV1dKSxcblx0XHRcdFx0bGlzdGVuZXJcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBlbmQgb2YgdGhlIGxpc3RlbmVycyBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudHMuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cblx0ICovXG5cdG9uKCkge1xuXHRcdHJldHVybiB0aGlzLmFkZExpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGhhbmRsZXIgdGhhdCBnZXRzIHRyaWdnZXJlZCB3aGVuIGFuIGV2ZW50IGlzIGxpc3RlbmVkIHRvIG9uIHRoaXNcblx0ICogaW5zdGFuY2UuXG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGhhbmRsZXJcblx0ICovXG5cdG9uTGlzdGVuZXIoaGFuZGxlcikge1xuXHRcdHRoaXMubGlzdGVuZXJIYW5kbGVyc18gPSB0aGlzLmFkZEhhbmRsZXJfKFxuXHRcdFx0dGhpcy5saXN0ZW5lckhhbmRsZXJzXyxcblx0XHRcdGhhbmRsZXJcblx0XHQpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIG9uZSB0aW1lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRzLiBUaGlzIGxpc3RlbmVyIGlzIGludm9rZWQgb25seSB0aGVcblx0ICogbmV4dCB0aW1lIGVhY2ggZXZlbnQgaXMgZmlyZWQsIGFmdGVyIHdoaWNoIGl0IGlzIHJlbW92ZWQuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cblx0ICovXG5cdG9uY2UoZXZlbnRzLCBsaXN0ZW5lcikge1xuXHRcdHJldHVybiB0aGlzLm1hbnkoZXZlbnRzLCAxLCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzLCBvciB0aG9zZSBvZiB0aGUgc3BlY2lmaWVkIGV2ZW50cy4gSXQncyBub3QgYSBnb29kXG5cdCAqIGlkZWEgdG8gcmVtb3ZlIGxpc3RlbmVycyB0aGF0IHdlcmUgYWRkZWQgZWxzZXdoZXJlIGluIHRoZSBjb2RlLFxuXHQgKiBlc3BlY2lhbGx5IHdoZW4gaXQncyBvbiBhbiBlbWl0dGVyIHRoYXQgeW91IGRpZG4ndCBjcmVhdGUuXG5cdCAqIEBwYXJhbSB7KEFycmF5fHN0cmluZyk9fSBldmVudFxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fSBSZXR1cm5zIGVtaXR0ZXIsIHNvIGNhbGxzIGNhbiBiZSBjaGFpbmVkLlxuXHQgKi9cblx0cmVtb3ZlQWxsTGlzdGVuZXJzKGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuZXZlbnRzXykge1xuXHRcdFx0aWYgKGV2ZW50KSB7XG5cdFx0XHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMudG9FdmVudHNBcnJheV8oZXZlbnQpO1xuXHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRcdHRoaXMuZXZlbnRzX1tldmVudHNbaV1dID0gbnVsbDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5ldmVudHNfID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhbGwgbGlzdGVuZXIgb2JqZWN0cyBmcm9tIHRoZSBnaXZlbiBhcnJheSB0aGF0IG1hdGNoIHRoZSBnaXZlblxuXHQgKiBsaXN0ZW5lciBmdW5jdGlvbi5cblx0ICogQHBhcmFtIHtBcnJheS48T2JqZWN0Pn0gbGlzdGVuZXJPYmpzXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHtBcnJheS48T2JqZWN0PnxPYmplY3R9IFRoZSBuZXcgbGlzdGVuZXJzIGFycmF5IGZvciB0aGlzIGV2ZW50LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRyZW1vdmVNYXRjaGluZ0xpc3RlbmVyT2Jqc18obGlzdGVuZXJPYmpzLCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IGZpbmFsTGlzdGVuZXJzID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0ZW5lck9ianMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmICghdGhpcy5tYXRjaGVzTGlzdGVuZXJfKGxpc3RlbmVyT2Jqc1tpXSwgbGlzdGVuZXIpKSB7XG5cdFx0XHRcdGZpbmFsTGlzdGVuZXJzLnB1c2gobGlzdGVuZXJPYmpzW2ldKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGZpbmFsTGlzdGVuZXJzLmxlbmd0aCA+IDAgPyBmaW5hbExpc3RlbmVycyA6IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQ2F1dGlvbjogY2hhbmdlcyBhcnJheSBpbmRpY2VzIGluIHRoZSBsaXN0ZW5lciBhcnJheSBiZWhpbmQgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRzXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fSBSZXR1cm5zIGVtaXR0ZXIsIHNvIGNhbGxzIGNhbiBiZSBjaGFpbmVkLlxuXHQgKi9cblx0cmVtb3ZlTGlzdGVuZXIoKSB7XG5cdFx0cmV0dXJuIHRoaXMub2ZmLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fVxuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBoYW5kbGVycyB3aGVuIGFuIGV2ZW50IGlzIGxpc3RlbmVkIHRvLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0cnVuTGlzdGVuZXJIYW5kbGVyc18oZXZlbnQpIHtcblx0XHRsZXQgaGFuZGxlcnMgPSB0aGlzLmxpc3RlbmVySGFuZGxlcnNfO1xuXHRcdGlmIChoYW5kbGVycykge1xuXHRcdFx0aGFuZGxlcnMgPSB0b0FycmF5KGhhbmRsZXJzKTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgaGFuZGxlcnMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0aGFuZGxlcnNbaV0oZXZlbnQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBnaXZlbiBsaXN0ZW5lcnMuXG5cdCAqIEBwYXJhbSB7IUFycmF5fSBsaXN0ZW5lcnNcblx0ICogQHBhcmFtIHshQXJyYXl9IGFyZ3Ncblx0ICogQHBhcmFtIHtPYmplY3R9IGZhY2FkZVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRydW5MaXN0ZW5lcnNfKGxpc3RlbmVycywgYXJncywgZmFjYWRlKSB7XG5cdFx0aWYgKGZhY2FkZSkge1xuXHRcdFx0YXJncy5wdXNoKGZhY2FkZSk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZGVmYXVsdExpc3RlbmVycyA9IFtdO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXS5mbiB8fCBsaXN0ZW5lcnNbaV07XG5cdFx0XHRpZiAobGlzdGVuZXJzW2ldLmRlZmF1bHQpIHtcblx0XHRcdFx0ZGVmYXVsdExpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoIWZhY2FkZSB8fCAhZmFjYWRlLnByZXZlbnRlZERlZmF1bHQpIHtcblx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgZGVmYXVsdExpc3RlbmVycy5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRkZWZhdWx0TGlzdGVuZXJzW2pdLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBjb25maWd1cmF0aW9uIG9wdGlvbiB3aGljaCBkZXRlcm1pbmVzIGlmIGFuIGV2ZW50IGZhY2FkZSBzaG91bGRcblx0ICogYmUgc2VudCBhcyBhIHBhcmFtIG9mIGxpc3RlbmVycyB3aGVuIGVtaXR0aW5nIGV2ZW50cy4gSWYgc2V0IHRvIHRydWUsIHRoZVxuXHQgKiBmYWNhZGUgd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIHRoZSBsaXN0ZW5lci5cblx0ICogQHBhcmFtIHtib29sZWFufSBzaG91bGRVc2VGYWNhZGVcblx0ICogQHJldHVybiB7IU9iamVjdH0gUmV0dXJucyBlbWl0dGVyLCBzbyBjYWxscyBjYW4gYmUgY2hhaW5lZC5cblx0ICovXG5cdHNldFNob3VsZFVzZUZhY2FkZShzaG91bGRVc2VGYWNhZGUpIHtcblx0XHR0aGlzLnNob3VsZFVzZUZhY2FkZV8gPSBzaG91bGRVc2VGYWNhZGU7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgdGhlIHBhcmFtZXRlciB0byBhbiBhcnJheSBpZiBvbmx5IG9uZSBldmVudCBpcyBnaXZlbi4gUmV1c2VzIHRoZVxuXHQgKiBzYW1lIGFycmF5IGVhY2ggdGltZSB0aGlzIGNvbnZlcnNpb24gaXMgZG9uZSwgdG8gYXZvaWQgdXNpbmcgbW9yZSBtZW1vcnlcblx0ICogdGhhbiBuZWNlc3NhcnkuXG5cdCAqIEBwYXJhbSAgeyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRzXG5cdCAqIEByZXR1cm4geyFBcnJheX1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dG9FdmVudHNBcnJheV8oZXZlbnRzKSB7XG5cdFx0aWYgKGlzU3RyaW5nKGV2ZW50cykpIHtcblx0XHRcdHNpbmdsZUFycmF5X1swXSA9IGV2ZW50cztcblx0XHRcdGV2ZW50cyA9IHNpbmdsZUFycmF5Xztcblx0XHR9XG5cdFx0cmV0dXJuIGV2ZW50cztcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGxpc3RlbmVyIGlzIHZhbGlkLCB0aHJvd2luZyBhbiBleGNlcHRpb24gd2hlbiBpdCdzIG5vdC5cblx0ICogQHBhcmFtICB7Kn0gbGlzdGVuZXJcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dmFsaWRhdGVMaXN0ZW5lcl8obGlzdGVuZXIpIHtcblx0XHRpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCdMaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0byBhbiBhcnJheVxuICogQHBhcmFtIHtPYmplY3R9IHZhbFxuICogQHJldHVybiB7QXJyYXl9XG4gKi9cbmZ1bmN0aW9uIHRvQXJyYXkodmFsKSB7XG5cdHZhbCA9IHZhbCB8fCBbXTtcblx0cmV0dXJuIEFycmF5LmlzQXJyYXkodmFsKSA/IHZhbCA6IFt2YWxdO1xufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEVtaXR0ZXI7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7RGlzcG9zYWJsZX0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEV2ZW50RW1pdHRlclByb3h5IHV0aWxpdHkuIEl0J3MgcmVzcG9uc2libGUgZm9yIGxpbmtpbmcgdHdvIEV2ZW50RW1pdHRlclxuICogaW5zdGFuY2VzIHRvZ2V0aGVyLCBlbWl0dGluZyBldmVudHMgZnJvbSB0aGUgZmlyc3QgZW1pdHRlciB0aHJvdWdoIHRoZVxuICogc2Vjb25kIG9uZS4gVGhhdCBtZWFucyB0aGF0IGxpc3RlbmluZyB0byBhIHN1cHBvcnRlZCBldmVudCBvbiB0aGUgdGFyZ2V0XG4gKiBlbWl0dGVyIHdpbGwgbWVhbiBsaXN0ZW5pbmcgdG8gaXQgb24gdGhlIG9yaWdpbiBlbWl0dGVyIGFzIHdlbGwuXG4gKiBAZXh0ZW5kcyB7RGlzcG9zYWJsZX1cbiAqL1xuY2xhc3MgRXZlbnRFbWl0dGVyUHJveHkgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblx0LyoqXG5cdCAqIEBwYXJhbSB7RXZlbnRFbWl0dGVyfSBvcmlnaW5FbWl0dGVyIEV2ZW50cyBvcmlnaW5hdGVkIG9uIHRoaXMgZW1pdHRlclxuXHQgKiB3aWxsIGJlIGZpcmVkIGZvciB0aGUgdGFyZ2V0IGVtaXR0ZXIncyBsaXN0ZW5lcnMgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtFdmVudEVtaXR0ZXJ9IHRhcmdldEVtaXR0ZXIgRXZlbnQgbGlzdGVuZXJzIGF0dGFjaGVkIHRvIHRoaXMgZW1pdHRlclxuXHQgKiB3aWxsIGFsc28gYmUgdHJpZ2dlcmVkIHdoZW4gdGhlIGV2ZW50IGlzIGZpcmVkIGJ5IHRoZSBvcmlnaW4gZW1pdHRlci5cblx0ICogQHBhcmFtIHtPYmplY3R9IGJsYWNrbGlzdCBPcHRpb25hbCBibGFja2xpc3Qgb2YgZXZlbnRzIHRoYXQgc2hvdWxkIG5vdCBiZVxuXHQgKiBwcm94aWVkLlxuXHQgKiBAcGFyYW0ge09iamVjdH0gd2hpdGVsaXN0XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihvcmlnaW5FbWl0dGVyLCB0YXJnZXRFbWl0dGVyLCBibGFja2xpc3QsIHdoaXRlbGlzdCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBNYXAgb2YgZXZlbnRzIHRoYXQgc2hvdWxkIG5vdCBiZSBwcm94aWVkLlxuXHRcdCAqIEB0eXBlIHtPYmplY3R9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYmxhY2tsaXN0XyA9IGJsYWNrbGlzdDtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBvcmlnaW4gZW1pdHRlci4gVGhpcyBlbWl0dGVyJ3MgZXZlbnRzIHdpbGwgYmUgcHJveGllZCB0aHJvdWdoIHRoZVxuXHRcdCAqIHRhcmdldCBlbWl0dGVyLlxuXHRcdCAqIEB0eXBlIHtFdmVudEVtaXR0ZXJ9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMub3JpZ2luRW1pdHRlcl8gPSBvcmlnaW5FbWl0dGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogQSBsaXN0IG9mIGV2ZW50cyB0aGF0IGFyZSBwZW5kaW5nIHRvIGJlIGxpc3RlbmVkIGJ5IGFuIGFjdHVhbCBvcmlnaW5cblx0XHQgKiBlbWl0dGVyLiBFdmVudHMgYXJlIHN0b3JlZCBoZXJlIHdoZW4gdGhlIG9yaWdpbiBkb2Vzbid0IGV4aXN0LCBzbyB0aGV5XG5cdFx0ICogY2FuIGJlIHNldCBvbiBhIG5ldyBvcmlnaW4gd2hlbiBvbmUgaXMgc2V0LlxuXHRcdCAqIEB0eXBlIHtBcnJheX1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wZW5kaW5nRXZlbnRzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBhIG1hcCBvZiBldmVudHMgZnJvbSB0aGUgb3JpZ2luIGVtaXR0ZXIgdGhhdCBhcmUgYWxyZWFkeSBiZWluZyBwcm94aWVkLlxuXHRcdCAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCAhRXZlbnRIYW5kbGU+fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSB0YXJnZXQgZW1pdHRlci4gVGhpcyBlbWl0dGVyIHdpbGwgZW1pdCBhbGwgZXZlbnRzIHRoYXQgY29tZSBmcm9tXG5cdFx0ICogdGhlIG9yaWdpbiBlbWl0dGVyLlxuXHRcdCAqIEB0eXBlIHtFdmVudEVtaXR0ZXJ9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudGFyZ2V0RW1pdHRlcl8gPSB0YXJnZXRFbWl0dGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogTWFwIG9mIGV2ZW50cyB0aGF0IHNob3VsZCBiZSBwcm94aWVkLiBJZiB3aGl0ZWxpc3QgaXMgc2V0IGJsYWNrbGlzdCBpcyBpZ25vcmVkLlxuXHRcdCAqIEB0eXBlIHtPYmplY3R9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMud2hpdGVsaXN0XyA9IHdoaXRlbGlzdDtcblxuXHRcdHRoaXMuc3RhcnRQcm94eV8oKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIHRoZSBnaXZlbiBsaXN0ZW5lciBmb3IgdGhlIGdpdmVuIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKX0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBUaGUgbGlzdGVuZWQgZXZlbnQncyBoYW5kbGUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFkZExpc3RlbmVyXyhldmVudCwgbGlzdGVuZXIpIHtcblx0XHRyZXR1cm4gdGhpcy5vcmlnaW5FbWl0dGVyXy5vbihldmVudCwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5yZW1vdmVMaXN0ZW5lcnNfKCk7XG5cdFx0dGhpcy5wcm94aWVkRXZlbnRzXyA9IG51bGw7XG5cdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyA9IG51bGw7XG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogRW1pdHMgdGhlIHNwZWNpZmllZCBldmVudCB0eXBlIG9uIHRoZSB0YXJnZXQgZW1pdHRlci5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0ZW1pdE9uVGFyZ2V0XyguLi5hcmdzKSB7XG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXy5lbWl0KC4uLmFyZ3MpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByb3hpZXMgdGhlIGdpdmVuIGV2ZW50IGZyb20gdGhlIG9yaWdpbiB0byB0aGUgdGFyZ2V0IGVtaXR0ZXIuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKi9cblx0cHJveHlFdmVudChldmVudCkge1xuXHRcdGlmICh0aGlzLnNob3VsZFByb3h5RXZlbnRfKGV2ZW50KSkge1xuXHRcdFx0dGhpcy50cnlUb0FkZExpc3RlbmVyXyhldmVudCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIHByb3h5IGxpc3RlbmVyIGZvciBhbGwgZXZlbnRzLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRyZW1vdmVMaXN0ZW5lcnNfKCkge1xuXHRcdGlmICh0aGlzLnByb3hpZWRFdmVudHNfKSB7XG5cdFx0XHRjb25zdCBldmVudHMgPSBPYmplY3Qua2V5cyh0aGlzLnByb3hpZWRFdmVudHNfKTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHRoaXMucHJveGllZEV2ZW50c19bZXZlbnRzW2ldXS5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzXyA9IG51bGw7XG5cdFx0fVxuXHRcdHRoaXMucGVuZGluZ0V2ZW50c18gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoYW5nZXMgdGhlIG9yaWdpbiBlbWl0dGVyLiBUaGlzIGF1dG9tYXRpY2FsbHkgZGV0YWNoZXMgYW55IGV2ZW50cyB0aGF0XG5cdCAqIHdlcmUgYWxyZWFkeSBiZWluZyBwcm94aWVkIGZyb20gdGhlIHByZXZpb3VzIGVtaXR0ZXIsIGFuZCBzdGFydHMgcHJveHlpbmdcblx0ICogdGhlbSBvbiB0aGUgbmV3IGVtaXR0ZXIgaW5zdGVhZC5cblx0ICogQHBhcmFtIHshRXZlbnRFbWl0dGVyfSBvcmlnaW5FbWl0dGVyXG5cdCAqL1xuXHRzZXRPcmlnaW5FbWl0dGVyKG9yaWdpbkVtaXR0ZXIpIHtcblx0XHRjb25zdCBldmVudHMgPVxuXHRcdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyAmJiB0aGlzLnByb3hpZWRFdmVudHNfXG5cdFx0XHRcdD8gT2JqZWN0LmtleXModGhpcy5wcm94aWVkRXZlbnRzXylcblx0XHRcdFx0OiB0aGlzLnBlbmRpbmdFdmVudHNfO1xuXHRcdHRoaXMub3JpZ2luRW1pdHRlcl8gPSBvcmlnaW5FbWl0dGVyO1xuXHRcdGlmIChldmVudHMpIHtcblx0XHRcdHRoaXMucmVtb3ZlTGlzdGVuZXJzXygpO1xuXHRcdFx0ZXZlbnRzLmZvckVhY2goZXZlbnQgPT4gdGhpcy5wcm94eUV2ZW50KGV2ZW50KSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZXZlbnQgc2hvdWxkIGJlIHByb3hpZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRzaG91bGRQcm94eUV2ZW50XyhldmVudCkge1xuXHRcdGlmICh0aGlzLndoaXRlbGlzdF8gJiYgIXRoaXMud2hpdGVsaXN0X1tldmVudF0pIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0aWYgKHRoaXMuYmxhY2tsaXN0XyAmJiB0aGlzLmJsYWNrbGlzdF9bZXZlbnRdKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiAhdGhpcy5wcm94aWVkRXZlbnRzXyB8fCAhdGhpcy5wcm94aWVkRXZlbnRzX1tldmVudF07XG5cdH1cblxuXHQvKipcblx0ICogU3RhcnRzIHByb3h5aW5nIGFsbCBldmVudHMgZnJvbSB0aGUgb3JpZ2luIHRvIHRoZSB0YXJnZXQgZW1pdHRlci5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0c3RhcnRQcm94eV8oKSB7XG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXy5vbkxpc3RlbmVyKHRoaXMucHJveHlFdmVudC5iaW5kKHRoaXMpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIG9yaWdpbiBlbWl0dGVyLCBpZiBpdCBleGlzdHMuIE90aGVyd2lzZSwgc3RvcmVzXG5cdCAqIHRoZSBwZW5kaW5nIGxpc3RlbmVyIHNvIGl0IGNhbiBiZSB1c2VkIG9uIGEgZnV0dXJlIG9yaWdpbiBlbWl0dGVyLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dHJ5VG9BZGRMaXN0ZW5lcl8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5vcmlnaW5FbWl0dGVyXykge1xuXHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzXyA9IHRoaXMucHJveGllZEV2ZW50c18gfHwge307XG5cdFx0XHR0aGlzLnByb3hpZWRFdmVudHNfW2V2ZW50XSA9IHRoaXMuYWRkTGlzdGVuZXJfKFxuXHRcdFx0XHRldmVudCxcblx0XHRcdFx0dGhpcy5lbWl0T25UYXJnZXRfLmJpbmQodGhpcywgZXZlbnQpXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnBlbmRpbmdFdmVudHNfID0gdGhpcy5wZW5kaW5nRXZlbnRzXyB8fCBbXTtcblx0XHRcdHRoaXMucGVuZGluZ0V2ZW50c18ucHVzaChldmVudCk7XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50RW1pdHRlclByb3h5O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge0Rpc3Bvc2FibGV9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBFdmVudEhhbmRsZXIgdXRpbGl0eS4gSXQncyB1c2VmdWwgZm9yIGVhc2lseSByZW1vdmluZyBhIGdyb3VwIG9mXG4gKiBsaXN0ZW5lcnMgZnJvbSBkaWZmZXJlbnQgRXZlbnRFbWl0dGVyIGluc3RhbmNlcy5cbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEhhbmRsZXIgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblx0LyoqXG5cdCAqIEV2ZW50SGFuZGxlciBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEFuIGFycmF5IHRoYXQgaG9sZHMgdGhlIGFkZGVkIGV2ZW50IGhhbmRsZXMsIHNvIHRoZSBsaXN0ZW5lcnMgY2FuIGJlXG5cdFx0ICogcmVtb3ZlZCBsYXRlci5cblx0XHQgKiBAdHlwZSB7QXJyYXkuPEV2ZW50SGFuZGxlPn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ldmVudEhhbmRsZXNfID0gW107XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBldmVudCBoYW5kbGVzIHRvIGJlIHJlbW92ZWQgbGF0ZXIgdGhyb3VnaCB0aGUgYHJlbW92ZUFsbExpc3RlbmVyc2Bcblx0ICogbWV0aG9kLlxuXHQgKiBAcGFyYW0gey4uLighRXZlbnRIYW5kbGUpfSB2YXJfYXJnc1xuXHQgKi9cblx0YWRkKC4uLmFyZ3MpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dGhpcy5ldmVudEhhbmRsZXNfLnB1c2goYXJnc1tpXSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy5cblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5ldmVudEhhbmRsZXNfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgdGhhdCBoYXZlIGJlZW4gYWRkZWQgdGhyb3VnaCB0aGUgYGFkZGAgbWV0aG9kLlxuXHQgKi9cblx0cmVtb3ZlQWxsTGlzdGVuZXJzKCkge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5ldmVudEhhbmRsZXNfLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmV2ZW50SGFuZGxlc19baV0ucmVtb3ZlTGlzdGVuZXIoKTtcblx0XHR9XG5cblx0XHR0aGlzLmV2ZW50SGFuZGxlc18gPSBbXTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEhhbmRsZXI7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXJyYXksIGlzU3RyaW5nfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgZG9tRGF0YSBmcm9tICcuL2RvbURhdGEnO1xuaW1wb3J0IHtFdmVudEhhbmRsZX0gZnJvbSAnbWV0YWwtZXZlbnRzJztcblxuLyoqXG4gKiBUaGlzIGlzIGEgc3BlY2lhbCBFdmVudEhhbmRsZSwgdGhhdCBpcyByZXNwb25zaWJsZSBmb3IgZG9tIGRlbGVnYXRlZCBldmVudHNcbiAqIChvbmx5IHRoZSBvbmVzIHRoYXQgcmVjZWl2ZSBhIHRhcmdldCBlbGVtZW50LCBub3QgYSBzZWxlY3RvciBzdHJpbmcpLlxuICogQGV4dGVuZHMge0V2ZW50SGFuZGxlfVxuICovXG5jbGFzcyBEb21EZWxlZ2F0ZWRFdmVudEhhbmRsZSBleHRlbmRzIEV2ZW50SGFuZGxlIHtcblx0LyoqXG5cdCAqIFRoZSBjb25zdHJ1Y3RvciBmb3IgYERvbURlbGVnYXRlZEV2ZW50SGFuZGxlYC5cblx0ICogQHBhcmFtIHshRXZlbnR9IGVtaXR0ZXIgRWxlbWVudCB0aGUgZXZlbnQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCB3YXMgc3Vic2NyaWJlZCB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmc9fSBzZWxlY3RvciBBbiBvcHRpb25hbCBzZWxlY3RvciB1c2VkIHdoZW4gZGVsZWdhdGluZ1xuXHQgKiAgICAgdGhlIGV2ZW50LlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKGVtaXR0ZXIsIGV2ZW50LCBsaXN0ZW5lciwgc2VsZWN0b3IpIHtcblx0XHRzdXBlcihlbWl0dGVyLCBldmVudCwgbGlzdGVuZXIpO1xuXHRcdHRoaXMuc2VsZWN0b3JfID0gc2VsZWN0b3I7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyKCkge1xuXHRcdGNvbnN0IGRlbGVnYXRpbmcgPSBkb21EYXRhLmdldCh0aGlzLmVtaXR0ZXJfLCAnZGVsZWdhdGluZycsIHt9KTtcblx0XHRjb25zdCBsaXN0ZW5lcnMgPSBkb21EYXRhLmdldCh0aGlzLmVtaXR0ZXJfLCAnbGlzdGVuZXJzJywge30pO1xuXHRcdGNvbnN0IHNlbGVjdG9yID0gdGhpcy5zZWxlY3Rvcl87XG5cdFx0Y29uc3QgYXJyID0gaXNTdHJpbmcoc2VsZWN0b3IpXG5cdFx0XHQ/IGRlbGVnYXRpbmdbdGhpcy5ldmVudF9dLnNlbGVjdG9yc1xuXHRcdFx0OiBsaXN0ZW5lcnM7XG5cdFx0Y29uc3Qga2V5ID0gaXNTdHJpbmcoc2VsZWN0b3IpID8gc2VsZWN0b3IgOiB0aGlzLmV2ZW50XztcblxuXHRcdGFycmF5LnJlbW92ZShhcnJba2V5XSB8fCBbXSwgdGhpcy5saXN0ZW5lcl8pO1xuXHRcdGlmIChhcnJba2V5XSAmJiBhcnJba2V5XS5sZW5ndGggPT09IDApIHtcblx0XHRcdGRlbGV0ZSBhcnJba2V5XTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7RXZlbnRIYW5kbGV9IGZyb20gJ21ldGFsLWV2ZW50cyc7XG5cbi8qKlxuICogVGhpcyBpcyBhIHNwZWNpYWwgRXZlbnRIYW5kbGUsIHRoYXQgaXMgcmVzcG9uc2libGUgZm9yIGRvbSBldmVudHMsIGluc3RlYWRcbiAqIG9mIEV2ZW50RW1pdHRlciBldmVudHMuXG4gKiBAZXh0ZW5kcyB7RXZlbnRIYW5kbGV9XG4gKi9cbmNsYXNzIERvbUV2ZW50SGFuZGxlIGV4dGVuZHMgRXZlbnRIYW5kbGUge1xuXHQvKipcblx0ICogVGhlIGNvbnN0cnVjdG9yIGZvciBgRG9tRXZlbnRIYW5kbGVgLlxuXHQgKiBAcGFyYW0geyFFdmVudEVtaXR0ZXJ9IGVtaXR0ZXIgRW1pdHRlciB0aGUgZXZlbnQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCB3YXMgc3Vic2NyaWJlZCB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0ICogQHBhcmFtIHtib29sZWFufSBjYXB0dXJlIEZsYWcgaW5kaWNhdGluZyBpZiBsaXN0ZW5lciBzaG91bGQgYmUgdHJpZ2dlcmVkXG5cdCAqICAgZHVyaW5nIGNhcHR1cmUgcGhhc2UsIGluc3RlYWQgb2YgZHVyaW5nIHRoZSBidWJibGluZyBwaGFzZS4gRGVmYXVsdHMgdG8gZmFsc2UuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoZW1pdHRlciwgZXZlbnQsIGxpc3RlbmVyLCBjYXB0dXJlKSB7XG5cdFx0c3VwZXIoZW1pdHRlciwgZXZlbnQsIGxpc3RlbmVyKTtcblx0XHR0aGlzLmNhcHR1cmVfID0gY2FwdHVyZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0cmVtb3ZlTGlzdGVuZXIoKSB7XG5cdFx0dGhpcy5lbWl0dGVyXy5yZW1vdmVFdmVudExpc3RlbmVyKFxuXHRcdFx0dGhpcy5ldmVudF8sXG5cdFx0XHR0aGlzLmxpc3RlbmVyXyxcblx0XHRcdHRoaXMuY2FwdHVyZV9cblx0XHQpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERvbUV2ZW50SGFuZGxlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge1xuXHRpc0RlZixcblx0aXNEZWZBbmROb3ROdWxsLFxuXHRpc0RvY3VtZW50LFxuXHRpc0RvY3VtZW50RnJhZ21lbnQsXG5cdGlzRWxlbWVudCxcblx0aXNPYmplY3QsXG5cdGlzU3RyaW5nLFxuXHRvYmplY3QsXG59IGZyb20gJ21ldGFsJztcbmltcG9ydCBkb21EYXRhIGZyb20gJy4vZG9tRGF0YSc7XG5pbXBvcnQgRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGUgZnJvbSAnLi9Eb21EZWxlZ2F0ZWRFdmVudEhhbmRsZSc7XG5pbXBvcnQgRG9tRXZlbnRIYW5kbGUgZnJvbSAnLi9Eb21FdmVudEhhbmRsZSc7XG5cbmNvbnN0IGVsZW1lbnRzQnlUYWdfID0ge307XG5jb25zdCBzdXBwb3J0Q2FjaGVfID0ge307XG5leHBvcnQgY29uc3QgY3VzdG9tRXZlbnRzID0ge307XG5cbmNvbnN0IExBU1RfQ09OVEFJTkVSID0gJ19fbWV0YWxfbGFzdF9jb250YWluZXJfXyc7XG5jb25zdCBVU0VfQ0FQVFVSRSA9IHtcblx0Ymx1cjogdHJ1ZSxcblx0ZXJyb3I6IHRydWUsXG5cdGZvY3VzOiB0cnVlLFxuXHRpbnZhbGlkOiB0cnVlLFxuXHRsb2FkOiB0cnVlLFxuXHRzY3JvbGw6IHRydWUsXG59O1xuXG4vKipcbiAqIEFkZHMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyB0byBhbiBlbGVtZW50LlxuICogQHBhcmFtIHshRWxlbWVudHwhTm9kZWxpc3R9IGVsZW1lbnRzIFRoZSBlbGVtZW50IG9yIGVsZW1lbnRzIHRvIGFkZCBDU1MgY2xhc3NlcyB0by5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIGFkZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZENsYXNzZXMoZWxlbWVudHMsIGNsYXNzZXMpIHtcblx0aWYgKCFpc09iamVjdChlbGVtZW50cykgfHwgIWlzU3RyaW5nKGNsYXNzZXMpKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0aWYgKCFlbGVtZW50cy5sZW5ndGgpIHtcblx0XHRlbGVtZW50cyA9IFtlbGVtZW50c107XG5cdH1cblxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKCdjbGFzc0xpc3QnIGluIGVsZW1lbnRzW2ldKSB7XG5cdFx0XHRhZGRDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhZGRDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIEFkZHMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyB0byBhbiBlbGVtZW50IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gYWRkIENTUyBjbGFzc2VzIHRvLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgQ1NTIGNsYXNzZXMgdG8gYWRkLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkQ2xhc3Nlc1dpdGhOYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpIHtcblx0Y2xhc3Nlcy5zcGxpdCgnICcpLmZvckVhY2goZnVuY3Rpb24oY2xhc3NOYW1lKSB7XG5cdFx0aWYgKGNsYXNzTmFtZSkge1xuXHRcdFx0ZWxlbWVudC5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuLyoqXG4gKiBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBFbGVtZW50LmNsYXNzTGlzdC5hZGQgZnVuY3Rpb24sIHRoaXMgbWV0aG9kXG4gKiBhZGRzIHRoZSByZXF1ZXN0ZWQgQ1NTIGNsYXNzZXMgdG8gYW4gZWxlbWVudCB3aXRob3V0IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gYWRkIENTUyBjbGFzc2VzIHRvLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgQ1NTIGNsYXNzZXMgdG8gYWRkLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkQ2xhc3Nlc1dpdGhvdXROYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpIHtcblx0Y29uc3QgZWxlbWVudENsYXNzTmFtZSA9IGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYDtcblx0bGV0IGNsYXNzZXNUb0FwcGVuZCA9ICcnO1xuXG5cdGNsYXNzZXMgPSBjbGFzc2VzLnNwbGl0KCcgJyk7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjbGFzc2VzLmxlbmd0aDsgaSsrKSB7XG5cdFx0Y29uc3QgY2xhc3NOYW1lID0gY2xhc3Nlc1tpXTtcblxuXHRcdGlmIChlbGVtZW50Q2xhc3NOYW1lLmluZGV4T2YoYCAke2NsYXNzTmFtZX0gYCkgPT09IC0xKSB7XG5cdFx0XHRjbGFzc2VzVG9BcHBlbmQgKz0gYCAke2NsYXNzTmFtZX1gO1xuXHRcdH1cblx0fVxuXG5cdGlmIChjbGFzc2VzVG9BcHBlbmQpIHtcblx0XHRlbGVtZW50LmNsYXNzTmFtZSA9IGVsZW1lbnQuY2xhc3NOYW1lICsgY2xhc3Nlc1RvQXBwZW5kO1xuXHR9XG59XG5cbi8qKlxuICogQWRkcyBhbiBldmVudCBsaXN0ZW5lciB0byB0aGUgZ2l2ZW4gZWxlbWVudCwgdG8gYmUgdHJpZ2dlcmVkIHZpYSBkZWxlZ2F0ZS5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGxpc3RlbmVyXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBhZGRFbGVtZW50TGlzdGVuZXJfKGVsZW1lbnQsIGV2ZW50TmFtZSwgbGlzdGVuZXIpIHtcblx0YWRkVG9BcnJfKGRvbURhdGEuZ2V0KGVsZW1lbnQsICdsaXN0ZW5lcnMnLCB7fSksIGV2ZW50TmFtZSwgbGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIEFkZHMgYW4gZXZlbnQgbGlzdGVuZXIgdG8gdGhlIGdpdmVuIGVsZW1lbnQsIHRvIGJlIHRyaWdnZXJlZCB2aWEgZGVsZWdhdGVcbiAqIHNlbGVjdG9ycy5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICogQHBhcmFtIHshZnVuY3Rpb24oKX0gbGlzdGVuZXJcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGFkZFNlbGVjdG9yTGlzdGVuZXJfKGVsZW1lbnQsIGV2ZW50TmFtZSwgc2VsZWN0b3IsIGxpc3RlbmVyKSB7XG5cdGNvbnN0IGRlbGVnYXRpbmdEYXRhID0gZG9tRGF0YS5nZXQoZWxlbWVudCwgJ2RlbGVnYXRpbmcnLCB7fSk7XG5cdGFkZFRvQXJyXyhkZWxlZ2F0aW5nRGF0YVtldmVudE5hbWVdLnNlbGVjdG9ycywgc2VsZWN0b3IsIGxpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBBZGRzIGEgdmFsdWUgdG8gYW4gYXJyYXkgaW5zaWRlIGFuIG9iamVjdCwgY3JlYXRpbmcgaXQgZmlyc3QgaWYgaXQgZG9lc24ndFxuICogeWV0IGV4aXN0LlxuICogQHBhcmFtIHshQXJyYXl9IGFyclxuICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICogQHBhcmFtIHsqfSB2YWx1ZVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkVG9BcnJfKGFyciwga2V5LCB2YWx1ZSkge1xuXHRpZiAoIWFycltrZXldKSB7XG5cdFx0YXJyW2tleV0gPSBbXTtcblx0fVxuXHRhcnJba2V5XS5wdXNoKHZhbHVlKTtcbn1cblxuLyoqXG4gKiBBdHRhY2hlcyBhIGRlbGVnYXRlIGxpc3RlbmVyLCB1bmxlc3MgdGhlcmUncyBhbHJlYWR5IG9uZSBhdHRhY2hlZC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGF0dGFjaERlbGVnYXRlRXZlbnRfKGVsZW1lbnQsIGV2ZW50TmFtZSkge1xuXHRsZXQgZGVsZWdhdGluZ0RhdGEgPSBkb21EYXRhLmdldChlbGVtZW50LCAnZGVsZWdhdGluZycsIHt9KTtcblx0aWYgKCFkZWxlZ2F0aW5nRGF0YVtldmVudE5hbWVdKSB7XG5cdFx0ZGVsZWdhdGluZ0RhdGFbZXZlbnROYW1lXSA9IHtcblx0XHRcdGhhbmRsZTogb24oXG5cdFx0XHRcdGVsZW1lbnQsXG5cdFx0XHRcdGV2ZW50TmFtZSxcblx0XHRcdFx0aGFuZGxlRGVsZWdhdGVFdmVudF8sXG5cdFx0XHRcdCEhVVNFX0NBUFRVUkVbZXZlbnROYW1lXVxuXHRcdFx0KSxcblx0XHRcdHNlbGVjdG9yczoge30sXG5cdFx0fTtcblx0fVxufVxuXG4vKipcbiAqIElFMTEgZG9lc24ndCBzdXBwb3J0IEVsZW1lbnQuY2xvc2VzdCBmdW5jdGlvbiwgdGhpcyBtZXRob2RcbiAqIGdldHMgdGhlIGNsb3Nlc3QgZWxlbWVudCB1cCB0aGUgdHJlZSBmcm9tIHRoZSBnaXZlbiBlbGVtZW50IChpbmNsdWRpbmdcbiAqIGl0c2VsZikgdGhhdCBtYXRjaGVzIHRoZSBzcGVjaWZpZWQgc2VsZWN0b3IsIG9yIG51bGwgaWYgbm9uZSBtYXRjaC5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcmV0dXJuIHtFbGVtZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xvc2VzdChlbGVtZW50LCBzZWxlY3Rvcikge1xuXHR3aGlsZSAoZWxlbWVudCAmJiAhbWF0Y2goZWxlbWVudCwgc2VsZWN0b3IpKSB7XG5cdFx0ZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcblx0fVxuXHRyZXR1cm4gZWxlbWVudDtcbn1cblxuLyoqXG4gKiBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBFbGVtZW50LmNsYXNzTGlzdC5hZGQgZnVuY3Rpb24sIHRoaXMgbWV0aG9kXG4gKiBhcHBlbmRzIGEgY2hpbGQgbm9kZSB3aXRoIHRleHQgb3Igb3RoZXIgbm9kZXMgdG8gYSBwYXJlbnQgbm9kZS4gSWZcbiAqIGNoaWxkIGlzIGEgSFRNTCBzdHJpbmcgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNvbnZlcnRlZCB0byBhIGRvY3VtZW50XG4gKiBmcmFnbWVudCBiZWZvcmUgYXBwZW5kaW5nIGl0IHRvIHRoZSBwYXJlbnQuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBwYXJlbnQgVGhlIG5vZGUgdG8gYXBwZW5kIG5vZGVzIHRvLlxuICogQHBhcmFtIHshKEVsZW1lbnR8Tm9kZUxpc3R8c3RyaW5nKX0gY2hpbGQgVGhlIHRoaW5nIHRvIGFwcGVuZCB0byB0aGUgcGFyZW50LlxuICogQHJldHVybiB7IUVsZW1lbnR9IFRoZSBhcHBlbmRlZCBjaGlsZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGVuZChwYXJlbnQsIGNoaWxkKSB7XG5cdGlmIChpc1N0cmluZyhjaGlsZCkpIHtcblx0XHRjaGlsZCA9IGJ1aWxkRnJhZ21lbnQoY2hpbGQpO1xuXHR9XG5cdGlmIChpc05vZGVMaXN0TGlrZShjaGlsZCkpIHtcblx0XHRjb25zdCBjaGlsZEFyciA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGNoaWxkKTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkQXJyLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRwYXJlbnQuYXBwZW5kQ2hpbGQoY2hpbGRBcnJbaV0pO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRwYXJlbnQuYXBwZW5kQ2hpbGQoY2hpbGQpO1xuXHR9XG5cdHJldHVybiBjaGlsZDtcbn1cblxuLyoqXG4gKiBIZWxwZXIgZm9yIGNvbnZlcnRpbmcgYSBIVE1MIHN0cmluZyBpbnRvIGEgZG9jdW1lbnQgZnJhZ21lbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gaHRtbFN0cmluZyBUaGUgSFRNTCBzdHJpbmcgdG8gY29udmVydC5cbiAqIEByZXR1cm4geyFFbGVtZW50fSBUaGUgcmVzdWx0aW5nIGRvY3VtZW50IGZyYWdtZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRGcmFnbWVudChodG1sU3RyaW5nKSB7XG5cdGNvbnN0IHRlbXBEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblx0dGVtcERpdi5pbm5lckhUTUwgPSBgPGJyPiR7aHRtbFN0cmluZ31gO1xuXHR0ZW1wRGl2LnJlbW92ZUNoaWxkKHRlbXBEaXYuZmlyc3RDaGlsZCk7XG5cblx0Y29uc3QgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cdHdoaWxlICh0ZW1wRGl2LmZpcnN0Q2hpbGQpIHtcblx0XHRmcmFnbWVudC5hcHBlbmRDaGlsZCh0ZW1wRGl2LmZpcnN0Q2hpbGQpO1xuXHR9XG5cdHJldHVybiBmcmFnbWVudDtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGZpcnN0IGVsZW1lbnQgY29udGFpbnMgdGhlIHNlY29uZCBvbmUuXG4gKiBAZGVwcmVjYXRlZCBVc2UgZWxlbWVudDEuY29udGFpbnMoZWxlbWVudDIpIGRpcmVjdGx5IGluc3RlYWQgb2YgdGhpcyBtZXRob2RcbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQxXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50MlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zKGVsZW1lbnQxLCBlbGVtZW50Mikge1xuXHRpZiAoaXNEb2N1bWVudChlbGVtZW50MSkpIHtcblx0XHQvLyBkb2N1bWVudC5jb250YWlucyBpcyBub3QgZGVmaW5lZCBvbiBJRTksIHNvIGNhbGwgaXQgb24gZG9jdW1lbnRFbGVtZW50IGluc3RlYWQuXG5cdFx0cmV0dXJuIGVsZW1lbnQxLmRvY3VtZW50RWxlbWVudC5jb250YWlucyhlbGVtZW50Mik7XG5cdH0gZWxzZSB7XG5cdFx0cmV0dXJuIGVsZW1lbnQxLmNvbnRhaW5zKGVsZW1lbnQyKTtcblx0fVxufVxuXG4vKipcbiAqIExpc3RlbnMgdG8gdGhlIHNwZWNpZmllZCBldmVudCBvbiB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQsIGJ1dCBvbmx5IGNhbGxzIHRoZVxuICogZ2l2ZW4gY2FsbGJhY2sgbGlzdGVuZXIgd2hlbiBpdCdzIHRyaWdnZXJlZCBieSBlbGVtZW50cyB0aGF0IG1hdGNoIHRoZVxuICogZ2l2ZW4gc2VsZWN0b3Igb3IgdGFyZ2V0IGVsZW1lbnQuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBET00gZWxlbWVudCB0aGUgZXZlbnQgc2hvdWxkIGJlIGxpc3RlbmVkIG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gbGlzdGVuIHRvLlxuICogQHBhcmFtIHshRWxlbWVudHxzdHJpbmd9IHNlbGVjdG9yT3JUYXJnZXQgRWl0aGVyIGFuIGVsZW1lbnQgb3IgY3NzIHNlbGVjdG9yXG4gKiAgICAgdGhhdCBzaG91bGQgbWF0Y2ggdGhlIGV2ZW50IGZvciB0aGUgbGlzdGVuZXIgdG8gYmUgdHJpZ2dlcmVkLlxuICogQHBhcmFtIHshZnVuY3Rpb24oIU9iamVjdCl9IGNhbGxiYWNrIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudFxuICogICAgIGlzIHRyaWdnZXJlZC4gSXQgd2lsbCByZWNlaXZlIHRoZSBub3JtYWxpemVkIGV2ZW50IG9iamVjdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbj19IGRlZmF1bHRMaXN0ZW5lciBPcHRpb25hbCBmbGFnIGluZGljYXRpbmcgaWYgdGhpcyBpcyBhIGRlZmF1bHRcbiAqICAgICBsaXN0ZW5lci4gVGhhdCBtZWFucyB0aGF0IGl0IHdvdWxkIG9ubHkgYmUgZXhlY3V0ZWQgYWZ0ZXIgYWxsIG5vblxuICogICAgIGRlZmF1bHQgbGlzdGVuZXJzLCBhbmQgb25seSBpZiB0aGUgZXZlbnQgaXNuJ3QgcHJldmVudGVkIHZpYVxuICogICAgIGBwcmV2ZW50RGVmYXVsdGAuXG4gKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWxlZ2F0ZShcblx0ZWxlbWVudCxcblx0ZXZlbnROYW1lLFxuXHRzZWxlY3Rvck9yVGFyZ2V0LFxuXHRjYWxsYmFjayxcblx0ZGVmYXVsdExpc3RlbmVyXG4pIHtcblx0Y29uc3QgY3VzdG9tQ29uZmlnID0gY3VzdG9tRXZlbnRzW2V2ZW50TmFtZV07XG5cdGlmIChjdXN0b21Db25maWcgJiYgY3VzdG9tQ29uZmlnLmRlbGVnYXRlKSB7XG5cdFx0ZXZlbnROYW1lID0gY3VzdG9tQ29uZmlnLm9yaWdpbmFsRXZlbnQ7XG5cdFx0Y2FsbGJhY2sgPSBjdXN0b21Db25maWcuaGFuZGxlci5iaW5kKGN1c3RvbUNvbmZpZywgY2FsbGJhY2spO1xuXHR9XG5cblx0aWYgKGRlZmF1bHRMaXN0ZW5lcikge1xuXHRcdC8vIFdyYXAgY2FsbGJhY2sgc28gd2UgZG9uJ3Qgc2V0IHByb3BlcnR5IGRpcmVjdGx5IG9uIGl0LlxuXHRcdGNhbGxiYWNrID0gY2FsbGJhY2suYmluZCgpO1xuXHRcdGNhbGxiYWNrLmRlZmF1bHRMaXN0ZW5lcl8gPSB0cnVlO1xuXHR9XG5cblx0YXR0YWNoRGVsZWdhdGVFdmVudF8oZWxlbWVudCwgZXZlbnROYW1lKTtcblx0aWYgKGlzU3RyaW5nKHNlbGVjdG9yT3JUYXJnZXQpKSB7XG5cdFx0YWRkU2VsZWN0b3JMaXN0ZW5lcl8oZWxlbWVudCwgZXZlbnROYW1lLCBzZWxlY3Rvck9yVGFyZ2V0LCBjYWxsYmFjayk7XG5cdH0gZWxzZSB7XG5cdFx0YWRkRWxlbWVudExpc3RlbmVyXyhzZWxlY3Rvck9yVGFyZ2V0LCBldmVudE5hbWUsIGNhbGxiYWNrKTtcblx0fVxuXG5cdHJldHVybiBuZXcgRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGUoXG5cdFx0aXNTdHJpbmcoc2VsZWN0b3JPclRhcmdldCkgPyBlbGVtZW50IDogc2VsZWN0b3JPclRhcmdldCxcblx0XHRldmVudE5hbWUsXG5cdFx0Y2FsbGJhY2ssXG5cdFx0aXNTdHJpbmcoc2VsZWN0b3JPclRhcmdldCkgPyBzZWxlY3Rvck9yVGFyZ2V0IDogbnVsbFxuXHQpO1xufVxuXG4vKipcbiAqIFZlcmlmaWVzIGlmIHRoZSBlbGVtZW50IGlzIGFibGUgdG8gdHJpZ2dlciB0aGUgQ2xpY2sgZXZlbnQsXG4gKiBzaW11bGF0aW5nIGJyb3dzZXJzIGJlaGF2aW91ciwgYXZvaWRpbmcgZXZlbnQgbGlzdGVuZXJzIHRvIGJlIGNhbGxlZCBieSB0cmlnZ2VyRXZlbnQgbWV0aG9kLlxuICogQHBhcmFtIHtFbGVtZW50fSBub2RlIEVsZW1lbnQgdG8gYmUgY2hlY2tlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIGV2ZW50IG5hbWUuXG4gKiBAcGFyYW0ge09iamVjdD19IGV2ZW50T2JqXG4gKiBAcHJpdmF0ZVxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNBYmxlVG9JbnRlcmFjdFdpdGhfKG5vZGUsIGV2ZW50TmFtZSwgZXZlbnRPYmopIHtcblx0aWYgKGV2ZW50T2JqICYmIGV2ZW50TmFtZSA9PT0gJ2NsaWNrJyAmJiBldmVudE9iai5idXR0b24gPT09IDIpIHtcblx0XHQvLyBGaXJlZm94IHRyaWdnZXJzIFwiY2xpY2tcIiBldmVudHMgb24gdGhlIGRvY3VtZW50IGZvciByaWdodCBjbGlja3MuIFRoaXNcblx0XHQvLyBjYXVzZXMgb3VyIGRlbGVnYXRlIGxvZ2ljIHRvIHRyaWdnZXIgaXQgZm9yIHJlZ3VsYXIgZWxlbWVudHMgdG9vLCB3aGljaFxuXHRcdC8vIHNob3VsZG4ndCBoYXBwZW4uIElnbm9yaW5nIHRoZW0gaGVyZS5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRjb25zdCBtYXRjaGVzU2VsZWN0b3IgPSBbXG5cdFx0J0JVVFRPTicsXG5cdFx0J0lOUFVUJyxcblx0XHQnU0VMRUNUJyxcblx0XHQnVEVYVEFSRUEnLFxuXHRcdCdGSUVMRFNFVCcsXG5cdF07XG5cdGlmIChldmVudE5hbWUgPT09ICdjbGljaycgJiYgbWF0Y2hlc1NlbGVjdG9yLmluZGV4T2Yobm9kZS50YWdOYW1lKSA+IC0xKSB7XG5cdFx0cmV0dXJuICEobm9kZS5kaXNhYmxlZCB8fCBwYXJlbnQobm9kZSwgJ2ZpZWxkc2V0W2Rpc2FibGVkXScpKTtcblx0fVxuXHRyZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBhIE5vZGVMaXN0IG9yIGxpa2Ugb25lLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgbGlrZSBhIE5vZGVMaXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNOb2RlTGlzdExpa2UodmFsKSB7XG5cdHJldHVybiAoXG5cdFx0aXNEZWZBbmROb3ROdWxsKHZhbCkgJiZcblx0XHR0eXBlb2YgdmFsLmxlbmd0aCA9PT0gJ251bWJlcicgJiZcblx0XHR0eXBlb2YgdmFsLml0ZW0gPT09ICdmdW5jdGlvbidcblx0KTtcbn1cblxuLyoqXG4gKiBJbnNlcnRzIG5vZGUgaW4gZG9jdW1lbnQgYXMgbGFzdCBlbGVtZW50LlxuICogQHBhcmFtIHtFbGVtZW50fSBub2RlIEVsZW1lbnQgdG8gcmVtb3ZlIGNoaWxkcmVuIGZyb20uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnRlckRvY3VtZW50KG5vZGUpIHtcblx0bm9kZSAmJiBhcHBlbmQoZG9jdW1lbnQuYm9keSwgbm9kZSk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBub2RlIGZyb20gZG9jdW1lbnQuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGUgRWxlbWVudCB0byByZW1vdmUgY2hpbGRyZW4gZnJvbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4aXREb2N1bWVudChub2RlKSB7XG5cdGlmIChub2RlICYmIG5vZGUucGFyZW50Tm9kZSkge1xuXHRcdG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcblx0fVxufVxuXG4vKipcbiAqIFRoaXMgaXMgY2FsbGVkIHdoZW4gYW4gZXZlbnQgaXMgdHJpZ2dlcmVkIGJ5IGEgZGVsZWdhdGUgbGlzdGVuZXIuIEFsbFxuICogbWF0Y2hpbmcgbGlzdGVuZXJzIG9mIHRoaXMgZXZlbnQgdHlwZSBmcm9tIGB0YXJnZXRgIHRvIGBjdXJyZW50VGFyZ2V0YCB3aWxsXG4gKiBiZSB0cmlnZ2VyZWQuXG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgVGhlIGV2ZW50IHBheWxvYWQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBGYWxzZSBpZiBhdCBsZWFzdCBvbmUgb2YgdGhlIHRyaWdnZXJlZCBjYWxsYmFja3MgcmV0dXJuc1xuICogICAgIGZhbHNlLCBvciB0cnVlIG90aGVyd2lzZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZURlbGVnYXRlRXZlbnRfKGV2ZW50KSB7XG5cdG5vcm1hbGl6ZURlbGVnYXRlRXZlbnRfKGV2ZW50KTtcblx0bGV0IHJldCA9IHRydWU7XG5cdGNvbnN0IGNvbnRhaW5lciA9IGV2ZW50LmN1cnJlbnRUYXJnZXQ7XG5cdGNvbnN0IGRlZkZucyA9IFtdO1xuXG5cdHJldCAmPSB0cmlnZ2VyRGVsZWdhdGVkTGlzdGVuZXJzXyhjb250YWluZXIsIGV2ZW50LCBkZWZGbnMpO1xuXHRyZXQgJj0gdHJpZ2dlckRlZmF1bHREZWxlZ2F0ZWRMaXN0ZW5lcnNfKGRlZkZucywgZXZlbnQpO1xuXG5cdGV2ZW50LmRlbGVnYXRlVGFyZ2V0ID0gbnVsbDtcblx0ZXZlbnRbTEFTVF9DT05UQUlORVJdID0gY29udGFpbmVyO1xuXHRyZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZWxlbWVudCBoYXMgdGhlIHJlcXVlc3RlZCBjc3MgY2xhc3MuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzQ2xhc3MoZWxlbWVudCwgY2xhc3NOYW1lKSB7XG5cdGlmICgnY2xhc3NMaXN0JyBpbiBlbGVtZW50KSB7XG5cdFx0cmV0dXJuIGhhc0NsYXNzV2l0aE5hdGl2ZV8oZWxlbWVudCwgY2xhc3NOYW1lKTtcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gaGFzQ2xhc3NXaXRob3V0TmF0aXZlXyhlbGVtZW50LCBjbGFzc05hbWUpO1xuXHR9XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IGhhcyB0aGUgcmVxdWVzdGVkIGNzcyBjbGFzcyB1c2luZyBjbGFzc0xpc3QuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gaGFzQ2xhc3NXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc05hbWUpIHtcblx0cmV0dXJuIChcblx0XHRjbGFzc05hbWUuaW5kZXhPZignICcpID09PSAtMSAmJiBlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhjbGFzc05hbWUpXG5cdCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IGhhcyB0aGUgcmVxdWVzdGVkIGNzcyBjbGFzcyB3aXRob3V0IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc05hbWVcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBoYXNDbGFzc1dpdGhvdXROYXRpdmVfKGVsZW1lbnQsIGNsYXNzTmFtZSkge1xuXHRyZXR1cm4gKFxuXHRcdGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYC5pbmRleE9mKGAgJHtjbGFzc05hbWV9IGApID49IDAgJiZcblx0XHRjbGFzc05hbWUuc3BsaXQoJyAnKS5sZW5ndGggPT09IDFcblx0KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGdpdmVuIGVsZW1lbnQgaXMgZW1wdHkgb3Igbm90LlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRW1wdHkoZWxlbWVudCkge1xuXHRyZXR1cm4gZWxlbWVudC5jaGlsZE5vZGVzLmxlbmd0aCA9PT0gMDtcbn1cblxuLyoqXG4gKiBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBFbGVtZW50Lm1hdGNoZXMgZnVuY3Rpb24sIHRoaXMgbWV0aG9kXG4gKiBjaGVjayBpZiBhbiBlbGVtZW50IG1hdGNoZXMgYSBnaXZlbiBzZWxlY3Rvci5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2goZWxlbWVudCwgc2VsZWN0b3IpIHtcblx0aWYgKCFlbGVtZW50IHx8IGVsZW1lbnQubm9kZVR5cGUgIT09IDEpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRjb25zdCBwID0gRWxlbWVudC5wcm90b3R5cGU7XG5cdGNvbnN0IG0gPVxuXHRcdHAubWF0Y2hlcyB8fFxuXHRcdHAud2Via2l0TWF0Y2hlc1NlbGVjdG9yIHx8XG5cdFx0cC5tb3pNYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRwLm1zTWF0Y2hlc1NlbGVjdG9yIHx8XG5cdFx0cC5vTWF0Y2hlc1NlbGVjdG9yO1xuXHRpZiAobSkge1xuXHRcdHJldHVybiBtLmNhbGwoZWxlbWVudCwgc2VsZWN0b3IpO1xuXHR9XG5cblx0cmV0dXJuIG1hdGNoRmFsbGJhY2tfKGVsZW1lbnQsIHNlbGVjdG9yKTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhbiBlbGVtZW50IG1hdGNoZXMgYSBnaXZlbiBzZWxlY3RvciwgdXNpbmcgYW4gaW50ZXJuYWwgaW1wbGVtZW50YXRpb25cbiAqIGluc3RlYWQgb2YgY2FsbGluZyBleGlzdGluZyBqYXZhc2NyaXB0IGZ1bmN0aW9ucy5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gbWF0Y2hGYWxsYmFja18oZWxlbWVudCwgc2VsZWN0b3IpIHtcblx0Y29uc3QgcGFyZW50Tm9kZSA9IGVsZW1lbnQucGFyZW50Tm9kZTtcblxuXHRpZiAocGFyZW50Tm9kZSkge1xuXHRcdGNvbnN0IG5vZGVzID0gcGFyZW50Tm9kZS5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKTtcblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyArK2kpIHtcblx0XHRcdGlmIChub2Rlc1tpXSA9PT0gZWxlbWVudCkge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbmV4dCBzaWJsaW5nIG9mIHRoZSBnaXZlbiBlbGVtZW50IHRoYXQgbWF0Y2hlcyB0aGUgc3BlY2lmaWVkXG4gKiBzZWxlY3Rvciwgb3IgbnVsbCBpZiB0aGVyZSBpcyBub25lLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHs/c3RyaW5nfSBzZWxlY3RvclxuICogQHJldHVybiB7RWxlbWVudHxudWxsfVxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV4dChlbGVtZW50LCBzZWxlY3Rvcikge1xuXHRkbyB7XG5cdFx0ZWxlbWVudCA9IGVsZW1lbnQubmV4dFNpYmxpbmc7XG5cdFx0aWYgKGVsZW1lbnQgJiYgbWF0Y2goZWxlbWVudCwgc2VsZWN0b3IpKSB7XG5cdFx0XHRyZXR1cm4gZWxlbWVudDtcblx0XHR9XG5cdH0gd2hpbGUgKGVsZW1lbnQpO1xuXHRyZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBOb3JtYWxpemVzIHRoZSBldmVudCBwYXlsb2FkIGZvciBkZWxlZ2F0ZSBsaXN0ZW5lcnMuXG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnRcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZURlbGVnYXRlRXZlbnRfKGV2ZW50KSB7XG5cdGV2ZW50LnN0b3BQcm9wYWdhdGlvbiA9IHN0b3BQcm9wYWdhdGlvbl87XG5cdGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbiA9IHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbl87XG59XG5cbi8qKlxuICogTGlzdGVucyB0byB0aGUgc3BlY2lmaWVkIGV2ZW50IG9uIHRoZSBnaXZlbiBET00gZWxlbWVudC4gVGhpcyBmdW5jdGlvbiBub3JtYWxpemVzXG4gKiBET00gZXZlbnQgcGF5bG9hZHMgYW5kIGZ1bmN0aW9ucyBzbyB0aGV5J2xsIHdvcmsgdGhlIHNhbWUgd2F5IG9uIGFsbCBzdXBwb3J0ZWRcbiAqIGJyb3dzZXJzLlxuICogQHBhcmFtIHshRWxlbWVudHxzdHJpbmd9IGVsZW1lbnQgVGhlIERPTSBlbGVtZW50IHRvIGxpc3RlbiB0byB0aGUgZXZlbnQgb24sIG9yXG4gKiAgIGEgc2VsZWN0b3IgdGhhdCBzaG91bGQgYmUgZGVsZWdhdGVkIG9uIHRoZSBlbnRpcmUgZG9jdW1lbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBsaXN0ZW4gdG8uXG4gKiBAcGFyYW0geyFmdW5jdGlvbighT2JqZWN0KX0gY2FsbGJhY2sgRnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzXG4gKiAgIHRyaWdnZXJlZC4gSXQgd2lsbCByZWNlaXZlIHRoZSBub3JtYWxpemVkIGV2ZW50IG9iamVjdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gY2FwdHVyZSBGbGFnIGluZGljYXRpbmcgaWYgbGlzdGVuZXIgc2hvdWxkIGJlIHRyaWdnZXJlZFxuICogICBkdXJpbmcgY2FwdHVyZSBwaGFzZSwgaW5zdGVhZCBvZiBkdXJpbmcgdGhlIGJ1YmJsaW5nIHBoYXNlLiBEZWZhdWx0cyB0byBmYWxzZS5cbiAqIEByZXR1cm4geyFEb21FdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uKGVsZW1lbnQsIGV2ZW50TmFtZSwgY2FsbGJhY2ssIGNhcHR1cmUpIHtcblx0aWYgKGlzU3RyaW5nKGVsZW1lbnQpKSB7XG5cdFx0cmV0dXJuIGRlbGVnYXRlKGRvY3VtZW50LCBldmVudE5hbWUsIGVsZW1lbnQsIGNhbGxiYWNrKTtcblx0fVxuXHRjb25zdCBjdXN0b21Db25maWcgPSBjdXN0b21FdmVudHNbZXZlbnROYW1lXTtcblx0aWYgKGN1c3RvbUNvbmZpZyAmJiBjdXN0b21Db25maWcuZXZlbnQpIHtcblx0XHRldmVudE5hbWUgPSBjdXN0b21Db25maWcub3JpZ2luYWxFdmVudDtcblx0XHRjYWxsYmFjayA9IGN1c3RvbUNvbmZpZy5oYW5kbGVyLmJpbmQoY3VzdG9tQ29uZmlnLCBjYWxsYmFjayk7XG5cdH1cblx0ZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIGNhcHR1cmUpO1xuXHRyZXR1cm4gbmV3IERvbUV2ZW50SGFuZGxlKGVsZW1lbnQsIGV2ZW50TmFtZSwgY2FsbGJhY2ssIGNhcHR1cmUpO1xufVxuXG4vKipcbiAqIElFMTEgZG9lc24ndCBzdXBwb3J0IG9uY2UgZXZlbnQgbGlzdGVuZXIgb3B0aW9uLCB0aGlzIG1ldGhvZFxuICogTGlzdGVucyB0byB0aGUgc3BlY2lmaWVkIGV2ZW50IG9uIHRoZSBnaXZlbiBET00gZWxlbWVudCBvbmNlLiBUaGlzXG4gKiBmdW5jdGlvbiBub3JtYWxpemVzIERPTSBldmVudCBwYXlsb2FkcyBhbmQgZnVuY3Rpb25zIHNvIHRoZXknbGwgd29yayB0aGVcbiAqIHNhbWUgd2F5IG9uIGFsbCBzdXBwb3J0ZWQgYnJvd3NlcnMuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBET00gZWxlbWVudCB0byBsaXN0ZW4gdG8gdGhlIGV2ZW50IG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gbGlzdGVuIHRvLlxuICogQHBhcmFtIHshZnVuY3Rpb24oIU9iamVjdCl9IGNhbGxiYWNrIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudFxuICogICBpcyB0cmlnZ2VyZWQuIEl0IHdpbGwgcmVjZWl2ZSB0aGUgbm9ybWFsaXplZCBldmVudCBvYmplY3QuXG4gKiBAcmV0dXJuIHshRG9tRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbmNlKGVsZW1lbnQsIGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcblx0Y29uc3QgZG9tRXZlbnRIYW5kbGUgPSBvbihlbGVtZW50LCBldmVudE5hbWUsIGZ1bmN0aW9uKCkge1xuXHRcdGRvbUV2ZW50SGFuZGxlLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0cmV0dXJuIGNhbGxiYWNrLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fSk7XG5cdHJldHVybiBkb21FdmVudEhhbmRsZTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBmaXJzdCBwYXJlbnQgZnJvbSB0aGUgZ2l2ZW4gZWxlbWVudCB0aGF0IG1hdGNoZXMgdGhlIHNwZWNpZmllZFxuICogc2VsZWN0b3IsIG9yIG51bGwgaWYgbm9uZSBtYXRjaC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICogQHJldHVybiB7RWxlbWVudH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcmVudChlbGVtZW50LCBzZWxlY3Rvcikge1xuXHRyZXR1cm4gY2xvc2VzdChlbGVtZW50LnBhcmVudE5vZGUsIHNlbGVjdG9yKTtcbn1cblxuLyoqXG4gKiBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBFbGVtZW50LnByZXBlbmQgZnVuY3Rpb24sIHRoaXMgbWV0aG9kXG4gKiBpbnNlcnRzIGEgbm9kZSBiZWZvcmUgZmlyc3QgY2hpbGQgb2YgdGhlIHBhcmVudC4gSWYgY2hpbGQgaXMgYSBIVE1MIHN0cmluZ1xuICogaXQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gZG9jdW1lbnQgZnJhZ21lbnQgYmVmb3JlIHByZXBlbmRpbmcgaXQgdG8gdGhlIHBhcmVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IHBhcmVudCBUaGUgbm9kZSB0byBwcmVwZW5kIHRvLlxuICogQHBhcmFtIHshKEVsZW1lbnR8Tm9kZUxpc3R8c3RyaW5nKX0gY2hpbGQgVGhlIHRoaW5nIHRvIHByZXBlbmQgdG8gdGhlIHBhcmVudC5cbiAqIEByZXR1cm4geyFFbGVtZW50fSBUaGUgcHJlcGVuZGVkIGNoaWxkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlcGVuZChwYXJlbnQsIGNoaWxkKSB7XG5cdGlmIChpc1N0cmluZyhjaGlsZCkpIHtcblx0XHRjaGlsZCA9IGJ1aWxkRnJhZ21lbnQoY2hpbGQpO1xuXHR9XG5cblx0aWYgKCFpc05vZGVMaXN0TGlrZShjaGlsZCkgJiYgIWlzRGVmQW5kTm90TnVsbChwYXJlbnQuZmlyc3RDaGlsZCkpIHtcblx0XHRyZXR1cm4gYXBwZW5kKHBhcmVudCwgY2hpbGQpO1xuXHR9XG5cblx0aWYgKGlzTm9kZUxpc3RMaWtlKGNoaWxkKSkge1xuXHRcdGNvbnN0IGNoaWxkQXJyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoY2hpbGQpO1xuXHRcdGZvciAobGV0IGkgPSBjaGlsZEFyci5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuXHRcdFx0cGFyZW50Lmluc2VydEJlZm9yZShjaGlsZEFycltpXSwgcGFyZW50LmZpcnN0Q2hpbGQpO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRwYXJlbnQuaW5zZXJ0QmVmb3JlKGNoaWxkLCBwYXJlbnQuZmlyc3RDaGlsZCk7XG5cdH1cblxuXHRyZXR1cm4gY2hpbGQ7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgY3VzdG9tIGV2ZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgY3VzdG9tIGV2ZW50LlxuICogQHBhcmFtIHshT2JqZWN0fSBjdXN0b21Db25maWcgQW4gb2JqZWN0IHdpdGggaW5mb3JtYXRpb24gYWJvdXQgaG93IHRoZSBldmVudFxuICogICBzaG91bGQgYmUgaGFuZGxlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCBjdXN0b21Db25maWcpIHtcblx0Y3VzdG9tRXZlbnRzW2V2ZW50TmFtZV0gPSBjdXN0b21Db25maWc7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBhbGwgdGhlIGNoaWxkIG5vZGVzIG9uIGEgRE9NIG5vZGUuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGUgRWxlbWVudCB0byByZW1vdmUgY2hpbGRyZW4gZnJvbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUNoaWxkcmVuKG5vZGUpIHtcblx0bGV0IGNoaWxkO1xuXHR3aGlsZSAoKGNoaWxkID0gbm9kZS5maXJzdENoaWxkKSkge1xuXHRcdG5vZGUucmVtb3ZlQ2hpbGQoY2hpbGQpO1xuXHR9XG59XG5cbi8qKlxuICogUmVtb3ZlcyB0aGUgcmVxdWVzdGVkIENTUyBjbGFzc2VzIGZyb20gYW4gZWxlbWVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR8IU5vZGVMaXN0fSBlbGVtZW50cyBUaGUgZWxlbWVudCBvciBlbGVtZW50cyB0byByZW1vdmUgQ1NTIGNsYXNzZXMgZnJvbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIHJlbW92ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUNsYXNzZXMoZWxlbWVudHMsIGNsYXNzZXMpIHtcblx0aWYgKCFpc09iamVjdChlbGVtZW50cykgfHwgIWlzU3RyaW5nKGNsYXNzZXMpKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0aWYgKCFlbGVtZW50cy5sZW5ndGgpIHtcblx0XHRlbGVtZW50cyA9IFtlbGVtZW50c107XG5cdH1cblxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKCdjbGFzc0xpc3QnIGluIGVsZW1lbnRzW2ldKSB7XG5cdFx0XHRyZW1vdmVDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZW1vdmVDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIFJlbW92ZXMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQgdXNpbmcgY2xhc3NMaXN0LlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB0byByZW1vdmUgQ1NTIGNsYXNzZXMgZnJvbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIHJlbW92ZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZUNsYXNzZXNXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGNsYXNzZXMuc3BsaXQoJyAnKS5mb3JFYWNoKGZ1bmN0aW9uKGNsYXNzTmFtZSkge1xuXHRcdGlmIChjbGFzc05hbWUpIHtcblx0XHRcdGVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuXHRcdH1cblx0fSk7XG59XG5cbi8qKlxuICogSUUxMSBkb2Vzbid0IHN1cHBvcnQgRWxlbWVudC5jbGFzc0xpc3QsIHRoaXMgbWV0aG9kXG4gKiByZW1vdmVzIHRoZSByZXF1ZXN0ZWQgQ1NTIGNsYXNzZXMgZnJvbSBhbiBlbGVtZW50IHdpdGhvdXQgdXNpbmcgY2xhc3NMaXN0LlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB0byByZW1vdmUgQ1NTIGNsYXNzZXMgZnJvbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIHJlbW92ZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZUNsYXNzZXNXaXRob3V0TmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGxldCBlbGVtZW50Q2xhc3NOYW1lID0gYCAke2VsZW1lbnQuY2xhc3NOYW1lfSBgO1xuXG5cdGNsYXNzZXMgPSBjbGFzc2VzLnNwbGl0KCcgJyk7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjbGFzc2VzLmxlbmd0aDsgaSsrKSB7XG5cdFx0ZWxlbWVudENsYXNzTmFtZSA9IGVsZW1lbnRDbGFzc05hbWUucmVwbGFjZShgICR7Y2xhc3Nlc1tpXX0gYCwgJyAnKTtcblx0fVxuXG5cdGVsZW1lbnQuY2xhc3NOYW1lID0gZWxlbWVudENsYXNzTmFtZS50cmltKCk7XG59XG5cbi8qKlxuICogUmVwbGFjZXMgdGhlIGZpcnN0IGVsZW1lbnQgd2l0aCB0aGUgc2Vjb25kLlxuICogQGRlcHJlY2F0ZWQgVXNlIGVsZW1lbnQxLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKGVsZW1lbnQyLCBlbGVtZW50MSlcbiAqIGRpcmVjdGx5IGluc3RlYWQgb2YgdGhpcyBtZXRob2RcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudDFcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudDJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2UoZWxlbWVudDEsIGVsZW1lbnQyKSB7XG5cdGlmIChlbGVtZW50MSAmJiBlbGVtZW50MiAmJiBlbGVtZW50MSAhPT0gZWxlbWVudDIgJiYgZWxlbWVudDEucGFyZW50Tm9kZSkge1xuXHRcdGVsZW1lbnQxLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKGVsZW1lbnQyLCBlbGVtZW50MSk7XG5cdH1cbn1cblxuLyoqXG4gKiBUaGUgZnVuY3Rpb24gdGhhdCByZXBsYWNlcyBgc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uX2AgZm9yIGV2ZW50cy5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbl8oKSB7XG5cdGNvbnN0IGV2ZW50ID0gdGhpczsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRldmVudC5zdG9wcGVkID0gdHJ1ZTtcblx0ZXZlbnQuc3RvcHBlZEltbWVkaWF0ZSA9IHRydWU7XG5cdEV2ZW50LnByb3RvdHlwZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24uY2FsbChldmVudCk7XG59XG5cbi8qKlxuICogVGhlIGZ1bmN0aW9uIHRoYXQgcmVwbGFjZXMgYHN0b3BQcm9wYWdhdGlvbmAgZm9yIGV2ZW50cy5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHN0b3BQcm9wYWdhdGlvbl8oKSB7XG5cdGNvbnN0IGV2ZW50ID0gdGhpczsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRldmVudC5zdG9wcGVkID0gdHJ1ZTtcblx0RXZlbnQucHJvdG90eXBlLnN0b3BQcm9wYWdhdGlvbi5jYWxsKGV2ZW50KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGdpdmVuIGVsZW1lbnQgc3VwcG9ydHMgdGhlIGdpdmVuIGV2ZW50IHR5cGUuXG4gKiBAcGFyYW0geyFFbGVtZW50fHN0cmluZ30gZWxlbWVudCBUaGUgRE9NIGVsZW1lbnQgb3IgZWxlbWVudCB0YWcgbmFtZSB0byBjaGVjay5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGNoZWNrLlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1cHBvcnRzRXZlbnQoZWxlbWVudCwgZXZlbnROYW1lKSB7XG5cdGlmIChjdXN0b21FdmVudHNbZXZlbnROYW1lXSkge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0aWYgKGlzU3RyaW5nKGVsZW1lbnQpKSB7XG5cdFx0aWYgKCFlbGVtZW50c0J5VGFnX1tlbGVtZW50XSkge1xuXHRcdFx0ZWxlbWVudHNCeVRhZ19bZWxlbWVudF0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGVsZW1lbnQpO1xuXHRcdH1cblx0XHRlbGVtZW50ID0gZWxlbWVudHNCeVRhZ19bZWxlbWVudF07XG5cdH1cblxuXHRjb25zdCB0YWcgPSBlbGVtZW50LnRhZ05hbWU7XG5cdGlmICghc3VwcG9ydENhY2hlX1t0YWddIHx8ICFzdXBwb3J0Q2FjaGVfW3RhZ10uaGFzT3duUHJvcGVydHkoZXZlbnROYW1lKSkge1xuXHRcdHN1cHBvcnRDYWNoZV9bdGFnXSA9IHN1cHBvcnRDYWNoZV9bdGFnXSB8fCB7fTtcblx0XHRzdXBwb3J0Q2FjaGVfW3RhZ11bZXZlbnROYW1lXSA9ICdvbicgKyBldmVudE5hbWUgaW4gZWxlbWVudDtcblx0fVxuXHRyZXR1cm4gc3VwcG9ydENhY2hlX1t0YWddW2V2ZW50TmFtZV07XG59XG5cbi8qKlxuICogVGhpcyB0cmlnZ2VycyBhbGwgZGVmYXVsdCBtYXRjaGVkIGRlbGVnYXRlZCBsaXN0ZW5lcnMgb2YgYSBnaXZlbiBldmVudCB0eXBlLlxuICogQHBhcmFtIHshQXJyYXl9IGRlZkZucyBBcnJheSB0byBjb2xsZWN0IGRlZmF1bHQgbGlzdGVuZXJzIGluLCBpbnN0ZWFkXG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnRcbiAqIEByZXR1cm4ge2Jvb2xlYW59IEZhbHNlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdHJpZ2dlcmVkIGNhbGxiYWNrcyByZXR1cm5zXG4gKiAgICAgZmFsc2UsIG9yIHRydWUgb3RoZXJ3aXNlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gdHJpZ2dlckRlZmF1bHREZWxlZ2F0ZWRMaXN0ZW5lcnNfKGRlZkZucywgZXZlbnQpIHtcblx0bGV0IHJldCA9IHRydWU7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBkZWZGbnMubGVuZ3RoICYmICFldmVudC5kZWZhdWx0UHJldmVudGVkOyBpKyspIHtcblx0XHRldmVudC5kZWxlZ2F0ZVRhcmdldCA9IGRlZkZuc1tpXS5lbGVtZW50O1xuXHRcdHJldCAmPSBkZWZGbnNbaV0uZm4oZXZlbnQpO1xuXHR9XG5cblx0cmV0dXJuIHJldDtcbn1cblxuLyoqXG4gKiBUaGlzIHRyaWdnZXJzIGFsbCBtYXRjaGVkIGRlbGVnYXRlZCBsaXN0ZW5lcnMgb2YgYSBnaXZlbiBldmVudCB0eXBlIHdoZW4gaXRzXG4gKiBkZWxlZ2F0ZWQgdGFyZ2V0IGlzIGFibGUgdG8gaW50ZXJhY3QuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBjb250YWluZXJcbiAqIEBwYXJhbSB7IUV2ZW50fSBldmVudFxuICogQHBhcmFtIHshQXJyYXl9IGRlZmF1bHRGbnMgQXJyYXkgdG8gY29sbGVjdCBkZWZhdWx0IGxpc3RlbmVycyBpbiwgaW5zdGVhZFxuICogICAgIG9mIHJ1bm5pbmcgdGhlbS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IEZhbHNlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdHJpZ2dlcmVkIGNhbGxiYWNrcyByZXR1cm5zXG4gKiAgICAgZmFsc2UsIG9yIHRydWUgb3RoZXJ3aXNlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gdHJpZ2dlckRlbGVnYXRlZExpc3RlbmVyc18oY29udGFpbmVyLCBldmVudCwgZGVmYXVsdEZucykge1xuXHRsZXQgcmV0ID0gdHJ1ZTtcblx0bGV0IGN1cnJFbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuXHRjb25zdCBsaW1pdCA9IGNvbnRhaW5lci5wYXJlbnROb2RlO1xuXG5cdHdoaWxlIChjdXJyRWxlbWVudCAmJiBjdXJyRWxlbWVudCAhPT0gbGltaXQgJiYgIWV2ZW50LnN0b3BwZWQpIHtcblx0XHRpZiAoaXNBYmxlVG9JbnRlcmFjdFdpdGhfKGN1cnJFbGVtZW50LCBldmVudC50eXBlLCBldmVudCkpIHtcblx0XHRcdGV2ZW50LmRlbGVnYXRlVGFyZ2V0ID0gY3VyckVsZW1lbnQ7XG5cdFx0XHRyZXQgJj0gdHJpZ2dlckVsZW1lbnRMaXN0ZW5lcnNfKGN1cnJFbGVtZW50LCBldmVudCwgZGVmYXVsdEZucyk7XG5cdFx0XHRyZXQgJj0gdHJpZ2dlclNlbGVjdG9yTGlzdGVuZXJzXyhcblx0XHRcdFx0Y29udGFpbmVyLFxuXHRcdFx0XHRjdXJyRWxlbWVudCxcblx0XHRcdFx0ZXZlbnQsXG5cdFx0XHRcdGRlZmF1bHRGbnNcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGN1cnJFbGVtZW50ID0gY3VyckVsZW1lbnQucGFyZW50Tm9kZTtcblx0fVxuXG5cdHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIGFyZ3VtZW50IHRvIGEgRE9NIGVsZW1lbnQuIFN0cmluZ3MgYXJlIGFzc3VtZWQgdG9cbiAqIGJlIHNlbGVjdG9ycywgYW5kIHNvIGEgbWF0Y2hlZCBlbGVtZW50IHdpbGwgYmUgcmV0dXJuZWQuIElmIHRoZSBhcmdcbiAqIGlzIGFscmVhZHkgYSBET00gZWxlbWVudCBpdCB3aWxsIGJlIHRoZSByZXR1cm4gdmFsdWUuXG4gKiBAcGFyYW0ge3N0cmluZ3xFbGVtZW50fERvY3VtZW50fSBzZWxlY3Rvck9yRWxlbWVudFxuICogQHJldHVybiB7RWxlbWVudH0gVGhlIGNvbnZlcnRlZCBlbGVtZW50LCBvciBudWxsIGlmIG5vbmUgd2FzIGZvdW5kLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9FbGVtZW50KHNlbGVjdG9yT3JFbGVtZW50KSB7XG5cdGlmIChcblx0XHRpc0VsZW1lbnQoc2VsZWN0b3JPckVsZW1lbnQpIHx8XG5cdFx0aXNEb2N1bWVudChzZWxlY3Rvck9yRWxlbWVudCkgfHxcblx0XHRpc0RvY3VtZW50RnJhZ21lbnQoc2VsZWN0b3JPckVsZW1lbnQpXG5cdCkge1xuXHRcdHJldHVybiBzZWxlY3Rvck9yRWxlbWVudDtcblx0fSBlbHNlIGlmIChpc1N0cmluZyhzZWxlY3Rvck9yRWxlbWVudCkpIHtcblx0XHRyZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvck9yRWxlbWVudCk7XG5cdH0gZWxzZSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cbn1cblxuLyoqXG4gKiBBZGRzIG9yIHJlbW92ZXMgb25lIG9yIG1vcmUgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQuIElmIGFueSBvZiB0aGUgY2xhc3Nlc1xuICogaXMgcHJlc2VudCwgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQsIG9yIGFkZGVkIG90aGVyd2lzZS5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgd2hpY2ggY2xhc3NlcyB3aWxsIGJlIHRvZ2dsZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NlcyBUaGUgY2xhc3NlcyB3aGljaCBoYXZlIHRvIGFkZGVkIG9yIHJlbW92ZWQgZnJvbSB0aGUgZWxlbWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvZ2dsZUNsYXNzZXMoZWxlbWVudCwgY2xhc3Nlcykge1xuXHRpZiAoIWlzT2JqZWN0KGVsZW1lbnQpIHx8ICFpc1N0cmluZyhjbGFzc2VzKSkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdGlmICgnY2xhc3NMaXN0JyBpbiBlbGVtZW50KSB7XG5cdFx0dG9nZ2xlQ2xhc3Nlc1dpdGhOYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpO1xuXHR9IGVsc2Uge1xuXHRcdHRvZ2dsZUNsYXNzZXNXaXRob3V0TmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKTtcblx0fVxufVxuXG4vKipcbiAqIEFkZHMgb3IgcmVtb3ZlcyBvbmUgb3IgbW9yZSBjbGFzc2VzIGZyb20gYW4gZWxlbWVudCB1c2luZyBjbGFzc0xpc3QuXG4gKiBJZiBhbnkgb2YgdGhlIGNsYXNzZXMgaXMgcHJlc2VudCwgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQsXG4gKiBvciBhZGRlZCBvdGhlcndpc2UuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHdoaWNoIGNsYXNzZXMgd2lsbCBiZSB0b2dnbGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgVGhlIGNsYXNzZXMgd2hpY2ggaGF2ZSB0byBhZGRlZCBvciByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0b2dnbGVDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudCwgY2xhc3Nlcykge1xuXHRjbGFzc2VzLnNwbGl0KCcgJykuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcblx0XHRlbGVtZW50LmNsYXNzTGlzdC50b2dnbGUoY2xhc3NOYW1lKTtcblx0fSk7XG59XG5cbi8qKlxuICogSUUxMSBkb2Vzbid0IHN1cHBvcnQgRWxlbWVudC5jbGFzc0xpc3QsIHRoaXMgbWV0aG9kXG4gKiBhZGRzIG9yIHJlbW92ZXMgb25lIG9yIG1vcmUgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQgd2l0aG91dCB1c2luZyBjbGFzc0xpc3QuXG4gKiBJZiBhbnkgb2YgdGhlIGNsYXNzZXMgaXMgcHJlc2VudCwgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQsXG4gKiBvciBhZGRlZCBvdGhlcndpc2UuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHdoaWNoIGNsYXNzZXMgd2lsbCBiZSB0b2dnbGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgVGhlIGNsYXNzZXMgd2hpY2ggaGF2ZSB0byBhZGRlZCBvciByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0b2dnbGVDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudCwgY2xhc3Nlcykge1xuXHRsZXQgZWxlbWVudENsYXNzTmFtZSA9IGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYDtcblxuXHRjbGFzc2VzID0gY2xhc3Nlcy5zcGxpdCgnICcpO1xuXG5cdGZvciAobGV0IGkgPSAwOyBpIDwgY2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuXHRcdGNvbnN0IGNsYXNzTmFtZSA9IGAgJHtjbGFzc2VzW2ldfSBgO1xuXHRcdGNvbnN0IGNsYXNzSW5kZXggPSBlbGVtZW50Q2xhc3NOYW1lLmluZGV4T2YoY2xhc3NOYW1lKTtcblxuXHRcdGlmIChjbGFzc0luZGV4ID09PSAtMSkge1xuXHRcdFx0ZWxlbWVudENsYXNzTmFtZSA9IGAke2VsZW1lbnRDbGFzc05hbWV9JHtjbGFzc2VzW2ldfSBgO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zdCBiZWZvcmUgPSBlbGVtZW50Q2xhc3NOYW1lLnN1YnN0cmluZygwLCBjbGFzc0luZGV4KTtcblx0XHRcdGNvbnN0IGFmdGVyID0gZWxlbWVudENsYXNzTmFtZS5zdWJzdHJpbmcoXG5cdFx0XHRcdGNsYXNzSW5kZXggKyBjbGFzc05hbWUubGVuZ3RoXG5cdFx0XHQpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdFx0XHRlbGVtZW50Q2xhc3NOYW1lID0gYCR7YmVmb3JlfSAke2FmdGVyfWA7XG5cdFx0fVxuXHR9XG5cblx0ZWxlbWVudC5jbGFzc05hbWUgPSBlbGVtZW50Q2xhc3NOYW1lLnRyaW0oKTtcbn1cblxuLyoqXG4gKiBUcmlnZ2VycyBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZ2l2ZW4gZXZlbnQgdHlwZSB0aGF0IGFyZSBzdG9yZWQgaW4gdGhlXG4gKiBzcGVjaWZpZWQgZWxlbWVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7IUV2ZW50fSBldmVudFxuICogQHBhcmFtIHshQXJyYXl9IGRlZmF1bHRGbnMgQXJyYXkgdG8gY29sbGVjdCBkZWZhdWx0IGxpc3RlbmVycyBpbiwgaW5zdGVhZFxuICogICAgIG9mIHJ1bm5pbmcgdGhlbS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IEZhbHNlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdHJpZ2dlcmVkIGNhbGxiYWNrcyByZXR1cm5zXG4gKiAgICAgZmFsc2UsIG9yIHRydWUgb3RoZXJ3aXNlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gdHJpZ2dlckVsZW1lbnRMaXN0ZW5lcnNfKGVsZW1lbnQsIGV2ZW50LCBkZWZhdWx0Rm5zKSB7XG5cdGNvbnN0IGxhc3RDb250YWluZXIgPSBldmVudFtMQVNUX0NPTlRBSU5FUl07XG5cdGlmICghaXNEZWYobGFzdENvbnRhaW5lcikgfHwgIWNvbnRhaW5zKGxhc3RDb250YWluZXIsIGVsZW1lbnQpKSB7XG5cdFx0Y29uc3QgbGlzdGVuZXJzID0gZG9tRGF0YS5nZXQoZWxlbWVudCwgJ2xpc3RlbmVycycsIHt9KVtldmVudC50eXBlXTtcblx0XHRyZXR1cm4gdHJpZ2dlckxpc3RlbmVyc18obGlzdGVuZXJzLCBldmVudCwgZWxlbWVudCwgZGVmYXVsdEZucyk7XG5cdH1cblx0cmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogVHJpZ2dlcnMgdGhlIHNwZWNpZmllZCBldmVudCBvbiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAqIE5PVEU6IFRoaXMgc2hvdWxkIG1vc3RseSBiZSB1c2VkIGZvciB0ZXN0aW5nLCBub3Qgb24gcmVhbCBjb2RlLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgbm9kZSB0aGF0IHNob3VsZCB0cmlnZ2VyIHRoZSBldmVudC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGJlIHRyaWdncmVkLlxuICogQHBhcmFtIHtPYmplY3Q9fSBldmVudE9iaiBBbiBvYmplY3Qgd2l0aCBkYXRhIHRoYXQgc2hvdWxkIGJlIG9uIHRoZVxuICogICB0cmlnZ2VyZWQgZXZlbnQncyBwYXlsb2FkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdHJpZ2dlckV2ZW50KGVsZW1lbnQsIGV2ZW50TmFtZSwgZXZlbnRPYmopIHtcblx0aWYgKGlzQWJsZVRvSW50ZXJhY3RXaXRoXyhlbGVtZW50LCBldmVudE5hbWUsIGV2ZW50T2JqKSkge1xuXHRcdGNvbnN0IHBheWxvYWQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnSFRNTEV2ZW50cycpO1xuXHRcdHBheWxvYWQuaW5pdEV2ZW50KGV2ZW50TmFtZSwgdHJ1ZSwgdHJ1ZSk7XG5cdFx0b2JqZWN0Lm1peGluKHBheWxvYWQsIGV2ZW50T2JqKTtcblx0XHRlbGVtZW50LmRpc3BhdGNoRXZlbnQocGF5bG9hZCk7XG5cdH1cbn1cblxuLyoqXG4gKiBUcmlnZ2VycyB0aGUgZ2l2ZW4gbGlzdGVuZXJzIGFycmF5LlxuICogQHBhcmFtIHtBcnJheTwhZnVuY3Rpb24oKT59IGxpc3RlbmVyc1xuICogQHBhcmFtIHshRXZlbnR9IGV2ZW50XG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0geyFBcnJheX0gZGVmYXVsdEZucyBBcnJheSB0byBjb2xsZWN0IGRlZmF1bHQgbGlzdGVuZXJzIGluLCBpbnN0ZWFkXG4gKiAgICAgb2YgcnVubmluZyB0aGVtLlxuICogQHJldHVybiB7Ym9vbGVhbn0gRmFsc2UgaWYgYXQgbGVhc3Qgb25lIG9mIHRoZSB0cmlnZ2VyZWQgY2FsbGJhY2tzIHJldHVybnNcbiAqICAgICBmYWxzZSwgb3IgdHJ1ZSBvdGhlcndpc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0cmlnZ2VyTGlzdGVuZXJzXyhsaXN0ZW5lcnMsIGV2ZW50LCBlbGVtZW50LCBkZWZhdWx0Rm5zKSB7XG5cdGxldCByZXQgPSB0cnVlO1xuXHRsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMgfHwgW107XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aCAmJiAhZXZlbnQuc3RvcHBlZEltbWVkaWF0ZTsgaSsrKSB7XG5cdFx0aWYgKGxpc3RlbmVyc1tpXS5kZWZhdWx0TGlzdGVuZXJfKSB7XG5cdFx0XHRkZWZhdWx0Rm5zLnB1c2goe1xuXHRcdFx0XHRlbGVtZW50LFxuXHRcdFx0XHRmbjogbGlzdGVuZXJzW2ldLFxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldCAmPSBsaXN0ZW5lcnNbaV0oZXZlbnQpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIFRyaWdnZXJzIGFsbCBzZWxlY3RvciBsaXN0ZW5lcnMgZm9yIHRoZSBnaXZlbiBldmVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGNvbnRhaW5lclxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHshRXZlbnR9IGV2ZW50XG4gKiBAcGFyYW0geyFBcnJheX0gZGVmYXVsdEZucyBBcnJheSB0byBjb2xsZWN0IGRlZmF1bHQgbGlzdGVuZXJzIGluLCBpbnN0ZWFkXG4gKiAgICAgb2YgcnVubmluZyB0aGVtLlxuICogQHJldHVybiB7Ym9vbGVhbn0gRmFsc2UgaWYgYXQgbGVhc3Qgb25lIG9mIHRoZSB0cmlnZ2VyZWQgY2FsbGJhY2tzIHJldHVybnNcbiAqICAgICBmYWxzZSwgb3IgdHJ1ZSBvdGhlcndpc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0cmlnZ2VyU2VsZWN0b3JMaXN0ZW5lcnNfKGNvbnRhaW5lciwgZWxlbWVudCwgZXZlbnQsIGRlZmF1bHRGbnMpIHtcblx0bGV0IHJldCA9IHRydWU7XG5cdGNvbnN0IGRhdGEgPSBkb21EYXRhLmdldChjb250YWluZXIsICdkZWxlZ2F0aW5nJywge30pO1xuXHRjb25zdCBtYXAgPSBkYXRhW2V2ZW50LnR5cGVdLnNlbGVjdG9ycztcblx0Y29uc3Qgc2VsZWN0b3JzID0gT2JqZWN0LmtleXMobWFwKTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3RvcnMubGVuZ3RoICYmICFldmVudC5zdG9wcGVkSW1tZWRpYXRlOyBpKyspIHtcblx0XHRpZiAobWF0Y2goZWxlbWVudCwgc2VsZWN0b3JzW2ldKSkge1xuXHRcdFx0Y29uc3QgbGlzdGVuZXJzID0gbWFwW3NlbGVjdG9yc1tpXV07XG5cdFx0XHRyZXQgJj0gdHJpZ2dlckxpc3RlbmVyc18obGlzdGVuZXJzLCBldmVudCwgZWxlbWVudCwgZGVmYXVsdEZucyk7XG5cdFx0fVxuXHR9XG5cdHJldHVybiByZXQ7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbi8vIFRoaXMgZmlsZSBleGlzdHMganVzdCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHksIG1ha2luZyBzdXJlIHRoYXQgb2xkXG4vLyBkZWZhdWx0IGltcG9ydHMgZm9yIHRoaXMgZmlsZSBzdGlsbCB3b3JrLiBJdCdzIGJlc3QgdG8gdXNlIHRoZSBuYW1lZCBleHBvcnRzXG4vLyBmb3IgZWFjaCBmdW5jdGlvbiBpbnN0ZWFkIHRob3VnaCwgc2luY2UgdGhhdCBhbGxvd3MgYnVuZGxlcnMgbGlrZSBSb2xsdXAgdG9cbi8vIHJlZHVjZSB0aGUgYnVuZGxlIHNpemUgYnkgcmVtb3ZpbmcgdW51c2VkIGNvZGUuXG5pbXBvcnQgKiBhcyBkb20gZnJvbSAnLi9kb21OYW1lZCc7XG5cbmV4cG9ydCBkZWZhdWx0IGRvbTtcbmV4cG9ydCB7ZG9tfTtcbmV4cG9ydCAqIGZyb20gJy4vZG9tTmFtZWQnO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2RlbGVnYXRlLCBvbiwgc3VwcG9ydHNFdmVudH0gZnJvbSAnLi9kb20nO1xuaW1wb3J0IHtFdmVudEVtaXR0ZXJQcm94eX0gZnJvbSAnbWV0YWwtZXZlbnRzJztcblxuLyoqXG4gKiBEb21FdmVudEVtaXR0ZXJQcm94eSB1dGlsaXR5LiBJdCBleHRlbmRzIGBFdmVudEVtaXR0ZXJQcm94eWAgdG8gYWxzbyBhY2NlcHRcbiAqIGRvbSBlbGVtZW50cyBhcyBvcmlnaW4gZW1pdHRlcnMuXG4gKiBAZXh0ZW5kcyB7RXZlbnRFbWl0dGVyUHJveHl9XG4gKi9cbmNsYXNzIERvbUV2ZW50RW1pdHRlclByb3h5IGV4dGVuZHMgRXZlbnRFbWl0dGVyUHJveHkge1xuXHQvKipcblx0ICogQWRkcyB0aGUgZ2l2ZW4gbGlzdGVuZXIgZm9yIHRoZSBnaXZlbiBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gVGhlIGxpc3RlbmVkIGV2ZW50J3MgaGFuZGxlLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0YWRkTGlzdGVuZXJfKGV2ZW50LCBsaXN0ZW5lcikge1xuXHRcdGlmICh0aGlzLm9yaWdpbkVtaXR0ZXJfLmFkZEV2ZW50TGlzdGVuZXIpIHtcblx0XHRcdGlmICh0aGlzLmlzRGVsZWdhdGVFdmVudF8oZXZlbnQpKSB7XG5cdFx0XHRcdGNvbnN0IGluZGV4ID0gZXZlbnQuaW5kZXhPZignOicsIDkpO1xuXHRcdFx0XHRjb25zdCBldmVudE5hbWUgPSBldmVudC5zdWJzdHJpbmcoOSwgaW5kZXgpO1xuXHRcdFx0XHRjb25zdCBzZWxlY3RvciA9IGV2ZW50LnN1YnN0cmluZyhpbmRleCArIDEpO1xuXHRcdFx0XHRyZXR1cm4gZGVsZWdhdGUoXG5cdFx0XHRcdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyxcblx0XHRcdFx0XHRldmVudE5hbWUsXG5cdFx0XHRcdFx0c2VsZWN0b3IsXG5cdFx0XHRcdFx0bGlzdGVuZXJcblx0XHRcdFx0KTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIG9uKHRoaXMub3JpZ2luRW1pdHRlcl8sIGV2ZW50LCBsaXN0ZW5lcik7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBzdXBlci5hZGRMaXN0ZW5lcl8oZXZlbnQsIGxpc3RlbmVyKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBldmVudCBpcyBvZiB0aGUgZGVsZWdhdGUgdHlwZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGlzRGVsZWdhdGVFdmVudF8oZXZlbnQpIHtcblx0XHRyZXR1cm4gZXZlbnQuc3Vic3RyKDAsIDkpID09PSAnZGVsZWdhdGU6Jztcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGV2ZW50IGlzIHN1cHBvcnRlZCBieSB0aGUgb3JpZ2luIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRpc1N1cHBvcnRlZERvbUV2ZW50XyhldmVudCkge1xuXHRcdGlmICghdGhpcy5vcmlnaW5FbWl0dGVyXyB8fCAhdGhpcy5vcmlnaW5FbWl0dGVyXy5hZGRFdmVudExpc3RlbmVyKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIChcblx0XHRcdCh0aGlzLmlzRGVsZWdhdGVFdmVudF8oZXZlbnQpICYmIGV2ZW50LmluZGV4T2YoJzonLCA5KSAhPT0gLTEpIHx8XG5cdFx0XHRzdXBwb3J0c0V2ZW50KHRoaXMub3JpZ2luRW1pdHRlcl8sIGV2ZW50KVxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBldmVudCBzaG91bGQgYmUgcHJveGllZC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRzaG91bGRQcm94eUV2ZW50XyhldmVudCkge1xuXHRcdHJldHVybiAoXG5cdFx0XHRzdXBlci5zaG91bGRQcm94eUV2ZW50XyhldmVudCkgJiYgdGhpcy5pc1N1cHBvcnRlZERvbUV2ZW50XyhldmVudClcblx0XHQpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRG9tRXZlbnRFbWl0dGVyUHJveHk7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXBwZW5kfSBmcm9tICcuL2RvbSc7XG5pbXBvcnQge3N0cmluZ30gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIENsYXNzIHdpdGggc3RhdGljIG1ldGhvZHMgcmVzcG9uc2libGUgZm9yIGRvaW5nIGJyb3dzZXIgZmVhdHVyZSBjaGVja3MuXG4gKi9cbmNsYXNzIGZlYXR1cmVzIHtcblx0LyoqXG5cdCAqIFNvbWUgYnJvd3NlcnMgc3RpbGwgc3VwcG9ydHMgcHJlZml4ZWQgYW5pbWF0aW9uIGV2ZW50cy4gVGhpcyBtZXRob2QgY2FuXG5cdCAqIGJlIHVzZWQgdG8gcmV0cmlldmUgdGhlIGN1cnJlbnQgYnJvd3NlciBldmVudCBuYW1lIGZvciBib3RoLCBhbmltYXRpb25cblx0ICogYW5kIHRyYW5zaXRpb24uXG5cdCAqIEByZXR1cm4ge29iamVjdH1cblx0ICovXG5cdHN0YXRpYyBjaGVja0FuaW1hdGlvbkV2ZW50TmFtZSgpIHtcblx0XHRpZiAoZmVhdHVyZXMuYW5pbWF0aW9uRXZlbnROYW1lXyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRmZWF0dXJlcy5hbmltYXRpb25FdmVudE5hbWVfID0ge1xuXHRcdFx0XHRhbmltYXRpb246IGZlYXR1cmVzLmNoZWNrQW5pbWF0aW9uRXZlbnROYW1lXygnYW5pbWF0aW9uJyksXG5cdFx0XHRcdHRyYW5zaXRpb246IGZlYXR1cmVzLmNoZWNrQW5pbWF0aW9uRXZlbnROYW1lXygndHJhbnNpdGlvbicpLFxuXHRcdFx0fTtcblx0XHR9XG5cdFx0cmV0dXJuIGZlYXR1cmVzLmFuaW1hdGlvbkV2ZW50TmFtZV87XG5cdH1cblxuXHQvKipcblx0ICogQHByb3RlY3RlZFxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBUeXBlIHRvIHRlc3Q6IGFuaW1hdGlvbiwgdHJhbnNpdGlvbi5cblx0ICogQHJldHVybiB7c3RyaW5nfSBCcm93c2VyIGV2ZW50IG5hbWUuXG5cdCAqL1xuXHRzdGF0aWMgY2hlY2tBbmltYXRpb25FdmVudE5hbWVfKHR5cGUpIHtcblx0XHRjb25zdCBwcmVmaXhlcyA9IFsnV2Via2l0JywgJ01TJywgJ08nLCAnJ107XG5cdFx0Y29uc3QgdHlwZVRpdGxlQ2FzZSA9IHN0cmluZy5yZXBsYWNlSW50ZXJ2YWwoXG5cdFx0XHR0eXBlLFxuXHRcdFx0MCxcblx0XHRcdDEsXG5cdFx0XHR0eXBlLnN1YnN0cmluZygwLCAxKS50b1VwcGVyQ2FzZSgpXG5cdFx0KTtcblx0XHRjb25zdCBzdWZmaXhlcyA9IFtcblx0XHRcdGAke3R5cGVUaXRsZUNhc2V9RW5kYCxcblx0XHRcdGAke3R5cGVUaXRsZUNhc2V9RW5kYCxcblx0XHRcdGAke3R5cGVUaXRsZUNhc2V9RW5kYCxcblx0XHRcdGAke3R5cGV9ZW5kYCxcblx0XHRdO1xuXHRcdGlmICghZmVhdHVyZXMuYW5pbWF0aW9uRWxlbWVudF8pIHtcblx0XHRcdGZlYXR1cmVzLmFuaW1hdGlvbkVsZW1lbnRfID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cdFx0fVxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgcHJlZml4ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChcblx0XHRcdFx0ZmVhdHVyZXMuYW5pbWF0aW9uRWxlbWVudF8uc3R5bGVbXG5cdFx0XHRcdFx0cHJlZml4ZXNbaV0gKyB0eXBlVGl0bGVDYXNlXG5cdFx0XHRcdF0gIT09IHVuZGVmaW5lZCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdFx0XHQpIHtcblx0XHRcdFx0cmV0dXJuIHByZWZpeGVzW2ldLnRvTG93ZXJDYXNlKCkgKyBzdWZmaXhlc1tpXTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGAke3R5cGV9ZW5kYDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTb21lIGJyb3dzZXJzIChsaWtlIElFMTEsIEVkZ2UpIGNoYW5nZSB0aGUgb3JkZXIgb2YgZWxlbWVudCBhdHRyaWJ1dGVzLCB3aGVuIGh0bWxcblx0ICogaXMgcmVuZGVyZWQuIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGNoZWNrIGlmIHRoaXMgYmVoYXZpb3IgaGFwcGVucyBvblxuXHQgKiB0aGUgY3VycmVudCBicm93c2VyLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0c3RhdGljIGNoZWNrQXR0ck9yZGVyQ2hhbmdlKCkge1xuXHRcdGlmIChmZWF0dXJlcy5hdHRyT3JkZXJDaGFuZ2VfID09PSB1bmRlZmluZWQpIHtcblx0XHRcdGNvbnN0IG9yaWdpbmFsQ29udGVudCA9ICc8ZGl2IGRhdGEtY29tcG9uZW50PVwiXCIgZGF0YS1yZWY9XCJcIj48L2Rpdj4nO1xuXHRcdFx0Y29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXHRcdFx0YXBwZW5kKGVsZW1lbnQsIG9yaWdpbmFsQ29udGVudCk7XG5cdFx0XHRmZWF0dXJlcy5hdHRyT3JkZXJDaGFuZ2VfID0gb3JpZ2luYWxDb250ZW50ICE9PSBlbGVtZW50LmlubmVySFRNTDtcblx0XHR9XG5cdFx0cmV0dXJuIGZlYXR1cmVzLmF0dHJPcmRlckNoYW5nZV87XG5cdH1cbn1cblxuZmVhdHVyZXMuYW5pbWF0aW9uRWxlbWVudF8gPSB1bmRlZmluZWQ7XG5mZWF0dXJlcy5hbmltYXRpb25FdmVudE5hbWVfID0gdW5kZWZpbmVkO1xuZmVhdHVyZXMuYXR0ck9yZGVyQ2hhbmdlXyA9IHVuZGVmaW5lZDtcblxuZXhwb3J0IGRlZmF1bHQgZmVhdHVyZXM7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXN5bmN9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7ZXhpdERvY3VtZW50LCBvbmNlfSBmcm9tICcuL2RvbSc7XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbnMgZm9yIHJ1bm5pbmcgamF2YXNjcmlwdCBjb2RlIGluIHRoZSBnbG9iYWwgc2NvcGUuXG4gKi9cbmNsYXNzIGdsb2JhbEV2YWwge1xuXHQvKipcblx0ICogRXZhbHVhdGVzIHRoZSBnaXZlbiBzdHJpbmcgaW4gdGhlIGdsb2JhbCBzY29wZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHRleHRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc2NyaXB0XG5cdCAqL1xuXHRzdGF0aWMgcnVuKHRleHQsIGFwcGVuZEZuKSB7XG5cdFx0Y29uc3Qgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG5cdFx0c2NyaXB0LnRleHQgPSB0ZXh0O1xuXHRcdGlmIChhcHBlbmRGbikge1xuXHRcdFx0YXBwZW5kRm4oc2NyaXB0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuXHRcdH1cblx0XHRleGl0RG9jdW1lbnQoc2NyaXB0KTtcblx0XHRyZXR1cm4gc2NyaXB0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0aGUgZ2l2ZW4gamF2YXNjcmlwdCBmaWxlIGluIHRoZSBnbG9iYWwgc2NvcGUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzcmMgVGhlIGZpbGUncyBwYXRoLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBkZWZhdWx0Rm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXG5cdCAqICAgd2hlbiB0aGUgc2NyaXB0IGhhcyBiZWVuIHJ1bi5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc2NyaXB0XG5cdCAqL1xuXHRzdGF0aWMgcnVuRmlsZShzcmMsIGRlZmF1bHRGbiwgYXBwZW5kRm4pIHtcblx0XHRjb25zdCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcblx0XHRzY3JpcHQuc3JjID0gc3JjO1xuXG5cdFx0Y29uc3QgY2FsbGJhY2sgPSBmdW5jdGlvbigpIHtcblx0XHRcdGV4aXREb2N1bWVudChzY3JpcHQpO1xuXHRcdFx0ZGVmYXVsdEZuICYmIGRlZmF1bHRGbigpO1xuXHRcdH07XG5cdFx0b25jZShzY3JpcHQsICdsb2FkJywgY2FsbGJhY2spO1xuXHRcdG9uY2Uoc2NyaXB0LCAnZXJyb3InLCBjYWxsYmFjayk7XG5cblx0XHRpZiAoYXBwZW5kRm4pIHtcblx0XHRcdGFwcGVuZEZuKHNjcmlwdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gc2NyaXB0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0aGUgY29kZSByZWZlcmVuY2VkIGJ5IHRoZSBnaXZlbiBzY3JpcHQgZWxlbWVudC5cblx0ICogQHBhcmFtIHshRWxlbWVudH0gc2NyaXB0XG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IGRlZmF1bHRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICogICB3aGVuIHRoZSBzY3JpcHQgaGFzIGJlZW4gcnVuLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBhcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKiBAcmV0dXJuIHtFbGVtZW50fSBzY3JpcHRcblx0ICovXG5cdHN0YXRpYyBydW5TY3JpcHQoc2NyaXB0LCBkZWZhdWx0Rm4sIGFwcGVuZEZuKSB7XG5cdFx0Y29uc3QgY2FsbGJhY2sgPSBmdW5jdGlvbigpIHtcblx0XHRcdGRlZmF1bHRGbiAmJiBkZWZhdWx0Rm4oKTtcblx0XHR9O1xuXHRcdGlmIChzY3JpcHQudHlwZSAmJiBzY3JpcHQudHlwZSAhPT0gJ3RleHQvamF2YXNjcmlwdCcpIHtcblx0XHRcdGFzeW5jLm5leHRUaWNrKGNhbGxiYWNrKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0ZXhpdERvY3VtZW50KHNjcmlwdCk7XG5cdFx0aWYgKHNjcmlwdC5zcmMpIHtcblx0XHRcdHJldHVybiBnbG9iYWxFdmFsLnJ1bkZpbGUoc2NyaXB0LnNyYywgZGVmYXVsdEZuLCBhcHBlbmRGbik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFzeW5jLm5leHRUaWNrKGNhbGxiYWNrKTtcblx0XHRcdHJldHVybiBnbG9iYWxFdmFsLnJ1bihzY3JpcHQudGV4dCwgYXBwZW5kRm4pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgYW55IHNjcmlwdCB0YWdzIHByZXNlbnQgaW4gdGhlIGdpdmVuIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gZGVmYXVsdEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHNjcmlwdCBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IGFwcGVuZEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGFwcGVuZCB0aGUgbm9kZVxuXHQgKiAgIGludG8gZG9jdW1lbnQuXG5cdCAqL1xuXHRzdGF0aWMgcnVuU2NyaXB0c0luRWxlbWVudChlbGVtZW50LCBkZWZhdWx0Rm4sIGFwcGVuZEZuKSB7XG5cdFx0Y29uc3Qgc2NyaXB0cyA9IGVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnc2NyaXB0Jyk7XG5cdFx0aWYgKHNjcmlwdHMubGVuZ3RoKSB7XG5cdFx0XHRnbG9iYWxFdmFsLnJ1blNjcmlwdHNJbk9yZGVyKHNjcmlwdHMsIDAsIGRlZmF1bHRGbiwgYXBwZW5kRm4pO1xuXHRcdH0gZWxzZSBpZiAoZGVmYXVsdEZuKSB7XG5cdFx0XHRhc3luYy5uZXh0VGljayhkZWZhdWx0Rm4pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBnaXZlbiBzY3JpcHRzIGVsZW1lbnRzIGluIHRoZSBvcmRlciB0aGF0IHRoZXkgYXBwZWFyLlxuXHQgKiBAcGFyYW0geyFOb2RlTGlzdH0gc2NyaXB0c1xuXHQgKiBAcGFyYW0ge251bWJlcn0gaW5kZXhcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gZGVmYXVsdEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHNjcmlwdCBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IGFwcGVuZEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGFwcGVuZCB0aGUgbm9kZVxuXHQgKiAgIGludG8gZG9jdW1lbnQuXG5cdCAqL1xuXHRzdGF0aWMgcnVuU2NyaXB0c0luT3JkZXIoc2NyaXB0cywgaW5kZXgsIGRlZmF1bHRGbiwgYXBwZW5kRm4pIHtcblx0XHRnbG9iYWxFdmFsLnJ1blNjcmlwdChcblx0XHRcdHNjcmlwdHMuaXRlbShpbmRleCksXG5cdFx0XHRmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKGluZGV4IDwgc2NyaXB0cy5sZW5ndGggLSAxKSB7XG5cdFx0XHRcdFx0Z2xvYmFsRXZhbC5ydW5TY3JpcHRzSW5PcmRlcihcblx0XHRcdFx0XHRcdHNjcmlwdHMsXG5cdFx0XHRcdFx0XHRpbmRleCArIDEsXG5cdFx0XHRcdFx0XHRkZWZhdWx0Rm4sXG5cdFx0XHRcdFx0XHRhcHBlbmRGblxuXHRcdFx0XHRcdCk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0XHRcdFx0fSBlbHNlIGlmIChkZWZhdWx0Rm4pIHtcblx0XHRcdFx0XHRhc3luYy5uZXh0VGljayhkZWZhdWx0Rm4pO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0YXBwZW5kRm5cblx0XHQpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGdsb2JhbEV2YWw7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXN5bmN9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7b25jZX0gZnJvbSAnLi9kb20nO1xuXG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb25zIGZvciBydW5uaW5nIHN0eWxlcy5cbiAqL1xuY2xhc3MgZ2xvYmFsRXZhbFN0eWxlcyB7XG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgdGhlIGdpdmVuIHN0eWxlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBhcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKiBAcmV0dXJuIHtFbGVtZW50fSBzdHlsZVxuXHQgKi9cblx0c3RhdGljIHJ1bih0ZXh0LCBhcHBlbmRGbikge1xuXHRcdGNvbnN0IHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcblx0XHRzdHlsZS5pbm5lckhUTUwgPSB0ZXh0O1xuXHRcdGlmIChhcHBlbmRGbikge1xuXHRcdFx0YXBwZW5kRm4oc3R5bGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHN0eWxlKTtcblx0XHR9XG5cdFx0cmV0dXJuIHN0eWxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0aGUgZ2l2ZW4gc3R5bGUgZmlsZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGhyZWYgVGhlIGZpbGUncyBwYXRoLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBkZWZhdWx0Rm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXG5cdCAqICAgd2hlbiB0aGUgc3R5bGVzIGhhcyBiZWVuIHJ1bi5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc3R5bGVcblx0ICovXG5cdHN0YXRpYyBydW5GaWxlKGhyZWYsIGRlZmF1bHRGbiwgYXBwZW5kRm4pIHtcblx0XHRjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGluaycpO1xuXHRcdGxpbmsucmVsID0gJ3N0eWxlc2hlZXQnO1xuXHRcdGxpbmsuaHJlZiA9IGhyZWY7XG5cdFx0Z2xvYmFsRXZhbFN0eWxlcy5ydW5TdHlsZShsaW5rLCBkZWZhdWx0Rm4sIGFwcGVuZEZuKTtcblx0XHRyZXR1cm4gbGluaztcblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgdGhlIGNvZGUgcmVmZXJlbmNlZCBieSB0aGUgZ2l2ZW4gc3R5bGUvbGluayBlbGVtZW50LlxuXHQgKiBAcGFyYW0geyFFbGVtZW50fSBzdHlsZVxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBkZWZhdWx0Rm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXG5cdCAqICAgd2hlbiB0aGUgc2NyaXB0IGhhcyBiZWVuIHJ1bi5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogIEByZXR1cm4ge0VsZW1lbnR9IHN0eWxlXG5cdCAqL1xuXHRzdGF0aWMgcnVuU3R5bGUoc3R5bGUsIGRlZmF1bHRGbiwgYXBwZW5kRm4pIHtcblx0XHRjb25zdCBjYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0ZGVmYXVsdEZuICYmIGRlZmF1bHRGbigpO1xuXHRcdH07XG5cdFx0aWYgKFxuXHRcdFx0c3R5bGUucmVsICYmXG5cdFx0XHRzdHlsZS5yZWwgIT09ICdzdHlsZXNoZWV0JyAmJlxuXHRcdFx0c3R5bGUucmVsICE9PSAnY2Fub25pY2FsJyAmJlxuXHRcdFx0c3R5bGUucmVsICE9PSAnYWx0ZXJuYXRlJ1xuXHRcdCkge1xuXHRcdFx0YXN5bmMubmV4dFRpY2soY2FsbGJhY2spO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChcblx0XHRcdHN0eWxlLnRhZ05hbWUgPT09ICdTVFlMRScgfHxcblx0XHRcdHN0eWxlLnJlbCA9PT0gJ2Nhbm9uaWNhbCcgfHxcblx0XHRcdHN0eWxlLnJlbCA9PT0gJ2FsdGVybmF0ZSdcblx0XHQpIHtcblx0XHRcdGFzeW5jLm5leHRUaWNrKGNhbGxiYWNrKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0b25jZShzdHlsZSwgJ2xvYWQnLCBjYWxsYmFjayk7XG5cdFx0XHRvbmNlKHN0eWxlLCAnZXJyb3InLCBjYWxsYmFjayk7XG5cdFx0fVxuXG5cdFx0aWYgKGFwcGVuZEZuKSB7XG5cdFx0XHRhcHBlbmRGbihzdHlsZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGUpO1xuXHRcdH1cblxuXHRcdHJldHVybiBzdHlsZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgYW55IHN0eWxlIHByZXNlbnQgaW4gdGhlIGdpdmVuIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gZGVmYXVsdEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZVxuXHQgKiAgIHN0eWxlIGhhcyBiZWVuIHJ1bi5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICovXG5cdHN0YXRpYyBydW5TdHlsZXNJbkVsZW1lbnQoZWxlbWVudCwgZGVmYXVsdEZuLCBhcHBlbmRGbikge1xuXHRcdGNvbnN0IHN0eWxlcyA9IGVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnc3R5bGUsbGluaycpO1xuXHRcdGlmIChzdHlsZXMubGVuZ3RoID09PSAwICYmIGRlZmF1bHRGbikge1xuXHRcdFx0YXN5bmMubmV4dFRpY2soZGVmYXVsdEZuKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRsZXQgbG9hZENvdW50ID0gMDtcblx0XHRjb25zdCBjYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKGRlZmF1bHRGbiAmJiArK2xvYWRDb3VudCA9PT0gc3R5bGVzLmxlbmd0aCkge1xuXHRcdFx0XHRhc3luYy5uZXh0VGljayhkZWZhdWx0Rm4pO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzdHlsZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGdsb2JhbEV2YWxTdHlsZXMucnVuU3R5bGUoc3R5bGVzW2ldLCBjYWxsYmFjaywgYXBwZW5kRm4pO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBnbG9iYWxFdmFsU3R5bGVzO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2lzU2VydmVyU2lkZX0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHtyZWdpc3RlckN1c3RvbUV2ZW50LCBjb250YWluc30gZnJvbSAnLi9kb20nO1xuaW1wb3J0IGZlYXR1cmVzIGZyb20gJy4vZmVhdHVyZXMnO1xuXG4vKipcbiAqIFJlZ2lzdGVyIGN1c3RvbSBldmVudHMgZm9yIGV2ZW50IGRlbGVnYXRpb24uXG4gKi9cbmZ1bmN0aW9uIHJlZ2lzdGVyRXZlbnRzKCkge1xuXHRjb25zdCBtb3VzZUV2ZW50TWFwID0ge1xuXHRcdG1vdXNlZW50ZXI6ICdtb3VzZW92ZXInLFxuXHRcdG1vdXNlbGVhdmU6ICdtb3VzZW91dCcsXG5cdFx0cG9pbnRlcmVudGVyOiAncG9pbnRlcm92ZXInLFxuXHRcdHBvaW50ZXJsZWF2ZTogJ3BvaW50ZXJvdXQnLFxuXHR9O1xuXHRPYmplY3Qua2V5cyhtb3VzZUV2ZW50TWFwKS5mb3JFYWNoKGZ1bmN0aW9uKGV2ZW50TmFtZSkge1xuXHRcdHJlZ2lzdGVyQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCB7XG5cdFx0XHRkZWxlZ2F0ZTogdHJ1ZSxcblx0XHRcdGhhbmRsZXI6IGZ1bmN0aW9uKGNhbGxiYWNrLCBldmVudCkge1xuXHRcdFx0XHRjb25zdCByZWxhdGVkID0gZXZlbnQucmVsYXRlZFRhcmdldDtcblx0XHRcdFx0Y29uc3QgdGFyZ2V0ID0gZXZlbnQuZGVsZWdhdGVUYXJnZXQ7XG5cdFx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuXHRcdFx0XHRpZiAoXG5cdFx0XHRcdFx0IXJlbGF0ZWQgfHxcblx0XHRcdFx0XHQocmVsYXRlZCAhPT0gdGFyZ2V0ICYmICFjb250YWlucyh0YXJnZXQsIHJlbGF0ZWQpKVxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHRldmVudC5jdXN0b21UeXBlID0gZXZlbnROYW1lO1xuXHRcdFx0XHRcdHJldHVybiBjYWxsYmFjayhldmVudCk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRvcmlnaW5hbEV2ZW50OiBtb3VzZUV2ZW50TWFwW2V2ZW50TmFtZV0sXG5cdFx0fSk7XG5cdH0pO1xuXG5cdGNvbnN0IGFuaW1hdGlvbkV2ZW50TWFwID0ge1xuXHRcdGFuaW1hdGlvbjogJ2FuaW1hdGlvbmVuZCcsXG5cdFx0dHJhbnNpdGlvbjogJ3RyYW5zaXRpb25lbmQnLFxuXHR9O1xuXHRPYmplY3Qua2V5cyhhbmltYXRpb25FdmVudE1hcCkuZm9yRWFjaChmdW5jdGlvbihldmVudFR5cGUpIHtcblx0XHRjb25zdCBldmVudE5hbWUgPSBhbmltYXRpb25FdmVudE1hcFtldmVudFR5cGVdO1xuXHRcdHJlZ2lzdGVyQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCB7XG5cdFx0XHRldmVudDogdHJ1ZSxcblx0XHRcdGRlbGVnYXRlOiB0cnVlLFxuXHRcdFx0aGFuZGxlcjogZnVuY3Rpb24oY2FsbGJhY2ssIGV2ZW50KSB7XG5cdFx0XHRcdGV2ZW50LmN1c3RvbVR5cGUgPSBldmVudE5hbWU7XG5cdFx0XHRcdHJldHVybiBjYWxsYmFjayhldmVudCk7XG5cdFx0XHR9LFxuXHRcdFx0b3JpZ2luYWxFdmVudDogZmVhdHVyZXMuY2hlY2tBbmltYXRpb25FdmVudE5hbWUoKVtldmVudFR5cGVdLFxuXHRcdH0pO1xuXHR9KTtcbn1cblxuaWYgKCFpc1NlcnZlclNpZGUoKSkge1xuXHRyZWdpc3RlckV2ZW50cygpO1xufVxuIiwidmFyIGdsb2JhbHMgPSBnbG9iYWxzIHx8IHt9O1xuXG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0Z2xvYmFscy53aW5kb3cgPSB3aW5kb3c7XG59XG5cbmlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG5cdGdsb2JhbHMuZG9jdW1lbnQgPSBkb2N1bWVudDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZ2xvYmFscztcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBBIGNvbGxlY3Rpb24gb2YgY29yZSB1dGlsaXR5IGZ1bmN0aW9ucy5cbiAqIEBjb25zdFxuICovXG5cbmxldCBjb21wYXRpYmlsaXR5TW9kZURhdGFfO1xuXG4vKipcbiAqIENvdW50ZXIgZm9yIHVuaXF1ZSBpZC5cbiAqIEB0eXBlIHtOdW1iZXJ9XG4gKiBAcHJpdmF0ZVxuICovXG5sZXQgdW5pcXVlSWRDb3VudGVyXyA9IDE7XG5cbi8qKlxuICogVW5pcXVlIGlkIHByb3BlcnR5IHByZWZpeC5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAcHJvdGVjdGVkXG4gKi9cbmV4cG9ydCBjb25zdCBVSURfUFJPUEVSVFkgPSBgY29yZV8keyhNYXRoLnJhbmRvbSgpICogMWU5KSA+Pj4gMH1gO1xuXG4vKipcbiAqIFdoZW4gZGVmaW5pbmcgYSBjbGFzcyBGb28gd2l0aCBhbiBhYnN0cmFjdCBtZXRob2QgYmFyKCksIHlvdSBjYW4gZG86XG4gKiBGb28ucHJvdG90eXBlLmJhciA9IGFic3RyYWN0TWV0aG9kXG4gKlxuICogTm93IGlmIGEgc3ViY2xhc3Mgb2YgRm9vIGZhaWxzIHRvIG92ZXJyaWRlIGJhcigpLCBhbiBlcnJvciB3aWxsIGJlIHRocm93blxuICogd2hlbiBiYXIoKSBpcyBpbnZva2VkLlxuICpcbiAqIEB0eXBlIHshRnVuY3Rpb259XG4gKiBAdGhyb3dzIHtFcnJvcn0gd2hlbiBpbnZva2VkIHRvIGluZGljYXRlIHRoZSBtZXRob2Qgc2hvdWxkIGJlIG92ZXJyaWRkZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhYnN0cmFjdE1ldGhvZCgpIHtcblx0dGhyb3cgRXJyb3IoJ1VuaW1wbGVtZW50ZWQgYWJzdHJhY3QgbWV0aG9kJyk7XG59XG5cbi8qKlxuICogRGlzYWJsZXMgTWV0YWwuanMncyBjb21wYXRpYmlsaXR5IG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkaXNhYmxlQ29tcGF0aWJpbGl0eU1vZGUoKSB7XG5cdGNvbXBhdGliaWxpdHlNb2RlRGF0YV8gPSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogRW5hYmxlcyBNZXRhbC5qcydzIGNvbXBhdGliaWxpdHkgbW9kZSB3aXRoIHRoZSBmb2xsb3dpbmcgZmVhdHVyZXMgZnJvbSByY1xuICogYW5kIDEueCB2ZXJzaW9uczpcbiAqICAgICAtIFVzaW5nIFwia2V5XCIgdG8gcmVmZXJlbmNlIGNvbXBvbmVudCBpbnN0YW5jZXMuIEluIHRoZSBjdXJyZW50IHZlcnNpb25cbiAqICAgICAgIHRoaXMgc2hvdWxkIGJlIGRvbmUgdmlhIFwicmVmXCIgaW5zdGVhZC4gVGhpcyBhbGxvd3Mgb2xkIGNvZGUgc3RpbGxcbiAqICAgICAgIHVzaW5nIFwia2V5XCIgdG8ga2VlcCB3b3JraW5nIGxpa2UgYmVmb3JlLiBOT1RFOiB0aGlzIG1heSBjYXVzZVxuICogICAgICAgcHJvYmxlbXMsIHNpbmNlIFwia2V5XCIgaXMgbWVhbnQgdG8gYmUgdXNlZCBkaWZmZXJlbnRseS4gT25seSB1c2UgdGhpc1xuICogICAgICAgaWYgaXQncyBub3QgcG9zc2libGUgdG8gdXBncmFkZSB0aGUgY29kZSB0byB1c2UgXCJyZWZcIiBpbnN0ZWFkLlxuICogQHBhcmFtIHtPYmplY3Q9fSBkYXRhIE9wdGlvbmFsIG9iamVjdCB3aXRoIGRhdGEgdG8gc3BlY2lmeSBtb3JlXG4gKiAgICAgZGV0YWlscywgc3VjaCBhczpcbiAqICAgICAgICAgLSByZW5kZXJlcnMge0FycmF5fSB0aGUgdGVtcGxhdGUgcmVuZGVyZXJzIHRoYXQgc2hvdWxkIGJlIGluXG4gKiAgICAgICAgICAgY29tcGF0aWJpbGl0eSBtb2RlLCBlaXRoZXIgdGhlaXIgY29uc3RydWN0b3JzIG9yIHN0cmluZ3NcbiAqICAgICAgICAgICByZXByZXNlbnRpbmcgdGhlbSAoZS5nLiAnc295JyBvciAnanN4JykuIEJ5IGRlZmF1bHQsIGFsbCB0aGUgb25lc1xuICogICAgICAgICAgIHRoYXQgZXh0ZW5kIGZyb20gSW5jcmVtZW50YWxEb21SZW5kZXJlci5cbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmFibGVDb21wYXRpYmlsaXR5TW9kZShkYXRhID0ge30pIHtcblx0Y29tcGF0aWJpbGl0eU1vZGVEYXRhXyA9IGRhdGE7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZGF0YSB1c2VkIGZvciBjb21wYXRpYmlsaXR5IG1vZGUsIG9yIG5vdGhpbmcgaWYgaXQgaGFzbid0IGJlZW5cbiAqIGVuYWJsZWQuXG4gKiBAcmV0dXJuIHtPYmplY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb21wYXRpYmlsaXR5TW9kZURhdGEoKSB7XG5cdC8vIENvbXBhdGliaWxpdHkgbW9kZSBjYW4gYmUgc2V0IHZpYSB0aGUgX19NRVRBTF9DT01QQVRJQklMSVRZX18gZ2xvYmFsIHZhci5cblx0aWYgKGNvbXBhdGliaWxpdHlNb2RlRGF0YV8gPT09IHVuZGVmaW5lZCkge1xuXHRcdGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuX19NRVRBTF9DT01QQVRJQklMSVRZX18pIHtcblx0XHRcdGVuYWJsZUNvbXBhdGliaWxpdHlNb2RlKHdpbmRvdy5fX01FVEFMX0NPTVBBVElCSUxJVFlfXyk7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBjb21wYXRpYmlsaXR5TW9kZURhdGFfO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGZpcnN0IGFyZ3VtZW50IGlmIGl0J3MgdHJ1dGh5LCBvciB0aGUgc2Vjb25kIG90aGVyd2lzZS5cbiAqIEBwYXJhbSB7Kn0gYVxuICogQHBhcmFtIHsqfSBiXG4gKiBAcmV0dXJuIHsqfVxuICogQHByb3RlY3RlZFxuICovXG5mdW5jdGlvbiBnZXRGaXJzdFRydXRoeV8oYSwgYikge1xuXHRyZXR1cm4gYSB8fCBiO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIG5hbWUgb2YgdGhlIGdpdmVuIGZ1bmN0aW9uLiBJZiB0aGUgY3VycmVudCBicm93c2VyIGRvZXNuJ3RcbiAqIHN1cHBvcnQgdGhlIGBuYW1lYCBwcm9wZXJ0eSwgdGhpcyB3aWxsIGNhbGN1bGF0ZSBpdCBmcm9tIHRoZSBmdW5jdGlvbidzXG4gKiBjb250ZW50IHN0cmluZy5cbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGZuXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRGdW5jdGlvbk5hbWUoZm4pIHtcblx0aWYgKCFmbi5uYW1lKSB7XG5cdFx0Y29uc3Qgc3RyID0gZm4udG9TdHJpbmcoKTtcblx0XHRmbi5uYW1lID0gc3RyLnN1YnN0cmluZyg5LCBzdHIuaW5kZXhPZignKCcpKTtcblx0fVxuXHRyZXR1cm4gZm4ubmFtZTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSB2YWx1ZSBvZiBhIHN0YXRpYyBwcm9wZXJ0eSBpbiB0aGUgZ2l2ZW4gY2xhc3MuIFRoZSB2YWx1ZSB3aWxsIGJlXG4gKiBpbmhlcml0ZWQgZnJvbSBhbmNlc3RvcnMgYXMgZXhwZWN0ZWQsIHVubGVzcyBhIGN1c3RvbSBtZXJnZSBmdW5jdGlvbiBpcyBnaXZlbixcbiAqIHdoaWNoIGNhbiBjaGFuZ2UgaG93IHRoZSBzdXBlciBjbGFzc2VzJyB2YWx1ZSBmb3IgdGhhdCBwcm9wZXJ0eSB3aWxsIGJlIG1lcmdlZFxuICogdG9nZXRoZXIuXG4gKiBUaGUgZmluYWwgbWVyZ2VkIHZhbHVlIHdpbGwgYmUgc3RvcmVkIGluIGFub3RoZXIgcHJvcGVydHksIHNvIHRoYXQgaXQgd29uJ3RcbiAqIGJlIHJlY2FsY3VsYXRlZCBldmVuIGlmIHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIG11bHRpcGxlIHRpbWVzLlxuICogQHBhcmFtIHshZnVuY3Rpb24oKX0gY3RvciBDbGFzcyBjb25zdHJ1Y3Rvci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eU5hbWUgUHJvcGVydHkgbmFtZSB0byBiZSBtZXJnZWQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCosICopOio9fSBtZXJnZUZuIEZ1bmN0aW9uIHRoYXQgcmVjZWl2ZXMgdGhlIG1lcmdlZFxuICogICAgIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSBzbyBmYXIgYW5kIHRoZSBuZXh0IHZhbHVlIHRvIGJlIG1lcmdlZCB0byBpdC5cbiAqICAgICBTaG91bGQgcmV0dXJuIHRoZXNlIHR3byBtZXJnZWQgdG9nZXRoZXIuIElmIG5vdCBwYXNzZWQgdGhlIGZpbmFsIHByb3BlcnR5XG4gKiAgICAgd2lsbCBiZSB0aGUgZmlyc3QgdHJ1dGh5IHZhbHVlIGFtb25nIGFuY2VzdG9ycy5cbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0YXRpY1Byb3BlcnR5KFxuXHRjdG9yLFxuXHRwcm9wZXJ0eU5hbWUsXG5cdG1lcmdlRm4gPSBnZXRGaXJzdFRydXRoeV9cbikge1xuXHRjb25zdCBtZXJnZWROYW1lID0gcHJvcGVydHlOYW1lICsgJ19NRVJHRUQnO1xuXHRpZiAoIWN0b3IuaGFzT3duUHJvcGVydHkobWVyZ2VkTmFtZSkpIHtcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcblx0XHRsZXQgbWVyZ2VkID0gY3Rvci5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eU5hbWUpXG5cdFx0XHQ/IGN0b3JbcHJvcGVydHlOYW1lXVxuXHRcdFx0OiBudWxsO1xuXHRcdGlmIChjdG9yLl9fcHJvdG9fXyAmJiAhY3Rvci5fX3Byb3RvX18uaXNQcm90b3R5cGVPZihGdW5jdGlvbikpIHtcblx0XHRcdG1lcmdlZCA9IG1lcmdlRm4oXG5cdFx0XHRcdG1lcmdlZCxcblx0XHRcdFx0Z2V0U3RhdGljUHJvcGVydHkoY3Rvci5fX3Byb3RvX18sIHByb3BlcnR5TmFtZSwgbWVyZ2VGbilcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGN0b3JbbWVyZ2VkTmFtZV0gPSBtZXJnZWQ7XG5cdH1cblx0cmV0dXJuIGN0b3JbbWVyZ2VkTmFtZV07XG59XG5cbi8qKlxuICogR2V0cyBhbiB1bmlxdWUgaWQuIElmIGBvYmplY3RgIGFyZ3VtZW50IGlzIHBhc3NlZCwgdGhlIG9iamVjdCBpc1xuICogbXV0YXRlZCB3aXRoIGFuIHVuaXF1ZSBpZC4gQ29uc2VjdXRpdmUgY2FsbHMgd2l0aCB0aGUgc2FtZSBvYmplY3RcbiAqIHJlZmVyZW5jZSB3b24ndCBtdXRhdGUgdGhlIG9iamVjdCBhZ2FpbiwgaW5zdGVhZCB0aGUgY3VycmVudCBvYmplY3QgdWlkXG4gKiByZXR1cm5zLiBTZWUge0BsaW5rIFVJRF9QUk9QRVJUWX0uXG4gKiBAcGFyYW0ge09iamVjdD19IG9iamVjdCBPcHRpb25hbCBvYmplY3QgdG8gYmUgbXV0YXRlZCB3aXRoIHRoZSB1aWQuIElmXG4gKiAgICAgbm90IHNwZWNpZmllZCB0aGlzIG1ldGhvZCBvbmx5IHJldHVybnMgdGhlIHVpZC5cbiAqIEBwYXJhbSB7Ym9vbGVhbj19IG5vSW5oZXJpdGFuY2UgT3B0aW9uYWwgZmxhZyBpbmRpY2F0aW5nIGlmIHRoaXNcbiAqICAgICBvYmplY3QncyB1aWQgcHJvcGVydHkgY2FuIGJlIGluaGVyaXRlZCBmcm9tIHBhcmVudHMgb3Igbm90LlxuICogQHRocm93cyB7RXJyb3J9IHdoZW4gaW52b2tlZCB0byBpbmRpY2F0ZSB0aGUgbWV0aG9kIHNob3VsZCBiZSBvdmVycmlkZGVuLlxuICogQHJldHVybiB7bnVtYmVyfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VWlkKG9iamVjdCwgbm9Jbmhlcml0YW5jZSkge1xuXHRpZiAob2JqZWN0KSB7XG5cdFx0bGV0IGlkID0gb2JqZWN0W1VJRF9QUk9QRVJUWV07XG5cdFx0aWYgKG5vSW5oZXJpdGFuY2UgJiYgIW9iamVjdC5oYXNPd25Qcm9wZXJ0eShVSURfUFJPUEVSVFkpKSB7XG5cdFx0XHRpZCA9IG51bGw7XG5cdFx0fVxuXHRcdHJldHVybiBpZCB8fCAob2JqZWN0W1VJRF9QUk9QRVJUWV0gPSB1bmlxdWVJZENvdW50ZXJfKyspO1xuXHR9XG5cdHJldHVybiB1bmlxdWVJZENvdW50ZXJfKys7XG59XG5cbi8qKlxuICogVGhlIGlkZW50aXR5IGZ1bmN0aW9uLiBSZXR1cm5zIGl0cyBmaXJzdCBhcmd1bWVudC5cbiAqIEBwYXJhbSB7Kj19IHJldHVyblZhbHVlIFRoZSBzaW5nbGUgdmFsdWUgdGhhdCB3aWxsIGJlIHJldHVybmVkLlxuICogQHJldHVybiB7P30gVGhlIGZpcnN0IGFyZ3VtZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaWRlbnRpdHlGdW5jdGlvbihyZXR1cm5WYWx1ZSkge1xuXHRyZXR1cm4gcmV0dXJuVmFsdWU7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYSBib29sZWFuLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgYm9vbGVhbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQm9vbGVhbih2YWwpIHtcblx0cmV0dXJuIHR5cGVvZiB2YWwgPT09ICdib29sZWFuJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBub3QgdW5kZWZpbmVkLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgZGVmaW5lZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGVmKHZhbCkge1xuXHRyZXR1cm4gdmFsICE9PSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIG5vdCB1bmRlZmluZWQgb3IgbnVsbC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEZWZBbmROb3ROdWxsKHZhbCkge1xuXHRyZXR1cm4gaXNEZWYodmFsKSAmJiAhaXNOdWxsKHZhbCk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgZG9jdW1lbnQuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRG9jdW1lbnQodmFsKSB7XG5cdHJldHVybiB2YWwgJiYgdHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsLm5vZGVUeXBlID09PSA5O1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIGRvY3VtZW50LWZyYWdtZW50LlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RvY3VtZW50RnJhZ21lbnQodmFsKSB7XG5cdHJldHVybiB2YWwgJiYgdHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsLm5vZGVUeXBlID09PSAxMTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBkb20gZWxlbWVudC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFbGVtZW50KHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbC5ub2RlVHlwZSA9PT0gMTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBhIGZ1bmN0aW9uLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgYSBmdW5jdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRnVuY3Rpb24odmFsKSB7XG5cdHJldHVybiB0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBudWxsLlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc051bGwodmFsKSB7XG5cdHJldHVybiB2YWwgPT09IG51bGw7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYSBudW1iZXIuXG4gKiBAcGFyYW0gez99IHZhbCBWYXJpYWJsZSB0byB0ZXN0LlxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB2YXJpYWJsZSBpcyBhIG51bWJlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTnVtYmVyKHZhbCkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ251bWJlcic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgd2luZG93LlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1dpbmRvdyh2YWwpIHtcblx0cmV0dXJuIHZhbCAhPT0gbnVsbCAmJiB2YWwgPT09IHZhbC53aW5kb3c7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYW4gb2JqZWN0LiBUaGlzIGluY2x1ZGVzIGFycmF5c1xuICogYW5kIGZ1bmN0aW9ucy5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGFuIG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzT2JqZWN0KHZhbCkge1xuXHRjb25zdCB0eXBlID0gdHlwZW9mIHZhbDtcblx0cmV0dXJuICh0eXBlID09PSAnb2JqZWN0JyAmJiB2YWwgIT09IG51bGwpIHx8IHR5cGUgPT09ICdmdW5jdGlvbic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgUHJvbWlzZS5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQcm9taXNlKHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHR5cGVvZiB2YWwudGhlbiA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBzdHJpbmcuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU3RyaW5nKHZhbCkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ3N0cmluZycgfHwgdmFsIGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG4vKipcbiAqIFNldHMgdG8gdHJ1ZSBpZiBydW5uaW5nIGluc2lkZSBOb2RlLmpzIGVudmlyb25tZW50IHdpdGggZXh0cmEgY2hlY2sgZm9yXG4gKiBgcHJvY2Vzcy5icm93c2VyYCB0byBza2lwIEthcm1hIHJ1bm5lciBlbnZpcm9ubWVudC4gS2FybWEgZW52aXJvbm1lbnQgaGFzXG4gKiBgcHJvY2Vzc2AgZGVmaW5lZCBldmVuIHRob3VnaCBpdCBydW5zIG9uIHRoZSBicm93c2VyLlxuICogQHBhcmFtIHs/T2JqZWN0fSBvcHRpb25zIENvbnRhaW5zIGBjaGVja0VudmAgcHJvcGVydHkgd2hpY2ggaWYgdHJ1ZSwgY2hlY2tzXG4gKiB0aGUgTk9ERV9FTlYgdmFyaWFibGUuIElmIE5PREVfRU5WIGVxdWFscyAndGVzdCcsIHRoZSBmdW5jdGlvbiByZXR1cm5zIGZhbHNlLlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2VydmVyU2lkZShvcHRpb25zID0ge2NoZWNrRW52OiB0cnVlfSkge1xuXHRsZXQgc2VydmVyU2lkZSA9IHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiAhcHJvY2Vzcy5icm93c2VyO1xuXHRpZiAoc2VydmVyU2lkZSAmJiBvcHRpb25zLmNoZWNrRW52KSB7XG5cdFx0c2VydmVyU2lkZSA9XG5cdFx0XHR0eXBlb2YgcHJvY2Vzcy5lbnYgIT09ICd1bmRlZmluZWQnICYmXG5cdFx0XHRwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Rlc3QnO1xuXHR9XG5cdHJldHVybiBzZXJ2ZXJTaWRlO1xufVxuXG4vKipcbiAqIE51bGwgZnVuY3Rpb24gdXNlZCBmb3IgZGVmYXVsdCB2YWx1ZXMgb2YgY2FsbGJhY2tzLCBldGMuXG4gKiBAcmV0dXJuIHt2b2lkfSBOb3RoaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbnVsbEZ1bmN0aW9uKCkge31cbiIsIid1c2Ugc3RyaWN0JztcblxuLy8gVGhpcyBmaWxlIGV4aXN0cyBqdXN0IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgbWFraW5nIHN1cmUgdGhhdCBvbGRcbi8vIGRlZmF1bHQgaW1wb3J0cyBmb3IgdGhpcyBmaWxlIHN0aWxsIHdvcmsuIEl0J3MgYmVzdCB0byB1c2UgdGhlIG5hbWVkIGV4cG9ydHNcbi8vIGZvciBlYWNoIGZ1bmN0aW9uIGluc3RlYWQgdGhvdWdoLCBzaW5jZSB0aGF0IGFsbG93cyBidW5kbGVycyBsaWtlIFJvbGx1cCB0b1xuLy8gcmVkdWNlIHRoZSBidW5kbGUgc2l6ZSBieSByZW1vdmluZyB1bnVzZWQgY29kZS5cbmltcG9ydCAqIGFzIGNvcmUgZnJvbSAnLi9jb3JlTmFtZWQnO1xuXG5leHBvcnQgZGVmYXVsdCBjb3JlO1xuZXhwb3J0IHtjb3JlfTtcbmV4cG9ydCAqIGZyb20gJy4vY29yZU5hbWVkJztcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBTZXQgb2YgdXRpbGl0aWVzIGZvciBhcnJheSBvcGVyYXRpb25zXG4gKi9cbmNsYXNzIGFycmF5IHtcblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gYXJyYXlzIGhhdmUgdGhlIHNhbWUgY29udGVudC5cblx0ICogQHBhcmFtIHshQXJyYXk8Kj59IGFycjFcblx0ICogQHBhcmFtIHshQXJyYXk8Kj59IGFycjJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdHN0YXRpYyBlcXVhbChhcnIxLCBhcnIyKSB7XG5cdFx0aWYgKGFycjEgPT09IGFycjIpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRpZiAoYXJyMS5sZW5ndGggIT09IGFycjIubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJyMS5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGFycjFbaV0gIT09IGFycjJbaV0pIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBmaXJzdCB2YWx1ZSBpbiB0aGUgZ2l2ZW4gYXJyYXkgdGhhdCBpc24ndCB1bmRlZmluZWQuXG5cdCAqIEBwYXJhbSB7IUFycmF5fSBhcnJcblx0ICogQHJldHVybiB7Kn1cblx0ICovXG5cdHN0YXRpYyBmaXJzdERlZmluZWRWYWx1ZShhcnIpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGFycltpXSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHJldHVybiBhcnJbaV07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRyYW5zZm9ybXMgdGhlIGlucHV0IG5lc3RlZCBhcnJheSB0byBiZWNvbWUgZmxhdC5cblx0ICogQHBhcmFtIHtBcnJheS48KnxBcnJheS48Kj4+fSBhcnIgTmVzdGVkIGFycmF5IHRvIGZsYXR0ZW4uXG5cdCAqIEBwYXJhbSB7QXJyYXkuPCo+PX0gb3V0cHV0IE9wdGlvbmFsIG91dHB1dCBhcnJheS5cblx0ICogQHJldHVybiB7QXJyYXkuPCo+fSBGbGF0IGFycmF5LlxuXHQgKi9cblx0c3RhdGljIGZsYXR0ZW4oYXJyLCBvdXRwdXQgPSBbXSkge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAoQXJyYXkuaXNBcnJheShhcnJbaV0pKSB7XG5cdFx0XHRcdGFycmF5LmZsYXR0ZW4oYXJyW2ldLCBvdXRwdXQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0b3V0cHV0LnB1c2goYXJyW2ldKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIG91dHB1dDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGEgcGFydGljdWxhciB2YWx1ZSBmcm9tIGFuIGFycmF5LlxuXHQgKiBAcGFyYW0ge0FycmF5LjxUPn0gYXJyIEFycmF5IGZyb20gd2hpY2ggdG8gcmVtb3ZlIHZhbHVlLlxuXHQgKiBAcGFyYW0ge1R9IG9iaiBPYmplY3QgdG8gcmVtb3ZlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIGFuIGVsZW1lbnQgd2FzIHJlbW92ZWQuXG5cdCAqIEB0ZW1wbGF0ZSBUXG5cdCAqL1xuXHRzdGF0aWMgcmVtb3ZlKGFyciwgb2JqKSB7XG5cdFx0Y29uc3QgaSA9IGFyci5pbmRleE9mKG9iaik7XG5cdFx0bGV0IHJ2O1xuXHRcdGlmICgocnYgPSBpID49IDApKSB7XG5cdFx0XHRhcnJheS5yZW1vdmVBdChhcnIsIGkpO1xuXHRcdH1cblx0XHRyZXR1cm4gcnY7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBmcm9tIGFuIGFycmF5IHRoZSBlbGVtZW50IGF0IGluZGV4IGlcblx0ICogQHBhcmFtIHtBcnJheX0gYXJyIEFycmF5IG9yIGFycmF5IGxpa2Ugb2JqZWN0IGZyb20gd2hpY2ggdG8gcmVtb3ZlIHZhbHVlLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gaSBUaGUgaW5kZXggdG8gcmVtb3ZlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIGFuIGVsZW1lbnQgd2FzIHJlbW92ZWQuXG5cdCAqL1xuXHRzdGF0aWMgcmVtb3ZlQXQoYXJyLCBpKSB7XG5cdFx0cmV0dXJuIEFycmF5LnByb3RvdHlwZS5zcGxpY2UuY2FsbChhcnIsIGksIDEpLmxlbmd0aCA9PT0gMTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTbGljZXMgdGhlIGdpdmVuIGFycmF5LCBqdXN0IGxpa2UgQXJyYXkucHJvdG90eXBlLnNsaWNlLCBidXQgdGhpc1xuXHQgKiBpcyBmYXN0ZXIgYW5kIHdvcmtpbmcgb24gYWxsIGFycmF5LWxpa2Ugb2JqZWN0cyAobGlrZSBhcmd1bWVudHMpLlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IGFyciBBcnJheS1saWtlIG9iamVjdCB0byBzbGljZS5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0IFRoZSBpbmRleCB0aGF0IHNob3VsZCBzdGFydCB0aGUgc2xpY2UuXG5cdCAqIEBwYXJhbSB7bnVtYmVyPX0gZW5kIFRoZSBpbmRleCB3aGVyZSB0aGUgc2xpY2Ugc2hvdWxkIGVuZCwgbm90XG5cdCAqICAgaW5jbHVkZWQgaW4gdGhlIGZpbmFsIGFycmF5LiBJZiBub3QgZ2l2ZW4sIGFsbCBlbGVtZW50cyBhZnRlciB0aGVcblx0ICogICBzdGFydCBpbmRleCB3aWxsIGJlIGluY2x1ZGVkLlxuXHQgKiBAcmV0dXJuIHshQXJyYXl9XG5cdCAqL1xuXHRzdGF0aWMgc2xpY2UoYXJyLCBzdGFydCwgZW5kID0gYXJyLmxlbmd0aCkge1xuXHRcdGNvbnN0IHNsaWNlZCA9IFtdO1xuXHRcdGZvciAobGV0IGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG5cdFx0XHRzbGljZWQucHVzaChhcnJbaV0pO1xuXHRcdH1cblx0XHRyZXR1cm4gc2xpY2VkO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGFycmF5O1xuIiwiLyogIVxuICogUG9seWZpbGwgZnJvbSBHb29nbGUncyBDbG9zdXJlIExpYnJhcnkuXG4gKiBDb3B5cmlnaHQgMjAxMyBUaGUgQ2xvc3VyZSBMaWJyYXJ5IEF1dGhvcnMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2lzU2VydmVyU2lkZX0gZnJvbSAnLi4vY29yZU5hbWVkJztcblxuY29uc3QgYXN5bmMgPSB7fTtcblxuLyoqXG4gKiBUaHJvdyBhbiBpdGVtIHdpdGhvdXQgaW50ZXJydXB0aW5nIHRoZSBjdXJyZW50IGV4ZWN1dGlvbiBjb250ZXh0LiAgRm9yXG4gKiBleGFtcGxlLCBpZiBwcm9jZXNzaW5nIGEgZ3JvdXAgb2YgaXRlbXMgaW4gYSBsb29wLCBzb21ldGltZXMgaXQgaXMgdXNlZnVsXG4gKiB0byByZXBvcnQgYW4gZXJyb3Igd2hpbGUgc3RpbGwgYWxsb3dpbmcgdGhlIHJlc3Qgb2YgdGhlIGJhdGNoIHRvIGJlXG4gKiBwcm9jZXNzZWQuXG4gKiBAcGFyYW0geyp9IGV4Y2VwdGlvblxuICovXG5hc3luYy50aHJvd0V4Y2VwdGlvbiA9IGZ1bmN0aW9uKGV4Y2VwdGlvbikge1xuXHQvLyBFYWNoIHRocm93IG5lZWRzIHRvIGJlIGluIGl0cyBvd24gY29udGV4dC5cblx0YXN5bmMubmV4dFRpY2soZnVuY3Rpb24oKSB7XG5cdFx0dGhyb3cgZXhjZXB0aW9uO1xuXHR9KTtcbn07XG5cbi8qKlxuICogRmlyZXMgdGhlIHByb3ZpZGVkIGNhbGxiYWNrIGp1c3QgYmVmb3JlIHRoZSBjdXJyZW50IGNhbGxzdGFjayB1bndpbmRzLCBvciBhc1xuICogc29vbiBhcyBwb3NzaWJsZSBhZnRlciB0aGUgY3VycmVudCBKUyBleGVjdXRpb24gY29udGV4dC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24odGhpczpUSElTKX0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7VEhJUz19IGNvbnRleHQgT2JqZWN0IHRvIHVzZSBhcyB0aGUgXCJ0aGlzIHZhbHVlXCIgd2hlbiBjYWxsaW5nXG4gKiAgICAgdGhlIHByb3ZpZGVkIGZ1bmN0aW9uLlxuICogQHRlbXBsYXRlIFRISVNcbiAqL1xuYXN5bmMucnVuID0gZnVuY3Rpb24oY2FsbGJhY2ssIGNvbnRleHQpIHtcblx0aWYgKCFhc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXykge1xuXHRcdC8vIE5vdGhpbmcgaXMgY3VycmVudGx5IHNjaGVkdWxlZCwgc2NoZWR1bGUgaXQgbm93LlxuXHRcdGFzeW5jLm5leHRUaWNrKGFzeW5jLnJ1bi5wcm9jZXNzV29ya1F1ZXVlKTtcblx0XHRhc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXyA9IHRydWU7XG5cdH1cblxuXHRhc3luYy5ydW4ud29ya1F1ZXVlXy5wdXNoKG5ldyBhc3luYy5ydW4uV29ya0l0ZW1fKGNhbGxiYWNrLCBjb250ZXh0KSk7XG59O1xuXG4vKiogQHByaXZhdGUge2Jvb2xlYW59ICovXG5hc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXyA9IGZhbHNlO1xuXG4vKiogQHByaXZhdGUgeyFBcnJheS48IWFzeW5jLnJ1bi5Xb3JrSXRlbV8+fSAqL1xuYXN5bmMucnVuLndvcmtRdWV1ZV8gPSBbXTtcblxuLyoqXG4gKiBSdW4gYW55IHBlbmRpbmcgYXN5bmMucnVuIHdvcmsgaXRlbXMuIFRoaXMgZnVuY3Rpb24gaXMgbm90IGludGVuZGVkXG4gKiBmb3IgZ2VuZXJhbCB1c2UsIGJ1dCBmb3IgdXNlIGJ5IGVudHJ5IHBvaW50IGhhbmRsZXJzIHRvIHJ1biBpdGVtcyBhaGVhZCBvZlxuICogYXN5bmMubmV4dFRpY2suXG4gKi9cbmFzeW5jLnJ1bi5wcm9jZXNzV29ya1F1ZXVlID0gZnVuY3Rpb24oKSB7XG5cdC8vIE5PVEU6IGFkZGl0aW9uYWwgd29yayBxdWV1ZSBpdGVtcyBtYXkgYmUgcHVzaGVkIHdoaWxlIHByb2Nlc3NpbmcuXG5cdHdoaWxlIChhc3luYy5ydW4ud29ya1F1ZXVlXy5sZW5ndGgpIHtcblx0XHQvLyBEb24ndCBsZXQgdGhlIHdvcmsgcXVldWUgZ3JvdyBpbmRlZmluaXRlbHkuXG5cdFx0Y29uc3Qgd29ya0l0ZW1zID0gYXN5bmMucnVuLndvcmtRdWV1ZV87XG5cdFx0YXN5bmMucnVuLndvcmtRdWV1ZV8gPSBbXTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHdvcmtJdGVtcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3Qgd29ya0l0ZW0gPSB3b3JrSXRlbXNbaV07XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR3b3JrSXRlbS5mbi5jYWxsKHdvcmtJdGVtLnNjb3BlKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0YXN5bmMudGhyb3dFeGNlcHRpb24oZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gVGhlcmUgYXJlIG5vIG1vcmUgd29yayBpdGVtcywgcmVzZXQgdGhlIHdvcmsgcXVldWUuXG5cdGFzeW5jLnJ1bi53b3JrUXVldWVTY2hlZHVsZWRfID0gZmFsc2U7XG59O1xuXG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICogQGZpbmFsXG4gKiBAc3RydWN0XG4gKiBAcHJpdmF0ZVxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb24oKX0gZm5cbiAqIEBwYXJhbSB7T2JqZWN0fG51bGx8dW5kZWZpbmVkfSBzY29wZVxuICovXG5hc3luYy5ydW4uV29ya0l0ZW1fID0gZnVuY3Rpb24oZm4sIHNjb3BlKSB7XG5cdC8qKiBAY29uc3QgKi9cblx0dGhpcy5mbiA9IGZuO1xuXHQvKiogQGNvbnN0ICovXG5cdHRoaXMuc2NvcGUgPSBzY29wZTtcbn07XG5cbi8qKlxuICogRmlyZXMgdGhlIHByb3ZpZGVkIGNhbGxiYWNrcyBhcyBzb29uIGFzIHBvc3NpYmxlIGFmdGVyIHRoZSBjdXJyZW50IEpTXG4gKiBleGVjdXRpb24gY29udGV4dC4gc2V0VGltZW91dCjigKYsIDApIGFsd2F5cyB0YWtlcyBhdCBsZWFzdCA1bXMgZm9yIGxlZ2FjeVxuICogcmVhc29ucy5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24odGhpczpTQ09QRSl9IGNhbGxiYWNrIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGZpcmUgYXMgc29vbiBhc1xuICogICAgIHBvc3NpYmxlLlxuICogQHBhcmFtIHtTQ09QRT19IGNvbnRleHQgT2JqZWN0IGluIHdob3NlIHNjb3BlIHRvIGNhbGwgdGhlIGxpc3RlbmVyLlxuICogQHRlbXBsYXRlIFNDT1BFXG4gKi9cbmFzeW5jLm5leHRUaWNrID0gZnVuY3Rpb24oY2FsbGJhY2ssIGNvbnRleHQpIHtcblx0bGV0IGNiID0gY2FsbGJhY2s7XG5cdGlmIChjb250ZXh0KSB7XG5cdFx0Y2IgPSBjYWxsYmFjay5iaW5kKGNvbnRleHQpO1xuXHR9XG5cdGNiID0gYXN5bmMubmV4dFRpY2sud3JhcENhbGxiYWNrXyhjYik7XG5cdC8vIExvb2sgZm9yIGFuZCBjYWNoZSB0aGUgY3VzdG9tIGZhbGxiYWNrIHZlcnNpb24gb2Ygc2V0SW1tZWRpYXRlLlxuXHRpZiAoIWFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8pIHtcblx0XHRpZiAoXG5cdFx0XHR0eXBlb2Ygc2V0SW1tZWRpYXRlID09PSAnZnVuY3Rpb24nICYmXG5cdFx0XHRpc1NlcnZlclNpZGUoe2NoZWNrRW52OiBmYWxzZX0pXG5cdFx0KSB7XG5cdFx0XHRhc3luYy5uZXh0VGljay5zZXRJbW1lZGlhdGVfID0gc2V0SW1tZWRpYXRlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcblx0XHRcdGFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8gPSBhc3luYy5uZXh0VGljay5nZXRTZXRJbW1lZGlhdGVFbXVsYXRvcl8oKTtcblx0XHR9XG5cdH1cblx0YXN5bmMubmV4dFRpY2suc2V0SW1tZWRpYXRlXyhjYik7XG59O1xuXG4vKipcbiAqIENhY2hlIGZvciB0aGUgc2V0SW1tZWRpYXRlIGltcGxlbWVudGF0aW9uLlxuICogQHR5cGUge2Z1bmN0aW9uKGZ1bmN0aW9uKCkpfVxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMubmV4dFRpY2suc2V0SW1tZWRpYXRlXyA9IG51bGw7XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB0aGUgYmVzdCBwb3NzaWJsZSBpbXBsZW1lbnRhdGlvbiB0byBydW4gYSBmdW5jdGlvbiBhcyBzb29uIGFzXG4gKiB0aGUgSlMgZXZlbnQgbG9vcCBpcyBpZGxlLlxuICogQHJldHVybiB7ZnVuY3Rpb24oZnVuY3Rpb24oKSl9IFRoZSBcInNldEltbWVkaWF0ZVwiIGltcGxlbWVudGF0aW9uLlxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMubmV4dFRpY2suZ2V0U2V0SW1tZWRpYXRlRW11bGF0b3JfID0gZnVuY3Rpb24oKSB7XG5cdC8vIENyZWF0ZSBhIHByaXZhdGUgbWVzc2FnZSBjaGFubmVsIGFuZCB1c2UgaXQgdG8gcG9zdE1lc3NhZ2UgZW1wdHkgbWVzc2FnZXNcblx0Ly8gdG8gb3Vyc2VsdmVzLlxuXHRsZXQgQ2hhbm5lbDtcblxuXHQvLyBWZXJpZnkgaWYgdmFyaWFibGUgaXMgZGVmaW5lZCBvbiB0aGUgY3VycmVudCBydW50aW1lIChpLmUuLCBub2RlLCBicm93c2VyKS5cblx0Ly8gQ2FuJ3QgdXNlIHR5cGVvZiBlbmNsb3NlZCBpbiBhIGZ1bmN0aW9uIChzdWNoIGFzIGNvcmUuaXNGdW5jdGlvbikgb3IgYW5cblx0Ly8gZXhjZXB0aW9uIHdpbGwgYmUgdGhyb3duIHdoZW4gdGhlIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBhbiBlbnZpcm9ubWVudFxuXHQvLyB3aGVyZSB0aGUgdmFyaWFibGUgaXMgdW5kZWZpbmVkLlxuXHRpZiAodHlwZW9mIE1lc3NhZ2VDaGFubmVsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0Q2hhbm5lbCA9IE1lc3NhZ2VDaGFubmVsO1xuXHR9XG5cblx0Ly8gSWYgTWVzc2FnZUNoYW5uZWwgaXMgbm90IGF2YWlsYWJsZSBhbmQgd2UgYXJlIGluIGEgYnJvd3NlciwgaW1wbGVtZW50XG5cdC8vIGFuIGlmcmFtZSBiYXNlZCBwb2x5ZmlsbCBpbiBicm93c2VycyB0aGF0IGhhdmUgcG9zdE1lc3NhZ2UgYW5kXG5cdC8vIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIuIFRoZSBsYXR0ZXIgZXhjbHVkZXMgSUU4IGJlY2F1c2UgaXQgaGFzIGFcblx0Ly8gc3luY2hyb25vdXMgcG9zdE1lc3NhZ2UgaW1wbGVtZW50YXRpb24uXG5cdGlmIChcblx0XHR0eXBlb2YgQ2hhbm5lbCA9PT0gJ3VuZGVmaW5lZCcgJiZcblx0XHR0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJlxuXHRcdHdpbmRvdy5wb3N0TWVzc2FnZSAmJlxuXHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG5cdCkge1xuXHRcdC8qKiBAY29uc3RydWN0b3IgKi9cblx0XHRDaGFubmVsID0gZnVuY3Rpb24oKSB7XG5cdFx0XHQvLyBNYWtlIGFuIGVtcHR5LCBpbnZpc2libGUgaWZyYW1lLlxuXHRcdFx0Y29uc3QgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG5cdFx0XHRpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcblx0XHRcdGlmcmFtZS5zcmMgPSAnJztcblx0XHRcdGlmcmFtZS50aXRsZSA9ICcnO1xuXHRcdFx0ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmFwcGVuZENoaWxkKGlmcmFtZSk7XG5cdFx0XHRjb25zdCB3aW4gPSBpZnJhbWUuY29udGVudFdpbmRvdztcblx0XHRcdGNvbnN0IGRvYyA9IHdpbi5kb2N1bWVudDtcblx0XHRcdGRvYy5vcGVuKCk7XG5cdFx0XHRkb2Mud3JpdGUoJycpO1xuXHRcdFx0ZG9jLmNsb3NlKCk7XG5cdFx0XHRjb25zdCBtZXNzYWdlID0gJ2NhbGxJbW1lZGlhdGUnICsgTWF0aC5yYW5kb20oKTtcblx0XHRcdGNvbnN0IG9yaWdpbiA9IHdpbi5sb2NhdGlvbi5wcm90b2NvbCArICcvLycgKyB3aW4ubG9jYXRpb24uaG9zdDtcblx0XHRcdGNvbnN0IG9ubWVzc2FnZSA9IGZ1bmN0aW9uKGUpIHtcblx0XHRcdFx0Ly8gVmFsaWRhdGUgb3JpZ2luIGFuZCBtZXNzYWdlIHRvIG1ha2Ugc3VyZSB0aGF0IHRoaXMgbWVzc2FnZSB3YXNcblx0XHRcdFx0Ly8gaW50ZW5kZWQgZm9yIHVzLlxuXHRcdFx0XHRpZiAoZS5vcmlnaW4gIT09IG9yaWdpbiAmJiBlLmRhdGEgIT09IG1lc3NhZ2UpIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5wb3J0MS5vbm1lc3NhZ2UoKTtcblx0XHRcdH0uYmluZCh0aGlzKTtcblx0XHRcdHdpbi5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25tZXNzYWdlLCBmYWxzZSk7XG5cdFx0XHR0aGlzLnBvcnQxID0ge307XG5cdFx0XHR0aGlzLnBvcnQyID0ge1xuXHRcdFx0XHRwb3N0TWVzc2FnZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0d2luLnBvc3RNZXNzYWdlKG1lc3NhZ2UsIG9yaWdpbik7XG5cdFx0XHRcdH0sXG5cdFx0XHR9O1xuXHRcdH07XG5cdH1cblx0aWYgKHR5cGVvZiBDaGFubmVsICE9PSAndW5kZWZpbmVkJykge1xuXHRcdGNvbnN0IGNoYW5uZWwgPSBuZXcgQ2hhbm5lbCgpO1xuXHRcdC8vIFVzZSBhIGZpZm8gbGlua2VkIGxpc3QgdG8gY2FsbCBjYWxsYmFja3MgaW4gdGhlIHJpZ2h0IG9yZGVyLlxuXHRcdGxldCBoZWFkID0ge307XG5cdFx0bGV0IHRhaWwgPSBoZWFkO1xuXHRcdGNoYW5uZWwucG9ydDEub25tZXNzYWdlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRoZWFkID0gaGVhZC5uZXh0O1xuXHRcdFx0Y29uc3QgY2IgPSBoZWFkLmNiO1xuXHRcdFx0aGVhZC5jYiA9IG51bGw7XG5cdFx0XHRjYigpO1xuXHRcdH07XG5cdFx0cmV0dXJuIGZ1bmN0aW9uKGNiKSB7XG5cdFx0XHR0YWlsLm5leHQgPSB7XG5cdFx0XHRcdGNiOiBjYixcblx0XHRcdH07XG5cdFx0XHR0YWlsID0gdGFpbC5uZXh0O1xuXHRcdFx0Y2hhbm5lbC5wb3J0Mi5wb3N0TWVzc2FnZSgwKTtcblx0XHR9O1xuXHR9XG5cdC8vIEltcGxlbWVudGF0aW9uIGZvciBJRTYtODogU2NyaXB0IGVsZW1lbnRzIGZpcmUgYW4gYXN5bmNocm9ub3VzXG5cdC8vIG9ucmVhZHlzdGF0ZWNoYW5nZSBldmVudCB3aGVuIGluc2VydGVkIGludG8gdGhlIERPTS5cblx0aWYgKFxuXHRcdHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiZcblx0XHQnb25yZWFkeXN0YXRlY2hhbmdlJyBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKVxuXHQpIHtcblx0XHRyZXR1cm4gZnVuY3Rpb24oY2IpIHtcblx0XHRcdGxldCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcblx0XHRcdHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0Ly8gQ2xlYW4gdXAgYW5kIGNhbGwgdGhlIGNhbGxiYWNrLlxuXHRcdFx0XHRzY3JpcHQub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbDtcblx0XHRcdFx0c2NyaXB0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc2NyaXB0KTtcblx0XHRcdFx0c2NyaXB0ID0gbnVsbDtcblx0XHRcdFx0Y2IoKTtcblx0XHRcdFx0Y2IgPSBudWxsO1xuXHRcdFx0fTtcblx0XHRcdGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuXHRcdH07XG5cdH1cblx0Ly8gRmFsbCBiYWNrIHRvIHNldFRpbWVvdXQgd2l0aCAwLiBJbiBicm93c2VycyB0aGlzIGNyZWF0ZXMgYSBkZWxheSBvZiA1bXNcblx0Ly8gb3IgbW9yZS5cblx0cmV0dXJuIGZ1bmN0aW9uKGNiKSB7XG5cdFx0c2V0VGltZW91dChjYiwgMCk7XG5cdH07XG59O1xuXG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbiB0aGF0IGlzIG92ZXJyaWRlZCB0byBwcm90ZWN0IGNhbGxiYWNrcyB3aXRoIGVudHJ5IHBvaW50XG4gKiBtb25pdG9yIGlmIHRoZSBhcHBsaWNhdGlvbiBtb25pdG9ycyBlbnRyeSBwb2ludHMuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGNhbGxiYWNrIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGZpcmUgYXMgc29vbiBhcyBwb3NzaWJsZS5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKCl9IFRoZSB3cmFwcGVkIGNhbGxiYWNrLlxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMubmV4dFRpY2sud3JhcENhbGxiYWNrXyA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG5cdHJldHVybiBjYWxsYmFjaztcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIERpc3Bvc2FibGUgdXRpbGl0eS4gV2hlbiBpbmhlcml0ZWQgcHJvdmlkZXMgdGhlIGBkaXNwb3NlYCBmdW5jdGlvbiB0byBpdHNcbiAqIHN1YmNsYXNzLCB3aGljaCBpcyByZXNwb25zaWJsZSBmb3IgZGlzcG9zaW5nIG9mIGFueSBvYmplY3QgcmVmZXJlbmNlc1xuICogd2hlbiBhbiBpbnN0YW5jZSB3b24ndCBiZSB1c2VkIGFueW1vcmUuIFN1YmNsYXNzZXMgc2hvdWxkIG92ZXJyaWRlXG4gKiBgZGlzcG9zZUludGVybmFsYCB0byBpbXBsZW1lbnQgYW55IHNwZWNpZmljIGRpc3Bvc2luZyBsb2dpYy5cbiAqIEBjb25zdHJ1Y3RvclxuICovXG5jbGFzcyBEaXNwb3NhYmxlIHtcblx0LyoqXG5cdCAqIERpc3Bvc2FibGUgY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdC8qKlxuXHRcdCAqIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGluc3RhbmNlIGhhcyBhbHJlYWR5IGJlZW4gZGlzcG9zZWQuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZGlzcG9zZWRfID0gZmFsc2U7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLiBDYWxscyBgZGlzcG9zZUludGVybmFsYC5cblx0ICovXG5cdGRpc3Bvc2UoKSB7XG5cdFx0aWYgKCF0aGlzLmRpc3Bvc2VkXykge1xuXHRcdFx0dGhpcy5kaXNwb3NlSW50ZXJuYWwoKTtcblx0XHRcdHRoaXMuZGlzcG9zZWRfID0gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU3ViY2xhc3NlcyBzaG91bGQgb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gaW1wbGVtZW50IGFueSBzcGVjaWZpY1xuXHQgKiBkaXNwb3NpbmcgbG9naWMgKGxpa2UgY2xlYXJpbmcgcmVmZXJlbmNlcyBhbmQgY2FsbGluZyBgZGlzcG9zZWAgb24gb3RoZXJcblx0ICogZGlzcG9zYWJsZXMpLlxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge31cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoaXMgaW5zdGFuY2UgaGFzIGFscmVhZHkgYmVlbiBkaXNwb3NlZC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGlzRGlzcG9zZWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZGlzcG9zZWRfO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERpc3Bvc2FibGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogU2V0IG9mIHV0aWxpdGllcyBmb3Igb2JqZWN0IG9wZXJhdGlvbnNcbiAqL1xuY2xhc3Mgb2JqZWN0IHtcblx0LyoqXG5cdCAqIENvcGllcyBhbGwgdGhlIG1lbWJlcnMgb2YgYSBzb3VyY2Ugb2JqZWN0IHRvIGEgdGFyZ2V0IG9iamVjdC5cblx0ICogQHBhcmFtIHtPYmplY3R9IHRhcmdldCBUYXJnZXQgb2JqZWN0LlxuXHQgKiBAcGFyYW0gey4uLk9iamVjdH0gdmFyX2FyZ3MgVGhlIG9iamVjdHMgZnJvbSB3aGljaCB2YWx1ZXMgd2lsbCBiZSBjb3BpZWQuXG5cdCAqIEByZXR1cm4ge09iamVjdH0gUmV0dXJucyB0aGUgdGFyZ2V0IG9iamVjdCByZWZlcmVuY2UuXG5cdCAqL1xuXHRzdGF0aWMgbWl4aW4odGFyZ2V0LCAuLi5hcmdzKSB7XG5cdFx0bGV0IGtleTtcblx0XHRsZXQgc291cmNlO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuXHRcdFx0c291cmNlID0gYXJnc1tpXTtcblx0XHRcdC8vIFBvc3NpYmxlIHByb3RvdHlwZSBjaGFpbiBsZWFrLCBicmVha3MgMSBtZXRhbC1kb20gYW5kXG5cdFx0XHQvLyAxIG1ldGFsLWluY3JlbWVudGFsLWRvbSB0ZXN0IGlmIGd1YXJkLWZvci1pbiBydWxlIGlzIGFkZHJlc3NlZFxuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cdFx0XHRmb3IgKGtleSBpbiBzb3VyY2UpIHtcblx0XHRcdFx0dGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRhcmdldDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGFuIG9iamVjdCBiYXNlZCBvbiBpdHMgZnVsbHkgcXVhbGlmaWVkIGV4dGVybmFsIG5hbWUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmdWxseSBxdWFsaWZpZWQgbmFtZS5cblx0ICogQHBhcmFtIHtvYmplY3Q9fSBzY29wZSBUaGUgb2JqZWN0IHdpdGhpbiB3aGljaCB0byBsb29rOyBkZWZhdWx0IGlzXG5cdCAqICAgICA8Y29kZT53aW5kb3c8L2NvZGU+LlxuXHQgKiBAcmV0dXJuIHs/fSBUaGUgdmFsdWUgKG9iamVjdCBvciBwcmltaXRpdmUpIG9yLCBpZiBub3QgZm91bmQsIHVuZGVmaW5lZC5cblx0ICovXG5cdHN0YXRpYyBnZXRPYmplY3RCeU5hbWUobmFtZSwgc2NvcGUgPSB3aW5kb3cpIHtcblx0XHRjb25zdCBwYXJ0cyA9IG5hbWUuc3BsaXQoJy4nKTtcblx0XHRyZXR1cm4gcGFydHMucmVkdWNlKChwYXJ0LCBrZXkpID0+IHBhcnRba2V5XSwgc2NvcGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdpdGggdGhlIHNhbWUga2V5cyBhcyB0aGUgZ2l2ZW4gb25lLCBidXQgd2l0aFxuXHQgKiB0aGVpciB2YWx1ZXMgc2V0IHRvIHRoZSByZXR1cm4gdmFsdWVzIG9mIHRoZSBzcGVjaWZpZWQgZnVuY3Rpb24uXG5cdCAqIEBwYXJhbSB7IU9iamVjdH0gb2JqXG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKHN0cmluZywgKil9IGZuXG5cdCAqIEByZXR1cm4geyFPYmplY3R9XG5cdCAqL1xuXHRzdGF0aWMgbWFwKG9iaiwgZm4pIHtcblx0XHRjb25zdCBtYXBwZWRPYmogPSB7fTtcblx0XHRjb25zdCBrZXlzID0gT2JqZWN0LmtleXMob2JqKTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdG1hcHBlZE9ialtrZXlzW2ldXSA9IGZuKGtleXNbaV0sIG9ialtrZXlzW2ldXSk7XG5cdFx0fVxuXHRcdHJldHVybiBtYXBwZWRPYmo7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSB0d28gZ2l2ZW4gb2JqZWN0cyBhcmUgZXF1YWwuIFRoaXMgaXMgZG9uZSB2aWEgYSBzaGFsbG93XG5cdCAqIGNoZWNrLCBpbmNsdWRpbmcgb25seSB0aGUga2V5cyBkaXJlY3RseSBjb250YWluZWQgYnkgdGhlIDIgb2JqZWN0cy5cblx0ICogQHBhcmFtIHtPYmplY3R9IG9iajFcblx0ICogQHBhcmFtIHtPYmplY3R9IG9iajJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdHN0YXRpYyBzaGFsbG93RXF1YWwob2JqMSwgb2JqMikge1xuXHRcdGlmIChvYmoxID09PSBvYmoyKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRjb25zdCBrZXlzMSA9IE9iamVjdC5rZXlzKG9iajEpO1xuXHRcdGNvbnN0IGtleXMyID0gT2JqZWN0LmtleXMob2JqMik7XG5cdFx0aWYgKGtleXMxLmxlbmd0aCAhPT0ga2V5czIubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzMS5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKG9iajFba2V5czFbaV1dICE9PSBvYmoyW2tleXMxW2ldXSkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IG9iamVjdDtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBTZXQgb2YgdXRpbGl0aWVzIGZvciBzdHJpbmcgb3BlcmF0aW9uc1xuICovXG5jbGFzcyBzdHJpbmcge1xuXHQvKipcblx0ICogQ29tcGFyZXMgdGhlIGdpdmVuIHN0cmluZ3Mgd2l0aG91dCB0YWtpbmcgdGhlIGNhc2UgaW50byBhY2NvdW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHN0cjFcblx0ICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBzdHIyXG5cdCAqIEByZXR1cm4ge251bWJlcn0gRWl0aGVyIC0xLCAwIG9yIDEsIGFjY29yZGluZyB0byBpZiB0aGUgZmlyc3Qgc3RyaW5nIGlzXG5cdCAqICAgICBcInNtYWxsZXJcIiwgZXF1YWwgb3IgXCJiaWdnZXJcIiB0aGFuIHRoZSBzZWNvbmQgZ2l2ZW4gc3RyaW5nLlxuXHQgKi9cblx0c3RhdGljIGNhc2VJbnNlbnNpdGl2ZUNvbXBhcmUoc3RyMSwgc3RyMikge1xuXHRcdGNvbnN0IHRlc3QxID0gU3RyaW5nKHN0cjEpLnRvTG93ZXJDYXNlKCk7XG5cdFx0Y29uc3QgdGVzdDIgPSBTdHJpbmcoc3RyMikudG9Mb3dlckNhc2UoKTtcblxuXHRcdGlmICh0ZXN0MSA8IHRlc3QyKSB7XG5cdFx0XHRyZXR1cm4gLTE7XG5cdFx0fSBlbHNlIGlmICh0ZXN0MSA9PT0gdGVzdDIpIHtcblx0XHRcdHJldHVybiAwO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gMTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyB0aGUgYnJlYWtpbmcgc3BhY2VzIGZyb20gdGhlIGxlZnQgYW5kIHJpZ2h0IG9mIHRoZSBzdHJpbmcgYW5kXG5cdCAqIGNvbGxhcHNlcyB0aGUgc2VxdWVuY2VzIG9mIGJyZWFraW5nIHNwYWNlcyBpbiB0aGUgbWlkZGxlIGludG8gc2luZ2xlIHNwYWNlcy5cblx0ICogVGhlIG9yaWdpbmFsIGFuZCB0aGUgcmVzdWx0IHN0cmluZ3MgcmVuZGVyIHRoZSBzYW1lIHdheSBpbiBIVE1MLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyIEEgc3RyaW5nIGluIHdoaWNoIHRvIGNvbGxhcHNlIHNwYWNlcy5cblx0ICogQHJldHVybiB7c3RyaW5nfSBDb3B5IG9mIHRoZSBzdHJpbmcgd2l0aCBub3JtYWxpemVkIGJyZWFraW5nIHNwYWNlcy5cblx0ICovXG5cdHN0YXRpYyBjb2xsYXBzZUJyZWFraW5nU3BhY2VzKHN0cikge1xuXHRcdHJldHVybiBzdHJcblx0XHRcdC5yZXBsYWNlKC9bXFx0XFxyXFxuIF0rL2csICcgJylcblx0XHRcdC5yZXBsYWNlKC9eW1xcdFxcclxcbiBdK3xbXFx0XFxyXFxuIF0rJC9nLCAnJyk7XG5cdH1cblxuXHQvKipcblx0ICogRXNjYXBlcyBjaGFyYWN0ZXJzIGluIHRoZSBzdHJpbmcgdGhhdCBhcmUgbm90IHNhZmUgdG8gdXNlIGluIGEgUmVnRXhwLlxuXHQgKiBAcGFyYW0geyp9IHN0ciBUaGUgc3RyaW5nIHRvIGVzY2FwZS4gSWYgbm90IGEgc3RyaW5nLCBpdCB3aWxsIGJlIGNhc3RlZFxuXHQgKiAgICAgdG8gb25lLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IEEgUmVnRXhwIHNhZmUsIGVzY2FwZWQgY29weSBvZiB7QGNvZGUgc30uXG5cdCAqL1xuXHRzdGF0aWMgZXNjYXBlUmVnZXgoc3RyKSB7XG5cdFx0cmV0dXJuIFN0cmluZyhzdHIpXG5cdFx0XHQucmVwbGFjZSgvKFstKClbXFxde30rPyouJF58LDojPCFcXFxcXSkvZywgJ1xcXFwkMScpXG5cdFx0XHQucmVwbGFjZSgvXFx4MDgvZywgJ1xcXFx4MDgnKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYSBzdHJpbmcgd2l0aCBhdCBsZWFzdCA2NC1iaXRzIG9mIHJhbmRvbW5lc3MuXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gQSByYW5kb20gc3RyaW5nLCBlLmcuIHNuMXM3dmI0Z2NpYy5cblx0ICovXG5cdHN0YXRpYyBnZXRSYW5kb21TdHJpbmcoKSB7XG5cdFx0Y29uc3QgeCA9IDIxNDc0ODM2NDg7XG5cdFx0cmV0dXJuIChcblx0XHRcdE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHgpLnRvU3RyaW5nKDM2KSArXG5cdFx0XHRNYXRoLmFicyhNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB4KSBeIERhdGUubm93KCkpLnRvU3RyaW5nKDM2KVxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsY3VsYXRlcyB0aGUgaGFzaGNvZGUgZm9yIGEgc3RyaW5nLiBUaGUgaGFzaGNvZGUgdmFsdWUgaXMgY29tcHV0ZWQgYnlcblx0ICogdGhlIHN1bSBhbGdvcml0aG06IHNbMF0qMzFeKG4tMSkgKyBzWzFdKjMxXihuLTIpICsgLi4uICsgc1tuLTFdLiBBIG5pY2Vcblx0ICogcHJvcGVydHkgb2YgdXNpbmcgMzEgcHJpbWUgaXMgdGhhdCB0aGUgbXVsdGlwbGljYXRpb24gY2FuIGJlIHJlcGxhY2VkIGJ5XG5cdCAqIGEgc2hpZnQgYW5kIGEgc3VidHJhY3Rpb24gZm9yIGJldHRlciBwZXJmb3JtYW5jZTogMzEqaSA9PSAoaTw8NSktaS5cblx0ICogTW9kZXJuIFZNcyBkbyB0aGlzIHNvcnQgb2Ygb3B0aW1pemF0aW9uIGF1dG9tYXRpY2FsbHkuXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSB2YWwgVGFyZ2V0IHN0cmluZy5cblx0ICogQHJldHVybiB7TnVtYmVyfSBSZXR1cm5zIHRoZSBzdHJpbmcgaGFzaGNvZGUuXG5cdCAqL1xuXHRzdGF0aWMgaGFzaENvZGUodmFsKSB7XG5cdFx0bGV0IGhhc2ggPSAwO1xuXHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSB2YWwubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGhhc2ggPSAzMSAqIGhhc2ggKyB2YWwuY2hhckNvZGVBdChpKTtcblx0XHRcdGhhc2ggJT0gMHgxMDAwMDAwMDA7XG5cdFx0fVxuXHRcdHJldHVybiBoYXNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlcGxhY2VzIGludGVydmFsIGludG8gdGhlIHN0cmluZyB3aXRoIHNwZWNpZmllZCB2YWx1ZSwgZS5nLlxuXHQgKiBgcmVwbGFjZUludGVydmFsKFwiYWJjZGVcIiwgMSwgNCwgXCJcIilgIHJldHVybnMgXCJhZVwiLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyIFRoZSBpbnB1dCBzdHJpbmcuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBzdGFydCBTdGFydCBpbnRlcnZhbCBwb3NpdGlvbiB0byBiZSByZXBsYWNlZC5cblx0ICogQHBhcmFtIHtOdW1iZXJ9IGVuZCBFbmQgaW50ZXJ2YWwgcG9zaXRpb24gdG8gYmUgcmVwbGFjZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdGhhdCByZXBsYWNlcyB0aGUgc3BlY2lmaWVkIGludGVydmFsLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRzdGF0aWMgcmVwbGFjZUludGVydmFsKHN0ciwgc3RhcnQsIGVuZCwgdmFsdWUpIHtcblx0XHRyZXR1cm4gc3RyLnN1YnN0cmluZygwLCBzdGFydCkgKyB2YWx1ZSArIHN0ci5zdWJzdHJpbmcoZW5kKTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBzdHJpbmc7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogUGFyc2VzIHRoZSBnaXZlbiB1cmkgc3RyaW5nIGludG8gYW4gb2JqZWN0LlxuICogQHBhcmFtIHsqPX0gb3B0X3VyaSBPcHRpb25hbCBzdHJpbmcgVVJJIHRvIHBhcnNlXG4gKi9cbmZ1bmN0aW9uIHBhcnNlRnJvbUFuY2hvcihvcHRfdXJpKSB7XG5cdHZhciBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuXHRsaW5rLmhyZWYgPSBvcHRfdXJpO1xuXG5cdGlmKGxpbmsucHJvdG9jb2wgPT09ICc6JyB8fCAhLzovLnRlc3QobGluay5ocmVmKSkge1xuXHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYCR7b3B0X3VyaX0gaXMgbm90IGEgdmFsaWQgVVJMYCk7XG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdGhhc2g6IGxpbmsuaGFzaCxcblx0XHRob3N0bmFtZTogbGluay5ob3N0bmFtZSxcblx0XHRwYXNzd29yZDogbGluay5wYXNzd29yZCxcblx0XHRwYXRobmFtZTogbGluay5wYXRobmFtZVswXSA9PT0gJy8nID8gbGluay5wYXRobmFtZSA6ICcvJyArIGxpbmsucGF0aG5hbWUsXG5cdFx0cG9ydDogbGluay5wb3J0LFxuXHRcdHByb3RvY29sOiBsaW5rLnByb3RvY29sLFxuXHRcdHNlYXJjaDogbGluay5zZWFyY2gsXG5cdFx0dXNlcm5hbWU6IGxpbmsudXNlcm5hbWVcblx0fTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgcGFyc2VGcm9tQW5jaG9yO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBpc0Z1bmN0aW9uIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHBhcnNlRnJvbUFuY2hvciBmcm9tICcuL3BhcnNlRnJvbUFuY2hvcic7XG5cbi8qKlxuICogUGFyc2VzIHRoZSBnaXZlbiB1cmkgc3RyaW5nIGludG8gYW4gb2JqZWN0LiBUaGUgVVJMIGZ1bmN0aW9uIHdpbGwgYmUgdXNlZFxuICogd2hlbiBwcmVzZW50LCBvdGhlcndpc2Ugd2UnbGwgZmFsbCBiYWNrIHRvIHRoZSBhbmNob3Igbm9kZSBlbGVtZW50LlxuICogQHBhcmFtIHsqPX0gb3B0X3VyaSBPcHRpb25hbCBzdHJpbmcgVVJJIHRvIHBhcnNlXG4gKi9cbmZ1bmN0aW9uIHBhcnNlKG9wdF91cmkpIHtcblx0aWYgKGlzRnVuY3Rpb24oVVJMKSAmJiBVUkwubGVuZ3RoKSB7XG5cdFx0Y29uc3QgdXJsID0gbmV3IFVSTChvcHRfdXJpKTtcblxuXHRcdC8vIFNhZmFyaSBCcm93c2VycyB3aWxsIGNhcCBwb3J0IHRvIHRoZSBtYXggMTYtYml0IHVuc2lnbmVkIGludGVnZXIgKDY1NTM1KSBpbnN0ZWFkXG5cdFx0Ly8gb2YgdGhyb3dpbmcgYSBUeXBlRXJyb3IgYXMgcGVyIHNwZWMuIEl0IHdpbGwgc3RpbGwga2VlcCB0aGUgcG9ydCBudW1iZXIgaW4gdGhlXG5cdFx0Ly8gaHJlZiBhdHRyaWJ1dGUsIHNvIHdlIGNhbiB1c2UgdGhpcyBtaXNtYXRjaCB0byByYWlzZSB0aGUgZXhwZWN0ZWQgZXhjZXB0aW9uLlxuXHRcdGlmICh1cmwucG9ydCAmJiB1cmwuaHJlZi5pbmRleE9mKHVybC5wb3J0KSA9PT0gLTEpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYCR7b3B0X3VyaX0gaXMgbm90IGEgdmFsaWQgVVJMYCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVybDtcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gcGFyc2VGcm9tQW5jaG9yKG9wdF91cmkpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IHBhcnNlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlIH0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEEgY2FjaGVkIHJlZmVyZW5jZSB0byB0aGUgY3JlYXRlIGZ1bmN0aW9uLlxuICovXG52YXIgY3JlYXRlID0gT2JqZWN0LmNyZWF0ZTtcblxuLyoqXG4gKiBDYXNlIGluc2Vuc2l0aXZlIHN0cmluZyBNdWx0aW1hcCBpbXBsZW1lbnRhdGlvbi4gQWxsb3dzIG11bHRpcGxlIHZhbHVlcyBmb3JcbiAqIHRoZSBzYW1lIGtleSBuYW1lLlxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIE11bHRpTWFwIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cdFx0dGhpcy5rZXlzID0gY3JlYXRlKG51bGwpO1xuXHRcdHRoaXMudmFsdWVzID0gY3JlYXRlKG51bGwpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdmFsdWUgdG8gYSBrZXkgbmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHBhcmFtIHsqfSB2YWx1ZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRhZGQobmFtZSwgdmFsdWUpIHtcblx0XHR0aGlzLmtleXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IG5hbWU7XG5cdFx0dGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV0gfHwgW107XG5cdFx0dGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXS5wdXNoKHZhbHVlKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhcnMgbWFwIG5hbWVzIGFuZCB2YWx1ZXMuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGNsZWFyKCkge1xuXHRcdHRoaXMua2V5cyA9IGNyZWF0ZShudWxsKTtcblx0XHR0aGlzLnZhbHVlcyA9IGNyZWF0ZShudWxsKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgbWFwIGNvbnRhaW5zIGEgdmFsdWUgdG8gdGhlIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRjb250YWlucyhuYW1lKSB7XG5cdFx0cmV0dXJuIG5hbWUudG9Mb3dlckNhc2UoKSBpbiB0aGlzLnZhbHVlcztcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHRoaXMudmFsdWVzID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgYE11bHRpTWFwYCBpbnN0YW5jZSBmcm9tIHRoZSBnaXZlbiBvYmplY3QuXG5cdCAqIEBwYXJhbSB7IU9iamVjdH0gb2JqXG5cdCAqIEByZXR1cm4geyFNdWx0aU1hcH1cblx0ICovXG5cdHN0YXRpYyBmcm9tT2JqZWN0KG9iaikge1xuXHRcdHZhciBtYXAgPSBuZXcgTXVsdGlNYXAoKTtcblx0XHR2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRtYXAuc2V0KGtleXNbaV0sIG9ialtrZXlzW2ldXSk7XG5cdFx0fVxuXHRcdHJldHVybiBtYXA7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgZmlyc3QgYWRkZWQgdmFsdWUgZnJvbSBhIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAcmV0dXJuIHsqfVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRnZXQobmFtZSkge1xuXHRcdHZhciB2YWx1ZXMgPSB0aGlzLnZhbHVlc1tuYW1lLnRvTG93ZXJDYXNlKCldO1xuXHRcdGlmICh2YWx1ZXMpIHtcblx0XHRcdHJldHVybiB2YWx1ZXNbMF07XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYWxsIHZhbHVlcyBmcm9tIGEga2V5IG5hbWUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG5cdCAqIEByZXR1cm4ge0FycmF5LjwqPn1cblx0ICovXG5cdGdldEFsbChuYW1lKSB7XG5cdFx0cmV0dXJuIHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV07XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0cnVlIGlmIHRoZSBtYXAgaXMgZW1wdHksIGZhbHNlIG90aGVyd2lzZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGlzRW1wdHkoKSB7XG5cdFx0cmV0dXJuIHRoaXMuc2l6ZSgpID09PSAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYXJyYXkgb2Yga2V5IG5hbWVzLlxuXHQgKiBAcmV0dXJuIHtBcnJheS48c3RyaW5nPn1cblx0ICovXG5cdG5hbWVzKCkge1xuXHRcdHJldHVybiBPYmplY3Qua2V5cyh0aGlzLnZhbHVlcykubWFwKChrZXkpID0+IHRoaXMua2V5c1trZXldKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCB2YWx1ZXMgZnJvbSBhIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRyZW1vdmUobmFtZSkge1xuXHRcdGRlbGV0ZSB0aGlzLmtleXNbbmFtZS50b0xvd2VyQ2FzZSgpXTtcblx0XHRkZWxldGUgdGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB2YWx1ZSBvZiBhIGtleSBuYW1lLiBSZWxldmFudCB0byByZXBsYWNlIHRoZSBjdXJyZW50IHZhbHVlcyB3aXRoXG5cdCAqIGEgbmV3IG9uZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHBhcmFtIHsqfSB2YWx1ZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXQobmFtZSwgdmFsdWUpIHtcblx0XHR0aGlzLmtleXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IG5hbWU7XG5cdFx0dGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IFt2YWx1ZV07XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc2l6ZSBvZiB0aGUgbWFwIGtleSBuYW1lcy5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0c2l6ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5uYW1lcygpLmxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBwYXJzZWQgdmFsdWVzIGFzIGEgc3RyaW5nLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy52YWx1ZXMpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE11bHRpTWFwO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBhcnJheSB9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBHZW5lcmljIHRyZWUgbm9kZSBkYXRhIHN0cnVjdHVyZSB3aXRoIGFyYml0cmFyeSBudW1iZXIgb2YgY2hpbGQgbm9kZXMuXG4gKiBAcGFyYW0ge1Z9IHZhbHVlIFZhbHVlLlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmNsYXNzIFRyZWVOb2RlIHtcblxuXHRjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuXHRcdC8qKlxuXHRcdCAqIFRoZSB2YWx1ZS5cblx0XHQgKiBAcHJpdmF0ZSB7Vn1cblx0XHQgKi9cblx0XHR0aGlzLnZhbHVlXyA9IHZhbHVlO1xuXG5cdFx0LyoqXG5cdFx0ICogUmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgbm9kZSBvciBudWxsIGlmIGl0IGhhcyBubyBwYXJlbnQuXG5cdFx0ICogQHByaXZhdGUge1RyZWVOb2RlfVxuXHRcdCAqL1xuXHRcdHRoaXMucGFyZW50XyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBDaGlsZCBub2RlcyBvciBudWxsIGluIGNhc2Ugb2YgbGVhZiBub2RlLlxuXHRcdCAqIEBwcml2YXRlIHtBcnJheTwhVHJlZU5vZGU+fVxuXHRcdCAqL1xuXHRcdHRoaXMuY2hpbGRyZW5fID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBcHBlbmRzIGEgY2hpbGQgbm9kZSB0byB0aGlzIG5vZGUuXG5cdCAqIEBwYXJhbSB7IVRyZWVOb2RlfSBjaGlsZCBPcnBoYW4gY2hpbGQgbm9kZS5cblx0ICovXG5cdGFkZENoaWxkKGNoaWxkKSB7XG5cdFx0YXNzZXJ0Q2hpbGRIYXNOb1BhcmVudChjaGlsZCk7XG5cdFx0Y2hpbGQuc2V0UGFyZW50KHRoaXMpO1xuXHRcdHRoaXMuY2hpbGRyZW5fID0gdGhpcy5jaGlsZHJlbl8gfHwgW107XG5cdFx0dGhpcy5jaGlsZHJlbl8ucHVzaChjaGlsZCk7XG5cdH1cblxuXHQvKipcblx0ICogVGVsbHMgd2hldGhlciB0aGlzIG5vZGUgaXMgdGhlIGFuY2VzdG9yIG9mIHRoZSBnaXZlbiBub2RlLlxuXHQgKiBAcGFyYW0geyFUcmVlTm9kZX0gbm9kZSBBIG5vZGUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdGhpcyBub2RlIGlzIHRoZSBhbmNlc3RvciBvZiB7QGNvZGUgbm9kZX0uXG5cdCAqL1xuXHRjb250YWlucyhub2RlKSB7XG5cdFx0bGV0IGN1cnJlbnQgPSBub2RlLmdldFBhcmVudCgpO1xuXHRcdHdoaWxlIChjdXJyZW50KSB7XG5cdFx0XHRpZiAoY3VycmVudCA9PT0gdGhpcykge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdGN1cnJlbnQgPSBjdXJyZW50LmdldFBhcmVudCgpO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7IUFycmF5PFRyZWVOb2RlPn0gQWxsIGFuY2VzdG9yIG5vZGVzIGluIGJvdHRvbS11cCBvcmRlci5cblx0ICovXG5cdGdldEFuY2VzdG9ycygpIHtcblx0XHRsZXQgYW5jZXN0b3JzID0gW107XG5cdFx0bGV0IG5vZGUgPSB0aGlzLmdldFBhcmVudCgpO1xuXHRcdHdoaWxlIChub2RlKSB7XG5cdFx0XHRhbmNlc3RvcnMucHVzaChub2RlKTtcblx0XHRcdG5vZGUgPSBub2RlLmdldFBhcmVudCgpO1xuXHRcdH1cblx0XHRyZXR1cm4gYW5jZXN0b3JzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGNoaWxkIG5vZGUgb2YgdGhpcyBub2RlIGF0IHRoZSBnaXZlbiBpbmRleC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IENoaWxkIGluZGV4LlxuXHQgKiBAcmV0dXJuIHs/VHJlZU5vZGV9IFRoZSBub2RlIGF0IHRoZSBnaXZlbiBpbmRleFxuXHQgKiBvciBudWxsIGlmIG5vdCBmb3VuZC5cblx0ICovXG5cdGdldENoaWxkQXQoaW5kZXgpIHtcblx0XHRyZXR1cm4gdGhpcy5nZXRDaGlsZHJlbigpW2luZGV4XSB8fCBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4gez9BcnJheTwhVHJlZU5vZGU+fSBDaGlsZCBub2RlcyBvciBudWxsIGluIGNhc2Ugb2YgbGVhZiBub2RlLlxuXHQgKi9cblx0Z2V0Q2hpbGRyZW4oKSB7XG5cdFx0cmV0dXJuIHRoaXMuY2hpbGRyZW5fIHx8IFRyZWVOb2RlLkVNUFRZX0FSUkFZO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBjaGlsZHJlbi5cblx0ICovXG5cdGdldENoaWxkQ291bnQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0Q2hpbGRyZW4oKS5sZW5ndGg7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGFuY2VzdG9ycyBvZiB0aGUgbm9kZS5cblx0ICovXG5cdGdldERlcHRoKCkge1xuXHRcdGxldCBkZXB0aCA9IDA7XG5cdFx0bGV0IG5vZGUgPSB0aGlzO1xuXHRcdHdoaWxlIChub2RlLmdldFBhcmVudCgpKSB7XG5cdFx0XHRkZXB0aCsrO1xuXHRcdFx0bm9kZSA9IG5vZGUuZ2V0UGFyZW50KCk7XG5cdFx0fVxuXHRcdHJldHVybiBkZXB0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHs/VHJlZU5vZGV9IFBhcmVudCBub2RlIG9yIG51bGwgaWYgaXQgaGFzIG5vIHBhcmVudC5cblx0ICovXG5cdGdldFBhcmVudCgpIHtcblx0XHRyZXR1cm4gdGhpcy5wYXJlbnRfO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4geyFUcmVlTm9kZX0gVGhlIHJvb3Qgb2YgdGhlIHRyZWUgc3RydWN0dXJlLCBpLmUuIHRoZSBmYXJ0aGVzdFxuXHQgKiBhbmNlc3RvciBvZiB0aGUgbm9kZSBvciB0aGUgbm9kZSBpdHNlbGYgaWYgaXQgaGFzIG5vIHBhcmVudHMuXG5cdCAqL1xuXHRnZXRSb290KCkge1xuXHRcdGxldCByb290ID0gdGhpcztcblx0XHR3aGlsZSAocm9vdC5nZXRQYXJlbnQoKSkge1xuXHRcdFx0cm9vdCA9IHJvb3QuZ2V0UGFyZW50KCk7XG5cdFx0fVxuXHRcdHJldHVybiByb290O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHZhbHVlLlxuXHQgKiBAcmV0dXJuIHtWfSBUaGUgdmFsdWUuXG5cdCAqL1xuXHRnZXRWYWx1ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy52YWx1ZV87XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB0aGUgbm9kZSBpcyBhIGxlYWYgbm9kZS5cblx0ICovXG5cdGlzTGVhZigpIHtcblx0XHRyZXR1cm4gIXRoaXMuZ2V0Q2hpbGRDb3VudCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGdpdmVuIGNoaWxkIG5vZGUgb2YgdGhpcyBub2RlLlxuXHQgKiBAcGFyYW0ge1RyZWVOb2RlfSBjaGlsZCBUaGUgbm9kZSB0byByZW1vdmUuXG5cdCAqIEByZXR1cm4ge1RyZWVOb2RlfSBUaGUgcmVtb3ZlZCBub2RlIGlmIGFueSwgbnVsbCBvdGhlcndpc2UuXG5cdCAqL1xuXHRyZW1vdmVDaGlsZChjaGlsZCkge1xuXHRcdGlmIChhcnJheS5yZW1vdmUodGhpcy5nZXRDaGlsZHJlbigpLCBjaGlsZCkpIHtcblx0XHRcdHJldHVybiBjaGlsZDtcblx0XHR9XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgcGFyZW50IG5vZGUgb2YgdGhpcyBub2RlLiBUaGUgY2FsbGVycyBtdXN0IGVuc3VyZSB0aGF0IHRoZVxuXHQgKiBwYXJlbnQgbm9kZSBhbmQgb25seSB0aGF0IGhhcyB0aGlzIG5vZGUgYW1vbmcgaXRzIGNoaWxkcmVuLlxuXHQgKiBAcGFyYW0ge1RyZWVOb2RlfSBwYXJlbnQgVGhlIHBhcmVudCB0byBzZXQuIElmIG51bGwsIHRoZSBub2RlIHdpbGwgYmVcblx0ICogZGV0YWNoZWQgZnJvbSB0aGUgdHJlZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0c2V0UGFyZW50KHBhcmVudCkge1xuXHRcdHRoaXMucGFyZW50XyA9IHBhcmVudDtcblx0fVxuXG5cdC8qKlxuXHQgKiBUcmF2ZXJzZXMgdGhlIHN1YnRyZWUuIFRoZSBmaXJzdCBjYWxsYmFjayBzdGFydHMgd2l0aCB0aGlzIG5vZGUsXG5cdCAqIGFuZCB2aXNpdHMgdGhlIGRlc2NlbmRhbnQgbm9kZXMgZGVwdGgtZmlyc3QsIGluIHByZW9yZGVyLlxuXHQgKiBUaGUgc2Vjb25kIGNhbGxiYWNrLCBzdGFydHMgd2l0aCBkZWVwZXN0IGNoaWxkIHRoZW4gdmlzaXRzXG5cdCAqIHRoZSBhbmNlc3RvciBub2RlcyBkZXB0aC1maXJzdCwgaW4gcG9zdG9yZGVyLiBFLmcuXG5cdCAqXG5cdCAqICBcdCBBXG5cdCAqICAgIC8gXFxcblx0ICogICBCICAgQ1xuXHQgKiAgLyAgIC8gXFxcblx0ICogRCAgIEUgICBGXG5cdCAqXG5cdCAqIHByZW9yZGVyIC0+IFsnQScsICdCJywgJ0QnLCAnQycsICdFJywgJ0YnXVxuXHQgKiBwb3N0b3JkZXIgLT4gWydEJywgJ0InLCAnRScsICdGJywgJ0MnLCAnQSddXG5cdCAqXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb249fSBvcHRfcHJlb3JkZXJGbiBUaGUgY2FsbGJhY2sgdG8gZXhlY3V0ZSB3aGVuIHZpc2l0aW5nIGEgbm9kZS5cblx0ICogQHBhcmFtIHtmdW5jdGlvbj19IG9wdF9wb3N0b3JkZXJGbiBUaGUgY2FsbGJhY2sgdG8gZXhlY3V0ZSBiZWZvcmUgbGVhdmluZyBhIG5vZGUuXG5cdCAqL1xuXHR0cmF2ZXJzZShvcHRfcHJlb3JkZXJGbiwgb3B0X3Bvc3RvcmRlckZuKSB7XG5cdFx0aWYgKG9wdF9wcmVvcmRlckZuKSB7XG5cdFx0XHRvcHRfcHJlb3JkZXJGbih0aGlzKTtcblx0XHR9XG5cdFx0dGhpcy5nZXRDaGlsZHJlbigpLmZvckVhY2goKGNoaWxkKSA9PiBjaGlsZC50cmF2ZXJzZShvcHRfcHJlb3JkZXJGbiwgb3B0X3Bvc3RvcmRlckZuKSk7XG5cdFx0aWYgKG9wdF9wb3N0b3JkZXJGbikge1xuXHRcdFx0b3B0X3Bvc3RvcmRlckZuKHRoaXMpO1xuXHRcdH1cblx0fVxuXG59XG5cbi8qKlxuICogQ29uc3RhbnQgZm9yIGVtcHR5IGFycmF5IHRvIGF2b2lkIHVubmVjZXNzYXJ5IGFsbG9jYXRpb25zLlxuICogQHByaXZhdGVcbiAqL1xuVHJlZU5vZGUuRU1QVFlfQVJSQVkgPSBbXTtcblxuLyoqXG4gKiBBc3NlcnRzIHRoYXQgY2hpbGQgaGFzIG5vIHBhcmVudC5cbiAqIEBwYXJhbSB7VHJlZU5vZGV9IGNoaWxkIEEgY2hpbGQuXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBhc3NlcnRDaGlsZEhhc05vUGFyZW50ID0gZnVuY3Rpb24oY2hpbGQpIHtcblx0aWYgKGNoaWxkLmdldFBhcmVudCgpKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYWRkIGNoaWxkIHdpdGggcGFyZW50LicpO1xuXHR9XG59O1xuXG5leHBvcnQgZGVmYXVsdCBUcmVlTm9kZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaXNEZWYsIHN0cmluZyB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBwYXJzZSBmcm9tICcuL3BhcnNlJztcbmltcG9ydCB7IE11bHRpTWFwIH0gZnJvbSAnbWV0YWwtc3RydWN0cyc7XG5cbnZhciBwYXJzZUZuXyA9IHBhcnNlO1xuXG5jbGFzcyBVcmkge1xuXG5cdC8qKlxuXHQgKiBUaGlzIGNsYXNzIGNvbnRhaW5zIHNldHRlcnMgYW5kIGdldHRlcnMgZm9yIHRoZSBwYXJ0cyBvZiB0aGUgVVJJLlxuXHQgKiBUaGUgZm9sbG93aW5nIGZpZ3VyZSBkaXNwbGF5cyBhbiBleGFtcGxlIFVSSXMgYW5kIHRoZWlyIGNvbXBvbmVudCBwYXJ0cy5cblx0ICpcblx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aFxuXHQgKlx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilIzilIDilIDilIDilLTilIDilIDilIDilIDilJBcblx0ICpcdCAgYWJjOi8vZXhhbXBsZS5jb206MTIzL3BhdGgvZGF0YT9rZXk9dmFsdWUjZnJhZ2lkMVxuXHQgKlx0ICDilJTilKzilJggICDilJTilIDilIDilIDilIDilKzilIDilIDilIDilIDilJgg4pSU4pSs4pSYICAgICAgICAgICDilJTilIDilIDilIDilKzilIDilIDilIDilJgg4pSU4pSA4pSA4pSs4pSA4pSA4pSYXG5cdCAqIHByb3RvY29sICBob3N0bmFtZSAgcG9ydCAgICAgICAgICAgIHNlYXJjaCAgICBoYXNoXG5cdCAqICAgICAgICAgIOKUlOKUgOKUgOKUgOKUgOKUgOKUgOKUrOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUmFxuXHQgKiAgICAgICAgICAgICAgICBob3N0XG5cdCAqXG5cdCAqIEBwYXJhbSB7Kj19IG9wdF91cmkgT3B0aW9uYWwgc3RyaW5nIFVSSSB0byBwYXJzZVxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKG9wdF91cmkgPSAnJykge1xuXHRcdHRoaXMudXJsID0gVXJpLnBhcnNlKHRoaXMubWF5YmVBZGRQcm90b2NvbEFuZEhvc3RuYW1lXyhvcHRfdXJpKSk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBwYXJhbWV0ZXJzIHRvIHVyaSBmcm9tIGEgPGNvZGU+TXVsdGlNYXA8L2NvZGU+IGFzIHNvdXJjZS5cblx0ICogQHBhcmFtIHtNdWx0aU1hcH0gbXVsdGltYXAgVGhlIDxjb2RlPk11bHRpTWFwPC9jb2RlPiBjb250YWluaW5nIHRoZVxuXHQgKiAgIHBhcmFtZXRlcnMuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkUGFyYW1ldGVyc0Zyb21NdWx0aU1hcChtdWx0aW1hcCkge1xuXHRcdG11bHRpbWFwLm5hbWVzKCkuZm9yRWFjaCgobmFtZSkgPT4ge1xuXHRcdFx0bXVsdGltYXAuZ2V0QWxsKG5hbWUpLmZvckVhY2goKHZhbHVlKSA9PiB7XG5cdFx0XHRcdHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyB0aGUgdmFsdWUgb2YgdGhlIG5hbWVkIHF1ZXJ5IHBhcmFtZXRlcnMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIHBhcmFtZXRlciB0byBzZXQuXG5cdCAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG5ldyB2YWx1ZS4gV2lsbCBiZSBleHBsaWNpdGx5IGNhc3RlZCB0byBTdHJpbmcuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZFBhcmFtZXRlclZhbHVlKG5hbWUsIHZhbHVlKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdGlmIChpc0RlZih2YWx1ZSkpIHtcblx0XHRcdHZhbHVlID0gU3RyaW5nKHZhbHVlKTtcblx0XHR9XG5cdFx0dGhpcy5xdWVyeS5hZGQobmFtZSwgdmFsdWUpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIHZhbHVlcyBvZiB0aGUgbmFtZWQgcXVlcnkgcGFyYW1ldGVyLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZFBhcmFtZXRlclZhbHVlcyhuYW1lLCB2YWx1ZXMpIHtcblx0XHR2YWx1ZXMuZm9yRWFjaCgodmFsdWUpID0+IHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBFbnN1cmVzIHF1ZXJ5IGludGVybmFsIG1hcCBpcyBpbml0aWFsaXplZCBhbmQgc3luY2VkIHdpdGggaW5pdGlhbCB2YWx1ZVxuXHQgKiBleHRyYWN0ZWQgZnJvbSBVUkkgc2VhcmNoIHBhcnQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCkge1xuXHRcdGlmICh0aGlzLnF1ZXJ5KSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMucXVlcnkgPSBuZXcgTXVsdGlNYXAoKTtcblx0XHR2YXIgc2VhcmNoID0gdGhpcy51cmwuc2VhcmNoO1xuXHRcdGlmIChzZWFyY2gpIHtcblx0XHRcdHNlYXJjaC5zdWJzdHJpbmcoMSkuc3BsaXQoJyYnKS5mb3JFYWNoKChwYXJhbSkgPT4ge1xuXHRcdFx0XHR2YXIgW2tleSwgdmFsdWVdID0gcGFyYW0uc3BsaXQoJz0nKTtcblx0XHRcdFx0aWYgKGlzRGVmKHZhbHVlKSkge1xuXHRcdFx0XHRcdHZhbHVlID0gVXJpLnVybERlY29kZSh2YWx1ZSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5hZGRQYXJhbWV0ZXJWYWx1ZShrZXksIHZhbHVlKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBoYXNoIHBhcnQgb2YgdXJpLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRIYXNoKCkge1xuXHRcdHJldHVybiB0aGlzLnVybC5oYXNoIHx8ICcnO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGhvc3QgcGFydCBvZiB1cmkuIEUuZy4gPGNvZGU+W2hvc3RuYW1lXTpbcG9ydF08L2NvZGU+LlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRIb3N0KCkge1xuXHRcdHZhciBob3N0ID0gdGhpcy5nZXRIb3N0bmFtZSgpO1xuXHRcdGlmIChob3N0KSB7XG5cdFx0XHR2YXIgcG9ydCA9IHRoaXMuZ2V0UG9ydCgpO1xuXHRcdFx0aWYgKHBvcnQgJiYgcG9ydCAhPT0gJzgwJykge1xuXHRcdFx0XHRob3N0ICs9ICc6JyArIHBvcnQ7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBob3N0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGhvc3RuYW1lIHBhcnQgb2YgdXJpIHdpdGhvdXQgcHJvdG9jb2wgYW5kIHBvcnQuXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldEhvc3RuYW1lKCkge1xuXHRcdHZhciBob3N0bmFtZSA9IHRoaXMudXJsLmhvc3RuYW1lO1xuXHRcdGlmIChob3N0bmFtZSA9PT0gVXJpLkhPU1ROQU1FX1BMQUNFSE9MREVSKSB7XG5cdFx0XHRyZXR1cm4gJyc7XG5cdFx0fVxuXHRcdHJldHVybiBob3N0bmFtZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBvcmlnaW4gcGFydCBvZiB1cmkuIEUuZy4gPGNvZGU+aHR0cDovL1tob3N0bmFtZV06W3BvcnRdPC9jb2RlPi5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0T3JpZ2luKCkge1xuXHRcdHZhciBob3N0ID0gdGhpcy5nZXRIb3N0KCk7XG5cdFx0aWYgKGhvc3QpIHtcblx0XHRcdHJldHVybiB0aGlzLmdldFByb3RvY29sKCkgKyAnLy8nICsgaG9zdDtcblx0XHR9XG5cdFx0cmV0dXJuICcnO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGZpcnN0IHZhbHVlIGZvciBhIGdpdmVuIHBhcmFtZXRlciBvciB1bmRlZmluZWQgaWYgdGhlIGdpdmVuXG5cdCAqIHBhcmFtZXRlciBuYW1lIGRvZXMgbm90IGFwcGVhciBpbiB0aGUgcXVlcnkgc3RyaW5nLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGFyYW1OYW1lIFVuZXNjYXBlZCBwYXJhbWV0ZXIgbmFtZS5cblx0ICogQHJldHVybiB7c3RyaW5nfHVuZGVmaW5lZH0gVGhlIGZpcnN0IHZhbHVlIGZvciBhIGdpdmVuIHBhcmFtZXRlciBvclxuXHQgKiAgIHVuZGVmaW5lZCBpZiB0aGUgZ2l2ZW4gcGFyYW1ldGVyIG5hbWUgZG9lcyBub3QgYXBwZWFyIGluIHRoZSBxdWVyeVxuXHQgKiAgIHN0cmluZy5cblx0ICovXG5cdGdldFBhcmFtZXRlclZhbHVlKG5hbWUpIHtcblx0XHR0aGlzLmVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCk7XG5cdFx0cmV0dXJuIHRoaXMucXVlcnkuZ2V0KG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHZhbHVlPGI+czwvYj4gZm9yIGEgZ2l2ZW4gcGFyYW1ldGVyIGFzIGEgbGlzdCBvZiBkZWNvZGVkXG5cdCAqIHF1ZXJ5IHBhcmFtZXRlciB2YWx1ZXMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBwYXJhbWV0ZXIgdG8gZ2V0IHZhbHVlcyBmb3IuXG5cdCAqIEByZXR1cm4geyFBcnJheTw/Pn0gVGhlIHZhbHVlcyBmb3IgYSBnaXZlbiBwYXJhbWV0ZXIgYXMgYSBsaXN0IG9mIGRlY29kZWRcblx0ICogICBxdWVyeSBwYXJhbWV0ZXIgdmFsdWVzLlxuXHQgKi9cblx0Z2V0UGFyYW1ldGVyVmFsdWVzKG5hbWUpIHtcblx0XHR0aGlzLmVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCk7XG5cdFx0cmV0dXJuIHRoaXMucXVlcnkuZ2V0QWxsKG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIG5hbWU8Yj5zPC9iPiBvZiB0aGUgcGFyYW1ldGVycy5cblx0ICogQHJldHVybiB7IUFycmF5PHN0cmluZz59IFRoZSBuYW1lcyBmb3IgdGhlIHBhcmFtZXRlcnMgYXMgYSBsaXN0IG9mXG5cdCAqICAgc3RyaW5ncy5cblx0ICovXG5cdGdldFBhcmFtZXRlck5hbWVzKCkge1xuXHRcdHRoaXMuZW5zdXJlUXVlcnlJbml0aWFsaXplZF8oKTtcblx0XHRyZXR1cm4gdGhpcy5xdWVyeS5uYW1lcygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGZ1bmN0aW9uIGN1cnJlbnRseSBiZWluZyB1c2VkIHRvIHBhcnNlIFVSSXMuXG5cdCAqIEByZXR1cm4geyFmdW5jdGlvbigpfVxuXHQgKi9cblx0c3RhdGljIGdldFBhcnNlRm4oKSB7XG5cdFx0cmV0dXJuIHBhcnNlRm5fO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHBhdGhuYW1lIHBhcnQgb2YgdXJpLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRQYXRobmFtZSgpIHtcblx0XHRyZXR1cm4gdGhpcy51cmwucGF0aG5hbWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcG9ydCBudW1iZXIgcGFydCBvZiB1cmkgYXMgc3RyaW5nLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRQb3J0KCkge1xuXHRcdHJldHVybiB0aGlzLnVybC5wb3J0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHByb3RvY29sIHBhcnQgb2YgdXJpLiBFLmcuIDxjb2RlPmh0dHA6PC9jb2RlPi5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0UHJvdG9jb2woKSB7XG5cdFx0cmV0dXJuIHRoaXMudXJsLnByb3RvY29sO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHNlYXJjaCBwYXJ0IG9mIHVyaS4gU2VhcmNoIHZhbHVlIGlzIHJldHJpZXZlZCBmcm9tIHF1ZXJ5XG5cdCAqIHBhcmFtZXRlcnMuXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldFNlYXJjaCgpIHtcblx0XHR2YXIgc2VhcmNoID0gJyc7XG5cdFx0dmFyIHF1ZXJ5c3RyaW5nID0gJyc7XG5cdFx0dGhpcy5nZXRQYXJhbWV0ZXJOYW1lcygpLmZvckVhY2goKG5hbWUpID0+IHtcblx0XHRcdHRoaXMuZ2V0UGFyYW1ldGVyVmFsdWVzKG5hbWUpLmZvckVhY2goKHZhbHVlKSA9PiB7XG5cdFx0XHRcdHF1ZXJ5c3RyaW5nICs9IG5hbWU7XG5cdFx0XHRcdGlmIChpc0RlZih2YWx1ZSkpIHtcblx0XHRcdFx0XHRxdWVyeXN0cmluZyArPSAnPScgKyBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHF1ZXJ5c3RyaW5nICs9ICcmJztcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHRcdHF1ZXJ5c3RyaW5nID0gcXVlcnlzdHJpbmcuc2xpY2UoMCwgLTEpO1xuXHRcdGlmIChxdWVyeXN0cmluZykge1xuXHRcdFx0c2VhcmNoICs9ICc/JyArIHF1ZXJ5c3RyaW5nO1xuXHRcdH1cblx0XHRyZXR1cm4gc2VhcmNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB1cmkgY29udGFpbnMgdGhlIHBhcmFtZXRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGhhc1BhcmFtZXRlcihuYW1lKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdHJldHVybiB0aGlzLnF1ZXJ5LmNvbnRhaW5zKG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIHRoaXMgVVJMIHVuaXF1ZSBieSBhZGRpbmcgYSByYW5kb20gcGFyYW0gdG8gaXQuIFVzZWZ1bCBmb3IgYXZvaWRpbmdcblx0ICogY2FjaGUuXG5cdCAqL1xuXHRtYWtlVW5pcXVlKCkge1xuXHRcdHRoaXMuc2V0UGFyYW1ldGVyVmFsdWUoVXJpLlJBTkRPTV9QQVJBTSwgc3RyaW5nLmdldFJhbmRvbVN0cmluZygpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBhZGRzIHByb3RvY29sIGFuZCBhIGhvc3RuYW1lIHBsYWNlaG9sZGVyIG9uIGEgcGFyaWFsIFVSSSBpZiBuZWVkZWQuXG5cdCAqIFJlbGV2ZW50IGZvciBjb21wYXRpYmlsaXR5IHdpdGggPGNvZGU+VVJMPC9jb2RlPiBuYXRpdmUgb2JqZWN0LlxuXHQgKiBAcGFyYW0ge3N0cmluZz19IG9wdF91cmlcblx0ICogQHJldHVybiB7c3RyaW5nfSBVUkkgd2l0aCBwcm90b2NvbCBhbmQgaG9zdG5hbWUgcGxhY2Vob2xkZXIuXG5cdCAqL1xuXHRtYXliZUFkZFByb3RvY29sQW5kSG9zdG5hbWVfKG9wdF91cmkpIHtcblx0XHR2YXIgdXJsID0gb3B0X3VyaTtcblx0XHRpZiAob3B0X3VyaS5pbmRleE9mKCc6Ly8nKSA9PT0gLTEgJiZcblx0XHRcdG9wdF91cmkuaW5kZXhPZignamF2YXNjcmlwdDonKSAhPT0gMCkgeyAvLyBqc2hpbnQgaWdub3JlOmxpbmVcblxuXHRcdFx0dXJsID0gVXJpLkRFRkFVTFRfUFJPVE9DT0w7XG5cdFx0XHRpZiAob3B0X3VyaVswXSAhPT0gJy8nIHx8IG9wdF91cmlbMV0gIT09ICcvJykge1xuXHRcdFx0XHR1cmwgKz0gJy8vJztcblx0XHRcdH1cblxuXHRcdFx0c3dpdGNoIChvcHRfdXJpLmNoYXJBdCgwKSkge1xuXHRcdFx0XHRjYXNlICcuJzpcblx0XHRcdFx0Y2FzZSAnPyc6XG5cdFx0XHRcdGNhc2UgJyMnOlxuXHRcdFx0XHRcdHVybCArPSBVcmkuSE9TVE5BTUVfUExBQ0VIT0xERVI7XG5cdFx0XHRcdFx0dXJsICs9ICcvJztcblx0XHRcdFx0XHR1cmwgKz0gb3B0X3VyaTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnJzpcblx0XHRcdFx0Y2FzZSAnLyc6XG5cdFx0XHRcdFx0aWYgKG9wdF91cmlbMV0gIT09ICcvJykge1xuXHRcdFx0XHRcdFx0dXJsICs9IFVyaS5IT1NUTkFNRV9QTEFDRUhPTERFUjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dXJsICs9IG9wdF91cmk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0dXJsICs9IG9wdF91cmk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB1cmw7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2VzIHRoZSBnaXZlbiB1cmkgc3RyaW5nIGludG8gYW4gb2JqZWN0LlxuXHQgKiBAcGFyYW0geyo9fSBvcHRfdXJpIE9wdGlvbmFsIHN0cmluZyBVUkkgdG8gcGFyc2Vcblx0ICovXG5cdHN0YXRpYyBwYXJzZShvcHRfdXJpKSB7XG5cdFx0cmV0dXJuIHBhcnNlRm5fKG9wdF91cmkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIG5hbWVkIHF1ZXJ5IHBhcmFtZXRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIHBhcmFtZXRlciB0byByZW1vdmUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHJlbW92ZVBhcmFtZXRlcihuYW1lKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdHRoaXMucXVlcnkucmVtb3ZlKG5hbWUpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdW5pcXVlbmVzcyBwYXJhbWV0ZXIgb2YgdGhlIHVyaS5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0cmVtb3ZlVW5pcXVlKCkge1xuXHRcdHRoaXMucmVtb3ZlUGFyYW1ldGVyKFVyaS5SQU5ET01fUEFSQU0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGhhc2guXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBoYXNoXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldEhhc2goaGFzaCkge1xuXHRcdHRoaXMudXJsLmhhc2ggPSBoYXNoO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGhvc3RuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaG9zdG5hbWVcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0c2V0SG9zdG5hbWUoaG9zdG5hbWUpIHtcblx0XHR0aGlzLnVybC5ob3N0bmFtZSA9IGhvc3RuYW1lO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHZhbHVlIG9mIHRoZSBuYW1lZCBxdWVyeSBwYXJhbWV0ZXJzLCBjbGVhcmluZyBwcmV2aW91cyB2YWx1ZXNcblx0ICogZm9yIHRoYXQga2V5LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFBhcmFtZXRlclZhbHVlKG5hbWUsIHZhbHVlKSB7XG5cdFx0dGhpcy5yZW1vdmVQYXJhbWV0ZXIobmFtZSk7XG5cdFx0dGhpcy5hZGRQYXJhbWV0ZXJWYWx1ZShuYW1lLCB2YWx1ZSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgdmFsdWVzIG9mIHRoZSBuYW1lZCBxdWVyeSBwYXJhbWV0ZXJzLCBjbGVhcmluZyBwcmV2aW91cyB2YWx1ZXNcblx0ICogZm9yIHRoYXQga2V5LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFBhcmFtZXRlclZhbHVlcyhuYW1lLCB2YWx1ZXMpIHtcblx0XHR0aGlzLnJlbW92ZVBhcmFtZXRlcihuYW1lKTtcblx0XHR2YWx1ZXMuZm9yRWFjaCgodmFsdWUpID0+IHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwYXRobmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGhuYW1lXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFBhdGhuYW1lKHBhdGhuYW1lKSB7XG5cdFx0dGhpcy51cmwucGF0aG5hbWUgPSBwYXRobmFtZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwb3J0IG51bWJlci5cblx0ICogQHBhcmFtIHsqfSBwb3J0IFBvcnQgbnVtYmVyLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXRQb3J0KHBvcnQpIHtcblx0XHR0aGlzLnVybC5wb3J0ID0gcG9ydDtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgcGFyc2luZyB0aGUgb3JpZ2luYWwgc3RyaW5nIHVyaVxuXHQgKiBpbnRvIGFuIG9iamVjdC5cblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKX0gcGFyc2VGblxuXHQgKi9cblx0c3RhdGljIHNldFBhcnNlRm4ocGFyc2VGbikge1xuXHRcdHBhcnNlRm5fID0gcGFyc2VGbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwcm90b2NvbC4gSWYgbWlzc2luZyA8Y29kZT5odHRwOjwvY29kZT4gaXMgdXNlZCBhcyBkZWZhdWx0LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcHJvdG9jb2xcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0c2V0UHJvdG9jb2wocHJvdG9jb2wpIHtcblx0XHR0aGlzLnVybC5wcm90b2NvbCA9IHByb3RvY29sO1xuXHRcdGlmICh0aGlzLnVybC5wcm90b2NvbFt0aGlzLnVybC5wcm90b2NvbC5sZW5ndGggLSAxXSAhPT0gJzonKSB7XG5cdFx0XHR0aGlzLnVybC5wcm90b2NvbCArPSAnOic7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHN0cmluZyBmb3JtIG9mIHRoZSB1cmwuXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0dG9TdHJpbmcoKSB7XG5cdFx0dmFyIGhyZWYgPSAnJztcblx0XHR2YXIgaG9zdCA9IHRoaXMuZ2V0SG9zdCgpO1xuXHRcdGlmIChob3N0KSB7XG5cdFx0XHRocmVmICs9IHRoaXMuZ2V0UHJvdG9jb2woKSArICcvLyc7XG5cdFx0fVxuXHRcdGhyZWYgKz0gaG9zdCArIHRoaXMuZ2V0UGF0aG5hbWUoKSArIHRoaXMuZ2V0U2VhcmNoKCkgKyB0aGlzLmdldEhhc2goKTtcblx0XHRyZXR1cm4gaHJlZjtcblx0fVxuXG5cdC8qKlxuXHQgKiBKb2lucyB0aGUgZ2l2ZW4gcGF0aHMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlUGF0aFxuXHQgKiBAcGFyYW0gey4uLnN0cmluZ30gLi4ucGF0aHMgQW55IG51bWJlciBvZiBwYXRocyB0byBiZSBqb2luZWQgd2l0aCB0aGUgYmFzZSB1cmwuXG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBqb2luUGF0aHMoYmFzZVBhdGgsIC4uLnBhdGhzKSB7XG5cdFx0aWYgKGJhc2VQYXRoLmNoYXJBdChiYXNlUGF0aC5sZW5ndGggLSAxKSA9PT0gJy8nKSB7XG5cdFx0XHRiYXNlUGF0aCA9IGJhc2VQYXRoLnN1YnN0cmluZygwLCBiYXNlUGF0aC5sZW5ndGggLSAxKTtcblx0XHR9XG5cdFx0cGF0aHMgPSBwYXRocy5tYXAocGF0aCA9PiBwYXRoLmNoYXJBdCgwKSA9PT0gJy8nID8gcGF0aC5zdWJzdHJpbmcoMSkgOiBwYXRoKTtcblx0XHRyZXR1cm4gW2Jhc2VQYXRoXS5jb25jYXQocGF0aHMpLmpvaW4oJy8nKS5yZXBsYWNlKC9cXC8kLywgJycpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVSTC1kZWNvZGVzIHRoZSBzdHJpbmcuIFdlIG5lZWQgdG8gc3BlY2lhbGx5IGhhbmRsZSAnKydzIGJlY2F1c2Vcblx0ICogdGhlIGphdmFzY3JpcHQgbGlicmFyeSBkb2Vzbid0IGNvbnZlcnQgdGhlbSB0byBzcGFjZXMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byB1cmwgZGVjb2RlLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBkZWNvZGVkIHtAY29kZSBzdHJ9LlxuXHQgKi9cblx0c3RhdGljIHVybERlY29kZShzdHIpIHtcblx0XHRyZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHN0ci5yZXBsYWNlKC9cXCsvZywgJyAnKSk7XG5cdH1cblxufVxuXG4vKipcbiAqIERlZmF1bHQgcHJvdG9jb2wgdmFsdWUuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgaHR0cDpcbiAqIEBzdGF0aWNcbiAqL1xuY29uc3QgaXNTZWN1cmUgPSAoKSA9PlxuXHQodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiZcblx0XHR3aW5kb3cubG9jYXRpb24gJiZcblx0XHR3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgJiZcblx0XHR3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wuaW5kZXhPZignaHR0cHMnKSA9PT0gMCk7XG5cblVyaS5ERUZBVUxUX1BST1RPQ09MID0gaXNTZWN1cmUoKSA/ICdodHRwczonIDogJ2h0dHA6JztcblxuLyoqXG4gKiBIb3N0bmFtZSBwbGFjZWhvbGRlci4gUmVsZXZhbnQgdG8gaW50ZXJuYWwgdXNhZ2Ugb25seS5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cblVyaS5IT1NUTkFNRV9QTEFDRUhPTERFUiA9ICdob3N0bmFtZScgKyBEYXRlLm5vdygpO1xuXG4vKipcbiAqIE5hbWUgdXNlZCBieSB0aGUgcGFyYW0gZ2VuZXJhdGVkIGJ5IGBtYWtlVW5pcXVlYC5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cblVyaS5SQU5ET01fUEFSQU0gPSAnengnO1xuXG5leHBvcnQgZGVmYXVsdCBVcmk7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGV4aXREb2N1bWVudCB9IGZyb20gJ21ldGFsLWRvbSc7XG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IFVyaSBmcm9tICdtZXRhbC11cmknO1xuXG4vKipcbiAqIEEgY29sbGVjdGlvbiBvZiBzdGF0aWMgdXRpbGl0eSBmdW5jdGlvbnMuXG4gKiBAY29uc3RcbiAqL1xuY2xhc3MgdXRpbHMge1xuXG5cdC8qKlxuXHQgKiBDb3BpZXMgYXR0cmlidXRlcyBmb3JtIHNvdXJjZSBub2RlIHRvIHRhcmdldCBub2RlLlxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgY29weU5vZGVBdHRyaWJ1dGVzKHNvdXJjZSwgdGFyZ2V0KSB7XG5cdFx0QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoc291cmNlLmF0dHJpYnV0ZXMpLmZvckVhY2goKGF0dHJpYnV0ZSkgPT4gdGFyZ2V0LnNldEF0dHJpYnV0ZShhdHRyaWJ1dGUubmFtZSwgYXR0cmlidXRlLnZhbHVlKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgY3VycmVudCBicm93c2VyIHBhdGggaW5jbHVkaW5nIGhhc2hiYW5nLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0Q3VycmVudEJyb3dzZXJQYXRoKCkge1xuXHRcdHJldHVybiB0aGlzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCkgKyBnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5oYXNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGN1cnJlbnQgYnJvd3NlciBwYXRoIGV4Y2x1ZGluZyBoYXNoYmFuZy5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCkge1xuXHRcdHJldHVybiBnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSArIGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnNlYXJjaDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBnaXZlbiBub2RlIG9mZnNldCBjb29yZGluYXRlcy5cblx0ICogQHJldHVybiB7IW9iamVjdH1cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldE5vZGVPZmZzZXQobm9kZSkge1xuXHRcdGxldCBbb2Zmc2V0TGVmdCwgb2Zmc2V0VG9wXSA9IFswLCAwXTtcblx0XHRkbyB7XG5cdFx0XHRvZmZzZXRMZWZ0ICs9IG5vZGUub2Zmc2V0TGVmdDtcblx0XHRcdG9mZnNldFRvcCArPSBub2RlLm9mZnNldFRvcDtcblx0XHRcdG5vZGUgPSBub2RlLm9mZnNldFBhcmVudDtcblx0XHR9IHdoaWxlIChub2RlKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0b2Zmc2V0TGVmdCxcblx0XHRcdG9mZnNldFRvcFxuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogRXh0cmFjdHMgdGhlIHBhdGggcGFydCBvZiBhbiB1cmwuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBnZXRVcmxQYXRoKHVybCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHVybCk7XG5cdFx0cmV0dXJuIHVyaS5nZXRQYXRobmFtZSgpICsgdXJpLmdldFNlYXJjaCgpICsgdXJpLmdldEhhc2goKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFeHRyYWN0cyB0aGUgcGF0aCBwYXJ0IG9mIGFuIHVybCB3aXRob3V0IGhhc2hiYW5nLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0VXJsUGF0aFdpdGhvdXRIYXNoKHVybCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHVybCk7XG5cdFx0cmV0dXJuIHVyaS5nZXRQYXRobmFtZSgpICsgdXJpLmdldFNlYXJjaCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIHRoZSBwYXRoIHBhcnQgb2YgYW4gdXJsIHdpdGhvdXQgaGFzaGJhbmcgYW5kIHF1ZXJ5IHNlYXJjaC5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldFVybFBhdGhXaXRob3V0SGFzaEFuZFNlYXJjaCh1cmwpIHtcblx0XHR2YXIgdXJpID0gbmV3IFVyaSh1cmwpO1xuXHRcdHJldHVybiB1cmkuZ2V0UGF0aG5hbWUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdXJsIGlzIGluIHRoZSBzYW1lIGJyb3dzZXIgY3VycmVudCB1cmwgZXhjbHVkaW5nIHRoZSBoYXNoYmFuZy5cblx0ICogQHBhcmFtICB7IXN0cmluZ30gdXJsXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBpc0N1cnJlbnRCcm93c2VyUGF0aCh1cmwpIHtcblx0XHRpZiAodXJsKSB7XG5cdFx0XHRjb25zdCBjdXJyZW50QnJvd3NlclBhdGggPSB0aGlzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCk7XG5cdFx0XHQvLyB0aGUgZ2V0VXJsUGF0aCB3aWxsIGNyZWF0ZSBhIFVyaSBhbmQgd2lsbCBub3JtYWxpemUgdGhlIHBhdGggYW5kXG5cdFx0XHQvLyByZW1vdmUgdGhlIHRyYWlsbGluZyAnLycgZm9yIHByb3Blcmx5IGNvbXBhcmluZyBwYXRocy5cblx0XHRcdHJldHVybiB1dGlscy5nZXRVcmxQYXRoV2l0aG91dEhhc2godXJsKSA9PT0gdGhpcy5nZXRVcmxQYXRoKGN1cnJlbnRCcm93c2VyUGF0aCk7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgSFRNTDUgSGlzdG9yeSBhcGkgaXMgc3VwcG9ydGVkLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgaXNIdG1sNUhpc3RvcnlTdXBwb3J0ZWQoKSB7XG5cdFx0cmV0dXJuICEhKGdsb2JhbHMud2luZG93Lmhpc3RvcnkgJiYgZ2xvYmFscy53aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBhIGdpdmVuIHVybCBpcyBhIHZhbGlkIGh0dHAocykgdXJpIGFuZCByZXR1cm5zIHRoZSBmb3JtZWQgVXJpXG5cdCAqIG9yIGZhbHNlIGlmIHRoZSBwYXJzaW5nIGZhaWxlZFxuXHQgKiBAcmV0dXJuIHtVcml8Ym9vbGVhbn1cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGlzV2ViVXJpKHVybCkge1xuXHRcdHRyeSB7XG5cdFx0XHRyZXR1cm4gbmV3IFVyaSh1cmwpO1xuXHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0Y29uc29sZS5lcnJvcihgJHtlcnIubWVzc2FnZX0gJHt1cmx9YCk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYWxsIGF0dHJpYnV0ZXMgZm9ybSBub2RlLlxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgY2xlYXJOb2RlQXR0cmlidXRlcyhub2RlKSB7XG5cdFx0QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobm9kZS5hdHRyaWJ1dGVzKS5mb3JFYWNoKChhdHRyaWJ1dGUpID0+IG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJpYnV0ZS5uYW1lKSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlIGVsZW1lbnRzIGZyb20gdGhlIGRvY3VtZW50LlxuXHQgKiBAcGFyYW0geyFBcnJheTxFbGVtZW50Pn0gZWxlbWVudHNcblx0ICovXG5cdHN0YXRpYyByZW1vdmVFbGVtZW50c0Zyb21Eb2N1bWVudChlbGVtZW50cykge1xuXHRcdGVsZW1lbnRzLmZvckVhY2goKGVsZW1lbnQpID0+IGV4aXREb2N1bWVudChlbGVtZW50KSk7XG5cdH1cblxuXHQvKipcblx0KiBSZW1vdmVzIHRyYWlsaW5nIHNsYXNoIGluIHBhdGguXG5cdCogQHBhcmFtIHshc3RyaW5nfVxuXHQqIEByZXR1cm4ge3N0cmluZ31cblx0Ki9cblx0c3RhdGljIHJlbW92ZVBhdGhUcmFpbGluZ1NsYXNoKHBhdGgpIHtcblx0XHR2YXIgbGVuZ3RoID0gcGF0aCA/IHBhdGgubGVuZ3RoIDogMDtcblx0XHRpZiAobGVuZ3RoID4gMSAmJiBwYXRoW2xlbmd0aCAtIDFdID09PSAnLycpIHtcblx0XHRcdHBhdGggPSBwYXRoLnN1YnN0cigwLCBsZW5ndGggLSAxKTtcblx0XHR9XG5cdFx0cmV0dXJuIHBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIHJhbmRvbSBzdWZmaXggdG8gdGhlIGhyZWYgYXR0cmlidXRlIG9mIHRoZSBlbGVtZW50LlxuXHQgKiBAcGFyYW0geyFlbGVtZW50fSBlbGVtZW50XG5cdCAqIEByZXR1cm4ge2VsZW1lbnR9XG5cdCAqL1xuXHRzdGF0aWMgc2V0RWxlbWVudFdpdGhSYW5kb21IcmVmKGVsZW1lbnQpIHtcblx0XHRlbGVtZW50LmhyZWYgPSBlbGVtZW50LmhyZWYgKyAnP3E9JyArIE1hdGgucmFuZG9tKCk7XG5cdFx0cmV0dXJuIGVsZW1lbnQ7XG5cdH1cblxuXHQvKipcblx0ICogT3ZlcnJpZGVzIGRvY3VtZW50IHJlZmVycmVyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSByZWZlcnJlclxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgc2V0UmVmZXJyZXIocmVmZXJyZXIpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZ2xvYmFscy5kb2N1bWVudCwgJ3JlZmVycmVyJywge1xuXHRcdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdFx0Z2V0OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuIHJlZmVycmVyO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IHV0aWxzO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnQgZGVmYXVsdCB7XG5cdGJhc2VQYXRoOiAnZGF0YS1zZW5uYS1iYXNlLXBhdGgnLFxuXHRsaW5rU2VsZWN0b3I6ICdkYXRhLXNlbm5hLWxpbmstc2VsZWN0b3InLFxuXHRsb2FkaW5nQ3NzQ2xhc3M6ICdkYXRhLXNlbm5hLWxvYWRpbmctY3NzLWNsYXNzJyxcblx0c2VubmE6ICdkYXRhLXNlbm5hJyxcblx0ZGlzcGF0Y2g6ICdkYXRhLXNlbm5hLWRpc3BhdGNoJyxcblx0c3VyZmFjZTogJ2RhdGEtc2VubmEtc3VyZmFjZScsXG5cdHVwZGF0ZVNjcm9sbFBvc2l0aW9uOiAnZGF0YS1zZW5uYS11cGRhdGUtc2Nyb2xsLXBvc2l0aW9uJ1xufTsiLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7RGlzcG9zYWJsZX0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEV2ZW50SGFuZGxlIHV0aWxpdHkuIEhvbGRzIGluZm9ybWF0aW9uIGFib3V0IGFuIGV2ZW50IHN1YnNjcmlwdGlvbiwgYW5kXG4gKiBhbGxvd3MgcmVtb3ZpbmcgdGhlbSBlYXNpbHkuXG4gKiBFdmVudEhhbmRsZSBpcyBhIERpc3Bvc2FibGUsIGJ1dCBpdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgdGhlXG4gKiBFdmVudEVtaXR0ZXIgdGhhdCBjcmVhdGVkIGl0IGlzIG5vdCB0aGUgb25lIHJlc3BvbnNpYmxlIGZvciBkaXNwb3NpbmcgaXQuXG4gKiBUaGF0IHJlc3BvbnNpYmlsaXR5IGlzIGZvciB0aGUgY29kZSB0aGF0IGhvbGRzIGEgcmVmZXJlbmNlIHRvIGl0LlxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIEV2ZW50SGFuZGxlIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cdC8qKlxuXHQgKiBFdmVudEhhbmRsZSBjb25zdHJ1Y3RvclxuXHQgKiBAcGFyYW0geyFFdmVudEVtaXR0ZXJ9IGVtaXR0ZXIgRW1pdHRlciB0aGUgZXZlbnQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCB3YXMgc3Vic2NyaWJlZCB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0ICovXG5cdGNvbnN0cnVjdG9yKGVtaXR0ZXIsIGV2ZW50LCBsaXN0ZW5lcikge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgRXZlbnRFbWl0dGVyIGluc3RhbmNlIHRoYXQgdGhlIGV2ZW50IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHRcdCAqIEB0eXBlIHtFdmVudEVtaXR0ZXJ9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZW1pdHRlcl8gPSBlbWl0dGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRoYXQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdFx0ICogQHR5cGUge3N0cmluZ31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ldmVudF8gPSBldmVudDtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0XHQgKiBAdHlwZSB7RnVuY3Rpb259XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMubGlzdGVuZXJfID0gbGlzdGVuZXI7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0dGhpcy5lbWl0dGVyXyA9IG51bGw7XG5cdFx0dGhpcy5saXN0ZW5lcl8gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGxpc3RlbmVyIHN1YnNjcmlwdGlvbiBmcm9tIHRoZSBlbWl0dGVyLlxuXHQgKi9cblx0cmVtb3ZlTGlzdGVuZXIoKSB7XG5cdFx0aWYgKCF0aGlzLmVtaXR0ZXJfLmlzRGlzcG9zZWQoKSkge1xuXHRcdFx0dGhpcy5lbWl0dGVyXy5yZW1vdmVMaXN0ZW5lcih0aGlzLmV2ZW50XywgdGhpcy5saXN0ZW5lcl8pO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEhhbmRsZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHthcnJheSwgRGlzcG9zYWJsZSwgaXNGdW5jdGlvbiwgaXNTdHJpbmd9IGZyb20gJ21ldGFsJztcbmltcG9ydCBFdmVudEhhbmRsZSBmcm9tICcuL0V2ZW50SGFuZGxlJztcblxuY29uc3Qgc2luZ2xlQXJyYXlfID0gWzBdO1xuXG4vKipcbiAqIEV2ZW50RW1pdHRlciB1dGlsaXR5LlxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIEV2ZW50RW1pdHRlciBleHRlbmRzIERpc3Bvc2FibGUge1xuXHQvKipcblx0ICogRXZlbnRFbWl0dGVyIGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgZXZlbnQgbGlzdGVuZXJzIHNjb3BlZCBieSBldmVudCB0eXBlLlxuXHRcdCAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCAhQXJyYXk8IWZ1bmN0aW9uKCk+Pn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ldmVudHNfID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhhbmRsZXJzIHRoYXQgYXJlIHRyaWdnZXJlZCB3aGVuIGFuIGV2ZW50IGlzIGxpc3RlbmVkIHRvLlxuXHRcdCAqIEB0eXBlIHtBcnJheX1cblx0XHQgKi9cblx0XHR0aGlzLmxpc3RlbmVySGFuZGxlcnNfID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIENvbmZpZ3VyYXRpb24gb3B0aW9uIHdoaWNoIGRldGVybWluZXMgaWYgYW4gZXZlbnQgZmFjYWRlIHNob3VsZCBiZSBzZW50XG5cdFx0ICogYXMgYSBwYXJhbSBvZiBsaXN0ZW5lcnMgd2hlbiBlbWl0dGluZyBldmVudHMuIElmIHNldCB0byB0cnVlLCB0aGUgZmFjYWRlXG5cdFx0ICogd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIHRoZSBsaXN0ZW5lci5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5zaG91bGRVc2VGYWNhZGVfID0gZmFsc2U7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGhhbmRsZXIgdG8gZ2l2ZW4gaG9sZGVyIHZhcmlhYmxlLiBJZiB0aGUgaG9sZGVyIGRvZXNuJ3QgaGF2ZSBhXG5cdCAqIHZhbHVlIHlldCwgaXQgd2lsbCByZWNlaXZlIHRoZSBoYW5kbGVyIGRpcmVjdGx5LiBJZiB0aGUgaG9sZGVyIGlzIGFuIGFycmF5LFxuXHQgKiB0aGUgdmFsdWUgd2lsbCBqdXN0IGJlIGFkZGVkIHRvIGl0LiBPdGhlcndpc2UsIHRoZSBob2xkZXIgd2lsbCBiZSBzZXQgdG8gYVxuXHQgKiBuZXcgYXJyYXkgY29udGFpbmluZyBpdHMgcHJldmlvdXMgdmFsdWUgcGx1cyB0aGUgbmV3IGhhbmRsZXIuXG5cdCAqIEBwYXJhbSB7Kn0gaG9sZGVyXG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl8T2JqZWN0fSBoYW5kbGVyXG5cdCAqIEByZXR1cm4geyp9IFRoZSBob2xkZXIncyBuZXcgdmFsdWUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFkZEhhbmRsZXJfKGhvbGRlciwgaGFuZGxlcikge1xuXHRcdGlmICghaG9sZGVyKSB7XG5cdFx0XHRob2xkZXIgPSBoYW5kbGVyO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIUFycmF5LmlzQXJyYXkoaG9sZGVyKSkge1xuXHRcdFx0XHRob2xkZXIgPSBbaG9sZGVyXTtcblx0XHRcdH1cblx0XHRcdGhvbGRlci5wdXNoKGhhbmRsZXIpO1xuXHRcdH1cblx0XHRyZXR1cm4gaG9sZGVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0byB0aGUgZW5kIG9mIHRoZSBsaXN0ZW5lcnMgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRzLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gZGVmYXVsdExpc3RlbmVyIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGxpc3RlbmVyIGlzIGEgZGVmYXVsdFxuXHQgKiAgIGFjdGlvbiBmb3IgdGhpcyBldmVudC4gRGVmYXVsdCBhY3Rpb25zIGFyZSBydW4gbGFzdCwgYW5kIG9ubHkgaWYgbm8gcHJldmlvdXNcblx0ICogICBsaXN0ZW5lciBjYWxsIGBwcmV2ZW50RGVmYXVsdCgpYCBvbiB0aGUgcmVjZWl2ZWQgZXZlbnQgZmFjYWRlLlxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG5cdCAqL1xuXHRhZGRMaXN0ZW5lcihldmVudCwgbGlzdGVuZXIsIGRlZmF1bHRMaXN0ZW5lcikge1xuXHRcdHRoaXMudmFsaWRhdGVMaXN0ZW5lcl8obGlzdGVuZXIpO1xuXG5cdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuYWRkU2luZ2xlTGlzdGVuZXJfKGV2ZW50c1tpXSwgbGlzdGVuZXIsIGRlZmF1bHRMaXN0ZW5lcik7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBFdmVudEhhbmRsZSh0aGlzLCBldmVudCwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0byB0aGUgZW5kIG9mIHRoZSBsaXN0ZW5lcnMgYXJyYXkgZm9yIGEgc2luZ2xlIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gZGVmYXVsdExpc3RlbmVyIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGxpc3RlbmVyIGlzIGEgZGVmYXVsdFxuXHQgKiAgIGFjdGlvbiBmb3IgdGhpcyBldmVudC4gRGVmYXVsdCBhY3Rpb25zIGFyZSBydW4gbGFzdCwgYW5kIG9ubHkgaWYgbm8gcHJldmlvdXNcblx0ICogICBsaXN0ZW5lciBjYWxsIGBwcmV2ZW50RGVmYXVsdCgpYCBvbiB0aGUgcmVjZWl2ZWQgZXZlbnQgZmFjYWRlLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9uPX0gb3JpZ2luIFRoZSBvcmlnaW5hbCBmdW5jdGlvbiB0aGF0IHdhcyBhZGRlZCBhcyBhXG5cdCAqICAgbGlzdGVuZXIsIGlmIHRoZXJlIGlzIGFueS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0YWRkU2luZ2xlTGlzdGVuZXJfKGV2ZW50LCBsaXN0ZW5lciwgZGVmYXVsdExpc3RlbmVyLCBvcmlnaW4pIHtcblx0XHR0aGlzLnJ1bkxpc3RlbmVySGFuZGxlcnNfKGV2ZW50KTtcblx0XHRpZiAoZGVmYXVsdExpc3RlbmVyIHx8IG9yaWdpbikge1xuXHRcdFx0bGlzdGVuZXIgPSB7XG5cdFx0XHRcdGRlZmF1bHQ6IGRlZmF1bHRMaXN0ZW5lcixcblx0XHRcdFx0Zm46IGxpc3RlbmVyLFxuXHRcdFx0XHRvcmlnaW46IG9yaWdpbixcblx0XHRcdH07XG5cdFx0fVxuXHRcdHRoaXMuZXZlbnRzXyA9IHRoaXMuZXZlbnRzXyB8fCB7fTtcblx0XHR0aGlzLmV2ZW50c19bZXZlbnRdID0gdGhpcy5hZGRIYW5kbGVyXyh0aGlzLmV2ZW50c19bZXZlbnRdLCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQnVpbGRzIGZhY2FkZSBmb3IgdGhlIGdpdmVuIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7T2JqZWN0fVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRidWlsZEZhY2FkZV8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5nZXRTaG91bGRVc2VGYWNhZGUoKSkge1xuXHRcdFx0Y29uc3QgZmFjYWRlID0ge1xuXHRcdFx0XHRwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0ZmFjYWRlLnByZXZlbnRlZERlZmF1bHQgPSB0cnVlO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR0YXJnZXQ6IHRoaXMsXG5cdFx0XHRcdHR5cGU6IGV2ZW50LFxuXHRcdFx0fTtcblx0XHRcdHJldHVybiBmYWNhZGU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy5cblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5ldmVudHNfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBFeGVjdXRlIGVhY2ggb2YgdGhlIGxpc3RlbmVycyBpbiBvcmRlciB3aXRoIHRoZSBzdXBwbGllZCBhcmd1bWVudHMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0geyp9IG9wdF9hcmdzIFthcmcxXSwgW2FyZzJdLCBbLi4uXVxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBSZXR1cm5zIHRydWUgaWYgZXZlbnQgaGFkIGxpc3RlbmVycywgZmFsc2Ugb3RoZXJ3aXNlLlxuXHQgKi9cblx0ZW1pdChldmVudCkge1xuXHRcdGNvbnN0IGxpc3RlbmVycyA9IHRoaXMuZ2V0UmF3TGlzdGVuZXJzXyhldmVudCk7XG5cdFx0aWYgKGxpc3RlbmVycy5sZW5ndGggPT09IDApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRjb25zdCBhcmdzID0gYXJyYXkuc2xpY2UoYXJndW1lbnRzLCAxKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdHRoaXMucnVuTGlzdGVuZXJzXyhsaXN0ZW5lcnMsIGFyZ3MsIHRoaXMuYnVpbGRGYWNhZGVfKGV2ZW50KSk7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgbGlzdGVuZXIgb2JqZWN0cyBmb3IgdGhlIGdpdmVuIGV2ZW50LCBpZiB0aGVyZSBhcmUgYW55LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7IUFycmF5fVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRnZXRSYXdMaXN0ZW5lcnNfKGV2ZW50KSB7XG5cdFx0Y29uc3QgZGlyZWN0TGlzdGVuZXJzID0gdG9BcnJheSh0aGlzLmV2ZW50c18gJiYgdGhpcy5ldmVudHNfW2V2ZW50XSk7XG5cdFx0cmV0dXJuIGRpcmVjdExpc3RlbmVycy5jb25jYXQoXG5cdFx0XHR0b0FycmF5KHRoaXMuZXZlbnRzXyAmJiB0aGlzLmV2ZW50c19bJyonXSlcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9uIHdoaWNoIGRldGVybWluZXMgaWYgYW4gZXZlbnQgZmFjYWRlIHNob3VsZFxuXHQgKiBiZSBzZW50IGFzIGEgcGFyYW0gb2YgbGlzdGVuZXJzIHdoZW4gZW1pdHRpbmcgZXZlbnRzLiBJZiBzZXQgdG8gdHJ1ZSwgdGhlXG5cdCAqIGZhY2FkZSB3aWxsIGJlIHBhc3NlZCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgb2YgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0Z2V0U2hvdWxkVXNlRmFjYWRlKCkge1xuXHRcdHJldHVybiB0aGlzLnNob3VsZFVzZUZhY2FkZV87XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHtBcnJheX0gQXJyYXkgb2YgbGlzdGVuZXJzLlxuXHQgKi9cblx0bGlzdGVuZXJzKGV2ZW50KSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0UmF3TGlzdGVuZXJzXyhldmVudCkubWFwKFxuXHRcdFx0bGlzdGVuZXIgPT4gKGxpc3RlbmVyLmZuID8gbGlzdGVuZXIuZm4gOiBsaXN0ZW5lcilcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIGZpeGVkIG51bWJlciBvZiB0aW1lcyBmb3IgdGhlXG5cdCAqIGV2ZW50cy4gQWZ0ZXIgZWFjaCBldmVudCBpcyB0cmlnZ2VyZWQgdGhlIHNwZWNpZmllZCBhbW91bnQgb2YgdGltZXMsIHRoZVxuXHQgKiBsaXN0ZW5lciBpcyByZW1vdmVkIGZvciBpdC5cblx0ICogQHBhcmFtIHshKEFycmF5fHN0cmluZyl9IGV2ZW50XG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBhbW91bnQgVGhlIGFtb3VudCBvZiB0aW1lcyB0aGlzIGV2ZW50IHNob3VsZCBiZSBsaXN0ZW5lZFxuXHQgKiB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cblx0ICovXG5cdG1hbnkoZXZlbnQsIGFtb3VudCwgbGlzdGVuZXIpIHtcblx0XHRjb25zdCBldmVudHMgPSB0aGlzLnRvRXZlbnRzQXJyYXlfKGV2ZW50KTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dGhpcy5tYW55XyhldmVudHNbaV0sIGFtb3VudCwgbGlzdGVuZXIpO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgRXZlbnRIYW5kbGUodGhpcywgZXZlbnQsIGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBmaXhlZCBudW1iZXIgb2YgdGltZXMgZm9yIGEgc2luZ2xlXG5cdCAqIGV2ZW50LiBBZnRlciB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkIHRoZSBzcGVjaWZpZWQgYW1vdW50IG9mIHRpbWVzLCB0aGVcblx0ICogbGlzdGVuZXIgaXMgcmVtb3ZlZC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBhbW91bnQgVGhlIGFtb3VudCBvZiB0aW1lcyB0aGlzIGV2ZW50IHNob3VsZCBiZSBsaXN0ZW5lZFxuXHQgKiB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG1hbnlfKGV2ZW50LCBhbW91bnQsIGxpc3RlbmVyKSB7XG5cdFx0Y29uc3Qgc2VsZiA9IHRoaXM7XG5cblx0XHRpZiAoYW1vdW50IDw9IDApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvKipcblx0XHQgKlxuXHRcdCAqL1xuXHRcdGZ1bmN0aW9uIGhhbmRsZXJJbnRlcm5hbCgpIHtcblx0XHRcdGlmICgtLWFtb3VudCA9PT0gMCkge1xuXHRcdFx0XHRzZWxmLnJlbW92ZUxpc3RlbmVyKGV2ZW50LCBoYW5kbGVySW50ZXJuYWwpO1xuXHRcdFx0fVxuXHRcdFx0bGlzdGVuZXIuYXBwbHkoc2VsZiwgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdH1cblxuXHRcdHNlbGYuYWRkU2luZ2xlTGlzdGVuZXJfKGV2ZW50LCBoYW5kbGVySW50ZXJuYWwsIGZhbHNlLCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIGEgbGlzdGVuZXIgb2JqZWN0IG1hdGNoZXMgdGhlIGdpdmVuIGxpc3RlbmVyIGZ1bmN0aW9uLiBUbyBtYXRjaCxcblx0ICogaXQgbmVlZHMgdG8gZWl0aGVyIHBvaW50IHRvIHRoYXQgbGlzdGVuZXIgb3IgaGF2ZSBpdCBhcyBpdHMgb3JpZ2luLlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IGxpc3RlbmVyT2JqXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRtYXRjaGVzTGlzdGVuZXJfKGxpc3RlbmVyT2JqLCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IGZuID0gbGlzdGVuZXJPYmouZm4gfHwgbGlzdGVuZXJPYmo7XG5cdFx0cmV0dXJuIChcblx0XHRcdGZuID09PSBsaXN0ZW5lciB8fFxuXHRcdFx0KGxpc3RlbmVyT2JqLm9yaWdpbiAmJiBsaXN0ZW5lck9iai5vcmlnaW4gPT09IGxpc3RlbmVyKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRzLlxuXHQgKiBDYXV0aW9uOiBjaGFuZ2VzIGFycmF5IGluZGljZXMgaW4gdGhlIGxpc3RlbmVyIGFycmF5IGJlaGluZCB0aGUgbGlzdGVuZXIuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudFxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IU9iamVjdH0gUmV0dXJucyBlbWl0dGVyLCBzbyBjYWxscyBjYW4gYmUgY2hhaW5lZC5cblx0ICovXG5cdG9mZihldmVudCwgbGlzdGVuZXIpIHtcblx0XHR0aGlzLnZhbGlkYXRlTGlzdGVuZXJfKGxpc3RlbmVyKTtcblx0XHRpZiAoIXRoaXMuZXZlbnRzXykge1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuZXZlbnRzX1tldmVudHNbaV1dID0gdGhpcy5yZW1vdmVNYXRjaGluZ0xpc3RlbmVyT2Jqc18oXG5cdFx0XHRcdHRvQXJyYXkodGhpcy5ldmVudHNfW2V2ZW50c1tpXV0pLFxuXHRcdFx0XHRsaXN0ZW5lclxuXHRcdFx0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQHBhcmFtIHshKEFycmF5fHN0cmluZyl9IGV2ZW50c1xuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuXHQgKi9cblx0b24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgaGFuZGxlciB0aGF0IGdldHMgdHJpZ2dlcmVkIHdoZW4gYW4gZXZlbnQgaXMgbGlzdGVuZWQgdG8gb24gdGhpc1xuXHQgKiBpbnN0YW5jZS5cblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKX0gaGFuZGxlclxuXHQgKi9cblx0b25MaXN0ZW5lcihoYW5kbGVyKSB7XG5cdFx0dGhpcy5saXN0ZW5lckhhbmRsZXJzXyA9IHRoaXMuYWRkSGFuZGxlcl8oXG5cdFx0XHR0aGlzLmxpc3RlbmVySGFuZGxlcnNfLFxuXHRcdFx0aGFuZGxlclxuXHRcdCk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgb25lIHRpbWUgbGlzdGVuZXIgZm9yIHRoZSBldmVudHMuIFRoaXMgbGlzdGVuZXIgaXMgaW52b2tlZCBvbmx5IHRoZVxuXHQgKiBuZXh0IHRpbWUgZWFjaCBldmVudCBpcyBmaXJlZCwgYWZ0ZXIgd2hpY2ggaXQgaXMgcmVtb3ZlZC5cblx0ICogQHBhcmFtIHshKEFycmF5fHN0cmluZyl9IGV2ZW50c1xuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuXHQgKi9cblx0b25jZShldmVudHMsIGxpc3RlbmVyKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFueShldmVudHMsIDEsIGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMsIG9yIHRob3NlIG9mIHRoZSBzcGVjaWZpZWQgZXZlbnRzLiBJdCdzIG5vdCBhIGdvb2Rcblx0ICogaWRlYSB0byByZW1vdmUgbGlzdGVuZXJzIHRoYXQgd2VyZSBhZGRlZCBlbHNld2hlcmUgaW4gdGhlIGNvZGUsXG5cdCAqIGVzcGVjaWFsbHkgd2hlbiBpdCdzIG9uIGFuIGVtaXR0ZXIgdGhhdCB5b3UgZGlkbid0IGNyZWF0ZS5cblx0ICogQHBhcmFtIHsoQXJyYXl8c3RyaW5nKT19IGV2ZW50XG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRyZW1vdmVBbGxMaXN0ZW5lcnMoZXZlbnQpIHtcblx0XHRpZiAodGhpcy5ldmVudHNfKSB7XG5cdFx0XHRpZiAoZXZlbnQpIHtcblx0XHRcdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdFx0dGhpcy5ldmVudHNfW2V2ZW50c1tpXV0gPSBudWxsO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmV2ZW50c18gPSBudWxsO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lciBvYmplY3RzIGZyb20gdGhlIGdpdmVuIGFycmF5IHRoYXQgbWF0Y2ggdGhlIGdpdmVuXG5cdCAqIGxpc3RlbmVyIGZ1bmN0aW9uLlxuXHQgKiBAcGFyYW0ge0FycmF5LjxPYmplY3Q+fSBsaXN0ZW5lck9ianNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4ge0FycmF5LjxPYmplY3Q+fE9iamVjdH0gVGhlIG5ldyBsaXN0ZW5lcnMgYXJyYXkgZm9yIHRoaXMgZXZlbnQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHJlbW92ZU1hdGNoaW5nTGlzdGVuZXJPYmpzXyhsaXN0ZW5lck9ianMsIGxpc3RlbmVyKSB7XG5cdFx0Y29uc3QgZmluYWxMaXN0ZW5lcnMgPSBbXTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGxpc3RlbmVyT2Jqcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKCF0aGlzLm1hdGNoZXNMaXN0ZW5lcl8obGlzdGVuZXJPYmpzW2ldLCBsaXN0ZW5lcikpIHtcblx0XHRcdFx0ZmluYWxMaXN0ZW5lcnMucHVzaChsaXN0ZW5lck9ianNbaV0pO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gZmluYWxMaXN0ZW5lcnMubGVuZ3RoID4gMCA/IGZpbmFsTGlzdGVuZXJzIDogbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRzLlxuXHQgKiBDYXV0aW9uOiBjaGFuZ2VzIGFycmF5IGluZGljZXMgaW4gdGhlIGxpc3RlbmVyIGFycmF5IGJlaGluZCB0aGUgbGlzdGVuZXIuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRyZW1vdmVMaXN0ZW5lcigpIHtcblx0XHRyZXR1cm4gdGhpcy5vZmYuYXBwbHkodGhpcywgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHR9XG5cblx0LyoqXG5cdCAqIFJ1bnMgdGhlIGhhbmRsZXJzIHdoZW4gYW4gZXZlbnQgaXMgbGlzdGVuZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRydW5MaXN0ZW5lckhhbmRsZXJzXyhldmVudCkge1xuXHRcdGxldCBoYW5kbGVycyA9IHRoaXMubGlzdGVuZXJIYW5kbGVyc187XG5cdFx0aWYgKGhhbmRsZXJzKSB7XG5cdFx0XHRoYW5kbGVycyA9IHRvQXJyYXkoaGFuZGxlcnMpO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBoYW5kbGVycy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRoYW5kbGVyc1tpXShldmVudCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJ1bnMgdGhlIGdpdmVuIGxpc3RlbmVycy5cblx0ICogQHBhcmFtIHshQXJyYXl9IGxpc3RlbmVyc1xuXHQgKiBAcGFyYW0geyFBcnJheX0gYXJnc1xuXHQgKiBAcGFyYW0ge09iamVjdH0gZmFjYWRlXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHJ1bkxpc3RlbmVyc18obGlzdGVuZXJzLCBhcmdzLCBmYWNhZGUpIHtcblx0XHRpZiAoZmFjYWRlKSB7XG5cdFx0XHRhcmdzLnB1c2goZmFjYWRlKTtcblx0XHR9XG5cblx0XHRjb25zdCBkZWZhdWx0TGlzdGVuZXJzID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldLmZuIHx8IGxpc3RlbmVyc1tpXTtcblx0XHRcdGlmIChsaXN0ZW5lcnNbaV0uZGVmYXVsdCkge1xuXHRcdFx0XHRkZWZhdWx0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXIpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bGlzdGVuZXIuYXBwbHkodGhpcywgYXJncyk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICghZmFjYWRlIHx8ICFmYWNhZGUucHJldmVudGVkRGVmYXVsdCkge1xuXHRcdFx0Zm9yIChsZXQgaiA9IDA7IGogPCBkZWZhdWx0TGlzdGVuZXJzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdGRlZmF1bHRMaXN0ZW5lcnNbal0uYXBwbHkodGhpcywgYXJncyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9uIHdoaWNoIGRldGVybWluZXMgaWYgYW4gZXZlbnQgZmFjYWRlIHNob3VsZFxuXHQgKiBiZSBzZW50IGFzIGEgcGFyYW0gb2YgbGlzdGVuZXJzIHdoZW4gZW1pdHRpbmcgZXZlbnRzLiBJZiBzZXQgdG8gdHJ1ZSwgdGhlXG5cdCAqIGZhY2FkZSB3aWxsIGJlIHBhc3NlZCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgb2YgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IHNob3VsZFVzZUZhY2FkZVxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fSBSZXR1cm5zIGVtaXR0ZXIsIHNvIGNhbGxzIGNhbiBiZSBjaGFpbmVkLlxuXHQgKi9cblx0c2V0U2hvdWxkVXNlRmFjYWRlKHNob3VsZFVzZUZhY2FkZSkge1xuXHRcdHRoaXMuc2hvdWxkVXNlRmFjYWRlXyA9IHNob3VsZFVzZUZhY2FkZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyB0aGUgcGFyYW1ldGVyIHRvIGFuIGFycmF5IGlmIG9ubHkgb25lIGV2ZW50IGlzIGdpdmVuLiBSZXVzZXMgdGhlXG5cdCAqIHNhbWUgYXJyYXkgZWFjaCB0aW1lIHRoaXMgY29udmVyc2lvbiBpcyBkb25lLCB0byBhdm9pZCB1c2luZyBtb3JlIG1lbW9yeVxuXHQgKiB0aGFuIG5lY2Vzc2FyeS5cblx0ICogQHBhcmFtICB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHJldHVybiB7IUFycmF5fVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHR0b0V2ZW50c0FycmF5XyhldmVudHMpIHtcblx0XHRpZiAoaXNTdHJpbmcoZXZlbnRzKSkge1xuXHRcdFx0c2luZ2xlQXJyYXlfWzBdID0gZXZlbnRzO1xuXHRcdFx0ZXZlbnRzID0gc2luZ2xlQXJyYXlfO1xuXHRcdH1cblx0XHRyZXR1cm4gZXZlbnRzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gbGlzdGVuZXIgaXMgdmFsaWQsIHRocm93aW5nIGFuIGV4Y2VwdGlvbiB3aGVuIGl0J3Mgbm90LlxuXHQgKiBAcGFyYW0gIHsqfSBsaXN0ZW5lclxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHR2YWxpZGF0ZUxpc3RlbmVyXyhsaXN0ZW5lcikge1xuXHRcdGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoJ0xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIENvbnZlcnRzIHRvIGFuIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gdmFsXG4gKiBAcmV0dXJuIHtBcnJheX1cbiAqL1xuZnVuY3Rpb24gdG9BcnJheSh2YWwpIHtcblx0dmFsID0gdmFsIHx8IFtdO1xuXHRyZXR1cm4gQXJyYXkuaXNBcnJheSh2YWwpID8gdmFsIDogW3ZhbF07XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50RW1pdHRlcjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHtEaXNwb3NhYmxlfSBmcm9tICdtZXRhbCc7XG5cbi8qKlxuICogRXZlbnRFbWl0dGVyUHJveHkgdXRpbGl0eS4gSXQncyByZXNwb25zaWJsZSBmb3IgbGlua2luZyB0d28gRXZlbnRFbWl0dGVyXG4gKiBpbnN0YW5jZXMgdG9nZXRoZXIsIGVtaXR0aW5nIGV2ZW50cyBmcm9tIHRoZSBmaXJzdCBlbWl0dGVyIHRocm91Z2ggdGhlXG4gKiBzZWNvbmQgb25lLiBUaGF0IG1lYW5zIHRoYXQgbGlzdGVuaW5nIHRvIGEgc3VwcG9ydGVkIGV2ZW50IG9uIHRoZSB0YXJnZXRcbiAqIGVtaXR0ZXIgd2lsbCBtZWFuIGxpc3RlbmluZyB0byBpdCBvbiB0aGUgb3JpZ2luIGVtaXR0ZXIgYXMgd2VsbC5cbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEVtaXR0ZXJQcm94eSBleHRlbmRzIERpc3Bvc2FibGUge1xuXHQvKipcblx0ICogQHBhcmFtIHtFdmVudEVtaXR0ZXJ9IG9yaWdpbkVtaXR0ZXIgRXZlbnRzIG9yaWdpbmF0ZWQgb24gdGhpcyBlbWl0dGVyXG5cdCAqIHdpbGwgYmUgZmlyZWQgZm9yIHRoZSB0YXJnZXQgZW1pdHRlcidzIGxpc3RlbmVycyBhcyB3ZWxsLlxuXHQgKiBAcGFyYW0ge0V2ZW50RW1pdHRlcn0gdGFyZ2V0RW1pdHRlciBFdmVudCBsaXN0ZW5lcnMgYXR0YWNoZWQgdG8gdGhpcyBlbWl0dGVyXG5cdCAqIHdpbGwgYWxzbyBiZSB0cmlnZ2VyZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWQgYnkgdGhlIG9yaWdpbiBlbWl0dGVyLlxuXHQgKiBAcGFyYW0ge09iamVjdH0gYmxhY2tsaXN0IE9wdGlvbmFsIGJsYWNrbGlzdCBvZiBldmVudHMgdGhhdCBzaG91bGQgbm90IGJlXG5cdCAqIHByb3hpZWQuXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSB3aGl0ZWxpc3Rcblx0ICovXG5cdGNvbnN0cnVjdG9yKG9yaWdpbkVtaXR0ZXIsIHRhcmdldEVtaXR0ZXIsIGJsYWNrbGlzdCwgd2hpdGVsaXN0KSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIE1hcCBvZiBldmVudHMgdGhhdCBzaG91bGQgbm90IGJlIHByb3hpZWQuXG5cdFx0ICogQHR5cGUge09iamVjdH1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ibGFja2xpc3RfID0gYmxhY2tsaXN0O1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG9yaWdpbiBlbWl0dGVyLiBUaGlzIGVtaXR0ZXIncyBldmVudHMgd2lsbCBiZSBwcm94aWVkIHRocm91Z2ggdGhlXG5cdFx0ICogdGFyZ2V0IGVtaXR0ZXIuXG5cdFx0ICogQHR5cGUge0V2ZW50RW1pdHRlcn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyA9IG9yaWdpbkVtaXR0ZXI7XG5cblx0XHQvKipcblx0XHQgKiBBIGxpc3Qgb2YgZXZlbnRzIHRoYXQgYXJlIHBlbmRpbmcgdG8gYmUgbGlzdGVuZWQgYnkgYW4gYWN0dWFsIG9yaWdpblxuXHRcdCAqIGVtaXR0ZXIuIEV2ZW50cyBhcmUgc3RvcmVkIGhlcmUgd2hlbiB0aGUgb3JpZ2luIGRvZXNuJ3QgZXhpc3QsIHNvIHRoZXlcblx0XHQgKiBjYW4gYmUgc2V0IG9uIGEgbmV3IG9yaWdpbiB3aGVuIG9uZSBpcyBzZXQuXG5cdFx0ICogQHR5cGUge0FycmF5fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnBlbmRpbmdFdmVudHNfID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGEgbWFwIG9mIGV2ZW50cyBmcm9tIHRoZSBvcmlnaW4gZW1pdHRlciB0aGF0IGFyZSBhbHJlYWR5IGJlaW5nIHByb3hpZWQuXG5cdFx0ICogQHR5cGUge09iamVjdDxzdHJpbmcsICFFdmVudEhhbmRsZT59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucHJveGllZEV2ZW50c18gPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIHRhcmdldCBlbWl0dGVyLiBUaGlzIGVtaXR0ZXIgd2lsbCBlbWl0IGFsbCBldmVudHMgdGhhdCBjb21lIGZyb21cblx0XHQgKiB0aGUgb3JpZ2luIGVtaXR0ZXIuXG5cdFx0ICogQHR5cGUge0V2ZW50RW1pdHRlcn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXyA9IHRhcmdldEVtaXR0ZXI7XG5cblx0XHQvKipcblx0XHQgKiBNYXAgb2YgZXZlbnRzIHRoYXQgc2hvdWxkIGJlIHByb3hpZWQuIElmIHdoaXRlbGlzdCBpcyBzZXQgYmxhY2tsaXN0IGlzIGlnbm9yZWQuXG5cdFx0ICogQHR5cGUge09iamVjdH1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy53aGl0ZWxpc3RfID0gd2hpdGVsaXN0O1xuXG5cdFx0dGhpcy5zdGFydFByb3h5XygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIGdpdmVuIGxpc3RlbmVyIGZvciB0aGUgZ2l2ZW4gZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbigpfSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IFRoZSBsaXN0ZW5lZCBldmVudCdzIGhhbmRsZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0YWRkTGlzdGVuZXJfKGV2ZW50LCBsaXN0ZW5lcikge1xuXHRcdHJldHVybiB0aGlzLm9yaWdpbkVtaXR0ZXJfLm9uKGV2ZW50LCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLnJlbW92ZUxpc3RlbmVyc18oKTtcblx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gbnVsbDtcblx0XHR0aGlzLm9yaWdpbkVtaXR0ZXJfID0gbnVsbDtcblx0XHR0aGlzLnRhcmdldEVtaXR0ZXJfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBFbWl0cyB0aGUgc3BlY2lmaWVkIGV2ZW50IHR5cGUgb24gdGhlIHRhcmdldCBlbWl0dGVyLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRlbWl0T25UYXJnZXRfKC4uLmFyZ3MpIHtcblx0XHR0aGlzLnRhcmdldEVtaXR0ZXJfLmVtaXQoLi4uYXJncyk7XG5cdH1cblxuXHQvKipcblx0ICogUHJveGllcyB0aGUgZ2l2ZW4gZXZlbnQgZnJvbSB0aGUgb3JpZ2luIHRvIHRoZSB0YXJnZXQgZW1pdHRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqL1xuXHRwcm94eUV2ZW50KGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuc2hvdWxkUHJveHlFdmVudF8oZXZlbnQpKSB7XG5cdFx0XHR0aGlzLnRyeVRvQWRkTGlzdGVuZXJfKGV2ZW50KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyB0aGUgcHJveHkgbGlzdGVuZXIgZm9yIGFsbCBldmVudHMuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyc18oKSB7XG5cdFx0aWYgKHRoaXMucHJveGllZEV2ZW50c18pIHtcblx0XHRcdGNvbnN0IGV2ZW50cyA9IE9iamVjdC5rZXlzKHRoaXMucHJveGllZEV2ZW50c18pO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzX1tldmVudHNbaV1dLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gbnVsbDtcblx0XHR9XG5cdFx0dGhpcy5wZW5kaW5nRXZlbnRzXyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogQ2hhbmdlcyB0aGUgb3JpZ2luIGVtaXR0ZXIuIFRoaXMgYXV0b21hdGljYWxseSBkZXRhY2hlcyBhbnkgZXZlbnRzIHRoYXRcblx0ICogd2VyZSBhbHJlYWR5IGJlaW5nIHByb3hpZWQgZnJvbSB0aGUgcHJldmlvdXMgZW1pdHRlciwgYW5kIHN0YXJ0cyBwcm94eWluZ1xuXHQgKiB0aGVtIG9uIHRoZSBuZXcgZW1pdHRlciBpbnN0ZWFkLlxuXHQgKiBAcGFyYW0geyFFdmVudEVtaXR0ZXJ9IG9yaWdpbkVtaXR0ZXJcblx0ICovXG5cdHNldE9yaWdpbkVtaXR0ZXIob3JpZ2luRW1pdHRlcikge1xuXHRcdGNvbnN0IGV2ZW50cyA9XG5cdFx0XHR0aGlzLm9yaWdpbkVtaXR0ZXJfICYmIHRoaXMucHJveGllZEV2ZW50c19cblx0XHRcdFx0PyBPYmplY3Qua2V5cyh0aGlzLnByb3hpZWRFdmVudHNfKVxuXHRcdFx0XHQ6IHRoaXMucGVuZGluZ0V2ZW50c187XG5cdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyA9IG9yaWdpbkVtaXR0ZXI7XG5cdFx0aWYgKGV2ZW50cykge1xuXHRcdFx0dGhpcy5yZW1vdmVMaXN0ZW5lcnNfKCk7XG5cdFx0XHRldmVudHMuZm9yRWFjaChldmVudCA9PiB0aGlzLnByb3h5RXZlbnQoZXZlbnQpKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBldmVudCBzaG91bGQgYmUgcHJveGllZC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHNob3VsZFByb3h5RXZlbnRfKGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMud2hpdGVsaXN0XyAmJiAhdGhpcy53aGl0ZWxpc3RfW2V2ZW50XSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRpZiAodGhpcy5ibGFja2xpc3RfICYmIHRoaXMuYmxhY2tsaXN0X1tldmVudF0pIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuICF0aGlzLnByb3hpZWRFdmVudHNfIHx8ICF0aGlzLnByb3hpZWRFdmVudHNfW2V2ZW50XTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTdGFydHMgcHJveHlpbmcgYWxsIGV2ZW50cyBmcm9tIHRoZSBvcmlnaW4gdG8gdGhlIHRhcmdldCBlbWl0dGVyLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRzdGFydFByb3h5XygpIHtcblx0XHR0aGlzLnRhcmdldEVtaXR0ZXJfLm9uTGlzdGVuZXIodGhpcy5wcm94eUV2ZW50LmJpbmQodGhpcykpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0byB0aGUgb3JpZ2luIGVtaXR0ZXIsIGlmIGl0IGV4aXN0cy4gT3RoZXJ3aXNlLCBzdG9yZXNcblx0ICogdGhlIHBlbmRpbmcgbGlzdGVuZXIgc28gaXQgY2FuIGJlIHVzZWQgb24gYSBmdXR1cmUgb3JpZ2luIGVtaXR0ZXIuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHR0cnlUb0FkZExpc3RlbmVyXyhldmVudCkge1xuXHRcdGlmICh0aGlzLm9yaWdpbkVtaXR0ZXJfKSB7XG5cdFx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gdGhpcy5wcm94aWVkRXZlbnRzXyB8fCB7fTtcblx0XHRcdHRoaXMucHJveGllZEV2ZW50c19bZXZlbnRdID0gdGhpcy5hZGRMaXN0ZW5lcl8oXG5cdFx0XHRcdGV2ZW50LFxuXHRcdFx0XHR0aGlzLmVtaXRPblRhcmdldF8uYmluZCh0aGlzLCBldmVudClcblx0XHRcdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMucGVuZGluZ0V2ZW50c18gPSB0aGlzLnBlbmRpbmdFdmVudHNfIHx8IFtdO1xuXHRcdFx0dGhpcy5wZW5kaW5nRXZlbnRzXy5wdXNoKGV2ZW50KTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRXZlbnRFbWl0dGVyUHJveHk7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7RGlzcG9zYWJsZX0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEV2ZW50SGFuZGxlciB1dGlsaXR5LiBJdCdzIHVzZWZ1bCBmb3IgZWFzaWx5IHJlbW92aW5nIGEgZ3JvdXAgb2ZcbiAqIGxpc3RlbmVycyBmcm9tIGRpZmZlcmVudCBFdmVudEVtaXR0ZXIgaW5zdGFuY2VzLlxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIEV2ZW50SGFuZGxlciBleHRlbmRzIERpc3Bvc2FibGUge1xuXHQvKipcblx0ICogRXZlbnRIYW5kbGVyIGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogQW4gYXJyYXkgdGhhdCBob2xkcyB0aGUgYWRkZWQgZXZlbnQgaGFuZGxlcywgc28gdGhlIGxpc3RlbmVycyBjYW4gYmVcblx0XHQgKiByZW1vdmVkIGxhdGVyLlxuXHRcdCAqIEB0eXBlIHtBcnJheS48RXZlbnRIYW5kbGU+fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmV2ZW50SGFuZGxlc18gPSBbXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGV2ZW50IGhhbmRsZXMgdG8gYmUgcmVtb3ZlZCBsYXRlciB0aHJvdWdoIHRoZSBgcmVtb3ZlQWxsTGlzdGVuZXJzYFxuXHQgKiBtZXRob2QuXG5cdCAqIEBwYXJhbSB7Li4uKCFFdmVudEhhbmRsZSl9IHZhcl9hcmdzXG5cdCAqL1xuXHRhZGQoLi4uYXJncykge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmV2ZW50SGFuZGxlc18ucHVzaChhcmdzW2ldKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLmV2ZW50SGFuZGxlc18gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyB0aGF0IGhhdmUgYmVlbiBhZGRlZCB0aHJvdWdoIHRoZSBgYWRkYCBtZXRob2QuXG5cdCAqL1xuXHRyZW1vdmVBbGxMaXN0ZW5lcnMoKSB7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmV2ZW50SGFuZGxlc18ubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuZXZlbnRIYW5kbGVzX1tpXS5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdH1cblxuXHRcdHRoaXMuZXZlbnRIYW5kbGVzXyA9IFtdO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50SGFuZGxlcjtcbiIsIi8qIVxuICogUHJvbWlzZXMgcG9seWZpbGwgZnJvbSBHb29nbGUncyBDbG9zdXJlIExpYnJhcnkuXG4gKlxuICogICAgICBDb3B5cmlnaHQgMjAxMyBUaGUgQ2xvc3VyZSBMaWJyYXJ5IEF1dGhvcnMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogTk9URShlZHVhcmRvKTogUHJvbWlzZSBzdXBwb3J0IGlzIG5vdCByZWFkeSBvbiBhbGwgc3VwcG9ydGVkIGJyb3dzZXJzLFxuICogdGhlcmVmb3JlIG1ldGFsLXByb21pc2UgaXMgdGVtcG9yYXJpbHkgdXNpbmcgR29vZ2xlJ3MgcHJvbWlzZXMgYXMgcG9seWZpbGwuXG4gKiBJdCBzdXBwb3J0cyBjYW5jZWxsYWJsZSBwcm9taXNlcyBhbmQgaGFzIGNsZWFuIGFuZCBmYXN0IGltcGxlbWVudGF0aW9uLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaXNEZWYsIGlzRnVuY3Rpb24sIGlzT2JqZWN0IH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgYXN5bmMgfSBmcm9tICdtZXRhbCc7XG5cbi8qKlxuICogUHJvdmlkZXMgYSBtb3JlIHN0cmljdCBpbnRlcmZhY2UgZm9yIFRoZW5hYmxlcyBpbiB0ZXJtcyBvZlxuICogaHR0cDovL3Byb21pc2VzYXBsdXMuY29tIGZvciBpbnRlcm9wIHdpdGgge0BzZWUgQ2FuY2VsbGFibGVQcm9taXNlfS5cbiAqXG4gKiBAaW50ZXJmYWNlXG4gKiBAZXh0ZW5kcyB7SVRoZW5hYmxlLjxUWVBFPn1cbiAqIEB0ZW1wbGF0ZSBUWVBFXG4gKi9cbnZhciBUaGVuYWJsZSA9IGZ1bmN0aW9uKCkge307XG5cbi8qKlxuICogQWRkcyBjYWxsYmFja3MgdGhhdCB3aWxsIG9wZXJhdGUgb24gdGhlIHJlc3VsdCBvZiB0aGUgVGhlbmFibGUsIHJldHVybmluZyBhXG4gKiBuZXcgY2hpbGQgUHJvbWlzZS5cbiAqXG4gKiBJZiB0aGUgVGhlbmFibGUgaXMgZnVsZmlsbGVkLCB0aGUge0Bjb2RlIG9uRnVsZmlsbGVkfSBjYWxsYmFjayB3aWxsIGJlXG4gKiBpbnZva2VkIHdpdGggdGhlIGZ1bGZpbGxtZW50IHZhbHVlIGFzIGFyZ3VtZW50LCBhbmQgdGhlIGNoaWxkIFByb21pc2Ugd2lsbFxuICogYmUgZnVsZmlsbGVkIHdpdGggdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgY2FsbGJhY2suIElmIHRoZSBjYWxsYmFjayB0aHJvd3NcbiAqIGFuIGV4Y2VwdGlvbiwgdGhlIGNoaWxkIFByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSB0aHJvd24gdmFsdWVcbiAqIGluc3RlYWQuXG4gKlxuICogSWYgdGhlIFRoZW5hYmxlIGlzIHJlamVjdGVkLCB0aGUge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrIHdpbGwgYmUgaW52b2tlZFxuICogd2l0aCB0aGUgcmVqZWN0aW9uIHJlYXNvbiBhcyBhcmd1bWVudCwgYW5kIHRoZSBjaGlsZCBQcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWRcbiAqIHdpdGggdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgY2FsbGJhY2sgb3IgdGhyb3duIHZhbHVlLlxuICpcbiAqIEBwYXJhbSB7PyhmdW5jdGlvbih0aGlzOlRISVMsIFRZUEUpOlxuICogICAgICAgICAgICAgKFJFU1VMVHxJVGhlbmFibGUuPFJFU1VMVD58VGhlbmFibGUpKT19IG9wdF9vbkZ1bGZpbGxlZCBBXG4gKiAgICAgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGludm9rZWQgd2l0aCB0aGUgZnVsZmlsbG1lbnQgdmFsdWUgaWYgdGhlIFByb21pc2VcbiAqICAgICBpcyBmdWxsZmlsbGVkLlxuICogQHBhcmFtIHs/KGZ1bmN0aW9uKCopOiAqKT19IG9wdF9vblJlamVjdGVkIEEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGludm9rZWRcbiAqICAgICB3aXRoIHRoZSByZWplY3Rpb24gcmVhc29uIGlmIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLlxuICogQHBhcmFtIHtUSElTPX0gb3B0X2NvbnRleHQgQW4gb3B0aW9uYWwgY29udGV4dCBvYmplY3QgdGhhdCB3aWxsIGJlIHRoZVxuICogICAgIGV4ZWN1dGlvbiBjb250ZXh0IGZvciB0aGUgY2FsbGJhY2tzLiBCeSBkZWZhdWx0LCBmdW5jdGlvbnMgYXJlIGV4ZWN1dGVkXG4gKiAgICAgd2l0aCB0aGUgZGVmYXVsdCB0aGlzLlxuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZS48UkVTVUxUPn0gQSBuZXcgUHJvbWlzZSB0aGF0IHdpbGwgcmVjZWl2ZSB0aGVcbiAqICAgICByZXN1bHQgb2YgdGhlIGZ1bGZpbGxtZW50IG9yIHJlamVjdGlvbiBjYWxsYmFjay5cbiAqIEB0ZW1wbGF0ZSBSRVNVTFQsVEhJU1xuICovXG5UaGVuYWJsZS5wcm90b3R5cGUudGhlbiA9IGZ1bmN0aW9uKCkge307XG5cblxuLyoqXG4gKiBBbiBleHBhbmRvIHByb3BlcnR5IHRvIGluZGljYXRlIHRoYXQgYW4gb2JqZWN0IGltcGxlbWVudHNcbiAqIHtAY29kZSBUaGVuYWJsZX0uXG4gKlxuICoge0BzZWUgYWRkSW1wbGVtZW50YXRpb259LlxuICpcbiAqIEBjb25zdFxuICovXG5UaGVuYWJsZS5JTVBMRU1FTlRFRF9CWV9QUk9QID0gJyRnb29nX1RoZW5hYmxlJztcblxuXG4vKipcbiAqIE1hcmtzIGEgZ2l2ZW4gY2xhc3MgKGNvbnN0cnVjdG9yKSBhcyBhbiBpbXBsZW1lbnRhdGlvbiBvZiBUaGVuYWJsZSwgc29cbiAqIHRoYXQgd2UgY2FuIHF1ZXJ5IHRoYXQgZmFjdCBhdCBydW50aW1lLiBUaGUgY2xhc3MgbXVzdCBoYXZlIGFscmVhZHlcbiAqIGltcGxlbWVudGVkIHRoZSBpbnRlcmZhY2UuXG4gKiBFeHBvcnRzIGEgJ3RoZW4nIG1ldGhvZCBvbiB0aGUgY29uc3RydWN0b3IgcHJvdG90eXBlLCBzbyB0aGF0IHRoZSBvYmplY3RzXG4gKiBhbHNvIGltcGxlbWVudCB0aGUgZXh0ZXJuIHtAc2VlIFRoZW5hYmxlfSBpbnRlcmZhY2UgZm9yIGludGVyb3Agd2l0aFxuICogb3RoZXIgUHJvbWlzZSBpbXBsZW1lbnRhdGlvbnMuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKG5ldzpUaGVuYWJsZSwuLi5bP10pfSBjdG9yIFRoZSBjbGFzcyBjb25zdHJ1Y3Rvci4gVGhlXG4gKiAgICAgY29ycmVzcG9uZGluZyBjbGFzcyBtdXN0IGhhdmUgYWxyZWFkeSBpbXBsZW1lbnRlZCB0aGUgaW50ZXJmYWNlLlxuICovXG5UaGVuYWJsZS5hZGRJbXBsZW1lbnRhdGlvbiA9IGZ1bmN0aW9uKGN0b3IpIHtcbiAgY3Rvci5wcm90b3R5cGUudGhlbiA9IGN0b3IucHJvdG90eXBlLnRoZW47XG4gIGN0b3IucHJvdG90eXBlLiRnb29nX1RoZW5hYmxlID0gdHJ1ZTtcbn07XG5cblxuLyoqXG4gKiBAcGFyYW0geyp9IG9iamVjdFxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciBhIGdpdmVuIGluc3RhbmNlIGltcGxlbWVudHMge0Bjb2RlIFRoZW5hYmxlfS5cbiAqICAgICBUaGUgY2xhc3Mvc3VwZXJjbGFzcyBvZiB0aGUgaW5zdGFuY2UgbXVzdCBjYWxsIHtAY29kZSBhZGRJbXBsZW1lbnRhdGlvbn0uXG4gKi9cblRoZW5hYmxlLmlzSW1wbGVtZW50ZWRCeSA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICBpZiAoIW9iamVjdCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICB0cnkge1xuICAgIHJldHVybiAhIW9iamVjdC4kZ29vZ19UaGVuYWJsZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIFByb3BlcnR5IGFjY2VzcyBzZWVtcyB0byBiZSBmb3JiaWRkZW4uXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5cbi8qKlxuICogTGlrZSBiaW5kKCksIGV4Y2VwdCB0aGF0IGEgJ3RoaXMgb2JqZWN0JyBpcyBub3QgcmVxdWlyZWQuIFVzZWZ1bCB3aGVuIHRoZVxuICogdGFyZ2V0IGZ1bmN0aW9uIGlzIGFscmVhZHkgYm91bmQuXG4gKlxuICogVXNhZ2U6XG4gKiB2YXIgZyA9IHBhcnRpYWwoZiwgYXJnMSwgYXJnMik7XG4gKiBnKGFyZzMsIGFyZzQpO1xuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEEgZnVuY3Rpb24gdG8gcGFydGlhbGx5IGFwcGx5LlxuICogQHBhcmFtIHsuLi4qfSB2YXJfYXJncyBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0aGF0IGFyZSBwYXJ0aWFsbHkgYXBwbGllZCB0byBmbi5cbiAqIEByZXR1cm4geyFGdW5jdGlvbn0gQSBwYXJ0aWFsbHktYXBwbGllZCBmb3JtIG9mIHRoZSBmdW5jdGlvbiBiaW5kKCkgd2FzXG4gKiAgICAgaW52b2tlZCBhcyBhIG1ldGhvZCBvZi5cbiAqL1xudmFyIHBhcnRpYWwgPSBmdW5jdGlvbihmbikge1xuICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAvLyBDbG9uZSB0aGUgYXJyYXkgKHdpdGggc2xpY2UoKSkgYW5kIGFwcGVuZCBhZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgIC8vIHRvIHRoZSBleGlzdGluZyBhcmd1bWVudHMuXG4gICAgdmFyIG5ld0FyZ3MgPSBhcmdzLnNsaWNlKCk7XG4gICAgbmV3QXJncy5wdXNoLmFwcGx5KG5ld0FyZ3MsIGFyZ3VtZW50cyk7XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIG5ld0FyZ3MpO1xuICB9O1xufTtcblxuLyoqXG4gKiBQcm9taXNlcyBwcm92aWRlIGEgcmVzdWx0IHRoYXQgbWF5IGJlIHJlc29sdmVkIGFzeW5jaHJvbm91c2x5LiBBIFByb21pc2UgbWF5XG4gKiBiZSByZXNvbHZlZCBieSBiZWluZyBmdWxmaWxsZWQgb3IgcmVqZWN0ZWQgd2l0aCBhIHZhbHVlLCB3aGljaCB3aWxsIGJlIGtub3duXG4gKiBhcyB0aGUgZnVsZmlsbG1lbnQgdmFsdWUgb3IgdGhlIHJlamVjdGlvbiByZWFzb24uIFdoZXRoZXIgZnVsZmlsbGVkIG9yXG4gKiByZWplY3RlZCwgdGhlIFByb21pc2UgcmVzdWx0IGlzIGltbXV0YWJsZSBvbmNlIGl0IGlzIHNldC5cbiAqXG4gKiBQcm9taXNlcyBtYXkgcmVwcmVzZW50IHJlc3VsdHMgb2YgYW55IHR5cGUsIGluY2x1ZGluZyB1bmRlZmluZWQuIFJlamVjdGlvblxuICogcmVhc29ucyBhcmUgdHlwaWNhbGx5IEVycm9ycywgYnV0IG1heSBhbHNvIGJlIG9mIGFueSB0eXBlLiBDbG9zdXJlIFByb21pc2VzXG4gKiBhbGxvdyBmb3Igb3B0aW9uYWwgdHlwZSBhbm5vdGF0aW9ucyB0aGF0IGVuZm9yY2UgdGhhdCBmdWxmaWxsbWVudCB2YWx1ZXMgYXJlXG4gKiBvZiB0aGUgYXBwcm9wcmlhdGUgdHlwZXMgYXQgY29tcGlsZSB0aW1lLlxuICpcbiAqIFRoZSByZXN1bHQgb2YgYSBQcm9taXNlIGlzIGFjY2Vzc2libGUgYnkgY2FsbGluZyB7QGNvZGUgdGhlbn0gYW5kIHJlZ2lzdGVyaW5nXG4gKiB7QGNvZGUgb25GdWxmaWxsZWR9IGFuZCB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2tzLiBPbmNlIHRoZSBQcm9taXNlXG4gKiByZXNvbHZlcywgdGhlIHJlbGV2YW50IGNhbGxiYWNrcyBhcmUgaW52b2tlZCB3aXRoIHRoZSBmdWxmaWxsbWVudCB2YWx1ZSBvclxuICogcmVqZWN0aW9uIHJlYXNvbiBhcyBhcmd1bWVudC4gQ2FsbGJhY2tzIGFyZSBhbHdheXMgaW52b2tlZCBpbiB0aGUgb3JkZXIgdGhleVxuICogd2VyZSByZWdpc3RlcmVkLCBldmVuIHdoZW4gYWRkaXRpb25hbCB7QGNvZGUgdGhlbn0gY2FsbHMgYXJlIG1hZGUgZnJvbSBpbnNpZGVcbiAqIGFub3RoZXIgY2FsbGJhY2suIEEgY2FsbGJhY2sgaXMgYWx3YXlzIHJ1biBhc3luY2hyb25vdXNseSBzb21ldGltZSBhZnRlciB0aGVcbiAqIHNjb3BlIGNvbnRhaW5pbmcgdGhlIHJlZ2lzdGVyaW5nIHtAY29kZSB0aGVufSBpbnZvY2F0aW9uIGhhcyByZXR1cm5lZC5cbiAqXG4gKiBJZiBhIFByb21pc2UgaXMgcmVzb2x2ZWQgd2l0aCBhbm90aGVyIFByb21pc2UsIHRoZSBmaXJzdCBQcm9taXNlIHdpbGwgYmxvY2tcbiAqIHVudGlsIHRoZSBzZWNvbmQgaXMgcmVzb2x2ZWQsIGFuZCB0aGVuIGFzc3VtZXMgdGhlIHNhbWUgcmVzdWx0IGFzIHRoZSBzZWNvbmRcbiAqIFByb21pc2UuIFRoaXMgYWxsb3dzIFByb21pc2VzIHRvIGRlcGVuZCBvbiB0aGUgcmVzdWx0cyBvZiBvdGhlciBQcm9taXNlcyxcbiAqIGxpbmtpbmcgdG9nZXRoZXIgbXVsdGlwbGUgYXN5bmNocm9ub3VzIG9wZXJhdGlvbnMuXG4gKlxuICogVGhpcyBpbXBsZW1lbnRhdGlvbiBpcyBjb21wYXRpYmxlIHdpdGggdGhlIFByb21pc2VzL0ErIHNwZWNpZmljYXRpb24gYW5kXG4gKiBwYXNzZXMgdGhhdCBzcGVjaWZpY2F0aW9uJ3MgY29uZm9ybWFuY2UgdGVzdCBzdWl0ZS4gQSBDbG9zdXJlIFByb21pc2UgbWF5IGJlXG4gKiByZXNvbHZlZCB3aXRoIGEgUHJvbWlzZSBpbnN0YW5jZSAob3Igc3VmZmljaWVudGx5IGNvbXBhdGlibGUgUHJvbWlzZS1saWtlXG4gKiBvYmplY3QpIGNyZWF0ZWQgYnkgb3RoZXIgUHJvbWlzZSBpbXBsZW1lbnRhdGlvbnMuIEZyb20gdGhlIHNwZWNpZmljYXRpb24sXG4gKiBQcm9taXNlLWxpa2Ugb2JqZWN0cyBhcmUga25vd24gYXMgXCJUaGVuYWJsZXNcIi5cbiAqXG4gKiBAc2VlIGh0dHA6Ly9wcm9taXNlc2FwbHVzLmNvbS9cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKFxuICogICAgICAgICAgICAgdGhpczpSRVNPTFZFUl9DT05URVhULFxuICogICAgICAgICAgICAgZnVuY3Rpb24oKFRZUEV8SVRoZW5hYmxlLjxUWVBFPnxUaGVuYWJsZSkpLFxuICogICAgICAgICAgICAgZnVuY3Rpb24oKikpOiB2b2lkfSByZXNvbHZlclxuICogICAgIEluaXRpYWxpemF0aW9uIGZ1bmN0aW9uIHRoYXQgaXMgaW52b2tlZCBpbW1lZGlhdGVseSB3aXRoIHtAY29kZSByZXNvbHZlfVxuICogICAgIGFuZCB7QGNvZGUgcmVqZWN0fSBmdW5jdGlvbnMgYXMgYXJndW1lbnRzLiBUaGUgUHJvbWlzZSBpcyByZXNvbHZlZCBvclxuICogICAgIHJlamVjdGVkIHdpdGggdGhlIGZpcnN0IGFyZ3VtZW50IHBhc3NlZCB0byBlaXRoZXIgZnVuY3Rpb24uXG4gKiBAcGFyYW0ge1JFU09MVkVSX0NPTlRFWFQ9fSBvcHRfY29udGV4dCBBbiBvcHRpb25hbCBjb250ZXh0IGZvciBleGVjdXRpbmcgdGhlXG4gKiAgICAgcmVzb2x2ZXIgZnVuY3Rpb24uIElmIHVuc3BlY2lmaWVkLCB0aGUgcmVzb2x2ZXIgZnVuY3Rpb24gd2lsbCBiZSBleGVjdXRlZFxuICogICAgIGluIHRoZSBkZWZhdWx0IHNjb3BlLlxuICogQGNvbnN0cnVjdG9yXG4gKiBAc3RydWN0XG4gKiBAZmluYWxcbiAqIEBpbXBsZW1lbnRzIHtUaGVuYWJsZS48VFlQRT59XG4gKiBAdGVtcGxhdGUgVFlQRSxSRVNPTFZFUl9DT05URVhUXG4gKi9cbnZhciBDYW5jZWxsYWJsZVByb21pc2UgPSBmdW5jdGlvbihyZXNvbHZlciwgb3B0X2NvbnRleHQpIHtcbiAgLyoqXG4gICAqIFRoZSBpbnRlcm5hbCBzdGF0ZSBvZiB0aGlzIFByb21pc2UuIEVpdGhlciBQRU5ESU5HLCBGVUxGSUxMRUQsIFJFSkVDVEVELCBvclxuICAgKiBCTE9DS0VELlxuICAgKiBAcHJpdmF0ZSB7Q2FuY2VsbGFibGVQcm9taXNlLlN0YXRlX31cbiAgICovXG4gIHRoaXMuc3RhdGVfID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5QRU5ESU5HO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVzb2x2ZWQgcmVzdWx0IG9mIHRoZSBQcm9taXNlLiBJbW11dGFibGUgb25jZSBzZXQgd2l0aCBlaXRoZXIgYVxuICAgKiBmdWxmaWxsbWVudCB2YWx1ZSBvciByZWplY3Rpb24gcmVhc29uLlxuICAgKiBAcHJpdmF0ZSB7Kn1cbiAgICovXG4gIHRoaXMucmVzdWx0XyA9IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogRm9yIFByb21pc2VzIGNyZWF0ZWQgYnkgY2FsbGluZyB7QGNvZGUgdGhlbigpfSwgdGhlIG9yaWdpbmF0aW5nIHBhcmVudC5cbiAgICogQHByaXZhdGUge0NhbmNlbGxhYmxlUHJvbWlzZX1cbiAgICovXG4gIHRoaXMucGFyZW50XyA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFRoZSBsaXN0IG9mIHtAY29kZSBvbkZ1bGZpbGxlZH0gYW5kIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFja3MgYWRkZWQgdG9cbiAgICogdGhpcyBQcm9taXNlIGJ5IGNhbGxzIHRvIHtAY29kZSB0aGVuKCl9LlxuICAgKiBAcHJpdmF0ZSB7QXJyYXkuPENhbmNlbGxhYmxlUHJvbWlzZS5DYWxsYmFja0VudHJ5Xz59XG4gICAqL1xuICB0aGlzLmNhbGxiYWNrRW50cmllc18gPSBudWxsO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBQcm9taXNlIGlzIGluIHRoZSBxdWV1ZSBvZiBQcm9taXNlcyB0byBleGVjdXRlLlxuICAgKiBAcHJpdmF0ZSB7Ym9vbGVhbn1cbiAgICovXG4gIHRoaXMuZXhlY3V0aW5nXyA9IGZhbHNlO1xuXG4gIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA+IDApIHtcbiAgICAvKipcbiAgICAgKiBBIHRpbWVvdXQgSUQgdXNlZCB3aGVuIHRoZSB7QGNvZGUgVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWX0gaXMgZ3JlYXRlclxuICAgICAqIHRoYW4gMCBtaWxsaXNlY29uZHMuIFRoZSBJRCBpcyBzZXQgd2hlbiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZCwgYW5kXG4gICAgICogY2xlYXJlZCBvbmx5IGlmIGFuIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFjayBpcyBpbnZva2VkIGZvciB0aGVcbiAgICAgKiBQcm9taXNlIChvciBvbmUgb2YgaXRzIGRlc2NlbmRhbnRzKSBiZWZvcmUgdGhlIGRlbGF5IGlzIGV4Y2VlZGVkLlxuICAgICAqXG4gICAgICogSWYgdGhlIHJlamVjdGlvbiBpcyBub3QgaGFuZGxlZCBiZWZvcmUgdGhlIHRpbWVvdXQgY29tcGxldGVzLCB0aGVcbiAgICAgKiByZWplY3Rpb24gcmVhc29uIGlzIHBhc3NlZCB0byB0aGUgdW5oYW5kbGVkIHJlamVjdGlvbiBoYW5kbGVyLlxuICAgICAqIEBwcml2YXRlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy51bmhhbmRsZWRSZWplY3Rpb25JZF8gPSAwO1xuICB9IGVsc2UgaWYgKENhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZID09PSAwKSB7XG4gICAgLyoqXG4gICAgICogV2hlbiB0aGUge0Bjb2RlIFVOSEFORExFRF9SRUpFQ1RJT05fREVMQVl9IGlzIHNldCB0byAwIG1pbGxpc2Vjb25kcywgYVxuICAgICAqIGJvb2xlYW4gdGhhdCBpcyBzZXQgaWYgdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQsIGFuZCByZXNldCB0byBmYWxzZSBpZiBhblxuICAgICAqIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFjayBpcyBpbnZva2VkIGZvciB0aGUgUHJvbWlzZSAob3Igb25lIG9mIGl0c1xuICAgICAqIGRlc2NlbmRhbnRzKS4gSWYgdGhlIHJlamVjdGlvbiBpcyBub3QgaGFuZGxlZCBiZWZvcmUgdGhlIG5leHQgdGltZXN0ZXAsXG4gICAgICogdGhlIHJlamVjdGlvbiByZWFzb24gaXMgcGFzc2VkIHRvIHRoZSB1bmhhbmRsZWQgcmVqZWN0aW9uIGhhbmRsZXIuXG4gICAgICogQHByaXZhdGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgdGhpcy5oYWRVbmhhbmRsZWRSZWplY3Rpb25fID0gZmFsc2U7XG4gIH1cblxuICB0cnkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICByZXNvbHZlci5jYWxsKFxuICAgICAgb3B0X2NvbnRleHQsIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHNlbGYucmVzb2x2ZV8oQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5GVUxGSUxMRUQsIHZhbHVlKTtcbiAgICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikge1xuICAgICAgICBzZWxmLnJlc29sdmVfKENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQsIHJlYXNvbik7XG4gICAgICB9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRoaXMucmVzb2x2ZV8oQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCwgZSk7XG4gIH1cbn07XG5cbi8qKlxuICogVGhlIGRlbGF5IGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgYSByZWplY3RlZCBQcm9taXNlJ3MgcmVhc29uIGlzIHBhc3NlZCB0b1xuICogdGhlIHJlamVjdGlvbiBoYW5kbGVyLiBCeSBkZWZhdWx0LCB0aGUgcmVqZWN0aW9uIGhhbmRsZXIgcmV0aHJvd3MgdGhlXG4gKiByZWplY3Rpb24gcmVhc29uIHNvIHRoYXQgaXQgYXBwZWFycyBpbiB0aGUgZGV2ZWxvcGVyIGNvbnNvbGUgb3JcbiAqIHtAY29kZSB3aW5kb3cub25lcnJvcn0gaGFuZGxlci5cbiAqIFJlamVjdGlvbnMgYXJlIHJldGhyb3duIGFzIHF1aWNrbHkgYXMgcG9zc2libGUgYnkgZGVmYXVsdC4gQSBuZWdhdGl2ZSB2YWx1ZVxuICogZGlzYWJsZXMgcmVqZWN0aW9uIGhhbmRsaW5nIGVudGlyZWx5LlxuICogQHR5cGUge251bWJlcn1cbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLlVOSEFORExFRF9SRUpFQ1RJT05fREVMQVkgPSAwO1xuXG5cbi8qKlxuICogVGhlIHBvc3NpYmxlIGludGVybmFsIHN0YXRlcyBmb3IgYSBQcm9taXNlLiBUaGVzZSBzdGF0ZXMgYXJlIG5vdCBkaXJlY3RseVxuICogb2JzZXJ2YWJsZSB0byBleHRlcm5hbCBjYWxsZXJzLlxuICogQGVudW0ge251bWJlcn1cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8gPSB7XG4gIC8qKiBUaGUgUHJvbWlzZSBpcyB3YWl0aW5nIGZvciByZXNvbHV0aW9uLiAqL1xuICBQRU5ESU5HOiAwLFxuXG4gIC8qKiBUaGUgUHJvbWlzZSBpcyBibG9ja2VkIHdhaXRpbmcgZm9yIHRoZSByZXN1bHQgb2YgYW5vdGhlciBUaGVuYWJsZS4gKi9cbiAgQkxPQ0tFRDogMSxcblxuICAvKiogVGhlIFByb21pc2UgaGFzIGJlZW4gcmVzb2x2ZWQgd2l0aCBhIGZ1bGZpbGxtZW50IHZhbHVlLiAqL1xuICBGVUxGSUxMRUQ6IDIsXG5cbiAgLyoqIFRoZSBQcm9taXNlIGhhcyBiZWVuIHJlc29sdmVkIHdpdGggYSByZWplY3Rpb24gcmVhc29uLiAqL1xuICBSRUpFQ1RFRDogM1xufTtcblxuXG4vKipcbiAqIFR5cGVkZWYgZm9yIGVudHJpZXMgaW4gdGhlIGNhbGxiYWNrIGNoYWluLiBFYWNoIGNhbGwgdG8ge0Bjb2RlIHRoZW59LFxuICoge0Bjb2RlIHRoZW5DYXRjaH0sIG9yIHtAY29kZSB0aGVuQWx3YXlzfSBjcmVhdGVzIGFuIGVudHJ5IGNvbnRhaW5pbmcgdGhlXG4gKiBmdW5jdGlvbnMgdGhhdCBtYXkgYmUgaW52b2tlZCBvbmNlIHRoZSBQcm9taXNlIGlzIHJlc29sdmVkLlxuICpcbiAqIEB0eXBlZGVmIHt7XG4gKiAgIGNoaWxkOiBDYW5jZWxsYWJsZVByb21pc2UsXG4gKiAgIG9uRnVsZmlsbGVkOiBmdW5jdGlvbigqKSxcbiAqICAgb25SZWplY3RlZDogZnVuY3Rpb24oKilcbiAqIH19XG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuQ2FsbGJhY2tFbnRyeV8gPSBudWxsO1xuXG5cbi8qKlxuICogQHBhcmFtIHsoVFlQRXxUaGVuYWJsZS48VFlQRT58VGhlbmFibGUpPX0gb3B0X3ZhbHVlXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlLjxUWVBFPn0gQSBuZXcgUHJvbWlzZSB0aGF0IGlzIGltbWVkaWF0ZWx5IHJlc29sdmVkXG4gKiAgICAgd2l0aCB0aGUgZ2l2ZW4gdmFsdWUuXG4gKiBAdGVtcGxhdGUgVFlQRVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSA9IGZ1bmN0aW9uKG9wdF92YWx1ZSkge1xuICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7XG4gICAgICByZXNvbHZlKG9wdF92YWx1ZSk7XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQHBhcmFtIHsqPX0gb3B0X3JlYXNvblxuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZX0gQSBuZXcgUHJvbWlzZSB0aGF0IGlzIGltbWVkaWF0ZWx5IHJlamVjdGVkIHdpdGggdGhlXG4gKiAgICAgZ2l2ZW4gcmVhc29uLlxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucmVqZWN0ID0gZnVuY3Rpb24ob3B0X3JlYXNvbikge1xuICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIHJlamVjdChvcHRfcmVhc29uKTtcbiAgICB9KTtcbn07XG5cblxuLyoqXG4gKiBAcGFyYW0geyFBcnJheS48IShUaGVuYWJsZS48VFlQRT58VGhlbmFibGUpPn0gcHJvbWlzZXNcbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2UuPFRZUEU+fSBBIFByb21pc2UgdGhhdCByZWNlaXZlcyB0aGUgcmVzdWx0IG9mIHRoZVxuICogICAgIGZpcnN0IFByb21pc2UgKG9yIFByb21pc2UtbGlrZSkgaW5wdXQgdG8gY29tcGxldGUuXG4gKiBAdGVtcGxhdGUgVFlQRVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucmFjZSA9IGZ1bmN0aW9uKHByb21pc2VzKSB7XG4gIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgaWYgKCFwcm9taXNlcy5sZW5ndGgpIHtcbiAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIgaSA9IDAsIHByb21pc2U7IChwcm9taXNlID0gcHJvbWlzZXNbaV0pOyBpKyspIHtcbiAgICAgICAgcHJvbWlzZS50aGVuKHJlc29sdmUsIHJlamVjdCk7XG4gICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQHBhcmFtIHshQXJyYXkuPCEoVGhlbmFibGUuPFRZUEU+fFRoZW5hYmxlKT59IHByb21pc2VzXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlLjwhQXJyYXkuPFRZUEU+Pn0gQSBQcm9taXNlIHRoYXQgcmVjZWl2ZXMgYSBsaXN0IG9mXG4gKiAgICAgZXZlcnkgZnVsZmlsbGVkIHZhbHVlIG9uY2UgZXZlcnkgaW5wdXQgUHJvbWlzZSAob3IgUHJvbWlzZS1saWtlKSBpc1xuICogICAgIHN1Y2Nlc3NmdWxseSBmdWxmaWxsZWQsIG9yIGlzIHJlamVjdGVkIGJ5IHRoZSBmaXJzdCByZWplY3Rpb24gcmVzdWx0LlxuICogQHRlbXBsYXRlIFRZUEVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLmFsbCA9IGZ1bmN0aW9uKHByb21pc2VzKSB7XG4gIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdmFyIHRvRnVsZmlsbCA9IHByb21pc2VzLmxlbmd0aDtcbiAgICAgIHZhciB2YWx1ZXMgPSBbXTtcblxuICAgICAgaWYgKCF0b0Z1bGZpbGwpIHtcbiAgICAgICAgcmVzb2x2ZSh2YWx1ZXMpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBvbkZ1bGZpbGwgPSBmdW5jdGlvbihpbmRleCwgdmFsdWUpIHtcbiAgICAgICAgdG9GdWxmaWxsLS07XG4gICAgICAgIHZhbHVlc1tpbmRleF0gPSB2YWx1ZTtcbiAgICAgICAgaWYgKHRvRnVsZmlsbCA9PT0gMCkge1xuICAgICAgICAgIHJlc29sdmUodmFsdWVzKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgdmFyIG9uUmVqZWN0ID0gZnVuY3Rpb24ocmVhc29uKSB7XG4gICAgICAgIHJlamVjdChyZWFzb24pO1xuICAgICAgfTtcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIHByb21pc2U7IChwcm9taXNlID0gcHJvbWlzZXNbaV0pOyBpKyspIHtcbiAgICAgICAgcHJvbWlzZS50aGVuKHBhcnRpYWwob25GdWxmaWxsLCBpKSwgb25SZWplY3QpO1xuICAgICAgfVxuICAgIH0pO1xufTtcblxuXG4vKipcbiAqIEBwYXJhbSB7IUFycmF5LjwhKFRoZW5hYmxlLjxUWVBFPnxUaGVuYWJsZSk+fSBwcm9taXNlc1xuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZS48VFlQRT59IEEgUHJvbWlzZSB0aGF0IHJlY2VpdmVzIHRoZSB2YWx1ZSBvZlxuICogICAgIHRoZSBmaXJzdCBpbnB1dCB0byBiZSBmdWxmaWxsZWQsIG9yIGlzIHJlamVjdGVkIHdpdGggYSBsaXN0IG9mIGV2ZXJ5XG4gKiAgICAgcmVqZWN0aW9uIHJlYXNvbiBpZiBhbGwgaW5wdXRzIGFyZSByZWplY3RlZC5cbiAqIEB0ZW1wbGF0ZSBUWVBFXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5maXJzdEZ1bGZpbGxlZCA9IGZ1bmN0aW9uKHByb21pc2VzKSB7XG4gIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdmFyIHRvUmVqZWN0ID0gcHJvbWlzZXMubGVuZ3RoO1xuICAgICAgdmFyIHJlYXNvbnMgPSBbXTtcblxuICAgICAgaWYgKCF0b1JlamVjdCkge1xuICAgICAgICByZXNvbHZlKHVuZGVmaW5lZCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIG9uRnVsZmlsbCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJlc29sdmUodmFsdWUpO1xuICAgICAgfTtcblxuICAgICAgdmFyIG9uUmVqZWN0ID0gZnVuY3Rpb24oaW5kZXgsIHJlYXNvbikge1xuICAgICAgICB0b1JlamVjdC0tO1xuICAgICAgICByZWFzb25zW2luZGV4XSA9IHJlYXNvbjtcbiAgICAgICAgaWYgKHRvUmVqZWN0ID09PSAwKSB7XG4gICAgICAgICAgcmVqZWN0KHJlYXNvbnMpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBmb3IgKHZhciBpID0gMCwgcHJvbWlzZTsgKHByb21pc2UgPSBwcm9taXNlc1tpXSk7IGkrKykge1xuICAgICAgICBwcm9taXNlLnRoZW4ob25GdWxmaWxsLCBwYXJ0aWFsKG9uUmVqZWN0LCBpKSk7XG4gICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQWRkcyBjYWxsYmFja3MgdGhhdCB3aWxsIG9wZXJhdGUgb24gdGhlIHJlc3VsdCBvZiB0aGUgUHJvbWlzZSwgcmV0dXJuaW5nIGFcbiAqIG5ldyBjaGlsZCBQcm9taXNlLlxuICpcbiAqIElmIHRoZSBQcm9taXNlIGlzIGZ1bGZpbGxlZCwgdGhlIHtAY29kZSBvbkZ1bGZpbGxlZH0gY2FsbGJhY2sgd2lsbCBiZSBpbnZva2VkXG4gKiB3aXRoIHRoZSBmdWxmaWxsbWVudCB2YWx1ZSBhcyBhcmd1bWVudCwgYW5kIHRoZSBjaGlsZCBQcm9taXNlIHdpbGwgYmVcbiAqIGZ1bGZpbGxlZCB3aXRoIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGNhbGxiYWNrLiBJZiB0aGUgY2FsbGJhY2sgdGhyb3dzIGFuXG4gKiBleGNlcHRpb24sIHRoZSBjaGlsZCBQcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWQgd2l0aCB0aGUgdGhyb3duIHZhbHVlIGluc3RlYWQuXG4gKlxuICogSWYgdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQsIHRoZSB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2sgd2lsbCBiZSBpbnZva2VkXG4gKiB3aXRoIHRoZSByZWplY3Rpb24gcmVhc29uIGFzIGFyZ3VtZW50LCBhbmQgdGhlIGNoaWxkIFByb21pc2Ugd2lsbCBiZSByZWplY3RlZFxuICogd2l0aCB0aGUgcmV0dXJuIHZhbHVlIChvciB0aHJvd24gdmFsdWUpIG9mIHRoZSBjYWxsYmFjay5cbiAqXG4gKiBAb3ZlcnJpZGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS50aGVuID0gZnVuY3Rpb24ob3B0X29uRnVsZmlsbGVkLCBvcHRfb25SZWplY3RlZCwgb3B0X2NvbnRleHQpIHtcbiAgcmV0dXJuIHRoaXMuYWRkQ2hpbGRQcm9taXNlXyhcbiAgICBpc0Z1bmN0aW9uKG9wdF9vbkZ1bGZpbGxlZCkgPyBvcHRfb25GdWxmaWxsZWQgOiBudWxsLFxuICAgIGlzRnVuY3Rpb24ob3B0X29uUmVqZWN0ZWQpID8gb3B0X29uUmVqZWN0ZWQgOiBudWxsLFxuICAgIG9wdF9jb250ZXh0KTtcbn07XG5UaGVuYWJsZS5hZGRJbXBsZW1lbnRhdGlvbihDYW5jZWxsYWJsZVByb21pc2UpO1xuXG5cbi8qKlxuICogQWRkcyBhIGNhbGxiYWNrIHRoYXQgd2lsbCBiZSBpbnZva2VkIHdoZXRoZXIgdGhlIFByb21pc2UgaXMgZnVsZmlsbGVkIG9yXG4gKiByZWplY3RlZC4gVGhlIGNhbGxiYWNrIHJlY2VpdmVzIG5vIGFyZ3VtZW50LCBhbmQgbm8gbmV3IGNoaWxkIFByb21pc2UgaXNcbiAqIGNyZWF0ZWQuIFRoaXMgaXMgdXNlZnVsIGZvciBlbnN1cmluZyB0aGF0IGNsZWFudXAgdGFrZXMgcGxhY2UgYWZ0ZXIgY2VydGFpblxuICogYXN5bmNocm9ub3VzIG9wZXJhdGlvbnMuIENhbGxiYWNrcyBhZGRlZCB3aXRoIHtAY29kZSB0aGVuQWx3YXlzfSB3aWxsIGJlXG4gKiBleGVjdXRlZCBpbiB0aGUgc2FtZSBvcmRlciB3aXRoIG90aGVyIGNhbGxzIHRvIHtAY29kZSB0aGVufSxcbiAqIHtAY29kZSB0aGVuQWx3YXlzfSwgb3Ige0Bjb2RlIHRoZW5DYXRjaH0uXG4gKlxuICogU2luY2UgaXQgZG9lcyBub3QgcHJvZHVjZSBhIG5ldyBjaGlsZCBQcm9taXNlLCBjYW5jZWxsYXRpb24gcHJvcGFnYXRpb24gaXNcbiAqIG5vdCBwcmV2ZW50ZWQgYnkgYWRkaW5nIGNhbGxiYWNrcyB3aXRoIHtAY29kZSB0aGVuQWx3YXlzfS4gQSBQcm9taXNlIHRoYXQgaGFzXG4gKiBhIGNsZWFudXAgaGFuZGxlciBhZGRlZCB3aXRoIHtAY29kZSB0aGVuQWx3YXlzfSB3aWxsIGJlIGNhbmNlbGVkIGlmIGFsbCBvZlxuICogaXRzIGNoaWxkcmVuIGNyZWF0ZWQgYnkge0Bjb2RlIHRoZW59IChvciB7QGNvZGUgdGhlbkNhdGNofSkgYXJlIGNhbmNlbGVkLlxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb24odGhpczpUSElTKTogdm9pZH0gb25SZXNvbHZlZCBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBpbnZva2VkXG4gKiAgICAgd2hlbiB0aGUgUHJvbWlzZSBpcyByZXNvbHZlZC5cbiAqIEBwYXJhbSB7VEhJUz19IG9wdF9jb250ZXh0IEFuIG9wdGlvbmFsIGNvbnRleHQgb2JqZWN0IHRoYXQgd2lsbCBiZSB0aGVcbiAqICAgICBleGVjdXRpb24gY29udGV4dCBmb3IgdGhlIGNhbGxiYWNrcy4gQnkgZGVmYXVsdCwgZnVuY3Rpb25zIGFyZSBleGVjdXRlZFxuICogICAgIGluIHRoZSBnbG9iYWwgc2NvcGUuXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlLjxUWVBFPn0gVGhpcyBQcm9taXNlLCBmb3IgY2hhaW5pbmcgYWRkaXRpb25hbCBjYWxscy5cbiAqIEB0ZW1wbGF0ZSBUSElTXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudGhlbkFsd2F5cyA9IGZ1bmN0aW9uKG9uUmVzb2x2ZWQsIG9wdF9jb250ZXh0KSB7XG4gIHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuICAgIHRyeSB7XG4gICAgICAvLyBFbnN1cmUgdGhhdCBubyBhcmd1bWVudHMgYXJlIHBhc3NlZCB0byBvblJlc29sdmVkLlxuICAgICAgb25SZXNvbHZlZC5jYWxsKG9wdF9jb250ZXh0KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIENhbmNlbGxhYmxlUHJvbWlzZS5oYW5kbGVSZWplY3Rpb25fLmNhbGwobnVsbCwgZXJyKTtcbiAgICB9XG4gIH07XG5cbiAgdGhpcy5hZGRDYWxsYmFja0VudHJ5Xyh7XG4gICAgY2hpbGQ6IG51bGwsXG4gICAgb25SZWplY3RlZDogY2FsbGJhY2ssXG4gICAgb25GdWxmaWxsZWQ6IGNhbGxiYWNrXG4gIH0pO1xuICByZXR1cm4gdGhpcztcbn07XG5cblxuLyoqXG4gKiBBZGRzIGEgY2FsbGJhY2sgdGhhdCB3aWxsIGJlIGludm9rZWQgb25seSBpZiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZC4gVGhpc1xuICogaXMgZXF1aXZhbGVudCB0byB7QGNvZGUgdGhlbihudWxsLCBvblJlamVjdGVkKX0uXG4gKlxuICogQHBhcmFtIHshZnVuY3Rpb24odGhpczpUSElTLCAqKTogKn0gb25SZWplY3RlZCBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZVxuICogICAgIGludm9rZWQgd2l0aCB0aGUgcmVqZWN0aW9uIHJlYXNvbiBpZiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZC5cbiAqIEBwYXJhbSB7VEhJUz19IG9wdF9jb250ZXh0IEFuIG9wdGlvbmFsIGNvbnRleHQgb2JqZWN0IHRoYXQgd2lsbCBiZSB0aGVcbiAqICAgICBleGVjdXRpb24gY29udGV4dCBmb3IgdGhlIGNhbGxiYWNrcy4gQnkgZGVmYXVsdCwgZnVuY3Rpb25zIGFyZSBleGVjdXRlZFxuICogICAgIGluIHRoZSBnbG9iYWwgc2NvcGUuXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlfSBBIG5ldyBQcm9taXNlIHRoYXQgd2lsbCByZWNlaXZlIHRoZSByZXN1bHQgb2YgdGhlXG4gKiAgICAgY2FsbGJhY2suXG4gKiBAdGVtcGxhdGUgVEhJU1xuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnRoZW5DYXRjaCA9IGZ1bmN0aW9uKG9uUmVqZWN0ZWQsIG9wdF9jb250ZXh0KSB7XG4gIHJldHVybiB0aGlzLmFkZENoaWxkUHJvbWlzZV8obnVsbCwgb25SZWplY3RlZCwgb3B0X2NvbnRleHQpO1xufTtcblxuLyoqXG4gKiBBbGlhcyBvZiB7QGxpbmsgQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS50aGVuQ2F0Y2h9XG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuY2F0Y2ggPSBDYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnRoZW5DYXRjaDtcblxuXG4vKipcbiAqIENhbmNlbHMgdGhlIFByb21pc2UgaWYgaXQgaXMgc3RpbGwgcGVuZGluZyBieSByZWplY3RpbmcgaXQgd2l0aCBhIGNhbmNlbFxuICogRXJyb3IuIE5vIGFjdGlvbiBpcyBwZXJmb3JtZWQgaWYgdGhlIFByb21pc2UgaXMgYWxyZWFkeSByZXNvbHZlZC5cbiAqXG4gKiBBbGwgY2hpbGQgUHJvbWlzZXMgb2YgdGhlIGNhbmNlbGVkIFByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSBzYW1lXG4gKiBjYW5jZWwgZXJyb3IsIGFzIHdpdGggbm9ybWFsIFByb21pc2UgcmVqZWN0aW9uLiBJZiB0aGUgUHJvbWlzZSB0byBiZSBjYW5jZWxlZFxuICogaXMgdGhlIG9ubHkgY2hpbGQgb2YgYSBwZW5kaW5nIFByb21pc2UsIHRoZSBwYXJlbnQgUHJvbWlzZSB3aWxsIGFsc28gYmVcbiAqIGNhbmNlbGVkLiBDYW5jZWxsYXRpb24gbWF5IHByb3BhZ2F0ZSB1cHdhcmQgdGhyb3VnaCBtdWx0aXBsZSBnZW5lcmF0aW9ucy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZz19IG9wdF9tZXNzYWdlIEFuIG9wdGlvbmFsIGRlYnVnZ2luZyBtZXNzYWdlIGZvciBkZXNjcmliaW5nIHRoZVxuICogICAgIGNhbmNlbGxhdGlvbiByZWFzb24uXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuY2FuY2VsID0gZnVuY3Rpb24ob3B0X21lc3NhZ2UpIHtcbiAgaWYgKHRoaXMuc3RhdGVfID09PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkcpIHtcbiAgICBhc3luYy5ydW4oZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgZXJyID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcihvcHRfbWVzc2FnZSk7XG4gICAgICBlcnIuSVNfQ0FOQ0VMTEFUSU9OX0VSUk9SID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2FuY2VsSW50ZXJuYWxfKGVycik7XG4gICAgfSwgdGhpcyk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBDYW5jZWxzIHRoaXMgUHJvbWlzZSB3aXRoIHRoZSBnaXZlbiBlcnJvci5cbiAqXG4gKiBAcGFyYW0geyFFcnJvcn0gZXJyIFRoZSBjYW5jZWxsYXRpb24gZXJyb3IuXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmNhbmNlbEludGVybmFsXyA9IGZ1bmN0aW9uKGVycikge1xuICBpZiAodGhpcy5zdGF0ZV8gPT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORykge1xuICAgIGlmICh0aGlzLnBhcmVudF8pIHtcbiAgICAgIC8vIENhbmNlbCB0aGUgUHJvbWlzZSBhbmQgcmVtb3ZlIGl0IGZyb20gdGhlIHBhcmVudCdzIGNoaWxkIGxpc3QuXG4gICAgICB0aGlzLnBhcmVudF8uY2FuY2VsQ2hpbGRfKHRoaXMsIGVycik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVzb2x2ZV8oQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCwgZXJyKTtcbiAgICB9XG4gIH1cbn07XG5cblxuLyoqXG4gKiBDYW5jZWxzIGEgY2hpbGQgUHJvbWlzZSBmcm9tIHRoZSBsaXN0IG9mIGNhbGxiYWNrIGVudHJpZXMuIElmIHRoZSBQcm9taXNlIGhhc1xuICogbm90IGFscmVhZHkgYmVlbiByZXNvbHZlZCwgcmVqZWN0IGl0IHdpdGggYSBjYW5jZWwgZXJyb3IuIElmIHRoZXJlIGFyZSBub1xuICogb3RoZXIgY2hpbGRyZW4gaW4gdGhlIGxpc3Qgb2YgY2FsbGJhY2sgZW50cmllcywgcHJvcGFnYXRlIHRoZSBjYW5jZWxsYXRpb25cbiAqIGJ5IGNhbmNlbGluZyB0aGlzIFByb21pc2UgYXMgd2VsbC5cbiAqXG4gKiBAcGFyYW0geyFDYW5jZWxsYWJsZVByb21pc2V9IGNoaWxkUHJvbWlzZSBUaGUgUHJvbWlzZSB0byBjYW5jZWwuXG4gKiBAcGFyYW0geyFFcnJvcn0gZXJyIFRoZSBjYW5jZWwgZXJyb3IgdG8gdXNlIGZvciByZWplY3RpbmcgdGhlIFByb21pc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmNhbmNlbENoaWxkXyA9IGZ1bmN0aW9uKGNoaWxkUHJvbWlzZSwgZXJyKSB7XG4gIGlmICghdGhpcy5jYWxsYmFja0VudHJpZXNfKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBjaGlsZENvdW50ID0gMDtcbiAgdmFyIGNoaWxkSW5kZXggPSAtMTtcblxuICAvLyBGaW5kIHRoZSBjYWxsYmFjayBlbnRyeSBmb3IgdGhlIGNoaWxkUHJvbWlzZSwgYW5kIGNvdW50IHdoZXRoZXIgdGhlcmUgYXJlXG4gIC8vIGFkZGl0aW9uYWwgY2hpbGQgUHJvbWlzZXMuXG4gIGZvciAodmFyIGkgPSAwLCBlbnRyeTsgKGVudHJ5ID0gdGhpcy5jYWxsYmFja0VudHJpZXNfW2ldKTsgaSsrKSB7XG4gICAgdmFyIGNoaWxkID0gZW50cnkuY2hpbGQ7XG4gICAgaWYgKGNoaWxkKSB7XG4gICAgICBjaGlsZENvdW50Kys7XG4gICAgICBpZiAoY2hpbGQgPT09IGNoaWxkUHJvbWlzZSkge1xuICAgICAgICBjaGlsZEluZGV4ID0gaTtcbiAgICAgIH1cbiAgICAgIGlmIChjaGlsZEluZGV4ID49IDAgJiYgY2hpbGRDb3VudCA+IDEpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gSWYgdGhlIGNoaWxkIFByb21pc2Ugd2FzIHRoZSBvbmx5IGNoaWxkLCBjYW5jZWwgdGhpcyBQcm9taXNlIGFzIHdlbGwuXG4gIC8vIE90aGVyd2lzZSwgcmVqZWN0IG9ubHkgdGhlIGNoaWxkIFByb21pc2Ugd2l0aCB0aGUgY2FuY2VsIGVycm9yLlxuICBpZiAoY2hpbGRJbmRleCA+PSAwKSB7XG4gICAgaWYgKHRoaXMuc3RhdGVfID09PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkcgJiYgY2hpbGRDb3VudCA9PT0gMSkge1xuICAgICAgdGhpcy5jYW5jZWxJbnRlcm5hbF8oZXJyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGNhbGxiYWNrRW50cnkgPSB0aGlzLmNhbGxiYWNrRW50cmllc18uc3BsaWNlKGNoaWxkSW5kZXgsIDEpWzBdO1xuICAgICAgdGhpcy5leGVjdXRlQ2FsbGJhY2tfKFxuICAgICAgICBjYWxsYmFja0VudHJ5LCBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVELCBlcnIpO1xuICAgIH1cbiAgfVxufTtcblxuXG4vKipcbiAqIEFkZHMgYSBjYWxsYmFjayBlbnRyeSB0byB0aGUgY3VycmVudCBQcm9taXNlLCBhbmQgc2NoZWR1bGVzIGNhbGxiYWNrXG4gKiBleGVjdXRpb24gaWYgdGhlIFByb21pc2UgaGFzIGFscmVhZHkgYmVlbiByZXNvbHZlZC5cbiAqXG4gKiBAcGFyYW0ge0NhbmNlbGxhYmxlUHJvbWlzZS5DYWxsYmFja0VudHJ5X30gY2FsbGJhY2tFbnRyeSBSZWNvcmQgY29udGFpbmluZ1xuICogICAgIHtAY29kZSBvbkZ1bGZpbGxlZH0gYW5kIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFja3MgdG8gZXhlY3V0ZSBhZnRlclxuICogICAgIHRoZSBQcm9taXNlIGlzIHJlc29sdmVkLlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5hZGRDYWxsYmFja0VudHJ5XyA9IGZ1bmN0aW9uKGNhbGxiYWNrRW50cnkpIHtcbiAgaWYgKCghdGhpcy5jYWxsYmFja0VudHJpZXNfIHx8ICF0aGlzLmNhbGxiYWNrRW50cmllc18ubGVuZ3RoKSAmJlxuICAgICh0aGlzLnN0YXRlXyA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5GVUxGSUxMRUQgfHxcbiAgICB0aGlzLnN0YXRlXyA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCkpIHtcbiAgICB0aGlzLnNjaGVkdWxlQ2FsbGJhY2tzXygpO1xuICB9XG4gIGlmICghdGhpcy5jYWxsYmFja0VudHJpZXNfKSB7XG4gICAgdGhpcy5jYWxsYmFja0VudHJpZXNfID0gW107XG4gIH1cbiAgdGhpcy5jYWxsYmFja0VudHJpZXNfLnB1c2goY2FsbGJhY2tFbnRyeSk7XG59O1xuXG5cbi8qKlxuICogQ3JlYXRlcyBhIGNoaWxkIFByb21pc2UgYW5kIGFkZHMgaXQgdG8gdGhlIGNhbGxiYWNrIGVudHJ5IGxpc3QuIFRoZSByZXN1bHQgb2ZcbiAqIHRoZSBjaGlsZCBQcm9taXNlIGlzIGRldGVybWluZWQgYnkgdGhlIHN0YXRlIG9mIHRoZSBwYXJlbnQgUHJvbWlzZSBhbmQgdGhlXG4gKiByZXN1bHQgb2YgdGhlIHtAY29kZSBvbkZ1bGZpbGxlZH0gb3Ige0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrcyBhc1xuICogc3BlY2lmaWVkIGluIHRoZSBQcm9taXNlIHJlc29sdXRpb24gcHJvY2VkdXJlLlxuICpcbiAqIEBzZWUgaHR0cDovL3Byb21pc2VzYXBsdXMuY29tLyN0aGVfX21ldGhvZFxuICpcbiAqIEBwYXJhbSB7P2Z1bmN0aW9uKHRoaXM6VEhJUywgVFlQRSk6XG4gKiAgICAgICAgICAoUkVTVUxUfENhbmNlbGxhYmxlUHJvbWlzZS48UkVTVUxUPnxUaGVuYWJsZSl9IG9uRnVsZmlsbGVkIEEgY2FsbGJhY2sgdGhhdFxuICogICAgIHdpbGwgYmUgaW52b2tlZCBpZiB0aGUgUHJvbWlzZSBpcyBmdWxsZmlsbGVkLCBvciBudWxsLlxuICogQHBhcmFtIHs/ZnVuY3Rpb24odGhpczpUSElTLCAqKTogKn0gb25SZWplY3RlZCBBIGNhbGxiYWNrIHRoYXQgd2lsbCBiZVxuICogICAgIGludm9rZWQgaWYgdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQsIG9yIG51bGwuXG4gKiBAcGFyYW0ge1RISVM9fSBvcHRfY29udGV4dCBBbiBvcHRpb25hbCBleGVjdXRpb24gY29udGV4dCBmb3IgdGhlIGNhbGxiYWNrcy5cbiAqICAgICBpbiB0aGUgZGVmYXVsdCBjYWxsaW5nIGNvbnRleHQuXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlfSBUaGUgY2hpbGQgUHJvbWlzZS5cbiAqIEB0ZW1wbGF0ZSBSRVNVTFQsVEhJU1xuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5hZGRDaGlsZFByb21pc2VfID0gZnVuY3Rpb24oXG5vbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgb3B0X2NvbnRleHQpIHtcblxuICB2YXIgY2FsbGJhY2tFbnRyeSA9IHtcbiAgICBjaGlsZDogbnVsbCxcbiAgICBvbkZ1bGZpbGxlZDogbnVsbCxcbiAgICBvblJlamVjdGVkOiBudWxsXG4gIH07XG5cbiAgY2FsbGJhY2tFbnRyeS5jaGlsZCA9IG5ldyBDYW5jZWxsYWJsZVByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgLy8gSW52b2tlIG9uRnVsZmlsbGVkLCBvciByZXNvbHZlIHdpdGggdGhlIHBhcmVudCdzIHZhbHVlIGlmIGFic2VudC5cbiAgICBjYWxsYmFja0VudHJ5Lm9uRnVsZmlsbGVkID0gb25GdWxmaWxsZWQgPyBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG9uRnVsZmlsbGVkLmNhbGwob3B0X2NvbnRleHQsIHZhbHVlKTtcbiAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgfVxuICAgIH0gOiByZXNvbHZlO1xuXG4gICAgLy8gSW52b2tlIG9uUmVqZWN0ZWQsIG9yIHJlamVjdCB3aXRoIHRoZSBwYXJlbnQncyByZWFzb24gaWYgYWJzZW50LlxuICAgIGNhbGxiYWNrRW50cnkub25SZWplY3RlZCA9IG9uUmVqZWN0ZWQgPyBmdW5jdGlvbihyZWFzb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBvblJlamVjdGVkLmNhbGwob3B0X2NvbnRleHQsIHJlYXNvbik7XG4gICAgICAgIGlmICghaXNEZWYocmVzdWx0KSAmJiByZWFzb24uSVNfQ0FOQ0VMTEFUSU9OX0VSUk9SKSB7XG4gICAgICAgICAgLy8gUHJvcGFnYXRlIGNhbmNlbGxhdGlvbiB0byBjaGlsZHJlbiBpZiBubyBvdGhlciByZXN1bHQgaXMgcmV0dXJuZWQuXG4gICAgICAgICAgcmVqZWN0KHJlYXNvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9XG4gICAgfSA6IHJlamVjdDtcbiAgfSk7XG5cbiAgY2FsbGJhY2tFbnRyeS5jaGlsZC5wYXJlbnRfID0gdGhpcztcbiAgdGhpcy5hZGRDYWxsYmFja0VudHJ5XyhcbiAgICAvKiogQHR5cGUge0NhbmNlbGxhYmxlUHJvbWlzZS5DYWxsYmFja0VudHJ5X30gKi8gKGNhbGxiYWNrRW50cnkpKTtcbiAgcmV0dXJuIGNhbGxiYWNrRW50cnkuY2hpbGQ7XG59O1xuXG5cbi8qKlxuICogVW5ibG9ja3MgdGhlIFByb21pc2UgYW5kIGZ1bGZpbGxzIGl0IHdpdGggdGhlIGdpdmVuIHZhbHVlLlxuICpcbiAqIEBwYXJhbSB7VFlQRX0gdmFsdWVcbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudW5ibG9ja0FuZEZ1bGZpbGxfID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgaWYgKHRoaXMuc3RhdGVfICE9PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkJMT0NLRUQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbmNlbGxhYmxlUHJvbWlzZSBpcyBub3QgYmxvY2tlZC4nKTtcbiAgfVxuICB0aGlzLnN0YXRlXyA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORztcbiAgdGhpcy5yZXNvbHZlXyhDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkZVTEZJTExFRCwgdmFsdWUpO1xufTtcblxuXG4vKipcbiAqIFVuYmxvY2tzIHRoZSBQcm9taXNlIGFuZCByZWplY3RzIGl0IHdpdGggdGhlIGdpdmVuIHJlamVjdGlvbiByZWFzb24uXG4gKlxuICogQHBhcmFtIHsqfSByZWFzb25cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudW5ibG9ja0FuZFJlamVjdF8gPSBmdW5jdGlvbihyZWFzb24pIHtcbiAgaWYgKHRoaXMuc3RhdGVfICE9PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkJMT0NLRUQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbmNlbGxhYmxlUHJvbWlzZSBpcyBub3QgYmxvY2tlZC4nKTtcbiAgfVxuICB0aGlzLnN0YXRlXyA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORztcbiAgdGhpcy5yZXNvbHZlXyhDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVELCByZWFzb24pO1xufTtcblxuXG4vKipcbiAqIEF0dGVtcHRzIHRvIHJlc29sdmUgYSBQcm9taXNlIHdpdGggYSBnaXZlbiByZXNvbHV0aW9uIHN0YXRlIGFuZCB2YWx1ZS4gVGhpc1xuICogaXMgYSBuby1vcCBpZiB0aGUgZ2l2ZW4gUHJvbWlzZSBoYXMgYWxyZWFkeSBiZWVuIHJlc29sdmVkLlxuICpcbiAqIElmIHRoZSBnaXZlbiByZXN1bHQgaXMgYSBUaGVuYWJsZSAoc3VjaCBhcyBhbm90aGVyIFByb21pc2UpLCB0aGUgUHJvbWlzZSB3aWxsXG4gKiBiZSByZXNvbHZlZCB3aXRoIHRoZSBzYW1lIHN0YXRlIGFuZCByZXN1bHQgYXMgdGhlIFRoZW5hYmxlIG9uY2UgaXQgaXMgaXRzZWxmXG4gKiByZXNvbHZlZC5cbiAqXG4gKiBJZiB0aGUgZ2l2ZW4gcmVzdWx0IGlzIG5vdCBhIFRoZW5hYmxlLCB0aGUgUHJvbWlzZSB3aWxsIGJlIGZ1bGZpbGxlZCBvclxuICogcmVqZWN0ZWQgd2l0aCB0aGF0IHJlc3VsdCBiYXNlZCBvbiB0aGUgZ2l2ZW4gc3RhdGUuXG4gKlxuICogQHNlZSBodHRwOi8vcHJvbWlzZXNhcGx1cy5jb20vI3RoZV9wcm9taXNlX3Jlc29sdXRpb25fcHJvY2VkdXJlXG4gKlxuICogQHBhcmFtIHtDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVffSBzdGF0ZVxuICogQHBhcmFtIHsqfSB4IFRoZSByZXN1bHQgdG8gYXBwbHkgdG8gdGhlIFByb21pc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnJlc29sdmVfID0gZnVuY3Rpb24oc3RhdGUsIHgpIHtcbiAgaWYgKHRoaXMuc3RhdGVfICE9PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkcpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAodGhpcyA9PT0geCkge1xuICAgIHN0YXRlID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRDtcbiAgICB4ID0gbmV3IFR5cGVFcnJvcignQ2FuY2VsbGFibGVQcm9taXNlIGNhbm5vdCByZXNvbHZlIHRvIGl0c2VsZicpO1xuXG4gIH0gZWxzZSBpZiAoVGhlbmFibGUuaXNJbXBsZW1lbnRlZEJ5KHgpKSB7XG4gICAgeCA9IC8qKiBAdHlwZSB7IVRoZW5hYmxlfSAqLyAoeCk7XG4gICAgdGhpcy5zdGF0ZV8gPSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkJMT0NLRUQ7XG4gICAgeC50aGVuKHRoaXMudW5ibG9ja0FuZEZ1bGZpbGxfLCB0aGlzLnVuYmxvY2tBbmRSZWplY3RfLCB0aGlzKTtcbiAgICByZXR1cm47XG5cbiAgfSBlbHNlIGlmIChpc09iamVjdCh4KSkge1xuICAgIHRyeSB7XG4gICAgICB2YXIgdGhlbiA9IHgudGhlbjtcbiAgICAgIGlmIChpc0Z1bmN0aW9uKHRoZW4pKSB7XG4gICAgICAgIHRoaXMudHJ5VGhlbl8oeCwgdGhlbik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBzdGF0ZSA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQ7XG4gICAgICB4ID0gZTtcbiAgICB9XG4gIH1cblxuICB0aGlzLnJlc3VsdF8gPSB4O1xuICB0aGlzLnN0YXRlXyA9IHN0YXRlO1xuICB0aGlzLnNjaGVkdWxlQ2FsbGJhY2tzXygpO1xuXG4gIGlmIChzdGF0ZSA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCAmJiAheC5JU19DQU5DRUxMQVRJT05fRVJST1IpIHtcbiAgICBDYW5jZWxsYWJsZVByb21pc2UuYWRkVW5oYW5kbGVkUmVqZWN0aW9uXyh0aGlzLCB4KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEF0dGVtcHRzIHRvIGNhbGwgdGhlIHtAY29kZSB0aGVufSBtZXRob2Qgb24gYW4gb2JqZWN0IGluIHRoZSBob3BlcyB0aGF0IGl0IGlzXG4gKiBhIFByb21pc2UtY29tcGF0aWJsZSBpbnN0YW5jZS4gVGhpcyBhbGxvd3MgaW50ZXJvcGVyYXRpb24gYmV0d2VlbiBkaWZmZXJlbnRcbiAqIFByb21pc2UgaW1wbGVtZW50YXRpb25zLCBob3dldmVyIGEgbm9uLWNvbXBsaWFudCBvYmplY3QgbWF5IGNhdXNlIGEgUHJvbWlzZVxuICogdG8gaGFuZyBpbmRlZmluaXRlbHkuIElmIHRoZSB7QGNvZGUgdGhlbn0gbWV0aG9kIHRocm93cyBhbiBleGNlcHRpb24sIHRoZVxuICogZGVwZW5kZW50IFByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSB0aHJvd24gdmFsdWUuXG4gKlxuICogQHNlZSBodHRwOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTcwXG4gKlxuICogQHBhcmFtIHtUaGVuYWJsZX0gdGhlbmFibGUgQW4gb2JqZWN0IHdpdGggYSB7QGNvZGUgdGhlbn0gbWV0aG9kIHRoYXQgbWF5IGJlXG4gKiAgICAgY29tcGF0aWJsZSB3aXRoIHRoZSBQcm9taXNlL0ErIHNwZWNpZmljYXRpb24uXG4gKiBAcGFyYW0geyFGdW5jdGlvbn0gdGhlbiBUaGUge0Bjb2RlIHRoZW59IG1ldGhvZCBvZiB0aGUgVGhlbmFibGUgb2JqZWN0LlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS50cnlUaGVuXyA9IGZ1bmN0aW9uKHRoZW5hYmxlLCB0aGVuKSB7XG4gIHRoaXMuc3RhdGVfID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5CTE9DS0VEO1xuICB2YXIgcHJvbWlzZSA9IHRoaXM7XG4gIHZhciBjYWxsZWQgPSBmYWxzZTtcblxuICB2YXIgcmVzb2x2ZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgaWYgKCFjYWxsZWQpIHtcbiAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgICBwcm9taXNlLnVuYmxvY2tBbmRGdWxmaWxsXyh2YWx1ZSk7XG4gICAgfVxuICB9O1xuXG4gIHZhciByZWplY3QgPSBmdW5jdGlvbihyZWFzb24pIHtcbiAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgIHByb21pc2UudW5ibG9ja0FuZFJlamVjdF8ocmVhc29uKTtcbiAgICB9XG4gIH07XG5cbiAgdHJ5IHtcbiAgICB0aGVuLmNhbGwodGhlbmFibGUsIHJlc29sdmUsIHJlamVjdCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZWplY3QoZSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBFeGVjdXRlcyB0aGUgcGVuZGluZyBjYWxsYmFja3Mgb2YgYSByZXNvbHZlZCBQcm9taXNlIGFmdGVyIGEgdGltZW91dC5cbiAqXG4gKiBTZWN0aW9uIDIuMi40IG9mIHRoZSBQcm9taXNlcy9BKyBzcGVjaWZpY2F0aW9uIHJlcXVpcmVzIHRoYXQgUHJvbWlzZVxuICogY2FsbGJhY2tzIG11c3Qgb25seSBiZSBpbnZva2VkIGZyb20gYSBjYWxsIHN0YWNrIHRoYXQgb25seSBjb250YWlucyBQcm9taXNlXG4gKiBpbXBsZW1lbnRhdGlvbiBjb2RlLCB3aGljaCB3ZSBhY2NvbXBsaXNoIGJ5IGludm9raW5nIGNhbGxiYWNrIGV4ZWN1dGlvbiBhZnRlclxuICogYSB0aW1lb3V0LiBJZiB7QGNvZGUgc3RhcnRFeGVjdXRpb25ffSBpcyBjYWxsZWQgbXVsdGlwbGUgdGltZXMgZm9yIHRoZSBzYW1lXG4gKiBQcm9taXNlLCB0aGUgY2FsbGJhY2sgY2hhaW4gd2lsbCBiZSBldmFsdWF0ZWQgb25seSBvbmNlLiBBZGRpdGlvbmFsIGNhbGxiYWNrc1xuICogbWF5IGJlIGFkZGVkIGR1cmluZyB0aGUgZXZhbHVhdGlvbiBwaGFzZSwgYW5kIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIHNhbWVcbiAqIGV2ZW50IGxvb3AuXG4gKlxuICogQWxsIFByb21pc2VzIGFkZGVkIHRvIHRoZSB3YWl0aW5nIGxpc3QgZHVyaW5nIHRoZSBzYW1lIGJyb3dzZXIgZXZlbnQgbG9vcFxuICogd2lsbCBiZSBleGVjdXRlZCBpbiBvbmUgYmF0Y2ggdG8gYXZvaWQgdXNpbmcgYSBzZXBhcmF0ZSB0aW1lb3V0IHBlciBQcm9taXNlLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuc2NoZWR1bGVDYWxsYmFja3NfID0gZnVuY3Rpb24oKSB7XG4gIGlmICghdGhpcy5leGVjdXRpbmdfKSB7XG4gICAgdGhpcy5leGVjdXRpbmdfID0gdHJ1ZTtcbiAgICBhc3luYy5ydW4odGhpcy5leGVjdXRlQ2FsbGJhY2tzXywgdGhpcyk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBFeGVjdXRlcyBhbGwgcGVuZGluZyBjYWxsYmFja3MgZm9yIHRoaXMgUHJvbWlzZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmV4ZWN1dGVDYWxsYmFja3NfID0gZnVuY3Rpb24oKSB7XG4gIHdoaWxlICh0aGlzLmNhbGxiYWNrRW50cmllc18gJiYgdGhpcy5jYWxsYmFja0VudHJpZXNfLmxlbmd0aCkge1xuICAgIHZhciBlbnRyaWVzID0gdGhpcy5jYWxsYmFja0VudHJpZXNfO1xuICAgIHRoaXMuY2FsbGJhY2tFbnRyaWVzXyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbnRyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLmV4ZWN1dGVDYWxsYmFja18oZW50cmllc1tpXSwgdGhpcy5zdGF0ZV8sIHRoaXMucmVzdWx0Xyk7XG4gICAgfVxuICB9XG4gIHRoaXMuZXhlY3V0aW5nXyA9IGZhbHNlO1xufTtcblxuXG4vKipcbiAqIEV4ZWN1dGVzIGEgcGVuZGluZyBjYWxsYmFjayBmb3IgdGhpcyBQcm9taXNlLiBJbnZva2VzIGFuIHtAY29kZSBvbkZ1bGZpbGxlZH1cbiAqIG9yIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFjayBiYXNlZCBvbiB0aGUgcmVzb2x2ZWQgc3RhdGUgb2YgdGhlIFByb21pc2UuXG4gKlxuICogQHBhcmFtIHshQ2FuY2VsbGFibGVQcm9taXNlLkNhbGxiYWNrRW50cnlffSBjYWxsYmFja0VudHJ5IEFuIGVudHJ5IGNvbnRhaW5pbmcgdGhlXG4gKiAgICAgb25GdWxmaWxsZWQgYW5kL29yIG9uUmVqZWN0ZWQgY2FsbGJhY2tzIGZvciB0aGlzIHN0ZXAuXG4gKiBAcGFyYW0ge0NhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV99IHN0YXRlIFRoZSByZXNvbHV0aW9uIHN0YXR1cyBvZiB0aGUgUHJvbWlzZSxcbiAqICAgICBlaXRoZXIgRlVMRklMTEVEIG9yIFJFSkVDVEVELlxuICogQHBhcmFtIHsqfSByZXN1bHQgVGhlIHJlc29sdmVkIHJlc3VsdCBvZiB0aGUgUHJvbWlzZS5cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuZXhlY3V0ZUNhbGxiYWNrXyA9IGZ1bmN0aW9uKFxuY2FsbGJhY2tFbnRyeSwgc3RhdGUsIHJlc3VsdCkge1xuICBpZiAoc3RhdGUgPT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uRlVMRklMTEVEKSB7XG4gICAgY2FsbGJhY2tFbnRyeS5vbkZ1bGZpbGxlZChyZXN1bHQpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMucmVtb3ZlVW5oYW5kbGVkUmVqZWN0aW9uXygpO1xuICAgIGNhbGxiYWNrRW50cnkub25SZWplY3RlZChyZXN1bHQpO1xuICB9XG59O1xuXG5cbi8qKlxuICogTWFya3MgdGhpcyByZWplY3RlZCBQcm9taXNlIGFzIGhhdmluZyBiZWluZyBoYW5kbGVkLiBBbHNvIG1hcmtzIGFueSBwYXJlbnRcbiAqIFByb21pc2VzIGluIHRoZSByZWplY3RlZCBzdGF0ZSBhcyBoYW5kbGVkLiBUaGUgcmVqZWN0aW9uIGhhbmRsZXIgd2lsbCBub1xuICogbG9uZ2VyIGJlIGludm9rZWQgZm9yIHRoaXMgUHJvbWlzZSAoaWYgaXQgaGFzIG5vdCBiZWVuIGNhbGxlZCBhbHJlYWR5KS5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnJlbW92ZVVuaGFuZGxlZFJlamVjdGlvbl8gPSBmdW5jdGlvbigpIHtcbiAgdmFyIHA7XG4gIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA+IDApIHtcbiAgICBmb3IgKHAgPSB0aGlzOyBwICYmIHAudW5oYW5kbGVkUmVqZWN0aW9uSWRfOyBwID0gcC5wYXJlbnRfKSB7XG4gICAgICBjbGVhclRpbWVvdXQocC51bmhhbmRsZWRSZWplY3Rpb25JZF8pO1xuICAgICAgcC51bmhhbmRsZWRSZWplY3Rpb25JZF8gPSAwO1xuICAgIH1cbiAgfSBlbHNlIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA9PT0gMCkge1xuICAgIGZvciAocCA9IHRoaXM7IHAgJiYgcC5oYWRVbmhhbmRsZWRSZWplY3Rpb25fOyBwID0gcC5wYXJlbnRfKSB7XG4gICAgICBwLmhhZFVuaGFuZGxlZFJlamVjdGlvbl8gPSBmYWxzZTtcbiAgICB9XG4gIH1cbn07XG5cblxuLyoqXG4gKiBNYXJrcyB0aGlzIHJlamVjdGVkIFByb21pc2UgYXMgdW5oYW5kbGVkLiBJZiBubyB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2tcbiAqIGlzIGNhbGxlZCBmb3IgdGhpcyBQcm9taXNlIGJlZm9yZSB0aGUge0Bjb2RlIFVOSEFORExFRF9SRUpFQ1RJT05fREVMQVl9XG4gKiBleHBpcmVzLCB0aGUgcmVhc29uIHdpbGwgYmUgcGFzc2VkIHRvIHRoZSB1bmhhbmRsZWQgcmVqZWN0aW9uIGhhbmRsZXIuIFRoZVxuICogaGFuZGxlciB0eXBpY2FsbHkgcmV0aHJvd3MgdGhlIHJlamVjdGlvbiByZWFzb24gc28gdGhhdCBpdCBiZWNvbWVzIHZpc2libGUgaW5cbiAqIHRoZSBkZXZlbG9wZXIgY29uc29sZS5cbiAqXG4gKiBAcGFyYW0geyFDYW5jZWxsYWJsZVByb21pc2V9IHByb21pc2UgVGhlIHJlamVjdGVkIFByb21pc2UuXG4gKiBAcGFyYW0geyp9IHJlYXNvbiBUaGUgUHJvbWlzZSByZWplY3Rpb24gcmVhc29uLlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLmFkZFVuaGFuZGxlZFJlamVjdGlvbl8gPSBmdW5jdGlvbihwcm9taXNlLCByZWFzb24pIHtcbiAgaWYgKENhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZID4gMCkge1xuICAgIHByb21pc2UudW5oYW5kbGVkUmVqZWN0aW9uSWRfID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgIENhbmNlbGxhYmxlUHJvbWlzZS5oYW5kbGVSZWplY3Rpb25fLmNhbGwobnVsbCwgcmVhc29uKTtcbiAgICB9LCBDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSk7XG5cbiAgfSBlbHNlIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA9PT0gMCkge1xuICAgIHByb21pc2UuaGFkVW5oYW5kbGVkUmVqZWN0aW9uXyA9IHRydWU7XG4gICAgYXN5bmMucnVuKGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHByb21pc2UuaGFkVW5oYW5kbGVkUmVqZWN0aW9uXykge1xuICAgICAgICBDYW5jZWxsYWJsZVByb21pc2UuaGFuZGxlUmVqZWN0aW9uXy5jYWxsKG51bGwsIHJlYXNvbik7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBBIG1ldGhvZCB0aGF0IGlzIGludm9rZWQgd2l0aCB0aGUgcmVqZWN0aW9uIHJlYXNvbnMgZm9yIFByb21pc2VzIHRoYXQgYXJlXG4gKiByZWplY3RlZCBidXQgaGF2ZSBubyB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2tzIHJlZ2lzdGVyZWQgeWV0LlxuICogQHR5cGUge2Z1bmN0aW9uKCopfVxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLmhhbmRsZVJlamVjdGlvbl8gPSBhc3luYy50aHJvd0V4Y2VwdGlvbjtcblxuXG4vKipcbiAqIFNldHMgYSBoYW5kbGVyIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2l0aCByZWFzb25zIGZyb20gdW5oYW5kbGVkIHJlamVjdGVkXG4gKiBQcm9taXNlcy4gSWYgdGhlIHJlamVjdGVkIFByb21pc2UgKG9yIG9uZSBvZiBpdHMgZGVzY2VuZGFudHMpIGhhcyBhblxuICoge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrIHJlZ2lzdGVyZWQsIHRoZSByZWplY3Rpb24gd2lsbCBiZSBjb25zaWRlcmVkXG4gKiBoYW5kbGVkLCBhbmQgdGhlIHJlamVjdGlvbiBoYW5kbGVyIHdpbGwgbm90IGJlIGNhbGxlZC5cbiAqXG4gKiBCeSBkZWZhdWx0LCB1bmhhbmRsZWQgcmVqZWN0aW9ucyBhcmUgcmV0aHJvd24gc28gdGhhdCB0aGUgZXJyb3IgbWF5IGJlXG4gKiBjYXB0dXJlZCBieSB0aGUgZGV2ZWxvcGVyIGNvbnNvbGUgb3IgYSB7QGNvZGUgd2luZG93Lm9uZXJyb3J9IGhhbmRsZXIuXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbigqKX0gaGFuZGxlciBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2l0aCByZWFzb25zIGZyb21cbiAqICAgICByZWplY3RlZCBQcm9taXNlcy4gRGVmYXVsdHMgdG8ge0Bjb2RlIGFzeW5jLnRocm93RXhjZXB0aW9ufS5cbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnNldFVuaGFuZGxlZFJlamVjdGlvbkhhbmRsZXIgPSBmdW5jdGlvbihoYW5kbGVyKSB7XG4gIENhbmNlbGxhYmxlUHJvbWlzZS5oYW5kbGVSZWplY3Rpb25fID0gaGFuZGxlcjtcbn07XG5cblxuXG4vKipcbiAqIEVycm9yIHVzZWQgYXMgYSByZWplY3Rpb24gcmVhc29uIGZvciBjYW5jZWxlZCBQcm9taXNlcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZz19IG9wdF9tZXNzYWdlXG4gKiBAY29uc3RydWN0b3JcbiAqIEBleHRlbmRzIHtFcnJvcn1cbiAqIEBmaW5hbFxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuQ2FuY2VsbGF0aW9uRXJyb3IgPSBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3Iob3B0X21lc3NhZ2UpIHtcbiAgICAgc3VwZXIob3B0X21lc3NhZ2UpO1xuXG4gICAgIGlmIChvcHRfbWVzc2FnZSkge1xuICAgICAgIHRoaXMubWVzc2FnZSA9IG9wdF9tZXNzYWdlO1xuICAgICB9XG4gICB9XG59O1xuXG4vKiogQG92ZXJyaWRlICovXG5DYW5jZWxsYWJsZVByb21pc2UuQ2FuY2VsbGF0aW9uRXJyb3IucHJvdG90eXBlLm5hbWUgPSAnY2FuY2VsJztcblxuZXhwb3J0IHtDYW5jZWxsYWJsZVByb21pc2V9O1xuZXhwb3J0IGRlZmF1bHQgQ2FuY2VsbGFibGVQcm9taXNlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAgKiBEZWJvdW5jZXMgZnVuY3Rpb24gZXhlY3V0aW9uLlxuICAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGZuXG4gICogQHBhcmFtIHtudW1iZXJ9IGRlbGF5XG4gICogQHJldHVybiB7IWZ1bmN0aW9uKCl9XG4gICovXG5mdW5jdGlvbiBkZWJvdW5jZShmbiwgZGVsYXkpIHtcblx0cmV0dXJuIGZ1bmN0aW9uIGRlYm91bmNlZCgpIHtcblx0XHR2YXIgYXJncyA9IGFyZ3VtZW50cztcblx0XHRjYW5jZWxEZWJvdW5jZShkZWJvdW5jZWQpO1xuXHRcdGRlYm91bmNlZC5pZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRmbi5hcHBseShudWxsLCBhcmdzKTtcblx0XHR9LCBkZWxheSk7XG5cdH07XG59XG5cbi8qKlxuICogQ2FuY2VscyB0aGUgc2NoZWR1bGVkIGRlYm91bmNlZCBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gY2FuY2VsRGVib3VuY2UoZGVib3VuY2VkKSB7XG5cdGNsZWFyVGltZW91dChkZWJvdW5jZWQuaWQpO1xufVxuXG5leHBvcnQgZGVmYXVsdCBkZWJvdW5jZTtcbmV4cG9ydCB7IGNhbmNlbERlYm91bmNlLCBkZWJvdW5jZSB9O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgY29yZSBmcm9tICdtZXRhbCc7XG5cbmNvbnN0IFJFR0VYID0gLyhbXFwvXSk/KD86KD86XFw6KFxcdyspKD86XFwoKCg/OlxcXFwufFteXFxcXCgpXSkqKVxcKSk/fFxcKCgoPzpcXFxcLnxbXlxcXFwoKV0pKylcXCkpKFsrKj9dKT8pL2c7XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIGFycmF5IG9mIHJlZ2V4IG1hdGNoZXMgdG8gYSBtb3JlIHJlYWRhYmxlIG9iamVjdCBmb3JtYXQuXG4gKiBAcGFyYW0geyFBcnJheTxzdHJpbmc+fSBtYXRjaGVzXG4gKiBAcmV0dXJuIHshT2JqZWN0fVxuICovXG5mdW5jdGlvbiBjb252ZXJ0TWF0Y2hlc1RvT2JqKG1hdGNoZXMpIHtcblx0cmV0dXJuIHtcblx0XHRtYXRjaDogbWF0Y2hlc1swXSxcblx0XHRwcmVmaXg6IG1hdGNoZXNbMV0sXG5cdFx0bmFtZTogbWF0Y2hlc1syXSxcblx0XHRwYXJhbVBhdHRlcm46IG1hdGNoZXNbM10sXG5cdFx0dW5uYW1lZFBhdHRlcm46IG1hdGNoZXNbNF0sXG5cdFx0bW9kaWZpZXI6IG1hdGNoZXNbNV1cblx0fTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gdG9rZW5zIHBhcnNlZCBmcm9tIGEgcm91dGUgZm9ybWF0IHN0cmluZyB0byBhIHJlZ2V4LlxuICogQHBhcmFtIHshQXJyYXk8c3RyaW5nfCFPYmplY3Q+fSB0b2tlbnNcbiAqIEByZXR1cm4geyFSZWdFeHB9XG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRUb2tlbnNUb1JlZ2V4KHRva2Vucykge1xuXHRsZXQgcmVnZXggPSAnJztcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcblx0XHRpZiAoY29yZS5pc1N0cmluZyh0b2tlbnNbaV0pKSB7XG5cdFx0XHRyZWdleCArPSBlc2NhcGUodG9rZW5zW2ldKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bGV0IGNhcHR1cmUgPSBlbmNsb3NlTm9uQ2FwdHVyaW5nR3JvdXAodG9rZW5zW2ldLnBhdHRlcm4pO1xuXHRcdFx0aWYgKHRva2Vuc1tpXS5yZXBlYXQpIHtcblx0XHRcdFx0Y2FwdHVyZSArPSBlbmNsb3NlTm9uQ2FwdHVyaW5nR3JvdXAoJ1xcXFwvJyArIGNhcHR1cmUpICsgJyonO1xuXHRcdFx0fVxuXHRcdFx0Y2FwdHVyZSA9IGVzY2FwZSh0b2tlbnNbaV0ucHJlZml4KSArIGAoJHtjYXB0dXJlfSlgO1xuXHRcdFx0aWYgKHRva2Vuc1tpXS5vcHRpb25hbCkge1xuXHRcdFx0XHRpZiAoIXRva2Vuc1tpXS5wYXJ0aWFsKSB7XG5cdFx0XHRcdFx0Y2FwdHVyZSA9IGVuY2xvc2VOb25DYXB0dXJpbmdHcm91cChjYXB0dXJlKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjYXB0dXJlICs9ICc/Jztcblx0XHRcdH1cblx0XHRcdHJlZ2V4ICs9IGNhcHR1cmU7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBuZXcgUmVnRXhwKCdeJyArIG1ha2VUcmFpbGluZ1NsYXNoT3B0aW9uYWwocmVnZXgpICsgJyQnKTtcbn1cblxuLyoqXG4gKiBFbmNsb3NlcyB0aGUgZ2l2ZW4gcmVnZXggcGF0dGVybiBpbnRvIGEgbm9uIGNhcHR1cmluZyBncm91cC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXR0ZXJuXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIGVuY2xvc2VOb25DYXB0dXJpbmdHcm91cChwYXR0ZXJuKSB7XG5cdHJldHVybiBgKD86JHtwYXR0ZXJufSlgO1xufVxuXG4vKipcbiAqIEVzY2FwZXMgdGhlIGdpdmVuIHN0cmluZyB0byBzaG93IHVwIGluIHRoZSBwYXRoIHJlZ2V4LlxuICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiBlc2NhcGUoc3RyKSB7XG5cdHJldHVybiBzdHIucmVwbGFjZSgvKFsuKyo/PV4hOiR7fSgpW1xcXXxcXC9cXFxcXSkvZywgJ1xcXFwkMScpO1xufVxuXG4vKipcbiAqIE1ha2VzIHRyYWlsaW5nIHNsYXNoIG9wdGlvbmFsIG9uIHBhdGhzLlxuICogQHBhcmFtIHtzdHJpbmd9IHJlZ2V4XG4gKiBAcGFyYW0ge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gbWFrZVRyYWlsaW5nU2xhc2hPcHRpb25hbChyZWdleCkge1xuXHRpZiAoL1xcLyQvLnRlc3QocmVnZXgpKSB7XG5cdFx0cmVnZXggKz0gJz8nO1xuXHR9IGVsc2Uge1xuXHRcdHJlZ2V4ICs9ICdcXFxcLz8nO1xuXHR9XG5cdHJldHVybiByZWdleDtcbn1cblxuLyoqXG4gKiBQYXJzZXMgdGhlIGdpdmVuIHJvdXRlIGZvcm1hdCBzdHJpbmcgaW50byB0b2tlbnMgcmVwcmVzZW50aW5nIGl0cyBjb250ZW50cy5cbiAqIEBwYXJhbSB7IUFycmF5fHN0cmluZ30gcm91dGVPclRva2VucyBFaXRoZXIgYSByb3V0ZSBmb3JtYXQgc3RyaW5nIG9yIHRva2Vuc1xuICogICAgIHByZXZpb3VzbHkgcGFyc2VkIHZpYSB0aGUgYHBhcnNlYCBmdW5jdGlvbi5cbiAqIEByZXR1cm4geyFBcnJheTxzdHJpbmd8IU9iamVjdD59IEFuIGFycmF5IG9mIHRva2VucyB0aGF0IGNhbiBiZSBlaXRoZXIgcGxhaW5cbiAqICAgICBzdHJpbmdzIChwYXJ0IG9mIHRoZSByb3V0ZSkgb3Igb2JqZWN0cyBjb250YWluaW5nIGluZm9ybWF0aW9ucyBvbiBwYXJhbXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZShyb3V0ZU9yVG9rZW5zKSB7XG5cdGlmICghY29yZS5pc1N0cmluZyhyb3V0ZU9yVG9rZW5zKSkge1xuXHRcdHJldHVybiByb3V0ZU9yVG9rZW5zO1xuXHR9XG5cblx0Y29uc3Qgcm91dGUgPSByb3V0ZU9yVG9rZW5zO1xuXHRsZXQgdW5uYW1lZENvdW50ID0gMDtcblx0Y29uc3QgdG9rZW5zID0gW107XG5cdGxldCBjdXJyUGF0aCA9ICcnO1xuXHRsZXQgaW5kZXggPSAwO1xuXG5cdGxldCBtYXRjaGVzID0gUkVHRVguZXhlYyhyb3V0ZSk7XG5cdHdoaWxlIChtYXRjaGVzKSB7XG5cdFx0Y29uc3QgZGF0YSA9IGNvbnZlcnRNYXRjaGVzVG9PYmoobWF0Y2hlcyk7XG5cblx0XHRjdXJyUGF0aCA9IHJvdXRlLnNsaWNlKGluZGV4LCBtYXRjaGVzLmluZGV4KTtcblx0XHRpbmRleCA9IG1hdGNoZXMuaW5kZXggKyBkYXRhLm1hdGNoLmxlbmd0aDtcblx0XHR0b2tlbnMucHVzaChjdXJyUGF0aCk7XG5cblx0XHR0b2tlbnMucHVzaCh7XG5cdFx0XHRuYW1lOiBkYXRhLm5hbWUgPyBkYXRhLm5hbWUgOiAnJyArIHVubmFtZWRDb3VudCsrLFxuXHRcdFx0cGFydGlhbDogcm91dGVbaW5kZXhdICYmIHJvdXRlW2luZGV4XSAhPT0gZGF0YS5wcmVmaXgsXG5cdFx0XHRwcmVmaXg6IGRhdGEucHJlZml4IHx8ICcnLFxuXHRcdFx0cGF0dGVybjogZGF0YS5wYXJhbVBhdHRlcm4gfHwgZGF0YS51bm5hbWVkUGF0dGVybiB8fCAnW15cXFxcL10rJyxcblx0XHRcdHJlcGVhdDogZGF0YS5tb2RpZmllciA9PT0gJyonIHx8IGRhdGEubW9kaWZpZXIgPT09ICcrJyxcblx0XHRcdG9wdGlvbmFsOiBkYXRhLm1vZGlmaWVyID09PSAnKicgfHwgZGF0YS5tb2RpZmllciA9PT0gJz8nXG5cdFx0fSk7XG5cblx0XHRtYXRjaGVzID0gUkVHRVguZXhlYyhyb3V0ZSk7XG5cdH1cblxuXHRpZiAoaW5kZXggPCByb3V0ZS5sZW5ndGgpIHtcblx0XHR0b2tlbnMucHVzaChyb3V0ZS5zdWJzdHIoaW5kZXgpKTtcblx0fVxuXHRyZXR1cm4gdG9rZW5zO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIHRoZSBnaXZlbiByb3V0ZSBmb3JtYXQgc3RyaW5nIHRvIGEgcmVnZXggdGhhdCBjYW4gZXh0cmFjdCBwYXJhbVxuICogZGF0YSBmcm9tIHBhdGhzIG1hdGNoaW5nIGl0LlxuICogQHBhcmFtIHshQXJyYXl8c3RyaW5nfSByb3V0ZU9yVG9rZW5zIEVpdGhlciBhIHJvdXRlIGZvcm1hdCBzdHJpbmcgb3IgdG9rZW5zXG4gKiAgICAgcHJldmlvdXNseSBwYXJzZWQgdmlhIHRoZSBgcGFyc2VgIGZ1bmN0aW9uLlxuICogQHJldHVybiB7IVJlZ0V4cH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvUmVnZXgocm91dGVPclRva2Vucykge1xuXHRyZXR1cm4gY29udmVydFRva2Vuc1RvUmVnZXgocGFyc2Uocm91dGVPclRva2VucykpO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIGRhdGEgZnJvbSB0aGUgZ2l2ZW4gcGF0aCBhY2NvcmRpbmcgdG8gdGhlIHNwZWNpZmllZCByb3V0ZSBmb3JtYXQuXG4gKiBAcGFyYW0geyFBcnJheXxzdHJpbmd9IHJvdXRlT3JUb2tlbnMgRWl0aGVyIGEgcm91dGUgZm9ybWF0IHN0cmluZyBvciB0b2tlbnNcbiAqICAgICBwcmV2aW91c2x5IHBhcnNlZCB2aWEgdGhlIGBwYXJzZWAgZnVuY3Rpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gVGhlIHBhdGggdG8gZXh0cmFjdCBwYXJhbSBkYXRhIGZyb20uXG4gKiBAcmV0dXJuIHtPYmplY3Q8c3RyaW5nLCBzdHJpbmc+fSBUaGUgZGF0YSBvYmplY3QsIG9yIG51bGwgaWYgdGhlIHBhdGggZG9lc24ndFxuICogICAgIG1hdGNoIHRoZSBnaXZlbiBmb3JtYXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0RGF0YShyb3V0ZU9yVG9rZW5zLCBwYXRoKSB7XG5cdGNvbnN0IGRhdGEgPSB7fTtcblx0Y29uc3QgdG9rZW5zID0gcGFyc2Uocm91dGVPclRva2Vucyk7XG5cdGNvbnN0IG1hdGNoID0gcGF0aC5tYXRjaChjb252ZXJ0VG9rZW5zVG9SZWdleCh0b2tlbnMpKTtcblxuXHRpZiAoIW1hdGNoKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHRsZXQgcGFyYW1JbmRleCA9IDE7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKCFjb3JlLmlzU3RyaW5nKHRva2Vuc1tpXSkpIHtcblx0XHRcdGxldCB2YWx1ZSA9IG1hdGNoW3BhcmFtSW5kZXgrK107XG5cdFx0XHRpZiAoY29yZS5pc0RlZih2YWx1ZSkpIHtcblx0XHRcdFx0aWYgKHRva2Vuc1tpXS5yZXBlYXQpIHtcblx0XHRcdFx0XHR2YWx1ZSA9IHZhbHVlLnNwbGl0KCcvJyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZGF0YVt0b2tlbnNbaV0ubmFtZV0gPSB2YWx1ZTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0cmV0dXJuIGRhdGE7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmQW5kTm90TnVsbCwgaXNGdW5jdGlvbiwgaXNTdHJpbmcgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBleHRyYWN0RGF0YSwgcGFyc2UsIHRvUmVnZXggfSBmcm9tICdtZXRhbC1wYXRoLXBhcnNlcic7XG5cbmNsYXNzIFJvdXRlIHtcblxuXHQvKipcblx0ICogUm91dGUgY2xhc3MuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ3xSZWdFeHB8RnVuY3Rpb259IHBhdGhcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGhhbmRsZXJcblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihwYXRoLCBoYW5kbGVyKSB7XG5cdFx0aWYgKCFpc0RlZkFuZE5vdE51bGwocGF0aCkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignUm91dGUgcGF0aCBub3Qgc3BlY2lmaWVkLicpO1xuXHRcdH1cblx0XHRpZiAoIWlzRnVuY3Rpb24oaGFuZGxlcikpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignUm91dGUgaGFuZGxlciBpcyBub3QgYSBmdW5jdGlvbi4nKTtcblx0XHR9XG5cblx0XHQvKipcblx0XHQgKiBEZWZpbmVzIHRoZSBoYW5kbGVyIHdoaWNoIHdpbGwgZXhlY3V0ZSBvbmNlIGEgVVJMIGluIHRoZSBhcHBsaWNhdGlvblxuXHRcdCAqIG1hdGNoZXMgdGhlIHBhdGguXG5cdFx0ICogQHR5cGUgeyFGdW5jdGlvbn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5oYW5kbGVyID0gaGFuZGxlcjtcblxuXHRcdC8qKlxuXHRcdCAqIERlZmluZXMgdGhlIHBhdGggd2hpY2ggd2lsbCB0cmlnZ2VyIHRoZSByb3V0ZSBoYW5kbGVyLlxuXHRcdCAqIEB0eXBlIHshc3RyaW5nfFJlZ0V4cHxGdW5jdGlvbn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wYXRoID0gcGF0aDtcblx0fVxuXG5cdC8qKlxuXHQqIEJ1aWxkcyBwYXJzZWQgZGF0YSAocmVnZXggYW5kIHRva2VucykgZm9yIHRoaXMgcm91dGUuXG5cdCogQHJldHVybiB7IU9iamVjdH1cblx0KiBAcHJvdGVjdGVkXG5cdCovXG5cdGJ1aWxkUGFyc2VkRGF0YV8oKSB7XG5cdFx0aWYgKCF0aGlzLnBhcnNlZERhdGFfKSB7XG5cdFx0XHR2YXIgdG9rZW5zID0gcGFyc2UodGhpcy5wYXRoKTtcblx0XHRcdHZhciByZWdleCA9IHRvUmVnZXgodG9rZW5zKTtcblx0XHRcdHRoaXMucGFyc2VkRGF0YV8gPSB7XG5cdFx0XHRcdHJlZ2V4LFxuXHRcdFx0XHR0b2tlbnNcblx0XHRcdH07XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLnBhcnNlZERhdGFfO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIHBhcmFtIGRhdGEgZnJvbSB0aGUgZ2l2ZW4gcGF0aCwgYWNjb3JkaW5nIHRvIHRoaXMgcm91dGUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIFRoZSB1cmwgcGF0aCB0byBleHRyYWN0IHBhcmFtcyBmcm9tLlxuXHQgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBleHRyYWN0ZWQgZGF0YSwgaWYgdGhlIHBhdGggbWF0Y2hlcyB0aGlzIHJvdXRlLCBvclxuXHQgKiAgICAgbnVsbCBvdGhlcndpc2UuXG5cdCAqL1xuXHRleHRyYWN0UGFyYW1zKHBhdGgpIHtcblx0XHRpZiAoaXNTdHJpbmcodGhpcy5wYXRoKSkge1xuXHRcdFx0cmV0dXJuIGV4dHJhY3REYXRhKHRoaXMuYnVpbGRQYXJzZWREYXRhXygpLnRva2VucywgcGF0aCk7XG5cdFx0fVxuXHRcdHJldHVybiB7fTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByb3V0ZSBoYW5kbGVyLlxuXHQgKiBAcmV0dXJuIHshRnVuY3Rpb259XG5cdCAqL1xuXHRnZXRIYW5kbGVyKCkge1xuXHRcdHJldHVybiB0aGlzLmhhbmRsZXI7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcm91dGUgcGF0aC5cblx0ICogQHJldHVybiB7IXN0cmluZ3xSZWdFeHB8RnVuY3Rpb259XG5cdCAqL1xuXHRnZXRQYXRoKCkge1xuXHRcdHJldHVybiB0aGlzLnBhdGg7XG5cdH1cblxuXHQvKipcbiBcdCAqIE1hdGNoZXMgaWYgdGhlIHJvdXRlciBjYW4gaGFuZGxlIHRoZSB0ZXN0ZWQgcGF0aC5cbiBcdCAqIEBwYXJhbSB7IXN0cmluZ30gdmFsdWUgUGF0aCB0byB0ZXN0IChtYXkgY29udGFpbiB0aGUgcXVlcnlzdHJpbmcgcGFydCkuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiBtYXRjaGVzIGFueSByb3V0ZS5cblx0ICovXG5cdG1hdGNoZXNQYXRoKHZhbHVlKSB7XG5cdFx0dmFyIHBhdGggPSB0aGlzLnBhdGg7XG5cblx0XHRpZiAoaXNGdW5jdGlvbihwYXRoKSkge1xuXHRcdFx0cmV0dXJuIHBhdGgodmFsdWUpO1xuXHRcdH1cblx0XHRpZiAoaXNTdHJpbmcocGF0aCkpIHtcblx0XHRcdHBhdGggPSB0aGlzLmJ1aWxkUGFyc2VkRGF0YV8oKS5yZWdleDtcblx0XHR9XG5cdFx0aWYgKHBhdGggaW5zdGFuY2VvZiBSZWdFeHApIHtcblx0XHRcdHJldHVybiB2YWx1ZS5zZWFyY2gocGF0aCkgPiAtMTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBSb3V0ZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgRGlzcG9zYWJsZSB9IGZyb20gJ21ldGFsJztcblxuY2xhc3MgQ2FjaGVhYmxlIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cblx0LyoqXG5cdCAqIEFic3RyYWN0IGNsYXNzIGZvciBkZWZpbmluZyBjYWNoZWFibGUgYmVoYXZpb3IuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBjYWNoZWQgZGF0YS5cblx0XHQgKiBAdHlwZSB7IU9iamVjdH1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuY2FjaGUgPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgd2hldGhlciBjbGFzcyBpcyBjYWNoZWFibGUuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQGRlZmF1bHQgZmFsc2Vcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5jYWNoZWFibGUgPSBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGNvbnRlbnQgdG8gdGhlIGNhY2hlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gY29udGVudCBDb250ZW50IHRvIGJlIGNhY2hlZC5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkQ2FjaGUoY29udGVudCkge1xuXHRcdGlmICh0aGlzLmNhY2hlYWJsZSkge1xuXHRcdFx0dGhpcy5jYWNoZSA9IGNvbnRlbnQ7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENsZWFycyB0aGUgY2FjaGUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGNsZWFyQ2FjaGUoKSB7XG5cdFx0dGhpcy5jYWNoZSA9IG51bGw7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLmNsZWFyQ2FjaGUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjYWNoZWQgY29udGVudC5cblx0ICogQHJldHVybiB7T2JqZWN0fSBDYWNoZWQgY29udGVudC5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0Z2V0Q2FjaGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY2FjaGU7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgY2xhc3MgaXMgY2FjaGVhYmxlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBSZXR1cm5zIHRydWUgd2hlbiBjbGFzcyBpcyBjYWNoZWFibGUsIGZhbHNlIG90aGVyd2lzZS5cblx0ICovXG5cdGlzQ2FjaGVhYmxlKCkge1xuXHRcdHJldHVybiB0aGlzLmNhY2hlYWJsZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHdoZXRoZXIgdGhlIGNsYXNzIGlzIGNhY2hlYWJsZS5cblx0ICogQHBhcmFtIHtib29sZWFufSBjYWNoZWFibGVcblx0ICovXG5cdHNldENhY2hlYWJsZShjYWNoZWFibGUpIHtcblx0XHRpZiAoIWNhY2hlYWJsZSkge1xuXHRcdFx0dGhpcy5jbGVhckNhY2hlKCk7XG5cdFx0fVxuXHRcdHRoaXMuY2FjaGVhYmxlID0gY2FjaGVhYmxlO1xuXHR9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgQ2FjaGVhYmxlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBnZXRVaWQgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBnbG9iYWxFdmFsIH0gZnJvbSAnbWV0YWwtZG9tJztcbmltcG9ydCBDYWNoZWFibGUgZnJvbSAnLi4vY2FjaGVhYmxlL0NhY2hlYWJsZSc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuXG5jbGFzcyBTY3JlZW4gZXh0ZW5kcyBDYWNoZWFibGUge1xuXG5cdC8qKlxuXHQgKiBTY3JlZW4gY2xhc3MgaXMgYSBzcGVjaWFsIHR5cGUgb2Ygcm91dGUgaGFuZGxlciB0aGF0IHByb3ZpZGVzIGhlbHBlclxuXHQgKiB1dGlsaXRpZXMgdGhhdCBhZGRzIGxpZmVjeWNsZSBhbmQgbWV0aG9kcyB0byBwcm92aWRlIGNvbnRlbnQgdG8gZWFjaFxuXHQgKiByZWdpc3RlcmVkIHN1cmZhY2UuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKiBAZXh0ZW5kcyB7Q2FjaGVhYmxlfVxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBzY3JlZW4gaWQuXG5cdFx0ICogQHR5cGUge3N0cmluZ31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5pZCA9IHRoaXMubWFrZUlkXyhnZXRVaWQoKSk7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgc2NyZWVuIG1ldGEgdGFncy4gUmVsZXZhbnQgd2hlbiB0aGUgbWV0YSB0YWdzXG5cdFx0ICogc2hvdWxkIGJlIHVwZGF0ZWQgd2hlbiBzY3JlZW4gaXMgcmVuZGVyZWQuXG5cdFx0ICovXG5cdFx0dGhpcy5tZXRhcyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgc2NyZWVuIHRpdGxlLiBSZWxldmFudCB3aGVuIHRoZSBwYWdlIHRpdGxlIHNob3VsZCBiZVxuXHRcdCAqIHVwYWRhdGVkIHdoZW4gc2NyZWVuIGlzIHJlbmRlcmVkLlxuXHRcdCAqIEB0eXBlIHs/c3RyaW5nPX1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudGl0bGUgPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpcmVzIHdoZW4gdGhlIHNjcmVlbiBpcyBhY3RpdmUuIEFsbG93cyBhIHNjcmVlbiB0byBwZXJmb3JtIGFueSBzZXR1cFxuXHQgKiB0aGF0IHJlcXVpcmVzIGl0cyBET00gdG8gYmUgdmlzaWJsZS4gTGlmZWN5Y2xlLlxuXHQgKi9cblx0YWN0aXZhdGUoKSB7XG5cdFx0Y29uc29sZS5sb2coJ1NjcmVlbiBbJyArIHRoaXMgKyAnXSBhY3RpdmF0ZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdpdmVzIHRoZSBTY3JlZW4gYSBjaGFuY2UgdG8gY2FuY2VsIHRoZSBuYXZpZ2F0aW9uIGFuZCBzdG9wIGl0c2VsZiBmcm9tXG5cdCAqIGFjdGl2YXRpbmcuIENhbiBiZSB1c2VkLCBmb3IgZXhhbXBsZSwgdG8gcHJldmVudCBuYXZpZ2F0aW9uIGlmIGEgdXNlclxuXHQgKiBpcyBub3QgYXV0aGVudGljYXRlZC4gTGlmZWN5Y2xlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFuPXw/Q2FuY2VsbGFibGVQcm9taXNlPX0gSWYgcmV0dXJucyBvciByZXNvbHZlcyB0byB0cnVlLFxuXHQgKiAgICAgdGhlIGN1cnJlbnQgc2NyZWVuIGlzIGxvY2tlZCBhbmQgdGhlIG5leHQgbmFnaXZhdGlvbiBpbnRlcnJ1cHRlZC5cblx0ICovXG5cdGJlZm9yZUFjdGl2YXRlKCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gYmVmb3JlQWN0aXZhdGUnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHaXZlcyB0aGUgU2NyZWVuIGEgY2hhbmNlIHRvIGNhbmNlbCB0aGUgbmF2aWdhdGlvbiBhbmQgc3RvcCBpdHNlbGYgZnJvbVxuXHQgKiBiZWluZyBkZWFjdGl2YXRlZC4gQ2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCBpZiB0aGUgc2NyZWVuIGhhcyB1bnNhdmVkXG5cdCAqIHN0YXRlLiBMaWZlY3ljbGUuIENsZWFuLXVwIHNob3VsZCBub3QgYmUgcHJlZm9ybWVkIGhlcmUsIHNpbmNlIHRoZVxuXHQgKiBuYXZpZ2F0aW9uIG1heSBzdGlsbCBiZSBjYW5jZWxsZWQuIERvIGNsZWFuLXVwIGluIGRlYWN0aXZhdGUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW49fD9DYW5jZWxsYWJsZVByb21pc2U9fSBJZiByZXR1cm5zIG9yIHJlc29sdmVzIHRvIHRydWUsXG5cdCAqICAgICB0aGUgY3VycmVudCBzY3JlZW4gaXMgbG9ja2VkIGFuZCB0aGUgbmV4dCBuYWdpdmF0aW9uIGludGVycnVwdGVkLlxuXHQgKi9cblx0YmVmb3JlRGVhY3RpdmF0ZSgpIHtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGJlZm9yZURlYWN0aXZhdGUnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHaXZlcyB0aGUgU2NyZWVuIGEgY2hhbmNlIGZvcm1hdCB0aGUgcGF0aCBiZWZvcmUgaGlzdG9yeSB1cGRhdGUuXG5cdCAqIEBwYXRoIHshc3RyaW5nfSBwYXRoIE5hdmlnYXRpb24gcGF0aC5cblx0ICogQHJldHVybiB7IXN0cmluZ30gTmF2aWdhdGlvbiBwYXRoIHRvIHVzZSBvbiBoaXN0b3J5LlxuXHQgKi9cblx0YmVmb3JlVXBkYXRlSGlzdG9yeVBhdGgocGF0aCkge1xuXHRcdHJldHVybiBwYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdpdmVzIHRoZSBTY3JlZW4gYSBjaGFuY2UgZm9ybWF0IHRoZSBzdGF0ZSBiZWZvcmUgaGlzdG9yeSB1cGRhdGUuXG5cdCAqIEBwYXRoIHshb2JqZWN0fSBzdGF0ZSBIaXN0b3J5IHN0YXRlLlxuXHQgKiBAcmV0dXJuIHshb2JqZWN0fSBIaXN0b3J5IHN0YXRlIHRvIHVzZSBvbiBoaXN0b3J5LlxuXHQgKi9cblx0YmVmb3JlVXBkYXRlSGlzdG9yeVN0YXRlKHN0YXRlKSB7XG5cdFx0cmV0dXJuIHN0YXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBkbyBhbnkgY2xlYW51cCBuZWNlc3NhcnkgYWZ0ZXIgaXQgaGFzIGJlZW5cblx0ICogZGVhY3RpdmF0ZWQsIGZvciBleGFtcGxlIGNhbmNlbGxpbmcgb3V0c3RhbmRpbmcgcmVxdWVzdHMgb3Igc3RvcHBpbmdcblx0ICogdGltZXJzLiBMaWZlY3ljbGUuXG5cdCAqL1xuXHRkZWFjdGl2YXRlKCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZGVhY3RpdmF0ZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2UgYSBzY3JlZW4sIGVpdGhlciBhZnRlciBpdCBpcyBkZWFjdGl2YXRlZCAoaW4gdGhlIGNhc2Ugb2YgYVxuXHQgKiBub24tY2FjaGVhYmxlIHZpZXcpIG9yIHdoZW4gdGhlIEFwcCBpcyBpdHNlbGYgZGlzcG9zZWQgZm9yIHdoYXRldmVyXG5cdCAqIHJlYXNvbi4gTGlmZWN5Y2xlLlxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHN1cGVyLmRpc3Bvc2VJbnRlcm5hbCgpO1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZGlzcG9zZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBldmFsdWF0ZSBzY3JpcHRzIGJlZm9yZSB0aGUgZWxlbWVudCBpcyBtYWRlIHZpc2libGUuXG5cdCAqIExpZmVjeWNsZS5cblx0ICogQHBhcmFtIHshb2JqZWN0fSBzdXJmYWNlcyBNYXAgb2Ygc3VyZmFjZXMgdG8gZmxpcCBrZXllZCBieSBzdXJmYWNlIGlkLlxuXHQgKiBAcmV0dXJuIHs/Q2FuY2VsbGFibGVQcm9taXNlPX0gVGhpcyBjYW4gcmV0dXJuIGEgcHJvbWlzZSwgd2hpY2ggd2lsbFxuXHQgKiAgICAgcGF1c2UgdGhlIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHRldmFsdWF0ZVNjcmlwdHMoc3VyZmFjZXMpIHtcblx0XHRPYmplY3Qua2V5cyhzdXJmYWNlcykuZm9yRWFjaChzSWQgPT4ge1xuXHRcdFx0aWYgKHN1cmZhY2VzW3NJZF0uYWN0aXZlQ2hpbGQpIHtcblx0XHRcdFx0Z2xvYmFsRXZhbC5ydW5TY3JpcHRzSW5FbGVtZW50KHN1cmZhY2VzW3NJZF0uYWN0aXZlQ2hpbGQpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBldmFsdWF0ZSBzdHlsZXMgYmVmb3JlIHRoZSBlbGVtZW50IGlzIG1hZGUgdmlzaWJsZS5cblx0ICogTGlmZWN5Y2xlLlxuXHQgKiBAcGFyYW0geyFvYmplY3R9IHN1cmZhY2VzIE1hcCBvZiBzdXJmYWNlcyB0byBmbGlwIGtleWVkIGJ5IHN1cmZhY2UgaWQuXG5cdCAqIEByZXR1cm4gez9DYW5jZWxsYWJsZVByb21pc2U9fSBUaGlzIGNhbiByZXR1cm4gYSBwcm9taXNlLCB3aGljaCB3aWxsXG5cdCAqICAgICBwYXVzZSB0aGUgbmF2aWdhdGlvbiB1bnRpbCBpdCBpcyByZXNvbHZlZC5cblx0ICovXG5cdGV2YWx1YXRlU3R5bGVzKCkge1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBwZXJmb3JtIGFueSBzZXR1cCBpbW1lZGlhdGVseSBiZWZvcmUgdGhlIGVsZW1lbnQgaXNcblx0ICogbWFkZSB2aXNpYmxlLiBMaWZlY3ljbGUuXG5cdCAqIEBwYXJhbSB7IW9iamVjdH0gc3VyZmFjZXMgTWFwIG9mIHN1cmZhY2VzIHRvIGZsaXAga2V5ZWQgYnkgc3VyZmFjZSBpZC5cblx0ICogQHJldHVybiB7P0NhbmNlbGxhYmxlUHJvbWlzZT19IFRoaXMgY2FuIHJldHVybiBhIHByb21pc2UsIHdoaWNoIHdpbGwgcGF1c2UgdGhlXG5cdCAqICAgICBuYXZpZ2F0aW9uIHVudGlsIGl0IGlzIHJlc29sdmVkLlxuXHQgKi9cblx0ZmxpcChzdXJmYWNlcykge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZmxpcCcpO1xuXG5cdFx0dmFyIHRyYW5zaXRpb25zID0gW107XG5cblx0XHRPYmplY3Qua2V5cyhzdXJmYWNlcykuZm9yRWFjaChzSWQgPT4ge1xuXHRcdFx0dmFyIHN1cmZhY2UgPSBzdXJmYWNlc1tzSWRdO1xuXHRcdFx0dmFyIGRlZmVycmVkID0gc3VyZmFjZS5zaG93KHRoaXMuaWQpO1xuXHRcdFx0dHJhbnNpdGlvbnMucHVzaChkZWZlcnJlZCk7XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLmFsbCh0cmFuc2l0aW9ucyk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc2NyZWVuIGlkLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRJZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzY3JlZW4gbWV0YSB0YWdzLlxuXHQgKiBAcmV0dXJuIHtOb2RlTGlzdHxOb2RlfVxuXHQgKi9cblx0Z2V0TWV0YXMoKSB7XG5cdFx0cmV0dXJuIHRoaXMubWV0YXM7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgY29udGVudCBmb3IgdGhlIGdpdmVuIHN1cmZhY2UsIG9yIG51bGwgaWYgdGhlIHN1cmZhY2UgaXNuJ3Rcblx0ICogdXNlZCBieSB0aGlzIHNjcmVlbi4gVGhpcyB3aWxsIGJlIGNhbGxlZCB3aGVuIGEgc2NyZWVuIGlzIGluaXRpYWxseVxuXHQgKiBjb25zdHJ1Y3RlZCBvciwgaWYgYSBzY3JlZW4gaXMgbm9uLWNhY2hlYWJsZSwgd2hlbiBuYXZpZ2F0ZWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc3VyZmFjZUlkIFRoZSBpZCBvZiB0aGUgc3VyZmFjZSBET00gZWxlbWVudC5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBwYXJhbXMgUGFyYW1zIGV4dHJhY3RlZCBmcm9tIHRoZSBjdXJyZW50IHBhdGguXG5cdCAqIEByZXR1cm4gez9zdHJpbmd8RWxlbWVudD19IFRoaXMgY2FuIHJldHVybiBhIHN0cmluZyBvciBub2RlIHJlcHJlc2VudGluZ1xuXHQgKiAgICAgdGhlIGNvbnRlbnQgb2YgdGhlIHN1cmZhY2UuIElmIHJldHVybnMgZmFsc3kgdmFsdWVzIHN1cmZhY2UgZGVmYXVsdFxuXHQgKiAgICAgY29udGVudCBpcyByZXN0b3JlZC5cblx0ICovXG5cdGdldFN1cmZhY2VDb250ZW50KCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZ2V0U3VyZmFjZUNvbnRlbnQnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzY3JlZW4gdGl0bGUuXG5cdCAqIEByZXR1cm4gez9zdHJpbmc9fVxuXHQgKi9cblx0Z2V0VGl0bGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMudGl0bGU7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbGwgY29udGVudHMgZm9yIHRoZSBzdXJmYWNlcy4gVGhpcyB3aWxsIHBhc3MgdGhlIGxvYWRlZCBjb250ZW50XG5cdCAqIHRvIDxjb2RlPlNjcmVlbi5sb2FkPC9jb2RlPiB3aXRoIGFsbCBpbmZvcm1hdGlvbiB5b3Vcblx0ICogbmVlZCB0byBmdWxmaWxsIHRoZSBzdXJmYWNlcy4gTGlmZWN5Y2xlLlxuXHQgKiBAcGFyYW0geyFzdHJpbmc9fSBwYXRoIFRoZSByZXF1ZXN0ZWQgcGF0aC5cblx0ICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZX0gVGhpcyBjYW4gcmV0dXJuIGEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGVcblx0ICogICAgIGNvbnRlbnRzIG9mIHRoZSBzdXJmYWNlcyBvciBhIHByb21pc2UsIHdoaWNoIHdpbGwgcGF1c2UgdGhlIG5hdmlnYXRpb25cblx0ICogICAgIHVudGlsIGl0IGlzIHJlc29sdmVkLiBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9hZGluZyBhc3luYyBjb250ZW50LlxuXHQgKi9cblx0bG9hZCgpIHtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGxvYWQnKTtcblx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYWtlcyB0aGUgaWQgZm9yIHRoZSBzY3JlZW4uXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaWQgVGhlIHNjcmVlbiBpZCB0aGUgY29udGVudCBiZWxvbmdzIHRvby5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0bWFrZUlkXyhpZCkge1xuXHRcdHJldHVybiAnc2NyZWVuXycgKyBpZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBzY3JlZW4gaWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaWRcblx0ICovXG5cdHNldElkKGlkKSB7XG5cdFx0dGhpcy5pZCA9IGlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHNjcmVlbiBtZXRhIHRhZ3MuXG5cdCAqIEBwYXJhbSB7Tm9kZUxpc3R8Tm9kZX0gbWV0YXNcblx0ICovXG5cdHNldE1ldGFzKG1ldGFzKSB7XG5cdFx0dGhpcy5tZXRhcyA9IG1ldGFzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHNjcmVlbiB0aXRsZS5cblx0ICogQHBhcmFtIHs/c3RyaW5nPX0gdGl0bGVcblx0ICovXG5cdHNldFRpdGxlKHRpdGxlKSB7XG5cdFx0dGhpcy50aXRsZSA9IHRpdGxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdHRvU3RyaW5nKCkge1xuXHRcdHJldHVybiB0aGlzLmlkO1xuXHR9XG5cbn1cblxuLyoqXG4gKiBAcGFyYW0geyp9IG9iamVjdFxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciBhIGdpdmVuIGluc3RhbmNlIGltcGxlbWVudHNcbiAqIDxjb2RlPlNjcmVlbjwvY29kZT4uXG4gKi9cblNjcmVlbi5pc0ltcGxlbWVudGVkQnkgPSBmdW5jdGlvbihvYmplY3QpIHtcblx0cmV0dXJuIG9iamVjdCBpbnN0YW5jZW9mIFNjcmVlbjtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IFNjcmVlbjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IGdsb2JhbHMgZnJvbSAnLi4vZ2xvYmFscy9nbG9iYWxzJztcbmltcG9ydCB7IERpc3Bvc2FibGUsIGlzRGVmQW5kTm90TnVsbCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7IGFwcGVuZCwgcmVtb3ZlQ2hpbGRyZW4sIGV4aXREb2N1bWVudCB9IGZyb20gJ21ldGFsLWRvbSc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuXG5jbGFzcyBTdXJmYWNlIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cblx0LyoqXG5cdCAqIFN1cmZhY2UgY2xhc3MgcmVwcmVzZW50aW5nIHRoZSByZWZlcmVuY2VzIHRvIGVsZW1lbnRzIG9uIHRoZSBwYWdlIHRoYXRcblx0ICogY2FuIHBvdGVudGlhbGx5IGJlIHVwZGF0ZWQgYnkgPGNvZGU+QXBwPC9jb2RlPi5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGlkXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoaWQpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0aWYgKCFpZCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTdXJmYWNlIGVsZW1lbnQgaWQgbm90IHNwZWNpZmllZC4gQSBzdXJmYWNlIGVsZW1lbnQgcmVxdWlyZXMgYSB2YWxpZCBpZC4nKTtcblx0XHR9XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgYWN0aXZlIGNoaWxkIGVsZW1lbnQuXG5cdFx0ICogQHR5cGUge0VsZW1lbnR9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmFjdGl2ZUNoaWxkID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBkZWZhdWx0IGNoaWxkIGVsZW1lbnQuXG5cdFx0ICogQHR5cGUge0VsZW1lbnR9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmRlZmF1bHRDaGlsZCA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgZWxlbWVudCB3aXRoIHRoZSBzcGVjaWZpZWQgc3VyZmFjZSBpZCwgaWYgbm90IGZvdW5kIGNyZWF0ZXMgYVxuXHRcdCAqIG5ldyBlbGVtZW50IHdpdGggdGhlIHNwZWNpZmllZCBpZC5cblx0XHQgKiBAdHlwZSB7RWxlbWVudH1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZWxlbWVudCA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgc3VyZmFjZSBpZC5cblx0XHQgKiBAdHlwZSB7U3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5pZCA9IGlkO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGRlZmF1bHQgdHJhbnNpdGlvbkZuIGZvciB0aGUgc3VyZmFjZXMuXG5cdFx0ICogQHBhcmFtIHs/RWxlbWVudD19IGZyb20gVGhlIHZpc2libGUgc3VyZmFjZSBlbGVtZW50LlxuXHRcdCAqIEBwYXJhbSB7P0VsZW1lbnQ9fSB0byBUaGUgc3VyZmFjZSBlbGVtZW50IHRvIGJlIGZsaXBwZWQuXG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdHRoaXMudHJhbnNpdGlvbkZuID0gbnVsbDtcblxuXHRcdHRoaXMuZGVmYXVsdENoaWxkID0gdGhpcy5nZXRDaGlsZChTdXJmYWNlLkRFRkFVTFQpO1xuXHRcdHRoaXMubWF5YmVXcmFwQ29udGVudEFzRGVmYXVsdF8oKTtcblx0XHR0aGlzLmFjdGl2ZUNoaWxkID0gdGhpcy5kZWZhdWx0Q2hpbGQ7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBzY3JlZW4gY29udGVudCB0byBhIHN1cmZhY2UuIElmIGNvbnRlbnQgaGFzbid0IGJlZW4gcGFzc2VkLCBzZWUgaWZcblx0ICogYW4gZWxlbWVudCBleGlzdHMgaW4gdGhlIERPTSB0aGF0IG1hdGNoZXMgdGhlIGlkLiBCeSBjb252ZW50aW9uLCB0aGVcblx0ICogZWxlbWVudCBzaG91bGQgYWxyZWFkeSBiZSBuZXN0ZWQgaW4gdGhlIHJpZ2h0IGVsZW1lbnQgYW5kIHNob3VsZCBoYXZlIGFuXG5cdCAqIGlkIHRoYXQgaXMgYSBjb25jYXRlbnRhdGlvbiBvZiB0aGUgc3VyZmFjZSBpZCArICctJyArIHRoZSBzY3JlZW4gaWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2NyZWVuSWQgVGhlIHNjcmVlbiBpZCB0aGUgY29udGVudCBiZWxvbmdzIHRvby5cblx0ICogQHBhcmFtIHs/c3RyaW5nfEVsZW1lbnQ9fSBvcHRfY29udGVudCBUaGUgc3RyaW5nIGNvbnRlbnQgb3IgZWxlbWVudCB0b1xuXHQgKiAgICAgYWRkIGJlIGFkZGVkIGFzIHN1cmZhY2UgY29udGVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH1cblx0ICovXG5cdGFkZENvbnRlbnQoc2NyZWVuSWQsIG9wdF9jb250ZW50KSB7XG5cdFx0dmFyIGNoaWxkID0gdGhpcy5kZWZhdWx0Q2hpbGQ7XG5cblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKG9wdF9jb250ZW50KSkge1xuXHRcdFx0Y2hpbGQgPSB0aGlzLmdldENoaWxkKHNjcmVlbklkKTtcblx0XHRcdGlmIChjaGlsZCkge1xuXHRcdFx0XHRyZW1vdmVDaGlsZHJlbihjaGlsZCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjaGlsZCA9IHRoaXMuY3JlYXRlQ2hpbGQoc2NyZWVuSWQpO1xuXHRcdFx0XHR0aGlzLnRyYW5zaXRpb24oY2hpbGQsIG51bGwpO1xuXHRcdFx0fVxuXHRcdFx0YXBwZW5kKGNoaWxkLCBvcHRfY29udGVudCk7XG5cdFx0fVxuXG5cdFx0dmFyIGVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnQoKTtcblxuXHRcdGlmIChlbGVtZW50ICYmIGNoaWxkKSB7XG5cdFx0XHRhcHBlbmQoZWxlbWVudCwgY2hpbGQpO1xuXHRcdH1cblxuXHRcdHJldHVybiBjaGlsZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGNoaWxkIG5vZGUgZm9yIHRoZSBzdXJmYWNlLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQuXG5cdCAqIEByZXR1cm4ge0VsZW1lbnR9XG5cdCAqL1xuXHRjcmVhdGVDaGlsZChzY3JlZW5JZCkge1xuXHRcdHZhciBjaGlsZCA9IGdsb2JhbHMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cdFx0Y2hpbGQuc2V0QXR0cmlidXRlKCdpZCcsIHRoaXMubWFrZUlkXyhzY3JlZW5JZCkpO1xuXHRcdHJldHVybiBjaGlsZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGNoaWxkIG5vZGUgb2YgdGhlIHN1cmZhY2UuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2NyZWVuSWQgVGhlIHNjcmVlbiBpZC5cblx0ICogQHJldHVybiB7P0VsZW1lbnR9XG5cdCAqL1xuXHRnZXRDaGlsZChzY3JlZW5JZCkge1xuXHRcdHJldHVybiBnbG9iYWxzLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMubWFrZUlkXyhzY3JlZW5JZCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHN1cmZhY2UgZWxlbWVudCBmcm9tIGVsZW1lbnQsIGFuZCBzZXRzIGl0IHRvIHRoZSBlbCBwcm9wZXJ0eSBvZlxuXHQgKiB0aGUgY3VycmVudCBpbnN0YW5jZS5cblx0ICogPGNvZGU+dGhpcy5lbGVtZW50PC9jb2RlPiB3aWxsIGJlIHVzZWQuXG5cdCAqIEByZXR1cm4gez9FbGVtZW50fSBUaGUgY3VycmVudCBzdXJmYWNlIGVsZW1lbnQuXG5cdCAqL1xuXHRnZXRFbGVtZW50KCkge1xuXHRcdGlmICh0aGlzLmVsZW1lbnQpIHtcblx0XHRcdHJldHVybiB0aGlzLmVsZW1lbnQ7XG5cdFx0fVxuXHRcdHRoaXMuZWxlbWVudCA9IGdsb2JhbHMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5pZCk7XG5cdFx0cmV0dXJuIHRoaXMuZWxlbWVudDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzdXJmYWNlIGlkLlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqL1xuXHRnZXRJZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzdXJmYWNlIHRyYW5zaXRpb24gZnVuY3Rpb24uXG5cdCAqIFNlZSA8Y29kZT5TdXJmYWNlLmRlZmF1bHRUcmFuc2l0aW9uPC9jb2RlPi5cblx0ICogQHJldHVybiB7P0Z1bmN0aW9uPX0gVGhlIHRyYW5zaXRpb24gZnVuY3Rpb24uXG5cdCAqL1xuXHRnZXRUcmFuc2l0aW9uRm4oKSB7XG5cdFx0cmV0dXJuIHRoaXMudHJhbnNpdGlvbkZuO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIHRoZSBpZCBmb3IgdGhlIGVsZW1lbnQgdGhhdCBob2xkcyBjb250ZW50IGZvciBhIHNjcmVlbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzY3JlZW5JZCBUaGUgc2NyZWVuIGlkIHRoZSBjb250ZW50IGJlbG9uZ3MgdG9vLlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRtYWtlSWRfKHNjcmVlbklkKSB7XG5cdFx0cmV0dXJuIHRoaXMuaWQgKyAnLScgKyBzY3JlZW5JZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZiBkZWZhdWx0IGNoaWxkIGlzIG1pc3NpbmcsIHdyYXBzIHN1cmZhY2UgY29udGVudCBhcyBkZWZhdWx0IGNoaWxkLiBJZlxuXHQgKiBzdXJmYWNlIGhhdmUgc3RhdGljIGNvbnRlbnQsIG1ha2Ugc3VyZSB0byBwbGFjZSBhXG5cdCAqIDxjb2RlPnN1cmZhY2VJZC1kZWZhdWx0PC9jb2RlPiBlbGVtZW50IGluc2lkZSBzdXJmYWNlLCBvbmx5IGNvbnRlbnRzXG5cdCAqIGluc2lkZSB0aGUgZGVmYXVsdCBjaGlsZCB3aWxsIGJlIHJlcGxhY2VkIGJ5IG5hdmlnYXRpb24uXG5cdCAqL1xuXHRtYXliZVdyYXBDb250ZW50QXNEZWZhdWx0XygpIHtcblx0XHR2YXIgZWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudCgpO1xuXHRcdGlmIChlbGVtZW50ICYmICF0aGlzLmRlZmF1bHRDaGlsZCkge1xuXHRcdFx0dmFyIGZyYWdtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cdFx0XHR3aGlsZSAoZWxlbWVudC5maXJzdENoaWxkKSB7XG5cdFx0XHRcdGZyYWdtZW50LmFwcGVuZENoaWxkKGVsZW1lbnQuZmlyc3RDaGlsZCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmRlZmF1bHRDaGlsZCA9IHRoaXMuYWRkQ29udGVudChTdXJmYWNlLkRFRkFVTFQsIGZyYWdtZW50KTtcblx0XHRcdHRoaXMudHJhbnNpdGlvbihudWxsLCB0aGlzLmRlZmF1bHRDaGlsZCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHN1cmZhY2UgaWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaWRcblx0ICovXG5cdHNldElkKGlkKSB7XG5cdFx0dGhpcy5pZCA9IGlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHN1cmZhY2UgdHJhbnNpdGlvbiBmdW5jdGlvbi5cblx0ICogU2VlIDxjb2RlPlN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb248L2NvZGU+LlxuXHQgKiBAcGFyYW0gez9GdW5jdGlvbj19IHRyYW5zaXRpb25GbiBUaGUgdHJhbnNpdGlvbiBmdW5jdGlvbi5cblx0ICovXG5cdHNldFRyYW5zaXRpb25Gbih0cmFuc2l0aW9uRm4pIHtcblx0XHR0aGlzLnRyYW5zaXRpb25GbiA9IHRyYW5zaXRpb25Gbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBTaG93cyBzY3JlZW4gY29udGVudCBmcm9tIGEgc3VyZmFjZS5cblx0ICogQHBhcmFtIHtTdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQgdG8gc2hvdy5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBQYXVzZXMgdGhlIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHRzaG93KHNjcmVlbklkKSB7XG5cdFx0dmFyIGZyb20gPSB0aGlzLmFjdGl2ZUNoaWxkO1xuXHRcdHZhciB0byA9IHRoaXMuZ2V0Q2hpbGQoc2NyZWVuSWQpO1xuXHRcdGlmICghdG8pIHtcblx0XHRcdHRvID0gdGhpcy5kZWZhdWx0Q2hpbGQ7XG5cdFx0fVxuXHRcdHRoaXMuYWN0aXZlQ2hpbGQgPSB0bztcblx0XHRyZXR1cm4gdGhpcy50cmFuc2l0aW9uKGZyb20sIHRvKS50aGVuQWx3YXlzKCgpID0+IHtcblx0XHRcdGlmIChmcm9tICYmIGZyb20gIT09IHRvKSB7XG5cdFx0XHRcdGV4aXREb2N1bWVudChmcm9tKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHNjcmVlbiBjb250ZW50IGZyb20gYSBzdXJmYWNlLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQgdG8gcmVtb3ZlLlxuXHQgKi9cblx0cmVtb3ZlKHNjcmVlbklkKSB7XG5cdFx0dmFyIGNoaWxkID0gdGhpcy5nZXRDaGlsZChzY3JlZW5JZCk7XG5cdFx0aWYgKGNoaWxkKSB7XG5cdFx0XHRleGl0RG9jdW1lbnQoY2hpbGQpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqL1xuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbnZva2VzIHRoZSB0cmFuc2l0aW9uIGZ1bmN0aW9uIHNwZWNpZmllZCBvbiA8Y29kZT50cmFuc2l0aW9uPC9jb2RlPiBhdHRyaWJ1dGUuXG5cdCAqIEBwYXJhbSB7P0VsZW1lbnQ9fSBmcm9tXG5cdCAqIEBwYXJhbSB7P0VsZW1lbnQ9fSB0b1xuXHQgKiBAcmV0dXJuIHs/Q2FuY2VsbGFibGVQcm9taXNlPX0gVGhpcyBjYW4gcmV0dXJuIGEgcHJvbWlzZSwgd2hpY2ggd2lsbCBwYXVzZSB0aGVcblx0ICogICAgIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHR0cmFuc2l0aW9uKGZyb20sIHRvKSB7XG5cdFx0dmFyIHRyYW5zaXRpb25GbiA9IHRoaXMudHJhbnNpdGlvbkZuIHx8IFN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb247XG5cdFx0cmV0dXJuIENhbmNlbGxhYmxlUHJvbWlzZS5yZXNvbHZlKHRyYW5zaXRpb25Gbi5jYWxsKHRoaXMsIGZyb20sIHRvKSk7XG5cdH1cblxufVxuXG4vKipcbiAgICogSG9sZHMgdGhlIGRlZmF1bHQgc3VyZmFjZSBuYW1lLiBFbGVtZW50cyBvbiB0aGUgcGFnZSBtdXN0IGNvbnRhaW4gYSBjaGlsZFxuICAgKiBlbGVtZW50IGNvbnRhaW5pbmcgdGhlIGRlZmF1bHQgY29udGVudCwgdGhpcyBlbGVtZW50IG11c3QgYmUgYXMgZm9sbG93aW5nOlxuICAgKlxuICAgKiBFeGFtcGxlOlxuICAgKiA8Y29kZT5cbiAgICogICA8ZGl2IGlkPVwibXlzdXJmYWNlXCI+XG4gICAqICAgICA8ZGl2IGlkPVwibXlzdXJmYWNlLWRlZmF1bHRcIj5EZWZhdWx0IHN1cmZhY2UgY29udGVudC48L2Rpdj5cbiAgICogICA8L2Rpdj5cbiAgICogPC9jb2RlPlxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCBjb250ZW50IGlzIHJlbGV2YW50IGZvciB0aGUgaW5pdGlhbCBwYWdlIGNvbnRlbnQuIFdoZW4gYVxuICAgKiBzY3JlZW4gZG9lc24ndCBwcm92aWRlIGNvbnRlbnQgZm9yIHRoZSBzdXJmYWNlIHRoZSBkZWZhdWx0IGNvbnRlbnQgaXNcbiAgICogcmVzdG9yZWQgaW50byB0aGUgcGFnZS5cbiAgICpcbiAgICogQHR5cGUgeyFTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQHN0YXRpY1xuICAgKi9cblN1cmZhY2UuREVGQVVMVCA9ICdkZWZhdWx0JztcblxuLyoqXG4gKiBIb2xkcyB0aGUgZGVmYXVsdCB0cmFuc2l0aW9uIGZvciBhbGwgc3VyZmFjZXMuIEVhY2ggc3VyZmFjZSBjb3VsZCBoYXZlIGl0c1xuICogb3duIHRyYW5zaXRpb24uXG4gKlxuICogRXhhbXBsZTpcbiAqXG4gKiA8Y29kZT5cbiAqIHN1cmZhY2Uuc2V0VHJhbnNpdGlvbkZuKGZ1bmN0aW9uKGZyb20sIHRvKSB7XG4gKiAgIGlmIChmcm9tKSB7XG4gKiAgICAgZnJvbS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICogICAgIGZyb20uY2xhc3NMaXN0LnJlbW92ZSgnZmxpcHBlZCcpO1xuICogICB9XG4gKiAgIGlmICh0bykge1xuICogICAgIHRvLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICogICAgIHRvLmNsYXNzTGlzdC5hZGQoJ2ZsaXBwZWQnKTtcbiAqICAgfVxuICogICByZXR1cm4gbnVsbDtcbiAqIH0pO1xuICogPC9jb2RlPlxuICpcbiAqIEBwYXJhbSB7P0VsZW1lbnQ9fSBmcm9tIFRoZSB2aXNpYmxlIHN1cmZhY2UgZWxlbWVudC5cbiAqIEBwYXJhbSB7P0VsZW1lbnQ9fSB0byBUaGUgc3VyZmFjZSBlbGVtZW50IHRvIGJlIGZsaXBwZWQuXG4gKiBAc3RhdGljXG4gKi9cblN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb24gPSBmdW5jdGlvbihmcm9tLCB0bykge1xuXHRpZiAoZnJvbSkge1xuXHRcdGZyb20uc3R5bGUuZGlzcGxheSA9ICdub25lJztcblx0XHRmcm9tLmNsYXNzTGlzdC5yZW1vdmUoJ2ZsaXBwZWQnKTtcblx0fVxuXHRpZiAodG8pIHtcblx0XHR0by5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblx0XHR0by5jbGFzc0xpc3QuYWRkKCdmbGlwcGVkJyk7XG5cdH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IFN1cmZhY2U7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGFkZENsYXNzZXMsIGRlbGVnYXRlLCBtYXRjaCwgb24sIHJlbW92ZUNsYXNzZXMgfSBmcm9tICdtZXRhbC1kb20nO1xuaW1wb3J0IHsgYXJyYXksIGFzeW5jLCBpc0RlZkFuZE5vdE51bGwsIGlzU3RyaW5nLCBvYmplY3QgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIsIEV2ZW50SGFuZGxlciB9IGZyb20gJ21ldGFsLWV2ZW50cyc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuaW1wb3J0IGRlYm91bmNlIGZyb20gJ21ldGFsLWRlYm91bmNlJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgUm91dGUgZnJvbSAnLi4vcm91dGUvUm91dGUnO1xuaW1wb3J0IFNjcmVlbiBmcm9tICcuLi9zY3JlZW4vU2NyZWVuJztcbmltcG9ydCBTdXJmYWNlIGZyb20gJy4uL3N1cmZhY2UvU3VyZmFjZSc7XG5pbXBvcnQgVXJpIGZyb20gJ21ldGFsLXVyaSc7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi4vdXRpbHMvdXRpbHMnO1xuXG5jb25zdCBOYXZpZ2F0aW9uU3RyYXRlZ3kgPSB7XG5cdElNTUVESUFURTogJ2ltbWVkaWF0ZScsXG5cdFNDSEVEVUxFX0xBU1Q6ICdzY2hlZHVsZUxhc3QnXG59O1xuXG5jbGFzcyBBcHAgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuXG5cdC8qKlxuXHQgKiBBcHAgY2xhc3MgdGhhdCBoYW5kbGUgcm91dGVzIGFuZCBzY3JlZW5zIGxpZmVjeWNsZS5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqIEBleHRlbmRzIHtFdmVudEVtaXR0ZXJ9XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGFjdGl2ZSBzY3JlZW4uXG5cdFx0ICogQHR5cGUgez9TY3JlZW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYWN0aXZlU2NyZWVuID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBhY3RpdmUgcGF0aCBjb250YWluaW5nIHRoZSBxdWVyeSBwYXJhbWV0ZXJzLlxuXHRcdCAqIEB0eXBlIHs/c3RyaW5nfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmFjdGl2ZVBhdGggPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogQWxsb3dzIHByZXZlbnQgbmF2aWdhdGUgZnJvbSBkb20gcHJldmVudGVkIGV2ZW50LlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IHRydWVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5hbGxvd1ByZXZlbnROYXZpZ2F0ZSA9IHRydWU7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBsaW5rIGJhc2UgcGF0aC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCAnJ1xuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmJhc2VQYXRoID0gJyc7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgdmFsdWUgb2YgdGhlIGJyb3dzZXIgcGF0aCBiZWZvcmUgYSBuYXZpZ2F0aW9uIGlzIHBlcmZvcm1lZC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCB0aGUgY3VycmVudCBicm93c2VyIHBhdGguXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYnJvd3NlclBhdGhCZWZvcmVOYXZpZ2F0ZSA9IHV0aWxzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCk7XG5cblx0XHQvKipcblx0XHQgKiBDYXB0dXJlcyBzY3JvbGwgcG9zaXRpb24gZnJvbSBzY3JvbGwgZXZlbnQuXG5cdFx0ICogQHR5cGUgeyFib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IHRydWVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5jYXB0dXJlU2Nyb2xsUG9zaXRpb25Gcm9tU2Nyb2xsRXZlbnQgPSB0cnVlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGRlZmF1bHQgcGFnZSB0aXRsZS5cblx0XHQgKiBAdHlwZSB7c3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5kZWZhdWx0VGl0bGUgPSBnbG9iYWxzLmRvY3VtZW50LnRpdGxlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGZvcm0gc2VsZWN0b3IgdG8gZGVmaW5lIGZvcm1zIHRoYXQgYXJlIHJvdXRlZC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBmb3JtW2VuY3R5cGU9XCJtdWx0aXBhcnQvZm9ybS1kYXRhXCJdOm5vdChbZGF0YS1zZW5uYS1vZmZdKVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmZvcm1TZWxlY3RvciA9ICdmb3JtW2VuY3R5cGU9XCJtdWx0aXBhcnQvZm9ybS1kYXRhXCJdOm5vdChbZGF0YS1zZW5uYS1vZmZdKSc7XG5cblx0XHQvKipcblx0XHQgKiBXaGVuIGVuYWJsZWQsIHRoZSByb3V0ZSBtYXRjaGluZyBpZ25vcmVzIHF1ZXJ5IHN0cmluZyBmcm9tIHRoZSBwYXRoLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoID0gZmFsc2U7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgbGluayBzZWxlY3RvciB0byBkZWZpbmUgbGlua3MgdGhhdCBhcmUgcm91dGVkLlxuXHRcdCAqIEB0eXBlIHshc3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IGE6bm90KFtkYXRhLXNlbm5hLW9mZl0pXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMubGlua1NlbGVjdG9yID0gJ2E6bm90KFtkYXRhLXNlbm5hLW9mZl0pOm5vdChbdGFyZ2V0PVwiX2JsYW5rXCJdKSc7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgbG9hZGluZyBjc3MgY2xhc3MuXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgc2VubmEtbG9hZGluZ1xuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmxvYWRpbmdDc3NDbGFzcyA9ICdzZW5uYS1sb2FkaW5nJztcblxuXHRcdC8qKlxuXHRcdCAqIFVzaW5nIHRoZSBIaXN0b3J5IEFQSSB0byBtYW5hZ2UgeW91ciBVUkxzIGlzIGF3ZXNvbWUgYW5kLCBhcyBpdCBoYXBwZW5zLFxuXHRcdCAqIGEgY3J1Y2lhbCBmZWF0dXJlIG9mIGdvb2Qgd2ViIGFwcHMuIE9uZSBvZiBpdHMgZG93bnNpZGVzLCBob3dldmVyLCBpc1xuXHRcdCAqIHRoYXQgc2Nyb2xsIHBvc2l0aW9ucyBhcmUgc3RvcmVkIGFuZCB0aGVuLCBtb3JlIGltcG9ydGFudGx5LCByZXN0b3JlZFxuXHRcdCAqIHdoZW5ldmVyIHlvdSB0cmF2ZXJzZSB0aGUgaGlzdG9yeS4gVGhpcyBvZnRlbiBtZWFucyB1bnNpZ2h0bHkganVtcHMgYXNcblx0XHQgKiB0aGUgc2Nyb2xsIHBvc2l0aW9uIGNoYW5nZXMgYXV0b21hdGljYWxseSwgYW5kIGVzcGVjaWFsbHkgc28gaWYgeW91ciBhcHBcblx0XHQgKiBkb2VzIHRyYW5zaXRpb25zLCBvciBjaGFuZ2VzIHRoZSBjb250ZW50cyBvZiB0aGUgcGFnZSBpbiBhbnkgd2F5LlxuXHRcdCAqIFVsdGltYXRlbHkgdGhpcyBsZWFkcyB0byBhbiBob3JyaWJsZSB1c2VyIGV4cGVyaWVuY2UuIFRoZSBnb29kIG5ld3MgaXMsXG5cdFx0ICogaG93ZXZlciwgdGhhdCB0aGVyZeKAmXMgYSBwb3RlbnRpYWwgZml4OiBoaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uLlxuXHRcdCAqIGh0dHBzOi8vZGV2ZWxvcGVycy5nb29nbGUuY29tL3dlYi91cGRhdGVzLzIwMTUvMDkvaGlzdG9yeS1hcGktc2Nyb2xsLXJlc3RvcmF0aW9uXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMubmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25TdXBwb3J0ZWQgPSAoJ3Njcm9sbFJlc3RvcmF0aW9uJyBpbiBnbG9iYWxzLndpbmRvdy5oaXN0b3J5KTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gc2V0IHRvIE5hdmlnYXRpb25TdHJhdGVneS5TQ0hFRFVMRV9MQVNUIG1lYW5zIHRoYXQgdGhlIGN1cnJlbnQgbmF2aWdhdGlvblxuXHRcdCAqIGNhbm5vdCBiZSBDYW5jZWxsZWQgdG8gc3RhcnQgYW5vdGhlciBhbmQgd2lsbCBiZSBxdWV1ZWQgaW5cblx0XHQgKiBzY2hlZHVsZWROYXZpZ2F0aW9uUXVldWUuIFdoZW4gTmF2aWdhdGlvblN0cmF0ZWd5LklNTUVESUFURSBtZWFucyB0aGF0IGFsbFxuXHRcdCAqIG5hdmlnYXRpb24gd2lsbCBiZSBjYW5jZWxsZWQgdG8gc3RhcnQgYW5vdGhlci5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBpbW1lZGlhdGVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5uYXZpZ2F0aW9uU3RyYXRlZ3kgPSBOYXZpZ2F0aW9uU3RyYXRlZ3kuSU1NRURJQVRFO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hlbiBzZXQgdG8gdHJ1ZSB0aGVyZSBpcyBhIHBlbmRpbmdOYXZpZ2F0ZSB0aGF0IGhhcyBub3QgeWV0IGJlZW5cblx0XHQgKiByZXNvbHZlZCBvciByZWplY3RlZC5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmlzTmF2aWdhdGlvblBlbmRpbmcgPSBmYWxzZTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGEgZGVmZXJyZWQgd2l0aCB0aGUgY3VycmVudCBuYXZpZ2F0aW9uLlxuXHRcdCAqIEB0eXBlIHs/Q2FuY2VsbGFibGVQcm9taXNlfVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUgPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHdpbmRvdyBob3Jpem9udGFsIHNjcm9sbCBwb3NpdGlvbiB3aGVuIHRoZSBuYXZpZ2F0aW9uIHVzaW5nXG5cdFx0ICogYmFjayBvciBmb3J3YXJkIGhhcHBlbnMgdG8gYmUgcmVzdG9yZWQgYWZ0ZXIgdGhlIHN1cmZhY2VzIGFyZSB1cGRhdGVkLlxuXHRcdCAqIEB0eXBlIHshTnVtYmVyfVxuXHRcdCAqIEBkZWZhdWx0IDBcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wb3BzdGF0ZVNjcm9sbExlZnQgPSAwO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHdpbmRvdyB2ZXJ0aWNhbCBzY3JvbGwgcG9zaXRpb24gd2hlbiB0aGUgbmF2aWdhdGlvbiB1c2luZ1xuXHRcdCAqIGJhY2sgb3IgZm9yd2FyZCBoYXBwZW5zIHRvIGJlIHJlc3RvcmVkIGFmdGVyIHRoZSBzdXJmYWNlcyBhcmUgdXBkYXRlZC5cblx0XHQgKiBAdHlwZSB7IU51bWJlcn1cblx0XHQgKiBAZGVmYXVsdCAwXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucG9wc3RhdGVTY3JvbGxUb3AgPSAwO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHJlZGlyZWN0IHBhdGggY29udGFpbmluZyB0aGUgcXVlcnkgcGFyYW1ldGVycy5cblx0XHQgKiBAdHlwZSB7P3N0cmluZ31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5yZWRpcmVjdFBhdGggPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHNjcmVlbiByb3V0ZXMgY29uZmlndXJhdGlvbi5cblx0XHQgKiBAdHlwZSB7P0FycmF5fVxuXHRcdCAqIEBkZWZhdWx0IFtdXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucm91dGVzID0gW107XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBhIHF1ZXVlIHRoYXQgc3RvcmVzIGV2ZXJ5IERPTSBldmVudCB0aGF0IGNhbiBpbml0aWF0ZSBhIG5hdmlnYXRpb24uXG5cdFx0ICogQHR5cGUgeyFFdmVudH1cblx0XHQgKiBAZGVmYXVsdCBbXVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnNjaGVkdWxlZE5hdmlnYXRpb25RdWV1ZSA9IFtdO1xuXG5cdFx0LyoqXG5cdFx0ICogTWFwcyB0aGUgc2NyZWVuIGluc3RhbmNlcyBieSB0aGUgdXJsIGNvbnRhaW5pbmcgdGhlIHBhcmFtZXRlcnMuXG5cdFx0ICogQHR5cGUgez9PYmplY3R9XG5cdFx0ICogQGRlZmF1bHQge31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5zY3JlZW5zID0ge307XG5cblx0XHQvKipcblx0XHQgKiBXaGVuIHNldCB0byB0cnVlIHRoZSBmaXJzdCBlcnJvbmVvdXMgcG9wc3RhdGUgZmlyZWQgb24gcGFnZSBsb2FkIHdpbGwgYmVcblx0XHQgKiBpZ25vcmVkLCBvbmx5IGlmIDxjb2RlPmdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc3RhdGU8L2NvZGU+IGlzIGFsc29cblx0XHQgKiA8Y29kZT5udWxsPC9jb2RlPi5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnNraXBMb2FkUG9wc3RhdGUgPSBmYWxzZTtcblxuXHRcdC8qKlxuXHRcdCAqIE1hcHMgdGhhdCBpbmRleCB0aGUgc3VyZmFjZXMgaW5zdGFuY2VzIGJ5IHRoZSBzdXJmYWNlIGlkLlxuXHRcdCAqIEB0eXBlIHs/T2JqZWN0fVxuXHRcdCAqIEBkZWZhdWx0IHt9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuc3VyZmFjZXMgPSB7fTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gc2V0IHRvIHRydWUsIG1vdmVzIHRoZSBzY3JvbGwgcG9zaXRpb24gYWZ0ZXIgcG9wc3RhdGUsIG9yIHRvIHRoZVxuXHRcdCAqIHRvcCBvZiB0aGUgdmlld3BvcnQgZm9yIG5ldyBuYXZpZ2F0aW9uLiBJZiBmYWxzZSwgdGhlIGJyb3dzZXIgd2lsbFxuXHRcdCAqIHRha2UgY2FyZSBvZiBzY3JvbGwgcmVzdG9yYXRpb24uXG5cdFx0ICogQHR5cGUgeyFib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IHRydWVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy51cGRhdGVTY3JvbGxQb3NpdGlvbiA9IHRydWU7XG5cblx0XHR0aGlzLmFwcEV2ZW50SGFuZGxlcnNfID0gbmV3IEV2ZW50SGFuZGxlcigpO1xuXG5cdFx0dGhpcy5hcHBFdmVudEhhbmRsZXJzXy5hZGQoXG5cdFx0XHRvbihnbG9iYWxzLndpbmRvdywgJ3Njcm9sbCcsIGRlYm91bmNlKHRoaXMub25TY3JvbGxfLmJpbmQodGhpcyksIDEwMCkpLFxuXHRcdFx0b24oZ2xvYmFscy53aW5kb3csICdsb2FkJywgdGhpcy5vbkxvYWRfLmJpbmQodGhpcykpLFxuXHRcdFx0b24oZ2xvYmFscy53aW5kb3csICdwb3BzdGF0ZScsIHRoaXMub25Qb3BzdGF0ZV8uYmluZCh0aGlzKSlcblx0XHQpO1xuXG5cdFx0dGhpcy5vbignc3RhcnROYXZpZ2F0ZScsIHRoaXMub25TdGFydE5hdmlnYXRlXyk7XG5cdFx0dGhpcy5vbignYmVmb3JlTmF2aWdhdGUnLCB0aGlzLm9uQmVmb3JlTmF2aWdhdGVfKTtcblx0XHR0aGlzLm9uKCdiZWZvcmVOYXZpZ2F0ZScsIHRoaXMub25CZWZvcmVOYXZpZ2F0ZURlZmF1bHRfLCB0cnVlKTtcblx0XHR0aGlzLm9uKCdiZWZvcmVVbmxvYWQnLCB0aGlzLm9uQmVmb3JlVW5sb2FkRGVmYXVsdF8pO1xuXG5cdFx0dGhpcy5zZXRMaW5rU2VsZWN0b3IodGhpcy5saW5rU2VsZWN0b3IpO1xuXHRcdHRoaXMuc2V0Rm9ybVNlbGVjdG9yKHRoaXMuZm9ybVNlbGVjdG9yKTtcblxuXHRcdHRoaXMubWF5YmVPdmVybG9hZEJlZm9yZVVubG9hZF8oKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIG9uZSBvciBtb3JlIHNjcmVlbnMgdG8gdGhlIGFwcGxpY2F0aW9uLlxuXHQgKlxuXHQgKiBFeGFtcGxlOlxuXHQgKlxuXHQgKiA8Y29kZT5cblx0ICogICBhcHAuYWRkUm91dGVzKHsgcGF0aDogJy9mb28nLCBoYW5kbGVyOiBGb29TY3JlZW4gfSk7XG5cdCAqICAgb3Jcblx0ICogICBhcHAuYWRkUm91dGVzKFt7IHBhdGg6ICcvZm9vJywgaGFuZGxlcjogZnVuY3Rpb24ocm91dGUpIHsgcmV0dXJuIG5ldyBGb29TY3JlZW4oKTsgfSB9XSk7XG5cdCAqIDwvY29kZT5cblx0ICpcblx0ICogQHBhcmFtIHtPYmplY3R9IG9yIHtBcnJheX0gcm91dGVzIFNpbmdsZSBvYmplY3Qgb3IgYW4gYXJyYXkgb2Ygb2JqZWN0LlxuXHQgKiAgICAgRWFjaCBvYmplY3Qgc2hvdWxkIGNvbnRhaW4gPGNvZGU+cGF0aDwvY29kZT4gYW5kIDxjb2RlPnNjcmVlbjwvY29kZT4uXG5cdCAqICAgICBUaGUgPGNvZGU+cGF0aDwvY29kZT4gc2hvdWxkIGJlIGEgc3RyaW5nIG9yIGEgcmVnZXggdGhhdCBtYXBzIHRoZVxuXHQgKiAgICAgbmF2aWdhdGlvbiByb3V0ZSB0byBhIHNjcmVlbiBjbGFzcyBkZWZpbml0aW9uIChub3QgYW4gaW5zdGFuY2UpLCBlLmc6XG5cdCAqICAgICAgICAgPGNvZGU+eyBwYXRoOiBcIi9ob21lOnBhcmFtMVwiLCBoYW5kbGVyOiBNeVNjcmVlbiB9PC9jb2RlPlxuXHQgKiAgICAgICAgIDxjb2RlPnsgcGF0aDogL2Zvby4rLywgaGFuZGxlcjogTXlTY3JlZW4gfTwvY29kZT5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkUm91dGVzKHJvdXRlcykge1xuXHRcdGlmICghQXJyYXkuaXNBcnJheShyb3V0ZXMpKSB7XG5cdFx0XHRyb3V0ZXMgPSBbcm91dGVzXTtcblx0XHR9XG5cdFx0cm91dGVzLmZvckVhY2goKHJvdXRlKSA9PiB7XG5cdFx0XHRpZiAoIShyb3V0ZSBpbnN0YW5jZW9mIFJvdXRlKSkge1xuXHRcdFx0XHRyb3V0ZSA9IG5ldyBSb3V0ZShyb3V0ZS5wYXRoLCByb3V0ZS5oYW5kbGVyKTtcblx0XHRcdH1cblx0XHRcdHRoaXMucm91dGVzLnB1c2gocm91dGUpO1xuXHRcdH0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgb25lIG9yIG1vcmUgc3VyZmFjZXMgdG8gdGhlIGFwcGxpY2F0aW9uLlxuXHQgKiBAcGFyYW0ge1N1cmZhY2V8U3RyaW5nfEFycmF5LjxTdXJmYWNlfFN0cmluZz59IHN1cmZhY2VzXG5cdCAqICAgICBTdXJmYWNlIGVsZW1lbnQgaWQgb3Igc3VyZmFjZSBpbnN0YW5jZS4gWW91IGNhbiBhbHNvIHBhc3MgYW4gQXJyYXlcblx0ICogICAgIHdoaWNoY29udGFpbnMgc3VyZmFjZSBpbnN0YW5jZXMgb3IgaWQuIEluIGNhc2Ugb2YgSUQsIHRoZXNlIHNob3VsZCBiZVxuXHQgKiAgICAgdGhlIGlkIG9mIHN1cmZhY2UgZWxlbWVudC5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkU3VyZmFjZXMoc3VyZmFjZXMpIHtcblx0XHRpZiAoIUFycmF5LmlzQXJyYXkoc3VyZmFjZXMpKSB7XG5cdFx0XHRzdXJmYWNlcyA9IFtzdXJmYWNlc107XG5cdFx0fVxuXHRcdHN1cmZhY2VzLmZvckVhY2goKHN1cmZhY2UpID0+IHtcblx0XHRcdGlmIChpc1N0cmluZyhzdXJmYWNlKSkge1xuXHRcdFx0XHRzdXJmYWNlID0gbmV3IFN1cmZhY2Uoc3VyZmFjZSk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnN1cmZhY2VzW3N1cmZhY2UuZ2V0SWQoKV0gPSBzdXJmYWNlO1xuXHRcdH0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgaWYgY2FuIG5hdmlnYXRlIHRvIHBhdGguXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gdXJsXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRjYW5OYXZpZ2F0ZSh1cmwpIHtcblx0XHRjb25zdCB1cmkgPSB1dGlscy5pc1dlYlVyaSh1cmwpO1xuXG5cdFx0aWYgKCF1cmkpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRjb25zdCBwYXRoID0gdXRpbHMuZ2V0VXJsUGF0aCh1cmwpO1xuXG5cdFx0aWYgKCF0aGlzLmlzTGlua1NhbWVPcmlnaW5fKHVyaS5nZXRIb3N0KCkpKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnT2Zmc2l0ZSBsaW5rIGNsaWNrZWQnKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0aWYgKCF0aGlzLmlzU2FtZUJhc2VQYXRoXyhwYXRoKSkge1xuXHRcdFx0Y29uc29sZS5sb2coJ0xpbmsgY2xpY2tlZCBvdXRzaWRlIGFwcFxcJ3MgYmFzZSBwYXRoJyk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdC8vIFByZXZlbnRzIG5hdmlnYXRpb24gaWYgaXQncyBhIGhhc2ggY2hhbmdlIG9uIHRoZSBzYW1lIHVybC5cblx0XHRpZiAodXJpLmdldEhhc2goKSAmJiB1dGlscy5pc0N1cnJlbnRCcm93c2VyUGF0aChwYXRoKSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRpZiAoIXRoaXMuZmluZFJvdXRlKHBhdGgpKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnTm8gcm91dGUgZm9yICcgKyBwYXRoKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhciBzY3JlZW5zIGNhY2hlLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRjbGVhclNjcmVlbnNDYWNoZSgpIHtcblx0XHRPYmplY3Qua2V5cyh0aGlzLnNjcmVlbnMpLmZvckVhY2goKHBhdGgpID0+IHtcblx0XHRcdGlmIChwYXRoID09PSB0aGlzLmFjdGl2ZVBhdGgpIHtcblx0XHRcdFx0dGhpcy5hY3RpdmVTY3JlZW4uY2xlYXJDYWNoZSgpO1xuXHRcdFx0fSBlbHNlIGlmICghKHRoaXMuaXNOYXZpZ2F0aW9uUGVuZGluZyAmJiB0aGlzLnBlbmRpbmdOYXZpZ2F0ZS5wYXRoID09PSBwYXRoKSkge1xuXHRcdFx0XHR0aGlzLnJlbW92ZVNjcmVlbihwYXRoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXRyaWV2ZXMgb3IgY3JlYXRlIGEgc2NyZWVuIGluc3RhbmNlIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHJldHVybiB7U2NyZWVufVxuXHQgKi9cblx0Y3JlYXRlU2NyZWVuSW5zdGFuY2UocGF0aCwgcm91dGUpIHtcblx0XHRpZiAoIXRoaXMucGVuZGluZ05hdmlnYXRlICYmIHBhdGggPT09IHRoaXMuYWN0aXZlUGF0aCkge1xuXHRcdFx0Y29uc29sZS5sb2coJ0FscmVhZHkgYXQgZGVzdGluYXRpb24sIHJlZnJlc2ggbmF2aWdhdGlvbicpO1xuXHRcdFx0cmV0dXJuIHRoaXMuYWN0aXZlU2NyZWVuO1xuXHRcdH1cblx0XHQvKiBqc2hpbnQgbmV3Y2FwOiBmYWxzZSAqL1xuXHRcdHZhciBzY3JlZW4gPSB0aGlzLnNjcmVlbnNbcGF0aF07XG5cdFx0aWYgKCFzY3JlZW4pIHtcblx0XHRcdHZhciBoYW5kbGVyID0gcm91dGUuZ2V0SGFuZGxlcigpO1xuXHRcdFx0aWYgKGhhbmRsZXIgPT09IFNjcmVlbiB8fCBTY3JlZW4uaXNJbXBsZW1lbnRlZEJ5KGhhbmRsZXIucHJvdG90eXBlKSkge1xuXHRcdFx0XHRzY3JlZW4gPSBuZXcgaGFuZGxlcigpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2NyZWVuID0gaGFuZGxlcihyb3V0ZSkgfHwgbmV3IFNjcmVlbigpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc29sZS5sb2coJ0NyZWF0ZSBzY3JlZW4gZm9yIFsnICsgcGF0aCArICddIFsnICsgc2NyZWVuICsgJ10nKTtcblx0XHR9XG5cdFx0cmV0dXJuIHNjcmVlbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbikge1xuXHRcdFx0dGhpcy5yZW1vdmVTY3JlZW4odGhpcy5hY3RpdmVQYXRoKTtcblx0XHR9XG5cdFx0dGhpcy5jbGVhclNjcmVlbnNDYWNoZSgpO1xuXHRcdHRoaXMuZm9ybUV2ZW50SGFuZGxlcl8ucmVtb3ZlTGlzdGVuZXIoKTtcblx0XHR0aGlzLmxpbmtFdmVudEhhbmRsZXJfLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0dGhpcy5hcHBFdmVudEhhbmRsZXJzXy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcblx0XHRzdXBlci5kaXNwb3NlSW50ZXJuYWwoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwYXRjaGVzIHRvIHRoZSBmaXJzdCByb3V0ZSBoYW5kbGVyIHRoYXQgbWF0Y2hlcyB0aGUgY3VycmVudCBwYXRoLCBpZlxuXHQgKiBhbnkuXG5cdCAqIEByZXR1cm4ge0NhbmNlbGxhYmxlUHJvbWlzZX0gUmV0dXJucyBhIHBlbmRpbmcgcmVxdWVzdCBjYW5jZWxsYWJsZSBwcm9taXNlLlxuXHQgKi9cblx0ZGlzcGF0Y2goKSB7XG5cdFx0cmV0dXJuIHRoaXMubmF2aWdhdGUodXRpbHMuZ2V0Q3VycmVudEJyb3dzZXJQYXRoKCksIHRydWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0cyBuYXZpZ2F0aW9uIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3JlcGxhY2VIaXN0b3J5IFJlcGxhY2VzIGJyb3dzZXIgaGlzdG9yeS5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBSZXR1cm5zIGEgcGVuZGluZyByZXF1ZXN0IGNhbmNlbGxhYmxlIHByb21pc2UuXG5cdCAqL1xuXHRkb05hdmlnYXRlXyhwYXRoLCBvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHR2YXIgcm91dGUgPSB0aGlzLmZpbmRSb3V0ZShwYXRoKTtcblx0XHRpZiAoIXJvdXRlKSB7XG5cdFx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZSA9IENhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcignTm8gcm91dGUgZm9yICcgKyBwYXRoKSk7XG5cdFx0XHRyZXR1cm4gdGhpcy5wZW5kaW5nTmF2aWdhdGU7XG5cdFx0fVxuXG5cdFx0Y29uc29sZS5sb2coJ05hdmlnYXRlIHRvIFsnICsgcGF0aCArICddJyk7XG5cblx0XHR0aGlzLnN0b3BQZW5kaW5nTmF2aWdhdGVfKCk7XG5cdFx0dGhpcy5pc05hdmlnYXRpb25QZW5kaW5nID0gdHJ1ZTtcblxuXHRcdHZhciBuZXh0U2NyZWVuID0gdGhpcy5jcmVhdGVTY3JlZW5JbnN0YW5jZShwYXRoLCByb3V0ZSk7XG5cblx0XHRyZXR1cm4gdGhpcy5tYXliZVByZXZlbnREZWFjdGl2YXRlXygpXG5cdFx0XHQudGhlbigoKSA9PiB0aGlzLm1heWJlUHJldmVudEFjdGl2YXRlXyhuZXh0U2NyZWVuKSlcblx0XHRcdC50aGVuKCgpID0+IG5leHRTY3JlZW4ubG9hZChwYXRoKSlcblx0XHRcdC50aGVuKCgpID0+IHtcblx0XHRcdFx0Ly8gQXQgdGhpcyBwb2ludCB3ZSBjYW5ub3Qgc3RvcCBuYXZpZ2F0aW9uIGFuZCBhbGwgcmVjZWl2ZWRcblx0XHRcdFx0Ly8gbmF2aWdhdGUgY2FuZGlkYXRlcyB3aWxsIGJlIHF1ZXVlZCBhdCBzY2hlZHVsZWROYXZpZ2F0aW9uUXVldWUuXG5cdFx0XHRcdHRoaXMubmF2aWdhdGlvblN0cmF0ZWd5ID0gTmF2aWdhdGlvblN0cmF0ZWd5LlNDSEVEVUxFX0xBU1Q7XG5cblx0XHRcdFx0aWYgKHRoaXMuYWN0aXZlU2NyZWVuKSB7XG5cdFx0XHRcdFx0dGhpcy5hY3RpdmVTY3JlZW4uZGVhY3RpdmF0ZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMucHJlcGFyZU5hdmlnYXRlSGlzdG9yeV8ocGF0aCwgbmV4dFNjcmVlbiwgb3B0X3JlcGxhY2VIaXN0b3J5KTtcblx0XHRcdFx0dGhpcy5wcmVwYXJlTmF2aWdhdGVTdXJmYWNlc18oXG5cdFx0XHRcdFx0bmV4dFNjcmVlbixcblx0XHRcdFx0XHR0aGlzLnN1cmZhY2VzLFxuXHRcdFx0XHRcdHRoaXMuZXh0cmFjdFBhcmFtcyhyb3V0ZSwgcGF0aClcblx0XHRcdFx0KTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PiBuZXh0U2NyZWVuLmV2YWx1YXRlU3R5bGVzKHRoaXMuc3VyZmFjZXMpKVxuXHRcdFx0LnRoZW4oKCkgPT4gbmV4dFNjcmVlbi5mbGlwKHRoaXMuc3VyZmFjZXMpKVxuXHRcdFx0LnRoZW4oKCkgPT4gbmV4dFNjcmVlbi5ldmFsdWF0ZVNjcmlwdHModGhpcy5zdXJmYWNlcykpXG5cdFx0XHQudGhlbigoKSA9PiB0aGlzLm1heWJlVXBkYXRlU2Nyb2xsUG9zaXRpb25TdGF0ZV8oKSlcblx0XHRcdC50aGVuKCgpID0+IHRoaXMuc3luY1Njcm9sbFBvc2l0aW9uU3luY1RoZW5Bc3luY18oKSlcblx0XHRcdC50aGVuKCgpID0+IHRoaXMuZmluYWxpemVOYXZpZ2F0ZV8ocGF0aCwgbmV4dFNjcmVlbikpXG5cdFx0XHQudGhlbigoKSA9PiB0aGlzLm1heWJlT3ZlcmxvYWRCZWZvcmVVbmxvYWRfKCkpXG5cdFx0XHQuY2F0Y2goKHJlYXNvbikgPT4ge1xuXHRcdFx0XHR0aGlzLmlzTmF2aWdhdGlvblBlbmRpbmcgPSBmYWxzZTtcblx0XHRcdFx0dGhpcy5oYW5kbGVOYXZpZ2F0ZUVycm9yXyhwYXRoLCBuZXh0U2NyZWVuLCByZWFzb24pO1xuXHRcdFx0XHR0aHJvdyByZWFzb247XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW5BbHdheXMoKCkgPT4ge1xuXHRcdFx0XHR0aGlzLm5hdmlnYXRpb25TdHJhdGVneSA9IE5hdmlnYXRpb25TdHJhdGVneS5JTU1FRElBVEU7XG5cblx0XHRcdFx0aWYgKHRoaXMuc2NoZWR1bGVkTmF2aWdhdGlvblF1ZXVlLmxlbmd0aCkge1xuXHRcdFx0XHRcdGNvbnN0IHNjaGVkdWxlZE5hdmlnYXRpb24gPSB0aGlzLnNjaGVkdWxlZE5hdmlnYXRpb25RdWV1ZS5zaGlmdCgpO1xuXHRcdFx0XHRcdHRoaXMubWF5YmVOYXZpZ2F0ZV8oc2NoZWR1bGVkTmF2aWdhdGlvbi5ocmVmLCBzY2hlZHVsZWROYXZpZ2F0aW9uKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogRXh0cmFjdHMgcGFyYW1zIGFjY29yZGluZyB0byB0aGUgZ2l2ZW4gcGF0aCBhbmQgcm91dGUuXG5cdCAqIEBwYXJhbSB7IVJvdXRlfSByb3V0ZVxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGF0aFxuXHQgKiBAcGFyYW0geyFPYmplY3R9XG5cdCAqL1xuXHRleHRyYWN0UGFyYW1zKHJvdXRlLCBwYXRoKSB7XG5cdFx0cmV0dXJuIHJvdXRlLmV4dHJhY3RQYXJhbXModGhpcy5nZXRSb3V0ZVBhdGgocGF0aCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpbmFsaXplcyBhIHNjcmVlbiBuYXZpZ2F0aW9uLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcGFyYW0geyFTY3JlZW59IG5leHRTY3JlZW5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0ZmluYWxpemVOYXZpZ2F0ZV8ocGF0aCwgbmV4dFNjcmVlbikge1xuXHRcdG5leHRTY3JlZW4uYWN0aXZhdGUoKTtcblxuXHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbiAmJiAhdGhpcy5hY3RpdmVTY3JlZW4uaXNDYWNoZWFibGUoKSkge1xuXHRcdFx0aWYgKHRoaXMuYWN0aXZlU2NyZWVuICE9PSBuZXh0U2NyZWVuKSB7XG5cdFx0XHRcdHRoaXMucmVtb3ZlU2NyZWVuKHRoaXMuYWN0aXZlUGF0aCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5hY3RpdmVQYXRoID0gcGF0aDtcblx0XHR0aGlzLmFjdGl2ZVNjcmVlbiA9IG5leHRTY3JlZW47XG5cdFx0dGhpcy5icm93c2VyUGF0aEJlZm9yZU5hdmlnYXRlID0gdXRpbHMuZ2V0Q3VycmVudEJyb3dzZXJQYXRoV2l0aG91dEhhc2goKTtcblx0XHR0aGlzLnNjcmVlbnNbcGF0aF0gPSBuZXh0U2NyZWVuO1xuXHRcdHRoaXMuaXNOYXZpZ2F0aW9uUGVuZGluZyA9IGZhbHNlO1xuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gbnVsbDtcblx0XHRnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQgPSBudWxsO1xuXHRcdGdsb2JhbHMuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCA9IG51bGw7XG5cdFx0Y29uc29sZS5sb2coJ05hdmlnYXRpb24gZG9uZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpbmRzIGEgcm91dGUgZm9yIHRoZSB0ZXN0IHBhdGguIFJldHVybnMgdHJ1ZSBpZiBtYXRjaGVzIGhhcyBhIHJvdXRlLFxuXHQgKiBvdGhlcndpc2UgcmV0dXJucyBudWxsLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcmV0dXJuIHs/T2JqZWN0fSBSb3V0ZSBoYW5kbGVyIGlmIG1hdGNoIGFueSBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiB0aGVcblx0ICogICAgIHBhdGggaXMgdGhlIHNhbWUgYXMgdGhlIGN1cnJlbnQgdXJsIGFuZCB0aGUgcGF0aCBjb250YWlucyBhIGZyYWdtZW50LlxuXHQgKi9cblx0ZmluZFJvdXRlKHBhdGgpIHtcblx0XHRwYXRoID0gdGhpcy5nZXRSb3V0ZVBhdGgocGF0aCk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnJvdXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIHJvdXRlID0gdGhpcy5yb3V0ZXNbaV07XG5cdFx0XHRpZiAocm91dGUubWF0Y2hlc1BhdGgocGF0aCkpIHtcblx0XHRcdFx0cmV0dXJuIHJvdXRlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYWxsb3cgcHJldmVudCBuYXZpZ2F0ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldEFsbG93UHJldmVudE5hdmlnYXRlKCkge1xuXHRcdHJldHVybiB0aGlzLmFsbG93UHJldmVudE5hdmlnYXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgbGluayBiYXNlIHBhdGguXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqL1xuXHRnZXRCYXNlUGF0aCgpIHtcblx0XHRyZXR1cm4gdGhpcy5iYXNlUGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBkZWZhdWx0IHBhZ2UgdGl0bGUuXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gZGVmYXVsdFRpdGxlXG5cdCAqL1xuXHRnZXREZWZhdWx0VGl0bGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZGVmYXVsdFRpdGxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGZvcm0gc2VsZWN0b3IuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqL1xuXHRnZXRGb3JtU2VsZWN0b3IoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZm9ybVNlbGVjdG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrIGlmIHJvdXRlIG1hdGNoaW5nIGlzIGlnbm9yaW5nIHF1ZXJ5IHN0cmluZyBmcm9tIHRoZSByb3V0ZSBwYXRoLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0Z2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKCkge1xuXHRcdHJldHVybiB0aGlzLmlnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBsaW5rIHNlbGVjdG9yLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKi9cblx0Z2V0TGlua1NlbGVjdG9yKCkge1xuXHRcdHJldHVybiB0aGlzLmxpbmtTZWxlY3Rvcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBsb2FkaW5nIGNzcyBjbGFzcy5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICovXG5cdGdldExvYWRpbmdDc3NDbGFzcygpIHtcblx0XHRyZXR1cm4gdGhpcy5sb2FkaW5nQ3NzQ2xhc3M7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgZ2l2ZW4gcGF0aCBmb3JtYXR0ZWQgdG8gYmUgbWF0Y2hlZCBieSBhIHJvdXRlLiBUaGlzIHdpbGwsXG5cdCAqIGZvciBleGFtcGxlLCByZW1vdmUgdGhlIGJhc2UgcGF0aCBmcm9tIGl0LCBidXQgbWFrZSBzdXJlIGl0IHdpbGwgZW5kXG5cdCAqIHdpdGggYSAnLycuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldFJvdXRlUGF0aChwYXRoKSB7XG5cdFx0aWYgKHRoaXMuZ2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKCkpIHtcblx0XHRcdHBhdGggPSB1dGlscy5nZXRVcmxQYXRoV2l0aG91dEhhc2hBbmRTZWFyY2gocGF0aCk7XG5cdFx0XHRyZXR1cm4gdXRpbHMuZ2V0VXJsUGF0aFdpdGhvdXRIYXNoQW5kU2VhcmNoKHBhdGguc3Vic3RyKHRoaXMuYmFzZVBhdGgubGVuZ3RoKSk7XG5cdFx0fVxuXG5cdFx0cGF0aCA9IHV0aWxzLmdldFVybFBhdGhXaXRob3V0SGFzaChwYXRoKTtcblx0XHRyZXR1cm4gdXRpbHMuZ2V0VXJsUGF0aFdpdGhvdXRIYXNoKHBhdGguc3Vic3RyKHRoaXMuYmFzZVBhdGgubGVuZ3RoKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgdXBkYXRlIHNjcm9sbCBwb3NpdGlvbiB2YWx1ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldFVwZGF0ZVNjcm9sbFBvc2l0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLnVwZGF0ZVNjcm9sbFBvc2l0aW9uO1xuXHR9XG5cblx0LyoqXG5cdCAqIEhhbmRsZSBuYXZpZ2F0aW9uIGVycm9yLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcGFyYW0geyFTY3JlZW59IG5leHRTY3JlZW5cblx0ICogQHBhcmFtIHshRXJyb3J9IGVycm9yXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGhhbmRsZU5hdmlnYXRlRXJyb3JfKHBhdGgsIG5leHRTY3JlZW4sIGVycm9yKSB7XG5cdFx0Y29uc29sZS5sb2coJ05hdmlnYXRpb24gZXJyb3IgZm9yIFsnICsgbmV4dFNjcmVlbiArICddICgnICsgZXJyb3Iuc3RhY2sgKyAnKScpO1xuXHRcdHRoaXMuZW1pdCgnbmF2aWdhdGlvbkVycm9yJywge1xuXHRcdFx0ZXJyb3IsXG5cdFx0XHRuZXh0U2NyZWVuLFxuXHRcdFx0cGF0aFxuXHRcdH0pO1xuXHRcdGlmICghdXRpbHMuaXNDdXJyZW50QnJvd3NlclBhdGgocGF0aCkpIHtcblx0XHRcdGlmICh0aGlzLmlzTmF2aWdhdGlvblBlbmRpbmcgJiYgdGhpcy5wZW5kaW5nTmF2aWdhdGUpIHtcblx0XHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUudGhlbkFsd2F5cygoKSA9PiB0aGlzLnJlbW92ZVNjcmVlbihwYXRoKSwgdGhpcyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnJlbW92ZVNjcmVlbihwYXRoKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIGFwcCBoYXMgcm91dGVzLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0aGFzUm91dGVzKCkge1xuXHRcdHJldHVybiB0aGlzLnJvdXRlcy5sZW5ndGggPiAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRlc3RzIGlmIGhvc3QgaXMgYW4gb2Zmc2l0ZSBsaW5rLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IGhvc3QgTGluayBob3N0IHRvIGNvbXBhcmUgd2l0aFxuXHQgKiAgICAgPGNvZGU+Z2xvYmFscy53aW5kb3cubG9jYXRpb24uaG9zdDwvY29kZT4uXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGlzTGlua1NhbWVPcmlnaW5fKGhvc3QpIHtcblx0XHRjb25zdCBob3N0VXJpID0gbmV3IFVyaShob3N0KTtcblx0XHRjb25zdCBsb2NhdGlvbkhvc3RVcmkgPSBuZXcgVXJpKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhvc3QpO1xuXG5cdFx0cmV0dXJuIGhvc3RVcmkuZ2V0UG9ydCgpID09PSBsb2NhdGlvbkhvc3RVcmkuZ2V0UG9ydCgpICYmIGhvc3RVcmkuZ2V0SG9zdG5hbWUoKSA9PT0gbG9jYXRpb25Ib3N0VXJpLmdldEhvc3RuYW1lKCk7XG5cdH1cblxuXHQvKipcblx0ICogVGVzdHMgaWYgbGluayBlbGVtZW50IGhhcyB0aGUgc2FtZSBhcHAncyBiYXNlIHBhdGguXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBMaW5rIHBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0aXNTYW1lQmFzZVBhdGhfKHBhdGgpIHtcblx0XHRyZXR1cm4gcGF0aC5pbmRleE9mKHRoaXMuYmFzZVBhdGgpID09PSAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIExvY2sgdGhlIGRvY3VtZW50IHNjcm9sbCBpbiBvcmRlciB0byBhdm9pZCB0aGUgYnJvd3NlciBuYXRpdmUgYmFjayBhbmRcblx0ICogZm9yd2FyZCBuYXZpZ2F0aW9uIHRvIGNoYW5nZSB0aGUgc2Nyb2xsIHBvc2l0aW9uLiBJbiB0aGUgZW5kIG9mXG5cdCAqIG5hdmlnYXRpb24gbGlmZWN5Y2xlIHNjcm9sbCBpcyByZXBvc2l0aW9uZWQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGxvY2tIaXN0b3J5U2Nyb2xsUG9zaXRpb25fKCkge1xuXHRcdHZhciBzdGF0ZSA9IGdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc3RhdGU7XG5cdFx0aWYgKCFzdGF0ZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvLyBCcm93c2VycyBhcmUgaW5jb25zaXN0ZW50IHdoZW4gcmUtcG9zaXRpb25pbmcgdGhlIHNjcm9sbCBoaXN0b3J5IG9uXG5cdFx0Ly8gcG9wc3RhdGUuIEF0IHNvbWUgYnJvd3NlcnMsIGhpc3Rvcnkgc2Nyb2xsIGhhcHBlbnMgYmVmb3JlIHBvcHN0YXRlLCB0aGVuXG5cdFx0Ly8gbG9jayB0aGUgc2Nyb2xsIG9uIHRoZSBsYXN0IGtub3duIHBvc2l0aW9uIGFzIHNvb24gYXMgcG9zc2libGUgYWZ0ZXIgdGhlXG5cdFx0Ly8gY3VycmVudCBKUyBleGVjdXRpb24gY29udGV4dCBhbmQgY2FwdHVyZSB0aGUgY3VycmVudCB2YWx1ZS4gU29tZSBvdGhlcnMsXG5cdFx0Ly8gaGlzdG9yeSBzY3JvbGwgaGFwcGVucyBhZnRlciBwb3BzdGF0ZSwgaW4gdGhpcyBjYXNlLCB3ZSBiaW5kIGFuIG9uY2Vcblx0XHQvLyBzY3JvbGwgZXZlbnQgdG8gbG9jayB0aGUgbGFzIGtub3duIHBvc2l0aW9uLiBMYXN0bHksIHRoZSBwcmV2aW91cyB0d29cblx0XHQvLyBiZWhhdmlvcnMgY2FuIGhhcHBlbiBldmVuIG9uIHRoZSBzYW1lIGJyb3dzZXIsIGhlbmNlIHRoZSByYWNlIHdpbGwgZGVjaWRlXG5cdFx0Ly8gdGhlIHdpbm5lci5cblx0XHR2YXIgd2lubmVyID0gZmFsc2U7XG5cdFx0dmFyIHN3aXRjaFNjcm9sbFBvc2l0aW9uUmFjZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0Z2xvYmFscy5kb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBzd2l0Y2hTY3JvbGxQb3NpdGlvblJhY2UsIGZhbHNlKTtcblx0XHRcdGlmICghd2lubmVyKSB7XG5cdFx0XHRcdGdsb2JhbHMud2luZG93LnNjcm9sbFRvKHN0YXRlLnNjcm9sbExlZnQsIHN0YXRlLnNjcm9sbFRvcCk7XG5cdFx0XHRcdHdpbm5lciA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRhc3luYy5uZXh0VGljayhzd2l0Y2hTY3JvbGxQb3NpdGlvblJhY2UpO1xuXHRcdGdsb2JhbHMuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgc3dpdGNoU2Nyb2xsUG9zaXRpb25SYWNlLCBmYWxzZSk7XG5cdH1cblxuXHQvKipcblx0ICogSWYgc3VwcG9ydGVkIGJ5IHRoZSBicm93c2VyLCBkaXNhYmxlcyBuYXRpdmUgc2Nyb2xsIHJlc3RvcmF0aW9uIGFuZFxuXHQgKiBzdG9yZXMgY3VycmVudCB2YWx1ZS5cblx0ICovXG5cdG1heWJlRGlzYWJsZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uKCkge1xuXHRcdGlmICh0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uU3VwcG9ydGVkKSB7XG5cdFx0XHR0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uXyA9IGdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc2Nyb2xsUmVzdG9yYXRpb247XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uID0gJ21hbnVhbCc7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gZXZhbHVhdGUgaWYgaXMgcG9zc2libGUgdG8gcXVldWUgcmVjZWl2ZWRcblx0ICogIGRvbSBldmVudCB0byBzY2hlZHVsZU5hdmlnYXRpb25RdWV1ZSBhbmQgZW5xdWV1ZSBpdC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGhyZWYgSW5mb3JtYXRpb24gYWJvdXQgdGhlIGxpbmsncyBocmVmLlxuXHQgKiBAcGFyYW0ge0V2ZW50fSBldmVudCBEb20gZXZlbnQgdGhhdCBpbml0aWF0ZWQgdGhlIG5hdmlnYXRpb24uXG5cdCAqL1xuXHRtYXliZVNjaGVkdWxlTmF2aWdhdGlvbl8oaHJlZiwgZXZlbnQpIHtcblx0XHRpZiAodGhpcy5pc05hdmlnYXRpb25QZW5kaW5nICYmIHRoaXMubmF2aWdhdGlvblN0cmF0ZWd5ID09PSBOYXZpZ2F0aW9uU3RyYXRlZ3kuU0NIRURVTEVfTEFTVCkge1xuXHRcdFx0dGhpcy5zY2hlZHVsZWROYXZpZ2F0aW9uUXVldWUgPSBbb2JqZWN0Lm1peGluKHtcblx0XHRcdFx0aHJlZixcblx0XHRcdFx0aXNTY2hlZHVsZWROYXZpZ2F0aW9uOiB0cnVlXG5cdFx0XHR9LCBldmVudCldO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBuYXZpZ2F0ZSB0byBhIHBhdGguXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBocmVmIEluZm9ybWF0aW9uIGFib3V0IHRoZSBsaW5rJ3MgaHJlZi5cblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnQgRG9tIGV2ZW50IHRoYXQgaW5pdGlhdGVkIHRoZSBuYXZpZ2F0aW9uLlxuXHQgKi9cblx0bWF5YmVOYXZpZ2F0ZV8oaHJlZiwgZXZlbnQpIHtcblx0XHRpZiAoIXRoaXMuY2FuTmF2aWdhdGUoaHJlZikpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCBpc05hdmlnYXRpb25TY2hlZHVsZWQgPSB0aGlzLm1heWJlU2NoZWR1bGVOYXZpZ2F0aW9uXyhocmVmLCBldmVudCk7XG5cblx0XHRpZiAoaXNOYXZpZ2F0aW9uU2NoZWR1bGVkKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBuYXZpZ2F0ZUZhaWxlZCA9IGZhbHNlO1xuXHRcdHRyeSB7XG5cdFx0XHR0aGlzLm5hdmlnYXRlKHV0aWxzLmdldFVybFBhdGgoaHJlZiksIGZhbHNlLCBldmVudCk7XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHQvLyBEbyBub3QgcHJldmVudCBsaW5rIG5hdmlnYXRpb24gaW4gY2FzZSBzb21lIHN5bmNocm9ub3VzIGVycm9yIG9jY3Vyc1xuXHRcdFx0bmF2aWdhdGVGYWlsZWQgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICghbmF2aWdhdGVGYWlsZWQgJiYgIWV2ZW50LmlzU2NoZWR1bGVkTmF2aWdhdGlvbikge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIHdoZXRoZXIgdGhlIG9uYmVmb3JldW5sb2FkIGdsb2JhbCBldmVudCBoYW5kbGVyIGlzIG92ZXJsb2FkZWRcblx0ICogYnkgY2xpZW50IGNvZGUuIElmIHNvLCBpdCByZXBsYWNlcyB3aXRoIGEgZnVuY3Rpb24gdGhhdCBoYWx0cyB0aGUgbm9ybWFsXG5cdCAqIGV2ZW50IGZsb3cgaW4gcmVsYXRpb24gd2l0aCB0aGUgY2xpZW50IG9uYmVmb3JldW5sb2FkIGZ1bmN0aW9uLlxuXHQgKiBUaGlzIGNhbiBiZSBpbiBtb3N0IHBhcnQgdXNlZCB0byBwcmVtYXR1cmVseSB0ZXJtaW5hdGUgbmF2aWdhdGlvbiB0byBvdGhlciBwYWdlc1xuXHQgKiBhY2NvcmRpbmcgdG8gdGhlIGdpdmVuIGNvbnN0cmFpdChzKS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0bWF5YmVPdmVybG9hZEJlZm9yZVVubG9hZF8oKSB7XG5cdFx0aWYgKCdmdW5jdGlvbicgPT09IHR5cGVvZiB3aW5kb3cub25iZWZvcmV1bmxvYWQpIHtcblx0XHRcdHdpbmRvdy5fb25iZWZvcmV1bmxvYWQgPSB3aW5kb3cub25iZWZvcmV1bmxvYWQ7XG5cblx0XHRcdHdpbmRvdy5vbmJlZm9yZXVubG9hZCA9IGV2ZW50ID0+IHtcblx0XHRcdFx0dGhpcy5lbWl0KCdiZWZvcmVVbmxvYWQnLCBldmVudCk7XG5cdFx0XHRcdGlmIChldmVudCAmJiBldmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cblx0XHRcdC8vIG1hcmsgdGhlIHVwZGF0ZWQgaGFuZGxlciBkdWUgdW53YW50ZWQgcmVjdXJzaW9uXG5cdFx0XHR3aW5kb3cub25iZWZvcmV1bmxvYWQuX292ZXJsb2FkZWQgPSB0cnVlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDYW5jZWxzIG5hdmlnYXRpb24gaWYgbmV4dFNjcmVlbidzIGJlZm9yZUFjdGl2YXRlIGxpZmVjeWNsZSBtZXRob2Rcblx0ICogcmVzb2x2ZXMgdG8gdHJ1ZS5cblx0ICogQHBhcmFtIHshU2NyZWVufSBuZXh0U2NyZWVuXG5cdCAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2V9XG5cdCAqL1xuXHRtYXliZVByZXZlbnRBY3RpdmF0ZV8obmV4dFNjcmVlbikge1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdHJldHVybiBuZXh0U2NyZWVuLmJlZm9yZUFjdGl2YXRlKCk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4ocHJldmVudCA9PiB7XG5cdFx0XHRcdGlmIChwcmV2ZW50KSB7XG5cdFx0XHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUgPSBDYW5jZWxsYWJsZVByb21pc2UucmVqZWN0KG5ldyBDYW5jZWxsYWJsZVByb21pc2UuQ2FuY2VsbGF0aW9uRXJyb3IoJ0NhbmNlbGxlZCBieSBuZXh0IHNjcmVlbicpKTtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5wZW5kaW5nTmF2aWdhdGU7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbmNlbHMgbmF2aWdhdGlvbiBpZiBhY3RpdmVTY3JlZW4ncyBiZWZvcmVEZWFjdGl2YXRlIGxpZmVjeWNsZVxuXHQgKiBtZXRob2QgcmVzb2x2ZXMgdG8gdHJ1ZS5cblx0ICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZX1cblx0ICovXG5cdG1heWJlUHJldmVudERlYWN0aXZhdGVfKCkge1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbikge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLmFjdGl2ZVNjcmVlbi5iZWZvcmVEZWFjdGl2YXRlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pXG5cdFx0XHQudGhlbihwcmV2ZW50ID0+IHtcblx0XHRcdFx0aWYgKHByZXZlbnQpIHtcblx0XHRcdFx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZSA9IENhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcignQ2FuY2VsbGVkIGJ5IGFjdGl2ZSBzY3JlZW4nKSk7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXMucGVuZGluZ05hdmlnYXRlO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSByZXBvc2l0aW9uIHNjcm9sbCB0byBoYXNoZWQgYW5jaG9yLlxuXHQgKi9cblx0bWF5YmVSZXBvc2l0aW9uU2Nyb2xsVG9IYXNoZWRBbmNob3IoKSB7XG5cdFx0Y29uc3QgaGFzaCA9IGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdFx0aWYgKGhhc2gpIHtcblx0XHRcdGxldCBhbmNob3JFbGVtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChoYXNoLnN1YnN0cmluZygxKSk7XG5cdFx0XHRpZiAoYW5jaG9yRWxlbWVudCkge1xuXHRcdFx0XHRjb25zdCB7b2Zmc2V0TGVmdCwgb2Zmc2V0VG9wfSA9IHV0aWxzLmdldE5vZGVPZmZzZXQoYW5jaG9yRWxlbWVudCk7XG5cdFx0XHRcdGdsb2JhbHMud2luZG93LnNjcm9sbFRvKG9mZnNldExlZnQsIG9mZnNldFRvcCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIElmIHN1cHBvcnRlZCBieSB0aGUgYnJvd3NlciwgcmVzdG9yZXMgbmF0aXZlIHNjcm9sbCByZXN0b3JhdGlvbiB0byB0aGVcblx0ICogdmFsdWUgY2FwdHVyZWQgYnkgYG1heWJlRGlzYWJsZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uYC5cblx0ICovXG5cdG1heWJlUmVzdG9yZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uKCkge1xuXHRcdGlmICh0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uU3VwcG9ydGVkICYmIHRoaXMubmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25fKSB7XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uID0gdGhpcy5uYXRpdmVTY3JvbGxSZXN0b3JhdGlvbl87XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHJlc3RvcmUgcmVkaXJlY3RlZCBwYXRoIGhhc2ggaW4gY2FzZSBib3RoIHRoZSBjdXJyZW50IHBhdGggYW5kXG5cdCAqIHRoZSBnaXZlbiBwYXRoIGFyZSB0aGUgc2FtZS5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggYmVmb3JlIG5hdmlnYXRpb24uXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcmVkaXJlY3RQYXRoIFBhdGggYWZ0ZXIgbmF2aWdhdGlvbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBoYXNoIEhhc2ggdG8gYmUgYWRkZWQgdG8gdGhlIHBhdGguXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9IFJldHVybnMgdGhlIHBhdGggd2l0aCB0aGUgaGFzaCByZXN0b3JlZC5cblx0ICovXG5cdG1heWJlUmVzdG9yZVJlZGlyZWN0UGF0aEhhc2hfKHBhdGgsIHJlZGlyZWN0UGF0aCwgaGFzaCkge1xuXHRcdGlmIChyZWRpcmVjdFBhdGggPT09IHV0aWxzLmdldFVybFBhdGhXaXRob3V0SGFzaChwYXRoKSkge1xuXHRcdFx0cmV0dXJuIHJlZGlyZWN0UGF0aCArIGhhc2g7XG5cdFx0fVxuXHRcdHJldHVybiByZWRpcmVjdFBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogTWF5YmUgdXBkYXRlIHNjcm9sbCBwb3NpdGlvbiBpbiBoaXN0b3J5IHN0YXRlIHRvIGFuY2hvciBvbiBwYXRoLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIGFuY2hvclxuXHQgKi9cblx0bWF5YmVVcGRhdGVTY3JvbGxQb3NpdGlvblN0YXRlXygpIHtcblx0XHR2YXIgaGFzaCA9IGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdFx0dmFyIGFuY2hvckVsZW1lbnQgPSBnbG9iYWxzLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGhhc2guc3Vic3RyaW5nKDEpKTtcblx0XHRpZiAoYW5jaG9yRWxlbWVudCkge1xuXHRcdFx0Y29uc3Qge29mZnNldExlZnQsIG9mZnNldFRvcH0gPSB1dGlscy5nZXROb2RlT2Zmc2V0KGFuY2hvckVsZW1lbnQpO1xuXHRcdFx0dGhpcy5zYXZlSGlzdG9yeUN1cnJlbnRQYWdlU2Nyb2xsUG9zaXRpb25fKG9mZnNldFRvcCwgb2Zmc2V0TGVmdCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE5hdmlnYXRlcyB0byB0aGUgc3BlY2lmaWVkIHBhdGggaWYgdGhlcmUgaXMgYSByb3V0ZSBoYW5kbGVyIHRoYXQgbWF0Y2hlcy5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggdG8gbmF2aWdhdGUgY29udGFpbmluZyB0aGUgYmFzZSBwYXRoLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfcmVwbGFjZUhpc3RvcnkgUmVwbGFjZXMgYnJvd3NlciBoaXN0b3J5LlxuXHQgKiBAcGFyYW0ge0V2ZW50PX0gZXZlbnQgT3B0aW9uYWwgZXZlbnQgb2JqZWN0IHRoYXQgdHJpZ2dlcmVkIHRoZSBuYXZpZ2F0aW9uLlxuXHQgKiBAcmV0dXJuIHtDYW5jZWxsYWJsZVByb21pc2V9IFJldHVybnMgYSBwZW5kaW5nIHJlcXVlc3QgY2FuY2VsbGFibGUgcHJvbWlzZS5cblx0ICovXG5cdG5hdmlnYXRlKHBhdGgsIG9wdF9yZXBsYWNlSGlzdG9yeSwgb3B0X2V2ZW50KSB7XG5cdFx0aWYgKCF1dGlscy5pc0h0bWw1SGlzdG9yeVN1cHBvcnRlZCgpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0hUTUw1IEhpc3RvcnkgaXMgbm90IHN1cHBvcnRlZC4gU2VubmEgd2lsbCBub3QgaW50ZXJjZXB0IG5hdmlnYXRpb24uJyk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdF9ldmVudCkge1xuXHRcdFx0Z2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50ID0gb3B0X2V2ZW50LmNhcHR1cmVkRm9ybUVsZW1lbnQ7XG5cdFx0XHRnbG9iYWxzLmNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQgPSBvcHRfZXZlbnQuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudDtcblx0XHR9XG5cblx0XHQvLyBXaGVuIHJlbG9hZGluZyB0aGUgc2FtZSBwYXRoIGRvIHJlcGxhY2VTdGF0ZSBpbnN0ZWFkIG9mIHB1c2hTdGF0ZSB0b1xuXHRcdC8vIGF2b2lkIHBvbGx1dGluZyBoaXN0b3J5IHdpdGggc3RhdGVzIHdpdGggdGhlIHNhbWUgcGF0aC5cblx0XHRpZiAocGF0aCA9PT0gdGhpcy5hY3RpdmVQYXRoKSB7XG5cdFx0XHRvcHRfcmVwbGFjZUhpc3RvcnkgPSB0cnVlO1xuXHRcdH1cblxuXHRcdHRoaXMuZW1pdCgnYmVmb3JlTmF2aWdhdGUnLCB7XG5cdFx0XHRldmVudDogb3B0X2V2ZW50LFxuXHRcdFx0cGF0aDogcGF0aCxcblx0XHRcdHJlcGxhY2VIaXN0b3J5OiAhIW9wdF9yZXBsYWNlSGlzdG9yeVxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIHRoaXMucGVuZGluZ05hdmlnYXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEJlZm9yZXMgbmF2aWdhdGlvbiB0byBhIHBhdGguXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBFdmVudCBmYWNhZGUgY29udGFpbmluZyA8Y29kZT5wYXRoPC9jb2RlPiBhbmRcblx0ICogICAgIDxjb2RlPnJlcGxhY2VIaXN0b3J5PC9jb2RlPi5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25CZWZvcmVOYXZpZ2F0ZV8oZXZlbnQpIHtcblx0XHRpZiAoZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50KSB7XG5cdFx0XHRldmVudC5mb3JtID0gZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50O1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBCZWZvcmVzIG5hdmlnYXRpb24gdG8gYSBwYXRoLiBSdW5zIGFmdGVyIGV4dGVybmFsIGxpc3RlbmVycy5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZSBjb250YWluaW5nIDxjb2RlPnBhdGg8L2NvZGU+IGFuZFxuXHQgKiAgICAgPGNvZGU+cmVwbGFjZUhpc3Rvcnk8L2NvZGU+LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvbkJlZm9yZU5hdmlnYXRlRGVmYXVsdF8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5wZW5kaW5nTmF2aWdhdGUpIHtcblx0XHRcdGlmICh0aGlzLnBlbmRpbmdOYXZpZ2F0ZS5wYXRoID09PSBldmVudC5wYXRoIHx8IHRoaXMubmF2aWdhdGlvblN0cmF0ZWd5ID09PSBOYXZpZ2F0aW9uU3RyYXRlZ3kuU0NIRURVTEVfTEFTVCkge1xuXHRcdFx0XHRjb25zb2xlLmxvZygnV2FpdGluZy4uLicpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5lbWl0KCdiZWZvcmVVbmxvYWQnLCBldmVudCk7XG5cblx0XHR0aGlzLmVtaXQoJ3N0YXJ0TmF2aWdhdGUnLCB7XG5cdFx0XHRmb3JtOiBldmVudC5mb3JtLFxuXHRcdFx0cGF0aDogZXZlbnQucGF0aCxcblx0XHRcdHJlcGxhY2VIaXN0b3J5OiBldmVudC5yZXBsYWNlSGlzdG9yeVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEN1c3RvbSBldmVudCBoYW5kbGVyIHRoYXQgZXhlY3V0ZXMgdGhlIG9yaWdpbmFsIGxpc3RlbmVyIHRoYXQgaGFzIGJlZW5cblx0ICogYWRkZWQgYnkgdGhlIGNsaWVudCBjb2RlIGFuZCB0ZXJtaW5hdGVzIHRoZSBuYXZpZ2F0aW9uIGFjY29yZGluZ2x5LlxuXHQgKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgb3JpZ2luYWwgRXZlbnQgZmFjYWRlLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvbkJlZm9yZVVubG9hZERlZmF1bHRfKGV2ZW50KSB7XG5cdFx0dmFyIGZ1bmMgPSB3aW5kb3cuX29uYmVmb3JldW5sb2FkO1xuXHRcdGlmIChmdW5jICYmICFmdW5jLl9vdmVybG9hZGVkICYmIGZ1bmMoKSkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogSW50ZXJjZXB0cyBkb2N1bWVudCBjbGlja3MgYW5kIHRlc3QgbGluayBlbGVtZW50cyBpbiBvcmRlciB0byBkZWNpZGVcblx0ICogd2hldGhlciBTdXJmYWNlIGFwcCBjYW4gbmF2aWdhdGUuXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBFdmVudCBmYWNhZGVcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25Eb2NDbGlja0RlbGVnYXRlXyhldmVudCkge1xuXHRcdGlmIChldmVudC5hbHRLZXkgfHwgZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5IHx8IGV2ZW50LnNoaWZ0S2V5IHx8IGV2ZW50LmJ1dHRvbikge1xuXHRcdFx0Y29uc29sZS5sb2coJ05hdmlnYXRlIGFib3J0ZWQsIGludmFsaWQgbW91c2UgYnV0dG9uIG9yIG1vZGlmaWVyIGtleSBwcmVzc2VkLicpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLm1heWJlTmF2aWdhdGVfKGV2ZW50LmRlbGVnYXRlVGFyZ2V0LmhyZWYsIGV2ZW50KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbnRlcmNlcHRzIGRvY3VtZW50IGZvcm0gc3VibWl0cyBhbmQgdGVzdCBhY3Rpb24gcGF0aCBpbiBvcmRlciB0byBkZWNpZGVcblx0ICogd2hldGhlciBTdXJmYWNlIGFwcCBjYW4gbmF2aWdhdGUuXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBFdmVudCBmYWNhZGVcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25Eb2NTdWJtaXREZWxlZ2F0ZV8oZXZlbnQpIHtcblx0XHR2YXIgZm9ybSA9IGV2ZW50LmRlbGVnYXRlVGFyZ2V0O1xuXHRcdGlmIChmb3JtLm1ldGhvZCA9PT0gJ2dldCcpIHtcblx0XHRcdGNvbnNvbGUubG9nKCdHRVQgbWV0aG9kIG5vdCBzdXBwb3J0ZWQnKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0ZXZlbnQuY2FwdHVyZWRGb3JtRWxlbWVudCA9IGZvcm07XG5cdFx0Y29uc3QgYnV0dG9uU2VsZWN0b3IgPSAnYnV0dG9uOm5vdChbdHlwZV0pLGJ1dHRvblt0eXBlPXN1Ym1pdF0saW5wdXRbdHlwZT1zdWJtaXRdJztcblx0XHRpZiAobWF0Y2goZ2xvYmFscy5kb2N1bWVudC5hY3RpdmVFbGVtZW50LCBidXR0b25TZWxlY3RvcikpIHtcblx0XHRcdGV2ZW50LmNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQgPSBnbG9iYWxzLmRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGV2ZW50LmNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQgPSBmb3JtLnF1ZXJ5U2VsZWN0b3IoYnV0dG9uU2VsZWN0b3IpO1xuXHRcdH1cblx0XHR0aGlzLm1heWJlTmF2aWdhdGVfKGZvcm0uYWN0aW9uLCBldmVudCk7XG5cdH1cblxuXHQvKipcblx0ICogTGlzdGVucyB0byB0aGUgd2luZG93J3MgbG9hZCBldmVudCBpbiBvcmRlciB0byBhdm9pZCBpc3N1ZXMgd2l0aCBzb21lIGJyb3dzZXJzXG5cdCAqIHRoYXQgdHJpZ2dlciBwb3BzdGF0ZSBjYWxscyBvbiB0aGUgZmlyc3QgbG9hZC4gRm9yIG1vcmUgaW5mb3JtYXRpb24gc2VlXG5cdCAqIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjQyMTc2OS9wb3BzdGF0ZS1vbi1wYWdlcy1sb2FkLWluLWNocm9tZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25Mb2FkXygpIHtcblx0XHR0aGlzLnNraXBMb2FkUG9wc3RhdGUgPSB0cnVlO1xuXHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0Ly8gVGhlIHRpbWVvdXQgZW5zdXJlcyB0aGF0IHBvcHN0YXRlIGV2ZW50cyB3aWxsIGJlIHVuYmxvY2tlZCByaWdodFxuXHRcdFx0Ly8gYWZ0ZXIgdGhlIGxvYWQgZXZlbnQgb2NjdXJlZCwgYnV0IG5vdCBpbiB0aGUgc2FtZSBldmVudC1sb29wIGN5Y2xlLlxuXHRcdFx0dGhpcy5za2lwTG9hZFBvcHN0YXRlID0gZmFsc2U7XG5cdFx0fSwgMCk7XG5cdFx0Ly8gVHJ5IHRvIHJlcG9zaXRpb24gc2Nyb2xsIHRvIHRoZSBoYXNoZWQgYW5jaG9yIHdoZW4gcGFnZSBsb2Fkcy5cblx0XHR0aGlzLm1heWJlUmVwb3NpdGlvblNjcm9sbFRvSGFzaGVkQW5jaG9yKCk7XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlcyBicm93c2VyIGhpc3RvcnkgY2hhbmdlcyBhbmQgZmlyZXMgYXBwJ3MgbmF2aWdhdGlvbiBpZiB0aGUgc3RhdGVcblx0ICogYmVsb3dzIHRvIHVzLiBJZiB3ZSBkZXRlY3QgYSBwb3BzdGF0ZSBhbmQgdGhlIHN0YXRlIGlzIDxjb2RlPm51bGw8L2NvZGU+LFxuXHQgKiBhc3N1bWUgaXQgaXMgbmF2aWdhdGluZyB0byBhbiBleHRlcm5hbCBwYWdlIG9yIHRvIGEgcGFnZSB3ZSBkb24ndCBoYXZlXG5cdCAqIHJvdXRlLCB0aGVuIDxjb2RlPmdsb2JhbHMud2luZG93LmxvY2F0aW9uLnJlbG9hZCgpPC9jb2RlPiBpcyBpbnZva2VkIGluIG9yZGVyIHRvXG5cdCAqIHJlbG9hZCB0aGUgY29udGVudCB0byB0aGUgY3VycmVudCB1cmwuXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBFdmVudCBmYWNhZGVcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25Qb3BzdGF0ZV8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5za2lwTG9hZFBvcHN0YXRlKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gRG8gbm90IG5hdmlnYXRlIGlmIHRoZSBwb3BzdGF0ZSB3YXMgdHJpZ2dlcmVkIGJ5IGEgaGFzaCBjaGFuZ2UuXG5cdFx0aWYgKHV0aWxzLmlzQ3VycmVudEJyb3dzZXJQYXRoKHRoaXMuYnJvd3NlclBhdGhCZWZvcmVOYXZpZ2F0ZSkpIHtcblx0XHRcdHRoaXMubWF5YmVSZXBvc2l0aW9uU2Nyb2xsVG9IYXNoZWRBbmNob3IoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgc3RhdGUgPSBldmVudC5zdGF0ZTtcblxuXHRcdGlmICghc3RhdGUpIHtcblx0XHRcdGlmIChnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5oYXNoKSB7XG5cdFx0XHRcdC8vIElmIHNlbm5hIGlzIG9uIGFuIHJlZGlyZWN0IHBhdGggYW5kIGEgaGFzaCBwb3BzdGF0ZSBoYXBwZW5zXG5cdFx0XHRcdC8vIHRvIGEgZGlmZmVyZW50IHVybCwgcmVsb2FkIHRoZSBicm93c2VyLiBUaGlzIGJlaGF2aW9yIGRvZXNuJ3Rcblx0XHRcdFx0Ly8gcmVxdWlyZSBzZW5uYSB0byByb3V0ZSBoYXNoZWQgbGlua3MgYW5kIGlzIGNsb3NlciB0byBuYXRpdmVcblx0XHRcdFx0Ly8gYnJvd3NlciBiZWhhdmlvci5cblx0XHRcdFx0aWYgKHRoaXMucmVkaXJlY3RQYXRoICYmICF1dGlscy5pc0N1cnJlbnRCcm93c2VyUGF0aCh0aGlzLnJlZGlyZWN0UGF0aCkpIHtcblx0XHRcdFx0XHR0aGlzLnJlbG9hZFBhZ2UoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHQvLyBBbHdheXMgdHJ5IHRvIHJlcG9zaXRpb24gc2Nyb2xsIHRvIHRoZSBoYXNoZWQgYW5jaG9yIHdoZW5cblx0XHRcdFx0Ly8gaGFzaCBwb3BzdGF0ZSBoYXBwZW5zLlxuXHRcdFx0XHR0aGlzLm1heWJlUmVwb3NpdGlvblNjcm9sbFRvSGFzaGVkQW5jaG9yKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnJlbG9hZFBhZ2UoKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoc3RhdGUuc2VubmEpIHtcblx0XHRcdGNvbnNvbGUubG9nKCdIaXN0b3J5IG5hdmlnYXRpb24gdG8gWycgKyBzdGF0ZS5wYXRoICsgJ10nKTtcblx0XHRcdHRoaXMucG9wc3RhdGVTY3JvbGxUb3AgPSBzdGF0ZS5zY3JvbGxUb3A7XG5cdFx0XHR0aGlzLnBvcHN0YXRlU2Nyb2xsTGVmdCA9IHN0YXRlLnNjcm9sbExlZnQ7XG5cdFx0XHRpZiAoIXRoaXMubmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25TdXBwb3J0ZWQpIHtcblx0XHRcdFx0dGhpcy5sb2NrSGlzdG9yeVNjcm9sbFBvc2l0aW9uXygpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5vbmNlKCdlbmROYXZpZ2F0ZScsICgpID0+IHtcblx0XHRcdFx0aWYgKHN0YXRlLnJlZmVycmVyKSB7XG5cdFx0XHRcdFx0dXRpbHMuc2V0UmVmZXJyZXIoc3RhdGUucmVmZXJyZXIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdGNvbnN0IHVyaSA9IG5ldyBVcmkoc3RhdGUucGF0aCk7XG5cdFx0XHR1cmkuc2V0SG9zdG5hbWUoZ2xvYmFscy53aW5kb3cubG9jYXRpb24uaG9zdG5hbWUpO1xuXHRcdFx0dXJpLnNldFBvcnQoZ2xvYmFscy53aW5kb3cubG9jYXRpb24ucG9ydCk7XG5cdFx0XHRjb25zdCBpc05hdmlnYXRpb25TY2hlZHVsZWQgPSB0aGlzLm1heWJlU2NoZWR1bGVOYXZpZ2F0aW9uXyh1cmkudG9TdHJpbmcoKSwge30pO1xuXHRcdFx0aWYgKGlzTmF2aWdhdGlvblNjaGVkdWxlZCkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHR0aGlzLm5hdmlnYXRlKHN0YXRlLnBhdGgsIHRydWUpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBMaXN0ZW5zIGRvY3VtZW50IHNjcm9sbCBjaGFuZ2VzIGluIG9yZGVyIHRvIGNhcHR1cmUgdGhlIHBvc3NpYmxlIGxvY2tcblx0ICogc2Nyb2xsIHBvc2l0aW9uIGZvciBoaXN0b3J5IHNjcm9sbGluZy5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25TY3JvbGxfKCkge1xuXHRcdGlmICh0aGlzLmNhcHR1cmVTY3JvbGxQb3NpdGlvbkZyb21TY3JvbGxFdmVudCkge1xuXHRcdFx0dGhpcy5zYXZlSGlzdG9yeUN1cnJlbnRQYWdlU2Nyb2xsUG9zaXRpb25fKGdsb2JhbHMud2luZG93LnBhZ2VZT2Zmc2V0LCBnbG9iYWxzLndpbmRvdy5wYWdlWE9mZnNldCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0cyBuYXZpZ2F0aW9uIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZSBjb250YWluaW5nIDxjb2RlPnBhdGg8L2NvZGU+IGFuZFxuXHQgKiAgICAgPGNvZGU+cmVwbGFjZUhpc3Rvcnk8L2NvZGU+LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvblN0YXJ0TmF2aWdhdGVfKGV2ZW50KSB7XG5cdFx0dGhpcy5tYXliZURpc2FibGVOYXRpdmVTY3JvbGxSZXN0b3JhdGlvbigpO1xuXHRcdHRoaXMuY2FwdHVyZVNjcm9sbFBvc2l0aW9uRnJvbVNjcm9sbEV2ZW50ID0gZmFsc2U7XG5cdFx0YWRkQ2xhc3NlcyhnbG9iYWxzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgdGhpcy5sb2FkaW5nQ3NzQ2xhc3MpO1xuXG5cdFx0dmFyIGVuZE5hdmlnYXRlUGF5bG9hZCA9IHtcblx0XHRcdGZvcm06IGV2ZW50LmZvcm0sXG5cdFx0XHRwYXRoOiBldmVudC5wYXRoXG5cdFx0fTtcblxuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gdGhpcy5kb05hdmlnYXRlXyhldmVudC5wYXRoLCBldmVudC5yZXBsYWNlSGlzdG9yeSlcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdGVuZE5hdmlnYXRlUGF5bG9hZC5lcnJvciA9IHJlYXNvbjtcblx0XHRcdFx0dGhyb3cgcmVhc29uO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuQWx3YXlzKCgpID0+IHtcblx0XHRcdFx0aWYgKCF0aGlzLnBlbmRpbmdOYXZpZ2F0ZSAmJiAhdGhpcy5zY2hlZHVsZWROYXZpZ2F0aW9uUXVldWUubGVuZ3RoKSB7XG5cdFx0XHRcdFx0cmVtb3ZlQ2xhc3NlcyhnbG9iYWxzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgdGhpcy5sb2FkaW5nQ3NzQ2xhc3MpO1xuXHRcdFx0XHRcdHRoaXMubWF5YmVSZXN0b3JlTmF0aXZlU2Nyb2xsUmVzdG9yYXRpb24oKTtcblx0XHRcdFx0XHR0aGlzLmNhcHR1cmVTY3JvbGxQb3NpdGlvbkZyb21TY3JvbGxFdmVudCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5lbWl0KCdlbmROYXZpZ2F0ZScsIGVuZE5hdmlnYXRlUGF5bG9hZCk7XG5cdFx0XHR9KTtcblxuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlLnBhdGggPSBldmVudC5wYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByZWZldGNoZXMgdGhlIHNwZWNpZmllZCBwYXRoIGlmIHRoZXJlIGlzIGEgcm91dGUgaGFuZGxlciB0aGF0IG1hdGNoZXMuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIHRvIG5hdmlnYXRlIGNvbnRhaW5pbmcgdGhlIGJhc2UgcGF0aC5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBSZXR1cm5zIGEgcGVuZGluZyByZXF1ZXN0IGNhbmNlbGxhYmxlIHByb21pc2UuXG5cdCAqL1xuXHRwcmVmZXRjaChwYXRoKSB7XG5cdFx0dmFyIHJvdXRlID0gdGhpcy5maW5kUm91dGUocGF0aCk7XG5cdFx0aWYgKCFyb3V0ZSkge1xuXHRcdFx0cmV0dXJuIENhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcignTm8gcm91dGUgZm9yICcgKyBwYXRoKSk7XG5cdFx0fVxuXG5cdFx0Y29uc29sZS5sb2coJ1ByZWZldGNoaW5nIFsnICsgcGF0aCArICddJyk7XG5cblx0XHR2YXIgbmV4dFNjcmVlbiA9IHRoaXMuY3JlYXRlU2NyZWVuSW5zdGFuY2UocGF0aCwgcm91dGUpO1xuXG5cdFx0cmV0dXJuIG5leHRTY3JlZW4ubG9hZChwYXRoKVxuXHRcdFx0LnRoZW4oKCkgPT4gdGhpcy5zY3JlZW5zW3BhdGhdID0gbmV4dFNjcmVlbilcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdHRoaXMuaGFuZGxlTmF2aWdhdGVFcnJvcl8ocGF0aCwgbmV4dFNjcmVlbiwgcmVhc29uKTtcblx0XHRcdFx0dGhyb3cgcmVhc29uO1xuXHRcdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUHJlcGFyZXMgc2NyZWVuIGZsaXAuIFVwZGF0ZXMgaGlzdG9yeSBzdGF0ZSBhbmQgc3VyZmFjZXMgY29udGVudC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHBhcmFtIHshU2NyZWVufSBuZXh0U2NyZWVuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9yZXBsYWNlSGlzdG9yeSBSZXBsYWNlcyBicm93c2VyIGhpc3RvcnkuXG5cdCAqL1xuXHRwcmVwYXJlTmF2aWdhdGVIaXN0b3J5XyhwYXRoLCBuZXh0U2NyZWVuLCBvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHRsZXQgdGl0bGUgPSBuZXh0U2NyZWVuLmdldFRpdGxlKCk7XG5cdFx0aWYgKCFpc1N0cmluZyh0aXRsZSkpIHtcblx0XHRcdHRpdGxlID0gdGhpcy5nZXREZWZhdWx0VGl0bGUoKTtcblx0XHR9XG5cdFx0bGV0IHJlZGlyZWN0UGF0aCA9IG5leHRTY3JlZW4uYmVmb3JlVXBkYXRlSGlzdG9yeVBhdGgocGF0aCk7XG5cdFx0Y29uc3QgaGlzdG9yeVN0YXRlID0ge1xuXHRcdFx0Zm9ybTogaXNEZWZBbmROb3ROdWxsKGdsb2JhbHMuY2FwdHVyZWRGb3JtRWxlbWVudCksXG5cdFx0XHRwYXRoLFxuXHRcdFx0cmVkaXJlY3RQYXRoLFxuXHRcdFx0c2Nyb2xsTGVmdDogMCxcblx0XHRcdHNjcm9sbFRvcDogMCxcblx0XHRcdHNlbm5hOiB0cnVlXG5cdFx0fTtcblx0XHRpZiAob3B0X3JlcGxhY2VIaXN0b3J5KSB7XG5cdFx0XHRoaXN0b3J5U3RhdGUuc2Nyb2xsVG9wID0gdGhpcy5wb3BzdGF0ZVNjcm9sbFRvcDtcblx0XHRcdGhpc3RvcnlTdGF0ZS5zY3JvbGxMZWZ0ID0gdGhpcy5wb3BzdGF0ZVNjcm9sbExlZnQ7XG5cdFx0fVxuXHRcdGNvbnN0IGhhc2ggPSBuZXcgVXJpKHBhdGgpLmdldEhhc2goKTtcblx0XHRyZWRpcmVjdFBhdGggPSB0aGlzLm1heWJlUmVzdG9yZVJlZGlyZWN0UGF0aEhhc2hfKHBhdGgsIHJlZGlyZWN0UGF0aCwgaGFzaCk7XG5cdFx0dGhpcy51cGRhdGVIaXN0b3J5Xyh0aXRsZSwgcmVkaXJlY3RQYXRoLCBuZXh0U2NyZWVuLmJlZm9yZVVwZGF0ZUhpc3RvcnlTdGF0ZShoaXN0b3J5U3RhdGUpLCBvcHRfcmVwbGFjZUhpc3RvcnkpO1xuXHRcdHRoaXMucmVkaXJlY3RQYXRoID0gcmVkaXJlY3RQYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByZXBhcmVzIHNjcmVlbiBmbGlwLiBVcGRhdGVzIGhpc3Rvcnkgc3RhdGUgYW5kIHN1cmZhY2VzIGNvbnRlbnQuXG5cdCAqIEBwYXJhbSB7IVNjcmVlbn0gbmV4dFNjcmVlblxuXHQgKiBAcGFyYW0geyFPYmplY3R9IHN1cmZhY2VzIE1hcCBvZiBzdXJmYWNlcyB0byBmbGlwIGtleWVkIGJ5IHN1cmZhY2UgaWQuXG5cdCAqIEBwYXJhbSB7IU9iamVjdH0gcGFyYW1zIFBhcmFtcyBleHRyYWN0ZWQgZnJvbSB0aGUgY3VycmVudCBwYXRoLlxuXHQgKi9cblx0cHJlcGFyZU5hdmlnYXRlU3VyZmFjZXNfKG5leHRTY3JlZW4sIHN1cmZhY2VzLCBwYXJhbXMpIHtcblx0XHRPYmplY3Qua2V5cyhzdXJmYWNlcykuZm9yRWFjaCgoaWQpID0+IHtcblx0XHRcdHZhciBzdXJmYWNlQ29udGVudCA9IG5leHRTY3JlZW4uZ2V0U3VyZmFjZUNvbnRlbnQoaWQsIHBhcmFtcyk7XG5cdFx0XHRzdXJmYWNlc1tpZF0uYWRkQ29udGVudChuZXh0U2NyZWVuLmdldElkKCksIHN1cmZhY2VDb250ZW50KTtcblx0XHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyBuZXh0U2NyZWVuLmdldElkKCkgKyAnXSBhZGQgY29udGVudCB0byBzdXJmYWNlICcgK1xuXHRcdFx0XHQnWycgKyBzdXJmYWNlc1tpZF0gKyAnXSBbJyArIChpc0RlZkFuZE5vdE51bGwoc3VyZmFjZUNvbnRlbnQpID8gJy4uLicgOiAnZW1wdHknKSArICddJyk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVsb2FkcyB0aGUgcGFnZSBieSBwZXJmb3JtaW5nIGB3aW5kb3cubG9jYXRpb24ucmVsb2FkKClgLlxuXHQgKi9cblx0cmVsb2FkUGFnZSgpIHtcblx0XHRnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHJvdXRlIGluc3RhbmNlIGZyb20gYXBwIHJvdXRlcy5cblx0ICogQHBhcmFtIHtSb3V0ZX0gcm91dGVcblx0ICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhbiBlbGVtZW50IHdhcyByZW1vdmVkLlxuXHQgKi9cblx0cmVtb3ZlUm91dGUocm91dGUpIHtcblx0XHRyZXR1cm4gYXJyYXkucmVtb3ZlKHRoaXMucm91dGVzLCByb3V0ZSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhIHNjcmVlbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICovXG5cdHJlbW92ZVNjcmVlbihwYXRoKSB7XG5cdFx0dmFyIHNjcmVlbiA9IHRoaXMuc2NyZWVuc1twYXRoXTtcblx0XHRpZiAoc2NyZWVuKSB7XG5cdFx0XHRPYmplY3Qua2V5cyh0aGlzLnN1cmZhY2VzKS5mb3JFYWNoKChzdXJmYWNlSWQpID0+IHRoaXMuc3VyZmFjZXNbc3VyZmFjZUlkXS5yZW1vdmUoc2NyZWVuLmdldElkKCkpKTtcblx0XHRcdHNjcmVlbi5kaXNwb3NlKCk7XG5cdFx0XHRkZWxldGUgdGhpcy5zY3JlZW5zW3BhdGhdO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTYXZlcyBnaXZlbiBzY3JvbGwgcG9zaXRpb24gaW50byBoaXN0b3J5IHN0YXRlLlxuXHQgKiBAcGFyYW0geyFudW1iZXJ9IHNjcm9sbFRvcCBOdW1iZXIgY29udGFpbmluZyB0aGUgdG9wIHNjcm9sbCBwb3NpdGlvbiB0byBiZSBzYXZlZC5cblx0ICogQHBhcmFtIHshbnVtYmVyfSBzY3JvbGxMZWZ0IE51bWJlciBjb250YWluaW5nIHRoZSBsZWZ0IHNjcm9sbCBwb3NpdGlvbiB0byBiZSBzYXZlZC5cblx0ICovXG5cdHNhdmVIaXN0b3J5Q3VycmVudFBhZ2VTY3JvbGxQb3NpdGlvbl8oc2Nyb2xsVG9wLCBzY3JvbGxMZWZ0KSB7XG5cdFx0dmFyIHN0YXRlID0gZ2xvYmFscy53aW5kb3cuaGlzdG9yeS5zdGF0ZTtcblx0XHRpZiAoc3RhdGUgJiYgc3RhdGUuc2VubmEpIHtcblx0XHRcdFtzdGF0ZS5zY3JvbGxUb3AsIHN0YXRlLnNjcm9sbExlZnRdID0gW3Njcm9sbFRvcCwgc2Nyb2xsTGVmdF07XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShzdGF0ZSwgbnVsbCwgbnVsbCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgYWxsb3cgcHJldmVudCBuYXZpZ2F0ZS5cblx0ICogQHBhcmFtIHtib29sZWFufSBhbGxvd1ByZXZlbnROYXZpZ2F0ZVxuXHQgKi9cblx0c2V0QWxsb3dQcmV2ZW50TmF2aWdhdGUoYWxsb3dQcmV2ZW50TmF2aWdhdGUpIHtcblx0XHR0aGlzLmFsbG93UHJldmVudE5hdmlnYXRlID0gYWxsb3dQcmV2ZW50TmF2aWdhdGU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyBsaW5rIGJhc2UgcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoXG5cdCAqL1xuXHRzZXRCYXNlUGF0aChiYXNlUGF0aCkge1xuXHRcdHRoaXMuYmFzZVBhdGggPSB1dGlscy5yZW1vdmVQYXRoVHJhaWxpbmdTbGFzaChiYXNlUGF0aCk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgZGVmYXVsdCBwYWdlIHRpdGxlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZGVmYXVsdFRpdGxlXG5cdCAqL1xuXHRzZXREZWZhdWx0VGl0bGUoZGVmYXVsdFRpdGxlKSB7XG5cdFx0dGhpcy5kZWZhdWx0VGl0bGUgPSBkZWZhdWx0VGl0bGU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgZm9ybSBzZWxlY3Rvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBmb3JtU2VsZWN0b3Jcblx0ICovXG5cdHNldEZvcm1TZWxlY3Rvcihmb3JtU2VsZWN0b3IpIHtcblx0XHR0aGlzLmZvcm1TZWxlY3RvciA9IGZvcm1TZWxlY3Rvcjtcblx0XHRpZiAodGhpcy5mb3JtRXZlbnRIYW5kbGVyXykge1xuXHRcdFx0dGhpcy5mb3JtRXZlbnRIYW5kbGVyXy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdH1cblx0XHR0aGlzLmZvcm1FdmVudEhhbmRsZXJfID0gZGVsZWdhdGUoZG9jdW1lbnQsICdzdWJtaXQnLCB0aGlzLmZvcm1TZWxlY3RvciwgdGhpcy5vbkRvY1N1Ym1pdERlbGVnYXRlXy5iaW5kKHRoaXMpLCB0aGlzLmFsbG93UHJldmVudE5hdmlnYXRlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIGlmIHJvdXRlIG1hdGNoaW5nIHNob3VsZCBpZ25vcmUgcXVlcnkgc3RyaW5nIGZyb20gdGhlIHJvdXRlIHBhdGguXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoXG5cdCAqL1xuXHRzZXRJZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGgoaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKSB7XG5cdFx0dGhpcy5pZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGggPSBpZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgbGluayBzZWxlY3Rvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBsaW5rU2VsZWN0b3Jcblx0ICovXG5cdHNldExpbmtTZWxlY3RvcihsaW5rU2VsZWN0b3IpIHtcblx0XHR0aGlzLmxpbmtTZWxlY3RvciA9IGxpbmtTZWxlY3Rvcjtcblx0XHRpZiAodGhpcy5saW5rRXZlbnRIYW5kbGVyXykge1xuXHRcdFx0dGhpcy5saW5rRXZlbnRIYW5kbGVyXy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdH1cblx0XHR0aGlzLmxpbmtFdmVudEhhbmRsZXJfID0gZGVsZWdhdGUoZG9jdW1lbnQsICdjbGljaycsIHRoaXMubGlua1NlbGVjdG9yLCB0aGlzLm9uRG9jQ2xpY2tEZWxlZ2F0ZV8uYmluZCh0aGlzKSwgdGhpcy5hbGxvd1ByZXZlbnROYXZpZ2F0ZSk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgbG9hZGluZyBjc3MgY2xhc3MuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gbG9hZGluZ0Nzc0NsYXNzXG5cdCAqL1xuXHRzZXRMb2FkaW5nQ3NzQ2xhc3MobG9hZGluZ0Nzc0NsYXNzKSB7XG5cdFx0dGhpcy5sb2FkaW5nQ3NzQ2xhc3MgPSBsb2FkaW5nQ3NzQ2xhc3M7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgdXBkYXRlIHNjcm9sbCBwb3NpdGlvbiB2YWx1ZS5cblx0ICogQHBhcmFtIHtib29sZWFufSB1cGRhdGVTY3JvbGxQb3NpdGlvblxuXHQgKi9cblx0c2V0VXBkYXRlU2Nyb2xsUG9zaXRpb24odXBkYXRlU2Nyb2xsUG9zaXRpb24pIHtcblx0XHR0aGlzLnVwZGF0ZVNjcm9sbFBvc2l0aW9uID0gdXBkYXRlU2Nyb2xsUG9zaXRpb247XG5cdH1cblxuXHQvKipcblx0ICogQ2FuY2VscyBwZW5kaW5nIG5hdmlnYXRlIHdpdGggPGNvZGU+Q2FuY2VsIHBlbmRpbmcgbmF2aWdhdGlvbjwvY29kZT4gZXJyb3IuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHN0b3BQZW5kaW5nTmF2aWdhdGVfKCkge1xuXHRcdGlmICh0aGlzLnBlbmRpbmdOYXZpZ2F0ZSkge1xuXHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUuY2FuY2VsKCdDYW5jZWwgcGVuZGluZyBuYXZpZ2F0aW9uJyk7XG5cdFx0fVxuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTeW5jIGRvY3VtZW50IHNjcm9sbCBwb3NpdGlvbiB0d2ljZSwgdGhlIGZpcnN0IG9uZSBzeW5jaHJvbm91cyBhbmQgdGhlblxuXHQgKiBvbmUgaW5zaWRlIDxjb2RlPmFzeW5jLm5leHRUaWNrPC9jb2RlPi4gUmVsZXZhbnQgdG8gYnJvd3NlcnMgdGhhdCBmaXJlc1xuXHQgKiBzY3JvbGwgcmVzdG9yYXRpb24gYXN5bmNocm9ub3VzbHkgYWZ0ZXIgcG9wc3RhdGUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQHJldHVybiB7P0NhbmNlbGxhYmxlUHJvbWlzZT19XG5cdCAqL1xuXHRzeW5jU2Nyb2xsUG9zaXRpb25TeW5jVGhlbkFzeW5jXygpIHtcblx0XHR2YXIgc3RhdGUgPSBnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnN0YXRlO1xuXHRcdGlmICghc3RhdGUpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgc2Nyb2xsVG9wID0gc3RhdGUuc2Nyb2xsVG9wO1xuXHRcdHZhciBzY3JvbGxMZWZ0ID0gc3RhdGUuc2Nyb2xsTGVmdDtcblxuXHRcdHZhciBzeW5jID0gKCkgPT4ge1xuXHRcdFx0aWYgKHRoaXMudXBkYXRlU2Nyb2xsUG9zaXRpb24pIHtcblx0XHRcdFx0Z2xvYmFscy53aW5kb3cuc2Nyb2xsVG8oc2Nyb2xsTGVmdCwgc2Nyb2xsVG9wKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0cmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUpID0+IHN5bmMoKSAmIGFzeW5jLm5leHRUaWNrKCgpID0+IHN5bmMoKSAmIHJlc29sdmUoKSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZXMgb3IgcmVwbGFjZSBicm93c2VyIGhpc3RvcnkuXG5cdCAqIEBwYXJhbSB7P3N0cmluZ30gdGl0bGUgRG9jdW1lbnQgdGl0bGUuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIGNvbnRhaW5pbmcgdGhlIHF1ZXJ5c3RyaW5nIHBhcnQuXG5cdCAqIEBwYXJhbSB7IW9iamVjdH0gc3RhdGVcblx0ICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3JlcGxhY2VIaXN0b3J5IFJlcGxhY2VzIGJyb3dzZXIgaGlzdG9yeS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dXBkYXRlSGlzdG9yeV8odGl0bGUsIHBhdGgsIHN0YXRlLCBvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHRjb25zdCByZWZlcnJlciA9IGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhyZWY7XG5cblx0XHRpZiAoc3RhdGUpIHtcblx0XHRcdHN0YXRlLnJlZmVycmVyID0gcmVmZXJyZXI7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdF9yZXBsYWNlSGlzdG9yeSkge1xuXHRcdFx0Z2xvYmFscy53aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGUoc3RhdGUsIHRpdGxlLCBwYXRoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Z2xvYmFscy53aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUoc3RhdGUsIHRpdGxlLCBwYXRoKTtcblx0XHR9XG5cblx0XHR1dGlscy5zZXRSZWZlcnJlcihyZWZlcnJlcik7XG5cblx0XHRsZXQgdGl0bGVOb2RlID0gZ2xvYmFscy5kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCd0aXRsZScpO1xuXHRcdGlmICh0aXRsZU5vZGUpIHtcblx0XHRcdHRpdGxlTm9kZS5pbm5lckhUTUwgPSB0aXRsZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Z2xvYmFscy5kb2N1bWVudC50aXRsZSA9IHRpdGxlO1xuXHRcdH1cblx0fVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEFwcDtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaXNEZWYsIGlzRGVmQW5kTm90TnVsbCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBVcmkgZnJvbSAnbWV0YWwtdXJpJztcbmltcG9ydCB7IENhbmNlbGxhYmxlUHJvbWlzZSBhcyBQcm9taXNlIH0gZnJvbSAnbWV0YWwtcHJvbWlzZSc7XG5cbmNsYXNzIEFqYXgge1xuXG5cdC8qKlxuXHQgKiBYbWxIdHRwUmVxdWVzdCdzIGdldEFsbFJlc3BvbnNlSGVhZGVycygpIG1ldGhvZCByZXR1cm5zIGEgc3RyaW5nIG9mXG5cdCAqIHJlc3BvbnNlIGhlYWRlcnMgYWNjb3JkaW5nIHRvIHRoZSBmb3JtYXQgZGVzY3JpYmVkIG9uIHRoZSBzcGVjOlxuXHQgKiB7QGxpbmsgaHR0cDovL3d3dy53My5vcmcvVFIvWE1MSHR0cFJlcXVlc3QvI3RoZS1nZXRhbGxyZXNwb25zZWhlYWRlcnMtbWV0aG9kfS5cblx0ICogVGhpcyBtZXRob2QgcGFyc2VzIHRoYXQgc3RyaW5nIGludG8gYSB1c2VyLWZyaWVuZGx5IG5hbWUvdmFsdWUgcGFpclxuXHQgKiBvYmplY3QuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBhbGxIZWFkZXJzIEFsbCBoZWFkZXJzIGFzIHN0cmluZy5cblx0ICogQHJldHVybiB7IUFycmF5LjxPYmplY3Q8c3RyaW5nLCBzdHJpbmc+Pn1cblx0ICovXG5cdHN0YXRpYyBwYXJzZVJlc3BvbnNlSGVhZGVycyhhbGxIZWFkZXJzKSB7XG5cdFx0dmFyIGhlYWRlcnMgPSBbXTtcblx0XHRpZiAoIWFsbEhlYWRlcnMpIHtcblx0XHRcdHJldHVybiBoZWFkZXJzO1xuXHRcdH1cblx0XHR2YXIgcGFpcnMgPSBhbGxIZWFkZXJzLnNwbGl0KCdcXHUwMDBkXFx1MDAwYScpO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcGFpcnMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHZhciBpbmRleCA9IHBhaXJzW2ldLmluZGV4T2YoJ1xcdTAwM2FcXHUwMDIwJyk7XG5cdFx0XHRpZiAoaW5kZXggPiAwKSB7XG5cdFx0XHRcdHZhciBuYW1lID0gcGFpcnNbaV0uc3Vic3RyaW5nKDAsIGluZGV4KTtcblx0XHRcdFx0dmFyIHZhbHVlID0gcGFpcnNbaV0uc3Vic3RyaW5nKGluZGV4ICsgMik7XG5cdFx0XHRcdGhlYWRlcnMucHVzaCh7XG5cdFx0XHRcdFx0bmFtZTogbmFtZSxcblx0XHRcdFx0XHR2YWx1ZTogdmFsdWVcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBoZWFkZXJzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlcXVlc3RzIHRoZSB1cmwgdXNpbmcgWE1MSHR0cFJlcXVlc3QuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gdXJsXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gbWV0aG9kXG5cdCAqIEBwYXJhbSB7P3N0cmluZ30gYm9keVxuXHQgKiBAcGFyYW0ge011bHRpTWFwPX0gb3B0X2hlYWRlcnNcblx0ICogQHBhcmFtIHtNdWx0aU1hcD19IG9wdF9wYXJhbXNcblx0ICogQHBhcmFtIHtudW1iZXI9fSBvcHRfdGltZW91dFxuXHQgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfc3luY1xuXHQgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfd2l0aENyZWRlbnRpYWxzXG5cdCAqIEByZXR1cm4ge1Byb21pc2V9IERlZmVycmVkIGFqYXggcmVxdWVzdC5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0c3RhdGljIHJlcXVlc3QodXJsLCBtZXRob2QsIGJvZHksIG9wdF9oZWFkZXJzLCBvcHRfcGFyYW1zLCBvcHRfdGltZW91dCwgb3B0X3N5bmMsIG9wdF93aXRoQ3JlZGVudGlhbHMpIHtcblx0XHR1cmwgPSB1cmwgfHwgJyc7XG5cdFx0bWV0aG9kID0gbWV0aG9kIHx8ICdHRVQnO1xuXG5cdFx0dmFyIHJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcblx0XHR2YXIgcHJldmlvdXNSZWFkeVN0YXRlID0gMDtcblxuXHRcdHZhciBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cdFx0XHRyZXF1ZXN0Lm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAocmVxdWVzdC5hYm9ydGVkKSB7XG5cdFx0XHRcdFx0cmVxdWVzdC5vbmVycm9yKCk7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJlc29sdmUocmVxdWVzdCk7XG5cdFx0XHR9O1xuXHRcdFx0cmVxdWVzdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKHByZXZpb3VzUmVhZHlTdGF0ZSAmJiBwcmV2aW91c1JlYWR5U3RhdGUgPCAzICYmIDQgPT09IHJlcXVlc3QucmVhZHlTdGF0ZSkge1xuXHRcdFx0XHRcdHJlcXVlc3QudGVybWluYXRlZFByZW1hdHVyZWx5ID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRwcmV2aW91c1JlYWR5U3RhdGUgPSByZXF1ZXN0LnJlYWR5U3RhdGU7XG5cdFx0XHR9O1xuXHRcdFx0cmVxdWVzdC5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBtZXNzYWdlID0gJ1JlcXVlc3QgZXJyb3InO1xuXHRcdFx0XHRpZiAocmVxdWVzdC50ZXJtaW5hdGVkUHJlbWF0dXJlbHkpIHtcblx0XHRcdFx0XHRtZXNzYWdlID0gJ1JlcXVlc3QgdGVybWluYXRlZCBwcmVtYXR1cmVseSc7XG5cdFx0XHRcdH0gXG5cdFx0XHRcdHZhciBlcnJvciA9IG5ldyBFcnJvcihtZXNzYWdlKTtcblx0XHRcdFx0ZXJyb3IucmVxdWVzdCA9IHJlcXVlc3Q7XG5cdFx0XHRcdHJlamVjdChlcnJvcik7XG5cdFx0XHR9O1xuXHRcdH0pLnRoZW5DYXRjaChmdW5jdGlvbihyZWFzb24pIHtcblx0XHRcdHJlcXVlc3QuYWJvcnQoKTtcblx0XHRcdHRocm93IHJlYXNvbjtcblx0XHR9KS50aGVuQWx3YXlzKGZ1bmN0aW9uKCkge1xuXHRcdFx0Y2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXHRcdH0pO1xuXG5cdFx0dXJsID0gbmV3IFVyaSh1cmwpO1xuXG5cdFx0aWYgKG9wdF9wYXJhbXMpIHtcblx0XHRcdHVybC5hZGRQYXJhbWV0ZXJzRnJvbU11bHRpTWFwKG9wdF9wYXJhbXMpLnRvU3RyaW5nKCk7XG5cdFx0fVxuXG5cdFx0dXJsID0gdXJsLnRvU3RyaW5nKCk7XG5cblx0XHRyZXF1ZXN0Lm9wZW4obWV0aG9kLCB1cmwsICFvcHRfc3luYyk7XG5cblx0XHRpZiAob3B0X3dpdGhDcmVkZW50aWFscykge1xuXHRcdFx0cmVxdWVzdC53aXRoQ3JlZGVudGlhbHMgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmIChvcHRfaGVhZGVycykge1xuXHRcdFx0b3B0X2hlYWRlcnMubmFtZXMoKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcblx0XHRcdFx0cmVxdWVzdC5zZXRSZXF1ZXN0SGVhZGVyKG5hbWUsIG9wdF9oZWFkZXJzLmdldEFsbChuYW1lKS5qb2luKCcsICcpKTtcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdHJlcXVlc3Quc2VuZChpc0RlZihib2R5KSA/IGJvZHkgOiBudWxsKTtcblxuXHRcdGlmIChpc0RlZkFuZE5vdE51bGwob3B0X3RpbWVvdXQpKSB7XG5cdFx0XHR2YXIgdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHByb21pc2UuY2FuY2VsKCdSZXF1ZXN0IHRpbWVvdXQnKTtcblx0XHRcdH0sIG9wdF90aW1lb3V0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gcHJvbWlzZTtcblx0fVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEFqYXg7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogSG9sZHMgdmFsdWUgZXJyb3IgbWVzc2FnZXMuXG4gKiBAY29uc3RcbiAqL1xuY2xhc3MgZXJyb3JzIHtcbn1cblxuLyoqXG4gKiBJbnZhbGlkIHN0YXR1cyBlcnJvciBtZXNzYWdlLlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBzdGF0aWNcbiAqL1xuZXJyb3JzLklOVkFMSURfU1RBVFVTID0gJ0ludmFsaWQgc3RhdHVzIGNvZGUnO1xuXG4vKipcbiAqIFJlcXVlc3QgZXJyb3IgbWVzc2FnZS5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cbmVycm9ycy5SRVFVRVNUX0VSUk9SID0gJ1JlcXVlc3QgZXJyb3InO1xuXG4vKipcbiAqIFJlcXVlc3QgdGltZW91dCBlcnJvciBtZXNzYWdlLlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBzdGF0aWNcbiAqL1xuZXJyb3JzLlJFUVVFU1RfVElNRU9VVCA9ICdSZXF1ZXN0IHRpbWVvdXQnO1xuXG4vKipcbiAqIFJlcXVlc3QgaXMgYmxvY2tlZCBieSBDT1JTIGlzc3VlIG1lc3NhZ2UuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQHN0YXRpY1xuICovXG5lcnJvcnMuUkVRVUVTVF9QUkVNQVRVUkVfVEVSTUlOQVRJT04gPSAnUmVxdWVzdCB0ZXJtaW5hdGVkIHByZW1hdHVyZWx5JztcblxuZXhwb3J0IGRlZmF1bHQgZXJyb3JzO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2lzU2VydmVyU2lkZX0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIE1ldGFsLmpzIGJyb3dzZXIgdXNlciBhZ2VudCBkZXRlY3Rpb24uIEl0J3MgZXh0cmVtZWx5IHJlY29tbWVuZGVkIHRoZSB1c2FnZVxuICogb2YgZmVhdHVyZSBjaGVja2luZyBvdmVyIGJyb3dzZXIgdXNlciBhZ2VudCBzbmlmZmluZy4gVW5mb3J0dW5hdGVseSwgaW4gc29tZVxuICogc2l0dWF0aW9ucyBmZWF0dXJlIGNoZWNraW5nIGNhbiBiZSBzbG93IG9yIGV2ZW4gaW1wb3NzaWJsZSwgdGhlcmVmb3JlIHVzZVxuICogdGhpcyB1dGlsaXR5IHdpdGggY2F1dGlvbi5cbiAqIEBzZWUgPGEgaHJlZj1cImh0dHA6Ly93d3cudXNlcmFnZW50c3RyaW5nLmNvbS9cIj5Vc2VyIGFnZW50IHN0cmluZ3M8L2E+LlxuICovXG5jbGFzcyBVQSB7XG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBuYXRpdmUgdXNlckFnZW50IHN0cmluZyBmcm9tIG5hdmlnYXRvciBpZiBpdCBleGlzdHMuIElmXG5cdCAqIG5hdmlnYXRvciBvciBuYXZpZ2F0b3IudXNlckFnZW50IHN0cmluZyBpcyBtaXNzaW5nLCByZXR1cm5zIGFuIGVtcHR5XG5cdCAqIHN0cmluZy5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0TmF0aXZlVXNlckFnZW50KCkge1xuXHRcdGxldCBuYXZpZ2F0b3IgPSBVQS5nbG9iYWxzLndpbmRvdyAmJiBVQS5nbG9iYWxzLndpbmRvdy5uYXZpZ2F0b3I7XG5cdFx0aWYgKG5hdmlnYXRvcikge1xuXHRcdFx0bGV0IHVzZXJBZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XG5cdFx0XHRpZiAodXNlckFnZW50KSB7XG5cdFx0XHRcdHJldHVybiB1c2VyQWdlbnQ7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiAnJztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBuYXRpdmUgcGxhdGZvcm0gc3RyaW5nIGZyb20gbmF2aWdhdG9yIGlmIGl0IGV4aXN0cy4gSWZcblx0ICogbmF2aWdhdG9yIG9yIG5hdmlnYXRvci5wbGF0Zm9ybSBzdHJpbmcgaXMgbWlzc2luZywgcmV0dXJucyBhbiBlbXB0eVxuXHQgKiBzdHJpbmcuXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICogQHByaXZhdGVcblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldE5hdGl2ZVBsYXRmb3JtKCkge1xuXHRcdGxldCBuYXZpZ2F0b3IgPSBVQS5nbG9iYWxzLndpbmRvdyAmJiBVQS5nbG9iYWxzLndpbmRvdy5uYXZpZ2F0b3I7XG5cdFx0aWYgKG5hdmlnYXRvcikge1xuXHRcdFx0bGV0IHBsYXRmb3JtID0gbmF2aWdhdG9yLnBsYXRmb3JtO1xuXHRcdFx0aWYgKHBsYXRmb3JtKSB7XG5cdFx0XHRcdHJldHVybiBwbGF0Zm9ybTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuICcnO1xuXHR9XG5cblx0LyoqXG5cdCAqIFdoZXRoZXIgdGhlIHBsYXRmb3JtIGNvbnRhaW5zIHRoZSBnaXZlbiBzdHJpbmcsIGlnbm9yaW5nIGNhc2UuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByaXZhdGVcblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIG1hdGNoUGxhdGZvcm0oc3RyKSB7XG5cdFx0cmV0dXJuIFVBLnBsYXRmb3JtLmluZGV4T2Yoc3RyKSAhPT0gLTE7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgdXNlciBhZ2VudCBjb250YWlucyB0aGUgZ2l2ZW4gc3RyaW5nLCBpZ25vcmluZyBjYXNlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcml2YXRlXG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBtYXRjaFVzZXJBZ2VudChzdHIpIHtcblx0XHRyZXR1cm4gVUEudXNlckFnZW50LmluZGV4T2Yoc3RyKSAhPT0gLTE7XG5cdH1cblxuXHQvKipcblx0ICogVGVzdHMgdGhlIHVzZXIgYWdlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyQWdlbnQgVGhlIHVzZXIgYWdlbnQgc3RyaW5nLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGxhdGZvcm1cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIHRlc3RVc2VyQWdlbnQodXNlckFnZW50ID0gJycsIHBsYXRmb3JtID0gJycpIHtcblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgdXNlciBhZ2VudCB2YWx1ZSBleHRyYWN0ZWQgZnJvbSBicm93c2VyIG5hdGl2ZSB1c2VyIGFnZW50LlxuXHRcdCAqIEB0eXBlIHtzdHJpbmd9XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLnVzZXJBZ2VudCA9IHVzZXJBZ2VudDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBwbGF0Zm9ybSB2YWx1ZSBleHRyYWN0ZWQgZnJvbSBicm93c2VyIG5hdGl2ZSBwbGF0Zm9ybS5cblx0XHQgKiBAdHlwZSB7c3RyaW5nfVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIE9TIGlzIE1hYy5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNNYWMgPSBVQS5tYXRjaFBsYXRmb3JtKCdNYWMnKTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBPUyBpcyBXaW4uXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzV2luID0gVUEubWF0Y2hQbGF0Zm9ybSgnV2luJyk7XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgYnJvd3NlciBpcyBPcGVyYS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNPcGVyYSA9IFVBLm1hdGNoVXNlckFnZW50KCdPcGVyYScpIHx8IFVBLm1hdGNoVXNlckFnZW50KCdPUFInKTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBicm93c2VyIGlzIElFLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc0llID0gVUEubWF0Y2hVc2VyQWdlbnQoJ1RyaWRlbnQnKSB8fCBVQS5tYXRjaFVzZXJBZ2VudCgnTVNJRScpO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgRWRnZS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNFZGdlID0gVUEubWF0Y2hVc2VyQWdlbnQoJ0VkZ2UnKTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBicm93c2VyIGlzIElFIG9yIEVkZ2UuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzSWVPckVkZ2UgPSBVQS5pc0llIHx8IFVBLmlzRWRnZTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBicm93c2VyIGlzIENocm9tZS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNDaHJvbWUgPVxuXHRcdFx0KFVBLm1hdGNoVXNlckFnZW50KCdDaHJvbWUnKSB8fCBVQS5tYXRjaFVzZXJBZ2VudCgnQ3JpT1MnKSkgJiZcblx0XHRcdCFVQS5pc09wZXJhICYmXG5cdFx0XHQhVUEuaXNFZGdlO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgU2FmYXJpLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc1NhZmFyaSA9XG5cdFx0XHRVQS5tYXRjaFVzZXJBZ2VudCgnU2FmYXJpJykgJiZcblx0XHRcdCEoVUEuaXNDaHJvbWUgfHwgVUEuaXNPcGVyYSB8fCBVQS5pc0VkZ2UpO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgRmlyZWZveC5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNGaXJlZm94ID0gVUEubWF0Y2hVc2VyQWdlbnQoJ0ZpcmVmb3gnKTtcblx0fVxufVxuXG4vKipcbiAqIEV4cG9zZXMgZ2xvYmFsIHJlZmVyZW5jZXMuXG4gKiBAdHlwZSB7b2JqZWN0fVxuICogQHN0YXRpY1xuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoVUEsICdnbG9iYWxzJywge1xuXHR3cml0YWJsZTogdHJ1ZSxcblx0dmFsdWU6IHtcblx0XHR3aW5kb3c6IGlzU2VydmVyU2lkZSgpID8gbnVsbCA6IHdpbmRvdyxcblx0fSxcbn0pO1xuXG5VQS50ZXN0VXNlckFnZW50KFVBLmdldE5hdGl2ZVVzZXJBZ2VudCgpLCBVQS5nZXROYXRpdmVQbGF0Zm9ybSgpKTtcblxuZXhwb3J0IGRlZmF1bHQgVUE7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmQW5kTm90TnVsbCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBBamF4IGZyb20gJ21ldGFsLWFqYXgnO1xuaW1wb3J0IHsgTXVsdGlNYXAgfSBmcm9tICdtZXRhbC1zdHJ1Y3RzJztcbmltcG9ydCBDYW5jZWxsYWJsZVByb21pc2UgZnJvbSAnbWV0YWwtcHJvbWlzZSc7XG5pbXBvcnQgZXJyb3JzIGZyb20gJy4uL2Vycm9ycy9lcnJvcnMnO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4uL3V0aWxzL3V0aWxzJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgU2NyZWVuIGZyb20gJy4vU2NyZWVuJztcbmltcG9ydCBVcmkgZnJvbSAnbWV0YWwtdXJpJztcbmltcG9ydCBVQSBmcm9tICdtZXRhbC11c2VyYWdlbnQnO1xuXG5jbGFzcyBSZXF1ZXN0U2NyZWVuIGV4dGVuZHMgU2NyZWVuIHtcblxuXHQvKipcblx0ICogUmVxdWVzdCBzY3JlZW4gYWJzdHJhY3QgY2xhc3MgdG8gcGVyZm9ybSBpbyBvcGVyYXRpb25zIG9uIGRlc2NlbmRhbnRcblx0ICogc2NyZWVucy5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqIEBleHRlbmRzIHtTY3JlZW59XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogQGluaGVyaXREb2Ncblx0XHQgKiBAZGVmYXVsdCB0cnVlXG5cdFx0ICovXG5cdFx0dGhpcy5jYWNoZWFibGUgPSB0cnVlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgZGVmYXVsdCBodHRwIGhlYWRlcnMgdG8gc2V0IG9uIHJlcXVlc3QuXG5cdFx0ICogQHR5cGUgez9PYmplY3Q9fVxuXHRcdCAqIEBkZWZhdWx0IHtcblx0XHQgKiAgICdYLVBKQVgnOiAndHJ1ZScsXG5cdFx0ICogICAnWC1SZXF1ZXN0ZWQtV2l0aCc6ICdYTUxIdHRwUmVxdWVzdCdcblx0XHQgKiB9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuaHR0cEhlYWRlcnMgPSB7XG5cdFx0XHQnWC1QSkFYJzogJ3RydWUnLFxuXHRcdFx0J1gtUmVxdWVzdGVkLVdpdGgnOiAnWE1MSHR0cFJlcXVlc3QnXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGRlZmF1bHQgaHR0cCBtZXRob2QgdG8gcGVyZm9ybSB0aGUgcmVxdWVzdC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBSZXF1ZXN0U2NyZWVuLkdFVFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmh0dHBNZXRob2QgPSBSZXF1ZXN0U2NyZWVuLkdFVDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBYSFIgb2JqZWN0IHJlc3BvbnNpYmxlIGZvciB0aGUgcmVxdWVzdC5cblx0XHQgKiBAdHlwZSB7WE1MSHR0cFJlcXVlc3R9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnJlcXVlc3QgPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHJlcXVlc3QgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuXG5cdFx0ICogQHR5cGUgeyFudW1iZXJ9XG5cdFx0ICogQGRlZmF1bHQgMzAwMDBcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy50aW1lb3V0ID0gMzAwMDA7XG5cdH1cblxuXHQvKipcblx0ICogQXNzZXJ0cyB0aGF0IHJlc3BvbnNlIHN0YXR1cyBjb2RlIGlzIHZhbGlkLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gc3RhdHVzXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFzc2VydFZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlKHN0YXR1cykge1xuXHRcdGlmICghdGhpcy5pc1ZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlKHN0YXR1cykpIHtcblx0XHRcdHZhciBlcnJvciA9IG5ldyBFcnJvcihlcnJvcnMuSU5WQUxJRF9TVEFUVVMpO1xuXHRcdFx0ZXJyb3IuaW52YWxpZFN0YXR1cyA9IHRydWU7XG5cdFx0XHRlcnJvci5zdGF0dXNDb2RlID0gc3RhdHVzO1xuXHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRiZWZvcmVVcGRhdGVIaXN0b3J5UGF0aChwYXRoKSB7XG5cdFx0dmFyIHJlZGlyZWN0UGF0aCA9IHRoaXMuZ2V0UmVxdWVzdFBhdGgoKTtcblx0XHRpZiAocmVkaXJlY3RQYXRoICYmIHJlZGlyZWN0UGF0aCAhPT0gcGF0aCkge1xuXHRcdFx0cmV0dXJuIHJlZGlyZWN0UGF0aDtcblx0XHR9XG5cdFx0cmV0dXJuIHBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGJlZm9yZVVwZGF0ZUhpc3RvcnlTdGF0ZShzdGF0ZSkge1xuXHRcdC8vIElmIHN0YXRlIGlzIG91cnMgYW5kIG5hdmlnYXRlIHRvIHBvc3Qtd2l0aG91dC1yZWRpcmVjdC1nZXQgc2V0XG5cdFx0Ly8gaGlzdG9yeSBzdGF0ZSB0byBudWxsLCB0aGF0IHdheSBTZW5uYSB3aWxsIHJlbG9hZCB0aGUgcGFnZSBvblxuXHRcdC8vIHBvcHN0YXRlIHNpbmNlIGl0IGNhbm5vdCBwcmVkaWN0IHBvc3QgZGF0YS5cblx0XHRpZiAoc3RhdGUuc2VubmEgJiYgc3RhdGUuZm9ybSAmJiBzdGF0ZS5yZWRpcmVjdFBhdGggPT09IHN0YXRlLnBhdGgpIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblx0XHRyZXR1cm4gc3RhdGU7XG5cdH1cblxuXHQvKipcblx0ICogRm9ybWF0cyBsb2FkIHBhdGggYmVmb3JlIGludm9raW5nIGFqYXggY2FsbC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGhcblx0ICogQHJldHVybiB7c3RyaW5nfSBGb3JtYXR0ZWQgcGF0aDtcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0Zm9ybWF0TG9hZFBhdGgocGF0aCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHBhdGgpO1xuXG5cdFx0dXJpLnNldEhvc3RuYW1lKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhvc3RuYW1lKTtcblx0XHR1cmkuc2V0UHJvdG9jb2woZ2xvYmFscy53aW5kb3cubG9jYXRpb24ucHJvdG9jb2wpO1xuXG5cdFx0aWYgKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnBvcnQpIHtcblx0XHRcdHVyaS5zZXRQb3J0KGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnBvcnQpO1xuXHRcdH1cblxuXHRcdGlmIChVQS5pc0llT3JFZGdlICYmIHRoaXMuaHR0cE1ldGhvZCA9PT0gUmVxdWVzdFNjcmVlbi5HRVQpIHtcblx0XHRcdHJldHVybiB1cmkubWFrZVVuaXF1ZSgpLnRvU3RyaW5nKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVyaS50b1N0cmluZygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGh0dHAgaGVhZGVycy5cblx0ICogQHJldHVybiB7P09iamVjdD19XG5cdCAqL1xuXHRnZXRIdHRwSGVhZGVycygpIHtcblx0XHRyZXR1cm4gdGhpcy5odHRwSGVhZGVycztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBodHRwIG1ldGhvZC5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICovXG5cdGdldEh0dHBNZXRob2QoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaHR0cE1ldGhvZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHJlcXVlc3QgcGF0aC5cblx0ICogQHJldHVybiB7c3RyaW5nPX1cblx0ICovXG5cdGdldFJlcXVlc3RQYXRoKCkge1xuXHRcdHZhciByZXF1ZXN0ID0gdGhpcy5nZXRSZXF1ZXN0KCk7XG5cdFx0aWYgKHJlcXVlc3QpIHtcblx0XHRcdHZhciByZXF1ZXN0UGF0aCA9IHJlcXVlc3QucmVxdWVzdFBhdGg7XG5cdFx0XHR2YXIgcmVzcG9uc2VVcmwgPSB0aGlzLm1heWJlRXh0cmFjdFJlc3BvbnNlVXJsRnJvbVJlcXVlc3QocmVxdWVzdCk7XG5cdFx0XHRpZiAocmVzcG9uc2VVcmwpIHtcblx0XHRcdFx0cmVxdWVzdFBhdGggPSByZXNwb25zZVVybDtcblx0XHRcdH1cblx0XHRcdGlmIChVQS5pc0llT3JFZGdlICYmIHRoaXMuaHR0cE1ldGhvZCA9PT0gUmVxdWVzdFNjcmVlbi5HRVQpIHtcblx0XHRcdFx0cmVxdWVzdFBhdGggPSBuZXcgVXJpKHJlcXVlc3RQYXRoKS5yZW1vdmVVbmlxdWUoKS50b1N0cmluZygpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHV0aWxzLmdldFVybFBhdGgocmVxdWVzdFBhdGgpO1xuXHRcdH1cblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByZXF1ZXN0IG9iamVjdC5cblx0ICogQHJldHVybiB7P09iamVjdH1cblx0ICovXG5cdGdldFJlcXVlc3QoKSB7XG5cdFx0cmV0dXJuIHRoaXMucmVxdWVzdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByZXF1ZXN0IHRpbWVvdXQuXG5cdCAqIEByZXR1cm4geyFudW1iZXJ9XG5cdCAqL1xuXHRnZXRUaW1lb3V0KCkge1xuXHRcdHJldHVybiB0aGlzLnRpbWVvdXQ7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHJlc3BvbnNlIHN1Y2NlZWRlZC4gQW55IHN0YXR1cyBjb2RlIDJ4eCBvciAzeHggaXMgY29uc2lkZXJlZFxuXHQgKiB2YWxpZC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHN0YXR1c0NvZGVcblx0ICovXG5cdGlzVmFsaWRSZXNwb25zZVN0YXR1c0NvZGUoc3RhdHVzQ29kZSkge1xuXHRcdHJldHVybiBzdGF0dXNDb2RlID49IDIwMCAmJiBzdGF0dXNDb2RlIDw9IDM5OTtcblx0fVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBmb3JtIGRhdGFcbiAgICogVGhpcyBtZXRob2QgY2FuIGJlIGV4dGVuZGVkIGluIG9yZGVyIHRvIGhhdmUgYSBjdXN0b20gaW1wbGVtZW50YXRpb24gb2YgdGhlIGZvcm0gcGFyYW1zXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGZvcm1FbGVtZW50XG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnRcbiAgICogQHJldHVybiB7IUZvcm1EYXRhfVxuICAgKi9cblx0Z2V0Rm9ybURhdGEoZm9ybUVsZW1lbnQsIHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnQpIHtcbiAgICBsZXQgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoZm9ybUVsZW1lbnQpO1xuICAgIHRoaXMubWF5YmVBcHBlbmRTdWJtaXRCdXR0b25WYWx1ZV8oZm9ybURhdGEsIHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnQpO1xuICAgIHJldHVybiBmb3JtRGF0YTtcbiAgfVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0bG9hZChwYXRoKSB7XG5cdFx0Y29uc3QgY2FjaGUgPSB0aGlzLmdldENhY2hlKCk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChjYWNoZSkpIHtcblx0XHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZShjYWNoZSk7XG5cdFx0fVxuXHRcdGxldCBib2R5ID0gbnVsbDtcblx0XHRsZXQgaHR0cE1ldGhvZCA9IHRoaXMuaHR0cE1ldGhvZDtcblx0XHRjb25zdCBoZWFkZXJzID0gbmV3IE11bHRpTWFwKCk7XG5cdFx0T2JqZWN0LmtleXModGhpcy5odHRwSGVhZGVycykuZm9yRWFjaChoZWFkZXIgPT4gaGVhZGVycy5hZGQoaGVhZGVyLCB0aGlzLmh0dHBIZWFkZXJzW2hlYWRlcl0pKTtcblx0XHRpZiAoZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50KSB7XG5cdFx0XHR0aGlzLmFkZFNhZmFyaVhIUlBvbHlmaWxsKCk7XG5cdFx0XHRib2R5ID0gdGhpcy5nZXRGb3JtRGF0YShnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQsIGdsb2JhbHMuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCk7XG5cdFx0XHRodHRwTWV0aG9kID0gUmVxdWVzdFNjcmVlbi5QT1NUO1xuXHRcdFx0aWYgKFVBLmlzSWVPckVkZ2UpIHtcblx0XHRcdFx0aGVhZGVycy5hZGQoJ0lmLU5vbmUtTWF0Y2gnLCAnXCIwXCInKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0Y29uc3QgcmVxdWVzdFBhdGggPSB0aGlzLmZvcm1hdExvYWRQYXRoKHBhdGgpO1xuXHRcdHJldHVybiBBamF4XG5cdFx0XHQucmVxdWVzdChyZXF1ZXN0UGF0aCwgaHR0cE1ldGhvZCwgYm9keSwgaGVhZGVycywgbnVsbCwgdGhpcy50aW1lb3V0KVxuXHRcdFx0LnRoZW4oeGhyID0+IHtcblx0XHRcdFx0dGhpcy5yZW1vdmVTYWZhcmlYSFJQb2x5ZmlsbCgpO1xuXHRcdFx0XHR0aGlzLnNldFJlcXVlc3QoeGhyKTtcblx0XHRcdFx0dGhpcy5hc3NlcnRWYWxpZFJlc3BvbnNlU3RhdHVzQ29kZSh4aHIuc3RhdHVzKTtcblx0XHRcdFx0aWYgKGh0dHBNZXRob2QgPT09IFJlcXVlc3RTY3JlZW4uR0VUICYmIHRoaXMuaXNDYWNoZWFibGUoKSkge1xuXHRcdFx0XHRcdHRoaXMuYWRkQ2FjaGUoeGhyLnJlc3BvbnNlVGV4dCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0eGhyLnJlcXVlc3RQYXRoID0gcmVxdWVzdFBhdGg7XG5cdFx0XHRcdHJldHVybiB4aHIucmVzcG9uc2VUZXh0O1xuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdHRoaXMucmVtb3ZlU2FmYXJpWEhSUG9seWZpbGwoKTtcblx0XHRcdFx0c3dpdGNoIChyZWFzb24ubWVzc2FnZSkge1xuXHRcdFx0XHRcdGNhc2UgZXJyb3JzLlJFUVVFU1RfVElNRU9VVDpcblx0XHRcdFx0XHRcdHJlYXNvbi50aW1lb3V0ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgZXJyb3JzLlJFUVVFU1RfRVJST1I6XG5cdFx0XHRcdFx0XHRyZWFzb24ucmVxdWVzdEVycm9yID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgZXJyb3JzLlJFUVVFU1RfUFJFTUFUVVJFX1RFUk1JTkFUSU9OOlxuXHRcdFx0XHRcdFx0cmVhc29uLnJlcXVlc3RFcnJvciA9IHRydWU7XG5cdFx0XHRcdFx0XHRyZWFzb24ucmVxdWVzdFByZW1hdHVyZVRlcm1pbmF0aW9uID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRocm93IHJlYXNvbjtcblx0XHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYWRpdGlvbmFsIGRhdGEgdG8gdGhlIGJvZHkgb2YgdGhlIHJlcXVlc3QgaW4gY2FzZSBhIHN1Ym1pdCBidXR0b25cblx0ICogaXMgY2FwdHVyZWQgZHVyaW5nIGZvcm0gc3VibWlzc2lvbi5cblx0ICogQHBhcmFtIHshRm9ybURhdGF9IGJvZHkgVGhlIEZvcm1EYXRhIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHshRWxlbWVudH0gc3VibWl0dGVkQnV0dG9uRWxlbWVudFxuICAgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRtYXliZUFwcGVuZFN1Ym1pdEJ1dHRvblZhbHVlXyhmb3JtRGF0YSwgc3VibWl0dGVkQnV0dG9uRWxlbWVudCkge1xuXHRcdGlmIChzdWJtaXR0ZWRCdXR0b25FbGVtZW50ICYmIHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnQubmFtZSkge1xuICAgICAgZm9ybURhdGEuYXBwZW5kKHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnQubmFtZSwgc3VibWl0dGVkQnV0dG9uRWxlbWVudC52YWx1ZSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBmb2xsb3dpbmcgbWV0aG9kIHRyaWVzIHRvIGV4dHJhY3QgdGhlIHJlc3BvbnNlIHVybCB2YWx1ZSBieSBjaGVja2luZ1xuXHQgKiB0aGUgY3VzdG9tIHJlc3BvbnNlIGhlYWRlciAnWC1SZXF1ZXN0LVVSTCcgaWYgcHJvcGVyIHZhbHVlIGlzIG5vdCBwcmVzZW50XG5cdCAqIGluIFhNTEh0dHBSZXF1ZXN0LiBUaGUgdmFsdWUgb2YgcmVzcG9uc2VVUkwgd2lsbCBiZSB0aGUgZmluYWwgVVJMXG5cdCAqIG9idGFpbmVkIGFmdGVyIGFueSByZWRpcmVjdHMuIEludGVybmV0IEV4cGxvcmVyLCBFZGdlIGFuZCBTYWZhcmkgPD0gN1xuXHQgKiBkb2VzIG5vdCB5ZXQgc3VwcG9ydCB0aGUgZmVhdHVyZS4gRm9yIG1vcmUgaW5mb3JtYXRpb24gc2VlOlxuXHQgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvWE1MSHR0cFJlcXVlc3QvcmVzcG9uc2VVUkxcblx0ICogaHR0cHM6Ly94aHIuc3BlYy53aGF0d2cub3JnLyN0aGUtcmVzcG9uc2V1cmwtYXR0cmlidXRlXG5cdCAqIEBwYXJhbSB7WE1MSHR0cFJlcXVlc3R9IHJlcXVlc3Rcblx0ICogQHJldHVybiB7P3N0cmluZ30gUmVzcG9uc2UgdXJsIGJlc3QgbWF0Y2guXG5cdCAqL1xuXHRtYXliZUV4dHJhY3RSZXNwb25zZVVybEZyb21SZXF1ZXN0KHJlcXVlc3QpIHtcblx0XHR2YXIgcmVzcG9uc2VVcmwgPSByZXF1ZXN0LnJlc3BvbnNlVVJMO1xuXHRcdGlmIChyZXNwb25zZVVybCkge1xuXHRcdFx0cmV0dXJuIHJlc3BvbnNlVXJsO1xuXHRcdH1cblx0XHRyZXR1cm4gcmVxdWVzdC5nZXRSZXNwb25zZUhlYWRlcihSZXF1ZXN0U2NyZWVuLlhfUkVRVUVTVF9VUkxfSEVBREVSKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGlzIGZ1bmN0aW9uIHNldCBhdHRyaWJ1dGUgZGF0YS1zYWZhcmktdGVtcC1kaXNhYmxlZCB0byBcblx0ICogdHJ1ZSBhbmQgc2V0IGRpc2FibGUgYXR0cmlidXRlIG9mIGFuIGlucHV0IHR5cGU9XCJmaWxlXCIgdGFnXG5cdCAqIGlzIHVzZWQgYXMgYSBwb2x5ZmlsbCBmb3IgaU9TIDExLjMgU2FmYXJpIC8gbWFjT1MgU2FmYXJpIDExLjEgXG5cdCAqIGVtcHR5IDxpbnB1dCB0eXBlPVwiZmlsZVwiPiBYSFIgYnVnLlxuXHQgKiBodHRwczovL2dpdGh1Yi5jb20vcmFpbHMvcmFpbHMvaXNzdWVzLzMyNDQwXG5cdCAqIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xODQ0OTBcblx0ICovXG5cdGFkZFNhZmFyaVhIUlBvbHlmaWxsKCkge1xuXHRcdGlmIChnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQgJiYgVUEuaXNTYWZhcmkpIHtcblx0XHRcdGxldCBpbnB1dHMgPSBnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnaW5wdXRbdHlwZT1cImZpbGVcIl06bm90KFtkaXNhYmxlZF0pJyk7XG5cdFx0XHRmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgaW5wdXRzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRsZXQgaW5wdXQgPSBpbnB1dHNbaW5kZXhdO1xuXHRcdFx0XHRpZiAoaW5wdXQuZmlsZXMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpbnB1dC5zZXRBdHRyaWJ1dGUoJ2RhdGEtc2FmYXJpLXRlbXAtZGlzYWJsZWQnLCAndHJ1ZScpO1xuXHRcdFx0XHRpbnB1dC5zZXRBdHRyaWJ1dGUoJ2Rpc2FibGVkJywgJycpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBUaGlzIGZ1bmN0aW9uIHJlbW92ZSBhdHRyaWJ1dGUgZGF0YS1zYWZhcmktdGVtcC1kaXNhYmxlZCBhbmQgZGlzYWJsZSBhdHRyaWJ1dGVcblx0ICogb2YgYW4gaW5wdXQgdHlwZT1cImZpbGVcIiB0YWcgaXMgdXNlZCBhcyBhIHBvbHlmaWxsIGZvciBpT1MgMTEuMyBTYWZhcmkgLyBtYWNPUyBTYWZhcmkgMTEuMVxuXHQgKiBlbXB0eSA8aW5wdXQgdHlwZT1cImZpbGVcIj4gWEhSIGJ1Zy5cblx0ICogaHR0cHM6Ly9naXRodWIuY29tL3JhaWxzL3JhaWxzL2lzc3Vlcy8zMjQ0MFxuXHQgKiBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTg0NDkwXG5cdCAqL1xuXHRyZW1vdmVTYWZhcmlYSFJQb2x5ZmlsbCgpIHtcblx0XHRpZiAoZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50ICYmIFVBLmlzU2FmYXJpKSB7XG5cdFx0XHRsZXQgaW5wdXRzID0gZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2lucHV0W3R5cGU9XCJmaWxlXCJdW2RhdGEtc2FmYXJpLXRlbXAtZGlzYWJsZWRdJyk7XG5cdFx0XHRmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgaW5wdXRzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRjb25zdCBpbnB1dCA9IGlucHV0c1tpbmRleF07XG5cdFx0XHRcdGlucHV0LnJlbW92ZUF0dHJpYnV0ZSgnZGF0YS1zYWZhcmktdGVtcC1kaXNhYmxlZCcpO1xuXHRcdFx0XHRpbnB1dC5yZW1vdmVBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGh0dHAgaGVhZGVycy5cblx0ICogQHBhcmFtIHs/T2JqZWN0PX0gaHR0cEhlYWRlcnNcblx0ICovXG5cdHNldEh0dHBIZWFkZXJzKGh0dHBIZWFkZXJzKSB7XG5cdFx0dGhpcy5odHRwSGVhZGVycyA9IGh0dHBIZWFkZXJzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGh0dHAgbWV0aG9kLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IGh0dHBNZXRob2Rcblx0ICovXG5cdHNldEh0dHBNZXRob2QoaHR0cE1ldGhvZCkge1xuXHRcdHRoaXMuaHR0cE1ldGhvZCA9IGh0dHBNZXRob2QudG9Mb3dlckNhc2UoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSByZXF1ZXN0IG9iamVjdC5cblx0ICogQHBhcmFtIHs/T2JqZWN0fSByZXF1ZXN0XG5cdCAqL1xuXHRzZXRSZXF1ZXN0KHJlcXVlc3QpIHtcblx0XHR0aGlzLnJlcXVlc3QgPSByZXF1ZXN0O1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHJlcXVlc3QgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuXG5cdCAqIEBwYXJhbSB7IW51bWJlcn0gdGltZW91dFxuXHQgKi9cblx0c2V0VGltZW91dCh0aW1lb3V0KSB7XG5cdFx0dGhpcy50aW1lb3V0ID0gdGltZW91dDtcblx0fVxuXG59XG5cbi8qKlxuICogSG9sZHMgdmFsdWUgZm9yIG1ldGhvZCBnZXQuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgJ2dldCdcbiAqIEBzdGF0aWNcbiAqL1xuUmVxdWVzdFNjcmVlbi5HRVQgPSAnZ2V0JztcblxuLyoqXG4gKiBIb2xkcyB2YWx1ZSBmb3IgbWV0aG9kIHBvc3QuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgJ3Bvc3QnXG4gKiBAc3RhdGljXG4gKi9cblJlcXVlc3RTY3JlZW4uUE9TVCA9ICdwb3N0JztcblxuLyoqXG4gKiBGYWxsYmFjayBodHRwIGhlYWRlciB0byByZXRyaWV2ZSByZXNwb25zZSByZXF1ZXN0IHVybC5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAZGVmYXVsdCAnWC1SZXF1ZXN0LVVSTCdcbiAqIEBzdGF0aWNcbiAqL1xuUmVxdWVzdFNjcmVlbi5YX1JFUVVFU1RfVVJMX0hFQURFUiA9ICdYLVJlcXVlc3QtVVJMJztcblxuZXhwb3J0IGRlZmF1bHQgUmVxdWVzdFNjcmVlbjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgYnVpbGRGcmFnbWVudCwgZ2xvYmFsRXZhbCwgZ2xvYmFsRXZhbFN0eWxlcywgbWF0Y2ggfSBmcm9tICdtZXRhbC1kb20nO1xuaW1wb3J0IENhbmNlbGxhYmxlUHJvbWlzZSBmcm9tICdtZXRhbC1wcm9taXNlJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgUmVxdWVzdFNjcmVlbiBmcm9tICcuL1JlcXVlc3RTY3JlZW4nO1xuaW1wb3J0IFN1cmZhY2UgZnJvbSAnLi4vc3VyZmFjZS9TdXJmYWNlJztcbmltcG9ydCBVQSBmcm9tICdtZXRhbC11c2VyYWdlbnQnO1xuaW1wb3J0IFVyaSBmcm9tICdtZXRhbC11cmknO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4uL3V0aWxzL3V0aWxzJztcblxuY2xhc3MgSHRtbFNjcmVlbiBleHRlbmRzIFJlcXVlc3RTY3JlZW4ge1xuXG5cdC8qKlxuXHQgKiBTY3JlZW4gY2xhc3MgdGhhdCBwZXJmb3JtIGEgcmVxdWVzdCBhbmQgZXh0cmFjdHMgc3VyZmFjZSBjb250ZW50cyBmcm9tXG5cdCAqIHRoZSByZXNwb25zZSBjb250ZW50LlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICogQGV4dGVuZHMge1JlcXVlc3RTY3JlZW59XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIG1ldGEgc2VsZWN0b3IuIFJlbGV2YW50IHRvIGV4dHJhY3QgPGNvZGU+bWV0YTwvY29kZT4gdGFnc1xuXHRcdCAqIGVsZW1lbnRzIGZyb20gcmVxdWVzdCBmcmFnbWVudHMgdG8gdXNlIGFzIHRoZSBzY3JlZW4uXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgbWV0YVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLm1ldGFUYWdzU2VsZWN0b3IgPSAnbWV0YSc7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgdGl0bGUgc2VsZWN0b3IuIFJlbGV2YW50IHRvIGV4dHJhY3QgdGhlIDxjb2RlPjx0aXRsZT48L2NvZGU+XG5cdFx0ICogZWxlbWVudCBmcm9tIHJlcXVlc3QgZnJhZ21lbnRzIHRvIHVzZSBhcyB0aGUgc2NyZWVuIHRpdGxlLlxuXHRcdCAqIEB0eXBlIHshc3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IHRpdGxlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudGl0bGVTZWxlY3RvciA9ICd0aXRsZSc7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGFjdGl2YXRlKCkge1xuXHRcdHN1cGVyLmFjdGl2YXRlKCk7XG5cdFx0dGhpcy5yZWxlYXNlVmlydHVhbERvY3VtZW50KCk7XG5cdFx0dGhpcy5wZW5kaW5nU3R5bGVzID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGxvY2F0ZXMgdmlydHVhbCBkb2N1bWVudCBmb3IgY29udGVudC4gQWZ0ZXIgYWxsb2NhdGVkIHZpcnR1YWwgZG9jdW1lbnRcblx0ICogY2FuIGJlIGFjY2Vzc2VkIGJ5IDxjb2RlPnRoaXMudmlydHVhbERvY3VtZW50PC9jb2RlPi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBodG1sU3RyaW5nXG5cdCAqL1xuXHRhbGxvY2F0ZVZpcnR1YWxEb2N1bWVudEZvckNvbnRlbnQoaHRtbFN0cmluZykge1xuXHRcdGlmICghdGhpcy52aXJ0dWFsRG9jdW1lbnQpIHtcblx0XHRcdHRoaXMudmlydHVhbERvY3VtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdodG1sJyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5jb3B5Tm9kZUF0dHJpYnV0ZXNGcm9tQ29udGVudF8oaHRtbFN0cmluZywgdGhpcy52aXJ0dWFsRG9jdW1lbnQpO1xuXG5cdFx0dGhpcy52aXJ0dWFsRG9jdW1lbnQuaW5uZXJIVE1MID0gaHRtbFN0cmluZztcblx0fVxuXG5cdC8qKlxuXHQgKiBDdXN0b21pemVzIGxvZ2ljIHRvIGFwcGVuZCBzdHlsZXMgaW50byBkb2N1bWVudC4gUmVsZXZhbnQgdG8gd2hlblxuXHQgKiB0cmFja2luZyBhIHN0eWxlIGJ5IGlkIG1ha2Ugc3VyZSB0byByZS1wb3NpdGlvbnMgdGhlIG5ldyBzdHlsZSBpbiB0aGVcblx0ICogc2FtZSBkb20gb3JkZXIuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbmV3U3R5bGVcblx0ICovXG5cdGFwcGVuZFN0eWxlSW50b0RvY3VtZW50XyhuZXdTdHlsZSkge1xuXHRcdHZhciBpc1RlbXBvcmFyeVN0eWxlID0gbWF0Y2gobmV3U3R5bGUsIEh0bWxTY3JlZW4uc2VsZWN0b3JzLnN0eWxlc1RlbXBvcmFyeSk7XG5cdFx0aWYgKGlzVGVtcG9yYXJ5U3R5bGUpIHtcblx0XHRcdHRoaXMucGVuZGluZ1N0eWxlcy5wdXNoKG5ld1N0eWxlKTtcblx0XHR9XG5cdFx0aWYgKG5ld1N0eWxlLmlkKSB7XG5cdFx0XHR2YXIgc3R5bGVJbkRvYyA9IGdsb2JhbHMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQobmV3U3R5bGUuaWQpO1xuXHRcdFx0aWYgKHN0eWxlSW5Eb2MpIHtcblx0XHRcdFx0c3R5bGVJbkRvYy5wYXJlbnROb2RlLmluc2VydEJlZm9yZShuZXdTdHlsZSwgc3R5bGVJbkRvYy5uZXh0U2libGluZyk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cdFx0Z2xvYmFscy5kb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKG5ld1N0eWxlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZiBib2R5IGlzIHVzZWQgYXMgc3VyZmFjZSBmb3JjZXMgdGhlIHJlcXVlc3RlZCBkb2N1bWVudHMgdG8gaGF2ZSBzYW1lIGlkXG5cdCAqIG9mIHRoZSBpbml0aWFsIHBhZ2UuXG5cdCAqL1xuXHRhc3NlcnRTYW1lQm9keUlkSW5WaXJ0dWFsRG9jdW1lbnQoKSB7XG5cdFx0dmFyIGJvZHlTdXJmYWNlID0gdGhpcy52aXJ0dWFsRG9jdW1lbnQucXVlcnlTZWxlY3RvcignYm9keScpO1xuXHRcdGlmICghZ2xvYmFscy5kb2N1bWVudC5ib2R5LmlkKSB7XG5cdFx0XHRnbG9iYWxzLmRvY3VtZW50LmJvZHkuaWQgPSAnc2VubmFfc3VyZmFjZV8nICsgZ2V0VWlkKCk7XG5cdFx0fVxuXHRcdGlmIChib2R5U3VyZmFjZSkge1xuXHRcdFx0Ym9keVN1cmZhY2UuaWQgPSBnbG9iYWxzLmRvY3VtZW50LmJvZHkuaWQ7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENvcGllcyBhdHRyaWJ1dGVzIGZyb20gdGhlIDxodG1sPiB0YWcgb2YgY29udGVudCB0byB0aGUgZ2l2ZW4gbm9kZS5cblx0ICovXG5cdGNvcHlOb2RlQXR0cmlidXRlc0Zyb21Db250ZW50Xyhjb250ZW50LCBub2RlKSB7XG5cdFx0Y29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvWzxdXFxzKmh0bWwvaWcsICc8c2VubmEnKTtcblx0XHRjb250ZW50ID0gY29udGVudC5yZXBsYWNlKC9cXC9odG1sXFxzKlxcPi9pZywgJy9zZW5uYT4nKTtcblx0XHRsZXQgcGxhY2Vob2xkZXI7XG5cdFx0aWYgKFVBLmlzSWUpIHtcblx0XHRcdGNvbnN0IHRlbXBOb2RlID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVSYW5nZSgpLmNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudChjb250ZW50KTtcblx0XHRcdHBsYWNlaG9sZGVyID0gdGVtcE5vZGUucXVlcnlTZWxlY3Rvcignc2VubmEnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bm9kZS5pbm5lckhUTUwgPSBjb250ZW50O1xuXHRcdFx0cGxhY2Vob2xkZXIgPSBub2RlLnF1ZXJ5U2VsZWN0b3IoJ3Nlbm5hJyk7XG5cdFx0fVxuXG5cdFx0aWYgKHBsYWNlaG9sZGVyKSB7XG5cdFx0XHR1dGlscy5jbGVhck5vZGVBdHRyaWJ1dGVzKG5vZGUpO1xuXHRcdFx0dXRpbHMuY29weU5vZGVBdHRyaWJ1dGVzKHBsYWNlaG9sZGVyLCBub2RlKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQE92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5kaXNwb3NlUGVuZGluZ1N0eWxlcygpO1xuXHRcdHN1cGVyLmRpc3Bvc2VJbnRlcm5hbCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIHBlbmRpbmcgc3R5bGVzIGlmIHNjcmVlbiBnZXQgZGlzcG9zZWQgcHJpb3IgdG8gaXRzIGxvYWRpbmcuXG5cdCAqL1xuXHRkaXNwb3NlUGVuZGluZ1N0eWxlcygpIHtcblx0XHRpZiAodGhpcy5wZW5kaW5nU3R5bGVzKSB7XG5cdFx0XHR1dGlscy5yZW1vdmVFbGVtZW50c0Zyb21Eb2N1bWVudCh0aGlzLnBlbmRpbmdTdHlsZXMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAT3ZlcnJpZGVcblx0ICovXG5cdGV2YWx1YXRlU2NyaXB0cyhzdXJmYWNlcykge1xuXHRcdHZhciBldmFsdWF0ZVRyYWNrZWRTY3JpcHRzID0gdGhpcy5ldmFsdWF0ZVRyYWNrZWRSZXNvdXJjZXNfKFxuXHRcdFx0Z2xvYmFsRXZhbC5ydW5TY3JpcHRzSW5FbGVtZW50LCBIdG1sU2NyZWVuLnNlbGVjdG9ycy5zY3JpcHRzLFxuXHRcdFx0SHRtbFNjcmVlbi5zZWxlY3RvcnMuc2NyaXB0c1RlbXBvcmFyeSwgSHRtbFNjcmVlbi5zZWxlY3RvcnMuc2NyaXB0c1Blcm1hbmVudCk7XG5cblx0XHRyZXR1cm4gZXZhbHVhdGVUcmFja2VkU2NyaXB0cy50aGVuKCgpID0+IHN1cGVyLmV2YWx1YXRlU2NyaXB0cyhzdXJmYWNlcykpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBPdmVycmlkZVxuXHQgKi9cblx0ZXZhbHVhdGVTdHlsZXMoc3VyZmFjZXMpIHtcblx0XHR0aGlzLnBlbmRpbmdTdHlsZXMgPSBbXTtcblx0XHR2YXIgZXZhbHVhdGVUcmFja2VkU3R5bGVzID0gdGhpcy5ldmFsdWF0ZVRyYWNrZWRSZXNvdXJjZXNfKFxuXHRcdFx0Z2xvYmFsRXZhbFN0eWxlcy5ydW5TdHlsZXNJbkVsZW1lbnQsIEh0bWxTY3JlZW4uc2VsZWN0b3JzLnN0eWxlcyxcblx0XHRcdEh0bWxTY3JlZW4uc2VsZWN0b3JzLnN0eWxlc1RlbXBvcmFyeSwgSHRtbFNjcmVlbi5zZWxlY3RvcnMuc3R5bGVzUGVybWFuZW50LFxuXHRcdFx0dGhpcy5hcHBlbmRTdHlsZUludG9Eb2N1bWVudF8uYmluZCh0aGlzKSk7XG5cblx0XHRyZXR1cm4gZXZhbHVhdGVUcmFja2VkU3R5bGVzLnRoZW4oKCkgPT4gc3VwZXIuZXZhbHVhdGVTdHlsZXMoc3VyZmFjZXMpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGxvd3MgYSBzY3JlZW4gdG8gZXZhbHVhdGUgdGhlIGZhdmljb24gc3R5bGUgYmVmb3JlIHRoZSBzY3JlZW4gYmVjb21lcyB2aXNpYmxlLlxuXHQgKiBAcmV0dXJuIHtDYW5jZWxsYWJsZVByb21pc2V9XG5cdCAqL1xuXHRldmFsdWF0ZUZhdmljb25fKCkge1xuXHRcdGNvbnN0IHJlc291cmNlc0luVmlydHVhbCA9IHRoaXMudmlydHVhbFF1ZXJ5U2VsZWN0b3JBbGxfKEh0bWxTY3JlZW4uc2VsZWN0b3JzLmZhdmljb24pO1xuXHRcdGNvbnN0IHJlc291cmNlc0luRG9jdW1lbnQgPSB0aGlzLnF1ZXJ5U2VsZWN0b3JBbGxfKEh0bWxTY3JlZW4uc2VsZWN0b3JzLmZhdmljb24pO1xuXG5cdFx0cmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUpID0+IHtcblx0XHRcdHV0aWxzLnJlbW92ZUVsZW1lbnRzRnJvbURvY3VtZW50KHJlc291cmNlc0luRG9jdW1lbnQpO1xuXHRcdFx0dGhpcy5ydW5GYXZpY29uSW5FbGVtZW50XyhyZXNvdXJjZXNJblZpcnR1YWwpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKTtcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgdHJhY2tlZCByZXNvdXJjZXMgaW5zaWRlIGluY29taW5nIGZyYWdtZW50IGFuZCByZW1vdmUgZXhpc3Rpbmdcblx0ICogdGVtcG9yYXJ5IHJlc291cmNlcy5cblx0ICogQHBhcmFtIHs/ZnVuY3Rpb24oKX0gYXBwZW5kRm4gRnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlIGludG8gZG9jdW1lbnQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3IgU2VsZWN0b3IgdXNlZCB0byBmaW5kIHJlc291cmNlcyB0byB0cmFjay5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzZWxlY3RvclRlbXBvcmFyeSBTZWxlY3RvciB1c2VkIHRvIGZpbmQgdGVtcG9yYXJ5XG5cdCAqICAgICByZXNvdXJjZXMgdG8gdHJhY2suXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3JQZXJtYW5lbnQgU2VsZWN0b3IgdXNlZCB0byBmaW5kIHBlcm1hbmVudFxuXHQgKiAgICAgcmVzb3VyY2VzIHRvIHRyYWNrLlxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbn0gb3B0X2FwcGVuZFJlc291cmNlRm4gT3B0aW9uYWwgZnVuY3Rpb24gdXNlZCB0b1xuXHQgKiAgICAgZXZhbHVhdGUgZnJhZ21lbnQgY29udGFpbmluZyByZXNvdXJjZXMuXG5cdCAqIEByZXR1cm4ge0NhbmNlbGxhYmxlUHJvbWlzZX0gRGVmZXJyZWQgdGhhdCB3YWl0cyByZXNvdXJjZXMgZXZhbHVhdGlvbiB0b1xuXHQgKiAgICAgY29tcGxldGUuXG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRldmFsdWF0ZVRyYWNrZWRSZXNvdXJjZXNfKGV2YWx1YXRvckZuLCBzZWxlY3Rvciwgc2VsZWN0b3JUZW1wb3JhcnksIHNlbGVjdG9yUGVybWFuZW50LCBvcHRfYXBwZW5kUmVzb3VyY2VGbikge1xuXHRcdHZhciB0cmFja2VkID0gdGhpcy52aXJ0dWFsUXVlcnlTZWxlY3RvckFsbF8oc2VsZWN0b3IpO1xuXHRcdHZhciB0ZW1wb3Jhcmllc0luRG9jID0gdGhpcy5xdWVyeVNlbGVjdG9yQWxsXyhzZWxlY3RvclRlbXBvcmFyeSk7XG5cdFx0dmFyIHBlcm1hbmVudHNJbkRvYyA9IHRoaXMucXVlcnlTZWxlY3RvckFsbF8oc2VsZWN0b3JQZXJtYW5lbnQpO1xuXG5cdFx0Ly8gQWRkcyBwZXJtYW5lbnQgcmVzb3VyY2VzIGluIGRvY3VtZW50IHRvIGNhY2hlLlxuXHRcdHBlcm1hbmVudHNJbkRvYy5mb3JFYWNoKChyZXNvdXJjZSkgPT4ge1xuXHRcdFx0dmFyIHJlc291cmNlS2V5ID0gdGhpcy5nZXRSZXNvdXJjZUtleV8ocmVzb3VyY2UpO1xuXHRcdFx0aWYgKHJlc291cmNlS2V5KSB7XG5cdFx0XHRcdEh0bWxTY3JlZW4ucGVybWFuZW50UmVzb3VyY2VzSW5Eb2NbcmVzb3VyY2VLZXldID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHZhciBmcmFnID0gYnVpbGRGcmFnbWVudCgpO1xuXHRcdHRyYWNrZWQuZm9yRWFjaCgocmVzb3VyY2UpID0+IHtcblx0XHRcdHZhciByZXNvdXJjZUtleSA9IHRoaXMuZ2V0UmVzb3VyY2VLZXlfKHJlc291cmNlKTtcblx0XHRcdC8vIERvIG5vdCBsb2FkIHBlcm1hbmVudCByZXNvdXJjZXMgaWYgYWxyZWFkeSBpbiBkb2N1bWVudC5cblx0XHRcdGlmICghSHRtbFNjcmVlbi5wZXJtYW5lbnRSZXNvdXJjZXNJbkRvY1tyZXNvdXJjZUtleV0pIHtcblx0XHRcdFx0ZnJhZy5hcHBlbmRDaGlsZChyZXNvdXJjZSk7XG5cdFx0XHR9XG5cdFx0XHQvLyBJZiByZXNvdXJjZSBoYXMga2V5IGFuZCBpcyBwZXJtYW5lbnQgYWRkIHRvIGNhY2hlLlxuXHRcdFx0aWYgKHJlc291cmNlS2V5ICYmIG1hdGNoKHJlc291cmNlLCBzZWxlY3RvclBlcm1hbmVudCkpIHtcblx0XHRcdFx0SHRtbFNjcmVlbi5wZXJtYW5lbnRSZXNvdXJjZXNJbkRvY1tyZXNvdXJjZUtleV0gPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUpID0+IHtcblx0XHRcdGV2YWx1YXRvckZuKGZyYWcsICgpID0+IHtcblx0XHRcdFx0dXRpbHMucmVtb3ZlRWxlbWVudHNGcm9tRG9jdW1lbnQodGVtcG9yYXJpZXNJbkRvYyk7XG5cdFx0XHRcdHJlc29sdmUoKTtcblx0XHRcdH0sIG9wdF9hcHBlbmRSZXNvdXJjZUZuKTtcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAT3ZlcnJpZGVcblx0ICovXG5cdGZsaXAoc3VyZmFjZXMpIHtcblx0XHRyZXR1cm4gc3VwZXIuZmxpcChzdXJmYWNlcykudGhlbigoKSA9PiB7XG5cdFx0XHR1dGlscy5jbGVhck5vZGVBdHRyaWJ1dGVzKGdsb2JhbHMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KTtcblx0XHRcdHV0aWxzLmNvcHlOb2RlQXR0cmlidXRlcyh0aGlzLnZpcnR1YWxEb2N1bWVudCwgZ2xvYmFscy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpO1xuXHRcdFx0dGhpcy5ldmFsdWF0ZUZhdmljb25fKCk7XG5cdFx0XHR0aGlzLnVwZGF0ZU1ldGFUYWdzXygpO1xuXHRcdH0pO1xuXHR9XG5cblx0dXBkYXRlTWV0YVRhZ3NfKCkge1xuXHRcdGNvbnN0IGN1cnJlbnRNZXRhTm9kZXMgPSB0aGlzLnF1ZXJ5U2VsZWN0b3JBbGxfKCdtZXRhJyk7XG5cdFx0Y29uc3QgbWV0YXNGcm9tVmlydHVhbERvY3VtZW50ID0gdGhpcy5tZXRhcztcblx0XHRpZiAoY3VycmVudE1ldGFOb2Rlcykge1xuXHRcdFx0dXRpbHMucmVtb3ZlRWxlbWVudHNGcm9tRG9jdW1lbnQoY3VycmVudE1ldGFOb2Rlcyk7XG5cdFx0XHRpZiAobWV0YXNGcm9tVmlydHVhbERvY3VtZW50KSB7XG5cdFx0XHRcdG1ldGFzRnJvbVZpcnR1YWxEb2N1bWVudC5mb3JFYWNoKChtZXRhKSA9PiBnbG9iYWxzLmRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQobWV0YSkpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBFeHRyYWN0cyBhIGtleSB0byBpZGVudGlmeSB0aGUgcmVzb3VyY2UgYmFzZWQgb24gaXRzIGF0dHJpYnV0ZXMuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gcmVzb3VyY2Vcblx0ICogQHJldHVybiB7c3RyaW5nfSBFeHRyYWN0ZWQga2V5IGJhc2VkIG9uIHJlc291cmNlIGF0dHJpYnV0ZXMgaW4gb3JkZXIgb2Zcblx0ICogICAgIHByZWZlcmVuY2U6IGlkLCBocmVmLCBzcmMuXG5cdCAqL1xuXHRnZXRSZXNvdXJjZUtleV8ocmVzb3VyY2UpIHtcblx0XHRyZXR1cm4gcmVzb3VyY2UuaWQgfHwgcmVzb3VyY2UuaHJlZiB8fCByZXNvdXJjZS5zcmMgfHwgJyc7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGdldFN1cmZhY2VDb250ZW50KHN1cmZhY2VJZCkge1xuXHRcdHZhciBzdXJmYWNlID0gdGhpcy52aXJ0dWFsRG9jdW1lbnQucXVlcnlTZWxlY3RvcignIycgKyBzdXJmYWNlSWQpO1xuXHRcdGlmIChzdXJmYWNlKSB7XG5cdFx0XHR2YXIgZGVmYXVsdENoaWxkID0gc3VyZmFjZS5xdWVyeVNlbGVjdG9yKCcjJyArIHN1cmZhY2VJZCArICctJyArIFN1cmZhY2UuREVGQVVMVCk7XG5cdFx0XHRpZiAoZGVmYXVsdENoaWxkKSB7XG5cdFx0XHRcdHJldHVybiBkZWZhdWx0Q2hpbGQuaW5uZXJIVE1MO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHN1cmZhY2UuaW5uZXJIVE1MOyAvLyBJZiBkZWZhdWx0IGNvbnRlbnQgbm90IGZvdW5kLCB1c2Ugc3VyZmFjZSBjb250ZW50XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHRpdGxlIHNlbGVjdG9yLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKi9cblx0Z2V0VGl0bGVTZWxlY3RvcigpIHtcblx0XHRyZXR1cm4gdGhpcy50aXRsZVNlbGVjdG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRsb2FkKHBhdGgpIHtcblx0XHRyZXR1cm4gc3VwZXIubG9hZChwYXRoKVxuXHRcdFx0LnRoZW4oY29udGVudCA9PiB7XG5cdFx0XHRcdHRoaXMuYWxsb2NhdGVWaXJ0dWFsRG9jdW1lbnRGb3JDb250ZW50KGNvbnRlbnQpO1xuXHRcdFx0XHR0aGlzLnJlc29sdmVUaXRsZUZyb21WaXJ0dWFsRG9jdW1lbnQoKTtcblx0XHRcdFx0dGhpcy5yZXNvbHZlTWV0YVRhZ3NGcm9tVmlydHVhbERvY3VtZW50KCk7XG5cdFx0XHRcdHRoaXMuYXNzZXJ0U2FtZUJvZHlJZEluVmlydHVhbERvY3VtZW50KCk7XG5cdFx0XHRcdGlmIChVQS5pc0llKSB7XG5cdFx0XHRcdFx0dGhpcy5tYWtlVGVtcG9yYXJ5U3R5bGVzSHJlZnNVbmlxdWVfKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIGNvbnRlbnQ7XG5cdFx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBRdWVyaWVzIHRlbXBvcmFyeSBzdHlsZXMgZnJvbSB2aXJ0dWFsIGRvY3VtZW50LCBhbmQgbWFrZXMgdGhlbSB1bmlxdWUuXG5cdCAqIFRoaXMgaXMgbmVjZXNzYXJ5IGZvciBjYWNoaW5nIGFuZCBsb2FkIGV2ZW50IGZpcmluZyBpc3N1ZXMgc3BlY2lmaWMgdG9cblx0ICogSUUxMS4gaHR0cHM6Ly9kZXZlbG9wZXIubWljcm9zb2Z0LmNvbS9lbi11cy9taWNyb3NvZnQtZWRnZS9wbGF0Zm9ybS9pc3N1ZXMvNzk0MDE3MS9cblx0ICovXG5cdG1ha2VUZW1wb3JhcnlTdHlsZXNIcmVmc1VuaXF1ZV8oKSB7XG5cdFx0dmFyIHRlbXBvcmFyaWVzSW5Eb2MgPSB0aGlzLnZpcnR1YWxRdWVyeVNlbGVjdG9yQWxsXyhIdG1sU2NyZWVuLnNlbGVjdG9ycy5zdHlsZXNUZW1wb3JhcnkpO1xuXHRcdHRlbXBvcmFyaWVzSW5Eb2MuZm9yRWFjaCgoc3R5bGUpID0+IHRoaXMucmVwbGFjZVN0eWxlQW5kTWFrZVVuaXF1ZV8oc3R5bGUpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgbmV3IGVsZW1lbnQgZnJvbSBnaXZlbiwgY29waWVzIGF0dHJpYnV0ZXMsIG11dGF0ZXMgaHJlZiB0byBiZVxuXHQgKiB1bmlxdWUgdG8gcHJldmVudCBjYWNoaW5nIGFuZCBtb3JlIHRoYW4gb25lIGxvYWQvZXJyb3IgZXZlbnQgZnJvbSBmaXJpbmcuXG5cdCAqL1xuXHRyZXBsYWNlU3R5bGVBbmRNYWtlVW5pcXVlXyhzdHlsZSkge1xuXHRcdGlmIChzdHlsZS5ocmVmKSB7XG5cdFx0XHR2YXIgbmV3U3R5bGUgPSBnbG9iYWxzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoc3R5bGUudGFnTmFtZSk7XG5cdFx0XHRzdHlsZS5ocmVmID0gbmV3IFVyaShzdHlsZS5ocmVmKS5tYWtlVW5pcXVlKCkudG9TdHJpbmcoKTtcblx0XHRcdHV0aWxzLmNvcHlOb2RlQXR0cmlidXRlcyhzdHlsZSwgbmV3U3R5bGUpO1xuXHRcdFx0c3R5bGUucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3U3R5bGUsIHN0eWxlKTtcblx0XHRcdHN0eWxlLmRpc2FibGVkID0gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyB0aGUgZmF2aWNvbiBlbGVtZW50cyB0byB0aGUgZG9jdW1lbnQuXG5cdCAqIEBwYXJhbSB7IUFycmF5PEVsZW1lbnQ+fSBlbGVtZW50c1xuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcmV0dXJuIHtDYW5jZWxsYWJsZVByb21pc2V9XG5cdCAqL1xuXHRydW5GYXZpY29uSW5FbGVtZW50XyhlbGVtZW50cykge1xuXHRcdHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKChyZXNvbHZlKSA9PiB7XG5cdFx0XHRlbGVtZW50cy5mb3JFYWNoKChlbGVtZW50KSA9PiBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKFxuXHRcdFx0XHRVQS5pc0llID8gZWxlbWVudCA6IHV0aWxzLnNldEVsZW1lbnRXaXRoUmFuZG9tSHJlZihlbGVtZW50KVxuXHRcdFx0KSk7XG5cdFx0XHRyZXNvbHZlKCk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUXVlcmllcyBlbGVtZW50cyBmcm9tIHZpcnR1YWwgZG9jdW1lbnQgYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgZWxlbWVudHMuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3Jcblx0ICogQHJldHVybiB7YXJyYXkuPEVsZW1lbnQ+fVxuXHQgKi9cblx0dmlydHVhbFF1ZXJ5U2VsZWN0b3JBbGxfKHNlbGVjdG9yKSB7XG5cdFx0cmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMudmlydHVhbERvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBRdWVyaWVzIGVsZW1lbnRzIGZyb20gZG9jdW1lbnQgYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgZWxlbWVudHMuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3Jcblx0ICogQHJldHVybiB7YXJyYXkuPEVsZW1lbnQ+fVxuXHQgKi9cblx0cXVlcnlTZWxlY3RvckFsbF8oc2VsZWN0b3IpIHtcblx0XHRyZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZ2xvYmFscy5kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVsZWFzZXMgdmlydHVhbCBkb2N1bWVudCBhbGxvY2F0ZWQgZm9yIGNvbnRlbnQuXG5cdCAqL1xuXHRyZWxlYXNlVmlydHVhbERvY3VtZW50KCkge1xuXHRcdHRoaXMudmlydHVhbERvY3VtZW50ID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXNvbHZlcyB0aXRsZSBmcm9tIGFsbG9jYXRlZCB2aXJ0dWFsIGRvY3VtZW50LlxuXHQgKi9cblx0cmVzb2x2ZVRpdGxlRnJvbVZpcnR1YWxEb2N1bWVudCgpIHtcblx0XHRjb25zdCB0aXRsZSA9IHRoaXMudmlydHVhbERvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy50aXRsZVNlbGVjdG9yKTtcblx0XHRpZiAodGl0bGUpIHtcblx0XHRcdHRoaXMuc2V0VGl0bGUodGl0bGUudGV4dENvbnRlbnQudHJpbSgpKTtcblx0XHR9XG5cdH1cblxuXHRyZXNvbHZlTWV0YVRhZ3NGcm9tVmlydHVhbERvY3VtZW50KCkge1xuXHRcdGNvbnN0IG1ldGFzID0gdGhpcy52aXJ0dWFsUXVlcnlTZWxlY3RvckFsbF8odGhpcy5tZXRhVGFnc1NlbGVjdG9yKTtcblx0XHRpZiAobWV0YXMpIHtcblx0XHRcdHRoaXMuc2V0TWV0YXMobWV0YXMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB0aXRsZSBzZWxlY3Rvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSB0aXRsZVNlbGVjdG9yXG5cdCAqL1xuXHRzZXRUaXRsZVNlbGVjdG9yKHRpdGxlU2VsZWN0b3IpIHtcblx0XHR0aGlzLnRpdGxlU2VsZWN0b3IgPSB0aXRsZVNlbGVjdG9yO1xuXHR9XG5cbn1cblxuLyoqXG4gKiBIZWxwZXIgc2VsZWN0b3IgZm9yIGlnbm9yZSBmYXZpY29uIHdoZW4gZXhpc3QgZGF0YS1zZW5uYS10cmFjay5cbiAqL1xuY29uc3QgaWdub3JlRmF2aWNvbiA9ICc6bm90KFtyZWw9XCJTaG9ydGN1dCBJY29uXCJdKTpub3QoW3JlbD1cInNob3J0Y3V0IGljb25cIl0pOm5vdChbcmVsPVwiaWNvblwiXSk6bm90KFtocmVmJD1cImZhdmljb24uaWNvblwiXSknO1xuXG4vKipcbiAqIEhlbHBlciBzZWxlY3RvcnMgZm9yIHRyYWNraW5nIHJlc291cmNlcy5cbiAqIEB0eXBlIHtvYmplY3R9XG4gKiBAcHJvdGVjdGVkXG4gKiBAc3RhdGljXG4gKi9cbkh0bWxTY3JlZW4uc2VsZWN0b3JzID0ge1xuXHRmYXZpY29uOiAnbGlua1tyZWw9XCJTaG9ydGN1dCBJY29uXCJdLGxpbmtbcmVsPVwic2hvcnRjdXQgaWNvblwiXSxsaW5rW3JlbD1cImljb25cIl0sbGlua1tocmVmJD1cImZhdmljb24uaWNvblwiXScsXG5cdHNjcmlwdHM6ICdzY3JpcHRbZGF0YS1zZW5uYS10cmFja10nLFxuXHRzY3JpcHRzUGVybWFuZW50OiAnc2NyaXB0W2RhdGEtc2VubmEtdHJhY2s9XCJwZXJtYW5lbnRcIl0nLFxuXHRzY3JpcHRzVGVtcG9yYXJ5OiAnc2NyaXB0W2RhdGEtc2VubmEtdHJhY2s9XCJ0ZW1wb3JhcnlcIl0nLFxuXHRzdHlsZXM6IGBzdHlsZVtkYXRhLXNlbm5hLXRyYWNrXSxsaW5rW2RhdGEtc2VubmEtdHJhY2tdJHtpZ25vcmVGYXZpY29ufWAsXG5cdHN0eWxlc1Blcm1hbmVudDogYHN0eWxlW2RhdGEtc2VubmEtdHJhY2s9XCJwZXJtYW5lbnRcIl0sbGlua1tkYXRhLXNlbm5hLXRyYWNrPVwicGVybWFuZW50XCJdJHtpZ25vcmVGYXZpY29ufWAsXG5cdHN0eWxlc1RlbXBvcmFyeTogYHN0eWxlW2RhdGEtc2VubmEtdHJhY2s9XCJ0ZW1wb3JhcnlcIl0sbGlua1tkYXRhLXNlbm5hLXRyYWNrPVwidGVtcG9yYXJ5XCJdJHtpZ25vcmVGYXZpY29ufWBcbn07XG5cbi8qKlxuICogQ2FjaGVzIHBlcm1hbmVudCByZXNvdXJjZSBrZXlzLlxuICogQHR5cGUge29iamVjdH1cbiAqIEBwcm90ZWN0ZWRcbiAqIEBzdGF0aWNcbiAqL1xuSHRtbFNjcmVlbi5wZXJtYW5lbnRSZXNvdXJjZXNJbkRvYyA9IHt9O1xuXG5leHBvcnQgZGVmYXVsdCBIdG1sU2NyZWVuO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlLCBnZXRVaWQsIGlzRGVmQW5kTm90TnVsbCwgaXNFbGVtZW50LCBvYmplY3QgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgZGF0YUF0dHJpYnV0ZXMgZnJvbSAnLi9kYXRhQXR0cmlidXRlcyc7XG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IEFwcCBmcm9tICcuL0FwcCc7XG5pbXBvcnQgSHRtbFNjcmVlbiBmcm9tICcuLi9zY3JlZW4vSHRtbFNjcmVlbic7XG5pbXBvcnQgUm91dGUgZnJvbSAnLi4vcm91dGUvUm91dGUnO1xuXG5jbGFzcyBBcHBEYXRhQXR0cmlidXRlSGFuZGxlciBleHRlbmRzIERpc3Bvc2FibGUge1xuXG5cdC8qKlxuXHQgKiBJbml0aWxpemVzIEFwcCwgcmVnaXN0ZXIgc3VyZmFjZXMgYW5kIHJvdXRlcyBmcm9tIGRhdGEgYXR0cmlidXRlcy5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGFwcCByZWZlcmVuY2UgaW5pdGlhbGl6ZWQgYnkgZGF0YSBhdHRyaWJ1dGVzLlxuXHRcdCAqIEB0eXBlIHtBcHB9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdHRoaXMuYXBwID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBiYXNlIGVsZW1lbnQgdG8gc2VhcmNoIGluaXRpYWxpemF0aW9uIGRhdGEgYXR0cmlidXRlcy4gVGhpc1xuXHRcdCAqIGVsZW1lbnQgaXMgdGhlIGNvbnRhaW5lciB1c2VkIHRvIGVuYWJsZSBpbml0aWFsaXphdGlvbiBiYXNlZCBvbiB0aGVcblx0XHQgKiBwcmVzZW5jZSBvZiBgZGF0YS1zZW5uYWAgYXR0cmlidXRlLlxuXHRcdCAqIEB0eXBlIHtFbGVtZW50fVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHR0aGlzLmJhc2VFbGVtZW50ID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbml0cyBhcHBsaWNhdGlvbiBiYXNlZCBvbiBpbmZvcm1hdGlvbiBzY2FubmVkIGZyb20gZG9jdW1lbnQuXG5cdCAqL1xuXHRoYW5kbGUoKSB7XG5cdFx0aWYgKCFpc0VsZW1lbnQodGhpcy5iYXNlRWxlbWVudCkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignU2VubmEgZGF0YSBhdHRyaWJ1dGUgaGFuZGxlciBiYXNlIGVsZW1lbnQgJyArXG5cdFx0XHRcdCdub3Qgc2V0IG9yIGludmFsaWQsIHRyeSBzZXR0aW5nIGEgdmFsaWQgZWxlbWVudCB0aGF0ICcgK1xuXHRcdFx0XHQnY29udGFpbnMgYSBgZGF0YS1zZW5uYWAgYXR0cmlidXRlLicpO1xuXHRcdH1cblxuXHRcdGlmICghdGhpcy5iYXNlRWxlbWVudC5oYXNBdHRyaWJ1dGUoZGF0YUF0dHJpYnV0ZXMuc2VubmEpKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnU2VubmEgd2FzIG5vdCBpbml0aWFsaXplZCBmcm9tIGRhdGEgYXR0cmlidXRlcy4gJyArXG5cdFx0XHRcdCdJbiBvcmRlciB0byBlbmFibGUgaXRzIHVzYWdlIGZyb20gZGF0YSBhdHRyaWJ1dGVzIHRyeSBzZXR0aW5nICcgK1xuXHRcdFx0XHQnaW4gdGhlIGJhc2UgZWxlbWVudCwgZS5nLiBgPGJvZHkgZGF0YS1zZW5uYT5gLicpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLmFwcCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTZW5uYSBhcHAgd2FzIGFscmVhZHkgaW5pdGlhbGl6ZWQuJyk7XG5cdFx0fVxuXG5cdFx0Y29uc29sZS5sb2coJ1Nlbm5hIGluaXRpYWxpemVkIGZyb20gZGF0YSBhdHRyaWJ1dGUuJyk7XG5cblx0XHR0aGlzLmFwcCA9IG5ldyBBcHAoKTtcblx0XHR0aGlzLm1heWJlQWRkUm91dGVzXygpO1xuXHRcdHRoaXMubWF5YmVBZGRTdXJmYWNlc18oKTtcblx0XHR0aGlzLm1heWJlU2V0QmFzZVBhdGhfKCk7XG5cdFx0dGhpcy5tYXliZVNldExpbmtTZWxlY3Rvcl8oKTtcblx0XHR0aGlzLm1heWJlU2V0TG9hZGluZ0Nzc0NsYXNzXygpO1xuXHRcdHRoaXMubWF5YmVTZXRVcGRhdGVTY3JvbGxQb3NpdGlvbl8oKTtcblx0XHR0aGlzLm1heWJlRGlzcGF0Y2hfKCk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHRpZiAodGhpcy5hcHApIHtcblx0XHRcdHRoaXMuYXBwLmRpc3Bvc2UoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgYXBwIHJlZmVyZW5jZS5cblx0ICogQHJldHVybiB7QXBwfVxuXHQgKi9cblx0Z2V0QXBwKCkge1xuXHRcdHJldHVybiB0aGlzLmFwcDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBiYXNlIGVsZW1lbnQuXG5cdCAqIEByZXR1cm4ge0VsZW1lbnR9IGJhc2VFbGVtZW50XG5cdCAqL1xuXHRnZXRCYXNlRWxlbWVudCgpIHtcblx0XHRyZXR1cm4gdGhpcy5iYXNlRWxlbWVudDtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBhZGRzIGFwcCByb3V0ZXMgZnJvbSBsaW5rIGVsZW1lbnRzIHRoYXQgYXJlIGBzZW5uYS1yb3V0ZWAuXG5cdCAqL1xuXHRtYXliZUFkZFJvdXRlc18oKSB7XG5cdFx0dmFyIHJvdXRlc1NlbGVjdG9yID0gJ2xpbmtbcmVsPVwic2VubmEtcm91dGVcIl0nO1xuXHRcdHRoaXMucXVlcnlTZWxlY3RvckFsbEFzQXJyYXlfKHJvdXRlc1NlbGVjdG9yKS5mb3JFYWNoKChsaW5rKSA9PiB0aGlzLm1heWJlUGFyc2VMaW5rUm91dGVfKGxpbmspKTtcblx0XHRpZiAoIXRoaXMuYXBwLmhhc1JvdXRlcygpKSB7XG5cdFx0XHR0aGlzLmFwcC5hZGRSb3V0ZXMobmV3IFJvdXRlKC8uKi8sIEh0bWxTY3JlZW4pKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBjYW5cXCd0IGZpbmQgcm91dGUgZWxlbWVudHMsIGFkZGluZyBkZWZhdWx0LicpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBhZGRzIGFwcCBzdXJmYWNlcyBieSBzY2FubmluZyBgZGF0YS1zZW5uYS1zdXJmYWNlYCBkYXRhIGF0dHJpYnV0ZS5cblx0ICovXG5cdG1heWJlQWRkU3VyZmFjZXNfKCkge1xuXHRcdHZhciBzdXJmYWNlc1NlbGVjdG9yID0gJ1snICsgZGF0YUF0dHJpYnV0ZXMuc3VyZmFjZSArICddJztcblx0XHR0aGlzLnF1ZXJ5U2VsZWN0b3JBbGxBc0FycmF5XyhzdXJmYWNlc1NlbGVjdG9yKS5mb3JFYWNoKChzdXJmYWNlRWxlbWVudCkgPT4ge1xuXHRcdFx0dGhpcy51cGRhdGVFbGVtZW50SWRJZlNwZWNpYWxTdXJmYWNlXyhzdXJmYWNlRWxlbWVudCk7XG5cdFx0XHR0aGlzLmFwcC5hZGRTdXJmYWNlcyhzdXJmYWNlRWxlbWVudC5pZCk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcGF0Y2hlcyBhcHAgbmF2aWdhdGlvbiB0byB0aGUgY3VycmVudCBwYXRoIHdoZW4gaW5pdGlhbGl6ZXMuXG5cdCAqL1xuXHRtYXliZURpc3BhdGNoXygpIHtcblx0XHRpZiAodGhpcy5iYXNlRWxlbWVudC5oYXNBdHRyaWJ1dGUoZGF0YUF0dHJpYnV0ZXMuZGlzcGF0Y2gpKSB7XG5cdFx0XHR0aGlzLmFwcC5kaXNwYXRjaCgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGFwcCByb3V0ZSBieSBwYXJzaW5nIHZhbGlkIGxpbmsgZWxlbWVudHMuIEEgdmFsaWQgbGluayBlbGVtZW50IGlzIG9mXG5cdCAqIHRoZSBraW5kIGByZWw9XCJzZW5uYS1yb3V0ZVwiYC5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBsaW5rXG5cdCAqL1xuXHRtYXliZVBhcnNlTGlua1JvdXRlXyhsaW5rKSB7XG5cdFx0dmFyIHJvdXRlID0gbmV3IFJvdXRlKHRoaXMubWF5YmVQYXJzZUxpbmtSb3V0ZVBhdGhfKGxpbmspLCB0aGlzLm1heWJlUGFyc2VMaW5rUm91dGVIYW5kbGVyXyhsaW5rKSk7XG5cdFx0dGhpcy5hcHAuYWRkUm91dGVzKHJvdXRlKTtcblx0XHRjb25zb2xlLmxvZygnU2VubmEgc2Nhbm5lZCByb3V0ZSAnICsgcm91dGUuZ2V0UGF0aCgpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBwYXJzZSBsaW5rIHJvdXRlIGhhbmRsZXIuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbGlua1xuXHQgKiBAcmV0dXJuIHs/c3RyaW5nfVxuXHQgKi9cblx0bWF5YmVQYXJzZUxpbmtSb3V0ZUhhbmRsZXJfKGxpbmspIHtcblx0XHR2YXIgaGFuZGxlciA9IGxpbmsuZ2V0QXR0cmlidXRlKCd0eXBlJyk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChoYW5kbGVyKSkge1xuXHRcdFx0aGFuZGxlciA9IG9iamVjdC5nZXRPYmplY3RCeU5hbWUoaGFuZGxlcik7XG5cdFx0fVxuXHRcdHJldHVybiBoYW5kbGVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHBhcnNlIGxpbmsgcm91dGUgcGF0aC5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBsaW5rXG5cdCAqIEByZXR1cm4gez9zdHJpbmd9XG5cdCAqL1xuXHRtYXliZVBhcnNlTGlua1JvdXRlUGF0aF8obGluaykge1xuXHRcdHZhciBwYXRoID0gbGluay5nZXRBdHRyaWJ1dGUoJ2hyZWYnKTtcblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKHBhdGgpKSB7XG5cdFx0XHRpZiAocGF0aC5pbmRleE9mKCdyZWdleDonKSA9PT0gMCkge1xuXHRcdFx0XHRwYXRoID0gbmV3IFJlZ0V4cChwYXRoLnN1YnN0cmluZyg2KSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBwYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHNldHMgYXBwIGJhc2UgcGF0aCBmcm9tIGBkYXRhLXNlbm5hLWJhc2UtcGF0aGAgZGF0YSBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldEJhc2VQYXRoXygpIHtcblx0XHR2YXIgYmFzZVBhdGggPSB0aGlzLmJhc2VFbGVtZW50LmdldEF0dHJpYnV0ZShkYXRhQXR0cmlidXRlcy5iYXNlUGF0aCk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChiYXNlUGF0aCkpIHtcblx0XHRcdHRoaXMuYXBwLnNldEJhc2VQYXRoKGJhc2VQYXRoKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIGJhc2UgcGF0aCAnICsgYmFzZVBhdGgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBzZXRzIGFwcCBsaW5rIHNlbGVjdG9yIGZyb20gYGRhdGEtc2VubmEtbGluay1zZWxlY3RvcmAgZGF0YVxuXHQgKiBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldExpbmtTZWxlY3Rvcl8oKSB7XG5cdFx0dmFyIGxpbmtTZWxlY3RvciA9IHRoaXMuYmFzZUVsZW1lbnQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGVzLmxpbmtTZWxlY3Rvcik7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChsaW5rU2VsZWN0b3IpKSB7XG5cdFx0XHR0aGlzLmFwcC5zZXRMaW5rU2VsZWN0b3IobGlua1NlbGVjdG9yKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIGxpbmsgc2VsZWN0b3IgJyArIGxpbmtTZWxlY3Rvcik7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHNldHMgYXBwIGxpbmsgbG9hZGluZyBjc3MgY2xhc3MgZnJvbSBgZGF0YS1zZW5uYS1sb2FkaW5nLWNzcy1jbGFzc2Bcblx0ICogZGF0YSBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldExvYWRpbmdDc3NDbGFzc18oKSB7XG5cdFx0dmFyIGxvYWRpbmdDc3NDbGFzcyA9IHRoaXMuYmFzZUVsZW1lbnQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGVzLmxvYWRpbmdDc3NDbGFzcyk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChsb2FkaW5nQ3NzQ2xhc3MpKSB7XG5cdFx0XHR0aGlzLmFwcC5zZXRMb2FkaW5nQ3NzQ2xhc3MobG9hZGluZ0Nzc0NsYXNzKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIGxvYWRpbmcgY3NzIGNsYXNzICcgKyBsb2FkaW5nQ3NzQ2xhc3MpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBzZXRzIGFwcCB1cGRhdGUgc2Nyb2xsIHBvc2l0aW9uIGZyb21cblx0ICogYGRhdGEtc2VubmEtdXBkYXRlLXNjcm9sbC1wb3NpdGlvbmAgZGF0YSBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldFVwZGF0ZVNjcm9sbFBvc2l0aW9uXygpIHtcblx0XHR2YXIgdXBkYXRlU2Nyb2xsUG9zaXRpb24gPSB0aGlzLmJhc2VFbGVtZW50LmdldEF0dHJpYnV0ZShkYXRhQXR0cmlidXRlcy51cGRhdGVTY3JvbGxQb3NpdGlvbik7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbCh1cGRhdGVTY3JvbGxQb3NpdGlvbikpIHtcblx0XHRcdGlmICh1cGRhdGVTY3JvbGxQb3NpdGlvbiA9PT0gJ2ZhbHNlJykge1xuXHRcdFx0XHR0aGlzLmFwcC5zZXRVcGRhdGVTY3JvbGxQb3NpdGlvbihmYWxzZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmFwcC5zZXRVcGRhdGVTY3JvbGxQb3NpdGlvbih0cnVlKTtcblx0XHRcdH1cblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIHVwZGF0ZSBzY3JvbGwgcG9zaXRpb24gJyArIHVwZGF0ZVNjcm9sbFBvc2l0aW9uKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUXVlcmllcyBlbGVtZW50cyBmcm9tIGRvY3VtZW50IGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIGVsZW1lbnRzLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNlbGVjdG9yXG5cdCAqIEByZXR1cm4ge2FycmF5LjxFbGVtZW50Pn1cblx0ICovXG5cdHF1ZXJ5U2VsZWN0b3JBbGxBc0FycmF5XyhzZWxlY3Rvcikge1xuXHRcdHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChnbG9iYWxzLmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIGVsZW1lbnQgaWQgaWYgaGFuZGxlZCBhcyBzcGVjaWFsIHN1cmZhY2UgZWxlbWVudC4gU29tZSBzdXJmYWNlc1xuXHQgKiBhcmUgc2xpZ2h0bHkgZGlmZmVyZW50IGZyb20gb3RoZXJzLCBsaWtlIHdoZW4gdGhyZWF0aW5nIDxjb2RlPmJvZHk8L2NvZGU+XG5cdCAqIGFzIHN1cmZhY2UuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuXHQgKi9cblx0dXBkYXRlRWxlbWVudElkSWZTcGVjaWFsU3VyZmFjZV8oZWxlbWVudCkge1xuXHRcdGlmICghZWxlbWVudC5pZCAmJiBlbGVtZW50ID09PSBnbG9iYWxzLmRvY3VtZW50LmJvZHkpIHtcblx0XHRcdGVsZW1lbnQuaWQgPSAnc2VubmFfc3VyZmFjZV8nICsgZ2V0VWlkKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGJhc2UgZWxlbWVudC5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBiYXNlRWxlbWVudFxuXHQgKi9cblx0c2V0QmFzZUVsZW1lbnQoYmFzZUVsZW1lbnQpIHtcblx0XHR0aGlzLmJhc2VFbGVtZW50ID0gYmFzZUVsZW1lbnQ7XG5cdH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBBcHBEYXRhQXR0cmlidXRlSGFuZGxlcjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IGdsb2JhbHMgZnJvbSAnLi4vZ2xvYmFscy9nbG9iYWxzJztcbmltcG9ydCBBcHBEYXRhQXR0cmlidXRlSGFuZGxlciBmcm9tICcuL0FwcERhdGFBdHRyaWJ1dGVIYW5kbGVyJztcblxuLyoqXG4gKiBEYXRhIGF0dHJpYnV0ZSBoYW5kbGVyLlxuICogQHR5cGUge0FwcERhdGFBdHRyaWJ1dGVIYW5kbGVyfVxuICovXG52YXIgZGF0YUF0dHJpYnV0ZUhhbmRsZXIgPSBuZXcgQXBwRGF0YUF0dHJpYnV0ZUhhbmRsZXIoKTtcblxuZ2xvYmFscy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZnVuY3Rpb24oKSB7XG5cdGRhdGFBdHRyaWJ1dGVIYW5kbGVyLnNldEJhc2VFbGVtZW50KGdsb2JhbHMuZG9jdW1lbnQuYm9keSk7XG5cdGRhdGFBdHRyaWJ1dGVIYW5kbGVyLmhhbmRsZSgpO1xufSk7XG5cbmV4cG9ydCBkZWZhdWx0IGRhdGFBdHRyaWJ1dGVIYW5kbGVyOyIsIi8qKlxuICogQHJldHVybnMgU3RyaW5nIGNvbnRhaW5pbmcgdGhlIGN1cnJlbnQgc2VubmEgdmVyc2lvblxuICovXG5cbmNvbnN0IHZlcnNpb24gPSAnPCU9IHZlcnNpb24gJT4nO1xuXG5leHBvcnQgZGVmYXVsdCB2ZXJzaW9uOyJdLCJuYW1lcyI6WyJpc0RlZiIsInZhbCIsInVuZGVmaW5lZCIsImlzRGVmQW5kTm90TnVsbCIsImlzTnVsbCIsImlzRG9jdW1lbnQiLCJub2RlVHlwZSIsImlzRnVuY3Rpb24iLCJpc09iamVjdCIsInR5cGUiLCJpc1N0cmluZyIsIlN0cmluZyIsImlzU2VydmVyU2lkZSIsIm9wdGlvbnMiLCJjaGVja0VudiIsInNlcnZlclNpZGUiLCJwcm9jZXNzIiwiYnJvd3NlciIsImVudiIsIk5PREVfRU5WIiwiYXJyYXkiLCJhcnIxIiwiYXJyMiIsImxlbmd0aCIsImkiLCJhcnIiLCJvdXRwdXQiLCJBcnJheSIsImlzQXJyYXkiLCJmbGF0dGVuIiwicHVzaCIsIm9iaiIsImluZGV4T2YiLCJydiIsInJlbW92ZUF0IiwicHJvdG90eXBlIiwic3BsaWNlIiwiY2FsbCIsInN0YXJ0IiwiZW5kIiwic2xpY2VkIiwiYXN5bmMiLCJ0aHJvd0V4Y2VwdGlvbiIsImV4Y2VwdGlvbiIsIm5leHRUaWNrIiwicnVuIiwiY2FsbGJhY2siLCJjb250ZXh0Iiwid29ya1F1ZXVlU2NoZWR1bGVkXyIsInByb2Nlc3NXb3JrUXVldWUiLCJ3b3JrUXVldWVfIiwiV29ya0l0ZW1fIiwid29ya0l0ZW1zIiwid29ya0l0ZW0iLCJmbiIsInNjb3BlIiwiZSIsImNiIiwiYmluZCIsIndyYXBDYWxsYmFja18iLCJzZXRJbW1lZGlhdGVfIiwic2V0SW1tZWRpYXRlIiwiZ2V0U2V0SW1tZWRpYXRlRW11bGF0b3JfIiwiQ2hhbm5lbCIsIk1lc3NhZ2VDaGFubmVsIiwid2luZG93IiwicG9zdE1lc3NhZ2UiLCJhZGRFdmVudExpc3RlbmVyIiwiaWZyYW1lIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50Iiwic3R5bGUiLCJkaXNwbGF5Iiwic3JjIiwidGl0bGUiLCJkb2N1bWVudEVsZW1lbnQiLCJhcHBlbmRDaGlsZCIsIndpbiIsImNvbnRlbnRXaW5kb3ciLCJkb2MiLCJvcGVuIiwid3JpdGUiLCJjbG9zZSIsIm1lc3NhZ2UiLCJNYXRoIiwicmFuZG9tIiwib3JpZ2luIiwibG9jYXRpb24iLCJwcm90b2NvbCIsImhvc3QiLCJvbm1lc3NhZ2UiLCJkYXRhIiwicG9ydDEiLCJwb3J0MiIsImNoYW5uZWwiLCJoZWFkIiwidGFpbCIsIm5leHQiLCJzY3JpcHQiLCJvbnJlYWR5c3RhdGVjaGFuZ2UiLCJwYXJlbnROb2RlIiwicmVtb3ZlQ2hpbGQiLCJEaXNwb3NhYmxlIiwiZGlzcG9zZWRfIiwiZGlzcG9zZUludGVybmFsIiwib2JqZWN0IiwidGFyZ2V0Iiwia2V5Iiwic291cmNlIiwiYXJncyIsIm5hbWUiLCJwYXJ0cyIsInNwbGl0IiwicmVkdWNlIiwicGFydCIsIm1hcHBlZE9iaiIsImtleXMiLCJPYmplY3QiLCJvYmoxIiwib2JqMiIsImtleXMxIiwia2V5czIiLCJzdHJpbmciLCJzdHIxIiwic3RyMiIsInRlc3QxIiwidG9Mb3dlckNhc2UiLCJ0ZXN0MiIsInN0ciIsInJlcGxhY2UiLCJ4IiwiZmxvb3IiLCJ0b1N0cmluZyIsImFicyIsIkRhdGUiLCJub3ciLCJoYXNoIiwibGVuIiwiY2hhckNvZGVBdCIsInZhbHVlIiwic3Vic3RyaW5nIiwiTUVUQUxfREFUQSIsImRvbURhdGEiLCJlbGVtZW50IiwiaW5pdGlhbFZhbHVlIiwiRXZlbnRIYW5kbGUiLCJlbWl0dGVyIiwiZXZlbnQiLCJsaXN0ZW5lciIsImVtaXR0ZXJfIiwiZXZlbnRfIiwibGlzdGVuZXJfIiwicmVtb3ZlTGlzdGVuZXIiLCJpc0Rpc3Bvc2VkIiwic2luZ2xlQXJyYXlfIiwiRXZlbnRFbWl0dGVyIiwiZXZlbnRzXyIsImxpc3RlbmVySGFuZGxlcnNfIiwic2hvdWxkVXNlRmFjYWRlXyIsImhvbGRlciIsImhhbmRsZXIiLCJkZWZhdWx0TGlzdGVuZXIiLCJ2YWxpZGF0ZUxpc3RlbmVyXyIsImV2ZW50cyIsInRvRXZlbnRzQXJyYXlfIiwiYWRkU2luZ2xlTGlzdGVuZXJfIiwicnVuTGlzdGVuZXJIYW5kbGVyc18iLCJhZGRIYW5kbGVyXyIsImdldFNob3VsZFVzZUZhY2FkZSIsImZhY2FkZSIsInByZXZlbnRlZERlZmF1bHQiLCJsaXN0ZW5lcnMiLCJnZXRSYXdMaXN0ZW5lcnNfIiwic2xpY2UiLCJhcmd1bWVudHMiLCJydW5MaXN0ZW5lcnNfIiwiYnVpbGRGYWNhZGVfIiwiZGlyZWN0TGlzdGVuZXJzIiwidG9BcnJheSIsImNvbmNhdCIsIm1hcCIsImFtb3VudCIsIm1hbnlfIiwic2VsZiIsImhhbmRsZXJJbnRlcm5hbCIsImFwcGx5IiwibGlzdGVuZXJPYmoiLCJyZW1vdmVNYXRjaGluZ0xpc3RlbmVyT2Jqc18iLCJhZGRMaXN0ZW5lciIsIm1hbnkiLCJsaXN0ZW5lck9ianMiLCJmaW5hbExpc3RlbmVycyIsIm1hdGNoZXNMaXN0ZW5lcl8iLCJvZmYiLCJoYW5kbGVycyIsImRlZmF1bHRMaXN0ZW5lcnMiLCJkZWZhdWx0IiwiaiIsInNob3VsZFVzZUZhY2FkZSIsIlR5cGVFcnJvciIsIkV2ZW50RW1pdHRlclByb3h5Iiwib3JpZ2luRW1pdHRlciIsInRhcmdldEVtaXR0ZXIiLCJibGFja2xpc3QiLCJ3aGl0ZWxpc3QiLCJibGFja2xpc3RfIiwib3JpZ2luRW1pdHRlcl8iLCJwZW5kaW5nRXZlbnRzXyIsInByb3hpZWRFdmVudHNfIiwidGFyZ2V0RW1pdHRlcl8iLCJ3aGl0ZWxpc3RfIiwic3RhcnRQcm94eV8iLCJvbiIsInJlbW92ZUxpc3RlbmVyc18iLCJlbWl0Iiwic2hvdWxkUHJveHlFdmVudF8iLCJ0cnlUb0FkZExpc3RlbmVyXyIsImZvckVhY2giLCJwcm94eUV2ZW50Iiwib25MaXN0ZW5lciIsImFkZExpc3RlbmVyXyIsImVtaXRPblRhcmdldF8iLCJFdmVudEhhbmRsZXIiLCJldmVudEhhbmRsZXNfIiwiRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGUiLCJzZWxlY3RvciIsInNlbGVjdG9yXyIsImRlbGVnYXRpbmciLCJnZXQiLCJzZWxlY3RvcnMiLCJyZW1vdmUiLCJEb21FdmVudEhhbmRsZSIsImNhcHR1cmUiLCJjYXB0dXJlXyIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJlbGVtZW50c0J5VGFnXyIsInN1cHBvcnRDYWNoZV8iLCJjdXN0b21FdmVudHMiLCJMQVNUX0NPTlRBSU5FUiIsIlVTRV9DQVBUVVJFIiwiYWRkQ2xhc3NlcyIsImVsZW1lbnRzIiwiY2xhc3NlcyIsImFkZENsYXNzZXNXaXRoTmF0aXZlXyIsImNsYXNzTmFtZSIsImNsYXNzTGlzdCIsImFkZCIsImFkZENsYXNzZXNXaXRob3V0TmF0aXZlXyIsImVsZW1lbnRDbGFzc05hbWUiLCJjbGFzc2VzVG9BcHBlbmQiLCJhZGRFbGVtZW50TGlzdGVuZXJfIiwiZXZlbnROYW1lIiwiYWRkU2VsZWN0b3JMaXN0ZW5lcl8iLCJkZWxlZ2F0aW5nRGF0YSIsImFkZFRvQXJyXyIsImF0dGFjaERlbGVnYXRlRXZlbnRfIiwiaGFuZGxlRGVsZWdhdGVFdmVudF8iLCJjbG9zZXN0IiwibWF0Y2giLCJhcHBlbmQiLCJwYXJlbnQiLCJjaGlsZCIsImJ1aWxkRnJhZ21lbnQiLCJpc05vZGVMaXN0TGlrZSIsImNoaWxkQXJyIiwiaHRtbFN0cmluZyIsInRlbXBEaXYiLCJpbm5lckhUTUwiLCJmaXJzdENoaWxkIiwiZnJhZ21lbnQiLCJjcmVhdGVEb2N1bWVudEZyYWdtZW50IiwiY29udGFpbnMiLCJlbGVtZW50MSIsImVsZW1lbnQyIiwiZGVsZWdhdGUiLCJzZWxlY3Rvck9yVGFyZ2V0IiwiY3VzdG9tQ29uZmlnIiwib3JpZ2luYWxFdmVudCIsImRlZmF1bHRMaXN0ZW5lcl8iLCJpc0FibGVUb0ludGVyYWN0V2l0aF8iLCJub2RlIiwiZXZlbnRPYmoiLCJidXR0b24iLCJtYXRjaGVzU2VsZWN0b3IiLCJ0YWdOYW1lIiwiZGlzYWJsZWQiLCJpdGVtIiwiZXhpdERvY3VtZW50IiwicmV0IiwiY29udGFpbmVyIiwiY3VycmVudFRhcmdldCIsImRlZkZucyIsInRyaWdnZXJEZWxlZ2F0ZWRMaXN0ZW5lcnNfIiwidHJpZ2dlckRlZmF1bHREZWxlZ2F0ZWRMaXN0ZW5lcnNfIiwiZGVsZWdhdGVUYXJnZXQiLCJwIiwiRWxlbWVudCIsIm0iLCJtYXRjaGVzIiwid2Via2l0TWF0Y2hlc1NlbGVjdG9yIiwibW96TWF0Y2hlc1NlbGVjdG9yIiwibXNNYXRjaGVzU2VsZWN0b3IiLCJvTWF0Y2hlc1NlbGVjdG9yIiwibWF0Y2hGYWxsYmFja18iLCJub2RlcyIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJub3JtYWxpemVEZWxlZ2F0ZUV2ZW50XyIsInN0b3BQcm9wYWdhdGlvbiIsInN0b3BQcm9wYWdhdGlvbl8iLCJzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24iLCJzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb25fIiwib25jZSIsImRvbUV2ZW50SGFuZGxlIiwicmVnaXN0ZXJDdXN0b21FdmVudCIsInJlbW92ZUNoaWxkcmVuIiwicmVtb3ZlQ2xhc3NlcyIsInJlbW92ZUNsYXNzZXNXaXRoTmF0aXZlXyIsInJlbW92ZUNsYXNzZXNXaXRob3V0TmF0aXZlXyIsInRyaW0iLCJzdG9wcGVkIiwic3RvcHBlZEltbWVkaWF0ZSIsInN1cHBvcnRzRXZlbnQiLCJ0YWciLCJoYXNPd25Qcm9wZXJ0eSIsImRlZmF1bHRQcmV2ZW50ZWQiLCJkZWZhdWx0Rm5zIiwiY3VyckVsZW1lbnQiLCJsaW1pdCIsInRyaWdnZXJFbGVtZW50TGlzdGVuZXJzXyIsInRyaWdnZXJTZWxlY3Rvckxpc3RlbmVyc18iLCJsYXN0Q29udGFpbmVyIiwidHJpZ2dlckxpc3RlbmVyc18iLCJEb21FdmVudEVtaXR0ZXJQcm94eSIsImlzRGVsZWdhdGVFdmVudF8iLCJpbmRleCIsInN1YnN0ciIsImJhYmVsSGVscGVycy5nZXQiLCJpc1N1cHBvcnRlZERvbUV2ZW50XyIsImZlYXR1cmVzIiwiYW5pbWF0aW9uRXZlbnROYW1lXyIsImNoZWNrQW5pbWF0aW9uRXZlbnROYW1lXyIsInByZWZpeGVzIiwidHlwZVRpdGxlQ2FzZSIsInJlcGxhY2VJbnRlcnZhbCIsInRvVXBwZXJDYXNlIiwic3VmZml4ZXMiLCJhbmltYXRpb25FbGVtZW50XyIsImF0dHJPcmRlckNoYW5nZV8iLCJvcmlnaW5hbENvbnRlbnQiLCJnbG9iYWxFdmFsIiwidGV4dCIsImFwcGVuZEZuIiwiZGVmYXVsdEZuIiwicnVuRmlsZSIsInNjcmlwdHMiLCJydW5TY3JpcHRzSW5PcmRlciIsInJ1blNjcmlwdCIsImdsb2JhbEV2YWxTdHlsZXMiLCJocmVmIiwibGluayIsInJlbCIsInJ1blN0eWxlIiwic3R5bGVzIiwibG9hZENvdW50IiwicmVnaXN0ZXJFdmVudHMiLCJtb3VzZUV2ZW50TWFwIiwicmVsYXRlZCIsInJlbGF0ZWRUYXJnZXQiLCJjdXN0b21UeXBlIiwiYW5pbWF0aW9uRXZlbnRNYXAiLCJldmVudFR5cGUiLCJjaGVja0FuaW1hdGlvbkV2ZW50TmFtZSIsImdsb2JhbHMiLCJjb21wYXRpYmlsaXR5TW9kZURhdGFfIiwidW5pcXVlSWRDb3VudGVyXyIsIlVJRF9QUk9QRVJUWSIsImFic3RyYWN0TWV0aG9kIiwiRXJyb3IiLCJkaXNhYmxlQ29tcGF0aWJpbGl0eU1vZGUiLCJlbmFibGVDb21wYXRpYmlsaXR5TW9kZSIsImdldENvbXBhdGliaWxpdHlNb2RlRGF0YSIsIl9fTUVUQUxfQ09NUEFUSUJJTElUWV9fIiwiZ2V0Rmlyc3RUcnV0aHlfIiwiYSIsImIiLCJnZXRGdW5jdGlvbk5hbWUiLCJnZXRTdGF0aWNQcm9wZXJ0eSIsImN0b3IiLCJwcm9wZXJ0eU5hbWUiLCJtZXJnZUZuIiwibWVyZ2VkTmFtZSIsIm1lcmdlZCIsIl9fcHJvdG9fXyIsImlzUHJvdG90eXBlT2YiLCJGdW5jdGlvbiIsImdldFVpZCIsIm5vSW5oZXJpdGFuY2UiLCJpZCIsImlkZW50aXR5RnVuY3Rpb24iLCJyZXR1cm5WYWx1ZSIsImlzQm9vbGVhbiIsImlzRG9jdW1lbnRGcmFnbWVudCIsImlzRWxlbWVudCIsImlzTnVtYmVyIiwiaXNXaW5kb3ciLCJpc1Byb21pc2UiLCJ0aGVuIiwibnVsbEZ1bmN0aW9uIiwicGFyc2VGcm9tQW5jaG9yIiwib3B0X3VyaSIsInRlc3QiLCJob3N0bmFtZSIsInBhc3N3b3JkIiwicGF0aG5hbWUiLCJwb3J0Iiwic2VhcmNoIiwidXNlcm5hbWUiLCJwYXJzZSIsIlVSTCIsInVybCIsImNyZWF0ZSIsIk11bHRpTWFwIiwidmFsdWVzIiwic2l6ZSIsIm5hbWVzIiwiSlNPTiIsInN0cmluZ2lmeSIsInNldCIsIlRyZWVOb2RlIiwidmFsdWVfIiwicGFyZW50XyIsImNoaWxkcmVuXyIsInNldFBhcmVudCIsImN1cnJlbnQiLCJnZXRQYXJlbnQiLCJhbmNlc3RvcnMiLCJnZXRDaGlsZHJlbiIsIkVNUFRZX0FSUkFZIiwiZGVwdGgiLCJyb290IiwiZ2V0Q2hpbGRDb3VudCIsIm9wdF9wcmVvcmRlckZuIiwib3B0X3Bvc3RvcmRlckZuIiwidHJhdmVyc2UiLCJhc3NlcnRDaGlsZEhhc05vUGFyZW50IiwicGFyc2VGbl8iLCJVcmkiLCJtYXliZUFkZFByb3RvY29sQW5kSG9zdG5hbWVfIiwibXVsdGltYXAiLCJnZXRBbGwiLCJhZGRQYXJhbWV0ZXJWYWx1ZSIsImVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfIiwicXVlcnkiLCJwYXJhbSIsInVybERlY29kZSIsImdldEhvc3RuYW1lIiwiZ2V0UG9ydCIsIkhPU1ROQU1FX1BMQUNFSE9MREVSIiwiZ2V0SG9zdCIsImdldFByb3RvY29sIiwicXVlcnlzdHJpbmciLCJnZXRQYXJhbWV0ZXJOYW1lcyIsImdldFBhcmFtZXRlclZhbHVlcyIsImVuY29kZVVSSUNvbXBvbmVudCIsInNldFBhcmFtZXRlclZhbHVlIiwiUkFORE9NX1BBUkFNIiwiZ2V0UmFuZG9tU3RyaW5nIiwiREVGQVVMVF9QUk9UT0NPTCIsImNoYXJBdCIsInJlbW92ZVBhcmFtZXRlciIsImdldFBhdGhuYW1lIiwiZ2V0U2VhcmNoIiwiZ2V0SGFzaCIsInBhcnNlRm4iLCJiYXNlUGF0aCIsInBhdGhzIiwicGF0aCIsImpvaW4iLCJkZWNvZGVVUklDb21wb25lbnQiLCJpc1NlY3VyZSIsInV0aWxzIiwiYXR0cmlidXRlcyIsImF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZSIsImdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoIiwib2Zmc2V0TGVmdCIsIm9mZnNldFRvcCIsIm9mZnNldFBhcmVudCIsInVyaSIsImN1cnJlbnRCcm93c2VyUGF0aCIsImdldFVybFBhdGhXaXRob3V0SGFzaCIsImdldFVybFBhdGgiLCJoaXN0b3J5IiwicHVzaFN0YXRlIiwiZXJyIiwiZXJyb3IiLCJyZW1vdmVBdHRyaWJ1dGUiLCJyZWZlcnJlciIsImRlZmluZVByb3BlcnR5IiwiVGhlbmFibGUiLCJJTVBMRU1FTlRFRF9CWV9QUk9QIiwiYWRkSW1wbGVtZW50YXRpb24iLCIkZ29vZ19UaGVuYWJsZSIsImlzSW1wbGVtZW50ZWRCeSIsInBhcnRpYWwiLCJuZXdBcmdzIiwiQ2FuY2VsbGFibGVQcm9taXNlIiwicmVzb2x2ZXIiLCJvcHRfY29udGV4dCIsInN0YXRlXyIsIlN0YXRlXyIsIlBFTkRJTkciLCJyZXN1bHRfIiwiY2FsbGJhY2tFbnRyaWVzXyIsImV4ZWN1dGluZ18iLCJVTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZIiwidW5oYW5kbGVkUmVqZWN0aW9uSWRfIiwiaGFkVW5oYW5kbGVkUmVqZWN0aW9uXyIsInJlc29sdmVfIiwiRlVMRklMTEVEIiwicmVhc29uIiwiUkVKRUNURUQiLCJDYWxsYmFja0VudHJ5XyIsInJlc29sdmUiLCJvcHRfdmFsdWUiLCJyZWplY3QiLCJvcHRfcmVhc29uIiwicmFjZSIsInByb21pc2VzIiwicHJvbWlzZSIsImFsbCIsInRvRnVsZmlsbCIsIm9uRnVsZmlsbCIsIm9uUmVqZWN0IiwiZmlyc3RGdWxmaWxsZWQiLCJ0b1JlamVjdCIsInJlYXNvbnMiLCJvcHRfb25GdWxmaWxsZWQiLCJvcHRfb25SZWplY3RlZCIsImFkZENoaWxkUHJvbWlzZV8iLCJ0aGVuQWx3YXlzIiwib25SZXNvbHZlZCIsImhhbmRsZVJlamVjdGlvbl8iLCJhZGRDYWxsYmFja0VudHJ5XyIsInRoZW5DYXRjaCIsIm9uUmVqZWN0ZWQiLCJjYXRjaCIsImNhbmNlbCIsIm9wdF9tZXNzYWdlIiwiQ2FuY2VsbGF0aW9uRXJyb3IiLCJJU19DQU5DRUxMQVRJT05fRVJST1IiLCJjYW5jZWxJbnRlcm5hbF8iLCJjYW5jZWxDaGlsZF8iLCJjaGlsZFByb21pc2UiLCJjaGlsZENvdW50IiwiY2hpbGRJbmRleCIsImVudHJ5IiwiY2FsbGJhY2tFbnRyeSIsImV4ZWN1dGVDYWxsYmFja18iLCJzY2hlZHVsZUNhbGxiYWNrc18iLCJvbkZ1bGZpbGxlZCIsInJlc3VsdCIsInVuYmxvY2tBbmRGdWxmaWxsXyIsIkJMT0NLRUQiLCJ1bmJsb2NrQW5kUmVqZWN0XyIsInN0YXRlIiwidHJ5VGhlbl8iLCJhZGRVbmhhbmRsZWRSZWplY3Rpb25fIiwidGhlbmFibGUiLCJjYWxsZWQiLCJleGVjdXRlQ2FsbGJhY2tzXyIsImVudHJpZXMiLCJyZW1vdmVVbmhhbmRsZWRSZWplY3Rpb25fIiwic2V0VGltZW91dCIsInNldFVuaGFuZGxlZFJlamVjdGlvbkhhbmRsZXIiLCJkZWJvdW5jZSIsImRlbGF5IiwiZGVib3VuY2VkIiwiY2FuY2VsRGVib3VuY2UiLCJSRUdFWCIsImNvbnZlcnRNYXRjaGVzVG9PYmoiLCJjb252ZXJ0VG9rZW5zVG9SZWdleCIsInRva2VucyIsInJlZ2V4IiwiY29yZSIsImVzY2FwZSIsImVuY2xvc2VOb25DYXB0dXJpbmdHcm91cCIsInBhdHRlcm4iLCJyZXBlYXQiLCJwcmVmaXgiLCJvcHRpb25hbCIsIlJlZ0V4cCIsIm1ha2VUcmFpbGluZ1NsYXNoT3B0aW9uYWwiLCJyb3V0ZU9yVG9rZW5zIiwicm91dGUiLCJ1bm5hbWVkQ291bnQiLCJjdXJyUGF0aCIsImV4ZWMiLCJwYXJhbVBhdHRlcm4iLCJ1bm5hbWVkUGF0dGVybiIsIm1vZGlmaWVyIiwidG9SZWdleCIsImV4dHJhY3REYXRhIiwicGFyYW1JbmRleCIsIlJvdXRlIiwicGFyc2VkRGF0YV8iLCJidWlsZFBhcnNlZERhdGFfIiwiQ2FjaGVhYmxlIiwiY2FjaGUiLCJjYWNoZWFibGUiLCJjb250ZW50IiwiY2xlYXJDYWNoZSIsIlNjcmVlbiIsIm1ha2VJZF8iLCJtZXRhcyIsImxvZyIsInN1cmZhY2VzIiwic0lkIiwiYWN0aXZlQ2hpbGQiLCJydW5TY3JpcHRzSW5FbGVtZW50IiwidHJhbnNpdGlvbnMiLCJzdXJmYWNlIiwiZGVmZXJyZWQiLCJzaG93IiwiU3VyZmFjZSIsImRlZmF1bHRDaGlsZCIsInRyYW5zaXRpb25GbiIsImdldENoaWxkIiwiREVGQVVMVCIsIm1heWJlV3JhcENvbnRlbnRBc0RlZmF1bHRfIiwic2NyZWVuSWQiLCJvcHRfY29udGVudCIsImNyZWF0ZUNoaWxkIiwidHJhbnNpdGlvbiIsImdldEVsZW1lbnQiLCJnZXRFbGVtZW50QnlJZCIsImFkZENvbnRlbnQiLCJmcm9tIiwidG8iLCJkZWZhdWx0VHJhbnNpdGlvbiIsIk5hdmlnYXRpb25TdHJhdGVneSIsIkFwcCIsImFjdGl2ZVNjcmVlbiIsImFjdGl2ZVBhdGgiLCJhbGxvd1ByZXZlbnROYXZpZ2F0ZSIsImJyb3dzZXJQYXRoQmVmb3JlTmF2aWdhdGUiLCJjYXB0dXJlU2Nyb2xsUG9zaXRpb25Gcm9tU2Nyb2xsRXZlbnQiLCJkZWZhdWx0VGl0bGUiLCJmb3JtU2VsZWN0b3IiLCJpZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGgiLCJsaW5rU2VsZWN0b3IiLCJsb2FkaW5nQ3NzQ2xhc3MiLCJuYXRpdmVTY3JvbGxSZXN0b3JhdGlvblN1cHBvcnRlZCIsIm5hdmlnYXRpb25TdHJhdGVneSIsIklNTUVESUFURSIsImlzTmF2aWdhdGlvblBlbmRpbmciLCJwZW5kaW5nTmF2aWdhdGUiLCJwb3BzdGF0ZVNjcm9sbExlZnQiLCJwb3BzdGF0ZVNjcm9sbFRvcCIsInJlZGlyZWN0UGF0aCIsInJvdXRlcyIsInNjaGVkdWxlZE5hdmlnYXRpb25RdWV1ZSIsInNjcmVlbnMiLCJza2lwTG9hZFBvcHN0YXRlIiwidXBkYXRlU2Nyb2xsUG9zaXRpb24iLCJhcHBFdmVudEhhbmRsZXJzXyIsIm9uU2Nyb2xsXyIsIm9uTG9hZF8iLCJvblBvcHN0YXRlXyIsIm9uU3RhcnROYXZpZ2F0ZV8iLCJvbkJlZm9yZU5hdmlnYXRlXyIsIm9uQmVmb3JlTmF2aWdhdGVEZWZhdWx0XyIsIm9uQmVmb3JlVW5sb2FkRGVmYXVsdF8iLCJzZXRMaW5rU2VsZWN0b3IiLCJzZXRGb3JtU2VsZWN0b3IiLCJtYXliZU92ZXJsb2FkQmVmb3JlVW5sb2FkXyIsImdldElkIiwiaXNXZWJVcmkiLCJpc0xpbmtTYW1lT3JpZ2luXyIsImlzU2FtZUJhc2VQYXRoXyIsImlzQ3VycmVudEJyb3dzZXJQYXRoIiwiZmluZFJvdXRlIiwicmVtb3ZlU2NyZWVuIiwic2NyZWVuIiwiZ2V0SGFuZGxlciIsImNsZWFyU2NyZWVuc0NhY2hlIiwiZm9ybUV2ZW50SGFuZGxlcl8iLCJsaW5rRXZlbnRIYW5kbGVyXyIsInJlbW92ZUFsbExpc3RlbmVycyIsIm5hdmlnYXRlIiwiZ2V0Q3VycmVudEJyb3dzZXJQYXRoIiwib3B0X3JlcGxhY2VIaXN0b3J5Iiwic3RvcFBlbmRpbmdOYXZpZ2F0ZV8iLCJuZXh0U2NyZWVuIiwiY3JlYXRlU2NyZWVuSW5zdGFuY2UiLCJtYXliZVByZXZlbnREZWFjdGl2YXRlXyIsIm1heWJlUHJldmVudEFjdGl2YXRlXyIsImxvYWQiLCJTQ0hFRFVMRV9MQVNUIiwiZGVhY3RpdmF0ZSIsInByZXBhcmVOYXZpZ2F0ZUhpc3RvcnlfIiwicHJlcGFyZU5hdmlnYXRlU3VyZmFjZXNfIiwiZXh0cmFjdFBhcmFtcyIsImV2YWx1YXRlU3R5bGVzIiwiZmxpcCIsImV2YWx1YXRlU2NyaXB0cyIsIm1heWJlVXBkYXRlU2Nyb2xsUG9zaXRpb25TdGF0ZV8iLCJzeW5jU2Nyb2xsUG9zaXRpb25TeW5jVGhlbkFzeW5jXyIsImZpbmFsaXplTmF2aWdhdGVfIiwiaGFuZGxlTmF2aWdhdGVFcnJvcl8iLCJzY2hlZHVsZWROYXZpZ2F0aW9uIiwic2hpZnQiLCJtYXliZU5hdmlnYXRlXyIsImdldFJvdXRlUGF0aCIsImFjdGl2YXRlIiwiaXNDYWNoZWFibGUiLCJjYXB0dXJlZEZvcm1FbGVtZW50IiwiY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCIsIm1hdGNoZXNQYXRoIiwiZ2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoIiwiZ2V0VXJsUGF0aFdpdGhvdXRIYXNoQW5kU2VhcmNoIiwic3RhY2siLCJob3N0VXJpIiwibG9jYXRpb25Ib3N0VXJpIiwid2lubmVyIiwic3dpdGNoU2Nyb2xsUG9zaXRpb25SYWNlIiwic2Nyb2xsVG8iLCJzY3JvbGxMZWZ0Iiwic2Nyb2xsVG9wIiwibmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25fIiwic2Nyb2xsUmVzdG9yYXRpb24iLCJtaXhpbiIsImNhbk5hdmlnYXRlIiwiaXNOYXZpZ2F0aW9uU2NoZWR1bGVkIiwibWF5YmVTY2hlZHVsZU5hdmlnYXRpb25fIiwicHJldmVudERlZmF1bHQiLCJuYXZpZ2F0ZUZhaWxlZCIsImlzU2NoZWR1bGVkTmF2aWdhdGlvbiIsIm9uYmVmb3JldW5sb2FkIiwiX29uYmVmb3JldW5sb2FkIiwiX292ZXJsb2FkZWQiLCJiZWZvcmVBY3RpdmF0ZSIsInByZXZlbnQiLCJiZWZvcmVEZWFjdGl2YXRlIiwiYW5jaG9yRWxlbWVudCIsImdldE5vZGVPZmZzZXQiLCJzYXZlSGlzdG9yeUN1cnJlbnRQYWdlU2Nyb2xsUG9zaXRpb25fIiwib3B0X2V2ZW50IiwiaXNIdG1sNUhpc3RvcnlTdXBwb3J0ZWQiLCJmb3JtIiwicmVwbGFjZUhpc3RvcnkiLCJmdW5jIiwiYWx0S2V5IiwiY3RybEtleSIsIm1ldGFLZXkiLCJzaGlmdEtleSIsIm1ldGhvZCIsImJ1dHRvblNlbGVjdG9yIiwiYWN0aXZlRWxlbWVudCIsInF1ZXJ5U2VsZWN0b3IiLCJhY3Rpb24iLCJtYXliZVJlcG9zaXRpb25TY3JvbGxUb0hhc2hlZEFuY2hvciIsInJlbG9hZFBhZ2UiLCJzZW5uYSIsImxvY2tIaXN0b3J5U2Nyb2xsUG9zaXRpb25fIiwic2V0UmVmZXJyZXIiLCJzZXRIb3N0bmFtZSIsInNldFBvcnQiLCJwYWdlWU9mZnNldCIsInBhZ2VYT2Zmc2V0IiwibWF5YmVEaXNhYmxlTmF0aXZlU2Nyb2xsUmVzdG9yYXRpb24iLCJlbmROYXZpZ2F0ZVBheWxvYWQiLCJkb05hdmlnYXRlXyIsIm1heWJlUmVzdG9yZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uIiwiZ2V0VGl0bGUiLCJnZXREZWZhdWx0VGl0bGUiLCJiZWZvcmVVcGRhdGVIaXN0b3J5UGF0aCIsImhpc3RvcnlTdGF0ZSIsIm1heWJlUmVzdG9yZVJlZGlyZWN0UGF0aEhhc2hfIiwidXBkYXRlSGlzdG9yeV8iLCJiZWZvcmVVcGRhdGVIaXN0b3J5U3RhdGUiLCJwYXJhbXMiLCJzdXJmYWNlQ29udGVudCIsImdldFN1cmZhY2VDb250ZW50IiwicmVsb2FkIiwic3VyZmFjZUlkIiwiZGlzcG9zZSIsInJlcGxhY2VTdGF0ZSIsInJlbW92ZVBhdGhUcmFpbGluZ1NsYXNoIiwib25Eb2NTdWJtaXREZWxlZ2F0ZV8iLCJvbkRvY0NsaWNrRGVsZWdhdGVfIiwic3luYyIsInRpdGxlTm9kZSIsIkFqYXgiLCJhbGxIZWFkZXJzIiwiaGVhZGVycyIsInBhaXJzIiwiYm9keSIsIm9wdF9oZWFkZXJzIiwib3B0X3BhcmFtcyIsIm9wdF90aW1lb3V0Iiwib3B0X3N5bmMiLCJvcHRfd2l0aENyZWRlbnRpYWxzIiwicmVxdWVzdCIsIlhNTEh0dHBSZXF1ZXN0IiwicHJldmlvdXNSZWFkeVN0YXRlIiwiUHJvbWlzZSIsIm9ubG9hZCIsImFib3J0ZWQiLCJvbmVycm9yIiwicmVhZHlTdGF0ZSIsInRlcm1pbmF0ZWRQcmVtYXR1cmVseSIsImFib3J0IiwidGltZW91dCIsImFkZFBhcmFtZXRlcnNGcm9tTXVsdGlNYXAiLCJ3aXRoQ3JlZGVudGlhbHMiLCJzZXRSZXF1ZXN0SGVhZGVyIiwic2VuZCIsImVycm9ycyIsIklOVkFMSURfU1RBVFVTIiwiUkVRVUVTVF9FUlJPUiIsIlJFUVVFU1RfVElNRU9VVCIsIlJFUVVFU1RfUFJFTUFUVVJFX1RFUk1JTkFUSU9OIiwiVUEiLCJuYXZpZ2F0b3IiLCJ1c2VyQWdlbnQiLCJwbGF0Zm9ybSIsImlzTWFjIiwibWF0Y2hQbGF0Zm9ybSIsImlzV2luIiwiaXNPcGVyYSIsIm1hdGNoVXNlckFnZW50IiwiaXNJZSIsImlzRWRnZSIsImlzSWVPckVkZ2UiLCJpc0Nocm9tZSIsImlzU2FmYXJpIiwiaXNGaXJlZm94IiwidGVzdFVzZXJBZ2VudCIsImdldE5hdGl2ZVVzZXJBZ2VudCIsImdldE5hdGl2ZVBsYXRmb3JtIiwiUmVxdWVzdFNjcmVlbiIsImh0dHBIZWFkZXJzIiwiaHR0cE1ldGhvZCIsIkdFVCIsInN0YXR1cyIsImlzVmFsaWRSZXNwb25zZVN0YXR1c0NvZGUiLCJpbnZhbGlkU3RhdHVzIiwic3RhdHVzQ29kZSIsImdldFJlcXVlc3RQYXRoIiwic2V0UHJvdG9jb2wiLCJtYWtlVW5pcXVlIiwiZ2V0UmVxdWVzdCIsInJlcXVlc3RQYXRoIiwicmVzcG9uc2VVcmwiLCJtYXliZUV4dHJhY3RSZXNwb25zZVVybEZyb21SZXF1ZXN0IiwicmVtb3ZlVW5pcXVlIiwiZm9ybUVsZW1lbnQiLCJzdWJtaXR0ZWRCdXR0b25FbGVtZW50IiwiZm9ybURhdGEiLCJGb3JtRGF0YSIsIm1heWJlQXBwZW5kU3VibWl0QnV0dG9uVmFsdWVfIiwiZ2V0Q2FjaGUiLCJoZWFkZXIiLCJhZGRTYWZhcmlYSFJQb2x5ZmlsbCIsImdldEZvcm1EYXRhIiwiUE9TVCIsImZvcm1hdExvYWRQYXRoIiwicmVtb3ZlU2FmYXJpWEhSUG9seWZpbGwiLCJzZXRSZXF1ZXN0IiwieGhyIiwiYXNzZXJ0VmFsaWRSZXNwb25zZVN0YXR1c0NvZGUiLCJhZGRDYWNoZSIsInJlc3BvbnNlVGV4dCIsInJlcXVlc3RFcnJvciIsInJlcXVlc3RQcmVtYXR1cmVUZXJtaW5hdGlvbiIsInJlc3BvbnNlVVJMIiwiZ2V0UmVzcG9uc2VIZWFkZXIiLCJYX1JFUVVFU1RfVVJMX0hFQURFUiIsImlucHV0cyIsImlucHV0IiwiZmlsZXMiLCJIdG1sU2NyZWVuIiwibWV0YVRhZ3NTZWxlY3RvciIsInRpdGxlU2VsZWN0b3IiLCJyZWxlYXNlVmlydHVhbERvY3VtZW50IiwicGVuZGluZ1N0eWxlcyIsInZpcnR1YWxEb2N1bWVudCIsImNvcHlOb2RlQXR0cmlidXRlc0Zyb21Db250ZW50XyIsIm5ld1N0eWxlIiwiaXNUZW1wb3JhcnlTdHlsZSIsInN0eWxlc1RlbXBvcmFyeSIsInN0eWxlSW5Eb2MiLCJpbnNlcnRCZWZvcmUiLCJuZXh0U2libGluZyIsImJvZHlTdXJmYWNlIiwicGxhY2Vob2xkZXIiLCJ0ZW1wTm9kZSIsImNyZWF0ZVJhbmdlIiwiY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50IiwiY2xlYXJOb2RlQXR0cmlidXRlcyIsImNvcHlOb2RlQXR0cmlidXRlcyIsImRpc3Bvc2VQZW5kaW5nU3R5bGVzIiwicmVtb3ZlRWxlbWVudHNGcm9tRG9jdW1lbnQiLCJldmFsdWF0ZVRyYWNrZWRTY3JpcHRzIiwiZXZhbHVhdGVUcmFja2VkUmVzb3VyY2VzXyIsInNjcmlwdHNUZW1wb3JhcnkiLCJzY3JpcHRzUGVybWFuZW50IiwiZXZhbHVhdGVUcmFja2VkU3R5bGVzIiwicnVuU3R5bGVzSW5FbGVtZW50Iiwic3R5bGVzUGVybWFuZW50IiwiYXBwZW5kU3R5bGVJbnRvRG9jdW1lbnRfIiwicmVzb3VyY2VzSW5WaXJ0dWFsIiwidmlydHVhbFF1ZXJ5U2VsZWN0b3JBbGxfIiwiZmF2aWNvbiIsInJlc291cmNlc0luRG9jdW1lbnQiLCJxdWVyeVNlbGVjdG9yQWxsXyIsInJ1bkZhdmljb25JbkVsZW1lbnRfIiwiZXZhbHVhdG9yRm4iLCJzZWxlY3RvclRlbXBvcmFyeSIsInNlbGVjdG9yUGVybWFuZW50Iiwib3B0X2FwcGVuZFJlc291cmNlRm4iLCJ0cmFja2VkIiwidGVtcG9yYXJpZXNJbkRvYyIsInBlcm1hbmVudHNJbkRvYyIsInJlc291cmNlIiwicmVzb3VyY2VLZXkiLCJnZXRSZXNvdXJjZUtleV8iLCJwZXJtYW5lbnRSZXNvdXJjZXNJbkRvYyIsImZyYWciLCJldmFsdWF0ZUZhdmljb25fIiwidXBkYXRlTWV0YVRhZ3NfIiwiY3VycmVudE1ldGFOb2RlcyIsIm1ldGFzRnJvbVZpcnR1YWxEb2N1bWVudCIsIm1ldGEiLCJhbGxvY2F0ZVZpcnR1YWxEb2N1bWVudEZvckNvbnRlbnQiLCJyZXNvbHZlVGl0bGVGcm9tVmlydHVhbERvY3VtZW50IiwicmVzb2x2ZU1ldGFUYWdzRnJvbVZpcnR1YWxEb2N1bWVudCIsImFzc2VydFNhbWVCb2R5SWRJblZpcnR1YWxEb2N1bWVudCIsIm1ha2VUZW1wb3JhcnlTdHlsZXNIcmVmc1VuaXF1ZV8iLCJyZXBsYWNlU3R5bGVBbmRNYWtlVW5pcXVlXyIsInJlcGxhY2VDaGlsZCIsInNldEVsZW1lbnRXaXRoUmFuZG9tSHJlZiIsInNldFRpdGxlIiwidGV4dENvbnRlbnQiLCJzZXRNZXRhcyIsImlnbm9yZUZhdmljb24iLCJBcHBEYXRhQXR0cmlidXRlSGFuZGxlciIsImFwcCIsImJhc2VFbGVtZW50IiwiaGFzQXR0cmlidXRlIiwiZGF0YUF0dHJpYnV0ZXMiLCJtYXliZUFkZFJvdXRlc18iLCJtYXliZUFkZFN1cmZhY2VzXyIsIm1heWJlU2V0QmFzZVBhdGhfIiwibWF5YmVTZXRMaW5rU2VsZWN0b3JfIiwibWF5YmVTZXRMb2FkaW5nQ3NzQ2xhc3NfIiwibWF5YmVTZXRVcGRhdGVTY3JvbGxQb3NpdGlvbl8iLCJtYXliZURpc3BhdGNoXyIsInJvdXRlc1NlbGVjdG9yIiwicXVlcnlTZWxlY3RvckFsbEFzQXJyYXlfIiwibWF5YmVQYXJzZUxpbmtSb3V0ZV8iLCJoYXNSb3V0ZXMiLCJhZGRSb3V0ZXMiLCJzdXJmYWNlc1NlbGVjdG9yIiwic3VyZmFjZUVsZW1lbnQiLCJ1cGRhdGVFbGVtZW50SWRJZlNwZWNpYWxTdXJmYWNlXyIsImFkZFN1cmZhY2VzIiwiZGlzcGF0Y2giLCJtYXliZVBhcnNlTGlua1JvdXRlUGF0aF8iLCJtYXliZVBhcnNlTGlua1JvdXRlSGFuZGxlcl8iLCJnZXRQYXRoIiwiZ2V0QXR0cmlidXRlIiwiZ2V0T2JqZWN0QnlOYW1lIiwic2V0QmFzZVBhdGgiLCJzZXRMb2FkaW5nQ3NzQ2xhc3MiLCJzZXRVcGRhdGVTY3JvbGxQb3NpdGlvbiIsImRhdGFBdHRyaWJ1dGVIYW5kbGVyIiwic2V0QmFzZUVsZW1lbnQiLCJoYW5kbGUiLCJ2ZXJzaW9uIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkE7Ozs7O0FBS0E7Ozs7Ozs7Ozs7OztBQVlBOzs7OztBQU9BOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkE7Ozs7Ozs7QUFTQTs7QUFVQSxBQVdBOzs7Ozs7O0FBT0E7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"} \ No newline at end of file +{"version":3,"file":"senna.js","sources":["node_modules/metal-dom/node_modules/metal/src/coreNamed.js","node_modules/metal-dom/node_modules/metal/src/core.js","node_modules/metal-dom/node_modules/metal/src/array/array.js","node_modules/metal-dom/node_modules/metal/src/async/async.js","node_modules/metal-dom/node_modules/metal/src/disposable/Disposable.js","node_modules/metal-dom/node_modules/metal/src/object/object.js","node_modules/metal-dom/node_modules/metal/src/string/string.js","node_modules/metal-dom/src/domData.js","node_modules/metal-dom/node_modules/metal-events/src/EventHandle.js","node_modules/metal-dom/node_modules/metal-events/src/EventEmitter.js","node_modules/metal-dom/node_modules/metal-events/src/EventEmitterProxy.js","node_modules/metal-dom/node_modules/metal-events/src/EventHandler.js","node_modules/metal-dom/src/DomDelegatedEventHandle.js","node_modules/metal-dom/src/DomEventHandle.js","node_modules/metal-dom/src/domNamed.js","node_modules/metal-dom/src/dom.js","node_modules/metal-dom/src/DomEventEmitterProxy.js","node_modules/metal-dom/src/features.js","node_modules/metal-dom/src/globalEval.js","node_modules/metal-dom/src/globalEvalStyles.js","node_modules/metal-dom/src/events.js","src/globals/globals.js","node_modules/metal/src/coreNamed.js","node_modules/metal/src/core.js","node_modules/metal/src/array/array.js","node_modules/metal/src/async/async.js","node_modules/metal/src/disposable/Disposable.js","node_modules/metal/src/object/object.js","node_modules/metal/src/string/string.js","node_modules/metal-uri/src/parseFromAnchor.js","node_modules/metal-uri/src/parse.js","node_modules/metal-structs/src/MultiMap.js","node_modules/metal-structs/src/TreeNode.js","node_modules/metal-uri/src/Uri.js","src/utils/utils.js","src/app/dataAttributes.js","node_modules/metal-events/src/EventHandle.js","node_modules/metal-events/src/EventEmitter.js","node_modules/metal-events/src/EventEmitterProxy.js","node_modules/metal-events/src/EventHandler.js","node_modules/metal-promise/src/promise/Promise.js","node_modules/metal-debounce/src/debounce.js","node_modules/metal-path-parser/src/pathParser.js","src/route/Route.js","src/cacheable/Cacheable.js","src/screen/Screen.js","src/surface/Surface.js","src/app/App.js","node_modules/metal-ajax/src/Ajax.js","src/errors/errors.js","node_modules/metal-useragent/src/UA.js","src/screen/RequestScreen.js","src/screen/HtmlScreen.js","src/app/AppDataAttributeHandler.js","src/app/dataAttributeHandler.js","src/app/version.js"],"sourcesContent":["'use strict';\n\n/**\n * A collection of core utility functions.\n * @const\n */\n\nlet compatibilityModeData_;\n\n/**\n * Counter for unique id.\n * @type {Number}\n * @private\n */\nlet uniqueIdCounter_ = 1;\n\n/**\n * Unique id property prefix.\n * @type {String}\n * @protected\n */\nexport const UID_PROPERTY = `core_${(Math.random() * 1e9) >>> 0}`;\n\n/**\n * When defining a class Foo with an abstract method bar(), you can do:\n * Foo.prototype.bar = abstractMethod\n *\n * Now if a subclass of Foo fails to override bar(), an error will be thrown\n * when bar() is invoked.\n *\n * @type {!Function}\n * @throws {Error} when invoked to indicate the method should be overridden.\n */\nexport function abstractMethod() {\n\tthrow Error('Unimplemented abstract method');\n}\n\n/**\n * Disables Metal.js's compatibility mode.\n */\nexport function disableCompatibilityMode() {\n\tcompatibilityModeData_ = undefined;\n}\n\n/**\n * Enables Metal.js's compatibility mode with the following features from rc\n * and 1.x versions:\n * - Using \"key\" to reference component instances. In the current version\n * this should be done via \"ref\" instead. This allows old code still\n * using \"key\" to keep working like before. NOTE: this may cause\n * problems, since \"key\" is meant to be used differently. Only use this\n * if it's not possible to upgrade the code to use \"ref\" instead.\n * @param {Object=} data Optional object with data to specify more\n * details, such as:\n * - renderers {Array} the template renderers that should be in\n * compatibility mode, either their constructors or strings\n * representing them (e.g. 'soy' or 'jsx'). By default, all the ones\n * that extend from IncrementalDomRenderer.\n * @type {Object}\n */\nexport function enableCompatibilityMode(data = {}) {\n\tcompatibilityModeData_ = data;\n}\n\n/**\n * Returns the data used for compatibility mode, or nothing if it hasn't been\n * enabled.\n * @return {Object}\n */\nexport function getCompatibilityModeData() {\n\t// Compatibility mode can be set via the __METAL_COMPATIBILITY__ global var.\n\tif (compatibilityModeData_ === undefined) {\n\t\tif (typeof window !== 'undefined' && window.__METAL_COMPATIBILITY__) {\n\t\t\tenableCompatibilityMode(window.__METAL_COMPATIBILITY__);\n\t\t}\n\t}\n\treturn compatibilityModeData_;\n}\n\n/**\n * Returns the first argument if it's truthy, or the second otherwise.\n * @param {*} a\n * @param {*} b\n * @return {*}\n * @protected\n */\nfunction getFirstTruthy_(a, b) {\n\treturn a || b;\n}\n\n/**\n * Gets the name of the given function. If the current browser doesn't\n * support the `name` property, like IE11, this will calculate it from the function's\n * content string.\n * @param {!function()} fn\n * @return {string}\n */\nexport function getFunctionName(fn) {\n\tif (!fn.name) {\n\t\tconst str = fn.toString();\n\t\tfn.name = str.substring(9, str.indexOf('('));\n\t}\n\treturn fn.name;\n}\n\n/**\n * Gets the value of a static property in the given class. The value will be\n * inherited from ancestors as expected, unless a custom merge function is given,\n * which can change how the super classes' value for that property will be merged\n * together.\n * The final merged value will be stored in another property, so that it won't\n * be recalculated even if this function is called multiple times.\n * @param {!function()} ctor Class constructor.\n * @param {string} propertyName Property name to be merged.\n * @param {function(*, *):*=} mergeFn Function that receives the merged\n * value of the property so far and the next value to be merged to it.\n * Should return these two merged together. If not passed the final property\n * will be the first truthy value among ancestors.\n * @return {Object}\n */\nexport function getStaticProperty(\n\tctor,\n\tpropertyName,\n\tmergeFn = getFirstTruthy_\n) {\n\tconst mergedName = propertyName + '_MERGED';\n\tif (!ctor.hasOwnProperty(mergedName)) {\n\t\t// eslint-disable-next-line\n\t\tlet merged = ctor.hasOwnProperty(propertyName)\n\t\t\t? ctor[propertyName]\n\t\t\t: null;\n\t\tif (ctor.__proto__ && !ctor.__proto__.isPrototypeOf(Function)) {\n\t\t\tmerged = mergeFn(\n\t\t\t\tmerged,\n\t\t\t\tgetStaticProperty(ctor.__proto__, propertyName, mergeFn)\n\t\t\t);\n\t\t}\n\t\tctor[mergedName] = merged;\n\t}\n\treturn ctor[mergedName];\n}\n\n/**\n * Gets an unique id. If `object` argument is passed, the object is\n * mutated with an unique id. Consecutive calls with the same object\n * reference won't mutate the object again, instead the current object uid\n * returns. See {@link UID_PROPERTY}.\n * @param {Object=} object Optional object to be mutated with the uid. If\n * not specified this method only returns the uid.\n * @param {boolean=} noInheritance Optional flag indicating if this\n * object's uid property can be inherited from parents or not.\n * @throws {Error} when invoked to indicate the method should be overridden.\n * @return {number}\n */\nexport function getUid(object, noInheritance) {\n\tif (object) {\n\t\tlet id = object[UID_PROPERTY];\n\t\tif (noInheritance && !object.hasOwnProperty(UID_PROPERTY)) {\n\t\t\tid = null;\n\t\t}\n\t\treturn id || (object[UID_PROPERTY] = uniqueIdCounter_++);\n\t}\n\treturn uniqueIdCounter_++;\n}\n\n/**\n * The identity function. Returns its first argument.\n * @param {*=} returnValue The single value that will be returned.\n * @return {?} The first argument.\n */\nexport function identityFunction(returnValue) {\n\treturn returnValue;\n}\n\n/**\n * Returns true if the specified value is a boolean.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is boolean.\n */\nexport function isBoolean(val) {\n\treturn typeof val === 'boolean';\n}\n\n/**\n * Returns true if the specified value is not undefined.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is defined.\n */\nexport function isDef(val) {\n\treturn val !== undefined;\n}\n\n/**\n * Returns true if value is not undefined or null.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDefAndNotNull(val) {\n\treturn isDef(val) && !isNull(val);\n}\n\n/**\n * Returns true if value is a document.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDocument(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 9;\n}\n\n/**\n * Returns true if value is a document-fragment.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDocumentFragment(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 11;\n}\n\n/**\n * Returns true if value is a dom element.\n * @param {*} val\n * @return {boolean}\n */\nexport function isElement(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 1;\n}\n\n/**\n * Returns true if the specified value is a function.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is a function.\n */\nexport function isFunction(val) {\n\treturn typeof val === 'function';\n}\n\n/**\n * Returns true if value is null.\n * @param {*} val\n * @return {boolean}\n */\nexport function isNull(val) {\n\treturn val === null;\n}\n\n/**\n * Returns true if the specified value is a number.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is a number.\n */\nexport function isNumber(val) {\n\treturn typeof val === 'number';\n}\n\n/**\n * Returns true if value is a window.\n * @param {*} val\n * @return {boolean}\n */\nexport function isWindow(val) {\n\treturn val !== null && val === val.window;\n}\n\n/**\n * Returns true if the specified value is an object. This includes arrays\n * and functions.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is an object.\n */\nexport function isObject(val) {\n\tconst type = typeof val;\n\treturn (type === 'object' && val !== null) || type === 'function';\n}\n\n/**\n * Returns true if value is a Promise.\n * @param {*} val\n * @return {boolean}\n */\nexport function isPromise(val) {\n\treturn val && typeof val === 'object' && typeof val.then === 'function';\n}\n\n/**\n * Returns true if value is a string.\n * @param {*} val\n * @return {boolean}\n */\nexport function isString(val) {\n\treturn typeof val === 'string' || val instanceof String;\n}\n\n/**\n * Sets to true if running inside Node.js environment with extra check for\n * `process.browser` to skip Karma runner environment. Karma environment has\n * `process` defined even though it runs on the browser.\n * @param {?Object} options Contains `checkEnv` property which if true, checks\n * the NODE_ENV variable. If NODE_ENV equals 'test', the function returns false.\n * @return {boolean}\n */\nexport function isServerSide(options = {checkEnv: true}) {\n\tlet serverSide = typeof process !== 'undefined' && !process.browser;\n\tif (serverSide && options.checkEnv) {\n\t\tserverSide =\n\t\t\ttypeof process.env !== 'undefined' &&\n\t\t\tprocess.env.NODE_ENV !== 'test';\n\t}\n\treturn serverSide;\n}\n\n/**\n * Null function used for default values of callbacks, etc.\n * @return {void} Nothing.\n */\nexport function nullFunction() {}\n","'use strict';\n\n// This file exists just for backwards compatibility, making sure that old\n// default imports for this file still work. It's best to use the named exports\n// for each function instead though, since that allows bundlers like Rollup to\n// reduce the bundle size by removing unused code.\nimport * as core from './coreNamed';\n\nexport default core;\nexport {core};\nexport * from './coreNamed';\n","'use strict';\n\n/**\n * Set of utilities for array operations\n */\nclass array {\n\t/**\n\t * Checks if the given arrays have the same content.\n\t * @param {!Array<*>} arr1\n\t * @param {!Array<*>} arr2\n\t * @return {boolean}\n\t */\n\tstatic equal(arr1, arr2) {\n\t\tif (arr1 === arr2) {\n\t\t\treturn true;\n\t\t}\n\t\tif (arr1.length !== arr2.length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0; i < arr1.length; i++) {\n\t\t\tif (arr1[i] !== arr2[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns the first value in the given array that isn't undefined.\n\t * @param {!Array} arr\n\t * @return {*}\n\t */\n\tstatic firstDefinedValue(arr) {\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tif (arr[i] !== undefined) {\n\t\t\t\treturn arr[i];\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Transforms the input nested array to become flat.\n\t * @param {Array.<*|Array.<*>>} arr Nested array to flatten.\n\t * @param {Array.<*>=} output Optional output array.\n\t * @return {Array.<*>} Flat array.\n\t */\n\tstatic flatten(arr, output = []) {\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tif (Array.isArray(arr[i])) {\n\t\t\t\tarray.flatten(arr[i], output);\n\t\t\t} else {\n\t\t\t\toutput.push(arr[i]);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Removes the first occurrence of a particular value from an array.\n\t * @param {Array.<T>} arr Array from which to remove value.\n\t * @param {T} obj Object to remove.\n\t * @return {boolean} True if an element was removed.\n\t * @template T\n\t */\n\tstatic remove(arr, obj) {\n\t\tconst i = arr.indexOf(obj);\n\t\tlet rv;\n\t\tif ((rv = i >= 0)) {\n\t\t\tarray.removeAt(arr, i);\n\t\t}\n\t\treturn rv;\n\t}\n\n\t/**\n\t * Removes from an array the element at index i\n\t * @param {Array} arr Array or array like object from which to remove value.\n\t * @param {number} i The index to remove.\n\t * @return {boolean} True if an element was removed.\n\t */\n\tstatic removeAt(arr, i) {\n\t\treturn Array.prototype.splice.call(arr, i, 1).length === 1;\n\t}\n\n\t/**\n\t * Slices the given array, just like Array.prototype.slice, but this\n\t * is faster and working on all array-like objects (like arguments).\n\t * @param {!Object} arr Array-like object to slice.\n\t * @param {number} start The index that should start the slice.\n\t * @param {number=} end The index where the slice should end, not\n\t * included in the final array. If not given, all elements after the\n\t * start index will be included.\n\t * @return {!Array}\n\t */\n\tstatic slice(arr, start, end = arr.length) {\n\t\tconst sliced = [];\n\t\tfor (let i = start; i < end; i++) {\n\t\t\tsliced.push(arr[i]);\n\t\t}\n\t\treturn sliced;\n\t}\n}\n\nexport default array;\n","/* !\n * Polyfill from Google's Closure Library.\n * Copyright 2013 The Closure Library Authors. All Rights Reserved.\n */\n\n'use strict';\n\nimport {isServerSide} from '../coreNamed';\n\nconst async = {};\n\n/**\n * Throw an item without interrupting the current execution context. For\n * example, if processing a group of items in a loop, sometimes it is useful\n * to report an error while still allowing the rest of the batch to be\n * processed.\n * @param {*} exception\n */\nasync.throwException = function(exception) {\n\t// Each throw needs to be in its own context.\n\tasync.nextTick(function() {\n\t\tthrow exception;\n\t});\n};\n\n/**\n * Fires the provided callback just before the current callstack unwinds, or as\n * soon as possible after the current JS execution context.\n * @param {function(this:THIS)} callback\n * @param {THIS=} context Object to use as the \"this value\" when calling\n * the provided function.\n * @template THIS\n */\nasync.run = function(callback, context) {\n\tif (!async.run.workQueueScheduled_) {\n\t\t// Nothing is currently scheduled, schedule it now.\n\t\tasync.nextTick(async.run.processWorkQueue);\n\t\tasync.run.workQueueScheduled_ = true;\n\t}\n\n\tasync.run.workQueue_.push(new async.run.WorkItem_(callback, context));\n};\n\n/** @private {boolean} */\nasync.run.workQueueScheduled_ = false;\n\n/** @private {!Array.<!async.run.WorkItem_>} */\nasync.run.workQueue_ = [];\n\n/**\n * Run any pending async.run work items. This function is not intended\n * for general use, but for use by entry point handlers to run items ahead of\n * async.nextTick.\n */\nasync.run.processWorkQueue = function() {\n\t// NOTE: additional work queue items may be pushed while processing.\n\twhile (async.run.workQueue_.length) {\n\t\t// Don't let the work queue grow indefinitely.\n\t\tconst workItems = async.run.workQueue_;\n\t\tasync.run.workQueue_ = [];\n\t\tfor (let i = 0; i < workItems.length; i++) {\n\t\t\tconst workItem = workItems[i];\n\t\t\ttry {\n\t\t\t\tworkItem.fn.call(workItem.scope);\n\t\t\t} catch (e) {\n\t\t\t\tasync.throwException(e);\n\t\t\t}\n\t\t}\n\t}\n\n\t// There are no more work items, reset the work queue.\n\tasync.run.workQueueScheduled_ = false;\n};\n\n/**\n * @constructor\n * @final\n * @struct\n * @private\n *\n * @param {function()} fn\n * @param {Object|null|undefined} scope\n */\nasync.run.WorkItem_ = function(fn, scope) {\n\t/** @const */\n\tthis.fn = fn;\n\t/** @const */\n\tthis.scope = scope;\n};\n\n/**\n * Fires the provided callbacks as soon as possible after the current JS\n * execution context. setTimeout(…, 0) always takes at least 5ms for legacy\n * reasons.\n * @param {function(this:SCOPE)} callback Callback function to fire as soon as\n * possible.\n * @param {SCOPE=} context Object in whose scope to call the listener.\n * @template SCOPE\n */\nasync.nextTick = function(callback, context) {\n\tlet cb = callback;\n\tif (context) {\n\t\tcb = callback.bind(context);\n\t}\n\tcb = async.nextTick.wrapCallback_(cb);\n\t// Look for and cache the custom fallback version of setImmediate.\n\tif (!async.nextTick.setImmediate_) {\n\t\tif (\n\t\t\ttypeof setImmediate === 'function' &&\n\t\t\tisServerSide({checkEnv: false})\n\t\t) {\n\t\t\tasync.nextTick.setImmediate_ = setImmediate;\n\t\t} else {\n\t\t\t// eslint-disable-next-line\n\t\t\tasync.nextTick.setImmediate_ = async.nextTick.getSetImmediateEmulator_();\n\t\t}\n\t}\n\tasync.nextTick.setImmediate_(cb);\n};\n\n/**\n * Cache for the setImmediate implementation.\n * @type {function(function())}\n * @private\n */\nasync.nextTick.setImmediate_ = null;\n\n/**\n * Determines the best possible implementation to run a function as soon as\n * the JS event loop is idle.\n * @return {function(function())} The \"setImmediate\" implementation.\n * @private\n */\nasync.nextTick.getSetImmediateEmulator_ = function() {\n\t// Create a private message channel and use it to postMessage empty messages\n\t// to ourselves.\n\tlet Channel;\n\n\t// Verify if variable is defined on the current runtime (i.e., node, browser).\n\t// Can't use typeof enclosed in a function (such as core.isFunction) or an\n\t// exception will be thrown when the function is called on an environment\n\t// where the variable is undefined.\n\tif (typeof MessageChannel === 'function') {\n\t\tChannel = MessageChannel;\n\t}\n\n\t// If MessageChannel is not available and we are in a browser, implement\n\t// an iframe based polyfill in browsers that have postMessage and\n\t// document.addEventListener. The latter excludes IE8 because it has a\n\t// synchronous postMessage implementation.\n\tif (\n\t\ttypeof Channel === 'undefined' &&\n\t\ttypeof window !== 'undefined' &&\n\t\twindow.postMessage &&\n\t\twindow.addEventListener\n\t) {\n\t\t/** @constructor */\n\t\tChannel = function() {\n\t\t\t// Make an empty, invisible iframe.\n\t\t\tconst iframe = document.createElement('iframe');\n\t\t\tiframe.style.display = 'none';\n\t\t\tiframe.src = '';\n\t\t\tiframe.title = '';\n\t\t\tdocument.documentElement.appendChild(iframe);\n\t\t\tconst win = iframe.contentWindow;\n\t\t\tconst doc = win.document;\n\t\t\tdoc.open();\n\t\t\tdoc.write('');\n\t\t\tdoc.close();\n\t\t\tconst message = 'callImmediate' + Math.random();\n\t\t\tconst origin = win.location.protocol + '//' + win.location.host;\n\t\t\tconst onmessage = function(e) {\n\t\t\t\t// Validate origin and message to make sure that this message was\n\t\t\t\t// intended for us.\n\t\t\t\tif (e.origin !== origin && e.data !== message) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.port1.onmessage();\n\t\t\t}.bind(this);\n\t\t\twin.addEventListener('message', onmessage, false);\n\t\t\tthis.port1 = {};\n\t\t\tthis.port2 = {\n\t\t\t\tpostMessage: function() {\n\t\t\t\t\twin.postMessage(message, origin);\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\t}\n\tif (typeof Channel !== 'undefined') {\n\t\tconst channel = new Channel();\n\t\t// Use a fifo linked list to call callbacks in the right order.\n\t\tlet head = {};\n\t\tlet tail = head;\n\t\tchannel.port1.onmessage = function() {\n\t\t\thead = head.next;\n\t\t\tconst cb = head.cb;\n\t\t\thead.cb = null;\n\t\t\tcb();\n\t\t};\n\t\treturn function(cb) {\n\t\t\ttail.next = {\n\t\t\t\tcb: cb,\n\t\t\t};\n\t\t\ttail = tail.next;\n\t\t\tchannel.port2.postMessage(0);\n\t\t};\n\t}\n\t// Implementation for IE6-8: Script elements fire an asynchronous\n\t// onreadystatechange event when inserted into the DOM.\n\tif (\n\t\ttypeof document !== 'undefined' &&\n\t\t'onreadystatechange' in document.createElement('script')\n\t) {\n\t\treturn function(cb) {\n\t\t\tlet script = document.createElement('script');\n\t\t\tscript.onreadystatechange = function() {\n\t\t\t\t// Clean up and call the callback.\n\t\t\t\tscript.onreadystatechange = null;\n\t\t\t\tscript.parentNode.removeChild(script);\n\t\t\t\tscript = null;\n\t\t\t\tcb();\n\t\t\t\tcb = null;\n\t\t\t};\n\t\t\tdocument.documentElement.appendChild(script);\n\t\t};\n\t}\n\t// Fall back to setTimeout with 0. In browsers this creates a delay of 5ms\n\t// or more.\n\treturn function(cb) {\n\t\tsetTimeout(cb, 0);\n\t};\n};\n\n/**\n * Helper function that is overrided to protect callbacks with entry point\n * monitor if the application monitors entry points.\n * @param {function()} callback Callback function to fire as soon as possible.\n * @return {function()} The wrapped callback.\n * @private\n */\nasync.nextTick.wrapCallback_ = function(callback) {\n\treturn callback;\n};\n\nexport default async;\n","'use strict';\n\n/**\n * Disposable utility. When inherited provides the `dispose` function to its\n * subclass, which is responsible for disposing of any object references\n * when an instance won't be used anymore. Subclasses should override\n * `disposeInternal` to implement any specific disposing logic.\n * @constructor\n */\nclass Disposable {\n\t/**\n\t * Disposable constructor\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Flag indicating if this instance has already been disposed.\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.disposed_ = false;\n\t}\n\n\t/**\n\t * Disposes of this instance's object references. Calls `disposeInternal`.\n\t */\n\tdispose() {\n\t\tif (!this.disposed_) {\n\t\t\tthis.disposeInternal();\n\t\t\tthis.disposed_ = true;\n\t\t}\n\t}\n\n\t/**\n\t * Subclasses should override this method to implement any specific\n\t * disposing logic (like clearing references and calling `dispose` on other\n\t * disposables).\n\t */\n\tdisposeInternal() {}\n\n\t/**\n\t * Checks if this instance has already been disposed.\n\t * @return {boolean}\n\t */\n\tisDisposed() {\n\t\treturn this.disposed_;\n\t}\n}\n\nexport default Disposable;\n","'use strict';\n\n/**\n * Set of utilities for object operations\n */\nclass object {\n\t/**\n\t * Copies all the members of a source object to a target object.\n\t * @param {Object} target Target object.\n\t * @param {...Object} var_args The objects from which values will be copied.\n\t * @return {Object} Returns the target object reference.\n\t */\n\tstatic mixin(target, ...args) {\n\t\tlet key;\n\t\tlet source;\n\t\tfor (let i = 0; i < args.length; i++) {\n\t\t\tsource = args[i];\n\t\t\t// Possible prototype chain leak, breaks 1 metal-dom and\n\t\t\t// 1 metal-incremental-dom test if guard-for-in rule is addressed\n\t\t\t// eslint-disable-next-line\n\t\t\tfor (key in source) {\n\t\t\t\ttarget[key] = source[key];\n\t\t\t}\n\t\t}\n\t\treturn target;\n\t}\n\n\t/**\n\t * Returns an object based on its fully qualified external name.\n\t * @param {string} name The fully qualified name.\n\t * @param {object=} scope The object within which to look; default is\n\t * <code>window</code>.\n\t * @return {?} The value (object or primitive) or, if not found, undefined.\n\t */\n\tstatic getObjectByName(name, scope = window) {\n\t\tconst parts = name.split('.');\n\t\treturn parts.reduce((part, key) => part[key], scope);\n\t}\n\n\t/**\n\t * Returns a new object with the same keys as the given one, but with\n\t * their values set to the return values of the specified function.\n\t * @param {!Object} obj\n\t * @param {!function(string, *)} fn\n\t * @return {!Object}\n\t */\n\tstatic map(obj, fn) {\n\t\tconst mappedObj = {};\n\t\tconst keys = Object.keys(obj);\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tmappedObj[keys[i]] = fn(keys[i], obj[keys[i]]);\n\t\t}\n\t\treturn mappedObj;\n\t}\n\n\t/**\n\t * Checks if the two given objects are equal. This is done via a shallow\n\t * check, including only the keys directly contained by the 2 objects.\n\t * @param {Object} obj1\n\t * @param {Object} obj2\n\t * @return {boolean}\n\t */\n\tstatic shallowEqual(obj1, obj2) {\n\t\tif (obj1 === obj2) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst keys1 = Object.keys(obj1);\n\t\tconst keys2 = Object.keys(obj2);\n\t\tif (keys1.length !== keys2.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < keys1.length; i++) {\n\t\t\tif (obj1[keys1[i]] !== obj2[keys1[i]]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\n\nexport default object;\n","'use strict';\n\n/**\n * Set of utilities for string operations\n */\nclass string {\n\t/**\n\t * Compares the given strings without taking the case into account.\n\t * @param {string|number} str1\n\t * @param {string|number} str2\n\t * @return {number} Either -1, 0 or 1, according to if the first string is\n\t * \"smaller\", equal or \"bigger\" than the second given string.\n\t */\n\tstatic caseInsensitiveCompare(str1, str2) {\n\t\tconst test1 = String(str1).toLowerCase();\n\t\tconst test2 = String(str2).toLowerCase();\n\n\t\tif (test1 < test2) {\n\t\t\treturn -1;\n\t\t} else if (test1 === test2) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\t/**\n\t * Removes the breaking spaces from the left and right of the string and\n\t * collapses the sequences of breaking spaces in the middle into single spaces.\n\t * The original and the result strings render the same way in HTML.\n\t * @param {string} str A string in which to collapse spaces.\n\t * @return {string} Copy of the string with normalized breaking spaces.\n\t */\n\tstatic collapseBreakingSpaces(str) {\n\t\treturn str\n\t\t\t.replace(/[\\t\\r\\n ]+/g, ' ')\n\t\t\t.replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g, '');\n\t}\n\n\t/**\n\t * Escapes characters in the string that are not safe to use in a RegExp.\n\t * @param {*} str The string to escape. If not a string, it will be casted\n\t * to one.\n\t * @return {string} A RegExp safe, escaped copy of {@code s}.\n\t */\n\tstatic escapeRegex(str) {\n\t\treturn String(str)\n\t\t\t.replace(/([-()[\\]{}+?*.$^|,:#<!\\\\])/g, '\\\\$1')\n\t\t\t.replace(/\\x08/g, '\\\\x08'); // eslint-disable-line\n\t}\n\n\t/**\n\t * Returns a string with at least 64-bits of randomness.\n\t * @return {string} A random string, e.g. sn1s7vb4gcic.\n\t */\n\tstatic getRandomString() {\n\t\tconst x = 2147483648;\n\t\treturn (\n\t\t\tMath.floor(Math.random() * x).toString(36) +\n\t\t\tMath.abs(Math.floor(Math.random() * x) ^ Date.now()).toString(36)\n\t\t);\n\t}\n\n\t/**\n\t * Calculates the hashcode for a string. The hashcode value is computed by\n\t * the sum algorithm: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]. A nice\n\t * property of using 31 prime is that the multiplication can be replaced by\n\t * a shift and a subtraction for better performance: 31*i == (i<<5)-i.\n\t * Modern VMs do this sort of optimization automatically.\n\t * @param {String} val Target string.\n\t * @return {Number} Returns the string hashcode.\n\t */\n\tstatic hashCode(val) {\n\t\tlet hash = 0;\n\t\tfor (let i = 0, len = val.length; i < len; i++) {\n\t\t\thash = 31 * hash + val.charCodeAt(i);\n\t\t\thash %= 0x100000000;\n\t\t}\n\t\treturn hash;\n\t}\n\n\t/**\n\t * Replaces interval into the string with specified value, e.g.\n\t * `replaceInterval(\"abcde\", 1, 4, \"\")` returns \"ae\".\n\t * @param {string} str The input string.\n\t * @param {Number} start Start interval position to be replaced.\n\t * @param {Number} end End interval position to be replaced.\n\t * @param {string} value The value that replaces the specified interval.\n\t * @return {string}\n\t */\n\tstatic replaceInterval(str, start, end, value) {\n\t\treturn str.substring(0, start) + value + str.substring(end);\n\t}\n}\n\nexport default string;\n","'use strict';\n\nimport {isDef} from 'metal';\n\nconst METAL_DATA = '__metal_data__';\n\n/**\n * Set of utilities for dom data operations\n */\nclass domData {\n\t/**\n\t * Gets Metal.js's data for the given element.\n\t * @param {!Element} element\n\t * @param {string=} name Optional property from the data to be returned.\n\t * @param {*=} initialValue Optional value to the set the requested property\n\t * to if it doesn't exist yet in the data.\n\t * @return {!Object}\n\t */\n\tstatic get(element, name, initialValue) {\n\t\tif (!element[METAL_DATA]) {\n\t\t\telement[METAL_DATA] = {};\n\t\t}\n\t\tif (!name) {\n\t\t\treturn element[METAL_DATA];\n\t\t}\n\t\tif (!isDef(element[METAL_DATA][name]) && isDef(initialValue)) {\n\t\t\telement[METAL_DATA][name] = initialValue;\n\t\t}\n\t\treturn element[METAL_DATA][name];\n\t}\n\n\t/**\n\t * Checks if the given element has data stored in it.\n\t * @param {!Element} element\n\t * @return {boolean}\n\t */\n\tstatic has(element) {\n\t\treturn !!element[METAL_DATA];\n\t}\n\n\t/**\n\t * Sets Metal.js's data for the given element.\n\t * @param {!Element} element\n\t * @param {string=} name Property from the data to be set.\n\t * @param {*=} value Value to be set on the element.\n\t * @return {!Object|*}\n\t */\n\tstatic set(element, name, value) {\n\t\tif (!element[METAL_DATA]) {\n\t\t\telement[METAL_DATA] = {};\n\t\t}\n\t\tif (!name || !isDef(value)) {\n\t\t\treturn element[METAL_DATA];\n\t\t}\n\t\telement[METAL_DATA][name] = value;\n\t\treturn element[METAL_DATA][name];\n\t}\n}\n\nexport default domData;\n","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventHandle utility. Holds information about an event subscription, and\n * allows removing them easily.\n * EventHandle is a Disposable, but it's important to note that the\n * EventEmitter that created it is not the one responsible for disposing it.\n * That responsibility is for the code that holds a reference to it.\n * @extends {Disposable}\n */\nclass EventHandle extends Disposable {\n\t/**\n\t * EventHandle constructor\n\t * @param {!EventEmitter} emitter Emitter the event was subscribed to.\n\t * @param {string} event The name of the event that was subscribed to.\n\t * @param {!Function} listener The listener subscribed to the event.\n\t */\n\tconstructor(emitter, event, listener) {\n\t\tsuper();\n\n\t\t/**\n\t\t * The EventEmitter instance that the event was subscribed to.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.emitter_ = emitter;\n\n\t\t/**\n\t\t * The name of the event that was subscribed to.\n\t\t * @type {string}\n\t\t * @protected\n\t\t */\n\t\tthis.event_ = event;\n\n\t\t/**\n\t\t * The listener subscribed to the event.\n\t\t * @type {Function}\n\t\t * @protected\n\t\t */\n\t\tthis.listener_ = listener;\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.removeListener();\n\t\tthis.emitter_ = null;\n\t\tthis.listener_ = null;\n\t}\n\n\t/**\n\t * Removes the listener subscription from the emitter.\n\t */\n\tremoveListener() {\n\t\tif (!this.emitter_.isDisposed()) {\n\t\t\tthis.emitter_.removeListener(this.event_, this.listener_);\n\t\t}\n\t}\n}\n\nexport default EventHandle;\n","'use strict';\n\nimport {array, Disposable, isFunction, isString} from 'metal';\nimport EventHandle from './EventHandle';\n\nconst singleArray_ = [0];\n\n/**\n * EventEmitter utility.\n * @extends {Disposable}\n */\nclass EventEmitter extends Disposable {\n\t/**\n\t * EventEmitter constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds event listeners scoped by event type.\n\t\t * @type {Object<string, !Array<!function()>>}\n\t\t * @protected\n\t\t */\n\t\tthis.events_ = null;\n\n\t\t/**\n\t\t * Handlers that are triggered when an event is listened to.\n\t\t * @type {Array}\n\t\t */\n\t\tthis.listenerHandlers_ = null;\n\n\t\t/**\n\t\t * Configuration option which determines if an event facade should be sent\n\t\t * as a param of listeners when emitting events. If set to true, the facade\n\t\t * will be passed as the first argument of the listener.\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.shouldUseFacade_ = false;\n\t}\n\n\t/**\n\t * Adds a handler to given holder variable. If the holder doesn't have a\n\t * value yet, it will receive the handler directly. If the holder is an array,\n\t * the value will just be added to it. Otherwise, the holder will be set to a\n\t * new array containing its previous value plus the new handler.\n\t * @param {*} holder\n\t * @param {!function()|Object} handler\n\t * @return {*} The holder's new value.\n\t * @protected\n\t */\n\taddHandler_(holder, handler) {\n\t\tif (!holder) {\n\t\t\tholder = handler;\n\t\t} else {\n\t\t\tif (!Array.isArray(holder)) {\n\t\t\t\tholder = [holder];\n\t\t\t}\n\t\t\tholder.push(handler);\n\t\t}\n\t\treturn holder;\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for the specified events.\n\t * @param {!(Array|string)} event\n\t * @param {!Function} listener\n\t * @param {boolean} defaultListener Flag indicating if this listener is a default\n\t * action for this event. Default actions are run last, and only if no previous\n\t * listener call `preventDefault()` on the received event facade.\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\taddListener(event, listener, defaultListener) {\n\t\tthis.validateListener_(listener);\n\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.addSingleListener_(events[i], listener, defaultListener);\n\t\t}\n\n\t\treturn new EventHandle(this, event, listener);\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for a single event.\n\t * @param {string} event\n\t * @param {!Function} listener\n\t * @param {boolean} defaultListener Flag indicating if this listener is a default\n\t * action for this event. Default actions are run last, and only if no previous\n\t * listener call `preventDefault()` on the received event facade.\n\t * @param {Function=} origin The original function that was added as a\n\t * listener, if there is any.\n\t * @protected\n\t */\n\taddSingleListener_(event, listener, defaultListener, origin) {\n\t\tthis.runListenerHandlers_(event);\n\t\tif (defaultListener || origin) {\n\t\t\tlistener = {\n\t\t\t\tdefault: defaultListener,\n\t\t\t\tfn: listener,\n\t\t\t\torigin: origin,\n\t\t\t};\n\t\t}\n\t\tthis.events_ = this.events_ || {};\n\t\tthis.events_[event] = this.addHandler_(this.events_[event], listener);\n\t}\n\n\t/**\n\t * Builds facade for the given event.\n\t * @param {string} event\n\t * @return {Object}\n\t * @protected\n\t */\n\tbuildFacade_(event) {\n\t\tif (this.getShouldUseFacade()) {\n\t\t\tconst facade = {\n\t\t\t\tpreventDefault: function() {\n\t\t\t\t\tfacade.preventedDefault = true;\n\t\t\t\t},\n\t\t\t\ttarget: this,\n\t\t\t\ttype: event,\n\t\t\t};\n\t\t\treturn facade;\n\t\t}\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.events_ = null;\n\t}\n\n\t/**\n\t * Execute each of the listeners in order with the supplied arguments.\n\t * @param {string} event\n\t * @param {*} opt_args [arg1], [arg2], [...]\n\t * @return {boolean} Returns true if event had listeners, false otherwise.\n\t */\n\temit(event) {\n\t\tconst listeners = this.getRawListeners_(event);\n\t\tif (listeners.length === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst args = array.slice(arguments, 1); // eslint-disable-line\n\t\tthis.runListeners_(listeners, args, this.buildFacade_(event));\n\t\treturn true;\n\t}\n\n\t/**\n\t * Gets the listener objects for the given event, if there are any.\n\t * @param {string} event\n\t * @return {!Array}\n\t * @protected\n\t */\n\tgetRawListeners_(event) {\n\t\tconst directListeners = toArray(this.events_ && this.events_[event]);\n\t\treturn directListeners.concat(\n\t\t\ttoArray(this.events_ && this.events_['*'])\n\t\t);\n\t}\n\n\t/**\n\t * Gets the configuration option which determines if an event facade should\n\t * be sent as a param of listeners when emitting events. If set to true, the\n\t * facade will be passed as the first argument of the listener.\n\t * @return {boolean}\n\t */\n\tgetShouldUseFacade() {\n\t\treturn this.shouldUseFacade_;\n\t}\n\n\t/**\n\t * Returns an array of listeners for the specified event.\n\t * @param {string} event\n\t * @return {Array} Array of listeners.\n\t */\n\tlisteners(event) {\n\t\treturn this.getRawListeners_(event).map(\n\t\t\tlistener => (listener.fn ? listener.fn : listener)\n\t\t);\n\t}\n\n\t/**\n\t * Adds a listener that will be invoked a fixed number of times for the\n\t * events. After each event is triggered the specified amount of times, the\n\t * listener is removed for it.\n\t * @param {!(Array|string)} event\n\t * @param {number} amount The amount of times this event should be listened\n\t * to.\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\tmany(event, amount, listener) {\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.many_(events[i], amount, listener);\n\t\t}\n\n\t\treturn new EventHandle(this, event, listener);\n\t}\n\n\t/**\n\t * Adds a listener that will be invoked a fixed number of times for a single\n\t * event. After the event is triggered the specified amount of times, the\n\t * listener is removed.\n\t * @param {string} event\n\t * @param {number} amount The amount of times this event should be listened\n\t * to.\n\t * @param {!Function} listener\n\t * @protected\n\t */\n\tmany_(event, amount, listener) {\n\t\tconst self = this;\n\n\t\tif (amount <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t *\n\t\t */\n\t\tfunction handlerInternal() {\n\t\t\tif (--amount === 0) {\n\t\t\t\tself.removeListener(event, handlerInternal);\n\t\t\t}\n\t\t\tlistener.apply(self, arguments); // eslint-disable-line\n\t\t}\n\n\t\tself.addSingleListener_(event, handlerInternal, false, listener);\n\t}\n\n\t/**\n\t * Checks if a listener object matches the given listener function. To match,\n\t * it needs to either point to that listener or have it as its origin.\n\t * @param {!Object} listenerObj\n\t * @param {!Function} listener\n\t * @return {boolean}\n\t * @protected\n\t */\n\tmatchesListener_(listenerObj, listener) {\n\t\tconst fn = listenerObj.fn || listenerObj;\n\t\treturn (\n\t\t\tfn === listener ||\n\t\t\t(listenerObj.origin && listenerObj.origin === listener) // eslint-disable-line\n\t\t);\n\t}\n\n\t/**\n\t * Removes a listener for the specified events.\n\t * Caution: changes array indices in the listener array behind the listener.\n\t * @param {!(Array|string)} event\n\t * @param {!Function} listener\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\toff(event, listener) {\n\t\tthis.validateListener_(listener);\n\t\tif (!this.events_) {\n\t\t\treturn this;\n\t\t}\n\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.events_[events[i]] = this.removeMatchingListenerObjs_(\n\t\t\t\ttoArray(this.events_[events[i]]),\n\t\t\t\tlistener\n\t\t\t);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for the specified events.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\ton() {\n\t\treturn this.addListener.apply(this, arguments); // eslint-disable-line\n\t}\n\n\t/**\n\t * Adds handler that gets triggered when an event is listened to on this\n\t * instance.\n\t * @param {!function()} handler\n\t */\n\tonListener(handler) {\n\t\tthis.listenerHandlers_ = this.addHandler_(\n\t\t\tthis.listenerHandlers_,\n\t\t\thandler\n\t\t); // eslint-disable-line\n\t}\n\n\t/**\n\t * Adds a one time listener for the events. This listener is invoked only the\n\t * next time each event is fired, after which it is removed.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\tonce(events, listener) {\n\t\treturn this.many(events, 1, listener);\n\t}\n\n\t/**\n\t * Removes all listeners, or those of the specified events. It's not a good\n\t * idea to remove listeners that were added elsewhere in the code,\n\t * especially when it's on an emitter that you didn't create.\n\t * @param {(Array|string)=} event\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveAllListeners(event) {\n\t\tif (this.events_) {\n\t\t\tif (event) {\n\t\t\t\tconst events = this.toEventsArray_(event);\n\t\t\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\t\t\tthis.events_[events[i]] = null;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.events_ = null;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes all listener objects from the given array that match the given\n\t * listener function.\n\t * @param {Array.<Object>} listenerObjs\n\t * @param {!Function} listener\n\t * @return {Array.<Object>|Object} The new listeners array for this event.\n\t * @protected\n\t */\n\tremoveMatchingListenerObjs_(listenerObjs, listener) {\n\t\tconst finalListeners = [];\n\t\tfor (let i = 0; i < listenerObjs.length; i++) {\n\t\t\tif (!this.matchesListener_(listenerObjs[i], listener)) {\n\t\t\t\tfinalListeners.push(listenerObjs[i]);\n\t\t\t}\n\t\t}\n\t\treturn finalListeners.length > 0 ? finalListeners : null;\n\t}\n\n\t/**\n\t * Removes a listener for the specified events.\n\t * Caution: changes array indices in the listener array behind the listener.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveListener() {\n\t\treturn this.off.apply(this, arguments); // eslint-disable-line\n\t}\n\n\t/**\n\t * Runs the handlers when an event is listened to.\n\t * @param {string} event\n\t * @protected\n\t */\n\trunListenerHandlers_(event) {\n\t\tlet handlers = this.listenerHandlers_;\n\t\tif (handlers) {\n\t\t\thandlers = toArray(handlers);\n\t\t\tfor (let i = 0; i < handlers.length; i++) {\n\t\t\t\thandlers[i](event);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Runs the given listeners.\n\t * @param {!Array} listeners\n\t * @param {!Array} args\n\t * @param {Object} facade\n\t * @protected\n\t */\n\trunListeners_(listeners, args, facade) {\n\t\tif (facade) {\n\t\t\targs.push(facade);\n\t\t}\n\n\t\tconst defaultListeners = [];\n\t\tfor (let i = 0; i < listeners.length; i++) {\n\t\t\tconst listener = listeners[i].fn || listeners[i];\n\t\t\tif (listeners[i].default) {\n\t\t\t\tdefaultListeners.push(listener);\n\t\t\t} else {\n\t\t\t\tlistener.apply(this, args);\n\t\t\t}\n\t\t}\n\t\tif (!facade || !facade.preventedDefault) {\n\t\t\tfor (let j = 0; j < defaultListeners.length; j++) {\n\t\t\t\tdefaultListeners[j].apply(this, args);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets the configuration option which determines if an event facade should\n\t * be sent as a param of listeners when emitting events. If set to true, the\n\t * facade will be passed as the first argument of the listener.\n\t * @param {boolean} shouldUseFacade\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tsetShouldUseFacade(shouldUseFacade) {\n\t\tthis.shouldUseFacade_ = shouldUseFacade;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Converts the parameter to an array if only one event is given. Reuses the\n\t * same array each time this conversion is done, to avoid using more memory\n\t * than necessary.\n\t * @param {!(Array|string)} events\n\t * @return {!Array}\n\t * @protected\n\t */\n\ttoEventsArray_(events) {\n\t\tif (isString(events)) {\n\t\t\tsingleArray_[0] = events;\n\t\t\tevents = singleArray_;\n\t\t}\n\t\treturn events;\n\t}\n\n\t/**\n\t * Checks if the given listener is valid, throwing an exception when it's not.\n\t * @param {*} listener\n\t * @protected\n\t */\n\tvalidateListener_(listener) {\n\t\tif (!isFunction(listener)) {\n\t\t\tthrow new TypeError('Listener must be a function');\n\t\t}\n\t}\n}\n\n/**\n * Converts to an array\n * @param {Object} val\n * @return {Array}\n */\nfunction toArray(val) {\n\tval = val || [];\n\treturn Array.isArray(val) ? val : [val];\n}\n\nexport default EventEmitter;\n","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventEmitterProxy utility. It's responsible for linking two EventEmitter\n * instances together, emitting events from the first emitter through the\n * second one. That means that listening to a supported event on the target\n * emitter will mean listening to it on the origin emitter as well.\n * @extends {Disposable}\n */\nclass EventEmitterProxy extends Disposable {\n\t/**\n\t * @param {EventEmitter} originEmitter Events originated on this emitter\n\t * will be fired for the target emitter's listeners as well.\n\t * @param {EventEmitter} targetEmitter Event listeners attached to this emitter\n\t * will also be triggered when the event is fired by the origin emitter.\n\t * @param {Object} blacklist Optional blacklist of events that should not be\n\t * proxied.\n\t * @param {Object} whitelist\n\t */\n\tconstructor(originEmitter, targetEmitter, blacklist, whitelist) {\n\t\tsuper();\n\n\t\t/**\n\t\t * Map of events that should not be proxied.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.blacklist_ = blacklist;\n\n\t\t/**\n\t\t * The origin emitter. This emitter's events will be proxied through the\n\t\t * target emitter.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.originEmitter_ = originEmitter;\n\n\t\t/**\n\t\t * A list of events that are pending to be listened by an actual origin\n\t\t * emitter. Events are stored here when the origin doesn't exist, so they\n\t\t * can be set on a new origin when one is set.\n\t\t * @type {Array}\n\t\t * @protected\n\t\t */\n\t\tthis.pendingEvents_ = null;\n\n\t\t/**\n\t\t * Holds a map of events from the origin emitter that are already being proxied.\n\t\t * @type {Object<string, !EventHandle>}\n\t\t * @protected\n\t\t */\n\t\tthis.proxiedEvents_ = null;\n\n\t\t/**\n\t\t * The target emitter. This emitter will emit all events that come from\n\t\t * the origin emitter.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.targetEmitter_ = targetEmitter;\n\n\t\t/**\n\t\t * Map of events that should be proxied. If whitelist is set blacklist is ignored.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.whitelist_ = whitelist;\n\n\t\tthis.startProxy_();\n\t}\n\n\t/**\n\t * Adds the given listener for the given event.\n\t * @param {string} event\n\t * @param {!function()} listener\n\t * @return {!EventHandle} The listened event's handle.\n\t * @protected\n\t */\n\taddListener_(event, listener) {\n\t\treturn this.originEmitter_.on(event, listener);\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisposeInternal() {\n\t\tthis.removeListeners_();\n\t\tthis.proxiedEvents_ = null;\n\t\tthis.originEmitter_ = null;\n\t\tthis.targetEmitter_ = null;\n\t}\n\n\t/**\n\t * Emits the specified event type on the target emitter.\n\t * @protected\n\t */\n\temitOnTarget_(...args) {\n\t\tthis.targetEmitter_.emit(...args);\n\t}\n\n\t/**\n\t * Proxies the given event from the origin to the target emitter.\n\t * @param {string} event\n\t */\n\tproxyEvent(event) {\n\t\tif (this.shouldProxyEvent_(event)) {\n\t\t\tthis.tryToAddListener_(event);\n\t\t}\n\t}\n\n\t/**\n\t * Removes the proxy listener for all events.\n\t * @protected\n\t */\n\tremoveListeners_() {\n\t\tif (this.proxiedEvents_) {\n\t\t\tconst events = Object.keys(this.proxiedEvents_);\n\t\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\t\tthis.proxiedEvents_[events[i]].removeListener();\n\t\t\t}\n\t\t\tthis.proxiedEvents_ = null;\n\t\t}\n\t\tthis.pendingEvents_ = null;\n\t}\n\n\t/**\n\t * Changes the origin emitter. This automatically detaches any events that\n\t * were already being proxied from the previous emitter, and starts proxying\n\t * them on the new emitter instead.\n\t * @param {!EventEmitter} originEmitter\n\t */\n\tsetOriginEmitter(originEmitter) {\n\t\tconst events =\n\t\t\tthis.originEmitter_ && this.proxiedEvents_\n\t\t\t\t? Object.keys(this.proxiedEvents_)\n\t\t\t\t: this.pendingEvents_;\n\t\tthis.originEmitter_ = originEmitter;\n\t\tif (events) {\n\t\t\tthis.removeListeners_();\n\t\t\tevents.forEach(event => this.proxyEvent(event));\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given event should be proxied.\n\t * @param {string} event\n\t * @return {boolean}\n\t * @protected\n\t */\n\tshouldProxyEvent_(event) {\n\t\tif (this.whitelist_ && !this.whitelist_[event]) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.blacklist_ && this.blacklist_[event]) {\n\t\t\treturn false;\n\t\t}\n\t\treturn !this.proxiedEvents_ || !this.proxiedEvents_[event];\n\t}\n\n\t/**\n\t * Starts proxying all events from the origin to the target emitter.\n\t * @protected\n\t */\n\tstartProxy_() {\n\t\tthis.targetEmitter_.onListener(this.proxyEvent.bind(this));\n\t}\n\n\t/**\n\t * Adds a listener to the origin emitter, if it exists. Otherwise, stores\n\t * the pending listener so it can be used on a future origin emitter.\n\t * @param {string} event\n\t * @protected\n\t */\n\ttryToAddListener_(event) {\n\t\tif (this.originEmitter_) {\n\t\t\tthis.proxiedEvents_ = this.proxiedEvents_ || {};\n\t\t\tthis.proxiedEvents_[event] = this.addListener_(\n\t\t\t\tevent,\n\t\t\t\tthis.emitOnTarget_.bind(this, event)\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pendingEvents_ = this.pendingEvents_ || [];\n\t\t\tthis.pendingEvents_.push(event);\n\t\t}\n\t}\n}\n\nexport default EventEmitterProxy;\n","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventHandler utility. It's useful for easily removing a group of\n * listeners from different EventEmitter instances.\n * @extends {Disposable}\n */\nclass EventHandler extends Disposable {\n\t/**\n\t * EventHandler constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * An array that holds the added event handles, so the listeners can be\n\t\t * removed later.\n\t\t * @type {Array.<EventHandle>}\n\t\t * @protected\n\t\t */\n\t\tthis.eventHandles_ = [];\n\t}\n\n\t/**\n\t * Adds event handles to be removed later through the `removeAllListeners`\n\t * method.\n\t * @param {...(!EventHandle)} var_args\n\t */\n\tadd(...args) {\n\t\tfor (let i = 0; i < arguments.length; i++) {\n\t\t\tthis.eventHandles_.push(args[i]);\n\t\t}\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.eventHandles_ = null;\n\t}\n\n\t/**\n\t * Removes all listeners that have been added through the `add` method.\n\t */\n\tremoveAllListeners() {\n\t\tfor (let i = 0; i < this.eventHandles_.length; i++) {\n\t\t\tthis.eventHandles_[i].removeListener();\n\t\t}\n\n\t\tthis.eventHandles_ = [];\n\t}\n}\n\nexport default EventHandler;\n","'use strict';\n\nimport {array, isString} from 'metal';\nimport domData from './domData';\nimport {EventHandle} from 'metal-events';\n\n/**\n * This is a special EventHandle, that is responsible for dom delegated events\n * (only the ones that receive a target element, not a selector string).\n * @extends {EventHandle}\n */\nclass DomDelegatedEventHandle extends EventHandle {\n\t/**\n\t * The constructor for `DomDelegatedEventHandle`.\n\t * @param {!Event} emitter Element the event was subscribed to.\n\t * @param {string} event The name of the event that was subscribed to.\n\t * @param {!Function} listener The listener subscribed to the event.\n\t * @param {string=} selector An optional selector used when delegating\n\t * the event.\n\t * @constructor\n\t */\n\tconstructor(emitter, event, listener, selector) {\n\t\tsuper(emitter, event, listener);\n\t\tthis.selector_ = selector;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tremoveListener() {\n\t\tconst delegating = domData.get(this.emitter_, 'delegating', {});\n\t\tconst listeners = domData.get(this.emitter_, 'listeners', {});\n\t\tconst selector = this.selector_;\n\t\tconst arr = isString(selector)\n\t\t\t? delegating[this.event_].selectors\n\t\t\t: listeners;\n\t\tconst key = isString(selector) ? selector : this.event_;\n\n\t\tarray.remove(arr[key] || [], this.listener_);\n\t\tif (arr[key] && arr[key].length === 0) {\n\t\t\tdelete arr[key];\n\t\t}\n\t}\n}\n\nexport default DomDelegatedEventHandle;\n","'use strict';\n\nimport {EventHandle} from 'metal-events';\n\n/**\n * This is a special EventHandle, that is responsible for dom events, instead\n * of EventEmitter events.\n * @extends {EventHandle}\n */\nclass DomEventHandle extends EventHandle {\n\t/**\n\t * The constructor for `DomEventHandle`.\n\t * @param {!EventEmitter} emitter Emitter the event was subscribed to.\n\t * @param {string} event The name of the event that was subscribed to.\n\t * @param {!Function} listener The listener subscribed to the event.\n\t * @param {boolean} capture Flag indicating if listener should be triggered\n\t * during capture phase, instead of during the bubbling phase. Defaults to false.\n\t * @constructor\n\t */\n\tconstructor(emitter, event, listener, capture) {\n\t\tsuper(emitter, event, listener);\n\t\tthis.capture_ = capture;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tremoveListener() {\n\t\tthis.emitter_.removeEventListener(\n\t\t\tthis.event_,\n\t\t\tthis.listener_,\n\t\t\tthis.capture_\n\t\t);\n\t}\n}\n\nexport default DomEventHandle;\n","'use strict';\n\nimport {\n\tisDef,\n\tisDefAndNotNull,\n\tisDocument,\n\tisDocumentFragment,\n\tisElement,\n\tisObject,\n\tisString,\n\tobject,\n} from 'metal';\nimport domData from './domData';\nimport DomDelegatedEventHandle from './DomDelegatedEventHandle';\nimport DomEventHandle from './DomEventHandle';\n\nconst elementsByTag_ = {};\nconst supportCache_ = {};\nexport const customEvents = {};\n\nconst LAST_CONTAINER = '__metal_last_container__';\nconst USE_CAPTURE = {\n\tblur: true,\n\terror: true,\n\tfocus: true,\n\tinvalid: true,\n\tload: true,\n\tscroll: true,\n};\n\n/**\n * Adds the requested CSS classes to an element.\n * @param {!Element|!Nodelist} elements The element or elements to add CSS classes to.\n * @param {string} classes CSS classes to add.\n */\nexport function addClasses(elements, classes) {\n\tif (!isObject(elements) || !isString(classes)) {\n\t\treturn;\n\t}\n\n\tif (!elements.length) {\n\t\telements = [elements];\n\t}\n\n\tfor (let i = 0; i < elements.length; i++) {\n\t\tif ('classList' in elements[i]) {\n\t\t\taddClassesWithNative_(elements[i], classes);\n\t\t} else {\n\t\t\taddClassesWithoutNative_(elements[i], classes);\n\t\t}\n\t}\n}\n\n/**\n * Adds the requested CSS classes to an element using classList.\n * @param {!Element} element The element to add CSS classes to.\n * @param {string} classes CSS classes to add.\n * @private\n */\nfunction addClassesWithNative_(element, classes) {\n\tclasses.split(' ').forEach(function(className) {\n\t\tif (className) {\n\t\t\telement.classList.add(className);\n\t\t}\n\t});\n}\n\n/**\n * IE11 doesn't support Element.classList.add function, this method\n * adds the requested CSS classes to an element without using classList.\n * @param {!Element} element The element to add CSS classes to.\n * @param {string} classes CSS classes to add.\n * @private\n */\nfunction addClassesWithoutNative_(element, classes) {\n\tconst elementClassName = ` ${element.className} `;\n\tlet classesToAppend = '';\n\n\tclasses = classes.split(' ');\n\n\tfor (let i = 0; i < classes.length; i++) {\n\t\tconst className = classes[i];\n\n\t\tif (elementClassName.indexOf(` ${className} `) === -1) {\n\t\t\tclassesToAppend += ` ${className}`;\n\t\t}\n\t}\n\n\tif (classesToAppend) {\n\t\telement.className = element.className + classesToAppend;\n\t}\n}\n\n/**\n * Adds an event listener to the given element, to be triggered via delegate.\n * @param {!Element} element\n * @param {string} eventName\n * @param {!function()} listener\n * @private\n */\nfunction addElementListener_(element, eventName, listener) {\n\taddToArr_(domData.get(element, 'listeners', {}), eventName, listener);\n}\n\n/**\n * Adds an event listener to the given element, to be triggered via delegate\n * selectors.\n * @param {!Element} element\n * @param {string} eventName\n * @param {string} selector\n * @param {!function()} listener\n * @private\n */\nfunction addSelectorListener_(element, eventName, selector, listener) {\n\tconst delegatingData = domData.get(element, 'delegating', {});\n\taddToArr_(delegatingData[eventName].selectors, selector, listener);\n}\n\n/**\n * Adds a value to an array inside an object, creating it first if it doesn't\n * yet exist.\n * @param {!Array} arr\n * @param {string} key\n * @param {*} value\n * @private\n */\nfunction addToArr_(arr, key, value) {\n\tif (!arr[key]) {\n\t\tarr[key] = [];\n\t}\n\tarr[key].push(value);\n}\n\n/**\n * Attaches a delegate listener, unless there's already one attached.\n * @param {!Element} element\n * @param {string} eventName\n * @private\n */\nfunction attachDelegateEvent_(element, eventName) {\n\tlet delegatingData = domData.get(element, 'delegating', {});\n\tif (!delegatingData[eventName]) {\n\t\tdelegatingData[eventName] = {\n\t\t\thandle: on(\n\t\t\t\telement,\n\t\t\t\teventName,\n\t\t\t\thandleDelegateEvent_,\n\t\t\t\t!!USE_CAPTURE[eventName]\n\t\t\t),\n\t\t\tselectors: {},\n\t\t};\n\t}\n}\n\n/**\n * IE11 doesn't support Element.closest function, this method\n * gets the closest element up the tree from the given element (including\n * itself) that matches the specified selector, or null if none match.\n * @param {Element} element\n * @param {string} selector\n * @return {Element}\n */\nexport function closest(element, selector) {\n\twhile (element && !match(element, selector)) {\n\t\telement = element.parentNode;\n\t}\n\treturn element;\n}\n\n/**\n * IE11 doesn't support Element.classList.add function, this method\n * appends a child node with text or other nodes to a parent node. If\n * child is a HTML string it will be automatically converted to a document\n * fragment before appending it to the parent.\n * @param {!Element} parent The node to append nodes to.\n * @param {!(Element|NodeList|string)} child The thing to append to the parent.\n * @return {!Element} The appended child.\n */\nexport function append(parent, child) {\n\tif (isString(child)) {\n\t\tchild = buildFragment(child);\n\t}\n\tif (isNodeListLike(child)) {\n\t\tconst childArr = Array.prototype.slice.call(child);\n\t\tfor (let i = 0; i < childArr.length; i++) {\n\t\t\tparent.appendChild(childArr[i]);\n\t\t}\n\t} else {\n\t\tparent.appendChild(child);\n\t}\n\treturn child;\n}\n\n/**\n * Helper for converting a HTML string into a document fragment.\n * @param {string} htmlString The HTML string to convert.\n * @return {!Element} The resulting document fragment.\n */\nexport function buildFragment(htmlString) {\n\tconst tempDiv = document.createElement('div');\n\ttempDiv.innerHTML = `<br>${htmlString}`;\n\ttempDiv.removeChild(tempDiv.firstChild);\n\n\tconst fragment = document.createDocumentFragment();\n\twhile (tempDiv.firstChild) {\n\t\tfragment.appendChild(tempDiv.firstChild);\n\t}\n\treturn fragment;\n}\n\n/**\n * Checks if the first element contains the second one.\n * @deprecated Use element1.contains(element2) directly instead of this method\n * @param {!Element} element1\n * @param {!Element} element2\n * @return {boolean}\n */\nexport function contains(element1, element2) {\n\tif (isDocument(element1)) {\n\t\t// document.contains is not defined on IE9, so call it on documentElement instead.\n\t\treturn element1.documentElement.contains(element2);\n\t} else {\n\t\treturn element1.contains(element2);\n\t}\n}\n\n/**\n * Listens to the specified event on the given DOM element, but only calls the\n * given callback listener when it's triggered by elements that match the\n * given selector or target element.\n * @param {!Element} element The DOM element the event should be listened on.\n * @param {string} eventName The name of the event to listen to.\n * @param {!Element|string} selectorOrTarget Either an element or css selector\n * that should match the event for the listener to be triggered.\n * @param {!function(!Object)} callback Function to be called when the event\n * is triggered. It will receive the normalized event object.\n * @param {boolean=} defaultListener Optional flag indicating if this is a default\n * listener. That means that it would only be executed after all non\n * default listeners, and only if the event isn't prevented via\n * `preventDefault`.\n * @return {!EventHandle} Can be used to remove the listener.\n */\nexport function delegate(\n\telement,\n\teventName,\n\tselectorOrTarget,\n\tcallback,\n\tdefaultListener\n) {\n\tconst customConfig = customEvents[eventName];\n\tif (customConfig && customConfig.delegate) {\n\t\teventName = customConfig.originalEvent;\n\t\tcallback = customConfig.handler.bind(customConfig, callback);\n\t}\n\n\tif (defaultListener) {\n\t\t// Wrap callback so we don't set property directly on it.\n\t\tcallback = callback.bind();\n\t\tcallback.defaultListener_ = true;\n\t}\n\n\tattachDelegateEvent_(element, eventName);\n\tif (isString(selectorOrTarget)) {\n\t\taddSelectorListener_(element, eventName, selectorOrTarget, callback);\n\t} else {\n\t\taddElementListener_(selectorOrTarget, eventName, callback);\n\t}\n\n\treturn new DomDelegatedEventHandle(\n\t\tisString(selectorOrTarget) ? element : selectorOrTarget,\n\t\teventName,\n\t\tcallback,\n\t\tisString(selectorOrTarget) ? selectorOrTarget : null\n\t);\n}\n\n/**\n * Verifies if the element is able to trigger the Click event,\n * simulating browsers behaviour, avoiding event listeners to be called by triggerEvent method.\n * @param {Element} node Element to be checked.\n * @param {string} eventName The event name.\n * @param {Object=} eventObj\n * @private\n * @return {boolean}\n */\nfunction isAbleToInteractWith_(node, eventName, eventObj) {\n\tif (eventObj && eventName === 'click' && eventObj.button === 2) {\n\t\t// Firefox triggers \"click\" events on the document for right clicks. This\n\t\t// causes our delegate logic to trigger it for regular elements too, which\n\t\t// shouldn't happen. Ignoring them here.\n\t\treturn false;\n\t}\n\n\tconst matchesSelector = [\n\t\t'BUTTON',\n\t\t'INPUT',\n\t\t'SELECT',\n\t\t'TEXTAREA',\n\t\t'FIELDSET',\n\t];\n\tif (eventName === 'click' && matchesSelector.indexOf(node.tagName) > -1) {\n\t\treturn !(node.disabled || parent(node, 'fieldset[disabled]'));\n\t}\n\treturn true;\n}\n\n/**\n * Returns true if the specified value is a NodeList or like one.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is like a NodeList.\n */\nexport function isNodeListLike(val) {\n\treturn (\n\t\tisDefAndNotNull(val) &&\n\t\ttypeof val.length === 'number' &&\n\t\ttypeof val.item === 'function'\n\t);\n}\n\n/**\n * Inserts node in document as last element.\n * @param {Element} node Element to remove children from.\n */\nexport function enterDocument(node) {\n\tnode && append(document.body, node);\n}\n\n/**\n * Removes node from document.\n * @param {Element} node Element to remove children from.\n */\nexport function exitDocument(node) {\n\tif (node && node.parentNode) {\n\t\tnode.parentNode.removeChild(node);\n\t}\n}\n\n/**\n * This is called when an event is triggered by a delegate listener. All\n * matching listeners of this event type from `target` to `currentTarget` will\n * be triggered.\n * @param {!Event} event The event payload.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction handleDelegateEvent_(event) {\n\tnormalizeDelegateEvent_(event);\n\tlet ret = true;\n\tconst container = event.currentTarget;\n\tconst defFns = [];\n\n\tret &= triggerDelegatedListeners_(container, event, defFns);\n\tret &= triggerDefaultDelegatedListeners_(defFns, event);\n\n\tevent.delegateTarget = null;\n\tevent[LAST_CONTAINER] = container;\n\treturn ret;\n}\n\n/**\n * Checks if the given element has the requested css class.\n * @param {!Element} element\n * @param {string} className\n * @return {boolean}\n */\nexport function hasClass(element, className) {\n\tif ('classList' in element) {\n\t\treturn hasClassWithNative_(element, className);\n\t} else {\n\t\treturn hasClassWithoutNative_(element, className);\n\t}\n}\n\n/**\n * Checks if the given element has the requested css class using classList.\n * @param {!Element} element\n * @param {string} className\n * @return {boolean}\n * @private\n */\nfunction hasClassWithNative_(element, className) {\n\treturn (\n\t\tclassName.indexOf(' ') === -1 && element.classList.contains(className)\n\t);\n}\n\n/**\n * Checks if the given element has the requested css class without using classList.\n * @param {!Element} element\n * @param {string} className\n * @return {boolean}\n * @private\n */\nfunction hasClassWithoutNative_(element, className) {\n\treturn (\n\t\t` ${element.className} `.indexOf(` ${className} `) >= 0 &&\n\t\tclassName.split(' ').length === 1\n\t);\n}\n\n/**\n * Checks if the given element is empty or not.\n * @param {!Element} element\n * @return {boolean}\n */\nexport function isEmpty(element) {\n\treturn element.childNodes.length === 0;\n}\n\n/**\n * IE11 doesn't support Element.matches function, this method\n * check if an element matches a given selector.\n * @param {Element} element\n * @param {string} selector\n * @return {boolean}\n */\nexport function match(element, selector) {\n\tif (!element || element.nodeType !== 1) {\n\t\treturn false;\n\t}\n\n\tconst p = Element.prototype;\n\tconst m =\n\t\tp.matches ||\n\t\tp.webkitMatchesSelector ||\n\t\tp.mozMatchesSelector ||\n\t\tp.msMatchesSelector ||\n\t\tp.oMatchesSelector;\n\tif (m) {\n\t\treturn m.call(element, selector);\n\t}\n\n\treturn matchFallback_(element, selector);\n}\n\n/**\n * Check if an element matches a given selector, using an internal implementation\n * instead of calling existing javascript functions.\n * @param {Element} element\n * @param {string} selector\n * @return {boolean}\n * @private\n */\nfunction matchFallback_(element, selector) {\n\tconst parentNode = element.parentNode;\n\n\tif (parentNode) {\n\t\tconst nodes = parentNode.querySelectorAll(selector);\n\n\t\tfor (let i = 0; i < nodes.length; ++i) {\n\t\t\tif (nodes[i] === element) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Returns the next sibling of the given element that matches the specified\n * selector, or null if there is none.\n * @param {!Element} element\n * @param {?string} selector\n * @return {Element|null}\n */\nexport function next(element, selector) {\n\tdo {\n\t\telement = element.nextSibling;\n\t\tif (element && match(element, selector)) {\n\t\t\treturn element;\n\t\t}\n\t} while (element);\n\treturn null;\n}\n\n/**\n * Normalizes the event payload for delegate listeners.\n * @param {!Event} event\n * @private\n */\nfunction normalizeDelegateEvent_(event) {\n\tevent.stopPropagation = stopPropagation_;\n\tevent.stopImmediatePropagation = stopImmediatePropagation_;\n}\n\n/**\n * Listens to the specified event on the given DOM element. This function normalizes\n * DOM event payloads and functions so they'll work the same way on all supported\n * browsers.\n * @param {!Element|string} element The DOM element to listen to the event on, or\n * a selector that should be delegated on the entire document.\n * @param {string} eventName The name of the event to listen to.\n * @param {!function(!Object)} callback Function to be called when the event is\n * triggered. It will receive the normalized event object.\n * @param {boolean} capture Flag indicating if listener should be triggered\n * during capture phase, instead of during the bubbling phase. Defaults to false.\n * @return {!DomEventHandle} Can be used to remove the listener.\n */\nexport function on(element, eventName, callback, capture) {\n\tif (isString(element)) {\n\t\treturn delegate(document, eventName, element, callback);\n\t}\n\tconst customConfig = customEvents[eventName];\n\tif (customConfig && customConfig.event) {\n\t\teventName = customConfig.originalEvent;\n\t\tcallback = customConfig.handler.bind(customConfig, callback);\n\t}\n\telement.addEventListener(eventName, callback, capture);\n\treturn new DomEventHandle(element, eventName, callback, capture);\n}\n\n/**\n * IE11 doesn't support once event listener option, this method\n * Listens to the specified event on the given DOM element once. This\n * function normalizes DOM event payloads and functions so they'll work the\n * same way on all supported browsers.\n * @param {!Element} element The DOM element to listen to the event on.\n * @param {string} eventName The name of the event to listen to.\n * @param {!function(!Object)} callback Function to be called when the event\n * is triggered. It will receive the normalized event object.\n * @return {!DomEventHandle} Can be used to remove the listener.\n */\nexport function once(element, eventName, callback) {\n\tconst domEventHandle = on(element, eventName, function() {\n\t\tdomEventHandle.removeListener();\n\t\treturn callback.apply(this, arguments); // eslint-disable-line\n\t});\n\treturn domEventHandle;\n}\n\n/**\n * Gets the first parent from the given element that matches the specified\n * selector, or null if none match.\n * @param {!Element} element\n * @param {string} selector\n * @return {Element}\n */\nexport function parent(element, selector) {\n\treturn closest(element.parentNode, selector);\n}\n\n/**\n * IE11 doesn't support Element.prepend function, this method\n * inserts a node before first child of the parent. If child is a HTML string\n * it will be converted to document fragment before prepending it to the parent.\n * @param {!Element} parent The node to prepend to.\n * @param {!(Element|NodeList|string)} child The thing to prepend to the parent.\n * @return {!Element} The prepended child.\n */\nexport function prepend(parent, child) {\n\tif (isString(child)) {\n\t\tchild = buildFragment(child);\n\t}\n\n\tif (!isNodeListLike(child) && !isDefAndNotNull(parent.firstChild)) {\n\t\treturn append(parent, child);\n\t}\n\n\tif (isNodeListLike(child)) {\n\t\tconst childArr = Array.prototype.slice.call(child);\n\t\tfor (let i = childArr.length - 1; i >= 0; i--) {\n\t\t\tparent.insertBefore(childArr[i], parent.firstChild);\n\t\t}\n\t} else {\n\t\tparent.insertBefore(child, parent.firstChild);\n\t}\n\n\treturn child;\n}\n\n/**\n * Registers a custom event.\n * @param {string} eventName The name of the custom event.\n * @param {!Object} customConfig An object with information about how the event\n * should be handled.\n */\nexport function registerCustomEvent(eventName, customConfig) {\n\tcustomEvents[eventName] = customConfig;\n}\n\n/**\n * Removes all the child nodes on a DOM node.\n * @param {Element} node Element to remove children from.\n */\nexport function removeChildren(node) {\n\tlet child;\n\twhile ((child = node.firstChild)) {\n\t\tnode.removeChild(child);\n\t}\n}\n\n/**\n * Removes the requested CSS classes from an element.\n * @param {!Element|!NodeList} elements The element or elements to remove CSS classes from.\n * @param {string} classes CSS classes to remove.\n */\nexport function removeClasses(elements, classes) {\n\tif (!isObject(elements) || !isString(classes)) {\n\t\treturn;\n\t}\n\n\tif (!elements.length) {\n\t\telements = [elements];\n\t}\n\n\tfor (let i = 0; i < elements.length; i++) {\n\t\tif ('classList' in elements[i]) {\n\t\t\tremoveClassesWithNative_(elements[i], classes);\n\t\t} else {\n\t\t\tremoveClassesWithoutNative_(elements[i], classes);\n\t\t}\n\t}\n}\n\n/**\n * Removes the requested CSS classes from an element using classList.\n * @param {!Element} element The element to remove CSS classes from.\n * @param {string} classes CSS classes to remove.\n * @private\n */\nfunction removeClassesWithNative_(element, classes) {\n\tclasses.split(' ').forEach(function(className) {\n\t\tif (className) {\n\t\t\telement.classList.remove(className);\n\t\t}\n\t});\n}\n\n/**\n * IE11 doesn't support Element.classList, this method\n * removes the requested CSS classes from an element without using classList.\n * @param {!Element} element The element to remove CSS classes from.\n * @param {string} classes CSS classes to remove.\n * @private\n */\nfunction removeClassesWithoutNative_(element, classes) {\n\tlet elementClassName = ` ${element.className} `;\n\n\tclasses = classes.split(' ');\n\n\tfor (let i = 0; i < classes.length; i++) {\n\t\telementClassName = elementClassName.replace(` ${classes[i]} `, ' ');\n\t}\n\n\telement.className = elementClassName.trim();\n}\n\n/**\n * Replaces the first element with the second.\n * @deprecated Use element1.parentNode.replaceChild(element2, element1)\n * directly instead of this method\n * @param {Element} element1\n * @param {Element} element2\n */\nexport function replace(element1, element2) {\n\tif (element1 && element2 && element1 !== element2 && element1.parentNode) {\n\t\telement1.parentNode.replaceChild(element2, element1);\n\t}\n}\n\n/**\n * The function that replaces `stopImmediatePropagation_` for events.\n * @private\n */\nfunction stopImmediatePropagation_() {\n\tconst event = this; // eslint-disable-line\n\tevent.stopped = true;\n\tevent.stoppedImmediate = true;\n\tEvent.prototype.stopImmediatePropagation.call(event);\n}\n\n/**\n * The function that replaces `stopPropagation` for events.\n * @private\n */\nfunction stopPropagation_() {\n\tconst event = this; // eslint-disable-line\n\tevent.stopped = true;\n\tEvent.prototype.stopPropagation.call(event);\n}\n\n/**\n * Checks if the given element supports the given event type.\n * @param {!Element|string} element The DOM element or element tag name to check.\n * @param {string} eventName The name of the event to check.\n * @return {boolean}\n */\nexport function supportsEvent(element, eventName) {\n\tif (customEvents[eventName]) {\n\t\treturn true;\n\t}\n\n\tif (isString(element)) {\n\t\tif (!elementsByTag_[element]) {\n\t\t\telementsByTag_[element] = document.createElement(element);\n\t\t}\n\t\telement = elementsByTag_[element];\n\t}\n\n\tconst tag = element.tagName;\n\tif (!supportCache_[tag] || !supportCache_[tag].hasOwnProperty(eventName)) {\n\t\tsupportCache_[tag] = supportCache_[tag] || {};\n\t\tsupportCache_[tag][eventName] = 'on' + eventName in element;\n\t}\n\treturn supportCache_[tag][eventName];\n}\n\n/**\n * This triggers all default matched delegated listeners of a given event type.\n * @param {!Array} defFns Array to collect default listeners in, instead\n * @param {!Event} event\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerDefaultDelegatedListeners_(defFns, event) {\n\tlet ret = true;\n\n\tfor (let i = 0; i < defFns.length && !event.defaultPrevented; i++) {\n\t\tevent.delegateTarget = defFns[i].element;\n\t\tret &= defFns[i].fn(event);\n\t}\n\n\treturn ret;\n}\n\n/**\n * This triggers all matched delegated listeners of a given event type when its\n * delegated target is able to interact.\n * @param {!Element} container\n * @param {!Event} event\n * @param {!Array} defaultFns Array to collect default listeners in, instead\n * of running them.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerDelegatedListeners_(container, event, defaultFns) {\n\tlet ret = true;\n\tlet currElement = event.target;\n\tconst limit = container.parentNode;\n\n\twhile (currElement && currElement !== limit && !event.stopped) {\n\t\tif (isAbleToInteractWith_(currElement, event.type, event)) {\n\t\t\tevent.delegateTarget = currElement;\n\t\t\tret &= triggerElementListeners_(currElement, event, defaultFns);\n\t\t\tret &= triggerSelectorListeners_(\n\t\t\t\tcontainer,\n\t\t\t\tcurrElement,\n\t\t\t\tevent,\n\t\t\t\tdefaultFns\n\t\t\t);\n\t\t}\n\t\tcurrElement = currElement.parentNode;\n\t}\n\n\treturn ret;\n}\n\n/**\n * Converts the given argument to a DOM element. Strings are assumed to\n * be selectors, and so a matched element will be returned. If the arg\n * is already a DOM element it will be the return value.\n * @param {string|Element|Document} selectorOrElement\n * @return {Element} The converted element, or null if none was found.\n */\nexport function toElement(selectorOrElement) {\n\tif (\n\t\tisElement(selectorOrElement) ||\n\t\tisDocument(selectorOrElement) ||\n\t\tisDocumentFragment(selectorOrElement)\n\t) {\n\t\treturn selectorOrElement;\n\t} else if (isString(selectorOrElement)) {\n\t\treturn document.querySelector(selectorOrElement);\n\t} else {\n\t\treturn null;\n\t}\n}\n\n/**\n * Adds or removes one or more classes from an element. If any of the classes\n * is present, it will be removed from the element, or added otherwise.\n * @param {!Element} element The element which classes will be toggled.\n * @param {string} classes The classes which have to added or removed from the element.\n */\nexport function toggleClasses(element, classes) {\n\tif (!isObject(element) || !isString(classes)) {\n\t\treturn;\n\t}\n\n\tif ('classList' in element) {\n\t\ttoggleClassesWithNative_(element, classes);\n\t} else {\n\t\ttoggleClassesWithoutNative_(element, classes);\n\t}\n}\n\n/**\n * Adds or removes one or more classes from an element using classList.\n * If any of the classes is present, it will be removed from the element,\n * or added otherwise.\n * @param {!Element} element The element which classes will be toggled.\n * @param {string} classes The classes which have to added or removed from the element.\n * @private\n */\nfunction toggleClassesWithNative_(element, classes) {\n\tclasses.split(' ').forEach(function(className) {\n\t\telement.classList.toggle(className);\n\t});\n}\n\n/**\n * IE11 doesn't support Element.classList, this method\n * adds or removes one or more classes from an element without using classList.\n * If any of the classes is present, it will be removed from the element,\n * or added otherwise.\n * @param {!Element} element The element which classes will be toggled.\n * @param {string} classes The classes which have to added or removed from the element.\n * @private\n */\nfunction toggleClassesWithoutNative_(element, classes) {\n\tlet elementClassName = ` ${element.className} `;\n\n\tclasses = classes.split(' ');\n\n\tfor (let i = 0; i < classes.length; i++) {\n\t\tconst className = ` ${classes[i]} `;\n\t\tconst classIndex = elementClassName.indexOf(className);\n\n\t\tif (classIndex === -1) {\n\t\t\telementClassName = `${elementClassName}${classes[i]} `;\n\t\t} else {\n\t\t\tconst before = elementClassName.substring(0, classIndex);\n\t\t\tconst after = elementClassName.substring(\n\t\t\t\tclassIndex + className.length\n\t\t\t); // eslint-disable-line\n\t\t\telementClassName = `${before} ${after}`;\n\t\t}\n\t}\n\n\telement.className = elementClassName.trim();\n}\n\n/**\n * Triggers all listeners for the given event type that are stored in the\n * specified element.\n * @param {!Element} element\n * @param {!Event} event\n * @param {!Array} defaultFns Array to collect default listeners in, instead\n * of running them.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerElementListeners_(element, event, defaultFns) {\n\tconst lastContainer = event[LAST_CONTAINER];\n\tif (!isDef(lastContainer) || !contains(lastContainer, element)) {\n\t\tconst listeners = domData.get(element, 'listeners', {})[event.type];\n\t\treturn triggerListeners_(listeners, event, element, defaultFns);\n\t}\n\treturn true;\n}\n\n/**\n * Triggers the specified event on the given element.\n * NOTE: This should mostly be used for testing, not on real code.\n * @param {!Element} element The node that should trigger the event.\n * @param {string} eventName The name of the event to be triggred.\n * @param {Object=} eventObj An object with data that should be on the\n * triggered event's payload.\n */\nexport function triggerEvent(element, eventName, eventObj) {\n\tif (isAbleToInteractWith_(element, eventName, eventObj)) {\n\t\tconst payload = document.createEvent('HTMLEvents');\n\t\tpayload.initEvent(eventName, true, true);\n\t\tobject.mixin(payload, eventObj);\n\t\telement.dispatchEvent(payload);\n\t}\n}\n\n/**\n * Triggers the given listeners array.\n * @param {Array<!function()>} listeners\n * @param {!Event} event\n * @param {!Element} element\n * @param {!Array} defaultFns Array to collect default listeners in, instead\n * of running them.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerListeners_(listeners, event, element, defaultFns) {\n\tlet ret = true;\n\tlisteners = listeners || [];\n\tfor (let i = 0; i < listeners.length && !event.stoppedImmediate; i++) {\n\t\tif (listeners[i].defaultListener_) {\n\t\t\tdefaultFns.push({\n\t\t\t\telement,\n\t\t\t\tfn: listeners[i],\n\t\t\t});\n\t\t} else {\n\t\t\tret &= listeners[i](event);\n\t\t}\n\t}\n\treturn ret;\n}\n\n/**\n * Triggers all selector listeners for the given event.\n * @param {!Element} container\n * @param {!Element} element\n * @param {!Event} event\n * @param {!Array} defaultFns Array to collect default listeners in, instead\n * of running them.\n * @return {boolean} False if at least one of the triggered callbacks returns\n * false, or true otherwise.\n * @private\n */\nfunction triggerSelectorListeners_(container, element, event, defaultFns) {\n\tlet ret = true;\n\tconst data = domData.get(container, 'delegating', {});\n\tconst map = data[event.type].selectors;\n\tconst selectors = Object.keys(map);\n\tfor (let i = 0; i < selectors.length && !event.stoppedImmediate; i++) {\n\t\tif (match(element, selectors[i])) {\n\t\t\tconst listeners = map[selectors[i]];\n\t\t\tret &= triggerListeners_(listeners, event, element, defaultFns);\n\t\t}\n\t}\n\treturn ret;\n}\n","'use strict';\n\n// This file exists just for backwards compatibility, making sure that old\n// default imports for this file still work. It's best to use the named exports\n// for each function instead though, since that allows bundlers like Rollup to\n// reduce the bundle size by removing unused code.\nimport * as dom from './domNamed';\n\nexport default dom;\nexport {dom};\nexport * from './domNamed';\n","'use strict';\n\nimport {delegate, on, supportsEvent} from './dom';\nimport {EventEmitterProxy} from 'metal-events';\n\n/**\n * DomEventEmitterProxy utility. It extends `EventEmitterProxy` to also accept\n * dom elements as origin emitters.\n * @extends {EventEmitterProxy}\n */\nclass DomEventEmitterProxy extends EventEmitterProxy {\n\t/**\n\t * Adds the given listener for the given event.\n\t * @param {string} event\n\t * @param {!function()} listener\n\t * @return {!EventHandle} The listened event's handle.\n\t * @protected\n\t * @override\n\t */\n\taddListener_(event, listener) {\n\t\tif (this.originEmitter_.addEventListener) {\n\t\t\tif (this.isDelegateEvent_(event)) {\n\t\t\t\tconst index = event.indexOf(':', 9);\n\t\t\t\tconst eventName = event.substring(9, index);\n\t\t\t\tconst selector = event.substring(index + 1);\n\t\t\t\treturn delegate(\n\t\t\t\t\tthis.originEmitter_,\n\t\t\t\t\teventName,\n\t\t\t\t\tselector,\n\t\t\t\t\tlistener\n\t\t\t\t); // eslint-disable-line\n\t\t\t} else {\n\t\t\t\treturn on(this.originEmitter_, event, listener);\n\t\t\t}\n\t\t} else {\n\t\t\treturn super.addListener_(event, listener);\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given event is of the delegate type.\n\t * @param {string} event\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisDelegateEvent_(event) {\n\t\treturn event.substr(0, 9) === 'delegate:';\n\t}\n\n\t/**\n\t * Checks if the given event is supported by the origin element.\n\t * @param {string} event\n\t * @protected\n\t * @return {boolean}\n\t */\n\tisSupportedDomEvent_(event) {\n\t\tif (!this.originEmitter_ || !this.originEmitter_.addEventListener) {\n\t\t\treturn true;\n\t\t}\n\t\treturn (\n\t\t\t(this.isDelegateEvent_(event) && event.indexOf(':', 9) !== -1) ||\n\t\t\tsupportsEvent(this.originEmitter_, event)\n\t\t);\n\t}\n\n\t/**\n\t * Checks if the given event should be proxied.\n\t * @param {string} event\n\t * @return {boolean}\n\t * @protected\n\t * @override\n\t */\n\tshouldProxyEvent_(event) {\n\t\treturn (\n\t\t\tsuper.shouldProxyEvent_(event) && this.isSupportedDomEvent_(event)\n\t\t); // eslint-disable-line\n\t}\n}\n\nexport default DomEventEmitterProxy;\n","'use strict';\n\nimport {append} from './dom';\nimport {string} from 'metal';\n\n/**\n * Class with static methods responsible for doing browser feature checks.\n */\nclass features {\n\t/**\n\t * Some browsers still supports prefixed animation events. This method can\n\t * be used to retrieve the current browser event name for both, animation\n\t * and transition.\n\t * @return {object}\n\t */\n\tstatic checkAnimationEventName() {\n\t\tif (features.animationEventName_ === undefined) {\n\t\t\tfeatures.animationEventName_ = {\n\t\t\t\tanimation: features.checkAnimationEventName_('animation'),\n\t\t\t\ttransition: features.checkAnimationEventName_('transition'),\n\t\t\t};\n\t\t}\n\t\treturn features.animationEventName_;\n\t}\n\n\t/**\n\t * @protected\n\t * @param {string} type Type to test: animation, transition.\n\t * @return {string} Browser event name.\n\t */\n\tstatic checkAnimationEventName_(type) {\n\t\tconst prefixes = ['Webkit', 'MS', 'O', ''];\n\t\tconst typeTitleCase = string.replaceInterval(\n\t\t\ttype,\n\t\t\t0,\n\t\t\t1,\n\t\t\ttype.substring(0, 1).toUpperCase()\n\t\t);\n\t\tconst suffixes = [\n\t\t\t`${typeTitleCase}End`,\n\t\t\t`${typeTitleCase}End`,\n\t\t\t`${typeTitleCase}End`,\n\t\t\t`${type}end`,\n\t\t];\n\t\tif (!features.animationElement_) {\n\t\t\tfeatures.animationElement_ = document.createElement('div');\n\t\t}\n\t\tfor (let i = 0; i < prefixes.length; i++) {\n\t\t\tif (\n\t\t\t\tfeatures.animationElement_.style[\n\t\t\t\t\tprefixes[i] + typeTitleCase\n\t\t\t\t] !== undefined // eslint-disable-line\n\t\t\t) {\n\t\t\t\treturn prefixes[i].toLowerCase() + suffixes[i];\n\t\t\t}\n\t\t}\n\t\treturn `${type}end`;\n\t}\n\n\t/**\n\t * Some browsers (like IE11, Edge) change the order of element attributes, when html\n\t * is rendered. This method can be used to check if this behavior happens on\n\t * the current browser.\n\t * @return {boolean}\n\t */\n\tstatic checkAttrOrderChange() {\n\t\tif (features.attrOrderChange_ === undefined) {\n\t\t\tconst originalContent = '<div data-component=\"\" data-ref=\"\"></div>';\n\t\t\tconst element = document.createElement('div');\n\t\t\tappend(element, originalContent);\n\t\t\tfeatures.attrOrderChange_ = originalContent !== element.innerHTML;\n\t\t}\n\t\treturn features.attrOrderChange_;\n\t}\n}\n\nfeatures.animationElement_ = undefined;\nfeatures.animationEventName_ = undefined;\nfeatures.attrOrderChange_ = undefined;\n\nexport default features;\n","'use strict';\n\nimport {async} from 'metal';\nimport {exitDocument, once} from './dom';\n\n/**\n * Utility functions for running javascript code in the global scope.\n */\nclass globalEval {\n\t/**\n\t * Evaluates the given string in the global scope.\n\t * @param {string} text\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic run(text, appendFn) {\n\t\tconst script = document.createElement('script');\n\t\tscript.text = text;\n\t\tif (appendFn) {\n\t\t\tappendFn(script);\n\t\t} else {\n\t\t\tdocument.head.appendChild(script);\n\t\t}\n\t\texitDocument(script);\n\t\treturn script;\n\t}\n\n\t/**\n\t * Evaluates the given javascript file in the global scope.\n\t * @param {string} src The file's path.\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic runFile(src, defaultFn, appendFn) {\n\t\tconst script = document.createElement('script');\n\t\tscript.src = src;\n\n\t\tconst callback = function() {\n\t\t\texitDocument(script);\n\t\t\tdefaultFn && defaultFn();\n\t\t};\n\t\tonce(script, 'load', callback);\n\t\tonce(script, 'error', callback);\n\n\t\tif (appendFn) {\n\t\t\tappendFn(script);\n\t\t} else {\n\t\t\tdocument.head.appendChild(script);\n\t\t}\n\n\t\treturn script;\n\t}\n\n\t/**\n\t * Evaluates the code referenced by the given script element.\n\t * @param {!Element} script\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic runScript(script, defaultFn, appendFn) {\n\t\tconst callback = function() {\n\t\t\tdefaultFn && defaultFn();\n\t\t};\n\t\tif (script.type && script.type !== 'text/javascript') {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn;\n\t\t}\n\t\texitDocument(script);\n\t\tif (script.src) {\n\t\t\treturn globalEval.runFile(script.src, defaultFn, appendFn);\n\t\t} else {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn globalEval.run(script.text, appendFn);\n\t\t}\n\t}\n\n\t/**\n\t * Evaluates any script tags present in the given element.\n\t * @param {!Element} element\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runScriptsInElement(element, defaultFn, appendFn) {\n\t\tconst scripts = element.querySelectorAll('script');\n\t\tif (scripts.length) {\n\t\t\tglobalEval.runScriptsInOrder(scripts, 0, defaultFn, appendFn);\n\t\t} else if (defaultFn) {\n\t\t\tasync.nextTick(defaultFn);\n\t\t}\n\t}\n\n\t/**\n\t * Runs the given scripts elements in the order that they appear.\n\t * @param {!NodeList} scripts\n\t * @param {number} index\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runScriptsInOrder(scripts, index, defaultFn, appendFn) {\n\t\tglobalEval.runScript(\n\t\t\tscripts.item(index),\n\t\t\tfunction() {\n\t\t\t\tif (index < scripts.length - 1) {\n\t\t\t\t\tglobalEval.runScriptsInOrder(\n\t\t\t\t\t\tscripts,\n\t\t\t\t\t\tindex + 1,\n\t\t\t\t\t\tdefaultFn,\n\t\t\t\t\t\tappendFn\n\t\t\t\t\t); // eslint-disable-line\n\t\t\t\t} else if (defaultFn) {\n\t\t\t\t\tasync.nextTick(defaultFn);\n\t\t\t\t}\n\t\t\t},\n\t\t\tappendFn\n\t\t);\n\t}\n}\n\nexport default globalEval;\n","'use strict';\n\nimport {async} from 'metal';\nimport {once} from './dom';\n\n/**\n * Utility functions for running styles.\n */\nclass globalEvalStyles {\n\t/**\n\t * Evaluates the given style.\n\t * @param {string} text\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic run(text, appendFn) {\n\t\tconst style = document.createElement('style');\n\t\tstyle.innerHTML = text;\n\t\tif (appendFn) {\n\t\t\tappendFn(style);\n\t\t} else {\n\t\t\tdocument.head.appendChild(style);\n\t\t}\n\t\treturn style;\n\t}\n\n\t/**\n\t * Evaluates the given style file.\n\t * @param {string} href The file's path.\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the styles has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic runFile(href, defaultFn, appendFn) {\n\t\tconst link = document.createElement('link');\n\t\tlink.rel = 'stylesheet';\n\t\tlink.href = href;\n\t\tglobalEvalStyles.runStyle(link, defaultFn, appendFn);\n\t\treturn link;\n\t}\n\n\t/**\n\t * Evaluates the code referenced by the given style/link element.\n\t * @param {!Element} style\n\t * @param {function()=} defaultFn Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic runStyle(style, defaultFn, appendFn) {\n\t\tconst callback = function() {\n\t\t\tdefaultFn && defaultFn();\n\t\t};\n\t\tif (\n\t\t\tstyle.rel &&\n\t\t\tstyle.rel !== 'stylesheet' &&\n\t\t\tstyle.rel !== 'canonical' &&\n\t\t\tstyle.rel !== 'alternate'\n\t\t) {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tstyle.tagName === 'STYLE' ||\n\t\t\tstyle.rel === 'canonical' ||\n\t\t\tstyle.rel === 'alternate'\n\t\t) {\n\t\t\tasync.nextTick(callback);\n\t\t} else {\n\t\t\tonce(style, 'load', callback);\n\t\t\tonce(style, 'error', callback);\n\t\t}\n\n\t\tif (appendFn) {\n\t\t\tappendFn(style);\n\t\t} else {\n\t\t\tdocument.head.appendChild(style);\n\t\t}\n\n\t\treturn style;\n\t}\n\n\t/**\n\t * Evaluates any style present in the given element.\n\t * @param {!Element} element\n\t * @param {function()=} defaultFn Optional function to be called when the\n\t * style has been run.\n\t * @param {function()=} appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runStylesInElement(element, defaultFn, appendFn) {\n\t\tconst styles = element.querySelectorAll('style,link');\n\t\tif (styles.length === 0 && defaultFn) {\n\t\t\tasync.nextTick(defaultFn);\n\t\t\treturn;\n\t\t}\n\n\t\tlet loadCount = 0;\n\t\tconst callback = function() {\n\t\t\tif (defaultFn && ++loadCount === styles.length) {\n\t\t\t\tasync.nextTick(defaultFn);\n\t\t\t}\n\t\t};\n\t\tfor (let i = 0; i < styles.length; i++) {\n\t\t\tglobalEvalStyles.runStyle(styles[i], callback, appendFn);\n\t\t}\n\t}\n}\n\nexport default globalEvalStyles;\n","'use strict';\n\nimport {isServerSide} from 'metal';\nimport {registerCustomEvent, contains} from './dom';\nimport features from './features';\n\n/**\n * Register custom events for event delegation.\n */\nfunction registerEvents() {\n\tconst mouseEventMap = {\n\t\tmouseenter: 'mouseover',\n\t\tmouseleave: 'mouseout',\n\t\tpointerenter: 'pointerover',\n\t\tpointerleave: 'pointerout',\n\t};\n\tObject.keys(mouseEventMap).forEach(function(eventName) {\n\t\tregisterCustomEvent(eventName, {\n\t\t\tdelegate: true,\n\t\t\thandler: function(callback, event) {\n\t\t\t\tconst related = event.relatedTarget;\n\t\t\t\tconst target = event.delegateTarget;\n\t\t\t\t// eslint-disable-next-line\n\t\t\t\tif (\n\t\t\t\t\t!related ||\n\t\t\t\t\t(related !== target && !contains(target, related))\n\t\t\t\t) {\n\t\t\t\t\tevent.customType = eventName;\n\t\t\t\t\treturn callback(event);\n\t\t\t\t}\n\t\t\t},\n\t\t\toriginalEvent: mouseEventMap[eventName],\n\t\t});\n\t});\n\n\tconst animationEventMap = {\n\t\tanimation: 'animationend',\n\t\ttransition: 'transitionend',\n\t};\n\tObject.keys(animationEventMap).forEach(function(eventType) {\n\t\tconst eventName = animationEventMap[eventType];\n\t\tregisterCustomEvent(eventName, {\n\t\t\tevent: true,\n\t\t\tdelegate: true,\n\t\t\thandler: function(callback, event) {\n\t\t\t\tevent.customType = eventName;\n\t\t\t\treturn callback(event);\n\t\t\t},\n\t\t\toriginalEvent: features.checkAnimationEventName()[eventType],\n\t\t});\n\t});\n}\n\nif (!isServerSide()) {\n\tregisterEvents();\n}\n","var globals = globals || {};\n\nif (typeof window !== 'undefined') {\n\tglobals.window = window;\n}\n\nif (typeof document !== 'undefined') {\n\tglobals.document = document;\n}\n\nexport default globals;\n","'use strict';\n\n/**\n * A collection of core utility functions.\n * @const\n */\n\nlet compatibilityModeData_;\n\n/**\n * Counter for unique id.\n * @type {Number}\n * @private\n */\nlet uniqueIdCounter_ = 1;\n\n/**\n * Unique id property prefix.\n * @type {String}\n * @protected\n */\nexport const UID_PROPERTY = `core_${(Math.random() * 1e9) >>> 0}`;\n\n/**\n * When defining a class Foo with an abstract method bar(), you can do:\n * Foo.prototype.bar = abstractMethod\n *\n * Now if a subclass of Foo fails to override bar(), an error will be thrown\n * when bar() is invoked.\n *\n * @type {!Function}\n * @throws {Error} when invoked to indicate the method should be overridden.\n */\nexport function abstractMethod() {\n\tthrow Error('Unimplemented abstract method');\n}\n\n/**\n * Disables Metal.js's compatibility mode.\n */\nexport function disableCompatibilityMode() {\n\tcompatibilityModeData_ = undefined;\n}\n\n/**\n * Enables Metal.js's compatibility mode with the following features from rc\n * and 1.x versions:\n * - Using \"key\" to reference component instances. In the current version\n * this should be done via \"ref\" instead. This allows old code still\n * using \"key\" to keep working like before. NOTE: this may cause\n * problems, since \"key\" is meant to be used differently. Only use this\n * if it's not possible to upgrade the code to use \"ref\" instead.\n * @param {Object=} data Optional object with data to specify more\n * details, such as:\n * - renderers {Array} the template renderers that should be in\n * compatibility mode, either their constructors or strings\n * representing them (e.g. 'soy' or 'jsx'). By default, all the ones\n * that extend from IncrementalDomRenderer.\n * @type {Object}\n */\nexport function enableCompatibilityMode(data = {}) {\n\tcompatibilityModeData_ = data;\n}\n\n/**\n * Returns the data used for compatibility mode, or nothing if it hasn't been\n * enabled.\n * @return {Object}\n */\nexport function getCompatibilityModeData() {\n\t// Compatibility mode can be set via the __METAL_COMPATIBILITY__ global var.\n\tif (compatibilityModeData_ === undefined) {\n\t\tif (typeof window !== 'undefined' && window.__METAL_COMPATIBILITY__) {\n\t\t\tenableCompatibilityMode(window.__METAL_COMPATIBILITY__);\n\t\t}\n\t}\n\treturn compatibilityModeData_;\n}\n\n/**\n * Returns the first argument if it's truthy, or the second otherwise.\n * @param {*} a\n * @param {*} b\n * @return {*}\n * @protected\n */\nfunction getFirstTruthy_(a, b) {\n\treturn a || b;\n}\n\n/**\n * Gets the name of the given function. If the current browser doesn't\n * support the `name` property, this will calculate it from the function's\n * content string.\n * @param {!function()} fn\n * @return {string}\n */\nexport function getFunctionName(fn) {\n\tif (!fn.name) {\n\t\tconst str = fn.toString();\n\t\tfn.name = str.substring(9, str.indexOf('('));\n\t}\n\treturn fn.name;\n}\n\n/**\n * Gets the value of a static property in the given class. The value will be\n * inherited from ancestors as expected, unless a custom merge function is given,\n * which can change how the super classes' value for that property will be merged\n * together.\n * The final merged value will be stored in another property, so that it won't\n * be recalculated even if this function is called multiple times.\n * @param {!function()} ctor Class constructor.\n * @param {string} propertyName Property name to be merged.\n * @param {function(*, *):*=} mergeFn Function that receives the merged\n * value of the property so far and the next value to be merged to it.\n * Should return these two merged together. If not passed the final property\n * will be the first truthy value among ancestors.\n * @return {Object}\n */\nexport function getStaticProperty(\n\tctor,\n\tpropertyName,\n\tmergeFn = getFirstTruthy_\n) {\n\tconst mergedName = propertyName + '_MERGED';\n\tif (!ctor.hasOwnProperty(mergedName)) {\n\t\t// eslint-disable-next-line\n\t\tlet merged = ctor.hasOwnProperty(propertyName)\n\t\t\t? ctor[propertyName]\n\t\t\t: null;\n\t\tif (ctor.__proto__ && !ctor.__proto__.isPrototypeOf(Function)) {\n\t\t\tmerged = mergeFn(\n\t\t\t\tmerged,\n\t\t\t\tgetStaticProperty(ctor.__proto__, propertyName, mergeFn)\n\t\t\t);\n\t\t}\n\t\tctor[mergedName] = merged;\n\t}\n\treturn ctor[mergedName];\n}\n\n/**\n * Gets an unique id. If `object` argument is passed, the object is\n * mutated with an unique id. Consecutive calls with the same object\n * reference won't mutate the object again, instead the current object uid\n * returns. See {@link UID_PROPERTY}.\n * @param {Object=} object Optional object to be mutated with the uid. If\n * not specified this method only returns the uid.\n * @param {boolean=} noInheritance Optional flag indicating if this\n * object's uid property can be inherited from parents or not.\n * @throws {Error} when invoked to indicate the method should be overridden.\n * @return {number}\n */\nexport function getUid(object, noInheritance) {\n\tif (object) {\n\t\tlet id = object[UID_PROPERTY];\n\t\tif (noInheritance && !object.hasOwnProperty(UID_PROPERTY)) {\n\t\t\tid = null;\n\t\t}\n\t\treturn id || (object[UID_PROPERTY] = uniqueIdCounter_++);\n\t}\n\treturn uniqueIdCounter_++;\n}\n\n/**\n * The identity function. Returns its first argument.\n * @param {*=} returnValue The single value that will be returned.\n * @return {?} The first argument.\n */\nexport function identityFunction(returnValue) {\n\treturn returnValue;\n}\n\n/**\n * Returns true if the specified value is a boolean.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is boolean.\n */\nexport function isBoolean(val) {\n\treturn typeof val === 'boolean';\n}\n\n/**\n * Returns true if the specified value is not undefined.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is defined.\n */\nexport function isDef(val) {\n\treturn val !== undefined;\n}\n\n/**\n * Returns true if value is not undefined or null.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDefAndNotNull(val) {\n\treturn isDef(val) && !isNull(val);\n}\n\n/**\n * Returns true if value is a document.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDocument(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 9;\n}\n\n/**\n * Returns true if value is a document-fragment.\n * @param {*} val\n * @return {boolean}\n */\nexport function isDocumentFragment(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 11;\n}\n\n/**\n * Returns true if value is a dom element.\n * @param {*} val\n * @return {boolean}\n */\nexport function isElement(val) {\n\treturn val && typeof val === 'object' && val.nodeType === 1;\n}\n\n/**\n * Returns true if the specified value is a function.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is a function.\n */\nexport function isFunction(val) {\n\treturn typeof val === 'function';\n}\n\n/**\n * Returns true if value is null.\n * @param {*} val\n * @return {boolean}\n */\nexport function isNull(val) {\n\treturn val === null;\n}\n\n/**\n * Returns true if the specified value is a number.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is a number.\n */\nexport function isNumber(val) {\n\treturn typeof val === 'number';\n}\n\n/**\n * Returns true if value is a window.\n * @param {*} val\n * @return {boolean}\n */\nexport function isWindow(val) {\n\treturn val !== null && val === val.window;\n}\n\n/**\n * Returns true if the specified value is an object. This includes arrays\n * and functions.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is an object.\n */\nexport function isObject(val) {\n\tconst type = typeof val;\n\treturn (type === 'object' && val !== null) || type === 'function';\n}\n\n/**\n * Returns true if value is a Promise.\n * @param {*} val\n * @return {boolean}\n */\nexport function isPromise(val) {\n\treturn val && typeof val === 'object' && typeof val.then === 'function';\n}\n\n/**\n * Returns true if value is a string.\n * @param {*} val\n * @return {boolean}\n */\nexport function isString(val) {\n\treturn typeof val === 'string' || val instanceof String;\n}\n\n/**\n * Sets to true if running inside Node.js environment with extra check for\n * `process.browser` to skip Karma runner environment. Karma environment has\n * `process` defined even though it runs on the browser.\n * @param {?Object} options Contains `checkEnv` property which if true, checks\n * the NODE_ENV variable. If NODE_ENV equals 'test', the function returns false.\n * @return {boolean}\n */\nexport function isServerSide(options = {checkEnv: true}) {\n\tlet serverSide = typeof process !== 'undefined' && !process.browser;\n\tif (serverSide && options.checkEnv) {\n\t\tserverSide =\n\t\t\ttypeof process.env !== 'undefined' &&\n\t\t\tprocess.env.NODE_ENV !== 'test';\n\t}\n\treturn serverSide;\n}\n\n/**\n * Null function used for default values of callbacks, etc.\n * @return {void} Nothing.\n */\nexport function nullFunction() {}\n","'use strict';\n\n// This file exists just for backwards compatibility, making sure that old\n// default imports for this file still work. It's best to use the named exports\n// for each function instead though, since that allows bundlers like Rollup to\n// reduce the bundle size by removing unused code.\nimport * as core from './coreNamed';\n\nexport default core;\nexport {core};\nexport * from './coreNamed';\n","'use strict';\n\n/**\n * Set of utilities for array operations\n */\nclass array {\n\t/**\n\t * Checks if the given arrays have the same content.\n\t * @param {!Array<*>} arr1\n\t * @param {!Array<*>} arr2\n\t * @return {boolean}\n\t */\n\tstatic equal(arr1, arr2) {\n\t\tif (arr1 === arr2) {\n\t\t\treturn true;\n\t\t}\n\t\tif (arr1.length !== arr2.length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0; i < arr1.length; i++) {\n\t\t\tif (arr1[i] !== arr2[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns the first value in the given array that isn't undefined.\n\t * @param {!Array} arr\n\t * @return {*}\n\t */\n\tstatic firstDefinedValue(arr) {\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tif (arr[i] !== undefined) {\n\t\t\t\treturn arr[i];\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Transforms the input nested array to become flat.\n\t * @param {Array.<*|Array.<*>>} arr Nested array to flatten.\n\t * @param {Array.<*>=} output Optional output array.\n\t * @return {Array.<*>} Flat array.\n\t */\n\tstatic flatten(arr, output = []) {\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tif (Array.isArray(arr[i])) {\n\t\t\t\tarray.flatten(arr[i], output);\n\t\t\t} else {\n\t\t\t\toutput.push(arr[i]);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Removes the first occurrence of a particular value from an array.\n\t * @param {Array.<T>} arr Array from which to remove value.\n\t * @param {T} obj Object to remove.\n\t * @return {boolean} True if an element was removed.\n\t * @template T\n\t */\n\tstatic remove(arr, obj) {\n\t\tconst i = arr.indexOf(obj);\n\t\tlet rv;\n\t\tif ((rv = i >= 0)) {\n\t\t\tarray.removeAt(arr, i);\n\t\t}\n\t\treturn rv;\n\t}\n\n\t/**\n\t * Removes from an array the element at index i\n\t * @param {Array} arr Array or array like object from which to remove value.\n\t * @param {number} i The index to remove.\n\t * @return {boolean} True if an element was removed.\n\t */\n\tstatic removeAt(arr, i) {\n\t\treturn Array.prototype.splice.call(arr, i, 1).length === 1;\n\t}\n\n\t/**\n\t * Slices the given array, just like Array.prototype.slice, but this\n\t * is faster and working on all array-like objects (like arguments).\n\t * @param {!Object} arr Array-like object to slice.\n\t * @param {number} start The index that should start the slice.\n\t * @param {number=} end The index where the slice should end, not\n\t * included in the final array. If not given, all elements after the\n\t * start index will be included.\n\t * @return {!Array}\n\t */\n\tstatic slice(arr, start, end = arr.length) {\n\t\tconst sliced = [];\n\t\tfor (let i = start; i < end; i++) {\n\t\t\tsliced.push(arr[i]);\n\t\t}\n\t\treturn sliced;\n\t}\n}\n\nexport default array;\n","/* !\n * Polyfill from Google's Closure Library.\n * Copyright 2013 The Closure Library Authors. All Rights Reserved.\n */\n\n'use strict';\n\nimport {isServerSide} from '../coreNamed';\n\nconst async = {};\n\n/**\n * Throw an item without interrupting the current execution context. For\n * example, if processing a group of items in a loop, sometimes it is useful\n * to report an error while still allowing the rest of the batch to be\n * processed.\n * @param {*} exception\n */\nasync.throwException = function(exception) {\n\t// Each throw needs to be in its own context.\n\tasync.nextTick(function() {\n\t\tthrow exception;\n\t});\n};\n\n/**\n * Fires the provided callback just before the current callstack unwinds, or as\n * soon as possible after the current JS execution context.\n * @param {function(this:THIS)} callback\n * @param {THIS=} context Object to use as the \"this value\" when calling\n * the provided function.\n * @template THIS\n */\nasync.run = function(callback, context) {\n\tif (!async.run.workQueueScheduled_) {\n\t\t// Nothing is currently scheduled, schedule it now.\n\t\tasync.nextTick(async.run.processWorkQueue);\n\t\tasync.run.workQueueScheduled_ = true;\n\t}\n\n\tasync.run.workQueue_.push(new async.run.WorkItem_(callback, context));\n};\n\n/** @private {boolean} */\nasync.run.workQueueScheduled_ = false;\n\n/** @private {!Array.<!async.run.WorkItem_>} */\nasync.run.workQueue_ = [];\n\n/**\n * Run any pending async.run work items. This function is not intended\n * for general use, but for use by entry point handlers to run items ahead of\n * async.nextTick.\n */\nasync.run.processWorkQueue = function() {\n\t// NOTE: additional work queue items may be pushed while processing.\n\twhile (async.run.workQueue_.length) {\n\t\t// Don't let the work queue grow indefinitely.\n\t\tconst workItems = async.run.workQueue_;\n\t\tasync.run.workQueue_ = [];\n\t\tfor (let i = 0; i < workItems.length; i++) {\n\t\t\tconst workItem = workItems[i];\n\t\t\ttry {\n\t\t\t\tworkItem.fn.call(workItem.scope);\n\t\t\t} catch (e) {\n\t\t\t\tasync.throwException(e);\n\t\t\t}\n\t\t}\n\t}\n\n\t// There are no more work items, reset the work queue.\n\tasync.run.workQueueScheduled_ = false;\n};\n\n/**\n * @constructor\n * @final\n * @struct\n * @private\n *\n * @param {function()} fn\n * @param {Object|null|undefined} scope\n */\nasync.run.WorkItem_ = function(fn, scope) {\n\t/** @const */\n\tthis.fn = fn;\n\t/** @const */\n\tthis.scope = scope;\n};\n\n/**\n * Fires the provided callbacks as soon as possible after the current JS\n * execution context. setTimeout(…, 0) always takes at least 5ms for legacy\n * reasons.\n * @param {function(this:SCOPE)} callback Callback function to fire as soon as\n * possible.\n * @param {SCOPE=} context Object in whose scope to call the listener.\n * @template SCOPE\n */\nasync.nextTick = function(callback, context) {\n\tlet cb = callback;\n\tif (context) {\n\t\tcb = callback.bind(context);\n\t}\n\tcb = async.nextTick.wrapCallback_(cb);\n\t// Look for and cache the custom fallback version of setImmediate.\n\tif (!async.nextTick.setImmediate_) {\n\t\tif (\n\t\t\ttypeof setImmediate === 'function' &&\n\t\t\tisServerSide({checkEnv: false})\n\t\t) {\n\t\t\tasync.nextTick.setImmediate_ = setImmediate;\n\t\t} else {\n\t\t\t// eslint-disable-next-line\n\t\t\tasync.nextTick.setImmediate_ = async.nextTick.getSetImmediateEmulator_();\n\t\t}\n\t}\n\tasync.nextTick.setImmediate_(cb);\n};\n\n/**\n * Cache for the setImmediate implementation.\n * @type {function(function())}\n * @private\n */\nasync.nextTick.setImmediate_ = null;\n\n/**\n * Determines the best possible implementation to run a function as soon as\n * the JS event loop is idle.\n * @return {function(function())} The \"setImmediate\" implementation.\n * @private\n */\nasync.nextTick.getSetImmediateEmulator_ = function() {\n\t// Create a private message channel and use it to postMessage empty messages\n\t// to ourselves.\n\tlet Channel;\n\n\t// Verify if variable is defined on the current runtime (i.e., node, browser).\n\t// Can't use typeof enclosed in a function (such as core.isFunction) or an\n\t// exception will be thrown when the function is called on an environment\n\t// where the variable is undefined.\n\tif (typeof MessageChannel === 'function') {\n\t\tChannel = MessageChannel;\n\t}\n\n\t// If MessageChannel is not available and we are in a browser, implement\n\t// an iframe based polyfill in browsers that have postMessage and\n\t// document.addEventListener. The latter excludes IE8 because it has a\n\t// synchronous postMessage implementation.\n\tif (\n\t\ttypeof Channel === 'undefined' &&\n\t\ttypeof window !== 'undefined' &&\n\t\twindow.postMessage &&\n\t\twindow.addEventListener\n\t) {\n\t\t/** @constructor */\n\t\tChannel = function() {\n\t\t\t// Make an empty, invisible iframe.\n\t\t\tconst iframe = document.createElement('iframe');\n\t\t\tiframe.style.display = 'none';\n\t\t\tiframe.src = '';\n\t\t\tiframe.title = '';\n\t\t\tdocument.documentElement.appendChild(iframe);\n\t\t\tconst win = iframe.contentWindow;\n\t\t\tconst doc = win.document;\n\t\t\tdoc.open();\n\t\t\tdoc.write('');\n\t\t\tdoc.close();\n\t\t\tconst message = 'callImmediate' + Math.random();\n\t\t\tconst origin = win.location.protocol + '//' + win.location.host;\n\t\t\tconst onmessage = function(e) {\n\t\t\t\t// Validate origin and message to make sure that this message was\n\t\t\t\t// intended for us.\n\t\t\t\tif (e.origin !== origin && e.data !== message) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.port1.onmessage();\n\t\t\t}.bind(this);\n\t\t\twin.addEventListener('message', onmessage, false);\n\t\t\tthis.port1 = {};\n\t\t\tthis.port2 = {\n\t\t\t\tpostMessage: function() {\n\t\t\t\t\twin.postMessage(message, origin);\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\t}\n\tif (typeof Channel !== 'undefined') {\n\t\tconst channel = new Channel();\n\t\t// Use a fifo linked list to call callbacks in the right order.\n\t\tlet head = {};\n\t\tlet tail = head;\n\t\tchannel.port1.onmessage = function() {\n\t\t\thead = head.next;\n\t\t\tconst cb = head.cb;\n\t\t\thead.cb = null;\n\t\t\tcb();\n\t\t};\n\t\treturn function(cb) {\n\t\t\ttail.next = {\n\t\t\t\tcb: cb,\n\t\t\t};\n\t\t\ttail = tail.next;\n\t\t\tchannel.port2.postMessage(0);\n\t\t};\n\t}\n\t// Implementation for IE6-8: Script elements fire an asynchronous\n\t// onreadystatechange event when inserted into the DOM.\n\tif (\n\t\ttypeof document !== 'undefined' &&\n\t\t'onreadystatechange' in document.createElement('script')\n\t) {\n\t\treturn function(cb) {\n\t\t\tlet script = document.createElement('script');\n\t\t\tscript.onreadystatechange = function() {\n\t\t\t\t// Clean up and call the callback.\n\t\t\t\tscript.onreadystatechange = null;\n\t\t\t\tscript.parentNode.removeChild(script);\n\t\t\t\tscript = null;\n\t\t\t\tcb();\n\t\t\t\tcb = null;\n\t\t\t};\n\t\t\tdocument.documentElement.appendChild(script);\n\t\t};\n\t}\n\t// Fall back to setTimeout with 0. In browsers this creates a delay of 5ms\n\t// or more.\n\treturn function(cb) {\n\t\tsetTimeout(cb, 0);\n\t};\n};\n\n/**\n * Helper function that is overrided to protect callbacks with entry point\n * monitor if the application monitors entry points.\n * @param {function()} callback Callback function to fire as soon as possible.\n * @return {function()} The wrapped callback.\n * @private\n */\nasync.nextTick.wrapCallback_ = function(callback) {\n\treturn callback;\n};\n\nexport default async;\n","'use strict';\n\n/**\n * Disposable utility. When inherited provides the `dispose` function to its\n * subclass, which is responsible for disposing of any object references\n * when an instance won't be used anymore. Subclasses should override\n * `disposeInternal` to implement any specific disposing logic.\n * @constructor\n */\nclass Disposable {\n\t/**\n\t * Disposable constructor\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Flag indicating if this instance has already been disposed.\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.disposed_ = false;\n\t}\n\n\t/**\n\t * Disposes of this instance's object references. Calls `disposeInternal`.\n\t */\n\tdispose() {\n\t\tif (!this.disposed_) {\n\t\t\tthis.disposeInternal();\n\t\t\tthis.disposed_ = true;\n\t\t}\n\t}\n\n\t/**\n\t * Subclasses should override this method to implement any specific\n\t * disposing logic (like clearing references and calling `dispose` on other\n\t * disposables).\n\t */\n\tdisposeInternal() {}\n\n\t/**\n\t * Checks if this instance has already been disposed.\n\t * @return {boolean}\n\t */\n\tisDisposed() {\n\t\treturn this.disposed_;\n\t}\n}\n\nexport default Disposable;\n","'use strict';\n\n/**\n * Set of utilities for object operations\n */\nclass object {\n\t/**\n\t * Copies all the members of a source object to a target object.\n\t * @param {Object} target Target object.\n\t * @param {...Object} var_args The objects from which values will be copied.\n\t * @return {Object} Returns the target object reference.\n\t */\n\tstatic mixin(target, ...args) {\n\t\tlet key;\n\t\tlet source;\n\t\tfor (let i = 0; i < args.length; i++) {\n\t\t\tsource = args[i];\n\t\t\t// Possible prototype chain leak, breaks 1 metal-dom and\n\t\t\t// 1 metal-incremental-dom test if guard-for-in rule is addressed\n\t\t\t// eslint-disable-next-line\n\t\t\tfor (key in source) {\n\t\t\t\ttarget[key] = source[key];\n\t\t\t}\n\t\t}\n\t\treturn target;\n\t}\n\n\t/**\n\t * Returns an object based on its fully qualified external name.\n\t * @param {string} name The fully qualified name.\n\t * @param {object=} scope The object within which to look; default is\n\t * <code>window</code>.\n\t * @return {?} The value (object or primitive) or, if not found, undefined.\n\t */\n\tstatic getObjectByName(name, scope = window) {\n\t\tconst parts = name.split('.');\n\t\treturn parts.reduce((part, key) => part[key], scope);\n\t}\n\n\t/**\n\t * Returns a new object with the same keys as the given one, but with\n\t * their values set to the return values of the specified function.\n\t * @param {!Object} obj\n\t * @param {!function(string, *)} fn\n\t * @return {!Object}\n\t */\n\tstatic map(obj, fn) {\n\t\tconst mappedObj = {};\n\t\tconst keys = Object.keys(obj);\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tmappedObj[keys[i]] = fn(keys[i], obj[keys[i]]);\n\t\t}\n\t\treturn mappedObj;\n\t}\n\n\t/**\n\t * Checks if the two given objects are equal. This is done via a shallow\n\t * check, including only the keys directly contained by the 2 objects.\n\t * @param {Object} obj1\n\t * @param {Object} obj2\n\t * @return {boolean}\n\t */\n\tstatic shallowEqual(obj1, obj2) {\n\t\tif (obj1 === obj2) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst keys1 = Object.keys(obj1);\n\t\tconst keys2 = Object.keys(obj2);\n\t\tif (keys1.length !== keys2.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < keys1.length; i++) {\n\t\t\tif (obj1[keys1[i]] !== obj2[keys1[i]]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\n\nexport default object;\n","'use strict';\n\n/**\n * Set of utilities for string operations\n */\nclass string {\n\t/**\n\t * Compares the given strings without taking the case into account.\n\t * @param {string|number} str1\n\t * @param {string|number} str2\n\t * @return {number} Either -1, 0 or 1, according to if the first string is\n\t * \"smaller\", equal or \"bigger\" than the second given string.\n\t */\n\tstatic caseInsensitiveCompare(str1, str2) {\n\t\tconst test1 = String(str1).toLowerCase();\n\t\tconst test2 = String(str2).toLowerCase();\n\n\t\tif (test1 < test2) {\n\t\t\treturn -1;\n\t\t} else if (test1 === test2) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\t/**\n\t * Removes the breaking spaces from the left and right of the string and\n\t * collapses the sequences of breaking spaces in the middle into single spaces.\n\t * The original and the result strings render the same way in HTML.\n\t * @param {string} str A string in which to collapse spaces.\n\t * @return {string} Copy of the string with normalized breaking spaces.\n\t */\n\tstatic collapseBreakingSpaces(str) {\n\t\treturn str\n\t\t\t.replace(/[\\t\\r\\n ]+/g, ' ')\n\t\t\t.replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g, '');\n\t}\n\n\t/**\n\t * Escapes characters in the string that are not safe to use in a RegExp.\n\t * @param {*} str The string to escape. If not a string, it will be casted\n\t * to one.\n\t * @return {string} A RegExp safe, escaped copy of {@code s}.\n\t */\n\tstatic escapeRegex(str) {\n\t\treturn String(str)\n\t\t\t.replace(/([-()[\\]{}+?*.$^|,:#<!\\\\])/g, '\\\\$1')\n\t\t\t.replace(/\\x08/g, '\\\\x08'); // eslint-disable-line\n\t}\n\n\t/**\n\t * Returns a string with at least 64-bits of randomness.\n\t * @return {string} A random string, e.g. sn1s7vb4gcic.\n\t */\n\tstatic getRandomString() {\n\t\tconst x = 2147483648;\n\t\treturn (\n\t\t\tMath.floor(Math.random() * x).toString(36) +\n\t\t\tMath.abs(Math.floor(Math.random() * x) ^ Date.now()).toString(36)\n\t\t);\n\t}\n\n\t/**\n\t * Calculates the hashcode for a string. The hashcode value is computed by\n\t * the sum algorithm: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]. A nice\n\t * property of using 31 prime is that the multiplication can be replaced by\n\t * a shift and a subtraction for better performance: 31*i == (i<<5)-i.\n\t * Modern VMs do this sort of optimization automatically.\n\t * @param {String} val Target string.\n\t * @return {Number} Returns the string hashcode.\n\t */\n\tstatic hashCode(val) {\n\t\tlet hash = 0;\n\t\tfor (let i = 0, len = val.length; i < len; i++) {\n\t\t\thash = 31 * hash + val.charCodeAt(i);\n\t\t\thash %= 0x100000000;\n\t\t}\n\t\treturn hash;\n\t}\n\n\t/**\n\t * Replaces interval into the string with specified value, e.g.\n\t * `replaceInterval(\"abcde\", 1, 4, \"\")` returns \"ae\".\n\t * @param {string} str The input string.\n\t * @param {Number} start Start interval position to be replaced.\n\t * @param {Number} end End interval position to be replaced.\n\t * @param {string} value The value that replaces the specified interval.\n\t * @return {string}\n\t */\n\tstatic replaceInterval(str, start, end, value) {\n\t\treturn str.substring(0, start) + value + str.substring(end);\n\t}\n}\n\nexport default string;\n","'use strict';\n\n/**\n * Parses the given uri string into an object.\n * @param {*=} opt_uri Optional string URI to parse\n */\nfunction parseFromAnchor(opt_uri) {\n\tvar link = document.createElement('a');\n\tlink.href = opt_uri;\n\n\tif(link.protocol === ':' || !/:/.test(link.href)) {\n\t\tthrow new TypeError(`${opt_uri} is not a valid URL`);\n\t}\n\n\treturn {\n\t\thash: link.hash,\n\t\thostname: link.hostname,\n\t\tpassword: link.password,\n\t\tpathname: link.pathname[0] === '/' ? link.pathname : '/' + link.pathname,\n\t\tport: link.port,\n\t\tprotocol: link.protocol,\n\t\tsearch: link.search,\n\t\tusername: link.username\n\t};\n}\n\nexport default parseFromAnchor;\n","'use strict';\n\nimport { isFunction } from 'metal';\nimport parseFromAnchor from './parseFromAnchor';\n\n/**\n * Parses the given uri string into an object. The URL function will be used\n * when present, otherwise we'll fall back to the anchor node element.\n * @param {*=} opt_uri Optional string URI to parse\n */\nfunction parse(opt_uri) {\n\tif (isFunction(URL) && URL.length) {\n\t\tconst url = new URL(opt_uri);\n\n\t\t// Safari Browsers will cap port to the max 16-bit unsigned integer (65535) instead\n\t\t// of throwing a TypeError as per spec. It will still keep the port number in the\n\t\t// href attribute, so we can use this mismatch to raise the expected exception.\n\t\tif (url.port && url.href.indexOf(url.port) === -1) {\n\t\t\tthrow new TypeError(`${opt_uri} is not a valid URL`);\n\t\t}\n\n\t\treturn url;\n\t} else {\n\t\treturn parseFromAnchor(opt_uri);\n\t}\n}\n\nexport default parse;\n","'use strict';\n\nimport { Disposable } from 'metal';\n\n/**\n * A cached reference to the create function.\n */\nvar create = Object.create;\n\n/**\n * Case insensitive string Multimap implementation. Allows multiple values for\n * the same key name.\n * @extends {Disposable}\n */\nclass MultiMap extends Disposable {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.keys = create(null);\n\t\tthis.values = create(null);\n\t}\n\n\t/**\n\t * Adds value to a key name.\n\t * @param {string} name\n\t * @param {*} value\n\t * @chainable\n\t */\n\tadd(name, value) {\n\t\tthis.keys[name.toLowerCase()] = name;\n\t\tthis.values[name.toLowerCase()] = this.values[name.toLowerCase()] || [];\n\t\tthis.values[name.toLowerCase()].push(value);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Clears map names and values.\n\t * @chainable\n\t */\n\tclear() {\n\t\tthis.keys = create(null);\n\t\tthis.values = create(null);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Checks if map contains a value to the key name.\n\t * @param {string} name\n\t * @return {boolean}\n\t * @chainable\n\t */\n\tcontains(name) {\n\t\treturn name.toLowerCase() in this.values;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisposeInternal() {\n\t\tthis.values = null;\n\t}\n\n\t/**\n\t * Creates a `MultiMap` instance from the given object.\n\t * @param {!Object} obj\n\t * @return {!MultiMap}\n\t */\n\tstatic fromObject(obj) {\n\t\tvar map = new MultiMap();\n\t\tvar keys = Object.keys(obj);\n\t\tfor (var i = 0; i < keys.length; i++) {\n\t\t\tmap.set(keys[i], obj[keys[i]]);\n\t\t}\n\t\treturn map;\n\t}\n\n\t/**\n\t * Gets the first added value from a key name.\n\t * @param {string} name\n\t * @return {*}\n\t * @chainable\n\t */\n\tget(name) {\n\t\tvar values = this.values[name.toLowerCase()];\n\t\tif (values) {\n\t\t\treturn values[0];\n\t\t}\n\t}\n\n\t/**\n\t * Gets all values from a key name.\n\t * @param {string} name\n\t * @return {Array.<*>}\n\t */\n\tgetAll(name) {\n\t\treturn this.values[name.toLowerCase()];\n\t}\n\n\t/**\n\t * Returns true if the map is empty, false otherwise.\n\t * @return {boolean}\n\t */\n\tisEmpty() {\n\t\treturn this.size() === 0;\n\t}\n\n\t/**\n\t * Gets array of key names.\n\t * @return {Array.<string>}\n\t */\n\tnames() {\n\t\treturn Object.keys(this.values).map((key) => this.keys[key]);\n\t}\n\n\t/**\n\t * Removes all values from a key name.\n\t * @param {string} name\n\t * @chainable\n\t */\n\tremove(name) {\n\t\tdelete this.keys[name.toLowerCase()];\n\t\tdelete this.values[name.toLowerCase()];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the value of a key name. Relevant to replace the current values with\n\t * a new one.\n\t * @param {string} name\n\t * @param {*} value\n\t * @chainable\n\t */\n\tset(name, value) {\n\t\tthis.keys[name.toLowerCase()] = name;\n\t\tthis.values[name.toLowerCase()] = [value];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets the size of the map key names.\n\t * @return {number}\n\t */\n\tsize() {\n\t\treturn this.names().length;\n\t}\n\n\t/**\n\t * Returns the parsed values as a string.\n\t * @return {string}\n\t */\n\ttoString() {\n\t\treturn JSON.stringify(this.values);\n\t}\n}\n\nexport default MultiMap;\n","'use strict';\n\nimport { array } from 'metal';\n\n/**\n * Generic tree node data structure with arbitrary number of child nodes.\n * @param {V} value Value.\n * @constructor\n */\nclass TreeNode {\n\n\tconstructor(value) {\n\t\t/**\n\t\t * The value.\n\t\t * @private {V}\n\t\t */\n\t\tthis.value_ = value;\n\n\t\t/**\n\t\t * Reference to the parent node or null if it has no parent.\n\t\t * @private {TreeNode}\n\t\t */\n\t\tthis.parent_ = null;\n\n\t\t/**\n\t\t * Child nodes or null in case of leaf node.\n\t\t * @private {Array<!TreeNode>}\n\t\t */\n\t\tthis.children_ = null;\n\t}\n\n\t/**\n\t * Appends a child node to this node.\n\t * @param {!TreeNode} child Orphan child node.\n\t */\n\taddChild(child) {\n\t\tassertChildHasNoParent(child);\n\t\tchild.setParent(this);\n\t\tthis.children_ = this.children_ || [];\n\t\tthis.children_.push(child);\n\t}\n\n\t/**\n\t * Tells whether this node is the ancestor of the given node.\n\t * @param {!TreeNode} node A node.\n\t * @return {boolean} Whether this node is the ancestor of {@code node}.\n\t */\n\tcontains(node) {\n\t\tlet current = node.getParent();\n\t\twhile (current) {\n\t\t\tif (current === this) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcurrent = current.getParent();\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * @return {!Array<TreeNode>} All ancestor nodes in bottom-up order.\n\t */\n\tgetAncestors() {\n\t\tlet ancestors = [];\n\t\tlet node = this.getParent();\n\t\twhile (node) {\n\t\t\tancestors.push(node);\n\t\t\tnode = node.getParent();\n\t\t}\n\t\treturn ancestors;\n\t}\n\n\t/**\n\t * Gets the child node of this node at the given index.\n\t * @param {number} index Child index.\n\t * @return {?TreeNode} The node at the given index\n\t * or null if not found.\n\t */\n\tgetChildAt(index) {\n\t\treturn this.getChildren()[index] || null;\n\t}\n\n\t/**\n\t * @return {?Array<!TreeNode>} Child nodes or null in case of leaf node.\n\t */\n\tgetChildren() {\n\t\treturn this.children_ || TreeNode.EMPTY_ARRAY;\n\t}\n\n\t/**\n\t * @return {number} The number of children.\n\t */\n\tgetChildCount() {\n\t\treturn this.getChildren().length;\n\t}\n\n\t/**\n\t * @return {number} The number of ancestors of the node.\n\t */\n\tgetDepth() {\n\t\tlet depth = 0;\n\t\tlet node = this;\n\t\twhile (node.getParent()) {\n\t\t\tdepth++;\n\t\t\tnode = node.getParent();\n\t\t}\n\t\treturn depth;\n\t}\n\n\t/**\n\t * @return {?TreeNode} Parent node or null if it has no parent.\n\t */\n\tgetParent() {\n\t\treturn this.parent_;\n\t}\n\n\t/**\n\t * @return {!TreeNode} The root of the tree structure, i.e. the farthest\n\t * ancestor of the node or the node itself if it has no parents.\n\t */\n\tgetRoot() {\n\t\tlet root = this;\n\t\twhile (root.getParent()) {\n\t\t\troot = root.getParent();\n\t\t}\n\t\treturn root;\n\t}\n\n\t/**\n\t * Gets the value.\n\t * @return {V} The value.\n\t */\n\tgetValue() {\n\t\treturn this.value_;\n\t}\n\n\t/**\n\t * @return {boolean} Whether the node is a leaf node.\n\t */\n\tisLeaf() {\n\t\treturn !this.getChildCount();\n\t}\n\n\t/**\n\t * Removes the given child node of this node.\n\t * @param {TreeNode} child The node to remove.\n\t * @return {TreeNode} The removed node if any, null otherwise.\n\t */\n\tremoveChild(child) {\n\t\tif (array.remove(this.getChildren(), child)) {\n\t\t\treturn child;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Sets the parent node of this node. The callers must ensure that the\n\t * parent node and only that has this node among its children.\n\t * @param {TreeNode} parent The parent to set. If null, the node will be\n\t * detached from the tree.\n\t * @protected\n\t */\n\tsetParent(parent) {\n\t\tthis.parent_ = parent;\n\t}\n\n\t/**\n\t * Traverses the subtree. The first callback starts with this node,\n\t * and visits the descendant nodes depth-first, in preorder.\n\t * The second callback, starts with deepest child then visits\n\t * the ancestor nodes depth-first, in postorder. E.g.\n\t *\n\t * \t A\n\t * / \\\n\t * B C\n\t * / / \\\n\t * D E F\n\t *\n\t * preorder -> ['A', 'B', 'D', 'C', 'E', 'F']\n\t * postorder -> ['D', 'B', 'E', 'F', 'C', 'A']\n\t *\n\t * @param {function=} opt_preorderFn The callback to execute when visiting a node.\n\t * @param {function=} opt_postorderFn The callback to execute before leaving a node.\n\t */\n\ttraverse(opt_preorderFn, opt_postorderFn) {\n\t\tif (opt_preorderFn) {\n\t\t\topt_preorderFn(this);\n\t\t}\n\t\tthis.getChildren().forEach((child) => child.traverse(opt_preorderFn, opt_postorderFn));\n\t\tif (opt_postorderFn) {\n\t\t\topt_postorderFn(this);\n\t\t}\n\t}\n\n}\n\n/**\n * Constant for empty array to avoid unnecessary allocations.\n * @private\n */\nTreeNode.EMPTY_ARRAY = [];\n\n/**\n * Asserts that child has no parent.\n * @param {TreeNode} child A child.\n * @private\n */\nconst assertChildHasNoParent = function(child) {\n\tif (child.getParent()) {\n\t\tthrow new Error('Cannot add child with parent.');\n\t}\n};\n\nexport default TreeNode;\n","'use strict';\n\nimport { isDef, string } from 'metal';\nimport parse from './parse';\nimport { MultiMap } from 'metal-structs';\n\nvar parseFn_ = parse;\n\nclass Uri {\n\n\t/**\n\t * This class contains setters and getters for the parts of the URI.\n\t * The following figure displays an example URIs and their component parts.\n\t *\n\t * path\n\t *\t ┌───┴────┐\n\t *\t abc://example.com:123/path/data?key=value#fragid1\n\t *\t └┬┘ └────┬────┘ └┬┘ └───┬───┘ └──┬──┘\n\t * protocol hostname port search hash\n\t * └──────┬───────┘\n\t * host\n\t *\n\t * @param {*=} opt_uri Optional string URI to parse\n\t * @constructor\n\t */\n\tconstructor(opt_uri = '') {\n\t\tthis.url = Uri.parse(this.maybeAddProtocolAndHostname_(opt_uri));\n\t}\n\n\t/**\n\t * Adds parameters to uri from a <code>MultiMap</code> as source.\n\t * @param {MultiMap} multimap The <code>MultiMap</code> containing the\n\t * parameters.\n\t * @protected\n\t * @chainable\n\t */\n\taddParametersFromMultiMap(multimap) {\n\t\tmultimap.names().forEach((name) => {\n\t\t\tmultimap.getAll(name).forEach((value) => {\n\t\t\t\tthis.addParameterValue(name, value);\n\t\t\t});\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds the value of the named query parameters.\n\t * @param {string} key The parameter to set.\n\t * @param {*} value The new value. Will be explicitly casted to String.\n\t * @chainable\n\t */\n\taddParameterValue(name, value) {\n\t\tthis.ensureQueryInitialized_();\n\t\tif (isDef(value)) {\n\t\t\tvalue = String(value);\n\t\t}\n\t\tthis.query.add(name, value);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds the values of the named query parameter.\n\t * @param {string} key The parameter to set.\n\t * @param {*} value The new value.\n\t * @chainable\n\t */\n\taddParameterValues(name, values) {\n\t\tvalues.forEach((value) => this.addParameterValue(name, value));\n\t\treturn this;\n\t}\n\n\t/**\n\t * Ensures query internal map is initialized and synced with initial value\n\t * extracted from URI search part.\n\t * @protected\n\t */\n\tensureQueryInitialized_() {\n\t\tif (this.query) {\n\t\t\treturn;\n\t\t}\n\t\tthis.query = new MultiMap();\n\t\tvar search = this.url.search;\n\t\tif (search) {\n\t\t\tsearch.substring(1).split('&').forEach((param) => {\n\t\t\t\tvar [key, value] = param.split('=');\n\t\t\t\tif (isDef(value)) {\n\t\t\t\t\tvalue = Uri.urlDecode(value);\n\t\t\t\t}\n\t\t\t\tthis.addParameterValue(key, value);\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Gets the hash part of uri.\n\t * @return {string}\n\t */\n\tgetHash() {\n\t\treturn this.url.hash || '';\n\t}\n\n\t/**\n\t * Gets the host part of uri. E.g. <code>[hostname]:[port]</code>.\n\t * @return {string}\n\t */\n\tgetHost() {\n\t\tvar host = this.getHostname();\n\t\tif (host) {\n\t\t\tvar port = this.getPort();\n\t\t\tif (port && port !== '80') {\n\t\t\t\thost += ':' + port;\n\t\t\t}\n\t\t}\n\t\treturn host;\n\t}\n\n\t/**\n\t * Gets the hostname part of uri without protocol and port.\n\t * @return {string}\n\t */\n\tgetHostname() {\n\t\tvar hostname = this.url.hostname;\n\t\tif (hostname === Uri.HOSTNAME_PLACEHOLDER) {\n\t\t\treturn '';\n\t\t}\n\t\treturn hostname;\n\t}\n\n\t/**\n\t * Gets the origin part of uri. E.g. <code>http://[hostname]:[port]</code>.\n\t * @return {string}\n\t */\n\tgetOrigin() {\n\t\tvar host = this.getHost();\n\t\tif (host) {\n\t\t\treturn this.getProtocol() + '//' + host;\n\t\t}\n\t\treturn '';\n\t}\n\n\t/**\n\t * Returns the first value for a given parameter or undefined if the given\n\t * parameter name does not appear in the query string.\n\t * @param {string} paramName Unescaped parameter name.\n\t * @return {string|undefined} The first value for a given parameter or\n\t * undefined if the given parameter name does not appear in the query\n\t * string.\n\t */\n\tgetParameterValue(name) {\n\t\tthis.ensureQueryInitialized_();\n\t\treturn this.query.get(name);\n\t}\n\n\t/**\n\t * Returns the value<b>s</b> for a given parameter as a list of decoded\n\t * query parameter values.\n\t * @param {string} name The parameter to get values for.\n\t * @return {!Array<?>} The values for a given parameter as a list of decoded\n\t * query parameter values.\n\t */\n\tgetParameterValues(name) {\n\t\tthis.ensureQueryInitialized_();\n\t\treturn this.query.getAll(name);\n\t}\n\n\t/**\n\t * Returns the name<b>s</b> of the parameters.\n\t * @return {!Array<string>} The names for the parameters as a list of\n\t * strings.\n\t */\n\tgetParameterNames() {\n\t\tthis.ensureQueryInitialized_();\n\t\treturn this.query.names();\n\t}\n\n\t/**\n\t * Gets the function currently being used to parse URIs.\n\t * @return {!function()}\n\t */\n\tstatic getParseFn() {\n\t\treturn parseFn_;\n\t}\n\n\t/**\n\t * Gets the pathname part of uri.\n\t * @return {string}\n\t */\n\tgetPathname() {\n\t\treturn this.url.pathname;\n\t}\n\n\t/**\n\t * Gets the port number part of uri as string.\n\t * @return {string}\n\t */\n\tgetPort() {\n\t\treturn this.url.port;\n\t}\n\n\t/**\n\t * Gets the protocol part of uri. E.g. <code>http:</code>.\n\t * @return {string}\n\t */\n\tgetProtocol() {\n\t\treturn this.url.protocol;\n\t}\n\n\t/**\n\t * Gets the search part of uri. Search value is retrieved from query\n\t * parameters.\n\t * @return {string}\n\t */\n\tgetSearch() {\n\t\tvar search = '';\n\t\tvar querystring = '';\n\t\tthis.getParameterNames().forEach((name) => {\n\t\t\tthis.getParameterValues(name).forEach((value) => {\n\t\t\t\tquerystring += name;\n\t\t\t\tif (isDef(value)) {\n\t\t\t\t\tquerystring += '=' + encodeURIComponent(value);\n\t\t\t\t}\n\t\t\t\tquerystring += '&';\n\t\t\t});\n\t\t});\n\t\tquerystring = querystring.slice(0, -1);\n\t\tif (querystring) {\n\t\t\tsearch += '?' + querystring;\n\t\t}\n\t\treturn search;\n\t}\n\n\t/**\n\t * Checks if uri contains the parameter.\n\t * @param {string} name\n\t * @return {boolean}\n\t */\n\thasParameter(name) {\n\t\tthis.ensureQueryInitialized_();\n\t\treturn this.query.contains(name);\n\t}\n\n\t/**\n\t * Makes this URL unique by adding a random param to it. Useful for avoiding\n\t * cache.\n\t */\n\tmakeUnique() {\n\t\tthis.setParameterValue(Uri.RANDOM_PARAM, string.getRandomString());\n\t\treturn this;\n\t}\n\n\t/**\n\t * Maybe adds protocol and a hostname placeholder on a parial URI if needed.\n\t * Relevent for compatibility with <code>URL</code> native object.\n\t * @param {string=} opt_uri\n\t * @return {string} URI with protocol and hostname placeholder.\n\t */\n\tmaybeAddProtocolAndHostname_(opt_uri) {\n\t\tvar url = opt_uri;\n\t\tif (opt_uri.indexOf('://') === -1 &&\n\t\t\topt_uri.indexOf('javascript:') !== 0) { // jshint ignore:line\n\n\t\t\turl = Uri.DEFAULT_PROTOCOL;\n\t\t\tif (opt_uri[0] !== '/' || opt_uri[1] !== '/') {\n\t\t\t\turl += '//';\n\t\t\t}\n\n\t\t\tswitch (opt_uri.charAt(0)) {\n\t\t\t\tcase '.':\n\t\t\t\tcase '?':\n\t\t\t\tcase '#':\n\t\t\t\t\turl += Uri.HOSTNAME_PLACEHOLDER;\n\t\t\t\t\turl += '/';\n\t\t\t\t\turl += opt_uri;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '':\n\t\t\t\tcase '/':\n\t\t\t\t\tif (opt_uri[1] !== '/') {\n\t\t\t\t\t\turl += Uri.HOSTNAME_PLACEHOLDER;\n\t\t\t\t\t}\n\t\t\t\t\turl += opt_uri;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\turl += opt_uri;\n\t\t\t}\n\t\t}\n\t\treturn url;\n\t}\n\n\t/**\n\t * Parses the given uri string into an object.\n\t * @param {*=} opt_uri Optional string URI to parse\n\t */\n\tstatic parse(opt_uri) {\n\t\treturn parseFn_(opt_uri);\n\t}\n\n\t/**\n\t * Removes the named query parameter.\n\t * @param {string} name The parameter to remove.\n\t * @chainable\n\t */\n\tremoveParameter(name) {\n\t\tthis.ensureQueryInitialized_();\n\t\tthis.query.remove(name);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes uniqueness parameter of the uri.\n\t * @chainable\n\t */\n\tremoveUnique() {\n\t\tthis.removeParameter(Uri.RANDOM_PARAM);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the hash.\n\t * @param {string} hash\n\t * @chainable\n\t */\n\tsetHash(hash) {\n\t\tthis.url.hash = hash;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the hostname.\n\t * @param {string} hostname\n\t * @chainable\n\t */\n\tsetHostname(hostname) {\n\t\tthis.url.hostname = hostname;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the value of the named query parameters, clearing previous values\n\t * for that key.\n\t * @param {string} key The parameter to set.\n\t * @param {*} value The new value.\n\t * @chainable\n\t */\n\tsetParameterValue(name, value) {\n\t\tthis.removeParameter(name);\n\t\tthis.addParameterValue(name, value);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the values of the named query parameters, clearing previous values\n\t * for that key.\n\t * @param {string} key The parameter to set.\n\t * @param {*} value The new value.\n\t * @chainable\n\t */\n\tsetParameterValues(name, values) {\n\t\tthis.removeParameter(name);\n\t\tvalues.forEach((value) => this.addParameterValue(name, value));\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the pathname.\n\t * @param {string} pathname\n\t * @chainable\n\t */\n\tsetPathname(pathname) {\n\t\tthis.url.pathname = pathname;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the port number.\n\t * @param {*} port Port number.\n\t * @chainable\n\t */\n\tsetPort(port) {\n\t\tthis.url.port = port;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the function that will be used for parsing the original string uri\n\t * into an object.\n\t * @param {!function()} parseFn\n\t */\n\tstatic setParseFn(parseFn) {\n\t\tparseFn_ = parseFn;\n\t}\n\n\t/**\n\t * Sets the protocol. If missing <code>http:</code> is used as default.\n\t * @param {string} protocol\n\t * @chainable\n\t */\n\tsetProtocol(protocol) {\n\t\tthis.url.protocol = protocol;\n\t\tif (this.url.protocol[this.url.protocol.length - 1] !== ':') {\n\t\t\tthis.url.protocol += ':';\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * @return {string} The string form of the url.\n\t * @override\n\t */\n\ttoString() {\n\t\tvar href = '';\n\t\tvar host = this.getHost();\n\t\tif (host) {\n\t\t\thref += this.getProtocol() + '//';\n\t\t}\n\t\thref += host + this.getPathname() + this.getSearch() + this.getHash();\n\t\treturn href;\n\t}\n\n\t/**\n\t * Joins the given paths.\n\t * @param {string} basePath\n\t * @param {...string} ...paths Any number of paths to be joined with the base url.\n\t * @static\n\t */\n\tstatic joinPaths(basePath, ...paths) {\n\t\tif (basePath.charAt(basePath.length - 1) === '/') {\n\t\t\tbasePath = basePath.substring(0, basePath.length - 1);\n\t\t}\n\t\tpaths = paths.map(path => path.charAt(0) === '/' ? path.substring(1) : path);\n\t\treturn [basePath].concat(paths).join('/').replace(/\\/$/, '');\n\t}\n\n\t/**\n\t * URL-decodes the string. We need to specially handle '+'s because\n\t * the javascript library doesn't convert them to spaces.\n\t * @param {string} str The string to url decode.\n\t * @return {string} The decoded {@code str}.\n\t */\n\tstatic urlDecode(str) {\n\t\treturn decodeURIComponent(str.replace(/\\+/g, ' '));\n\t}\n\n}\n\n/**\n * Default protocol value.\n * @type {string}\n * @default http:\n * @static\n */\nconst isSecure = () =>\n\t(typeof window !== 'undefined' &&\n\t\twindow.location &&\n\t\twindow.location.protocol &&\n\t\twindow.location.protocol.indexOf('https') === 0);\n\nUri.DEFAULT_PROTOCOL = isSecure() ? 'https:' : 'http:';\n\n/**\n * Hostname placeholder. Relevant to internal usage only.\n * @type {string}\n * @static\n */\nUri.HOSTNAME_PLACEHOLDER = 'hostname' + Date.now();\n\n/**\n * Name used by the param generated by `makeUnique`.\n * @type {string}\n * @static\n */\nUri.RANDOM_PARAM = 'zx';\n\nexport default Uri;\n","'use strict';\n\nimport { exitDocument } from 'metal-dom';\nimport globals from '../globals/globals';\nimport Uri from 'metal-uri';\n\n/**\n * A collection of static utility functions.\n * @const\n */\nclass utils {\n\n\t/**\n\t * Copies attributes form source node to target node.\n\t * @return {void}\n\t * @static\n\t */\n\tstatic copyNodeAttributes(source, target) {\n\t\tArray.prototype.slice.call(source.attributes).forEach((attribute) => target.setAttribute(attribute.name, attribute.value));\n\t}\n\n\t/**\n\t * Gets the current browser path including hashbang.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getCurrentBrowserPath() {\n\t\treturn this.getCurrentBrowserPathWithoutHash() + globals.window.location.hash;\n\t}\n\n\t/**\n\t * Gets the current browser path excluding hashbang.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getCurrentBrowserPathWithoutHash() {\n\t\treturn globals.window.location.pathname + globals.window.location.search;\n\t}\n\n\t/**\n\t * Gets the given node offset coordinates.\n\t * @return {!object}\n\t * @static\n\t */\n\tstatic getNodeOffset(node) {\n\t\tlet [offsetLeft, offsetTop] = [0, 0];\n\t\tdo {\n\t\t\toffsetLeft += node.offsetLeft;\n\t\t\toffsetTop += node.offsetTop;\n\t\t\tnode = node.offsetParent;\n\t\t} while (node);\n\t\treturn {\n\t\t\toffsetLeft,\n\t\t\toffsetTop\n\t\t};\n\t}\n\n\t/**\n\t * Extracts the path part of an url.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getUrlPath(url) {\n\t\tvar uri = new Uri(url);\n\t\treturn uri.getPathname() + uri.getSearch() + uri.getHash();\n\t}\n\n\t/**\n\t * Extracts the path part of an url without hashbang.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getUrlPathWithoutHash(url) {\n\t\tvar uri = new Uri(url);\n\t\treturn uri.getPathname() + uri.getSearch();\n\t}\n\n\t/**\n\t * Extracts the path part of an url without hashbang and query search.\n\t * @return {!string}\n\t * @static\n\t */\n\tstatic getUrlPathWithoutHashAndSearch(url) {\n\t\tvar uri = new Uri(url);\n\t\treturn uri.getPathname();\n\t}\n\n\t/**\n\t * Checks if url is in the same browser current url excluding the hashbang.\n\t * @param {!string} url\n\t * @return {boolean}\n\t * @static\n\t */\n\tstatic isCurrentBrowserPath(url) {\n\t\tif (url) {\n\t\t\tconst currentBrowserPath = this.getCurrentBrowserPathWithoutHash();\n\t\t\t// the getUrlPath will create a Uri and will normalize the path and\n\t\t\t// remove the trailling '/' for properly comparing paths.\n\t\t\treturn utils.getUrlPathWithoutHash(url) === this.getUrlPath(currentBrowserPath);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Returns true if HTML5 History api is supported.\n\t * @return {boolean}\n\t * @static\n\t */\n\tstatic isHtml5HistorySupported() {\n\t\treturn !!(globals.window.history && globals.window.history.pushState);\n\t}\n\n\t/**\n\t * Checks if a given url is a valid http(s) uri and returns the formed Uri\n\t * or false if the parsing failed\n\t * @return {Uri|boolean}\n\t * @static\n\t */\n\tstatic isWebUri(url) {\n\t\ttry {\n\t\t\treturn new Uri(url);\n\t\t} catch (err) {\n\t\t\tconsole.error(`${err.message} ${url}`);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Removes all attributes form node.\n\t * @return {void}\n\t * @static\n\t */\n\tstatic clearNodeAttributes(node) {\n\t\tArray.prototype.slice.call(node.attributes).forEach((attribute) => node.removeAttribute(attribute.name));\n\t}\n\n\t/**\n\t * Remove elements from the document.\n\t * @param {!Array<Element>} elements\n\t */\n\tstatic removeElementsFromDocument(elements) {\n\t\telements.forEach((element) => exitDocument(element));\n\t}\n\n\t/**\n\t* Removes trailing slash in path.\n\t* @param {!string}\n\t* @return {string}\n\t*/\n\tstatic removePathTrailingSlash(path) {\n\t\tvar length = path ? path.length : 0;\n\t\tif (length > 1 && path[length - 1] === '/') {\n\t\t\tpath = path.substr(0, length - 1);\n\t\t}\n\t\treturn path;\n\t}\n\n\t/**\n\t * Adds a random suffix to the href attribute of the element.\n\t * @param {!element} element\n\t * @return {element}\n\t */\n\tstatic setElementWithRandomHref(element) {\n\t\telement.href = element.href + '?q=' + Math.random();\n\t\treturn element;\n\t}\n\n\t/**\n\t * Overrides document referrer\n\t * @param {string} referrer\n\t * @static\n\t */\n\tstatic setReferrer(referrer) {\n\t\tObject.defineProperty(globals.document, 'referrer', {\n\t\t\tconfigurable: true,\n\t\t\tget: function() {\n\t\t\t\treturn referrer;\n\t\t\t}\n\t\t});\n\t}\n}\n\nexport default utils;\n","'use strict';\n\nexport default {\n\tbasePath: 'data-senna-base-path',\n\tlinkSelector: 'data-senna-link-selector',\n\tloadingCssClass: 'data-senna-loading-css-class',\n\tsenna: 'data-senna',\n\tdispatch: 'data-senna-dispatch',\n\tsurface: 'data-senna-surface',\n\tupdateScrollPosition: 'data-senna-update-scroll-position'\n};","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventHandle utility. Holds information about an event subscription, and\n * allows removing them easily.\n * EventHandle is a Disposable, but it's important to note that the\n * EventEmitter that created it is not the one responsible for disposing it.\n * That responsibility is for the code that holds a reference to it.\n * @extends {Disposable}\n */\nclass EventHandle extends Disposable {\n\t/**\n\t * EventHandle constructor\n\t * @param {!EventEmitter} emitter Emitter the event was subscribed to.\n\t * @param {string} event The name of the event that was subscribed to.\n\t * @param {!Function} listener The listener subscribed to the event.\n\t */\n\tconstructor(emitter, event, listener) {\n\t\tsuper();\n\n\t\t/**\n\t\t * The EventEmitter instance that the event was subscribed to.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.emitter_ = emitter;\n\n\t\t/**\n\t\t * The name of the event that was subscribed to.\n\t\t * @type {string}\n\t\t * @protected\n\t\t */\n\t\tthis.event_ = event;\n\n\t\t/**\n\t\t * The listener subscribed to the event.\n\t\t * @type {Function}\n\t\t * @protected\n\t\t */\n\t\tthis.listener_ = listener;\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.removeListener();\n\t\tthis.emitter_ = null;\n\t\tthis.listener_ = null;\n\t}\n\n\t/**\n\t * Removes the listener subscription from the emitter.\n\t */\n\tremoveListener() {\n\t\tif (!this.emitter_.isDisposed()) {\n\t\t\tthis.emitter_.removeListener(this.event_, this.listener_);\n\t\t}\n\t}\n}\n\nexport default EventHandle;\n","'use strict';\n\nimport {array, Disposable, isFunction, isString} from 'metal';\nimport EventHandle from './EventHandle';\n\nconst singleArray_ = [0];\n\n/**\n * EventEmitter utility.\n * @extends {Disposable}\n */\nclass EventEmitter extends Disposable {\n\t/**\n\t * EventEmitter constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds event listeners scoped by event type.\n\t\t * @type {Object<string, !Array<!function()>>}\n\t\t * @protected\n\t\t */\n\t\tthis.events_ = null;\n\n\t\t/**\n\t\t * Handlers that are triggered when an event is listened to.\n\t\t * @type {Array}\n\t\t */\n\t\tthis.listenerHandlers_ = null;\n\n\t\t/**\n\t\t * Configuration option which determines if an event facade should be sent\n\t\t * as a param of listeners when emitting events. If set to true, the facade\n\t\t * will be passed as the first argument of the listener.\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.shouldUseFacade_ = false;\n\t}\n\n\t/**\n\t * Adds a handler to given holder variable. If the holder doesn't have a\n\t * value yet, it will receive the handler directly. If the holder is an array,\n\t * the value will just be added to it. Otherwise, the holder will be set to a\n\t * new array containing its previous value plus the new handler.\n\t * @param {*} holder\n\t * @param {!function()|Object} handler\n\t * @return {*} The holder's new value.\n\t * @protected\n\t */\n\taddHandler_(holder, handler) {\n\t\tif (!holder) {\n\t\t\tholder = handler;\n\t\t} else {\n\t\t\tif (!Array.isArray(holder)) {\n\t\t\t\tholder = [holder];\n\t\t\t}\n\t\t\tholder.push(handler);\n\t\t}\n\t\treturn holder;\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for the specified events.\n\t * @param {!(Array|string)} event\n\t * @param {!Function} listener\n\t * @param {boolean} defaultListener Flag indicating if this listener is a default\n\t * action for this event. Default actions are run last, and only if no previous\n\t * listener call `preventDefault()` on the received event facade.\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\taddListener(event, listener, defaultListener) {\n\t\tthis.validateListener_(listener);\n\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.addSingleListener_(events[i], listener, defaultListener);\n\t\t}\n\n\t\treturn new EventHandle(this, event, listener);\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for a single event.\n\t * @param {string} event\n\t * @param {!Function} listener\n\t * @param {boolean} defaultListener Flag indicating if this listener is a default\n\t * action for this event. Default actions are run last, and only if no previous\n\t * listener call `preventDefault()` on the received event facade.\n\t * @param {Function=} origin The original function that was added as a\n\t * listener, if there is any.\n\t * @protected\n\t */\n\taddSingleListener_(event, listener, defaultListener, origin) {\n\t\tthis.runListenerHandlers_(event);\n\t\tif (defaultListener || origin) {\n\t\t\tlistener = {\n\t\t\t\tdefault: defaultListener,\n\t\t\t\tfn: listener,\n\t\t\t\torigin: origin,\n\t\t\t};\n\t\t}\n\t\tthis.events_ = this.events_ || {};\n\t\tthis.events_[event] = this.addHandler_(this.events_[event], listener);\n\t}\n\n\t/**\n\t * Builds facade for the given event.\n\t * @param {string} event\n\t * @return {Object}\n\t * @protected\n\t */\n\tbuildFacade_(event) {\n\t\tif (this.getShouldUseFacade()) {\n\t\t\tconst facade = {\n\t\t\t\tpreventDefault: function() {\n\t\t\t\t\tfacade.preventedDefault = true;\n\t\t\t\t},\n\t\t\t\ttarget: this,\n\t\t\t\ttype: event,\n\t\t\t};\n\t\t\treturn facade;\n\t\t}\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.events_ = null;\n\t}\n\n\t/**\n\t * Execute each of the listeners in order with the supplied arguments.\n\t * @param {string} event\n\t * @param {*} opt_args [arg1], [arg2], [...]\n\t * @return {boolean} Returns true if event had listeners, false otherwise.\n\t */\n\temit(event) {\n\t\tconst listeners = this.getRawListeners_(event);\n\t\tif (listeners.length === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst args = array.slice(arguments, 1); // eslint-disable-line\n\t\tthis.runListeners_(listeners, args, this.buildFacade_(event));\n\t\treturn true;\n\t}\n\n\t/**\n\t * Gets the listener objects for the given event, if there are any.\n\t * @param {string} event\n\t * @return {!Array}\n\t * @protected\n\t */\n\tgetRawListeners_(event) {\n\t\tconst directListeners = toArray(this.events_ && this.events_[event]);\n\t\treturn directListeners.concat(\n\t\t\ttoArray(this.events_ && this.events_['*'])\n\t\t);\n\t}\n\n\t/**\n\t * Gets the configuration option which determines if an event facade should\n\t * be sent as a param of listeners when emitting events. If set to true, the\n\t * facade will be passed as the first argument of the listener.\n\t * @return {boolean}\n\t */\n\tgetShouldUseFacade() {\n\t\treturn this.shouldUseFacade_;\n\t}\n\n\t/**\n\t * Returns an array of listeners for the specified event.\n\t * @param {string} event\n\t * @return {Array} Array of listeners.\n\t */\n\tlisteners(event) {\n\t\treturn this.getRawListeners_(event).map(\n\t\t\tlistener => (listener.fn ? listener.fn : listener)\n\t\t);\n\t}\n\n\t/**\n\t * Adds a listener that will be invoked a fixed number of times for the\n\t * events. After each event is triggered the specified amount of times, the\n\t * listener is removed for it.\n\t * @param {!(Array|string)} event\n\t * @param {number} amount The amount of times this event should be listened\n\t * to.\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\tmany(event, amount, listener) {\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.many_(events[i], amount, listener);\n\t\t}\n\n\t\treturn new EventHandle(this, event, listener);\n\t}\n\n\t/**\n\t * Adds a listener that will be invoked a fixed number of times for a single\n\t * event. After the event is triggered the specified amount of times, the\n\t * listener is removed.\n\t * @param {string} event\n\t * @param {number} amount The amount of times this event should be listened\n\t * to.\n\t * @param {!Function} listener\n\t * @protected\n\t */\n\tmany_(event, amount, listener) {\n\t\tconst self = this;\n\n\t\tif (amount <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t *\n\t\t */\n\t\tfunction handlerInternal() {\n\t\t\tif (--amount === 0) {\n\t\t\t\tself.removeListener(event, handlerInternal);\n\t\t\t}\n\t\t\tlistener.apply(self, arguments); // eslint-disable-line\n\t\t}\n\n\t\tself.addSingleListener_(event, handlerInternal, false, listener);\n\t}\n\n\t/**\n\t * Checks if a listener object matches the given listener function. To match,\n\t * it needs to either point to that listener or have it as its origin.\n\t * @param {!Object} listenerObj\n\t * @param {!Function} listener\n\t * @return {boolean}\n\t * @protected\n\t */\n\tmatchesListener_(listenerObj, listener) {\n\t\tconst fn = listenerObj.fn || listenerObj;\n\t\treturn (\n\t\t\tfn === listener ||\n\t\t\t(listenerObj.origin && listenerObj.origin === listener) // eslint-disable-line\n\t\t);\n\t}\n\n\t/**\n\t * Removes a listener for the specified events.\n\t * Caution: changes array indices in the listener array behind the listener.\n\t * @param {!(Array|string)} event\n\t * @param {!Function} listener\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\toff(event, listener) {\n\t\tthis.validateListener_(listener);\n\t\tif (!this.events_) {\n\t\t\treturn this;\n\t\t}\n\n\t\tconst events = this.toEventsArray_(event);\n\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\tthis.events_[events[i]] = this.removeMatchingListenerObjs_(\n\t\t\t\ttoArray(this.events_[events[i]]),\n\t\t\t\tlistener\n\t\t\t);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds a listener to the end of the listeners array for the specified events.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\ton() {\n\t\treturn this.addListener.apply(this, arguments); // eslint-disable-line\n\t}\n\n\t/**\n\t * Adds handler that gets triggered when an event is listened to on this\n\t * instance.\n\t * @param {!function()} handler\n\t */\n\tonListener(handler) {\n\t\tthis.listenerHandlers_ = this.addHandler_(\n\t\t\tthis.listenerHandlers_,\n\t\t\thandler\n\t\t); // eslint-disable-line\n\t}\n\n\t/**\n\t * Adds a one time listener for the events. This listener is invoked only the\n\t * next time each event is fired, after which it is removed.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!EventHandle} Can be used to remove the listener.\n\t */\n\tonce(events, listener) {\n\t\treturn this.many(events, 1, listener);\n\t}\n\n\t/**\n\t * Removes all listeners, or those of the specified events. It's not a good\n\t * idea to remove listeners that were added elsewhere in the code,\n\t * especially when it's on an emitter that you didn't create.\n\t * @param {(Array|string)=} event\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveAllListeners(event) {\n\t\tif (this.events_) {\n\t\t\tif (event) {\n\t\t\t\tconst events = this.toEventsArray_(event);\n\t\t\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\t\t\tthis.events_[events[i]] = null;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.events_ = null;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes all listener objects from the given array that match the given\n\t * listener function.\n\t * @param {Array.<Object>} listenerObjs\n\t * @param {!Function} listener\n\t * @return {Array.<Object>|Object} The new listeners array for this event.\n\t * @protected\n\t */\n\tremoveMatchingListenerObjs_(listenerObjs, listener) {\n\t\tconst finalListeners = [];\n\t\tfor (let i = 0; i < listenerObjs.length; i++) {\n\t\t\tif (!this.matchesListener_(listenerObjs[i], listener)) {\n\t\t\t\tfinalListeners.push(listenerObjs[i]);\n\t\t\t}\n\t\t}\n\t\treturn finalListeners.length > 0 ? finalListeners : null;\n\t}\n\n\t/**\n\t * Removes a listener for the specified events.\n\t * Caution: changes array indices in the listener array behind the listener.\n\t * @param {!(Array|string)} events\n\t * @param {!Function} listener\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveListener() {\n\t\treturn this.off.apply(this, arguments); // eslint-disable-line\n\t}\n\n\t/**\n\t * Runs the handlers when an event is listened to.\n\t * @param {string} event\n\t * @protected\n\t */\n\trunListenerHandlers_(event) {\n\t\tlet handlers = this.listenerHandlers_;\n\t\tif (handlers) {\n\t\t\thandlers = toArray(handlers);\n\t\t\tfor (let i = 0; i < handlers.length; i++) {\n\t\t\t\thandlers[i](event);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Runs the given listeners.\n\t * @param {!Array} listeners\n\t * @param {!Array} args\n\t * @param {Object} facade\n\t * @protected\n\t */\n\trunListeners_(listeners, args, facade) {\n\t\tif (facade) {\n\t\t\targs.push(facade);\n\t\t}\n\n\t\tconst defaultListeners = [];\n\t\tfor (let i = 0; i < listeners.length; i++) {\n\t\t\tconst listener = listeners[i].fn || listeners[i];\n\t\t\tif (listeners[i].default) {\n\t\t\t\tdefaultListeners.push(listener);\n\t\t\t} else {\n\t\t\t\tlistener.apply(this, args);\n\t\t\t}\n\t\t}\n\t\tif (!facade || !facade.preventedDefault) {\n\t\t\tfor (let j = 0; j < defaultListeners.length; j++) {\n\t\t\t\tdefaultListeners[j].apply(this, args);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets the configuration option which determines if an event facade should\n\t * be sent as a param of listeners when emitting events. If set to true, the\n\t * facade will be passed as the first argument of the listener.\n\t * @param {boolean} shouldUseFacade\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tsetShouldUseFacade(shouldUseFacade) {\n\t\tthis.shouldUseFacade_ = shouldUseFacade;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Converts the parameter to an array if only one event is given. Reuses the\n\t * same array each time this conversion is done, to avoid using more memory\n\t * than necessary.\n\t * @param {!(Array|string)} events\n\t * @return {!Array}\n\t * @protected\n\t */\n\ttoEventsArray_(events) {\n\t\tif (isString(events)) {\n\t\t\tsingleArray_[0] = events;\n\t\t\tevents = singleArray_;\n\t\t}\n\t\treturn events;\n\t}\n\n\t/**\n\t * Checks if the given listener is valid, throwing an exception when it's not.\n\t * @param {*} listener\n\t * @protected\n\t */\n\tvalidateListener_(listener) {\n\t\tif (!isFunction(listener)) {\n\t\t\tthrow new TypeError('Listener must be a function');\n\t\t}\n\t}\n}\n\n/**\n * Converts to an array\n * @param {Object} val\n * @return {Array}\n */\nfunction toArray(val) {\n\tval = val || [];\n\treturn Array.isArray(val) ? val : [val];\n}\n\nexport default EventEmitter;\n","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventEmitterProxy utility. It's responsible for linking two EventEmitter\n * instances together, emitting events from the first emitter through the\n * second one. That means that listening to a supported event on the target\n * emitter will mean listening to it on the origin emitter as well.\n * @extends {Disposable}\n */\nclass EventEmitterProxy extends Disposable {\n\t/**\n\t * @param {EventEmitter} originEmitter Events originated on this emitter\n\t * will be fired for the target emitter's listeners as well.\n\t * @param {EventEmitter} targetEmitter Event listeners attached to this emitter\n\t * will also be triggered when the event is fired by the origin emitter.\n\t * @param {Object} blacklist Optional blacklist of events that should not be\n\t * proxied.\n\t * @param {Object} whitelist\n\t */\n\tconstructor(originEmitter, targetEmitter, blacklist, whitelist) {\n\t\tsuper();\n\n\t\t/**\n\t\t * Map of events that should not be proxied.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.blacklist_ = blacklist;\n\n\t\t/**\n\t\t * The origin emitter. This emitter's events will be proxied through the\n\t\t * target emitter.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.originEmitter_ = originEmitter;\n\n\t\t/**\n\t\t * A list of events that are pending to be listened by an actual origin\n\t\t * emitter. Events are stored here when the origin doesn't exist, so they\n\t\t * can be set on a new origin when one is set.\n\t\t * @type {Array}\n\t\t * @protected\n\t\t */\n\t\tthis.pendingEvents_ = null;\n\n\t\t/**\n\t\t * Holds a map of events from the origin emitter that are already being proxied.\n\t\t * @type {Object<string, !EventHandle>}\n\t\t * @protected\n\t\t */\n\t\tthis.proxiedEvents_ = null;\n\n\t\t/**\n\t\t * The target emitter. This emitter will emit all events that come from\n\t\t * the origin emitter.\n\t\t * @type {EventEmitter}\n\t\t * @protected\n\t\t */\n\t\tthis.targetEmitter_ = targetEmitter;\n\n\t\t/**\n\t\t * Map of events that should be proxied. If whitelist is set blacklist is ignored.\n\t\t * @type {Object}\n\t\t * @protected\n\t\t */\n\t\tthis.whitelist_ = whitelist;\n\n\t\tthis.startProxy_();\n\t}\n\n\t/**\n\t * Adds the given listener for the given event.\n\t * @param {string} event\n\t * @param {!function()} listener\n\t * @return {!EventHandle} The listened event's handle.\n\t * @protected\n\t */\n\taddListener_(event, listener) {\n\t\treturn this.originEmitter_.on(event, listener);\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisposeInternal() {\n\t\tthis.removeListeners_();\n\t\tthis.proxiedEvents_ = null;\n\t\tthis.originEmitter_ = null;\n\t\tthis.targetEmitter_ = null;\n\t}\n\n\t/**\n\t * Emits the specified event type on the target emitter.\n\t * @protected\n\t */\n\temitOnTarget_(...args) {\n\t\tthis.targetEmitter_.emit(...args);\n\t}\n\n\t/**\n\t * Proxies the given event from the origin to the target emitter.\n\t * @param {string} event\n\t */\n\tproxyEvent(event) {\n\t\tif (this.shouldProxyEvent_(event)) {\n\t\t\tthis.tryToAddListener_(event);\n\t\t}\n\t}\n\n\t/**\n\t * Removes the proxy listener for all events.\n\t * @protected\n\t */\n\tremoveListeners_() {\n\t\tif (this.proxiedEvents_) {\n\t\t\tconst events = Object.keys(this.proxiedEvents_);\n\t\t\tfor (let i = 0; i < events.length; i++) {\n\t\t\t\tthis.proxiedEvents_[events[i]].removeListener();\n\t\t\t}\n\t\t\tthis.proxiedEvents_ = null;\n\t\t}\n\t\tthis.pendingEvents_ = null;\n\t}\n\n\t/**\n\t * Changes the origin emitter. This automatically detaches any events that\n\t * were already being proxied from the previous emitter, and starts proxying\n\t * them on the new emitter instead.\n\t * @param {!EventEmitter} originEmitter\n\t */\n\tsetOriginEmitter(originEmitter) {\n\t\tconst events =\n\t\t\tthis.originEmitter_ && this.proxiedEvents_\n\t\t\t\t? Object.keys(this.proxiedEvents_)\n\t\t\t\t: this.pendingEvents_;\n\t\tthis.originEmitter_ = originEmitter;\n\t\tif (events) {\n\t\t\tthis.removeListeners_();\n\t\t\tevents.forEach(event => this.proxyEvent(event));\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given event should be proxied.\n\t * @param {string} event\n\t * @return {boolean}\n\t * @protected\n\t */\n\tshouldProxyEvent_(event) {\n\t\tif (this.whitelist_ && !this.whitelist_[event]) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.blacklist_ && this.blacklist_[event]) {\n\t\t\treturn false;\n\t\t}\n\t\treturn !this.proxiedEvents_ || !this.proxiedEvents_[event];\n\t}\n\n\t/**\n\t * Starts proxying all events from the origin to the target emitter.\n\t * @protected\n\t */\n\tstartProxy_() {\n\t\tthis.targetEmitter_.onListener(this.proxyEvent.bind(this));\n\t}\n\n\t/**\n\t * Adds a listener to the origin emitter, if it exists. Otherwise, stores\n\t * the pending listener so it can be used on a future origin emitter.\n\t * @param {string} event\n\t * @protected\n\t */\n\ttryToAddListener_(event) {\n\t\tif (this.originEmitter_) {\n\t\t\tthis.proxiedEvents_ = this.proxiedEvents_ || {};\n\t\t\tthis.proxiedEvents_[event] = this.addListener_(\n\t\t\t\tevent,\n\t\t\t\tthis.emitOnTarget_.bind(this, event)\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pendingEvents_ = this.pendingEvents_ || [];\n\t\t\tthis.pendingEvents_.push(event);\n\t\t}\n\t}\n}\n\nexport default EventEmitterProxy;\n","'use strict';\n\nimport {Disposable} from 'metal';\n\n/**\n * EventHandler utility. It's useful for easily removing a group of\n * listeners from different EventEmitter instances.\n * @extends {Disposable}\n */\nclass EventHandler extends Disposable {\n\t/**\n\t * EventHandler constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * An array that holds the added event handles, so the listeners can be\n\t\t * removed later.\n\t\t * @type {Array.<EventHandle>}\n\t\t * @protected\n\t\t */\n\t\tthis.eventHandles_ = [];\n\t}\n\n\t/**\n\t * Adds event handles to be removed later through the `removeAllListeners`\n\t * method.\n\t * @param {...(!EventHandle)} var_args\n\t */\n\tadd(...args) {\n\t\tfor (let i = 0; i < arguments.length; i++) {\n\t\t\tthis.eventHandles_.push(args[i]);\n\t\t}\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.eventHandles_ = null;\n\t}\n\n\t/**\n\t * Removes all listeners that have been added through the `add` method.\n\t */\n\tremoveAllListeners() {\n\t\tfor (let i = 0; i < this.eventHandles_.length; i++) {\n\t\t\tthis.eventHandles_[i].removeListener();\n\t\t}\n\n\t\tthis.eventHandles_ = [];\n\t}\n}\n\nexport default EventHandler;\n","/*!\n * Promises polyfill from Google's Closure Library.\n *\n * Copyright 2013 The Closure Library Authors. All Rights Reserved.\n *\n * NOTE(eduardo): Promise support is not ready on all supported browsers,\n * therefore metal-promise is temporarily using Google's promises as polyfill.\n * It supports cancellable promises and has clean and fast implementation.\n */\n\n'use strict';\n\nimport { isDef, isFunction, isObject } from 'metal';\nimport { async } from 'metal';\n\n/**\n * Provides a more strict interface for Thenables in terms of\n * http://promisesaplus.com for interop with {@see CancellablePromise}.\n *\n * @interface\n * @extends {IThenable.<TYPE>}\n * @template TYPE\n */\nvar Thenable = function() {};\n\n/**\n * Adds callbacks that will operate on the result of the Thenable, returning a\n * new child Promise.\n *\n * If the Thenable is fulfilled, the {@code onFulfilled} callback will be\n * invoked with the fulfillment value as argument, and the child Promise will\n * be fulfilled with the return value of the callback. If the callback throws\n * an exception, the child Promise will be rejected with the thrown value\n * instead.\n *\n * If the Thenable is rejected, the {@code onRejected} callback will be invoked\n * with the rejection reason as argument, and the child Promise will be rejected\n * with the return value of the callback or thrown value.\n *\n * @param {?(function(this:THIS, TYPE):\n * (RESULT|IThenable.<RESULT>|Thenable))=} opt_onFulfilled A\n * function that will be invoked with the fulfillment value if the Promise\n * is fullfilled.\n * @param {?(function(*): *)=} opt_onRejected A function that will be invoked\n * with the rejection reason if the Promise is rejected.\n * @param {THIS=} opt_context An optional context object that will be the\n * execution context for the callbacks. By default, functions are executed\n * with the default this.\n * @return {!CancellablePromise.<RESULT>} A new Promise that will receive the\n * result of the fulfillment or rejection callback.\n * @template RESULT,THIS\n */\nThenable.prototype.then = function() {};\n\n\n/**\n * An expando property to indicate that an object implements\n * {@code Thenable}.\n *\n * {@see addImplementation}.\n *\n * @const\n */\nThenable.IMPLEMENTED_BY_PROP = '$goog_Thenable';\n\n\n/**\n * Marks a given class (constructor) as an implementation of Thenable, so\n * that we can query that fact at runtime. The class must have already\n * implemented the interface.\n * Exports a 'then' method on the constructor prototype, so that the objects\n * also implement the extern {@see Thenable} interface for interop with\n * other Promise implementations.\n * @param {function(new:Thenable,...[?])} ctor The class constructor. The\n * corresponding class must have already implemented the interface.\n */\nThenable.addImplementation = function(ctor) {\n ctor.prototype.then = ctor.prototype.then;\n ctor.prototype.$goog_Thenable = true;\n};\n\n\n/**\n * @param {*} object\n * @return {boolean} Whether a given instance implements {@code Thenable}.\n * The class/superclass of the instance must call {@code addImplementation}.\n */\nThenable.isImplementedBy = function(object) {\n if (!object) {\n return false;\n }\n try {\n return !!object.$goog_Thenable;\n } catch (e) {\n // Property access seems to be forbidden.\n return false;\n }\n};\n\n\n/**\n * Like bind(), except that a 'this object' is not required. Useful when the\n * target function is already bound.\n *\n * Usage:\n * var g = partial(f, arg1, arg2);\n * g(arg3, arg4);\n *\n * @param {Function} fn A function to partially apply.\n * @param {...*} var_args Additional arguments that are partially applied to fn.\n * @return {!Function} A partially-applied form of the function bind() was\n * invoked as a method of.\n */\nvar partial = function(fn) {\n var args = Array.prototype.slice.call(arguments, 1);\n return function() {\n // Clone the array (with slice()) and append additional arguments\n // to the existing arguments.\n var newArgs = args.slice();\n newArgs.push.apply(newArgs, arguments);\n return fn.apply(this, newArgs);\n };\n};\n\n/**\n * Promises provide a result that may be resolved asynchronously. A Promise may\n * be resolved by being fulfilled or rejected with a value, which will be known\n * as the fulfillment value or the rejection reason. Whether fulfilled or\n * rejected, the Promise result is immutable once it is set.\n *\n * Promises may represent results of any type, including undefined. Rejection\n * reasons are typically Errors, but may also be of any type. Closure Promises\n * allow for optional type annotations that enforce that fulfillment values are\n * of the appropriate types at compile time.\n *\n * The result of a Promise is accessible by calling {@code then} and registering\n * {@code onFulfilled} and {@code onRejected} callbacks. Once the Promise\n * resolves, the relevant callbacks are invoked with the fulfillment value or\n * rejection reason as argument. Callbacks are always invoked in the order they\n * were registered, even when additional {@code then} calls are made from inside\n * another callback. A callback is always run asynchronously sometime after the\n * scope containing the registering {@code then} invocation has returned.\n *\n * If a Promise is resolved with another Promise, the first Promise will block\n * until the second is resolved, and then assumes the same result as the second\n * Promise. This allows Promises to depend on the results of other Promises,\n * linking together multiple asynchronous operations.\n *\n * This implementation is compatible with the Promises/A+ specification and\n * passes that specification's conformance test suite. A Closure Promise may be\n * resolved with a Promise instance (or sufficiently compatible Promise-like\n * object) created by other Promise implementations. From the specification,\n * Promise-like objects are known as \"Thenables\".\n *\n * @see http://promisesaplus.com/\n *\n * @param {function(\n * this:RESOLVER_CONTEXT,\n * function((TYPE|IThenable.<TYPE>|Thenable)),\n * function(*)): void} resolver\n * Initialization function that is invoked immediately with {@code resolve}\n * and {@code reject} functions as arguments. The Promise is resolved or\n * rejected with the first argument passed to either function.\n * @param {RESOLVER_CONTEXT=} opt_context An optional context for executing the\n * resolver function. If unspecified, the resolver function will be executed\n * in the default scope.\n * @constructor\n * @struct\n * @final\n * @implements {Thenable.<TYPE>}\n * @template TYPE,RESOLVER_CONTEXT\n */\nvar CancellablePromise = function(resolver, opt_context) {\n /**\n * The internal state of this Promise. Either PENDING, FULFILLED, REJECTED, or\n * BLOCKED.\n * @private {CancellablePromise.State_}\n */\n this.state_ = CancellablePromise.State_.PENDING;\n\n /**\n * The resolved result of the Promise. Immutable once set with either a\n * fulfillment value or rejection reason.\n * @private {*}\n */\n this.result_ = undefined;\n\n /**\n * For Promises created by calling {@code then()}, the originating parent.\n * @private {CancellablePromise}\n */\n this.parent_ = null;\n\n /**\n * The list of {@code onFulfilled} and {@code onRejected} callbacks added to\n * this Promise by calls to {@code then()}.\n * @private {Array.<CancellablePromise.CallbackEntry_>}\n */\n this.callbackEntries_ = null;\n\n /**\n * Whether the Promise is in the queue of Promises to execute.\n * @private {boolean}\n */\n this.executing_ = false;\n\n if (CancellablePromise.UNHANDLED_REJECTION_DELAY > 0) {\n /**\n * A timeout ID used when the {@code UNHANDLED_REJECTION_DELAY} is greater\n * than 0 milliseconds. The ID is set when the Promise is rejected, and\n * cleared only if an {@code onRejected} callback is invoked for the\n * Promise (or one of its descendants) before the delay is exceeded.\n *\n * If the rejection is not handled before the timeout completes, the\n * rejection reason is passed to the unhandled rejection handler.\n * @private {number}\n */\n this.unhandledRejectionId_ = 0;\n } else if (CancellablePromise.UNHANDLED_REJECTION_DELAY === 0) {\n /**\n * When the {@code UNHANDLED_REJECTION_DELAY} is set to 0 milliseconds, a\n * boolean that is set if the Promise is rejected, and reset to false if an\n * {@code onRejected} callback is invoked for the Promise (or one of its\n * descendants). If the rejection is not handled before the next timestep,\n * the rejection reason is passed to the unhandled rejection handler.\n * @private {boolean}\n */\n this.hadUnhandledRejection_ = false;\n }\n\n try {\n var self = this;\n resolver.call(\n opt_context, function(value) {\n self.resolve_(CancellablePromise.State_.FULFILLED, value);\n }, function(reason) {\n self.resolve_(CancellablePromise.State_.REJECTED, reason);\n });\n } catch (e) {\n this.resolve_(CancellablePromise.State_.REJECTED, e);\n }\n};\n\n/**\n * The delay in milliseconds before a rejected Promise's reason is passed to\n * the rejection handler. By default, the rejection handler rethrows the\n * rejection reason so that it appears in the developer console or\n * {@code window.onerror} handler.\n * Rejections are rethrown as quickly as possible by default. A negative value\n * disables rejection handling entirely.\n * @type {number}\n */\nCancellablePromise.UNHANDLED_REJECTION_DELAY = 0;\n\n\n/**\n * The possible internal states for a Promise. These states are not directly\n * observable to external callers.\n * @enum {number}\n * @private\n */\nCancellablePromise.State_ = {\n /** The Promise is waiting for resolution. */\n PENDING: 0,\n\n /** The Promise is blocked waiting for the result of another Thenable. */\n BLOCKED: 1,\n\n /** The Promise has been resolved with a fulfillment value. */\n FULFILLED: 2,\n\n /** The Promise has been resolved with a rejection reason. */\n REJECTED: 3\n};\n\n\n/**\n * Typedef for entries in the callback chain. Each call to {@code then},\n * {@code thenCatch}, or {@code thenAlways} creates an entry containing the\n * functions that may be invoked once the Promise is resolved.\n *\n * @typedef {{\n * child: CancellablePromise,\n * onFulfilled: function(*),\n * onRejected: function(*)\n * }}\n * @private\n */\nCancellablePromise.CallbackEntry_ = null;\n\n\n/**\n * @param {(TYPE|Thenable.<TYPE>|Thenable)=} opt_value\n * @return {!CancellablePromise.<TYPE>} A new Promise that is immediately resolved\n * with the given value.\n * @template TYPE\n */\nCancellablePromise.resolve = function(opt_value) {\n return new CancellablePromise(function(resolve) {\n resolve(opt_value);\n });\n};\n\n\n/**\n * @param {*=} opt_reason\n * @return {!CancellablePromise} A new Promise that is immediately rejected with the\n * given reason.\n */\nCancellablePromise.reject = function(opt_reason) {\n return new CancellablePromise(function(resolve, reject) {\n reject(opt_reason);\n });\n};\n\n\n/**\n * @param {!Array.<!(Thenable.<TYPE>|Thenable)>} promises\n * @return {!CancellablePromise.<TYPE>} A Promise that receives the result of the\n * first Promise (or Promise-like) input to complete.\n * @template TYPE\n */\nCancellablePromise.race = function(promises) {\n return new CancellablePromise(function(resolve, reject) {\n if (!promises.length) {\n resolve(undefined);\n }\n for (var i = 0, promise; (promise = promises[i]); i++) {\n promise.then(resolve, reject);\n }\n });\n};\n\n\n/**\n * @param {!Array.<!(Thenable.<TYPE>|Thenable)>} promises\n * @return {!CancellablePromise.<!Array.<TYPE>>} A Promise that receives a list of\n * every fulfilled value once every input Promise (or Promise-like) is\n * successfully fulfilled, or is rejected by the first rejection result.\n * @template TYPE\n */\nCancellablePromise.all = function(promises) {\n return new CancellablePromise(function(resolve, reject) {\n var toFulfill = promises.length;\n var values = [];\n\n if (!toFulfill) {\n resolve(values);\n return;\n }\n\n var onFulfill = function(index, value) {\n toFulfill--;\n values[index] = value;\n if (toFulfill === 0) {\n resolve(values);\n }\n };\n\n var onReject = function(reason) {\n reject(reason);\n };\n\n for (var i = 0, promise; (promise = promises[i]); i++) {\n promise.then(partial(onFulfill, i), onReject);\n }\n });\n};\n\n\n/**\n * @param {!Array.<!(Thenable.<TYPE>|Thenable)>} promises\n * @return {!CancellablePromise.<TYPE>} A Promise that receives the value of\n * the first input to be fulfilled, or is rejected with a list of every\n * rejection reason if all inputs are rejected.\n * @template TYPE\n */\nCancellablePromise.firstFulfilled = function(promises) {\n return new CancellablePromise(function(resolve, reject) {\n var toReject = promises.length;\n var reasons = [];\n\n if (!toReject) {\n resolve(undefined);\n return;\n }\n\n var onFulfill = function(value) {\n resolve(value);\n };\n\n var onReject = function(index, reason) {\n toReject--;\n reasons[index] = reason;\n if (toReject === 0) {\n reject(reasons);\n }\n };\n\n for (var i = 0, promise; (promise = promises[i]); i++) {\n promise.then(onFulfill, partial(onReject, i));\n }\n });\n};\n\n\n/**\n * Adds callbacks that will operate on the result of the Promise, returning a\n * new child Promise.\n *\n * If the Promise is fulfilled, the {@code onFulfilled} callback will be invoked\n * with the fulfillment value as argument, and the child Promise will be\n * fulfilled with the return value of the callback. If the callback throws an\n * exception, the child Promise will be rejected with the thrown value instead.\n *\n * If the Promise is rejected, the {@code onRejected} callback will be invoked\n * with the rejection reason as argument, and the child Promise will be rejected\n * with the return value (or thrown value) of the callback.\n *\n * @override\n */\nCancellablePromise.prototype.then = function(opt_onFulfilled, opt_onRejected, opt_context) {\n return this.addChildPromise_(\n isFunction(opt_onFulfilled) ? opt_onFulfilled : null,\n isFunction(opt_onRejected) ? opt_onRejected : null,\n opt_context);\n};\nThenable.addImplementation(CancellablePromise);\n\n\n/**\n * Adds a callback that will be invoked whether the Promise is fulfilled or\n * rejected. The callback receives no argument, and no new child Promise is\n * created. This is useful for ensuring that cleanup takes place after certain\n * asynchronous operations. Callbacks added with {@code thenAlways} will be\n * executed in the same order with other calls to {@code then},\n * {@code thenAlways}, or {@code thenCatch}.\n *\n * Since it does not produce a new child Promise, cancellation propagation is\n * not prevented by adding callbacks with {@code thenAlways}. A Promise that has\n * a cleanup handler added with {@code thenAlways} will be canceled if all of\n * its children created by {@code then} (or {@code thenCatch}) are canceled.\n *\n * @param {function(this:THIS): void} onResolved A function that will be invoked\n * when the Promise is resolved.\n * @param {THIS=} opt_context An optional context object that will be the\n * execution context for the callbacks. By default, functions are executed\n * in the global scope.\n * @return {!CancellablePromise.<TYPE>} This Promise, for chaining additional calls.\n * @template THIS\n */\nCancellablePromise.prototype.thenAlways = function(onResolved, opt_context) {\n var callback = function() {\n try {\n // Ensure that no arguments are passed to onResolved.\n onResolved.call(opt_context);\n } catch (err) {\n CancellablePromise.handleRejection_.call(null, err);\n }\n };\n\n this.addCallbackEntry_({\n child: null,\n onRejected: callback,\n onFulfilled: callback\n });\n return this;\n};\n\n\n/**\n * Adds a callback that will be invoked only if the Promise is rejected. This\n * is equivalent to {@code then(null, onRejected)}.\n *\n * @param {!function(this:THIS, *): *} onRejected A function that will be\n * invoked with the rejection reason if the Promise is rejected.\n * @param {THIS=} opt_context An optional context object that will be the\n * execution context for the callbacks. By default, functions are executed\n * in the global scope.\n * @return {!CancellablePromise} A new Promise that will receive the result of the\n * callback.\n * @template THIS\n */\nCancellablePromise.prototype.thenCatch = function(onRejected, opt_context) {\n return this.addChildPromise_(null, onRejected, opt_context);\n};\n\n/**\n * Alias of {@link CancellablePromise.prototype.thenCatch}\n */\nCancellablePromise.prototype.catch = CancellablePromise.prototype.thenCatch;\n\n\n/**\n * Cancels the Promise if it is still pending by rejecting it with a cancel\n * Error. No action is performed if the Promise is already resolved.\n *\n * All child Promises of the canceled Promise will be rejected with the same\n * cancel error, as with normal Promise rejection. If the Promise to be canceled\n * is the only child of a pending Promise, the parent Promise will also be\n * canceled. Cancellation may propagate upward through multiple generations.\n *\n * @param {string=} opt_message An optional debugging message for describing the\n * cancellation reason.\n */\nCancellablePromise.prototype.cancel = function(opt_message) {\n if (this.state_ === CancellablePromise.State_.PENDING) {\n async.run(function() {\n var err = new CancellablePromise.CancellationError(opt_message);\n err.IS_CANCELLATION_ERROR = true;\n this.cancelInternal_(err);\n }, this);\n }\n};\n\n\n/**\n * Cancels this Promise with the given error.\n *\n * @param {!Error} err The cancellation error.\n * @private\n */\nCancellablePromise.prototype.cancelInternal_ = function(err) {\n if (this.state_ === CancellablePromise.State_.PENDING) {\n if (this.parent_) {\n // Cancel the Promise and remove it from the parent's child list.\n this.parent_.cancelChild_(this, err);\n } else {\n this.resolve_(CancellablePromise.State_.REJECTED, err);\n }\n }\n};\n\n\n/**\n * Cancels a child Promise from the list of callback entries. If the Promise has\n * not already been resolved, reject it with a cancel error. If there are no\n * other children in the list of callback entries, propagate the cancellation\n * by canceling this Promise as well.\n *\n * @param {!CancellablePromise} childPromise The Promise to cancel.\n * @param {!Error} err The cancel error to use for rejecting the Promise.\n * @private\n */\nCancellablePromise.prototype.cancelChild_ = function(childPromise, err) {\n if (!this.callbackEntries_) {\n return;\n }\n var childCount = 0;\n var childIndex = -1;\n\n // Find the callback entry for the childPromise, and count whether there are\n // additional child Promises.\n for (var i = 0, entry; (entry = this.callbackEntries_[i]); i++) {\n var child = entry.child;\n if (child) {\n childCount++;\n if (child === childPromise) {\n childIndex = i;\n }\n if (childIndex >= 0 && childCount > 1) {\n break;\n }\n }\n }\n\n // If the child Promise was the only child, cancel this Promise as well.\n // Otherwise, reject only the child Promise with the cancel error.\n if (childIndex >= 0) {\n if (this.state_ === CancellablePromise.State_.PENDING && childCount === 1) {\n this.cancelInternal_(err);\n } else {\n var callbackEntry = this.callbackEntries_.splice(childIndex, 1)[0];\n this.executeCallback_(\n callbackEntry, CancellablePromise.State_.REJECTED, err);\n }\n }\n};\n\n\n/**\n * Adds a callback entry to the current Promise, and schedules callback\n * execution if the Promise has already been resolved.\n *\n * @param {CancellablePromise.CallbackEntry_} callbackEntry Record containing\n * {@code onFulfilled} and {@code onRejected} callbacks to execute after\n * the Promise is resolved.\n * @private\n */\nCancellablePromise.prototype.addCallbackEntry_ = function(callbackEntry) {\n if ((!this.callbackEntries_ || !this.callbackEntries_.length) &&\n (this.state_ === CancellablePromise.State_.FULFILLED ||\n this.state_ === CancellablePromise.State_.REJECTED)) {\n this.scheduleCallbacks_();\n }\n if (!this.callbackEntries_) {\n this.callbackEntries_ = [];\n }\n this.callbackEntries_.push(callbackEntry);\n};\n\n\n/**\n * Creates a child Promise and adds it to the callback entry list. The result of\n * the child Promise is determined by the state of the parent Promise and the\n * result of the {@code onFulfilled} or {@code onRejected} callbacks as\n * specified in the Promise resolution procedure.\n *\n * @see http://promisesaplus.com/#the__method\n *\n * @param {?function(this:THIS, TYPE):\n * (RESULT|CancellablePromise.<RESULT>|Thenable)} onFulfilled A callback that\n * will be invoked if the Promise is fullfilled, or null.\n * @param {?function(this:THIS, *): *} onRejected A callback that will be\n * invoked if the Promise is rejected, or null.\n * @param {THIS=} opt_context An optional execution context for the callbacks.\n * in the default calling context.\n * @return {!CancellablePromise} The child Promise.\n * @template RESULT,THIS\n * @private\n */\nCancellablePromise.prototype.addChildPromise_ = function(\nonFulfilled, onRejected, opt_context) {\n\n var callbackEntry = {\n child: null,\n onFulfilled: null,\n onRejected: null\n };\n\n callbackEntry.child = new CancellablePromise(function(resolve, reject) {\n // Invoke onFulfilled, or resolve with the parent's value if absent.\n callbackEntry.onFulfilled = onFulfilled ? function(value) {\n try {\n var result = onFulfilled.call(opt_context, value);\n resolve(result);\n } catch (err) {\n reject(err);\n }\n } : resolve;\n\n // Invoke onRejected, or reject with the parent's reason if absent.\n callbackEntry.onRejected = onRejected ? function(reason) {\n try {\n var result = onRejected.call(opt_context, reason);\n if (!isDef(result) && reason.IS_CANCELLATION_ERROR) {\n // Propagate cancellation to children if no other result is returned.\n reject(reason);\n } else {\n resolve(result);\n }\n } catch (err) {\n reject(err);\n }\n } : reject;\n });\n\n callbackEntry.child.parent_ = this;\n this.addCallbackEntry_(\n /** @type {CancellablePromise.CallbackEntry_} */ (callbackEntry));\n return callbackEntry.child;\n};\n\n\n/**\n * Unblocks the Promise and fulfills it with the given value.\n *\n * @param {TYPE} value\n * @private\n */\nCancellablePromise.prototype.unblockAndFulfill_ = function(value) {\n if (this.state_ !== CancellablePromise.State_.BLOCKED) {\n throw new Error('CancellablePromise is not blocked.');\n }\n this.state_ = CancellablePromise.State_.PENDING;\n this.resolve_(CancellablePromise.State_.FULFILLED, value);\n};\n\n\n/**\n * Unblocks the Promise and rejects it with the given rejection reason.\n *\n * @param {*} reason\n * @private\n */\nCancellablePromise.prototype.unblockAndReject_ = function(reason) {\n if (this.state_ !== CancellablePromise.State_.BLOCKED) {\n throw new Error('CancellablePromise is not blocked.');\n }\n this.state_ = CancellablePromise.State_.PENDING;\n this.resolve_(CancellablePromise.State_.REJECTED, reason);\n};\n\n\n/**\n * Attempts to resolve a Promise with a given resolution state and value. This\n * is a no-op if the given Promise has already been resolved.\n *\n * If the given result is a Thenable (such as another Promise), the Promise will\n * be resolved with the same state and result as the Thenable once it is itself\n * resolved.\n *\n * If the given result is not a Thenable, the Promise will be fulfilled or\n * rejected with that result based on the given state.\n *\n * @see http://promisesaplus.com/#the_promise_resolution_procedure\n *\n * @param {CancellablePromise.State_} state\n * @param {*} x The result to apply to the Promise.\n * @private\n */\nCancellablePromise.prototype.resolve_ = function(state, x) {\n if (this.state_ !== CancellablePromise.State_.PENDING) {\n return;\n }\n\n if (this === x) {\n state = CancellablePromise.State_.REJECTED;\n x = new TypeError('CancellablePromise cannot resolve to itself');\n\n } else if (Thenable.isImplementedBy(x)) {\n x = /** @type {!Thenable} */ (x);\n this.state_ = CancellablePromise.State_.BLOCKED;\n x.then(this.unblockAndFulfill_, this.unblockAndReject_, this);\n return;\n\n } else if (isObject(x)) {\n try {\n var then = x.then;\n if (isFunction(then)) {\n this.tryThen_(x, then);\n return;\n }\n } catch (e) {\n state = CancellablePromise.State_.REJECTED;\n x = e;\n }\n }\n\n this.result_ = x;\n this.state_ = state;\n this.scheduleCallbacks_();\n\n if (state === CancellablePromise.State_.REJECTED && !x.IS_CANCELLATION_ERROR) {\n CancellablePromise.addUnhandledRejection_(this, x);\n }\n};\n\n\n/**\n * Attempts to call the {@code then} method on an object in the hopes that it is\n * a Promise-compatible instance. This allows interoperation between different\n * Promise implementations, however a non-compliant object may cause a Promise\n * to hang indefinitely. If the {@code then} method throws an exception, the\n * dependent Promise will be rejected with the thrown value.\n *\n * @see http://promisesaplus.com/#point-70\n *\n * @param {Thenable} thenable An object with a {@code then} method that may be\n * compatible with the Promise/A+ specification.\n * @param {!Function} then The {@code then} method of the Thenable object.\n * @private\n */\nCancellablePromise.prototype.tryThen_ = function(thenable, then) {\n this.state_ = CancellablePromise.State_.BLOCKED;\n var promise = this;\n var called = false;\n\n var resolve = function(value) {\n if (!called) {\n called = true;\n promise.unblockAndFulfill_(value);\n }\n };\n\n var reject = function(reason) {\n if (!called) {\n called = true;\n promise.unblockAndReject_(reason);\n }\n };\n\n try {\n then.call(thenable, resolve, reject);\n } catch (e) {\n reject(e);\n }\n};\n\n\n/**\n * Executes the pending callbacks of a resolved Promise after a timeout.\n *\n * Section 2.2.4 of the Promises/A+ specification requires that Promise\n * callbacks must only be invoked from a call stack that only contains Promise\n * implementation code, which we accomplish by invoking callback execution after\n * a timeout. If {@code startExecution_} is called multiple times for the same\n * Promise, the callback chain will be evaluated only once. Additional callbacks\n * may be added during the evaluation phase, and will be executed in the same\n * event loop.\n *\n * All Promises added to the waiting list during the same browser event loop\n * will be executed in one batch to avoid using a separate timeout per Promise.\n *\n * @private\n */\nCancellablePromise.prototype.scheduleCallbacks_ = function() {\n if (!this.executing_) {\n this.executing_ = true;\n async.run(this.executeCallbacks_, this);\n }\n};\n\n\n/**\n * Executes all pending callbacks for this Promise.\n *\n * @private\n */\nCancellablePromise.prototype.executeCallbacks_ = function() {\n while (this.callbackEntries_ && this.callbackEntries_.length) {\n var entries = this.callbackEntries_;\n this.callbackEntries_ = [];\n\n for (var i = 0; i < entries.length; i++) {\n this.executeCallback_(entries[i], this.state_, this.result_);\n }\n }\n this.executing_ = false;\n};\n\n\n/**\n * Executes a pending callback for this Promise. Invokes an {@code onFulfilled}\n * or {@code onRejected} callback based on the resolved state of the Promise.\n *\n * @param {!CancellablePromise.CallbackEntry_} callbackEntry An entry containing the\n * onFulfilled and/or onRejected callbacks for this step.\n * @param {CancellablePromise.State_} state The resolution status of the Promise,\n * either FULFILLED or REJECTED.\n * @param {*} result The resolved result of the Promise.\n * @private\n */\nCancellablePromise.prototype.executeCallback_ = function(\ncallbackEntry, state, result) {\n if (state === CancellablePromise.State_.FULFILLED) {\n callbackEntry.onFulfilled(result);\n } else {\n this.removeUnhandledRejection_();\n callbackEntry.onRejected(result);\n }\n};\n\n\n/**\n * Marks this rejected Promise as having being handled. Also marks any parent\n * Promises in the rejected state as handled. The rejection handler will no\n * longer be invoked for this Promise (if it has not been called already).\n *\n * @private\n */\nCancellablePromise.prototype.removeUnhandledRejection_ = function() {\n var p;\n if (CancellablePromise.UNHANDLED_REJECTION_DELAY > 0) {\n for (p = this; p && p.unhandledRejectionId_; p = p.parent_) {\n clearTimeout(p.unhandledRejectionId_);\n p.unhandledRejectionId_ = 0;\n }\n } else if (CancellablePromise.UNHANDLED_REJECTION_DELAY === 0) {\n for (p = this; p && p.hadUnhandledRejection_; p = p.parent_) {\n p.hadUnhandledRejection_ = false;\n }\n }\n};\n\n\n/**\n * Marks this rejected Promise as unhandled. If no {@code onRejected} callback\n * is called for this Promise before the {@code UNHANDLED_REJECTION_DELAY}\n * expires, the reason will be passed to the unhandled rejection handler. The\n * handler typically rethrows the rejection reason so that it becomes visible in\n * the developer console.\n *\n * @param {!CancellablePromise} promise The rejected Promise.\n * @param {*} reason The Promise rejection reason.\n * @private\n */\nCancellablePromise.addUnhandledRejection_ = function(promise, reason) {\n if (CancellablePromise.UNHANDLED_REJECTION_DELAY > 0) {\n promise.unhandledRejectionId_ = setTimeout(function() {\n CancellablePromise.handleRejection_.call(null, reason);\n }, CancellablePromise.UNHANDLED_REJECTION_DELAY);\n\n } else if (CancellablePromise.UNHANDLED_REJECTION_DELAY === 0) {\n promise.hadUnhandledRejection_ = true;\n async.run(function() {\n if (promise.hadUnhandledRejection_) {\n CancellablePromise.handleRejection_.call(null, reason);\n }\n });\n }\n};\n\n\n/**\n * A method that is invoked with the rejection reasons for Promises that are\n * rejected but have no {@code onRejected} callbacks registered yet.\n * @type {function(*)}\n * @private\n */\nCancellablePromise.handleRejection_ = async.throwException;\n\n\n/**\n * Sets a handler that will be called with reasons from unhandled rejected\n * Promises. If the rejected Promise (or one of its descendants) has an\n * {@code onRejected} callback registered, the rejection will be considered\n * handled, and the rejection handler will not be called.\n *\n * By default, unhandled rejections are rethrown so that the error may be\n * captured by the developer console or a {@code window.onerror} handler.\n *\n * @param {function(*)} handler A function that will be called with reasons from\n * rejected Promises. Defaults to {@code async.throwException}.\n */\nCancellablePromise.setUnhandledRejectionHandler = function(handler) {\n CancellablePromise.handleRejection_ = handler;\n};\n\n\n\n/**\n * Error used as a rejection reason for canceled Promises.\n *\n * @param {string=} opt_message\n * @constructor\n * @extends {Error}\n * @final\n */\nCancellablePromise.CancellationError = class extends Error {\n constructor(opt_message) {\n super(opt_message);\n\n if (opt_message) {\n this.message = opt_message;\n }\n }\n};\n\n/** @override */\nCancellablePromise.CancellationError.prototype.name = 'cancel';\n\nexport {CancellablePromise};\nexport default CancellablePromise;\n","'use strict';\n\n/**\n * Debounces function execution.\n * @param {!function()} fn\n * @param {number} delay\n * @return {!function()}\n */\nfunction debounce(fn, delay) {\n\treturn function debounced() {\n\t\tvar args = arguments;\n\t\tcancelDebounce(debounced);\n\t\tdebounced.id = setTimeout(function() {\n\t\t\tfn.apply(null, args);\n\t\t}, delay);\n\t};\n}\n\n/**\n * Cancels the scheduled debounced function.\n */\nfunction cancelDebounce(debounced) {\n\tclearTimeout(debounced.id);\n}\n\nexport default debounce;\nexport { cancelDebounce, debounce };\n","'use strict';\n\nimport core from 'metal';\n\nconst REGEX = /([\\/])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])*)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?)/g;\n\n/**\n * Converts the given array of regex matches to a more readable object format.\n * @param {!Array<string>} matches\n * @return {!Object}\n */\nfunction convertMatchesToObj(matches) {\n\treturn {\n\t\tmatch: matches[0],\n\t\tprefix: matches[1],\n\t\tname: matches[2],\n\t\tparamPattern: matches[3],\n\t\tunnamedPattern: matches[4],\n\t\tmodifier: matches[5]\n\t};\n}\n\n/**\n * Converts the given tokens parsed from a route format string to a regex.\n * @param {!Array<string|!Object>} tokens\n * @return {!RegExp}\n */\nfunction convertTokensToRegex(tokens) {\n\tlet regex = '';\n\tfor (let i = 0; i < tokens.length; i++) {\n\t\tif (core.isString(tokens[i])) {\n\t\t\tregex += escape(tokens[i]);\n\t\t} else {\n\t\t\tlet capture = encloseNonCapturingGroup(tokens[i].pattern);\n\t\t\tif (tokens[i].repeat) {\n\t\t\t\tcapture += encloseNonCapturingGroup('\\\\/' + capture) + '*';\n\t\t\t}\n\t\t\tcapture = escape(tokens[i].prefix) + `(${capture})`;\n\t\t\tif (tokens[i].optional) {\n\t\t\t\tif (!tokens[i].partial) {\n\t\t\t\t\tcapture = encloseNonCapturingGroup(capture);\n\t\t\t\t}\n\t\t\t\tcapture += '?';\n\t\t\t}\n\t\t\tregex += capture;\n\t\t}\n\t}\n\treturn new RegExp('^' + makeTrailingSlashOptional(regex) + '$');\n}\n\n/**\n * Encloses the given regex pattern into a non capturing group.\n * @param {string} pattern\n * @return {string}\n */\nfunction encloseNonCapturingGroup(pattern) {\n\treturn `(?:${pattern})`;\n}\n\n/**\n * Escapes the given string to show up in the path regex.\n * @param {string} str\n * @return {string}\n */\nfunction escape(str) {\n\treturn str.replace(/([.+*?=^!:${}()[\\]|\\/\\\\])/g, '\\\\$1');\n}\n\n/**\n * Makes trailing slash optional on paths.\n * @param {string} regex\n * @param {string}\n */\nfunction makeTrailingSlashOptional(regex) {\n\tif (/\\/$/.test(regex)) {\n\t\tregex += '?';\n\t} else {\n\t\tregex += '\\\\/?';\n\t}\n\treturn regex;\n}\n\n/**\n * Parses the given route format string into tokens representing its contents.\n * @param {!Array|string} routeOrTokens Either a route format string or tokens\n * previously parsed via the `parse` function.\n * @return {!Array<string|!Object>} An array of tokens that can be either plain\n * strings (part of the route) or objects containing informations on params.\n */\nexport function parse(routeOrTokens) {\n\tif (!core.isString(routeOrTokens)) {\n\t\treturn routeOrTokens;\n\t}\n\n\tconst route = routeOrTokens;\n\tlet unnamedCount = 0;\n\tconst tokens = [];\n\tlet currPath = '';\n\tlet index = 0;\n\n\tlet matches = REGEX.exec(route);\n\twhile (matches) {\n\t\tconst data = convertMatchesToObj(matches);\n\n\t\tcurrPath = route.slice(index, matches.index);\n\t\tindex = matches.index + data.match.length;\n\t\ttokens.push(currPath);\n\n\t\ttokens.push({\n\t\t\tname: data.name ? data.name : '' + unnamedCount++,\n\t\t\tpartial: route[index] && route[index] !== data.prefix,\n\t\t\tprefix: data.prefix || '',\n\t\t\tpattern: data.paramPattern || data.unnamedPattern || '[^\\\\/]+',\n\t\t\trepeat: data.modifier === '*' || data.modifier === '+',\n\t\t\toptional: data.modifier === '*' || data.modifier === '?'\n\t\t});\n\n\t\tmatches = REGEX.exec(route);\n\t}\n\n\tif (index < route.length) {\n\t\ttokens.push(route.substr(index));\n\t}\n\treturn tokens;\n}\n\n/**\n * Converts the given route format string to a regex that can extract param\n * data from paths matching it.\n * @param {!Array|string} routeOrTokens Either a route format string or tokens\n * previously parsed via the `parse` function.\n * @return {!RegExp}\n */\nexport function toRegex(routeOrTokens) {\n\treturn convertTokensToRegex(parse(routeOrTokens));\n}\n\n/**\n * Extracts data from the given path according to the specified route format.\n * @param {!Array|string} routeOrTokens Either a route format string or tokens\n * previously parsed via the `parse` function.\n * @param {string} The path to extract param data from.\n * @return {Object<string, string>} The data object, or null if the path doesn't\n * match the given format.\n */\nexport function extractData(routeOrTokens, path) {\n\tconst data = {};\n\tconst tokens = parse(routeOrTokens);\n\tconst match = path.match(convertTokensToRegex(tokens));\n\n\tif (!match) {\n\t\treturn null;\n\t}\n\n\tlet paramIndex = 1;\n\tfor (let i = 0; i < tokens.length; i++) {\n\t\tif (!core.isString(tokens[i])) {\n\t\t\tlet value = match[paramIndex++];\n\t\t\tif (core.isDef(value)) {\n\t\t\t\tif (tokens[i].repeat) {\n\t\t\t\t\tvalue = value.split('/');\n\t\t\t\t}\n\t\t\t\tdata[tokens[i].name] = value;\n\t\t\t}\n\t\t}\n\t}\n\treturn data;\n}\n","'use strict';\n\nimport { isDefAndNotNull, isFunction, isString } from 'metal';\nimport { extractData, parse, toRegex } from 'metal-path-parser';\n\nclass Route {\n\n\t/**\n\t * Route class.\n\t * @param {!string|RegExp|Function} path\n\t * @param {!Function} handler\n\t * @constructor\n\t */\n\tconstructor(path, handler) {\n\t\tif (!isDefAndNotNull(path)) {\n\t\t\tthrow new Error('Route path not specified.');\n\t\t}\n\t\tif (!isFunction(handler)) {\n\t\t\tthrow new Error('Route handler is not a function.');\n\t\t}\n\n\t\t/**\n\t\t * Defines the handler which will execute once a URL in the application\n\t\t * matches the path.\n\t\t * @type {!Function}\n\t\t * @protected\n\t\t */\n\t\tthis.handler = handler;\n\n\t\t/**\n\t\t * Defines the path which will trigger the route handler.\n\t\t * @type {!string|RegExp|Function}\n\t\t * @protected\n\t\t */\n\t\tthis.path = path;\n\t}\n\n\t/**\n\t* Builds parsed data (regex and tokens) for this route.\n\t* @return {!Object}\n\t* @protected\n\t*/\n\tbuildParsedData_() {\n\t\tif (!this.parsedData_) {\n\t\t\tvar tokens = parse(this.path);\n\t\t\tvar regex = toRegex(tokens);\n\t\t\tthis.parsedData_ = {\n\t\t\t\tregex,\n\t\t\t\ttokens\n\t\t\t};\n\t\t}\n\t\treturn this.parsedData_;\n\t}\n\n\t/**\n\t * Extracts param data from the given path, according to this route.\n\t * @param {string} path The url path to extract params from.\n\t * @return {Object} The extracted data, if the path matches this route, or\n\t * null otherwise.\n\t */\n\textractParams(path) {\n\t\tif (isString(this.path)) {\n\t\t\treturn extractData(this.buildParsedData_().tokens, path);\n\t\t}\n\t\treturn {};\n\t}\n\n\t/**\n\t * Gets the route handler.\n\t * @return {!Function}\n\t */\n\tgetHandler() {\n\t\treturn this.handler;\n\t}\n\n\t/**\n\t * Gets the route path.\n\t * @return {!string|RegExp|Function}\n\t */\n\tgetPath() {\n\t\treturn this.path;\n\t}\n\n\t/**\n \t * Matches if the router can handle the tested path.\n \t * @param {!string} value Path to test (may contain the querystring part).\n\t * @return {boolean} Returns true if matches any route.\n\t */\n\tmatchesPath(value) {\n\t\tvar path = this.path;\n\n\t\tif (isFunction(path)) {\n\t\t\treturn path(value);\n\t\t}\n\t\tif (isString(path)) {\n\t\t\tpath = this.buildParsedData_().regex;\n\t\t}\n\t\tif (path instanceof RegExp) {\n\t\t\treturn value.search(path) > -1;\n\t\t}\n\n\t\treturn false;\n\t}\n\n}\n\nexport default Route;\n","'use strict';\n\nimport { Disposable } from 'metal';\n\nclass Cacheable extends Disposable {\n\n\t/**\n\t * Abstract class for defining cacheable behavior.\n\t * @constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the cached data.\n\t\t * @type {!Object}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.cache = null;\n\n\t\t/**\n\t\t * Holds whether class is cacheable.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.cacheable = false;\n\t}\n\n\t/**\n\t * Adds content to the cache.\n\t * @param {string} content Content to be cached.\n\t * @chainable\n\t */\n\taddCache(content) {\n\t\tif (this.cacheable) {\n\t\t\tthis.cache = content;\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Clears the cache.\n\t * @chainable\n\t */\n\tclearCache() {\n\t\tthis.cache = null;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tthis.clearCache();\n\t}\n\n\t/**\n\t * Gets the cached content.\n\t * @return {Object} Cached content.\n\t * @protected\n\t */\n\tgetCache() {\n\t\treturn this.cache;\n\t}\n\n\t/**\n\t * Whether the class is cacheable.\n\t * @return {boolean} Returns true when class is cacheable, false otherwise.\n\t */\n\tisCacheable() {\n\t\treturn this.cacheable;\n\t}\n\n\t/**\n\t * Sets whether the class is cacheable.\n\t * @param {boolean} cacheable\n\t */\n\tsetCacheable(cacheable) {\n\t\tif (!cacheable) {\n\t\t\tthis.clearCache();\n\t\t}\n\t\tthis.cacheable = cacheable;\n\t}\n\n}\n\nexport default Cacheable;\n","'use strict';\n\nimport { getUid } from 'metal';\nimport { globalEval } from 'metal-dom';\nimport Cacheable from '../cacheable/Cacheable';\nimport CancellablePromise from 'metal-promise';\n\nclass Screen extends Cacheable {\n\n\t/**\n\t * Screen class is a special type of route handler that provides helper\n\t * utilities that adds lifecycle and methods to provide content to each\n\t * registered surface.\n\t * @constructor\n\t * @extends {Cacheable}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the screen id.\n\t\t * @type {string}\n\t\t * @protected\n\t\t */\n\t\tthis.id = this.makeId_(getUid());\n\n\t\t/**\n\t\t * Holds the screen meta tags. Relevant when the meta tags\n\t\t * should be updated when screen is rendered.\n\t\t */\n\t\tthis.metas = null;\n\n\t\t/**\n\t\t * Holds the screen title. Relevant when the page title should be\n\t\t * upadated when screen is rendered.\n\t\t * @type {?string=}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.title = null;\n\t}\n\n\t/**\n\t * Fires when the screen is active. Allows a screen to perform any setup\n\t * that requires its DOM to be visible. Lifecycle.\n\t */\n\tactivate() {\n\t\tconsole.log('Screen [' + this + '] activate');\n\t}\n\n\t/**\n\t * Gives the Screen a chance to cancel the navigation and stop itself from\n\t * activating. Can be used, for example, to prevent navigation if a user\n\t * is not authenticated. Lifecycle.\n\t * @return {boolean=|?CancellablePromise=} If returns or resolves to true,\n\t * the current screen is locked and the next nagivation interrupted.\n\t */\n\tbeforeActivate() {\n\t\tconsole.log('Screen [' + this + '] beforeActivate');\n\t}\n\n\t/**\n\t * Gives the Screen a chance to cancel the navigation and stop itself from\n\t * being deactivated. Can be used, for example, if the screen has unsaved\n\t * state. Lifecycle. Clean-up should not be preformed here, since the\n\t * navigation may still be cancelled. Do clean-up in deactivate.\n\t * @return {boolean=|?CancellablePromise=} If returns or resolves to true,\n\t * the current screen is locked and the next nagivation interrupted.\n\t */\n\tbeforeDeactivate() {\n\t\tconsole.log('Screen [' + this + '] beforeDeactivate');\n\t}\n\n\t/**\n\t * Gives the Screen a chance format the path before history update.\n\t * @path {!string} path Navigation path.\n\t * @return {!string} Navigation path to use on history.\n\t */\n\tbeforeUpdateHistoryPath(path) {\n\t\treturn path;\n\t}\n\n\t/**\n\t * Gives the Screen a chance format the state before history update.\n\t * @path {!object} state History state.\n\t * @return {!object} History state to use on history.\n\t */\n\tbeforeUpdateHistoryState(state) {\n\t\treturn state;\n\t}\n\n\t/**\n\t * Allows a screen to do any cleanup necessary after it has been\n\t * deactivated, for example cancelling outstanding requests or stopping\n\t * timers. Lifecycle.\n\t */\n\tdeactivate() {\n\t\tconsole.log('Screen [' + this + '] deactivate');\n\t}\n\n\t/**\n\t * Dispose a screen, either after it is deactivated (in the case of a\n\t * non-cacheable view) or when the App is itself disposed for whatever\n\t * reason. Lifecycle.\n\t */\n\tdisposeInternal() {\n\t\tsuper.disposeInternal();\n\t\tconsole.log('Screen [' + this + '] dispose');\n\t}\n\n\t/**\n\t * Allows a screen to evaluate scripts before the element is made visible.\n\t * Lifecycle.\n\t * @param {!object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @return {?CancellablePromise=} This can return a promise, which will\n\t * pause the navigation until it is resolved.\n\t */\n\tevaluateScripts(surfaces) {\n\t\tObject.keys(surfaces).forEach(sId => {\n\t\t\tif (surfaces[sId].activeChild) {\n\t\t\t\tglobalEval.runScriptsInElement(surfaces[sId].activeChild);\n\t\t\t}\n\t\t});\n\t\treturn CancellablePromise.resolve();\n\t}\n\n\t/**\n\t * Allows a screen to evaluate styles before the element is made visible.\n\t * Lifecycle.\n\t * @param {!object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @return {?CancellablePromise=} This can return a promise, which will\n\t * pause the navigation until it is resolved.\n\t */\n\tevaluateStyles() {\n\t\treturn CancellablePromise.resolve();\n\t}\n\n\t/**\n\t * Allows a screen to perform any setup immediately before the element is\n\t * made visible. Lifecycle.\n\t * @param {!object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @return {?CancellablePromise=} This can return a promise, which will pause the\n\t * navigation until it is resolved.\n\t */\n\tflip(surfaces) {\n\t\tconsole.log('Screen [' + this + '] flip');\n\n\t\tvar transitions = [];\n\n\t\tObject.keys(surfaces).forEach(sId => {\n\t\t\tvar surface = surfaces[sId];\n\t\t\tvar deferred = surface.show(this.id);\n\t\t\ttransitions.push(deferred);\n\t\t});\n\n\t\treturn CancellablePromise.all(transitions);\n\t}\n\n\t/**\n\t * Gets the screen id.\n\t * @return {string}\n\t */\n\tgetId() {\n\t\treturn this.id;\n\t}\n\n\t/**\n\t * Gets the screen meta tags.\n\t * @return {NodeList|Node}\n\t */\n\tgetMetas() {\n\t\treturn this.metas;\n\t}\n\n\t/**\n\t * Returns the content for the given surface, or null if the surface isn't\n\t * used by this screen. This will be called when a screen is initially\n\t * constructed or, if a screen is non-cacheable, when navigated.\n\t * @param {!string} surfaceId The id of the surface DOM element.\n\t * @param {!Object} params Params extracted from the current path.\n\t * @return {?string|Element=} This can return a string or node representing\n\t * the content of the surface. If returns falsy values surface default\n\t * content is restored.\n\t */\n\tgetSurfaceContent() {\n\t\tconsole.log('Screen [' + this + '] getSurfaceContent');\n\t}\n\n\t/**\n\t * Gets the screen title.\n\t * @return {?string=}\n\t */\n\tgetTitle() {\n\t\treturn this.title;\n\t}\n\n\t/**\n\t * Returns all contents for the surfaces. This will pass the loaded content\n\t * to <code>Screen.load</code> with all information you\n\t * need to fulfill the surfaces. Lifecycle.\n\t * @param {!string=} path The requested path.\n\t * @return {!CancellablePromise} This can return a string representing the\n\t * contents of the surfaces or a promise, which will pause the navigation\n\t * until it is resolved. This is useful for loading async content.\n\t */\n\tload() {\n\t\tconsole.log('Screen [' + this + '] load');\n\t\treturn CancellablePromise.resolve();\n\t}\n\n\t/**\n\t * Makes the id for the screen.\n\t * @param {!string} id The screen id the content belongs too.\n\t * @return {string}\n\t * @private\n\t */\n\tmakeId_(id) {\n\t\treturn 'screen_' + id;\n\t}\n\n\t/**\n\t * Sets the screen id.\n\t * @param {!string} id\n\t */\n\tsetId(id) {\n\t\tthis.id = id;\n\t}\n\n\t/**\n\t * Sets the screen meta tags.\n\t * @param {NodeList|Node} metas\n\t */\n\tsetMetas(metas) {\n\t\tthis.metas = metas;\n\t}\n\n\t/**\n\t * Sets the screen title.\n\t * @param {?string=} title\n\t */\n\tsetTitle(title) {\n\t\tthis.title = title;\n\t}\n\n\t/**\n\t * @return {string}\n\t */\n\ttoString() {\n\t\treturn this.id;\n\t}\n\n}\n\n/**\n * @param {*} object\n * @return {boolean} Whether a given instance implements\n * <code>Screen</code>.\n */\nScreen.isImplementedBy = function(object) {\n\treturn object instanceof Screen;\n};\n\nexport default Screen;\n","'use strict';\n\nimport globals from '../globals/globals';\nimport { Disposable, isDefAndNotNull } from 'metal';\nimport { append, removeChildren, exitDocument } from 'metal-dom';\nimport CancellablePromise from 'metal-promise';\n\nclass Surface extends Disposable {\n\n\t/**\n\t * Surface class representing the references to elements on the page that\n\t * can potentially be updated by <code>App</code>.\n\t * @param {string} id\n\t * @constructor\n\t */\n\tconstructor(id) {\n\t\tsuper();\n\n\t\tif (!id) {\n\t\t\tthrow new Error('Surface element id not specified. A surface element requires a valid id.');\n\t\t}\n\n\t\t/**\n\t\t * Holds the active child element.\n\t\t * @type {Element}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.activeChild = null;\n\n\t\t/**\n\t\t * Holds the default child element.\n\t\t * @type {Element}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.defaultChild = null;\n\n\t\t/**\n\t\t * Holds the element with the specified surface id, if not found creates a\n\t\t * new element with the specified id.\n\t\t * @type {Element}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.element = null;\n\n\t\t/**\n\t\t * Holds the surface id.\n\t\t * @type {String}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.id = id;\n\n\t\t/**\n\t\t * Holds the default transitionFn for the surfaces.\n\t\t * @param {?Element=} from The visible surface element.\n\t\t * @param {?Element=} to The surface element to be flipped.\n\t\t * @default null\n\t\t */\n\t\tthis.transitionFn = null;\n\n\t\tthis.defaultChild = this.getChild(Surface.DEFAULT);\n\t\tthis.maybeWrapContentAsDefault_();\n\t\tthis.activeChild = this.defaultChild;\n\t}\n\n\t/**\n\t * Adds screen content to a surface. If content hasn't been passed, see if\n\t * an element exists in the DOM that matches the id. By convention, the\n\t * element should already be nested in the right element and should have an\n\t * id that is a concatentation of the surface id + '-' + the screen id.\n\t * @param {!string} screenId The screen id the content belongs too.\n\t * @param {?string|Element=} opt_content The string content or element to\n\t * add be added as surface content.\n\t * @return {Element}\n\t */\n\taddContent(screenId, opt_content) {\n\t\tvar child = this.defaultChild;\n\n\t\tif (isDefAndNotNull(opt_content)) {\n\t\t\tchild = this.getChild(screenId);\n\t\t\tif (child) {\n\t\t\t\tremoveChildren(child);\n\t\t\t} else {\n\t\t\t\tchild = this.createChild(screenId);\n\t\t\t\tthis.transition(child, null);\n\t\t\t}\n\t\t\tappend(child, opt_content);\n\t\t}\n\n\t\tvar element = this.getElement();\n\n\t\tif (element && child) {\n\t\t\tappend(element, child);\n\t\t}\n\n\t\treturn child;\n\t}\n\n\t/**\n\t * Creates child node for the surface.\n\t * @param {!string} screenId The screen id.\n\t * @return {Element}\n\t */\n\tcreateChild(screenId) {\n\t\tvar child = globals.document.createElement('div');\n\t\tchild.setAttribute('id', this.makeId_(screenId));\n\t\treturn child;\n\t}\n\n\t/**\n\t * Gets child node of the surface.\n\t * @param {!string} screenId The screen id.\n\t * @return {?Element}\n\t */\n\tgetChild(screenId) {\n\t\treturn globals.document.getElementById(this.makeId_(screenId));\n\t}\n\n\t/**\n\t * Gets the surface element from element, and sets it to the el property of\n\t * the current instance.\n\t * <code>this.element</code> will be used.\n\t * @return {?Element} The current surface element.\n\t */\n\tgetElement() {\n\t\tif (this.element) {\n\t\t\treturn this.element;\n\t\t}\n\t\tthis.element = globals.document.getElementById(this.id);\n\t\treturn this.element;\n\t}\n\n\t/**\n\t * Gets the surface id.\n\t * @return {String}\n\t */\n\tgetId() {\n\t\treturn this.id;\n\t}\n\n\t/**\n\t * Gets the surface transition function.\n\t * See <code>Surface.defaultTransition</code>.\n\t * @return {?Function=} The transition function.\n\t */\n\tgetTransitionFn() {\n\t\treturn this.transitionFn;\n\t}\n\n\t/**\n\t * Makes the id for the element that holds content for a screen.\n\t * @param {!string} screenId The screen id the content belongs too.\n\t * @return {String}\n\t * @private\n\t */\n\tmakeId_(screenId) {\n\t\treturn this.id + '-' + screenId;\n\t}\n\n\t/**\n\t * If default child is missing, wraps surface content as default child. If\n\t * surface have static content, make sure to place a\n\t * <code>surfaceId-default</code> element inside surface, only contents\n\t * inside the default child will be replaced by navigation.\n\t */\n\tmaybeWrapContentAsDefault_() {\n\t\tvar element = this.getElement();\n\t\tif (element && !this.defaultChild) {\n\t\t\tvar fragment = globals.document.createDocumentFragment();\n\t\t\twhile (element.firstChild) {\n\t\t\t\tfragment.appendChild(element.firstChild);\n\t\t\t}\n\t\t\tthis.defaultChild = this.addContent(Surface.DEFAULT, fragment);\n\t\t\tthis.transition(null, this.defaultChild);\n\t\t}\n\t}\n\n\t/**\n\t * Sets the surface id.\n\t * @param {!string} id\n\t */\n\tsetId(id) {\n\t\tthis.id = id;\n\t}\n\n\t/**\n\t * Sets the surface transition function.\n\t * See <code>Surface.defaultTransition</code>.\n\t * @param {?Function=} transitionFn The transition function.\n\t */\n\tsetTransitionFn(transitionFn) {\n\t\tthis.transitionFn = transitionFn;\n\t}\n\n\t/**\n\t * Shows screen content from a surface.\n\t * @param {String} screenId The screen id to show.\n\t * @return {CancellablePromise} Pauses the navigation until it is resolved.\n\t */\n\tshow(screenId) {\n\t\tvar from = this.activeChild;\n\t\tvar to = this.getChild(screenId);\n\t\tif (!to) {\n\t\t\tto = this.defaultChild;\n\t\t}\n\t\tthis.activeChild = to;\n\t\treturn this.transition(from, to).thenAlways(() => {\n\t\t\tif (from && from !== to) {\n\t\t\t\texitDocument(from);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Removes screen content from a surface.\n\t * @param {!string} screenId The screen id to remove.\n\t */\n\tremove(screenId) {\n\t\tvar child = this.getChild(screenId);\n\t\tif (child) {\n\t\t\texitDocument(child);\n\t\t}\n\t}\n\n\t/**\n\t * @return {String}\n\t */\n\ttoString() {\n\t\treturn this.id;\n\t}\n\n\t/**\n\t * Invokes the transition function specified on <code>transition</code> attribute.\n\t * @param {?Element=} from\n\t * @param {?Element=} to\n\t * @return {?CancellablePromise=} This can return a promise, which will pause the\n\t * navigation until it is resolved.\n\t */\n\ttransition(from, to) {\n\t\tvar transitionFn = this.transitionFn || Surface.defaultTransition;\n\t\treturn CancellablePromise.resolve(transitionFn.call(this, from, to));\n\t}\n\n}\n\n/**\n * Holds the default surface name. Elements on the page must contain a child\n * element containing the default content, this element must be as following:\n *\n * Example:\n * <code>\n * <div id=\"mysurface\">\n * <div id=\"mysurface-default\">Default surface content.</div>\n * </div>\n * </code>\n *\n * The default content is relevant for the initial page content. When a\n * screen doesn't provide content for the surface the default content is\n * restored into the page.\n *\n * @type {!String}\n * @default default\n * @static\n */\nSurface.DEFAULT = 'default';\n\n/**\n * Holds the default transition for all surfaces. Each surface could have its\n * own transition.\n *\n * Example:\n *\n * <code>\n * surface.setTransitionFn(function(from, to) {\n * if (from) {\n * from.style.display = 'none';\n * from.classList.remove('flipped');\n * }\n * if (to) {\n * to.style.display = 'block';\n * to.classList.add('flipped');\n * }\n * return null;\n * });\n * </code>\n *\n * @param {?Element=} from The visible surface element.\n * @param {?Element=} to The surface element to be flipped.\n * @static\n */\nSurface.defaultTransition = function(from, to) {\n\tif (from) {\n\t\tfrom.style.display = 'none';\n\t\tfrom.classList.remove('flipped');\n\t}\n\tif (to) {\n\t\tto.style.display = 'block';\n\t\tto.classList.add('flipped');\n\t}\n};\n\nexport default Surface;\n","'use strict';\n\nimport { addClasses, delegate, match, on, removeClasses } from 'metal-dom';\nimport { array, async, isDefAndNotNull, isString, object } from 'metal';\nimport { EventEmitter, EventHandler } from 'metal-events';\nimport CancellablePromise from 'metal-promise';\nimport debounce from 'metal-debounce';\nimport globals from '../globals/globals';\nimport Route from '../route/Route';\nimport Screen from '../screen/Screen';\nimport Surface from '../surface/Surface';\nimport Uri from 'metal-uri';\nimport utils from '../utils/utils';\n\nconst NavigationStrategy = {\n\tIMMEDIATE: 'immediate',\n\tSCHEDULE_LAST: 'scheduleLast'\n};\n\nclass App extends EventEmitter {\n\n\t/**\n\t * App class that handle routes and screens lifecycle.\n\t * @constructor\n\t * @extends {EventEmitter}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the active screen.\n\t\t * @type {?Screen}\n\t\t * @protected\n\t\t */\n\t\tthis.activeScreen = null;\n\n\t\t/**\n\t\t * Holds the active path containing the query parameters.\n\t\t * @type {?string}\n\t\t * @protected\n\t\t */\n\t\tthis.activePath = null;\n\n\t\t/**\n\t\t * Allows prevent navigate from dom prevented event.\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.allowPreventNavigate = true;\n\n\t\t/**\n\t\t * Holds link base path.\n\t\t * @type {!string}\n\t\t * @default ''\n\t\t * @protected\n\t\t */\n\t\tthis.basePath = '';\n\n\t\t/**\n\t\t * Holds the value of the browser path before a navigation is performed.\n\t\t * @type {!string}\n\t\t * @default the current browser path.\n\t\t * @protected\n\t\t */\n\t\tthis.browserPathBeforeNavigate = utils.getCurrentBrowserPathWithoutHash();\n\n\t\t/**\n\t\t * Captures scroll position from scroll event.\n\t\t * @type {!boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.captureScrollPositionFromScrollEvent = true;\n\n\t\t/**\n\t\t * Holds the default page title.\n\t\t * @type {string}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.defaultTitle = globals.document.title;\n\n\t\t/**\n\t\t * Holds the form selector to define forms that are routed.\n\t\t * @type {!string}\n\t\t * @default form[enctype=\"multipart/form-data\"]:not([data-senna-off])\n\t\t * @protected\n\t\t */\n\t\tthis.formSelector = 'form[enctype=\"multipart/form-data\"]:not([data-senna-off])';\n\n\t\t/**\n\t\t * When enabled, the route matching ignores query string from the path.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.ignoreQueryStringFromRoutePath = false;\n\n\t\t/**\n\t\t * Holds the link selector to define links that are routed.\n\t\t * @type {!string}\n\t\t * @default a:not([data-senna-off])\n\t\t * @protected\n\t\t */\n\t\tthis.linkSelector = 'a:not([data-senna-off]):not([target=\"_blank\"])';\n\n\t\t/**\n\t\t * Holds the loading css class.\n\t\t * @type {!string}\n\t\t * @default senna-loading\n\t\t * @protected\n\t\t */\n\t\tthis.loadingCssClass = 'senna-loading';\n\n\t\t/**\n\t\t * Using the History API to manage your URLs is awesome and, as it happens,\n\t\t * a crucial feature of good web apps. One of its downsides, however, is\n\t\t * that scroll positions are stored and then, more importantly, restored\n\t\t * whenever you traverse the history. This often means unsightly jumps as\n\t\t * the scroll position changes automatically, and especially so if your app\n\t\t * does transitions, or changes the contents of the page in any way.\n\t\t * Ultimately this leads to an horrible user experience. The good news is,\n\t\t * however, that there’s a potential fix: history.scrollRestoration.\n\t\t * https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration\n\t\t * @type {boolean}\n\t\t * @protected\n\t\t */\n\t\tthis.nativeScrollRestorationSupported = ('scrollRestoration' in globals.window.history);\n\n\t\t/**\n\t\t * When set to NavigationStrategy.SCHEDULE_LAST means that the current navigation\n\t\t * cannot be Cancelled to start another and will be queued in\n\t\t * scheduledNavigationQueue. When NavigationStrategy.IMMEDIATE means that all\n\t\t * navigation will be cancelled to start another.\n\t\t * @type {!string}\n\t\t * @default immediate\n\t\t * @protected\n\t\t */\n\t\tthis.navigationStrategy = NavigationStrategy.IMMEDIATE;\n\n\t\t/**\n\t\t * When set to true there is a pendingNavigate that has not yet been\n\t\t * resolved or rejected.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.isNavigationPending = false;\n\n\t\t/**\n\t\t * Holds a deferred with the current navigation.\n\t\t * @type {?CancellablePromise}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.pendingNavigate = null;\n\n\t\t/**\n\t\t * Holds the window horizontal scroll position when the navigation using\n\t\t * back or forward happens to be restored after the surfaces are updated.\n\t\t * @type {!Number}\n\t\t * @default 0\n\t\t * @protected\n\t\t */\n\t\tthis.popstateScrollLeft = 0;\n\n\t\t/**\n\t\t * Holds the window vertical scroll position when the navigation using\n\t\t * back or forward happens to be restored after the surfaces are updated.\n\t\t * @type {!Number}\n\t\t * @default 0\n\t\t * @protected\n\t\t */\n\t\tthis.popstateScrollTop = 0;\n\n\t\t/**\n\t\t * Holds the redirect path containing the query parameters.\n\t\t * @type {?string}\n\t\t * @protected\n\t\t */\n\t\tthis.redirectPath = null;\n\n\t\t/**\n\t\t * Holds the screen routes configuration.\n\t\t * @type {?Array}\n\t\t * @default []\n\t\t * @protected\n\t\t */\n\t\tthis.routes = [];\n\n\t\t/**\n\t\t * Holds a queue that stores every DOM event that can initiate a navigation.\n\t\t * @type {!Event}\n\t\t * @default []\n\t\t * @protected\n\t\t */\n\t\tthis.scheduledNavigationQueue = [];\n\n\t\t/**\n\t\t * Maps the screen instances by the url containing the parameters.\n\t\t * @type {?Object}\n\t\t * @default {}\n\t\t * @protected\n\t\t */\n\t\tthis.screens = {};\n\n\t\t/**\n\t\t * When set to true the first erroneous popstate fired on page load will be\n\t\t * ignored, only if <code>globals.window.history.state</code> is also\n\t\t * <code>null</code>.\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t * @protected\n\t\t */\n\t\tthis.skipLoadPopstate = false;\n\n\t\t/**\n\t\t * Maps that index the surfaces instances by the surface id.\n\t\t * @type {?Object}\n\t\t * @default {}\n\t\t * @protected\n\t\t */\n\t\tthis.surfaces = {};\n\n\t\t/**\n\t\t * When set to true, moves the scroll position after popstate, or to the\n\t\t * top of the viewport for new navigation. If false, the browser will\n\t\t * take care of scroll restoration.\n\t\t * @type {!boolean}\n\t\t * @default true\n\t\t * @protected\n\t\t */\n\t\tthis.updateScrollPosition = true;\n\n\t\tthis.appEventHandlers_ = new EventHandler();\n\n\t\tthis.appEventHandlers_.add(\n\t\t\ton(globals.window, 'scroll', debounce(this.onScroll_.bind(this), 100)),\n\t\t\ton(globals.window, 'load', this.onLoad_.bind(this)),\n\t\t\ton(globals.window, 'popstate', this.onPopstate_.bind(this))\n\t\t);\n\n\t\tthis.on('startNavigate', this.onStartNavigate_);\n\t\tthis.on('beforeNavigate', this.onBeforeNavigate_);\n\t\tthis.on('beforeNavigate', this.onBeforeNavigateDefault_, true);\n\t\tthis.on('beforeUnload', this.onBeforeUnloadDefault_);\n\n\t\tthis.setLinkSelector(this.linkSelector);\n\t\tthis.setFormSelector(this.formSelector);\n\n\t\tthis.maybeOverloadBeforeUnload_();\n\t}\n\n\t/**\n\t * Adds one or more screens to the application.\n\t *\n\t * Example:\n\t *\n\t * <code>\n\t * app.addRoutes({ path: '/foo', handler: FooScreen });\n\t * or\n\t * app.addRoutes([{ path: '/foo', handler: function(route) { return new FooScreen(); } }]);\n\t * </code>\n\t *\n\t * @param {Object} or {Array} routes Single object or an array of object.\n\t * Each object should contain <code>path</code> and <code>screen</code>.\n\t * The <code>path</code> should be a string or a regex that maps the\n\t * navigation route to a screen class definition (not an instance), e.g:\n\t * <code>{ path: \"/home:param1\", handler: MyScreen }</code>\n\t * <code>{ path: /foo.+/, handler: MyScreen }</code>\n\t * @chainable\n\t */\n\taddRoutes(routes) {\n\t\tif (!Array.isArray(routes)) {\n\t\t\troutes = [routes];\n\t\t}\n\t\troutes.forEach((route) => {\n\t\t\tif (!(route instanceof Route)) {\n\t\t\t\troute = new Route(route.path, route.handler);\n\t\t\t}\n\t\t\tthis.routes.push(route);\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds one or more surfaces to the application.\n\t * @param {Surface|String|Array.<Surface|String>} surfaces\n\t * Surface element id or surface instance. You can also pass an Array\n\t * whichcontains surface instances or id. In case of ID, these should be\n\t * the id of surface element.\n\t * @chainable\n\t */\n\taddSurfaces(surfaces) {\n\t\tif (!Array.isArray(surfaces)) {\n\t\t\tsurfaces = [surfaces];\n\t\t}\n\t\tsurfaces.forEach((surface) => {\n\t\t\tif (isString(surface)) {\n\t\t\t\tsurface = new Surface(surface);\n\t\t\t}\n\t\t\tthis.surfaces[surface.getId()] = surface;\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns if can navigate to path.\n\t * @param {!string} url\n\t * @return {boolean}\n\t */\n\tcanNavigate(url) {\n\t\tconst uri = utils.isWebUri(url);\n\n\t\tif (!uri) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst path = utils.getUrlPath(url);\n\n\t\tif (!this.isLinkSameOrigin_(uri.getHost())) {\n\t\t\tconsole.log('Offsite link clicked');\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.isSameBasePath_(path)) {\n\t\t\tconsole.log('Link clicked outside app\\'s base path');\n\t\t\treturn false;\n\t\t}\n\t\t// Prevents navigation if it's a hash change on the same url.\n\t\tif (uri.getHash() && utils.isCurrentBrowserPath(path)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.findRoute(path)) {\n\t\t\tconsole.log('No route for ' + path);\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Clear screens cache.\n\t * @chainable\n\t */\n\tclearScreensCache() {\n\t\tObject.keys(this.screens).forEach((path) => {\n\t\t\tif (path === this.activePath) {\n\t\t\t\tthis.activeScreen.clearCache();\n\t\t\t} else if (!(this.isNavigationPending && this.pendingNavigate.path === path)) {\n\t\t\t\tthis.removeScreen(path);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves or create a screen instance to a path.\n\t * @param {!string} path Path containing the querystring part.\n\t * @return {Screen}\n\t */\n\tcreateScreenInstance(path, route) {\n\t\tif (!this.pendingNavigate && path === this.activePath) {\n\t\t\tconsole.log('Already at destination, refresh navigation');\n\t\t\treturn this.activeScreen;\n\t\t}\n\t\t/* jshint newcap: false */\n\t\tvar screen = this.screens[path];\n\t\tif (!screen) {\n\t\t\tvar handler = route.getHandler();\n\t\t\tif (handler === Screen || Screen.isImplementedBy(handler.prototype)) {\n\t\t\t\tscreen = new handler();\n\t\t\t} else {\n\t\t\t\tscreen = handler(route) || new Screen();\n\t\t\t}\n\t\t\tconsole.log('Create screen for [' + path + '] [' + screen + ']');\n\t\t}\n\t\treturn screen;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisposeInternal() {\n\t\tif (this.activeScreen) {\n\t\t\tthis.removeScreen(this.activePath);\n\t\t}\n\t\tthis.clearScreensCache();\n\t\tthis.formEventHandler_.removeListener();\n\t\tthis.linkEventHandler_.removeListener();\n\t\tthis.appEventHandlers_.removeAllListeners();\n\t\tsuper.disposeInternal();\n\t}\n\n\t/**\n\t * Dispatches to the first route handler that matches the current path, if\n\t * any.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tdispatch() {\n\t\treturn this.navigate(utils.getCurrentBrowserPath(), true);\n\t}\n\n\t/**\n\t * Starts navigation to a path.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tdoNavigate_(path, opt_replaceHistory) {\n\t\tvar route = this.findRoute(path);\n\t\tif (!route) {\n\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('No route for ' + path));\n\t\t\treturn this.pendingNavigate;\n\t\t}\n\n\t\tconsole.log('Navigate to [' + path + ']');\n\n\t\tthis.stopPendingNavigate_();\n\t\tthis.isNavigationPending = true;\n\n\t\tvar nextScreen = this.createScreenInstance(path, route);\n\n\t\treturn this.maybePreventDeactivate_()\n\t\t\t.then(() => this.maybePreventActivate_(nextScreen))\n\t\t\t.then(() => nextScreen.load(path))\n\t\t\t.then(() => {\n\t\t\t\t// At this point we cannot stop navigation and all received\n\t\t\t\t// navigate candidates will be queued at scheduledNavigationQueue.\n\t\t\t\tthis.navigationStrategy = NavigationStrategy.SCHEDULE_LAST;\n\n\t\t\t\tif (this.activeScreen) {\n\t\t\t\t\tthis.activeScreen.deactivate();\n\t\t\t\t}\n\t\t\t\tthis.prepareNavigateHistory_(path, nextScreen, opt_replaceHistory);\n\t\t\t\tthis.prepareNavigateSurfaces_(\n\t\t\t\t\tnextScreen,\n\t\t\t\t\tthis.surfaces,\n\t\t\t\t\tthis.extractParams(route, path)\n\t\t\t\t);\n\t\t\t})\n\t\t\t.then(() => nextScreen.evaluateStyles(this.surfaces))\n\t\t\t.then(() => nextScreen.flip(this.surfaces))\n\t\t\t.then(() => nextScreen.evaluateScripts(this.surfaces))\n\t\t\t.then(() => this.maybeUpdateScrollPositionState_())\n\t\t\t.then(() => this.syncScrollPositionSyncThenAsync_())\n\t\t\t.then(() => this.finalizeNavigate_(path, nextScreen))\n\t\t\t.then(() => this.maybeOverloadBeforeUnload_())\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.isNavigationPending = false;\n\t\t\t\tthis.handleNavigateError_(path, nextScreen, reason);\n\t\t\t\tthrow reason;\n\t\t\t})\n\t\t\t.thenAlways(() => {\n\t\t\t\tthis.navigationStrategy = NavigationStrategy.IMMEDIATE;\n\n\t\t\t\tif (this.scheduledNavigationQueue.length) {\n\t\t\t\t\tconst scheduledNavigation = this.scheduledNavigationQueue.shift();\n\t\t\t\t\tthis.maybeNavigate_(scheduledNavigation.href, scheduledNavigation);\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Extracts params according to the given path and route.\n\t * @param {!Route} route\n\t * @param {string} path\n\t * @param {!Object}\n\t */\n\textractParams(route, path) {\n\t\treturn route.extractParams(this.getRoutePath(path));\n\t}\n\n\t/**\n\t * Finalizes a screen navigation.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @protected\n\t */\n\tfinalizeNavigate_(path, nextScreen) {\n\t\tnextScreen.activate();\n\n\t\tif (this.activeScreen && !this.activeScreen.isCacheable()) {\n\t\t\tif (this.activeScreen !== nextScreen) {\n\t\t\t\tthis.removeScreen(this.activePath);\n\t\t\t}\n\t\t}\n\n\t\tthis.activePath = path;\n\t\tthis.activeScreen = nextScreen;\n\t\tthis.browserPathBeforeNavigate = utils.getCurrentBrowserPathWithoutHash();\n\t\tthis.screens[path] = nextScreen;\n\t\tthis.isNavigationPending = false;\n\t\tthis.pendingNavigate = null;\n\t\tglobals.capturedFormElement = null;\n\t\tglobals.capturedFormButtonElement = null;\n\t\tconsole.log('Navigation done');\n\t}\n\n\t/**\n\t * Finds a route for the test path. Returns true if matches has a route,\n\t * otherwise returns null.\n\t * @param {!string} path Path containing the querystring part.\n\t * @return {?Object} Route handler if match any or <code>null</code> if the\n\t * path is the same as the current url and the path contains a fragment.\n\t */\n\tfindRoute(path) {\n\t\tpath = this.getRoutePath(path);\n\t\tfor (var i = 0; i < this.routes.length; i++) {\n\t\t\tvar route = this.routes[i];\n\t\t\tif (route.matchesPath(path)) {\n\t\t\t\treturn route;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Gets allow prevent navigate.\n\t * @return {boolean}\n\t */\n\tgetAllowPreventNavigate() {\n\t\treturn this.allowPreventNavigate;\n\t}\n\n\t/**\n\t * Gets link base path.\n\t * @return {!string}\n\t */\n\tgetBasePath() {\n\t\treturn this.basePath;\n\t}\n\n\t/**\n\t * Gets the default page title.\n\t * @return {string} defaultTitle\n\t */\n\tgetDefaultTitle() {\n\t\treturn this.defaultTitle;\n\t}\n\n\t/**\n\t * Gets the form selector.\n\t * @return {!string}\n\t */\n\tgetFormSelector() {\n\t\treturn this.formSelector;\n\t}\n\n\t/**\n\t * Check if route matching is ignoring query string from the route path.\n\t * @return {boolean}\n\t */\n\tgetIgnoreQueryStringFromRoutePath() {\n\t\treturn this.ignoreQueryStringFromRoutePath;\n\t}\n\n\t/**\n\t * Gets the link selector.\n\t * @return {!string}\n\t */\n\tgetLinkSelector() {\n\t\treturn this.linkSelector;\n\t}\n\n\t/**\n\t * Gets the loading css class.\n\t * @return {!string}\n\t */\n\tgetLoadingCssClass() {\n\t\treturn this.loadingCssClass;\n\t}\n\n\t/**\n\t * Returns the given path formatted to be matched by a route. This will,\n\t * for example, remove the base path from it, but make sure it will end\n\t * with a '/'.\n\t * @param {string} path\n\t * @return {string}\n\t */\n\tgetRoutePath(path) {\n\t\tif (this.getIgnoreQueryStringFromRoutePath()) {\n\t\t\tpath = utils.getUrlPathWithoutHashAndSearch(path);\n\t\t\treturn utils.getUrlPathWithoutHashAndSearch(path.substr(this.basePath.length));\n\t\t}\n\n\t\tpath = utils.getUrlPathWithoutHash(path);\n\t\treturn utils.getUrlPathWithoutHash(path.substr(this.basePath.length));\n\t}\n\n\t/**\n\t * Gets the update scroll position value.\n\t * @return {boolean}\n\t */\n\tgetUpdateScrollPosition() {\n\t\treturn this.updateScrollPosition;\n\t}\n\n\t/**\n\t * Handle navigation error.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @param {!Error} error\n\t * @protected\n\t */\n\thandleNavigateError_(path, nextScreen, error) {\n\t\tconsole.log('Navigation error for [' + nextScreen + '] (' + error.stack + ')');\n\t\tthis.emit('navigationError', {\n\t\t\terror,\n\t\t\tnextScreen,\n\t\t\tpath\n\t\t});\n\t\tif (!utils.isCurrentBrowserPath(path)) {\n\t\t\tif (this.isNavigationPending && this.pendingNavigate) {\n\t\t\t\tthis.pendingNavigate.thenAlways(() => this.removeScreen(path), this);\n\t\t\t} else {\n\t\t\t\tthis.removeScreen(path);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if app has routes.\n\t * @return {boolean}\n\t */\n\thasRoutes() {\n\t\treturn this.routes.length > 0;\n\t}\n\n\t/**\n\t * Tests if host is an offsite link.\n\t * @param {!string} host Link host to compare with\n\t * <code>globals.window.location.host</code>.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisLinkSameOrigin_(host) {\n\t\tconst hostUri = new Uri(host);\n\t\tconst locationHostUri = new Uri(globals.window.location.host);\n\n\t\treturn hostUri.getPort() === locationHostUri.getPort() && hostUri.getHostname() === locationHostUri.getHostname();\n\t}\n\n\t/**\n\t * Tests if link element has the same app's base path.\n\t * @param {!string} path Link path containing the querystring part.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisSameBasePath_(path) {\n\t\treturn path.indexOf(this.basePath) === 0;\n\t}\n\n\t/**\n\t * Lock the document scroll in order to avoid the browser native back and\n\t * forward navigation to change the scroll position. In the end of\n\t * navigation lifecycle scroll is repositioned.\n\t * @protected\n\t */\n\tlockHistoryScrollPosition_() {\n\t\tvar state = globals.window.history.state;\n\t\tif (!state) {\n\t\t\treturn;\n\t\t}\n\t\t// Browsers are inconsistent when re-positioning the scroll history on\n\t\t// popstate. At some browsers, history scroll happens before popstate, then\n\t\t// lock the scroll on the last known position as soon as possible after the\n\t\t// current JS execution context and capture the current value. Some others,\n\t\t// history scroll happens after popstate, in this case, we bind an once\n\t\t// scroll event to lock the las known position. Lastly, the previous two\n\t\t// behaviors can happen even on the same browser, hence the race will decide\n\t\t// the winner.\n\t\tvar winner = false;\n\t\tvar switchScrollPositionRace = function() {\n\t\t\tglobals.document.removeEventListener('scroll', switchScrollPositionRace, false);\n\t\t\tif (!winner) {\n\t\t\t\tglobals.window.scrollTo(state.scrollLeft, state.scrollTop);\n\t\t\t\twinner = true;\n\t\t\t}\n\t\t};\n\t\tasync.nextTick(switchScrollPositionRace);\n\t\tglobals.document.addEventListener('scroll', switchScrollPositionRace, false);\n\t}\n\n\t/**\n\t * If supported by the browser, disables native scroll restoration and\n\t * stores current value.\n\t */\n\tmaybeDisableNativeScrollRestoration() {\n\t\tif (this.nativeScrollRestorationSupported) {\n\t\t\tthis.nativeScrollRestoration_ = globals.window.history.scrollRestoration;\n\t\t\tglobals.window.history.scrollRestoration = 'manual';\n\t\t}\n\t}\n\n\t/**\n\t * This method is used to evaluate if is possible to queue received\n\t * dom event to scheduleNavigationQueue and enqueue it.\n\t * @param {string} href Information about the link's href.\n\t * @param {Event} event Dom event that initiated the navigation.\n\t */\n\tmaybeScheduleNavigation_(href, event) {\n\t\tif (this.isNavigationPending && this.navigationStrategy === NavigationStrategy.SCHEDULE_LAST) {\n\t\t\tthis.scheduledNavigationQueue = [object.mixin({\n\t\t\t\thref,\n\t\t\t\tisScheduledNavigation: true\n\t\t\t}, event)];\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Maybe navigate to a path.\n\t * @param {string} href Information about the link's href.\n\t * @param {Event} event Dom event that initiated the navigation.\n\t */\n\tmaybeNavigate_(href, event) {\n\t\tif (!this.canNavigate(href)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isNavigationScheduled = this.maybeScheduleNavigation_(href, event);\n\n\t\tif (isNavigationScheduled) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tvar navigateFailed = false;\n\t\ttry {\n\t\t\tthis.navigate(utils.getUrlPath(href), false, event);\n\t\t} catch (err) {\n\t\t\t// Do not prevent link navigation in case some synchronous error occurs\n\t\t\tnavigateFailed = true;\n\t\t}\n\n\t\tif (!navigateFailed && !event.isScheduledNavigation) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether the onbeforeunload global event handler is overloaded\n\t * by client code. If so, it replaces with a function that halts the normal\n\t * event flow in relation with the client onbeforeunload function.\n\t * This can be in most part used to prematurely terminate navigation to other pages\n\t * according to the given constrait(s).\n\t * @protected\n\t */\n\tmaybeOverloadBeforeUnload_() {\n\t\tif ('function' === typeof window.onbeforeunload) {\n\t\t\twindow._onbeforeunload = window.onbeforeunload;\n\n\t\t\twindow.onbeforeunload = event => {\n\t\t\t\tthis.emit('beforeUnload', event);\n\t\t\t\tif (event && event.defaultPrevented) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// mark the updated handler due unwanted recursion\n\t\t\twindow.onbeforeunload._overloaded = true;\n\t\t}\n\t}\n\n\t/**\n\t * Cancels navigation if nextScreen's beforeActivate lifecycle method\n\t * resolves to true.\n\t * @param {!Screen} nextScreen\n\t * @return {!CancellablePromise}\n\t */\n\tmaybePreventActivate_(nextScreen) {\n\t\treturn CancellablePromise.resolve()\n\t\t\t.then(() => {\n\t\t\t\treturn nextScreen.beforeActivate();\n\t\t\t})\n\t\t\t.then(prevent => {\n\t\t\t\tif (prevent) {\n\t\t\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by next screen'));\n\t\t\t\t\treturn this.pendingNavigate;\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Cancels navigation if activeScreen's beforeDeactivate lifecycle\n\t * method resolves to true.\n\t * @return {!CancellablePromise}\n\t */\n\tmaybePreventDeactivate_() {\n\t\treturn CancellablePromise.resolve()\n\t\t\t.then(() => {\n\t\t\t\tif (this.activeScreen) {\n\t\t\t\t\treturn this.activeScreen.beforeDeactivate();\n\t\t\t\t}\n\t\t\t})\n\t\t\t.then(prevent => {\n\t\t\t\tif (prevent) {\n\t\t\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by active screen'));\n\t\t\t\t\treturn this.pendingNavigate;\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Maybe reposition scroll to hashed anchor.\n\t */\n\tmaybeRepositionScrollToHashedAnchor() {\n\t\tconst hash = globals.window.location.hash;\n\t\tif (hash) {\n\t\t\tlet anchorElement = globals.document.getElementById(hash.substring(1));\n\t\t\tif (anchorElement) {\n\t\t\t\tconst {offsetLeft, offsetTop} = utils.getNodeOffset(anchorElement);\n\t\t\t\tglobals.window.scrollTo(offsetLeft, offsetTop);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * If supported by the browser, restores native scroll restoration to the\n\t * value captured by `maybeDisableNativeScrollRestoration`.\n\t */\n\tmaybeRestoreNativeScrollRestoration() {\n\t\tif (this.nativeScrollRestorationSupported && this.nativeScrollRestoration_) {\n\t\t\tglobals.window.history.scrollRestoration = this.nativeScrollRestoration_;\n\t\t}\n\t}\n\n\t/**\n\t * Maybe restore redirected path hash in case both the current path and\n\t * the given path are the same.\n\t * @param {!string} path Path before navigation.\n\t * @param {!string} redirectPath Path after navigation.\n\t * @param {!string} hash Hash to be added to the path.\n\t * @return {!string} Returns the path with the hash restored.\n\t */\n\tmaybeRestoreRedirectPathHash_(path, redirectPath, hash) {\n\t\tif (redirectPath === utils.getUrlPathWithoutHash(path)) {\n\t\t\treturn redirectPath + hash;\n\t\t}\n\t\treturn redirectPath;\n\t}\n\n\t/**\n\t * Maybe update scroll position in history state to anchor on path.\n\t * @param {!string} path Path containing anchor\n\t */\n\tmaybeUpdateScrollPositionState_() {\n\t\tvar hash = globals.window.location.hash;\n\t\tvar anchorElement = globals.document.getElementById(hash.substring(1));\n\t\tif (anchorElement) {\n\t\t\tconst {offsetLeft, offsetTop} = utils.getNodeOffset(anchorElement);\n\t\t\tthis.saveHistoryCurrentPageScrollPosition_(offsetTop, offsetLeft);\n\t\t}\n\t}\n\n\t/**\n\t * Navigates to the specified path if there is a route handler that matches.\n\t * @param {!string} path Path to navigate containing the base path.\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @param {Event=} event Optional event object that triggered the navigation.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tnavigate(path, opt_replaceHistory, opt_event) {\n\t\tif (!utils.isHtml5HistorySupported()) {\n\t\t\tthrow new Error('HTML5 History is not supported. Senna will not intercept navigation.');\n\t\t}\n\n\t\tif (opt_event) {\n\t\t\tglobals.capturedFormElement = opt_event.capturedFormElement;\n\t\t\tglobals.capturedFormButtonElement = opt_event.capturedFormButtonElement;\n\t\t}\n\n\t\t// When reloading the same path do replaceState instead of pushState to\n\t\t// avoid polluting history with states with the same path.\n\t\tif (path === this.activePath) {\n\t\t\topt_replaceHistory = true;\n\t\t}\n\n\t\tthis.emit('beforeNavigate', {\n\t\t\tevent: opt_event,\n\t\t\tpath: path,\n\t\t\treplaceHistory: !!opt_replaceHistory\n\t\t});\n\n\t\treturn this.pendingNavigate;\n\t}\n\n\t/**\n\t * Befores navigation to a path.\n\t * @param {!Event} event Event facade containing <code>path</code> and\n\t * <code>replaceHistory</code>.\n\t * @protected\n\t */\n\tonBeforeNavigate_(event) {\n\t\tif (globals.capturedFormElement) {\n\t\t\tevent.form = globals.capturedFormElement;\n\t\t}\n\t}\n\n\t/**\n\t * Befores navigation to a path. Runs after external listeners.\n\t * @param {!Event} event Event facade containing <code>path</code> and\n\t * <code>replaceHistory</code>.\n\t * @protected\n\t */\n\tonBeforeNavigateDefault_(event) {\n\t\tif (this.pendingNavigate) {\n\t\t\tif (this.pendingNavigate.path === event.path || this.navigationStrategy === NavigationStrategy.SCHEDULE_LAST) {\n\t\t\t\tconsole.log('Waiting...');\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.emit('beforeUnload', event);\n\n\t\tthis.emit('startNavigate', {\n\t\t\tform: event.form,\n\t\t\tpath: event.path,\n\t\t\treplaceHistory: event.replaceHistory\n\t\t});\n\t}\n\n\t/**\n\t * Custom event handler that executes the original listener that has been\n\t * added by the client code and terminates the navigation accordingly.\n\t * @param {!Event} event original Event facade.\n\t * @protected\n\t */\n\tonBeforeUnloadDefault_(event) {\n\t\tvar func = window._onbeforeunload;\n\t\tif (func && !func._overloaded && func()) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\t/**\n\t * Intercepts document clicks and test link elements in order to decide\n\t * whether Surface app can navigate.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonDocClickDelegate_(event) {\n\t\tif (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.button) {\n\t\t\tconsole.log('Navigate aborted, invalid mouse button or modifier key pressed.');\n\t\t\treturn;\n\t\t}\n\t\tthis.maybeNavigate_(event.delegateTarget.href, event);\n\t}\n\n\t/**\n\t * Intercepts document form submits and test action path in order to decide\n\t * whether Surface app can navigate.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonDocSubmitDelegate_(event) {\n\t\tvar form = event.delegateTarget;\n\t\tif (form.method === 'get') {\n\t\t\tconsole.log('GET method not supported');\n\t\t\treturn;\n\t\t}\n\t\tevent.capturedFormElement = form;\n\t\tconst buttonSelector = 'button:not([type]),button[type=submit],input[type=submit]';\n\t\tif (match(globals.document.activeElement, buttonSelector)) {\n\t\t\tevent.capturedFormButtonElement = globals.document.activeElement;\n\t\t} else {\n\t\t\tevent.capturedFormButtonElement = form.querySelector(buttonSelector);\n\t\t}\n\t\tthis.maybeNavigate_(form.action, event);\n\t}\n\n\t/**\n\t * Listens to the window's load event in order to avoid issues with some browsers\n\t * that trigger popstate calls on the first load. For more information see\n\t * http://stackoverflow.com/questions/6421769/popstate-on-pages-load-in-chrome.\n\t * @protected\n\t */\n\tonLoad_() {\n\t\tthis.skipLoadPopstate = true;\n\t\tsetTimeout(() => {\n\t\t\t// The timeout ensures that popstate events will be unblocked right\n\t\t\t// after the load event occured, but not in the same event-loop cycle.\n\t\t\tthis.skipLoadPopstate = false;\n\t\t}, 0);\n\t\t// Try to reposition scroll to the hashed anchor when page loads.\n\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t}\n\n\t/**\n\t * Handles browser history changes and fires app's navigation if the state\n\t * belows to us. If we detect a popstate and the state is <code>null</code>,\n\t * assume it is navigating to an external page or to a page we don't have\n\t * route, then <code>globals.window.location.reload()</code> is invoked in order to\n\t * reload the content to the current url.\n\t * @param {!Event} event Event facade\n\t * @protected\n\t */\n\tonPopstate_(event) {\n\t\tif (this.skipLoadPopstate) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Do not navigate if the popstate was triggered by a hash change.\n\t\tif (utils.isCurrentBrowserPath(this.browserPathBeforeNavigate)) {\n\t\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t\t\treturn;\n\t\t}\n\n\t\tvar state = event.state;\n\n\t\tif (!state) {\n\t\t\tif (globals.window.location.hash) {\n\t\t\t\t// If senna is on an redirect path and a hash popstate happens\n\t\t\t\t// to a different url, reload the browser. This behavior doesn't\n\t\t\t\t// require senna to route hashed links and is closer to native\n\t\t\t\t// browser behavior.\n\t\t\t\tif (this.redirectPath && !utils.isCurrentBrowserPath(this.redirectPath)) {\n\t\t\t\t\tthis.reloadPage();\n\t\t\t\t}\n\t\t\t\t// Always try to reposition scroll to the hashed anchor when\n\t\t\t\t// hash popstate happens.\n\t\t\t\tthis.maybeRepositionScrollToHashedAnchor();\n\t\t\t} else {\n\t\t\t\tthis.reloadPage();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (state.senna) {\n\t\t\tconsole.log('History navigation to [' + state.path + ']');\n\t\t\tthis.popstateScrollTop = state.scrollTop;\n\t\t\tthis.popstateScrollLeft = state.scrollLeft;\n\t\t\tif (!this.nativeScrollRestorationSupported) {\n\t\t\t\tthis.lockHistoryScrollPosition_();\n\t\t\t}\n\t\t\tthis.once('endNavigate', () => {\n\t\t\t\tif (state.referrer) {\n\t\t\t\t\tutils.setReferrer(state.referrer);\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst uri = new Uri(state.path);\n\t\t\turi.setHostname(globals.window.location.hostname);\n\t\t\turi.setPort(globals.window.location.port);\n\t\t\tconst isNavigationScheduled = this.maybeScheduleNavigation_(uri.toString(), {});\n\t\t\tif (isNavigationScheduled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.navigate(state.path, true);\n\t\t}\n\t}\n\n\t/**\n\t * Listens document scroll changes in order to capture the possible lock\n\t * scroll position for history scrolling.\n\t * @protected\n\t */\n\tonScroll_() {\n\t\tif (this.captureScrollPositionFromScrollEvent) {\n\t\t\tthis.saveHistoryCurrentPageScrollPosition_(globals.window.pageYOffset, globals.window.pageXOffset);\n\t\t}\n\t}\n\n\t/**\n\t * Starts navigation to a path.\n\t * @param {!Event} event Event facade containing <code>path</code> and\n\t * <code>replaceHistory</code>.\n\t * @protected\n\t */\n\tonStartNavigate_(event) {\n\t\tthis.maybeDisableNativeScrollRestoration();\n\t\tthis.captureScrollPositionFromScrollEvent = false;\n\t\taddClasses(globals.document.documentElement, this.loadingCssClass);\n\n\t\tvar endNavigatePayload = {\n\t\t\tform: event.form,\n\t\t\tpath: event.path\n\t\t};\n\n\t\tthis.pendingNavigate = this.doNavigate_(event.path, event.replaceHistory)\n\t\t\t.catch((reason) => {\n\t\t\t\tendNavigatePayload.error = reason;\n\t\t\t\tthrow reason;\n\t\t\t})\n\t\t\t.thenAlways(() => {\n\t\t\t\tif (!this.pendingNavigate && !this.scheduledNavigationQueue.length) {\n\t\t\t\t\tremoveClasses(globals.document.documentElement, this.loadingCssClass);\n\t\t\t\t\tthis.maybeRestoreNativeScrollRestoration();\n\t\t\t\t\tthis.captureScrollPositionFromScrollEvent = true;\n\t\t\t\t}\n\t\t\t\tthis.emit('endNavigate', endNavigatePayload);\n\t\t\t});\n\n\t\tthis.pendingNavigate.path = event.path;\n\t}\n\n\t/**\n\t * Prefetches the specified path if there is a route handler that matches.\n\t * @param {!string} path Path to navigate containing the base path.\n\t * @return {CancellablePromise} Returns a pending request cancellable promise.\n\t */\n\tprefetch(path) {\n\t\tvar route = this.findRoute(path);\n\t\tif (!route) {\n\t\t\treturn CancellablePromise.reject(new CancellablePromise.CancellationError('No route for ' + path));\n\t\t}\n\n\t\tconsole.log('Prefetching [' + path + ']');\n\n\t\tvar nextScreen = this.createScreenInstance(path, route);\n\n\t\treturn nextScreen.load(path)\n\t\t\t.then(() => this.screens[path] = nextScreen)\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.handleNavigateError_(path, nextScreen, reason);\n\t\t\t\tthrow reason;\n\t\t\t});\n\t}\n\n\t/**\n\t * Prepares screen flip. Updates history state and surfaces content.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!Screen} nextScreen\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t */\n\tprepareNavigateHistory_(path, nextScreen, opt_replaceHistory) {\n\t\tlet title = nextScreen.getTitle();\n\t\tif (!isString(title)) {\n\t\t\ttitle = this.getDefaultTitle();\n\t\t}\n\t\tlet redirectPath = nextScreen.beforeUpdateHistoryPath(path);\n\t\tconst hash = new Uri(path).getHash();\n\t\tredirectPath = this.maybeRestoreRedirectPathHash_(path, redirectPath, hash);\n\t\tconst historyState = {\n\t\t\tform: isDefAndNotNull(globals.capturedFormElement),\n\t\t\tpath,\n\t\t\tredirectPath,\n\t\t\tscrollLeft: 0,\n\t\t\tscrollTop: 0,\n\t\t\tsenna: true\n\t\t};\n\t\tif (opt_replaceHistory) {\n\t\t\thistoryState.scrollTop = this.popstateScrollTop;\n\t\t\thistoryState.scrollLeft = this.popstateScrollLeft;\n\t\t}\n\t\tthis.updateHistory_(title, redirectPath, nextScreen.beforeUpdateHistoryState(historyState), opt_replaceHistory);\n\t\tthis.redirectPath = redirectPath;\n\t}\n\n\t/**\n\t * Prepares screen flip. Updates history state and surfaces content.\n\t * @param {!Screen} nextScreen\n\t * @param {!Object} surfaces Map of surfaces to flip keyed by surface id.\n\t * @param {!Object} params Params extracted from the current path.\n\t */\n\tprepareNavigateSurfaces_(nextScreen, surfaces, params) {\n\t\tObject.keys(surfaces).forEach((id) => {\n\t\t\tvar surfaceContent = nextScreen.getSurfaceContent(id, params);\n\t\t\tsurfaces[id].addContent(nextScreen.getId(), surfaceContent);\n\t\t\tconsole.log('Screen [' + nextScreen.getId() + '] add content to surface ' +\n\t\t\t\t'[' + surfaces[id] + '] [' + (isDefAndNotNull(surfaceContent) ? '...' : 'empty') + ']');\n\t\t});\n\t}\n\n\t/**\n\t * Reloads the page by performing `window.location.reload()`.\n\t */\n\treloadPage() {\n\t\tglobals.window.location.reload();\n\t}\n\n\t/**\n\t * Removes route instance from app routes.\n\t * @param {Route} route\n\t * @return {boolean} True if an element was removed.\n\t */\n\tremoveRoute(route) {\n\t\treturn array.remove(this.routes, route);\n\t}\n\n\t/**\n\t * Removes a screen.\n\t * @param {!string} path Path containing the querystring part.\n\t */\n\tremoveScreen(path) {\n\t\tvar screen = this.screens[path];\n\t\tif (screen) {\n\t\t\tObject.keys(this.surfaces).forEach((surfaceId) => this.surfaces[surfaceId].remove(screen.getId()));\n\t\t\tscreen.dispose();\n\t\t\tdelete this.screens[path];\n\t\t}\n\t}\n\n\t/**\n\t * Saves given scroll position into history state.\n\t * @param {!number} scrollTop Number containing the top scroll position to be saved.\n\t * @param {!number} scrollLeft Number containing the left scroll position to be saved.\n\t */\n\tsaveHistoryCurrentPageScrollPosition_(scrollTop, scrollLeft) {\n\t\tvar state = globals.window.history.state;\n\t\tif (state && state.senna) {\n\t\t\t[state.scrollTop, state.scrollLeft] = [scrollTop, scrollLeft];\n\t\t\tglobals.window.history.replaceState(state, null, null);\n\t\t}\n\t}\n\n\t/**\n\t * Sets allow prevent navigate.\n\t * @param {boolean} allowPreventNavigate\n\t */\n\tsetAllowPreventNavigate(allowPreventNavigate) {\n\t\tthis.allowPreventNavigate = allowPreventNavigate;\n\t}\n\n\t/**\n\t * Sets link base path.\n\t * @param {!string} path\n\t */\n\tsetBasePath(basePath) {\n\t\tthis.basePath = utils.removePathTrailingSlash(basePath);\n\t}\n\n\t/**\n\t * Sets the default page title.\n\t * @param {string} defaultTitle\n\t */\n\tsetDefaultTitle(defaultTitle) {\n\t\tthis.defaultTitle = defaultTitle;\n\t}\n\n\t/**\n\t * Sets the form selector.\n\t * @param {!string} formSelector\n\t */\n\tsetFormSelector(formSelector) {\n\t\tthis.formSelector = formSelector;\n\t\tif (this.formEventHandler_) {\n\t\t\tthis.formEventHandler_.removeListener();\n\t\t}\n\t\tthis.formEventHandler_ = delegate(document, 'submit', this.formSelector, this.onDocSubmitDelegate_.bind(this), this.allowPreventNavigate);\n\t}\n\n\t/**\n\t * Sets if route matching should ignore query string from the route path.\n\t * @param {boolean} ignoreQueryStringFromRoutePath\n\t */\n\tsetIgnoreQueryStringFromRoutePath(ignoreQueryStringFromRoutePath) {\n\t\tthis.ignoreQueryStringFromRoutePath = ignoreQueryStringFromRoutePath;\n\t}\n\n\t/**\n\t * Sets the link selector.\n\t * @param {!string} linkSelector\n\t */\n\tsetLinkSelector(linkSelector) {\n\t\tthis.linkSelector = linkSelector;\n\t\tif (this.linkEventHandler_) {\n\t\t\tthis.linkEventHandler_.removeListener();\n\t\t}\n\t\tthis.linkEventHandler_ = delegate(document, 'click', this.linkSelector, this.onDocClickDelegate_.bind(this), this.allowPreventNavigate);\n\t}\n\n\t/**\n\t * Sets the loading css class.\n\t * @param {!string} loadingCssClass\n\t */\n\tsetLoadingCssClass(loadingCssClass) {\n\t\tthis.loadingCssClass = loadingCssClass;\n\t}\n\n\t/**\n\t * Sets the update scroll position value.\n\t * @param {boolean} updateScrollPosition\n\t */\n\tsetUpdateScrollPosition(updateScrollPosition) {\n\t\tthis.updateScrollPosition = updateScrollPosition;\n\t}\n\n\t/**\n\t * Cancels pending navigate with <code>Cancel pending navigation</code> error.\n\t * @protected\n\t */\n\tstopPendingNavigate_() {\n\t\tif (this.pendingNavigate) {\n\t\t\tthis.pendingNavigate.cancel('Cancel pending navigation');\n\t\t}\n\t\tthis.pendingNavigate = null;\n\t}\n\n\t/**\n\t * Sync document scroll position twice, the first one synchronous and then\n\t * one inside <code>async.nextTick</code>. Relevant to browsers that fires\n\t * scroll restoration asynchronously after popstate.\n\t * @protected\n\t * @return {?CancellablePromise=}\n\t */\n\tsyncScrollPositionSyncThenAsync_() {\n\t\tvar state = globals.window.history.state;\n\t\tif (!state) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar scrollTop = state.scrollTop;\n\t\tvar scrollLeft = state.scrollLeft;\n\n\t\tvar sync = () => {\n\t\t\tif (this.updateScrollPosition) {\n\t\t\t\tglobals.window.scrollTo(scrollLeft, scrollTop);\n\t\t\t}\n\t\t};\n\n\t\treturn new CancellablePromise((resolve) => sync() & async.nextTick(() => sync() & resolve()));\n\t}\n\n\t/**\n\t * Updates or replace browser history.\n\t * @param {?string} title Document title.\n\t * @param {!string} path Path containing the querystring part.\n\t * @param {!object} state\n\t * @param {boolean=} opt_replaceHistory Replaces browser history.\n\t * @protected\n\t */\n\tupdateHistory_(title, path, state, opt_replaceHistory) {\n\t\tconst referrer = globals.window.location.href;\n\n\t\tif (state) {\n\t\t\tstate.referrer = referrer;\n\t\t}\n\n\t\tif (opt_replaceHistory) {\n\t\t\tglobals.window.history.replaceState(state, title, path);\n\t\t} else {\n\t\t\tglobals.window.history.pushState(state, title, path);\n\t\t}\n\n\t\tutils.setReferrer(referrer);\n\n\t\tlet titleNode = globals.document.querySelector('title');\n\t\tif (titleNode) {\n\t\t\ttitleNode.innerHTML = title;\n\t\t} else {\n\t\t\tglobals.document.title = title;\n\t\t}\n\t}\n\n}\n\nexport default App;\n","'use strict';\n\nimport { isDef, isDefAndNotNull } from 'metal';\nimport Uri from 'metal-uri';\nimport { CancellablePromise as Promise } from 'metal-promise';\n\nclass Ajax {\n\n\t/**\n\t * XmlHttpRequest's getAllResponseHeaders() method returns a string of\n\t * response headers according to the format described on the spec:\n\t * {@link http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method}.\n\t * This method parses that string into a user-friendly name/value pair\n\t * object.\n\t * @param {string} allHeaders All headers as string.\n\t * @return {!Array.<Object<string, string>>}\n\t */\n\tstatic parseResponseHeaders(allHeaders) {\n\t\tvar headers = [];\n\t\tif (!allHeaders) {\n\t\t\treturn headers;\n\t\t}\n\t\tvar pairs = allHeaders.split('\\u000d\\u000a');\n\t\tfor (var i = 0; i < pairs.length; i++) {\n\t\t\tvar index = pairs[i].indexOf('\\u003a\\u0020');\n\t\t\tif (index > 0) {\n\t\t\t\tvar name = pairs[i].substring(0, index);\n\t\t\t\tvar value = pairs[i].substring(index + 2);\n\t\t\t\theaders.push({\n\t\t\t\t\tname: name,\n\t\t\t\t\tvalue: value\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn headers;\n\t}\n\n\t/**\n\t * Requests the url using XMLHttpRequest.\n\t * @param {!string} url\n\t * @param {!string} method\n\t * @param {?string} body\n\t * @param {MultiMap=} opt_headers\n\t * @param {MultiMap=} opt_params\n\t * @param {number=} opt_timeout\n\t * @param {boolean=} opt_sync\n\t * @param {boolean=} opt_withCredentials\n\t * @return {Promise} Deferred ajax request.\n\t * @protected\n\t */\n\tstatic request(url, method, body, opt_headers, opt_params, opt_timeout, opt_sync, opt_withCredentials) {\n\t\turl = url || '';\n\t\tmethod = method || 'GET';\n\n\t\tvar request = new XMLHttpRequest();\n\t\tvar previousReadyState = 0;\n\n\t\tvar promise = new Promise(function(resolve, reject) {\n\t\t\trequest.onload = function() {\n\t\t\t\tif (request.aborted) {\n\t\t\t\t\trequest.onerror();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tresolve(request);\n\t\t\t};\n\t\t\trequest.onreadystatechange = function() {\n\t\t\t\tif (previousReadyState && previousReadyState < 3 && 4 === request.readyState) {\n\t\t\t\t\trequest.terminatedPrematurely = true;\n\t\t\t\t}\n\t\t\t\tpreviousReadyState = request.readyState;\n\t\t\t};\n\t\t\trequest.onerror = function() {\n\t\t\t\tvar message = 'Request error';\n\t\t\t\tif (request.terminatedPrematurely) {\n\t\t\t\t\tmessage = 'Request terminated prematurely';\n\t\t\t\t} \n\t\t\t\tvar error = new Error(message);\n\t\t\t\terror.request = request;\n\t\t\t\treject(error);\n\t\t\t};\n\t\t}).thenCatch(function(reason) {\n\t\t\trequest.abort();\n\t\t\tthrow reason;\n\t\t}).thenAlways(function() {\n\t\t\tclearTimeout(timeout);\n\t\t});\n\n\t\turl = new Uri(url);\n\n\t\tif (opt_params) {\n\t\t\turl.addParametersFromMultiMap(opt_params).toString();\n\t\t}\n\n\t\turl = url.toString();\n\n\t\trequest.open(method, url, !opt_sync);\n\n\t\tif (opt_withCredentials) {\n\t\t\trequest.withCredentials = true;\n\t\t}\n\n\t\tif (opt_headers) {\n\t\t\topt_headers.names().forEach(function(name) {\n\t\t\t\trequest.setRequestHeader(name, opt_headers.getAll(name).join(', '));\n\t\t\t});\n\t\t}\n\n\t\trequest.send(isDef(body) ? body : null);\n\n\t\tif (isDefAndNotNull(opt_timeout)) {\n\t\t\tvar timeout = setTimeout(function() {\n\t\t\t\tpromise.cancel('Request timeout');\n\t\t\t}, opt_timeout);\n\t\t}\n\n\t\treturn promise;\n\t}\n\n}\n\nexport default Ajax;\n","'use strict';\n\n/**\n * Holds value error messages.\n * @const\n */\nclass errors {\n}\n\n/**\n * Invalid status error message.\n * @type {string}\n * @static\n */\nerrors.INVALID_STATUS = 'Invalid status code';\n\n/**\n * Request error message.\n * @type {string}\n * @static\n */\nerrors.REQUEST_ERROR = 'Request error';\n\n/**\n * Request timeout error message.\n * @type {string}\n * @static\n */\nerrors.REQUEST_TIMEOUT = 'Request timeout';\n\n/**\n * Request is blocked by CORS issue message.\n * @type {string}\n * @static\n */\nerrors.REQUEST_PREMATURE_TERMINATION = 'Request terminated prematurely';\n\nexport default errors;\n","'use strict';\n\nimport {isServerSide} from 'metal';\n\n/**\n * Metal.js browser user agent detection. It's extremely recommended the usage\n * of feature checking over browser user agent sniffing. Unfortunately, in some\n * situations feature checking can be slow or even impossible, therefore use\n * this utility with caution.\n * @see <a href=\"http://www.useragentstring.com/\">User agent strings</a>.\n */\nclass UA {\n\t/**\n\t * Gets the native userAgent string from navigator if it exists. If\n\t * navigator or navigator.userAgent string is missing, returns an empty\n\t * string.\n\t * @return {string}\n\t * @private\n\t * @static\n\t */\n\tstatic getNativeUserAgent() {\n\t\tlet navigator = UA.globals.window && UA.globals.window.navigator;\n\t\tif (navigator) {\n\t\t\tlet userAgent = navigator.userAgent;\n\t\t\tif (userAgent) {\n\t\t\t\treturn userAgent;\n\t\t\t}\n\t\t}\n\t\treturn '';\n\t}\n\n\t/**\n\t * Gets the native platform string from navigator if it exists. If\n\t * navigator or navigator.platform string is missing, returns an empty\n\t * string.\n\t * @return {string}\n\t * @private\n\t * @static\n\t */\n\tstatic getNativePlatform() {\n\t\tlet navigator = UA.globals.window && UA.globals.window.navigator;\n\t\tif (navigator) {\n\t\t\tlet platform = navigator.platform;\n\t\t\tif (platform) {\n\t\t\t\treturn platform;\n\t\t\t}\n\t\t}\n\t\treturn '';\n\t}\n\n\t/**\n\t * Whether the platform contains the given string, ignoring case.\n\t * @param {string} str\n\t * @return {boolean}\n\t * @private\n\t * @static\n\t */\n\tstatic matchPlatform(str) {\n\t\treturn UA.platform.indexOf(str) !== -1;\n\t}\n\n\t/**\n\t * Whether the user agent contains the given string, ignoring case.\n\t * @param {string} str\n\t * @return {boolean}\n\t * @private\n\t * @static\n\t */\n\tstatic matchUserAgent(str) {\n\t\treturn UA.userAgent.indexOf(str) !== -1;\n\t}\n\n\t/**\n\t * Tests the user agent.\n\t * @param {string} userAgent The user agent string.\n\t * @param {string} platform\n\t * @static\n\t */\n\tstatic testUserAgent(userAgent = '', platform = '') {\n\t\t/**\n\t\t * Holds the user agent value extracted from browser native user agent.\n\t\t * @type {string}\n\t\t * @static\n\t\t */\n\t\tUA.userAgent = userAgent;\n\n\t\t/**\n\t\t * Holds the platform value extracted from browser native platform.\n\t\t * @type {string}\n\t\t * @static\n\t\t */\n\t\tUA.platform = platform;\n\n\t\t/**\n\t\t * Whether the user's OS is Mac.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isMac = UA.matchPlatform('Mac');\n\n\t\t/**\n\t\t * Whether the user's OS is Win.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isWin = UA.matchPlatform('Win');\n\n\t\t/**\n\t\t * Whether the user's browser is Opera.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isOpera = UA.matchUserAgent('Opera') || UA.matchUserAgent('OPR');\n\n\t\t/**\n\t\t * Whether the user's browser is IE.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isIe = UA.matchUserAgent('Trident') || UA.matchUserAgent('MSIE');\n\n\t\t/**\n\t\t * Whether the user's browser is Edge.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isEdge = UA.matchUserAgent('Edge');\n\n\t\t/**\n\t\t * Whether the user's browser is IE or Edge.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isIeOrEdge = UA.isIe || UA.isEdge;\n\n\t\t/**\n\t\t * Whether the user's browser is Chrome.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isChrome =\n\t\t\t(UA.matchUserAgent('Chrome') || UA.matchUserAgent('CriOS')) &&\n\t\t\t!UA.isOpera &&\n\t\t\t!UA.isEdge;\n\n\t\t/**\n\t\t * Whether the user's browser is Safari.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isSafari =\n\t\t\tUA.matchUserAgent('Safari') &&\n\t\t\t!(UA.isChrome || UA.isOpera || UA.isEdge);\n\n\t\t/**\n\t\t * Whether the user's browser is Firefox.\n\t\t * @type {boolean}\n\t\t * @static\n\t\t */\n\t\tUA.isFirefox = UA.matchUserAgent('Firefox');\n\t}\n}\n\n/**\n * Exposes global references.\n * @type {object}\n * @static\n */\nObject.defineProperty(UA, 'globals', {\n\twritable: true,\n\tvalue: {\n\t\twindow: isServerSide() ? null : window,\n\t},\n});\n\nUA.testUserAgent(UA.getNativeUserAgent(), UA.getNativePlatform());\n\nexport default UA;\n","'use strict';\n\nimport { isDefAndNotNull } from 'metal';\nimport Ajax from 'metal-ajax';\nimport { MultiMap } from 'metal-structs';\nimport CancellablePromise from 'metal-promise';\nimport errors from '../errors/errors';\nimport utils from '../utils/utils';\nimport globals from '../globals/globals';\nimport Screen from './Screen';\nimport Uri from 'metal-uri';\nimport UA from 'metal-useragent';\n\nclass RequestScreen extends Screen {\n\n\t/**\n\t * Request screen abstract class to perform io operations on descendant\n\t * screens.\n\t * @constructor\n\t * @extends {Screen}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * @inheritDoc\n\t\t * @default true\n\t\t */\n\t\tthis.cacheable = true;\n\n\t\t/**\n\t\t * Holds default http headers to set on request.\n\t\t * @type {?Object=}\n\t\t * @default {\n\t\t * 'X-PJAX': 'true',\n\t\t * 'X-Requested-With': 'XMLHttpRequest'\n\t\t * }\n\t\t * @protected\n\t\t */\n\t\tthis.httpHeaders = {\n\t\t\t'X-PJAX': 'true',\n\t\t\t'X-Requested-With': 'XMLHttpRequest'\n\t\t};\n\n\t\t/**\n\t\t * Holds default http method to perform the request.\n\t\t * @type {!string}\n\t\t * @default RequestScreen.GET\n\t\t * @protected\n\t\t */\n\t\tthis.httpMethod = RequestScreen.GET;\n\n\t\t/**\n\t\t * Holds the XHR object responsible for the request.\n\t\t * @type {XMLHttpRequest}\n\t\t * @default null\n\t\t * @protected\n\t\t */\n\t\tthis.request = null;\n\n\t\t/**\n\t\t * Holds the request timeout in milliseconds.\n\t\t * @type {!number}\n\t\t * @default 30000\n\t\t * @protected\n\t\t */\n\t\tthis.timeout = 30000;\n\t}\n\n\t/**\n\t * Asserts that response status code is valid.\n\t * @param {number} status\n\t * @protected\n\t */\n\tassertValidResponseStatusCode(status) {\n\t\tif (!this.isValidResponseStatusCode(status)) {\n\t\t\tvar error = new Error(errors.INVALID_STATUS);\n\t\t\terror.invalidStatus = true;\n\t\t\terror.statusCode = status;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tbeforeUpdateHistoryPath(path) {\n\t\tvar redirectPath = this.getRequestPath();\n\t\tif (redirectPath && redirectPath !== path) {\n\t\t\treturn redirectPath;\n\t\t}\n\t\treturn path;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tbeforeUpdateHistoryState(state) {\n\t\t// If state is ours and navigate to post-without-redirect-get set\n\t\t// history state to null, that way Senna will reload the page on\n\t\t// popstate since it cannot predict post data.\n\t\tif (state.senna && state.form && state.redirectPath === state.path) {\n\t\t\treturn null;\n\t\t}\n\t\treturn state;\n\t}\n\n\t/**\n\t * Formats load path before invoking ajax call.\n\t * @param {string} path\n\t * @return {string} Formatted path;\n\t * @protected\n\t */\n\tformatLoadPath(path) {\n\t\tvar uri = new Uri(path);\n\n\t\turi.setHostname(globals.window.location.hostname);\n\t\turi.setProtocol(globals.window.location.protocol);\n\n\t\tif (globals.window.location.port) {\n\t\t\turi.setPort(globals.window.location.port);\n\t\t}\n\n\t\tif (UA.isIeOrEdge && this.httpMethod === RequestScreen.GET) {\n\t\t\treturn uri.makeUnique().toString();\n\t\t}\n\n\t\treturn uri.toString();\n\t}\n\n\t/**\n\t * Gets the http headers.\n\t * @return {?Object=}\n\t */\n\tgetHttpHeaders() {\n\t\treturn this.httpHeaders;\n\t}\n\n\t/**\n\t * Gets the http method.\n\t * @return {!string}\n\t */\n\tgetHttpMethod() {\n\t\treturn this.httpMethod;\n\t}\n\n\t/**\n\t * Gets request path.\n\t * @return {string=}\n\t */\n\tgetRequestPath() {\n\t\tvar request = this.getRequest();\n\t\tif (request) {\n\t\t\tvar requestPath = request.requestPath;\n\t\t\tvar responseUrl = this.maybeExtractResponseUrlFromRequest(request);\n\t\t\tif (responseUrl) {\n\t\t\t\trequestPath = responseUrl;\n\t\t\t}\n\t\t\tif (UA.isIeOrEdge && this.httpMethod === RequestScreen.GET) {\n\t\t\t\trequestPath = new Uri(requestPath).removeUnique().toString();\n\t\t\t}\n\t\t\treturn utils.getUrlPath(requestPath);\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Gets the request object.\n\t * @return {?Object}\n\t */\n\tgetRequest() {\n\t\treturn this.request;\n\t}\n\n\t/**\n\t * Gets the request timeout.\n\t * @return {!number}\n\t */\n\tgetTimeout() {\n\t\treturn this.timeout;\n\t}\n\n\t/**\n\t * Checks if response succeeded. Any status code 2xx or 3xx is considered\n\t * valid.\n\t * @param {number} statusCode\n\t */\n\tisValidResponseStatusCode(statusCode) {\n\t\treturn statusCode >= 200 && statusCode <= 399;\n\t}\n\n /**\n * Returns the form data\n * This method can be extended in order to have a custom implementation of the form params\n * @param {!Element} formElement\n * @param {!Element} submittedButtonElement\n * @return {!FormData}\n */\n\tgetFormData(formElement, submittedButtonElement) {\n let formData = new FormData(formElement);\n this.maybeAppendSubmitButtonValue_(formData, submittedButtonElement);\n return formData;\n }\n\n\t/**\n\t * @inheritDoc\n\t */\n\tload(path) {\n\t\tconst cache = this.getCache();\n\t\tif (isDefAndNotNull(cache)) {\n\t\t\treturn CancellablePromise.resolve(cache);\n\t\t}\n\t\tlet body = null;\n\t\tlet httpMethod = this.httpMethod;\n\t\tconst headers = new MultiMap();\n\t\tObject.keys(this.httpHeaders).forEach(header => headers.add(header, this.httpHeaders[header]));\n\t\tif (globals.capturedFormElement) {\n\t\t\tthis.addSafariXHRPolyfill();\n\t\t\tbody = this.getFormData(globals.capturedFormElement, globals.capturedFormButtonElement);\n\t\t\thttpMethod = RequestScreen.POST;\n\t\t\tif (UA.isIeOrEdge) {\n\t\t\t\theaders.add('If-None-Match', '\"0\"');\n\t\t\t}\n\t\t}\n\t\tconst requestPath = this.formatLoadPath(path);\n\t\treturn Ajax\n\t\t\t.request(requestPath, httpMethod, body, headers, null, this.timeout)\n\t\t\t.then(xhr => {\n\t\t\t\tthis.removeSafariXHRPolyfill();\n\t\t\t\tthis.setRequest(xhr);\n\t\t\t\tthis.assertValidResponseStatusCode(xhr.status);\n\t\t\t\tif (httpMethod === RequestScreen.GET && this.isCacheable()) {\n\t\t\t\t\tthis.addCache(xhr.responseText);\n\t\t\t\t}\n\t\t\t\txhr.requestPath = requestPath;\n\t\t\t\treturn xhr.responseText;\n\t\t\t})\n\t\t\t.catch((reason) => {\n\t\t\t\tthis.removeSafariXHRPolyfill();\n\t\t\t\tswitch (reason.message) {\n\t\t\t\t\tcase errors.REQUEST_TIMEOUT:\n\t\t\t\t\t\treason.timeout = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase errors.REQUEST_ERROR:\n\t\t\t\t\t\treason.requestError = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase errors.REQUEST_PREMATURE_TERMINATION:\n\t\t\t\t\t\treason.requestError = true;\n\t\t\t\t\t\treason.requestPrematureTermination = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthrow reason;\n\t\t\t});\n\t}\n\n\t/**\n\t * Adds aditional data to the body of the request in case a submit button\n\t * is captured during form submission.\n\t * @param {!FormData} body The FormData containing the request body.\n * @param {!Element} submittedButtonElement\n * @protected\n\t */\n\tmaybeAppendSubmitButtonValue_(formData, submittedButtonElement) {\n\t\tif (submittedButtonElement && submittedButtonElement.name) {\n formData.append(submittedButtonElement.name, submittedButtonElement.value);\n\t\t}\n\t}\n\n\t/**\n\t * The following method tries to extract the response url value by checking\n\t * the custom response header 'X-Request-URL' if proper value is not present\n\t * in XMLHttpRequest. The value of responseURL will be the final URL\n\t * obtained after any redirects. Internet Explorer, Edge and Safari <= 7\n\t * does not yet support the feature. For more information see:\n\t * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseURL\n\t * https://xhr.spec.whatwg.org/#the-responseurl-attribute\n\t * @param {XMLHttpRequest} request\n\t * @return {?string} Response url best match.\n\t */\n\tmaybeExtractResponseUrlFromRequest(request) {\n\t\tvar responseUrl = request.responseURL;\n\t\tif (responseUrl) {\n\t\t\treturn responseUrl;\n\t\t}\n\t\treturn request.getResponseHeader(RequestScreen.X_REQUEST_URL_HEADER);\n\t}\n\n\t/**\n\t * This function set attribute data-safari-temp-disabled to \n\t * true and set disable attribute of an input type=\"file\" tag\n\t * is used as a polyfill for iOS 11.3 Safari / macOS Safari 11.1 \n\t * empty <input type=\"file\"> XHR bug.\n\t * https://github.com/rails/rails/issues/32440\n\t * https://bugs.webkit.org/show_bug.cgi?id=184490\n\t */\n\taddSafariXHRPolyfill() {\n\t\tif (globals.capturedFormElement && UA.isSafari) {\n\t\t\tlet inputs = globals.capturedFormElement.querySelectorAll('input[type=\"file\"]:not([disabled])');\n\t\t\tfor (let index = 0; index < inputs.length; index++) {\n\t\t\t\tlet input = inputs[index];\n\t\t\t\tif (input.files.length > 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tinput.setAttribute('data-safari-temp-disabled', 'true');\n\t\t\t\tinput.setAttribute('disabled', '');\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * This function remove attribute data-safari-temp-disabled and disable attribute\n\t * of an input type=\"file\" tag is used as a polyfill for iOS 11.3 Safari / macOS Safari 11.1\n\t * empty <input type=\"file\"> XHR bug.\n\t * https://github.com/rails/rails/issues/32440\n\t * https://bugs.webkit.org/show_bug.cgi?id=184490\n\t */\n\tremoveSafariXHRPolyfill() {\n\t\tif (globals.capturedFormElement && UA.isSafari) {\n\t\t\tlet inputs = globals.capturedFormElement.querySelectorAll('input[type=\"file\"][data-safari-temp-disabled]');\n\t\t\tfor (let index = 0; index < inputs.length; index++) {\n\t\t\t\tconst input = inputs[index];\n\t\t\t\tinput.removeAttribute('data-safari-temp-disabled');\n\t\t\t\tinput.removeAttribute('disabled');\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets the http headers.\n\t * @param {?Object=} httpHeaders\n\t */\n\tsetHttpHeaders(httpHeaders) {\n\t\tthis.httpHeaders = httpHeaders;\n\t}\n\n\t/**\n\t * Sets the http method.\n\t * @param {!string} httpMethod\n\t */\n\tsetHttpMethod(httpMethod) {\n\t\tthis.httpMethod = httpMethod.toLowerCase();\n\t}\n\n\t/**\n\t * Sets the request object.\n\t * @param {?Object} request\n\t */\n\tsetRequest(request) {\n\t\tthis.request = request;\n\t}\n\n\t/**\n\t * Sets the request timeout in milliseconds.\n\t * @param {!number} timeout\n\t */\n\tsetTimeout(timeout) {\n\t\tthis.timeout = timeout;\n\t}\n\n}\n\n/**\n * Holds value for method get.\n * @type {string}\n * @default 'get'\n * @static\n */\nRequestScreen.GET = 'get';\n\n/**\n * Holds value for method post.\n * @type {string}\n * @default 'post'\n * @static\n */\nRequestScreen.POST = 'post';\n\n/**\n * Fallback http header to retrieve response request url.\n * @type {string}\n * @default 'X-Request-URL'\n * @static\n */\nRequestScreen.X_REQUEST_URL_HEADER = 'X-Request-URL';\n\nexport default RequestScreen;\n","'use strict';\n\nimport { getUid } from 'metal';\nimport { buildFragment, globalEval, globalEvalStyles, match } from 'metal-dom';\nimport CancellablePromise from 'metal-promise';\nimport globals from '../globals/globals';\nimport RequestScreen from './RequestScreen';\nimport Surface from '../surface/Surface';\nimport UA from 'metal-useragent';\nimport Uri from 'metal-uri';\nimport utils from '../utils/utils';\n\nclass HtmlScreen extends RequestScreen {\n\n\t/**\n\t * Screen class that perform a request and extracts surface contents from\n\t * the response content.\n\t * @constructor\n\t * @extends {RequestScreen}\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the meta selector. Relevant to extract <code>meta</code> tags\n\t\t * elements from request fragments to use as the screen.\n\t\t * @type {!string}\n\t\t * @default meta\n\t\t * @protected\n\t\t */\n\t\tthis.metaTagsSelector = 'meta';\n\n\t\t/**\n\t\t * Holds the title selector. Relevant to extract the <code><title></code>\n\t\t * element from request fragments to use as the screen title.\n\t\t * @type {!string}\n\t\t * @default title\n\t\t * @protected\n\t\t */\n\t\tthis.titleSelector = 'title';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tactivate() {\n\t\tsuper.activate();\n\t\tthis.releaseVirtualDocument();\n\t\tthis.pendingStyles = null;\n\t}\n\n\t/**\n\t * Allocates virtual document for content. After allocated virtual document\n\t * can be accessed by <code>this.virtualDocument</code>.\n\t * @param {!string} htmlString\n\t */\n\tallocateVirtualDocumentForContent(htmlString) {\n\t\tif (!this.virtualDocument) {\n\t\t\tthis.virtualDocument = globals.document.createElement('html');\n\t\t}\n\n\t\tthis.copyNodeAttributesFromContent_(htmlString, this.virtualDocument);\n\n\t\tthis.virtualDocument.innerHTML = htmlString;\n\t}\n\n\t/**\n\t * Customizes logic to append styles into document. Relevant to when\n\t * tracking a style by id make sure to re-positions the new style in the\n\t * same dom order.\n\t * @param {Element} newStyle\n\t */\n\tappendStyleIntoDocument_(newStyle) {\n\t\tvar isTemporaryStyle = match(newStyle, HtmlScreen.selectors.stylesTemporary);\n\t\tif (isTemporaryStyle) {\n\t\t\tthis.pendingStyles.push(newStyle);\n\t\t}\n\t\tif (newStyle.id) {\n\t\t\tvar styleInDoc = globals.document.getElementById(newStyle.id);\n\t\t\tif (styleInDoc) {\n\t\t\t\tstyleInDoc.parentNode.insertBefore(newStyle, styleInDoc.nextSibling);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tglobals.document.head.appendChild(newStyle);\n\t}\n\n\t/**\n\t * If body is used as surface forces the requested documents to have same id\n\t * of the initial page.\n\t */\n\tassertSameBodyIdInVirtualDocument() {\n\t\tvar bodySurface = this.virtualDocument.querySelector('body');\n\t\tif (!globals.document.body.id) {\n\t\t\tglobals.document.body.id = 'senna_surface_' + getUid();\n\t\t}\n\t\tif (bodySurface) {\n\t\t\tbodySurface.id = globals.document.body.id;\n\t\t}\n\t}\n\n\t/**\n\t * Copies attributes from the <html> tag of content to the given node.\n\t */\n\tcopyNodeAttributesFromContent_(content, node) {\n\t\tcontent = content.replace(/[<]\\s*html/ig, '<senna');\n\t\tcontent = content.replace(/\\/html\\s*\\>/ig, '/senna>');\n\t\tlet placeholder;\n\t\tif (UA.isIe) {\n\t\t\tconst tempNode = globals.document.createRange().createContextualFragment(content);\n\t\t\tplaceholder = tempNode.querySelector('senna');\n\t\t} else {\n\t\t\tnode.innerHTML = content;\n\t\t\tplaceholder = node.querySelector('senna');\n\t\t}\n\n\t\tif (placeholder) {\n\t\t\tutils.clearNodeAttributes(node);\n\t\t\tutils.copyNodeAttributes(placeholder, node);\n\t\t}\n\t}\n\n\t/**\n\t * @Override\n\t */\n\tdisposeInternal() {\n\t\tthis.disposePendingStyles();\n\t\tsuper.disposeInternal();\n\t}\n\n\t/**\n\t * Disposes pending styles if screen get disposed prior to its loading.\n\t */\n\tdisposePendingStyles() {\n\t\tif (this.pendingStyles) {\n\t\t\tutils.removeElementsFromDocument(this.pendingStyles);\n\t\t}\n\t}\n\n\t/**\n\t * @Override\n\t */\n\tevaluateScripts(surfaces) {\n\t\tvar evaluateTrackedScripts = this.evaluateTrackedResources_(\n\t\t\tglobalEval.runScriptsInElement, HtmlScreen.selectors.scripts,\n\t\t\tHtmlScreen.selectors.scriptsTemporary, HtmlScreen.selectors.scriptsPermanent);\n\n\t\treturn evaluateTrackedScripts.then(() => super.evaluateScripts(surfaces));\n\t}\n\n\t/**\n\t * @Override\n\t */\n\tevaluateStyles(surfaces) {\n\t\tthis.pendingStyles = [];\n\t\tvar evaluateTrackedStyles = this.evaluateTrackedResources_(\n\t\t\tglobalEvalStyles.runStylesInElement, HtmlScreen.selectors.styles,\n\t\t\tHtmlScreen.selectors.stylesTemporary, HtmlScreen.selectors.stylesPermanent,\n\t\t\tthis.appendStyleIntoDocument_.bind(this));\n\n\t\treturn evaluateTrackedStyles.then(() => super.evaluateStyles(surfaces));\n\t}\n\n\t/**\n\t * Allows a screen to evaluate the favicon style before the screen becomes visible.\n\t * @return {CancellablePromise}\n\t */\n\tevaluateFavicon_() {\n\t\tconst resourcesInVirtual = this.virtualQuerySelectorAll_(HtmlScreen.selectors.favicon);\n\t\tconst resourcesInDocument = this.querySelectorAll_(HtmlScreen.selectors.favicon);\n\n\t\treturn new CancellablePromise((resolve) => {\n\t\t\tutils.removeElementsFromDocument(resourcesInDocument);\n\t\t\tthis.runFaviconInElement_(resourcesInVirtual).then(() => resolve());\n\t\t});\n\t}\n\n\t/**\n\t * Evaluates tracked resources inside incoming fragment and remove existing\n\t * temporary resources.\n\t * @param {?function()} appendFn Function to append the node into document.\n\t * @param {!string} selector Selector used to find resources to track.\n\t * @param {!string} selectorTemporary Selector used to find temporary\n\t * resources to track.\n\t * @param {!string} selectorPermanent Selector used to find permanent\n\t * resources to track.\n\t * @param {!function} opt_appendResourceFn Optional function used to\n\t * evaluate fragment containing resources.\n\t * @return {CancellablePromise} Deferred that waits resources evaluation to\n\t * complete.\n\t * @private\n\t */\n\tevaluateTrackedResources_(evaluatorFn, selector, selectorTemporary, selectorPermanent, opt_appendResourceFn) {\n\t\tvar tracked = this.virtualQuerySelectorAll_(selector);\n\t\tvar temporariesInDoc = this.querySelectorAll_(selectorTemporary);\n\t\tvar permanentsInDoc = this.querySelectorAll_(selectorPermanent);\n\n\t\t// Adds permanent resources in document to cache.\n\t\tpermanentsInDoc.forEach((resource) => {\n\t\t\tvar resourceKey = this.getResourceKey_(resource);\n\t\t\tif (resourceKey) {\n\t\t\t\tHtmlScreen.permanentResourcesInDoc[resourceKey] = true;\n\t\t\t}\n\t\t});\n\n\t\tvar frag = buildFragment();\n\t\ttracked.forEach((resource) => {\n\t\t\tvar resourceKey = this.getResourceKey_(resource);\n\t\t\t// Do not load permanent resources if already in document.\n\t\t\tif (!HtmlScreen.permanentResourcesInDoc[resourceKey]) {\n\t\t\t\tfrag.appendChild(resource);\n\t\t\t}\n\t\t\t// If resource has key and is permanent add to cache.\n\t\t\tif (resourceKey && match(resource, selectorPermanent)) {\n\t\t\t\tHtmlScreen.permanentResourcesInDoc[resourceKey] = true;\n\t\t\t}\n\t\t});\n\n\t\treturn new CancellablePromise((resolve) => {\n\t\t\tevaluatorFn(frag, () => {\n\t\t\t\tutils.removeElementsFromDocument(temporariesInDoc);\n\t\t\t\tresolve();\n\t\t\t}, opt_appendResourceFn);\n\t\t});\n\t}\n\n\t/**\n\t * @Override\n\t */\n\tflip(surfaces) {\n\t\treturn super.flip(surfaces).then(() => {\n\t\t\tutils.clearNodeAttributes(globals.document.documentElement);\n\t\t\tutils.copyNodeAttributes(this.virtualDocument, globals.document.documentElement);\n\t\t\tthis.evaluateFavicon_();\n\t\t\tthis.updateMetaTags_();\n\t\t});\n\t}\n\n\tupdateMetaTags_() {\n\t\tconst currentMetaNodes = this.querySelectorAll_('meta');\n\t\tconst metasFromVirtualDocument = this.metas;\n\t\tif (currentMetaNodes) {\n\t\t\tutils.removeElementsFromDocument(currentMetaNodes);\n\t\t\tif (metasFromVirtualDocument) {\n\t\t\t\tmetasFromVirtualDocument.forEach((meta) => globals.document.head.appendChild(meta));\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Extracts a key to identify the resource based on its attributes.\n\t * @param {Element} resource\n\t * @return {string} Extracted key based on resource attributes in order of\n\t * preference: id, href, src.\n\t */\n\tgetResourceKey_(resource) {\n\t\treturn resource.id || resource.href || resource.src || '';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tgetSurfaceContent(surfaceId) {\n\t\tvar surface = this.virtualDocument.querySelector('#' + surfaceId);\n\t\tif (surface) {\n\t\t\tvar defaultChild = surface.querySelector('#' + surfaceId + '-' + Surface.DEFAULT);\n\t\t\tif (defaultChild) {\n\t\t\t\treturn defaultChild.innerHTML;\n\t\t\t}\n\t\t\treturn surface.innerHTML; // If default content not found, use surface content\n\t\t}\n\t}\n\n\t/**\n\t * Gets the title selector.\n\t * @return {!string}\n\t */\n\tgetTitleSelector() {\n\t\treturn this.titleSelector;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tload(path) {\n\t\treturn super.load(path)\n\t\t\t.then(content => {\n\t\t\t\tthis.allocateVirtualDocumentForContent(content);\n\t\t\t\tthis.resolveTitleFromVirtualDocument();\n\t\t\t\tthis.resolveMetaTagsFromVirtualDocument();\n\t\t\t\tthis.assertSameBodyIdInVirtualDocument();\n\t\t\t\tif (UA.isIe) {\n\t\t\t\t\tthis.makeTemporaryStylesHrefsUnique_();\n\t\t\t\t}\n\t\t\t\treturn content;\n\t\t\t});\n\t}\n\n\t/**\n\t * Queries temporary styles from virtual document, and makes them unique.\n\t * This is necessary for caching and load event firing issues specific to\n\t * IE11. https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7940171/\n\t */\n\tmakeTemporaryStylesHrefsUnique_() {\n\t\tvar temporariesInDoc = this.virtualQuerySelectorAll_(HtmlScreen.selectors.stylesTemporary);\n\t\ttemporariesInDoc.forEach((style) => this.replaceStyleAndMakeUnique_(style));\n\t}\n\n\t/**\n\t * Creates a new element from given, copies attributes, mutates href to be\n\t * unique to prevent caching and more than one load/error event from firing.\n\t */\n\treplaceStyleAndMakeUnique_(style) {\n\t\tif (style.href) {\n\t\t\tvar newStyle = globals.document.createElement(style.tagName);\n\t\t\tstyle.href = new Uri(style.href).makeUnique().toString();\n\t\t\tutils.copyNodeAttributes(style, newStyle);\n\t\t\tstyle.parentNode.replaceChild(newStyle, style);\n\t\t\tstyle.disabled = true;\n\t\t}\n\t}\n\n\t/**\n\t * Adds the favicon elements to the document.\n\t * @param {!Array<Element>} elements\n\t * @private\n\t * @return {CancellablePromise}\n\t */\n\trunFaviconInElement_(elements) {\n\t\treturn new CancellablePromise((resolve) => {\n\t\t\telements.forEach((element) => document.head.appendChild(\n\t\t\t\tUA.isIe ? element : utils.setElementWithRandomHref(element)\n\t\t\t));\n\t\t\tresolve();\n\t\t});\n\t}\n\n\t/**\n\t * Queries elements from virtual document and returns an array of elements.\n\t * @param {!string} selector\n\t * @return {array.<Element>}\n\t */\n\tvirtualQuerySelectorAll_(selector) {\n\t\treturn Array.prototype.slice.call(this.virtualDocument.querySelectorAll(selector));\n\t}\n\n\t/**\n\t * Queries elements from document and returns an array of elements.\n\t * @param {!string} selector\n\t * @return {array.<Element>}\n\t */\n\tquerySelectorAll_(selector) {\n\t\treturn Array.prototype.slice.call(globals.document.querySelectorAll(selector));\n\t}\n\n\t/**\n\t * Releases virtual document allocated for content.\n\t */\n\treleaseVirtualDocument() {\n\t\tthis.virtualDocument = null;\n\t}\n\n\t/**\n\t * Resolves title from allocated virtual document.\n\t */\n\tresolveTitleFromVirtualDocument() {\n\t\tconst title = this.virtualDocument.querySelector(this.titleSelector);\n\t\tif (title) {\n\t\t\tthis.setTitle(title.textContent.trim());\n\t\t}\n\t}\n\n\tresolveMetaTagsFromVirtualDocument() {\n\t\tconst metas = this.virtualQuerySelectorAll_(this.metaTagsSelector);\n\t\tif (metas) {\n\t\t\tthis.setMetas(metas);\n\t\t}\n\t}\n\n\t/**\n\t * Sets the title selector.\n\t * @param {!string} titleSelector\n\t */\n\tsetTitleSelector(titleSelector) {\n\t\tthis.titleSelector = titleSelector;\n\t}\n\n}\n\n/**\n * Helper selector for ignore favicon when exist data-senna-track.\n */\nconst ignoreFavicon = ':not([rel=\"Shortcut Icon\"]):not([rel=\"shortcut icon\"]):not([rel=\"icon\"]):not([href$=\"favicon.icon\"])';\n\n/**\n * Helper selectors for tracking resources.\n * @type {object}\n * @protected\n * @static\n */\nHtmlScreen.selectors = {\n\tfavicon: 'link[rel=\"Shortcut Icon\"],link[rel=\"shortcut icon\"],link[rel=\"icon\"],link[href$=\"favicon.icon\"]',\n\tscripts: 'script[data-senna-track]',\n\tscriptsPermanent: 'script[data-senna-track=\"permanent\"]',\n\tscriptsTemporary: 'script[data-senna-track=\"temporary\"]',\n\tstyles: `style[data-senna-track],link[data-senna-track]${ignoreFavicon}`,\n\tstylesPermanent: `style[data-senna-track=\"permanent\"],link[data-senna-track=\"permanent\"]${ignoreFavicon}`,\n\tstylesTemporary: `style[data-senna-track=\"temporary\"],link[data-senna-track=\"temporary\"]${ignoreFavicon}`\n};\n\n/**\n * Caches permanent resource keys.\n * @type {object}\n * @protected\n * @static\n */\nHtmlScreen.permanentResourcesInDoc = {};\n\nexport default HtmlScreen;\n","'use strict';\n\nimport { Disposable, getUid, isDefAndNotNull, isElement, object } from 'metal';\nimport dataAttributes from './dataAttributes';\nimport globals from '../globals/globals';\nimport App from './App';\nimport HtmlScreen from '../screen/HtmlScreen';\nimport Route from '../route/Route';\n\nclass AppDataAttributeHandler extends Disposable {\n\n\t/**\n\t * Initilizes App, register surfaces and routes from data attributes.\n\t * @constructor\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Holds the app reference initialized by data attributes.\n\t\t * @type {App}\n\t\t * @default null\n\t\t */\n\t\tthis.app = null;\n\n\t\t/**\n\t\t * Holds the base element to search initialization data attributes. This\n\t\t * element is the container used to enable initialization based on the\n\t\t * presence of `data-senna` attribute.\n\t\t * @type {Element}\n\t\t * @default null\n\t\t */\n\t\tthis.baseElement = null;\n\t}\n\n\t/**\n\t * Inits application based on information scanned from document.\n\t */\n\thandle() {\n\t\tif (!isElement(this.baseElement)) {\n\t\t\tthrow new Error('Senna data attribute handler base element ' +\n\t\t\t\t'not set or invalid, try setting a valid element that ' +\n\t\t\t\t'contains a `data-senna` attribute.');\n\t\t}\n\n\t\tif (!this.baseElement.hasAttribute(dataAttributes.senna)) {\n\t\t\tconsole.log('Senna was not initialized from data attributes. ' +\n\t\t\t\t'In order to enable its usage from data attributes try setting ' +\n\t\t\t\t'in the base element, e.g. `<body data-senna>`.');\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.app) {\n\t\t\tthrow new Error('Senna app was already initialized.');\n\t\t}\n\n\t\tconsole.log('Senna initialized from data attribute.');\n\n\t\tthis.app = new App();\n\t\tthis.maybeAddRoutes_();\n\t\tthis.maybeAddSurfaces_();\n\t\tthis.maybeSetBasePath_();\n\t\tthis.maybeSetLinkSelector_();\n\t\tthis.maybeSetLoadingCssClass_();\n\t\tthis.maybeSetUpdateScrollPosition_();\n\t\tthis.maybeDispatch_();\n\t}\n\n\t/**\n\t * Disposes of this instance's object references.\n\t * @override\n\t */\n\tdisposeInternal() {\n\t\tif (this.app) {\n\t\t\tthis.app.dispose();\n\t\t}\n\t}\n\n\t/**\n\t * Gets the app reference.\n\t * @return {App}\n\t */\n\tgetApp() {\n\t\treturn this.app;\n\t}\n\n\t/**\n\t * Gets the base element.\n\t * @return {Element} baseElement\n\t */\n\tgetBaseElement() {\n\t\treturn this.baseElement;\n\t}\n\n\t/**\n\t * Maybe adds app routes from link elements that are `senna-route`.\n\t */\n\tmaybeAddRoutes_() {\n\t\tvar routesSelector = 'link[rel=\"senna-route\"]';\n\t\tthis.querySelectorAllAsArray_(routesSelector).forEach((link) => this.maybeParseLinkRoute_(link));\n\t\tif (!this.app.hasRoutes()) {\n\t\t\tthis.app.addRoutes(new Route(/.*/, HtmlScreen));\n\t\t\tconsole.log('Senna can\\'t find route elements, adding default.');\n\t\t}\n\t}\n\n\t/**\n\t * Maybe adds app surfaces by scanning `data-senna-surface` data attribute.\n\t */\n\tmaybeAddSurfaces_() {\n\t\tvar surfacesSelector = '[' + dataAttributes.surface + ']';\n\t\tthis.querySelectorAllAsArray_(surfacesSelector).forEach((surfaceElement) => {\n\t\t\tthis.updateElementIdIfSpecialSurface_(surfaceElement);\n\t\t\tthis.app.addSurfaces(surfaceElement.id);\n\t\t});\n\t}\n\n\t/**\n\t * Dispatches app navigation to the current path when initializes.\n\t */\n\tmaybeDispatch_() {\n\t\tif (this.baseElement.hasAttribute(dataAttributes.dispatch)) {\n\t\t\tthis.app.dispatch();\n\t\t}\n\t}\n\n\t/**\n\t * Adds app route by parsing valid link elements. A valid link element is of\n\t * the kind `rel=\"senna-route\"`.\n\t * @param {Element} link\n\t */\n\tmaybeParseLinkRoute_(link) {\n\t\tvar route = new Route(this.maybeParseLinkRoutePath_(link), this.maybeParseLinkRouteHandler_(link));\n\t\tthis.app.addRoutes(route);\n\t\tconsole.log('Senna scanned route ' + route.getPath());\n\t}\n\n\t/**\n\t * Maybe parse link route handler.\n\t * @param {Element} link\n\t * @return {?string}\n\t */\n\tmaybeParseLinkRouteHandler_(link) {\n\t\tvar handler = link.getAttribute('type');\n\t\tif (isDefAndNotNull(handler)) {\n\t\t\thandler = object.getObjectByName(handler);\n\t\t}\n\t\treturn handler;\n\t}\n\n\t/**\n\t * Maybe parse link route path.\n\t * @param {Element} link\n\t * @return {?string}\n\t */\n\tmaybeParseLinkRoutePath_(link) {\n\t\tvar path = link.getAttribute('href');\n\t\tif (isDefAndNotNull(path)) {\n\t\t\tif (path.indexOf('regex:') === 0) {\n\t\t\t\tpath = new RegExp(path.substring(6));\n\t\t\t}\n\t\t}\n\t\treturn path;\n\t}\n\n\t/**\n\t * Maybe sets app base path from `data-senna-base-path` data attribute.\n\t */\n\tmaybeSetBasePath_() {\n\t\tvar basePath = this.baseElement.getAttribute(dataAttributes.basePath);\n\t\tif (isDefAndNotNull(basePath)) {\n\t\t\tthis.app.setBasePath(basePath);\n\t\t\tconsole.log('Senna scanned base path ' + basePath);\n\t\t}\n\t}\n\n\t/**\n\t * Maybe sets app link selector from `data-senna-link-selector` data\n\t * attribute.\n\t */\n\tmaybeSetLinkSelector_() {\n\t\tvar linkSelector = this.baseElement.getAttribute(dataAttributes.linkSelector);\n\t\tif (isDefAndNotNull(linkSelector)) {\n\t\t\tthis.app.setLinkSelector(linkSelector);\n\t\t\tconsole.log('Senna scanned link selector ' + linkSelector);\n\t\t}\n\t}\n\n\t/**\n\t * Maybe sets app link loading css class from `data-senna-loading-css-class`\n\t * data attribute.\n\t */\n\tmaybeSetLoadingCssClass_() {\n\t\tvar loadingCssClass = this.baseElement.getAttribute(dataAttributes.loadingCssClass);\n\t\tif (isDefAndNotNull(loadingCssClass)) {\n\t\t\tthis.app.setLoadingCssClass(loadingCssClass);\n\t\t\tconsole.log('Senna scanned loading css class ' + loadingCssClass);\n\t\t}\n\t}\n\n\t/**\n\t * Maybe sets app update scroll position from\n\t * `data-senna-update-scroll-position` data attribute.\n\t */\n\tmaybeSetUpdateScrollPosition_() {\n\t\tvar updateScrollPosition = this.baseElement.getAttribute(dataAttributes.updateScrollPosition);\n\t\tif (isDefAndNotNull(updateScrollPosition)) {\n\t\t\tif (updateScrollPosition === 'false') {\n\t\t\t\tthis.app.setUpdateScrollPosition(false);\n\t\t\t} else {\n\t\t\t\tthis.app.setUpdateScrollPosition(true);\n\t\t\t}\n\t\t\tconsole.log('Senna scanned update scroll position ' + updateScrollPosition);\n\t\t}\n\t}\n\n\t/**\n\t * Queries elements from document and returns an array of elements.\n\t * @param {!string} selector\n\t * @return {array.<Element>}\n\t */\n\tquerySelectorAllAsArray_(selector) {\n\t\treturn Array.prototype.slice.call(globals.document.querySelectorAll(selector));\n\t}\n\n\t/**\n\t * Updates element id if handled as special surface element. Some surfaces\n\t * are slightly different from others, like when threating <code>body</code>\n\t * as surface.\n\t * @param {Element} element\n\t */\n\tupdateElementIdIfSpecialSurface_(element) {\n\t\tif (!element.id && element === globals.document.body) {\n\t\t\telement.id = 'senna_surface_' + getUid();\n\t\t}\n\t}\n\n\t/**\n\t * Sets the base element.\n\t * @param {Element} baseElement\n\t */\n\tsetBaseElement(baseElement) {\n\t\tthis.baseElement = baseElement;\n\t}\n\n}\n\nexport default AppDataAttributeHandler;\n","'use strict';\n\nimport globals from '../globals/globals';\nimport AppDataAttributeHandler from './AppDataAttributeHandler';\n\n/**\n * Data attribute handler.\n * @type {AppDataAttributeHandler}\n */\nvar dataAttributeHandler = new AppDataAttributeHandler();\n\nglobals.document.addEventListener('DOMContentLoaded', function() {\n\tdataAttributeHandler.setBaseElement(globals.document.body);\n\tdataAttributeHandler.handle();\n});\n\nexport default dataAttributeHandler;","/**\n * @returns String containing the current senna version\n */\n\nconst version = '<%= version %>';\n\nexport default version;"],"names":["isDef","val","undefined","isDefAndNotNull","isNull","isDocument","nodeType","isFunction","isObject","type","isString","String","isServerSide","options","checkEnv","serverSide","process","browser","env","NODE_ENV","array","arr1","arr2","length","i","arr","output","Array","isArray","flatten","push","obj","indexOf","rv","removeAt","prototype","splice","call","start","end","sliced","async","throwException","exception","nextTick","run","callback","context","workQueueScheduled_","processWorkQueue","workQueue_","WorkItem_","workItems","workItem","fn","scope","e","cb","bind","wrapCallback_","setImmediate_","setImmediate","getSetImmediateEmulator_","Channel","MessageChannel","window","postMessage","addEventListener","iframe","document","createElement","style","display","src","title","documentElement","appendChild","win","contentWindow","doc","open","write","close","message","Math","random","origin","location","protocol","host","onmessage","data","port1","port2","channel","head","tail","next","script","onreadystatechange","parentNode","removeChild","Disposable","disposed_","disposeInternal","object","target","key","source","args","name","parts","split","reduce","part","mappedObj","keys","Object","obj1","obj2","keys1","keys2","string","str1","str2","test1","toLowerCase","test2","str","replace","x","floor","toString","abs","Date","now","hash","len","charCodeAt","value","substring","METAL_DATA","domData","element","initialValue","EventHandle","emitter","event","listener","emitter_","event_","listener_","removeListener","isDisposed","singleArray_","EventEmitter","events_","listenerHandlers_","shouldUseFacade_","holder","handler","defaultListener","validateListener_","events","toEventsArray_","addSingleListener_","runListenerHandlers_","addHandler_","getShouldUseFacade","facade","preventedDefault","listeners","getRawListeners_","slice","arguments","runListeners_","buildFacade_","directListeners","toArray","concat","map","amount","many_","self","handlerInternal","apply","listenerObj","removeMatchingListenerObjs_","addListener","many","listenerObjs","finalListeners","matchesListener_","off","handlers","defaultListeners","default","j","shouldUseFacade","TypeError","EventEmitterProxy","originEmitter","targetEmitter","blacklist","whitelist","blacklist_","originEmitter_","pendingEvents_","proxiedEvents_","targetEmitter_","whitelist_","startProxy_","on","removeListeners_","emit","shouldProxyEvent_","tryToAddListener_","forEach","proxyEvent","onListener","addListener_","emitOnTarget_","EventHandler","eventHandles_","DomDelegatedEventHandle","selector","selector_","delegating","get","selectors","remove","DomEventHandle","capture","capture_","removeEventListener","elementsByTag_","supportCache_","customEvents","LAST_CONTAINER","USE_CAPTURE","addClasses","elements","classes","addClassesWithNative_","className","classList","add","addClassesWithoutNative_","elementClassName","classesToAppend","addElementListener_","eventName","addSelectorListener_","delegatingData","addToArr_","attachDelegateEvent_","handleDelegateEvent_","closest","match","append","parent","child","buildFragment","isNodeListLike","childArr","htmlString","tempDiv","innerHTML","firstChild","fragment","createDocumentFragment","contains","element1","element2","delegate","selectorOrTarget","customConfig","originalEvent","defaultListener_","isAbleToInteractWith_","node","eventObj","button","matchesSelector","tagName","disabled","item","exitDocument","ret","container","currentTarget","defFns","triggerDelegatedListeners_","triggerDefaultDelegatedListeners_","delegateTarget","p","Element","m","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector","matchFallback_","nodes","querySelectorAll","normalizeDelegateEvent_","stopPropagation","stopPropagation_","stopImmediatePropagation","stopImmediatePropagation_","once","domEventHandle","registerCustomEvent","removeChildren","removeClasses","removeClassesWithNative_","removeClassesWithoutNative_","trim","stopped","stoppedImmediate","supportsEvent","tag","hasOwnProperty","defaultPrevented","defaultFns","currElement","limit","triggerElementListeners_","triggerSelectorListeners_","lastContainer","triggerListeners_","DomEventEmitterProxy","isDelegateEvent_","index","substr","babelHelpers.get","isSupportedDomEvent_","features","animationEventName_","checkAnimationEventName_","prefixes","typeTitleCase","replaceInterval","toUpperCase","suffixes","animationElement_","attrOrderChange_","originalContent","globalEval","text","appendFn","defaultFn","runFile","scripts","runScriptsInOrder","runScript","globalEvalStyles","href","link","rel","runStyle","styles","loadCount","registerEvents","mouseEventMap","related","relatedTarget","customType","animationEventMap","eventType","checkAnimationEventName","globals","compatibilityModeData_","uniqueIdCounter_","UID_PROPERTY","abstractMethod","Error","disableCompatibilityMode","enableCompatibilityMode","getCompatibilityModeData","__METAL_COMPATIBILITY__","getFirstTruthy_","a","b","getFunctionName","getStaticProperty","ctor","propertyName","mergeFn","mergedName","merged","__proto__","isPrototypeOf","Function","getUid","noInheritance","id","identityFunction","returnValue","isBoolean","isDocumentFragment","isElement","isNumber","isWindow","isPromise","then","nullFunction","parseFromAnchor","opt_uri","test","hostname","password","pathname","port","search","username","parse","URL","url","create","MultiMap","values","size","names","JSON","stringify","set","TreeNode","value_","parent_","children_","setParent","current","getParent","ancestors","getChildren","EMPTY_ARRAY","depth","root","getChildCount","opt_preorderFn","opt_postorderFn","traverse","assertChildHasNoParent","parseFn_","Uri","maybeAddProtocolAndHostname_","multimap","getAll","addParameterValue","ensureQueryInitialized_","query","param","urlDecode","getHostname","getPort","HOSTNAME_PLACEHOLDER","getHost","getProtocol","querystring","getParameterNames","getParameterValues","encodeURIComponent","setParameterValue","RANDOM_PARAM","getRandomString","DEFAULT_PROTOCOL","charAt","removeParameter","getPathname","getSearch","getHash","parseFn","basePath","paths","path","join","decodeURIComponent","isSecure","utils","attributes","attribute","setAttribute","getCurrentBrowserPathWithoutHash","offsetLeft","offsetTop","offsetParent","uri","currentBrowserPath","getUrlPathWithoutHash","getUrlPath","history","pushState","err","error","removeAttribute","referrer","defineProperty","Thenable","IMPLEMENTED_BY_PROP","addImplementation","$goog_Thenable","isImplementedBy","partial","newArgs","CancellablePromise","resolver","opt_context","state_","State_","PENDING","result_","callbackEntries_","executing_","UNHANDLED_REJECTION_DELAY","unhandledRejectionId_","hadUnhandledRejection_","resolve_","FULFILLED","reason","REJECTED","CallbackEntry_","resolve","opt_value","reject","opt_reason","race","promises","promise","all","toFulfill","onFulfill","onReject","firstFulfilled","toReject","reasons","opt_onFulfilled","opt_onRejected","addChildPromise_","thenAlways","onResolved","handleRejection_","addCallbackEntry_","thenCatch","onRejected","catch","cancel","opt_message","CancellationError","IS_CANCELLATION_ERROR","cancelInternal_","cancelChild_","childPromise","childCount","childIndex","entry","callbackEntry","executeCallback_","scheduleCallbacks_","onFulfilled","result","unblockAndFulfill_","BLOCKED","unblockAndReject_","state","tryThen_","addUnhandledRejection_","thenable","called","executeCallbacks_","entries","removeUnhandledRejection_","setTimeout","setUnhandledRejectionHandler","debounce","delay","debounced","cancelDebounce","REGEX","convertMatchesToObj","convertTokensToRegex","tokens","regex","core","escape","encloseNonCapturingGroup","pattern","repeat","prefix","optional","RegExp","makeTrailingSlashOptional","routeOrTokens","route","unnamedCount","currPath","exec","paramPattern","unnamedPattern","modifier","toRegex","extractData","paramIndex","Route","parsedData_","buildParsedData_","Cacheable","cache","cacheable","content","clearCache","Screen","makeId_","metas","log","surfaces","sId","activeChild","runScriptsInElement","transitions","surface","deferred","show","Surface","defaultChild","transitionFn","getChild","DEFAULT","maybeWrapContentAsDefault_","screenId","opt_content","createChild","transition","getElement","getElementById","addContent","from","to","defaultTransition","NavigationStrategy","App","activeScreen","activePath","allowPreventNavigate","browserPathBeforeNavigate","captureScrollPositionFromScrollEvent","defaultTitle","formSelector","ignoreQueryStringFromRoutePath","linkSelector","loadingCssClass","nativeScrollRestorationSupported","navigationStrategy","IMMEDIATE","isNavigationPending","pendingNavigate","popstateScrollLeft","popstateScrollTop","redirectPath","routes","scheduledNavigationQueue","screens","skipLoadPopstate","updateScrollPosition","appEventHandlers_","onScroll_","onLoad_","onPopstate_","onStartNavigate_","onBeforeNavigate_","onBeforeNavigateDefault_","onBeforeUnloadDefault_","setLinkSelector","setFormSelector","maybeOverloadBeforeUnload_","getId","isWebUri","isLinkSameOrigin_","isSameBasePath_","isCurrentBrowserPath","findRoute","removeScreen","screen","getHandler","clearScreensCache","formEventHandler_","linkEventHandler_","removeAllListeners","navigate","getCurrentBrowserPath","opt_replaceHistory","stopPendingNavigate_","nextScreen","createScreenInstance","maybePreventDeactivate_","maybePreventActivate_","load","SCHEDULE_LAST","deactivate","prepareNavigateHistory_","prepareNavigateSurfaces_","extractParams","evaluateStyles","flip","evaluateScripts","maybeUpdateScrollPositionState_","syncScrollPositionSyncThenAsync_","finalizeNavigate_","handleNavigateError_","scheduledNavigation","shift","maybeNavigate_","getRoutePath","activate","isCacheable","capturedFormElement","capturedFormButtonElement","matchesPath","getIgnoreQueryStringFromRoutePath","getUrlPathWithoutHashAndSearch","stack","hostUri","locationHostUri","winner","switchScrollPositionRace","scrollTo","scrollLeft","scrollTop","nativeScrollRestoration_","scrollRestoration","mixin","canNavigate","isNavigationScheduled","maybeScheduleNavigation_","preventDefault","navigateFailed","isScheduledNavigation","onbeforeunload","_onbeforeunload","_overloaded","beforeActivate","prevent","beforeDeactivate","anchorElement","getNodeOffset","saveHistoryCurrentPageScrollPosition_","opt_event","isHtml5HistorySupported","form","replaceHistory","func","altKey","ctrlKey","metaKey","shiftKey","method","buttonSelector","activeElement","querySelector","action","maybeRepositionScrollToHashedAnchor","reloadPage","senna","lockHistoryScrollPosition_","setReferrer","setHostname","setPort","pageYOffset","pageXOffset","maybeDisableNativeScrollRestoration","endNavigatePayload","doNavigate_","maybeRestoreNativeScrollRestoration","getTitle","getDefaultTitle","beforeUpdateHistoryPath","maybeRestoreRedirectPathHash_","historyState","updateHistory_","beforeUpdateHistoryState","params","surfaceContent","getSurfaceContent","reload","surfaceId","dispose","replaceState","removePathTrailingSlash","onDocSubmitDelegate_","onDocClickDelegate_","sync","titleNode","Ajax","allHeaders","headers","pairs","body","opt_headers","opt_params","opt_timeout","opt_sync","opt_withCredentials","request","XMLHttpRequest","previousReadyState","Promise","onload","aborted","onerror","readyState","terminatedPrematurely","abort","timeout","addParametersFromMultiMap","withCredentials","setRequestHeader","send","errors","INVALID_STATUS","REQUEST_ERROR","REQUEST_TIMEOUT","REQUEST_PREMATURE_TERMINATION","UA","navigator","userAgent","platform","isMac","matchPlatform","isWin","isOpera","matchUserAgent","isIe","isEdge","isIeOrEdge","isChrome","isSafari","isFirefox","testUserAgent","getNativeUserAgent","getNativePlatform","RequestScreen","httpHeaders","httpMethod","GET","status","isValidResponseStatusCode","invalidStatus","statusCode","getRequestPath","setProtocol","makeUnique","getRequest","requestPath","responseUrl","maybeExtractResponseUrlFromRequest","removeUnique","formElement","submittedButtonElement","formData","FormData","maybeAppendSubmitButtonValue_","getCache","header","addSafariXHRPolyfill","getFormData","POST","formatLoadPath","removeSafariXHRPolyfill","setRequest","xhr","assertValidResponseStatusCode","addCache","responseText","requestError","requestPrematureTermination","responseURL","getResponseHeader","X_REQUEST_URL_HEADER","inputs","input","files","HtmlScreen","metaTagsSelector","titleSelector","releaseVirtualDocument","pendingStyles","virtualDocument","copyNodeAttributesFromContent_","newStyle","isTemporaryStyle","stylesTemporary","styleInDoc","insertBefore","nextSibling","bodySurface","placeholder","tempNode","createRange","createContextualFragment","clearNodeAttributes","copyNodeAttributes","disposePendingStyles","removeElementsFromDocument","evaluateTrackedScripts","evaluateTrackedResources_","scriptsTemporary","scriptsPermanent","evaluateTrackedStyles","runStylesInElement","stylesPermanent","appendStyleIntoDocument_","resourcesInVirtual","virtualQuerySelectorAll_","favicon","resourcesInDocument","querySelectorAll_","runFaviconInElement_","evaluatorFn","selectorTemporary","selectorPermanent","opt_appendResourceFn","tracked","temporariesInDoc","permanentsInDoc","resource","resourceKey","getResourceKey_","permanentResourcesInDoc","frag","evaluateFavicon_","updateMetaTags_","currentMetaNodes","metasFromVirtualDocument","meta","allocateVirtualDocumentForContent","resolveTitleFromVirtualDocument","resolveMetaTagsFromVirtualDocument","assertSameBodyIdInVirtualDocument","makeTemporaryStylesHrefsUnique_","replaceStyleAndMakeUnique_","replaceChild","setElementWithRandomHref","setTitle","textContent","setMetas","ignoreFavicon","AppDataAttributeHandler","app","baseElement","hasAttribute","dataAttributes","maybeAddRoutes_","maybeAddSurfaces_","maybeSetBasePath_","maybeSetLinkSelector_","maybeSetLoadingCssClass_","maybeSetUpdateScrollPosition_","maybeDispatch_","routesSelector","querySelectorAllAsArray_","maybeParseLinkRoute_","hasRoutes","addRoutes","surfacesSelector","surfaceElement","updateElementIdIfSpecialSurface_","addSurfaces","dispatch","maybeParseLinkRoutePath_","maybeParseLinkRouteHandler_","getPath","getAttribute","getObjectByName","setBasePath","setLoadingCssClass","setUpdateScrollPosition","dataAttributeHandler","setBaseElement","handle","version"],"mappings":"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","preExistingComment":"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9jb3JlTmFtZWQuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvY29yZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9hcnJheS9hcnJheS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9hc3luYy9hc3luYy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9kaXNwb3NhYmxlL0Rpc3Bvc2FibGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvb2JqZWN0L29iamVjdC5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9zdHJpbmcvc3RyaW5nLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZG9tRGF0YS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsLWV2ZW50cy9zcmMvRXZlbnRIYW5kbGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL25vZGVfbW9kdWxlcy9tZXRhbC1ldmVudHMvc3JjL0V2ZW50RW1pdHRlci5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vbm9kZV9tb2R1bGVzL21ldGFsLWV2ZW50cy9zcmMvRXZlbnRFbWl0dGVyUHJveHkuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL25vZGVfbW9kdWxlcy9tZXRhbC1ldmVudHMvc3JjL0V2ZW50SGFuZGxlci5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL0RvbURlbGVnYXRlZEV2ZW50SGFuZGxlLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvRG9tRXZlbnRIYW5kbGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9kb21OYW1lZC5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL2RvbS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL0RvbUV2ZW50RW1pdHRlclByb3h5LmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZmVhdHVyZXMuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9nbG9iYWxFdmFsLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZ2xvYmFsRXZhbFN0eWxlcy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL2V2ZW50cy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9nbG9iYWxzL2dsb2JhbHMuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL2NvcmVOYW1lZC5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvY29yZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvYXJyYXkvYXJyYXkuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL2FzeW5jL2FzeW5jLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9kaXNwb3NhYmxlL0Rpc3Bvc2FibGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL29iamVjdC9vYmplY3QuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL3N0cmluZy9zdHJpbmcuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtdXJpL3NyYy9wYXJzZUZyb21BbmNob3IuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtdXJpL3NyYy9wYXJzZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1zdHJ1Y3RzL3NyYy9NdWx0aU1hcC5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1zdHJ1Y3RzL3NyYy9UcmVlTm9kZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC11cmkvc3JjL1VyaS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy91dGlscy91dGlscy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9hcHAvZGF0YUF0dHJpYnV0ZXMuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZXZlbnRzL3NyYy9FdmVudEhhbmRsZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1ldmVudHMvc3JjL0V2ZW50RW1pdHRlci5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1ldmVudHMvc3JjL0V2ZW50RW1pdHRlclByb3h5LmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWV2ZW50cy9zcmMvRXZlbnRIYW5kbGVyLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLXByb21pc2Uvc3JjL3Byb21pc2UvUHJvbWlzZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kZWJvdW5jZS9zcmMvZGVib3VuY2UuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtcGF0aC1wYXJzZXIvc3JjL3BhdGhQYXJzZXIuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9zcmMvcm91dGUvUm91dGUuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9zcmMvY2FjaGVhYmxlL0NhY2hlYWJsZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9zY3JlZW4vU2NyZWVuLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvc3JjL3N1cmZhY2UvU3VyZmFjZS5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9hcHAvQXBwLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWFqYXgvc3JjL0FqYXguanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9zcmMvZXJyb3JzL2Vycm9ycy5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC11c2VyYWdlbnQvc3JjL1VBLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvc3JjL3NjcmVlbi9SZXF1ZXN0U2NyZWVuLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvc3JjL3NjcmVlbi9IdG1sU2NyZWVuLmpzIiwiL1VzZXJzL2RpZWdvbmFzY2ltZW50by93b3Jrc3BhY2Uvc2VubmEuanMvc3JjL2FwcC9BcHBEYXRhQXR0cmlidXRlSGFuZGxlci5qcyIsIi9Vc2Vycy9kaWVnb25hc2NpbWVudG8vd29ya3NwYWNlL3Nlbm5hLmpzL3NyYy9hcHAvZGF0YUF0dHJpYnV0ZUhhbmRsZXIuanMiLCIvVXNlcnMvZGllZ29uYXNjaW1lbnRvL3dvcmtzcGFjZS9zZW5uYS5qcy9zcmMvYXBwL3ZlcnNpb24uanMiXSwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIEEgY29sbGVjdGlvbiBvZiBjb3JlIHV0aWxpdHkgZnVuY3Rpb25zLlxuICogQGNvbnN0XG4gKi9cblxubGV0IGNvbXBhdGliaWxpdHlNb2RlRGF0YV87XG5cbi8qKlxuICogQ291bnRlciBmb3IgdW5pcXVlIGlkLlxuICogQHR5cGUge051bWJlcn1cbiAqIEBwcml2YXRlXG4gKi9cbmxldCB1bmlxdWVJZENvdW50ZXJfID0gMTtcblxuLyoqXG4gKiBVbmlxdWUgaWQgcHJvcGVydHkgcHJlZml4LlxuICogQHR5cGUge1N0cmluZ31cbiAqIEBwcm90ZWN0ZWRcbiAqL1xuZXhwb3J0IGNvbnN0IFVJRF9QUk9QRVJUWSA9IGBjb3JlXyR7KE1hdGgucmFuZG9tKCkgKiAxZTkpID4+PiAwfWA7XG5cbi8qKlxuICogV2hlbiBkZWZpbmluZyBhIGNsYXNzIEZvbyB3aXRoIGFuIGFic3RyYWN0IG1ldGhvZCBiYXIoKSwgeW91IGNhbiBkbzpcbiAqIEZvby5wcm90b3R5cGUuYmFyID0gYWJzdHJhY3RNZXRob2RcbiAqXG4gKiBOb3cgaWYgYSBzdWJjbGFzcyBvZiBGb28gZmFpbHMgdG8gb3ZlcnJpZGUgYmFyKCksIGFuIGVycm9yIHdpbGwgYmUgdGhyb3duXG4gKiB3aGVuIGJhcigpIGlzIGludm9rZWQuXG4gKlxuICogQHR5cGUgeyFGdW5jdGlvbn1cbiAqIEB0aHJvd3Mge0Vycm9yfSB3aGVuIGludm9rZWQgdG8gaW5kaWNhdGUgdGhlIG1ldGhvZCBzaG91bGQgYmUgb3ZlcnJpZGRlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFic3RyYWN0TWV0aG9kKCkge1xuXHR0aHJvdyBFcnJvcignVW5pbXBsZW1lbnRlZCBhYnN0cmFjdCBtZXRob2QnKTtcbn1cblxuLyoqXG4gKiBEaXNhYmxlcyBNZXRhbC5qcydzIGNvbXBhdGliaWxpdHkgbW9kZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRpc2FibGVDb21wYXRpYmlsaXR5TW9kZSgpIHtcblx0Y29tcGF0aWJpbGl0eU1vZGVEYXRhXyA9IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBFbmFibGVzIE1ldGFsLmpzJ3MgY29tcGF0aWJpbGl0eSBtb2RlIHdpdGggdGhlIGZvbGxvd2luZyBmZWF0dXJlcyBmcm9tIHJjXG4gKiBhbmQgMS54IHZlcnNpb25zOlxuICogICAgIC0gVXNpbmcgXCJrZXlcIiB0byByZWZlcmVuY2UgY29tcG9uZW50IGluc3RhbmNlcy4gSW4gdGhlIGN1cnJlbnQgdmVyc2lvblxuICogICAgICAgdGhpcyBzaG91bGQgYmUgZG9uZSB2aWEgXCJyZWZcIiBpbnN0ZWFkLiBUaGlzIGFsbG93cyBvbGQgY29kZSBzdGlsbFxuICogICAgICAgdXNpbmcgXCJrZXlcIiB0byBrZWVwIHdvcmtpbmcgbGlrZSBiZWZvcmUuIE5PVEU6IHRoaXMgbWF5IGNhdXNlXG4gKiAgICAgICBwcm9ibGVtcywgc2luY2UgXCJrZXlcIiBpcyBtZWFudCB0byBiZSB1c2VkIGRpZmZlcmVudGx5LiBPbmx5IHVzZSB0aGlzXG4gKiAgICAgICBpZiBpdCdzIG5vdCBwb3NzaWJsZSB0byB1cGdyYWRlIHRoZSBjb2RlIHRvIHVzZSBcInJlZlwiIGluc3RlYWQuXG4gKiBAcGFyYW0ge09iamVjdD19IGRhdGEgT3B0aW9uYWwgb2JqZWN0IHdpdGggZGF0YSB0byBzcGVjaWZ5IG1vcmVcbiAqICAgICBkZXRhaWxzLCBzdWNoIGFzOlxuICogICAgICAgICAtIHJlbmRlcmVycyB7QXJyYXl9IHRoZSB0ZW1wbGF0ZSByZW5kZXJlcnMgdGhhdCBzaG91bGQgYmUgaW5cbiAqICAgICAgICAgICBjb21wYXRpYmlsaXR5IG1vZGUsIGVpdGhlciB0aGVpciBjb25zdHJ1Y3RvcnMgb3Igc3RyaW5nc1xuICogICAgICAgICAgIHJlcHJlc2VudGluZyB0aGVtIChlLmcuICdzb3knIG9yICdqc3gnKS4gQnkgZGVmYXVsdCwgYWxsIHRoZSBvbmVzXG4gKiAgICAgICAgICAgdGhhdCBleHRlbmQgZnJvbSBJbmNyZW1lbnRhbERvbVJlbmRlcmVyLlxuICogQHR5cGUge09iamVjdH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuYWJsZUNvbXBhdGliaWxpdHlNb2RlKGRhdGEgPSB7fSkge1xuXHRjb21wYXRpYmlsaXR5TW9kZURhdGFfID0gZGF0YTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBkYXRhIHVzZWQgZm9yIGNvbXBhdGliaWxpdHkgbW9kZSwgb3Igbm90aGluZyBpZiBpdCBoYXNuJ3QgYmVlblxuICogZW5hYmxlZC5cbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbXBhdGliaWxpdHlNb2RlRGF0YSgpIHtcblx0Ly8gQ29tcGF0aWJpbGl0eSBtb2RlIGNhbiBiZSBzZXQgdmlhIHRoZSBfX01FVEFMX0NPTVBBVElCSUxJVFlfXyBnbG9iYWwgdmFyLlxuXHRpZiAoY29tcGF0aWJpbGl0eU1vZGVEYXRhXyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0aWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5fX01FVEFMX0NPTVBBVElCSUxJVFlfXykge1xuXHRcdFx0ZW5hYmxlQ29tcGF0aWJpbGl0eU1vZGUod2luZG93Ll9fTUVUQUxfQ09NUEFUSUJJTElUWV9fKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGNvbXBhdGliaWxpdHlNb2RlRGF0YV87XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZmlyc3QgYXJndW1lbnQgaWYgaXQncyB0cnV0aHksIG9yIHRoZSBzZWNvbmQgb3RoZXJ3aXNlLlxuICogQHBhcmFtIHsqfSBhXG4gKiBAcGFyYW0geyp9IGJcbiAqIEByZXR1cm4geyp9XG4gKiBAcHJvdGVjdGVkXG4gKi9cbmZ1bmN0aW9uIGdldEZpcnN0VHJ1dGh5XyhhLCBiKSB7XG5cdHJldHVybiBhIHx8IGI7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgbmFtZSBvZiB0aGUgZ2l2ZW4gZnVuY3Rpb24uIElmIHRoZSBjdXJyZW50IGJyb3dzZXIgZG9lc24ndFxuICogc3VwcG9ydCB0aGUgYG5hbWVgIHByb3BlcnR5LCBsaWtlIElFMTEsIHRoaXMgd2lsbCBjYWxjdWxhdGUgaXQgZnJvbSB0aGUgZnVuY3Rpb24nc1xuICogY29udGVudCBzdHJpbmcuXG4gKiBAcGFyYW0geyFmdW5jdGlvbigpfSBmblxuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RnVuY3Rpb25OYW1lKGZuKSB7XG5cdGlmICghZm4ubmFtZSkge1xuXHRcdGNvbnN0IHN0ciA9IGZuLnRvU3RyaW5nKCk7XG5cdFx0Zm4ubmFtZSA9IHN0ci5zdWJzdHJpbmcoOSwgc3RyLmluZGV4T2YoJygnKSk7XG5cdH1cblx0cmV0dXJuIGZuLm5hbWU7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgdmFsdWUgb2YgYSBzdGF0aWMgcHJvcGVydHkgaW4gdGhlIGdpdmVuIGNsYXNzLiBUaGUgdmFsdWUgd2lsbCBiZVxuICogaW5oZXJpdGVkIGZyb20gYW5jZXN0b3JzIGFzIGV4cGVjdGVkLCB1bmxlc3MgYSBjdXN0b20gbWVyZ2UgZnVuY3Rpb24gaXMgZ2l2ZW4sXG4gKiB3aGljaCBjYW4gY2hhbmdlIGhvdyB0aGUgc3VwZXIgY2xhc3NlcycgdmFsdWUgZm9yIHRoYXQgcHJvcGVydHkgd2lsbCBiZSBtZXJnZWRcbiAqIHRvZ2V0aGVyLlxuICogVGhlIGZpbmFsIG1lcmdlZCB2YWx1ZSB3aWxsIGJlIHN0b3JlZCBpbiBhbm90aGVyIHByb3BlcnR5LCBzbyB0aGF0IGl0IHdvbid0XG4gKiBiZSByZWNhbGN1bGF0ZWQgZXZlbiBpZiB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBtdWx0aXBsZSB0aW1lcy5cbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGN0b3IgQ2xhc3MgY29uc3RydWN0b3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHlOYW1lIFByb3BlcnR5IG5hbWUgdG8gYmUgbWVyZ2VkLlxuICogQHBhcmFtIHtmdW5jdGlvbigqLCAqKToqPX0gbWVyZ2VGbiBGdW5jdGlvbiB0aGF0IHJlY2VpdmVzIHRoZSBtZXJnZWRcbiAqICAgICB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgc28gZmFyIGFuZCB0aGUgbmV4dCB2YWx1ZSB0byBiZSBtZXJnZWQgdG8gaXQuXG4gKiAgICAgU2hvdWxkIHJldHVybiB0aGVzZSB0d28gbWVyZ2VkIHRvZ2V0aGVyLiBJZiBub3QgcGFzc2VkIHRoZSBmaW5hbCBwcm9wZXJ0eVxuICogICAgIHdpbGwgYmUgdGhlIGZpcnN0IHRydXRoeSB2YWx1ZSBhbW9uZyBhbmNlc3RvcnMuXG4gKiBAcmV0dXJuIHtPYmplY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGF0aWNQcm9wZXJ0eShcblx0Y3Rvcixcblx0cHJvcGVydHlOYW1lLFxuXHRtZXJnZUZuID0gZ2V0Rmlyc3RUcnV0aHlfXG4pIHtcblx0Y29uc3QgbWVyZ2VkTmFtZSA9IHByb3BlcnR5TmFtZSArICdfTUVSR0VEJztcblx0aWYgKCFjdG9yLmhhc093blByb3BlcnR5KG1lcmdlZE5hbWUpKSB7XG5cdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cdFx0bGV0IG1lcmdlZCA9IGN0b3IuaGFzT3duUHJvcGVydHkocHJvcGVydHlOYW1lKVxuXHRcdFx0PyBjdG9yW3Byb3BlcnR5TmFtZV1cblx0XHRcdDogbnVsbDtcblx0XHRpZiAoY3Rvci5fX3Byb3RvX18gJiYgIWN0b3IuX19wcm90b19fLmlzUHJvdG90eXBlT2YoRnVuY3Rpb24pKSB7XG5cdFx0XHRtZXJnZWQgPSBtZXJnZUZuKFxuXHRcdFx0XHRtZXJnZWQsXG5cdFx0XHRcdGdldFN0YXRpY1Byb3BlcnR5KGN0b3IuX19wcm90b19fLCBwcm9wZXJ0eU5hbWUsIG1lcmdlRm4pXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRjdG9yW21lcmdlZE5hbWVdID0gbWVyZ2VkO1xuXHR9XG5cdHJldHVybiBjdG9yW21lcmdlZE5hbWVdO1xufVxuXG4vKipcbiAqIEdldHMgYW4gdW5pcXVlIGlkLiBJZiBgb2JqZWN0YCBhcmd1bWVudCBpcyBwYXNzZWQsIHRoZSBvYmplY3QgaXNcbiAqIG11dGF0ZWQgd2l0aCBhbiB1bmlxdWUgaWQuIENvbnNlY3V0aXZlIGNhbGxzIHdpdGggdGhlIHNhbWUgb2JqZWN0XG4gKiByZWZlcmVuY2Ugd29uJ3QgbXV0YXRlIHRoZSBvYmplY3QgYWdhaW4sIGluc3RlYWQgdGhlIGN1cnJlbnQgb2JqZWN0IHVpZFxuICogcmV0dXJucy4gU2VlIHtAbGluayBVSURfUFJPUEVSVFl9LlxuICogQHBhcmFtIHtPYmplY3Q9fSBvYmplY3QgT3B0aW9uYWwgb2JqZWN0IHRvIGJlIG11dGF0ZWQgd2l0aCB0aGUgdWlkLiBJZlxuICogICAgIG5vdCBzcGVjaWZpZWQgdGhpcyBtZXRob2Qgb25seSByZXR1cm5zIHRoZSB1aWQuXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBub0luaGVyaXRhbmNlIE9wdGlvbmFsIGZsYWcgaW5kaWNhdGluZyBpZiB0aGlzXG4gKiAgICAgb2JqZWN0J3MgdWlkIHByb3BlcnR5IGNhbiBiZSBpbmhlcml0ZWQgZnJvbSBwYXJlbnRzIG9yIG5vdC5cbiAqIEB0aHJvd3Mge0Vycm9yfSB3aGVuIGludm9rZWQgdG8gaW5kaWNhdGUgdGhlIG1ldGhvZCBzaG91bGQgYmUgb3ZlcnJpZGRlbi5cbiAqIEByZXR1cm4ge251bWJlcn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFVpZChvYmplY3QsIG5vSW5oZXJpdGFuY2UpIHtcblx0aWYgKG9iamVjdCkge1xuXHRcdGxldCBpZCA9IG9iamVjdFtVSURfUFJPUEVSVFldO1xuXHRcdGlmIChub0luaGVyaXRhbmNlICYmICFvYmplY3QuaGFzT3duUHJvcGVydHkoVUlEX1BST1BFUlRZKSkge1xuXHRcdFx0aWQgPSBudWxsO1xuXHRcdH1cblx0XHRyZXR1cm4gaWQgfHwgKG9iamVjdFtVSURfUFJPUEVSVFldID0gdW5pcXVlSWRDb3VudGVyXysrKTtcblx0fVxuXHRyZXR1cm4gdW5pcXVlSWRDb3VudGVyXysrO1xufVxuXG4vKipcbiAqIFRoZSBpZGVudGl0eSBmdW5jdGlvbi4gUmV0dXJucyBpdHMgZmlyc3QgYXJndW1lbnQuXG4gKiBAcGFyYW0geyo9fSByZXR1cm5WYWx1ZSBUaGUgc2luZ2xlIHZhbHVlIHRoYXQgd2lsbCBiZSByZXR1cm5lZC5cbiAqIEByZXR1cm4gez99IFRoZSBmaXJzdCBhcmd1bWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlkZW50aXR5RnVuY3Rpb24ocmV0dXJuVmFsdWUpIHtcblx0cmV0dXJuIHJldHVyblZhbHVlO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGEgYm9vbGVhbi5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGJvb2xlYW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Jvb2xlYW4odmFsKSB7XG5cdHJldHVybiB0eXBlb2YgdmFsID09PSAnYm9vbGVhbic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgbm90IHVuZGVmaW5lZC5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGRlZmluZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RlZih2YWwpIHtcblx0cmV0dXJuIHZhbCAhPT0gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBub3QgdW5kZWZpbmVkIG9yIG51bGwuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGVmQW5kTm90TnVsbCh2YWwpIHtcblx0cmV0dXJuIGlzRGVmKHZhbCkgJiYgIWlzTnVsbCh2YWwpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIGRvY3VtZW50LlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RvY3VtZW50KHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbC5ub2RlVHlwZSA9PT0gOTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBkb2N1bWVudC1mcmFnbWVudC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEb2N1bWVudEZyYWdtZW50KHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbC5ub2RlVHlwZSA9PT0gMTE7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgZG9tIGVsZW1lbnQuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRWxlbWVudCh2YWwpIHtcblx0cmV0dXJuIHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB2YWwubm9kZVR5cGUgPT09IDE7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYSBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGEgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbCkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgbnVsbC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNOdWxsKHZhbCkge1xuXHRyZXR1cm4gdmFsID09PSBudWxsO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGEgbnVtYmVyLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgYSBudW1iZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc051bWJlcih2YWwpIHtcblx0cmV0dXJuIHR5cGVvZiB2YWwgPT09ICdudW1iZXInO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIHdpbmRvdy5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNXaW5kb3codmFsKSB7XG5cdHJldHVybiB2YWwgIT09IG51bGwgJiYgdmFsID09PSB2YWwud2luZG93O1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGFuIG9iamVjdC4gVGhpcyBpbmNsdWRlcyBhcnJheXNcbiAqIGFuZCBmdW5jdGlvbnMuXG4gKiBAcGFyYW0gez99IHZhbCBWYXJpYWJsZSB0byB0ZXN0LlxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB2YXJpYWJsZSBpcyBhbiBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc09iamVjdCh2YWwpIHtcblx0Y29uc3QgdHlwZSA9IHR5cGVvZiB2YWw7XG5cdHJldHVybiAodHlwZSA9PT0gJ29iamVjdCcgJiYgdmFsICE9PSBudWxsKSB8fCB0eXBlID09PSAnZnVuY3Rpb24nO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIFByb21pc2UuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUHJvbWlzZSh2YWwpIHtcblx0cmV0dXJuIHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgdmFsLnRoZW4gPT09ICdmdW5jdGlvbic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgc3RyaW5nLlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1N0cmluZyh2YWwpIHtcblx0cmV0dXJuIHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnIHx8IHZhbCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuLyoqXG4gKiBTZXRzIHRvIHRydWUgaWYgcnVubmluZyBpbnNpZGUgTm9kZS5qcyBlbnZpcm9ubWVudCB3aXRoIGV4dHJhIGNoZWNrIGZvclxuICogYHByb2Nlc3MuYnJvd3NlcmAgdG8gc2tpcCBLYXJtYSBydW5uZXIgZW52aXJvbm1lbnQuIEthcm1hIGVudmlyb25tZW50IGhhc1xuICogYHByb2Nlc3NgIGRlZmluZWQgZXZlbiB0aG91Z2ggaXQgcnVucyBvbiB0aGUgYnJvd3Nlci5cbiAqIEBwYXJhbSB7P09iamVjdH0gb3B0aW9ucyBDb250YWlucyBgY2hlY2tFbnZgIHByb3BlcnR5IHdoaWNoIGlmIHRydWUsIGNoZWNrc1xuICogdGhlIE5PREVfRU5WIHZhcmlhYmxlLiBJZiBOT0RFX0VOViBlcXVhbHMgJ3Rlc3QnLCB0aGUgZnVuY3Rpb24gcmV0dXJucyBmYWxzZS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1NlcnZlclNpZGUob3B0aW9ucyA9IHtjaGVja0VudjogdHJ1ZX0pIHtcblx0bGV0IHNlcnZlclNpZGUgPSB0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgIXByb2Nlc3MuYnJvd3Nlcjtcblx0aWYgKHNlcnZlclNpZGUgJiYgb3B0aW9ucy5jaGVja0Vudikge1xuXHRcdHNlcnZlclNpZGUgPVxuXHRcdFx0dHlwZW9mIHByb2Nlc3MuZW52ICE9PSAndW5kZWZpbmVkJyAmJlxuXHRcdFx0cHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICd0ZXN0Jztcblx0fVxuXHRyZXR1cm4gc2VydmVyU2lkZTtcbn1cblxuLyoqXG4gKiBOdWxsIGZ1bmN0aW9uIHVzZWQgZm9yIGRlZmF1bHQgdmFsdWVzIG9mIGNhbGxiYWNrcywgZXRjLlxuICogQHJldHVybiB7dm9pZH0gTm90aGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG51bGxGdW5jdGlvbigpIHt9XG4iLCIndXNlIHN0cmljdCc7XG5cbi8vIFRoaXMgZmlsZSBleGlzdHMganVzdCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHksIG1ha2luZyBzdXJlIHRoYXQgb2xkXG4vLyBkZWZhdWx0IGltcG9ydHMgZm9yIHRoaXMgZmlsZSBzdGlsbCB3b3JrLiBJdCdzIGJlc3QgdG8gdXNlIHRoZSBuYW1lZCBleHBvcnRzXG4vLyBmb3IgZWFjaCBmdW5jdGlvbiBpbnN0ZWFkIHRob3VnaCwgc2luY2UgdGhhdCBhbGxvd3MgYnVuZGxlcnMgbGlrZSBSb2xsdXAgdG9cbi8vIHJlZHVjZSB0aGUgYnVuZGxlIHNpemUgYnkgcmVtb3ZpbmcgdW51c2VkIGNvZGUuXG5pbXBvcnQgKiBhcyBjb3JlIGZyb20gJy4vY29yZU5hbWVkJztcblxuZXhwb3J0IGRlZmF1bHQgY29yZTtcbmV4cG9ydCB7Y29yZX07XG5leHBvcnQgKiBmcm9tICcuL2NvcmVOYW1lZCc7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogU2V0IG9mIHV0aWxpdGllcyBmb3IgYXJyYXkgb3BlcmF0aW9uc1xuICovXG5jbGFzcyBhcnJheSB7XG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGFycmF5cyBoYXZlIHRoZSBzYW1lIGNvbnRlbnQuXG5cdCAqIEBwYXJhbSB7IUFycmF5PCo+fSBhcnIxXG5cdCAqIEBwYXJhbSB7IUFycmF5PCo+fSBhcnIyXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRzdGF0aWMgZXF1YWwoYXJyMSwgYXJyMikge1xuXHRcdGlmIChhcnIxID09PSBhcnIyKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0aWYgKGFycjEubGVuZ3RoICE9PSBhcnIyLmxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFycjEubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChhcnIxW2ldICE9PSBhcnIyW2ldKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgZmlyc3QgdmFsdWUgaW4gdGhlIGdpdmVuIGFycmF5IHRoYXQgaXNuJ3QgdW5kZWZpbmVkLlxuXHQgKiBAcGFyYW0geyFBcnJheX0gYXJyXG5cdCAqIEByZXR1cm4geyp9XG5cdCAqL1xuXHRzdGF0aWMgZmlyc3REZWZpbmVkVmFsdWUoYXJyKSB7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChhcnJbaV0gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRyZXR1cm4gYXJyW2ldO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBUcmFuc2Zvcm1zIHRoZSBpbnB1dCBuZXN0ZWQgYXJyYXkgdG8gYmVjb21lIGZsYXQuXG5cdCAqIEBwYXJhbSB7QXJyYXkuPCp8QXJyYXkuPCo+Pn0gYXJyIE5lc3RlZCBhcnJheSB0byBmbGF0dGVuLlxuXHQgKiBAcGFyYW0ge0FycmF5LjwqPj19IG91dHB1dCBPcHRpb25hbCBvdXRwdXQgYXJyYXkuXG5cdCAqIEByZXR1cm4ge0FycmF5LjwqPn0gRmxhdCBhcnJheS5cblx0ICovXG5cdHN0YXRpYyBmbGF0dGVuKGFyciwgb3V0cHV0ID0gW10pIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKEFycmF5LmlzQXJyYXkoYXJyW2ldKSkge1xuXHRcdFx0XHRhcnJheS5mbGF0dGVuKGFycltpXSwgb3V0cHV0KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG91dHB1dC5wdXNoKGFycltpXSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBvdXRwdXQ7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBhIHBhcnRpY3VsYXIgdmFsdWUgZnJvbSBhbiBhcnJheS5cblx0ICogQHBhcmFtIHtBcnJheS48VD59IGFyciBBcnJheSBmcm9tIHdoaWNoIHRvIHJlbW92ZSB2YWx1ZS5cblx0ICogQHBhcmFtIHtUfSBvYmogT2JqZWN0IHRvIHJlbW92ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhbiBlbGVtZW50IHdhcyByZW1vdmVkLlxuXHQgKiBAdGVtcGxhdGUgVFxuXHQgKi9cblx0c3RhdGljIHJlbW92ZShhcnIsIG9iaikge1xuXHRcdGNvbnN0IGkgPSBhcnIuaW5kZXhPZihvYmopO1xuXHRcdGxldCBydjtcblx0XHRpZiAoKHJ2ID0gaSA+PSAwKSkge1xuXHRcdFx0YXJyYXkucmVtb3ZlQXQoYXJyLCBpKTtcblx0XHR9XG5cdFx0cmV0dXJuIHJ2O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgZnJvbSBhbiBhcnJheSB0aGUgZWxlbWVudCBhdCBpbmRleCBpXG5cdCAqIEBwYXJhbSB7QXJyYXl9IGFyciBBcnJheSBvciBhcnJheSBsaWtlIG9iamVjdCBmcm9tIHdoaWNoIHRvIHJlbW92ZSB2YWx1ZS5cblx0ICogQHBhcmFtIHtudW1iZXJ9IGkgVGhlIGluZGV4IHRvIHJlbW92ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhbiBlbGVtZW50IHdhcyByZW1vdmVkLlxuXHQgKi9cblx0c3RhdGljIHJlbW92ZUF0KGFyciwgaSkge1xuXHRcdHJldHVybiBBcnJheS5wcm90b3R5cGUuc3BsaWNlLmNhbGwoYXJyLCBpLCAxKS5sZW5ndGggPT09IDE7XG5cdH1cblxuXHQvKipcblx0ICogU2xpY2VzIHRoZSBnaXZlbiBhcnJheSwganVzdCBsaWtlIEFycmF5LnByb3RvdHlwZS5zbGljZSwgYnV0IHRoaXNcblx0ICogaXMgZmFzdGVyIGFuZCB3b3JraW5nIG9uIGFsbCBhcnJheS1saWtlIG9iamVjdHMgKGxpa2UgYXJndW1lbnRzKS5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBhcnIgQXJyYXktbGlrZSBvYmplY3QgdG8gc2xpY2UuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydCBUaGUgaW5kZXggdGhhdCBzaG91bGQgc3RhcnQgdGhlIHNsaWNlLlxuXHQgKiBAcGFyYW0ge251bWJlcj19IGVuZCBUaGUgaW5kZXggd2hlcmUgdGhlIHNsaWNlIHNob3VsZCBlbmQsIG5vdFxuXHQgKiAgIGluY2x1ZGVkIGluIHRoZSBmaW5hbCBhcnJheS4gSWYgbm90IGdpdmVuLCBhbGwgZWxlbWVudHMgYWZ0ZXIgdGhlXG5cdCAqICAgc3RhcnQgaW5kZXggd2lsbCBiZSBpbmNsdWRlZC5cblx0ICogQHJldHVybiB7IUFycmF5fVxuXHQgKi9cblx0c3RhdGljIHNsaWNlKGFyciwgc3RhcnQsIGVuZCA9IGFyci5sZW5ndGgpIHtcblx0XHRjb25zdCBzbGljZWQgPSBbXTtcblx0XHRmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuXHRcdFx0c2xpY2VkLnB1c2goYXJyW2ldKTtcblx0XHR9XG5cdFx0cmV0dXJuIHNsaWNlZDtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBhcnJheTtcbiIsIi8qICFcbiAqIFBvbHlmaWxsIGZyb20gR29vZ2xlJ3MgQ2xvc3VyZSBMaWJyYXJ5LlxuICogQ29weXJpZ2h0IDIwMTMgVGhlIENsb3N1cmUgTGlicmFyeSBBdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHtpc1NlcnZlclNpZGV9IGZyb20gJy4uL2NvcmVOYW1lZCc7XG5cbmNvbnN0IGFzeW5jID0ge307XG5cbi8qKlxuICogVGhyb3cgYW4gaXRlbSB3aXRob3V0IGludGVycnVwdGluZyB0aGUgY3VycmVudCBleGVjdXRpb24gY29udGV4dC4gIEZvclxuICogZXhhbXBsZSwgaWYgcHJvY2Vzc2luZyBhIGdyb3VwIG9mIGl0ZW1zIGluIGEgbG9vcCwgc29tZXRpbWVzIGl0IGlzIHVzZWZ1bFxuICogdG8gcmVwb3J0IGFuIGVycm9yIHdoaWxlIHN0aWxsIGFsbG93aW5nIHRoZSByZXN0IG9mIHRoZSBiYXRjaCB0byBiZVxuICogcHJvY2Vzc2VkLlxuICogQHBhcmFtIHsqfSBleGNlcHRpb25cbiAqL1xuYXN5bmMudGhyb3dFeGNlcHRpb24gPSBmdW5jdGlvbihleGNlcHRpb24pIHtcblx0Ly8gRWFjaCB0aHJvdyBuZWVkcyB0byBiZSBpbiBpdHMgb3duIGNvbnRleHQuXG5cdGFzeW5jLm5leHRUaWNrKGZ1bmN0aW9uKCkge1xuXHRcdHRocm93IGV4Y2VwdGlvbjtcblx0fSk7XG59O1xuXG4vKipcbiAqIEZpcmVzIHRoZSBwcm92aWRlZCBjYWxsYmFjayBqdXN0IGJlZm9yZSB0aGUgY3VycmVudCBjYWxsc3RhY2sgdW53aW5kcywgb3IgYXNcbiAqIHNvb24gYXMgcG9zc2libGUgYWZ0ZXIgdGhlIGN1cnJlbnQgSlMgZXhlY3V0aW9uIGNvbnRleHQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKHRoaXM6VEhJUyl9IGNhbGxiYWNrXG4gKiBAcGFyYW0ge1RISVM9fSBjb250ZXh0IE9iamVjdCB0byB1c2UgYXMgdGhlIFwidGhpcyB2YWx1ZVwiIHdoZW4gY2FsbGluZ1xuICogICAgIHRoZSBwcm92aWRlZCBmdW5jdGlvbi5cbiAqIEB0ZW1wbGF0ZSBUSElTXG4gKi9cbmFzeW5jLnJ1biA9IGZ1bmN0aW9uKGNhbGxiYWNrLCBjb250ZXh0KSB7XG5cdGlmICghYXN5bmMucnVuLndvcmtRdWV1ZVNjaGVkdWxlZF8pIHtcblx0XHQvLyBOb3RoaW5nIGlzIGN1cnJlbnRseSBzY2hlZHVsZWQsIHNjaGVkdWxlIGl0IG5vdy5cblx0XHRhc3luYy5uZXh0VGljayhhc3luYy5ydW4ucHJvY2Vzc1dvcmtRdWV1ZSk7XG5cdFx0YXN5bmMucnVuLndvcmtRdWV1ZVNjaGVkdWxlZF8gPSB0cnVlO1xuXHR9XG5cblx0YXN5bmMucnVuLndvcmtRdWV1ZV8ucHVzaChuZXcgYXN5bmMucnVuLldvcmtJdGVtXyhjYWxsYmFjaywgY29udGV4dCkpO1xufTtcblxuLyoqIEBwcml2YXRlIHtib29sZWFufSAqL1xuYXN5bmMucnVuLndvcmtRdWV1ZVNjaGVkdWxlZF8gPSBmYWxzZTtcblxuLyoqIEBwcml2YXRlIHshQXJyYXkuPCFhc3luYy5ydW4uV29ya0l0ZW1fPn0gKi9cbmFzeW5jLnJ1bi53b3JrUXVldWVfID0gW107XG5cbi8qKlxuICogUnVuIGFueSBwZW5kaW5nIGFzeW5jLnJ1biB3b3JrIGl0ZW1zLiBUaGlzIGZ1bmN0aW9uIGlzIG5vdCBpbnRlbmRlZFxuICogZm9yIGdlbmVyYWwgdXNlLCBidXQgZm9yIHVzZSBieSBlbnRyeSBwb2ludCBoYW5kbGVycyB0byBydW4gaXRlbXMgYWhlYWQgb2ZcbiAqIGFzeW5jLm5leHRUaWNrLlxuICovXG5hc3luYy5ydW4ucHJvY2Vzc1dvcmtRdWV1ZSA9IGZ1bmN0aW9uKCkge1xuXHQvLyBOT1RFOiBhZGRpdGlvbmFsIHdvcmsgcXVldWUgaXRlbXMgbWF5IGJlIHB1c2hlZCB3aGlsZSBwcm9jZXNzaW5nLlxuXHR3aGlsZSAoYXN5bmMucnVuLndvcmtRdWV1ZV8ubGVuZ3RoKSB7XG5cdFx0Ly8gRG9uJ3QgbGV0IHRoZSB3b3JrIHF1ZXVlIGdyb3cgaW5kZWZpbml0ZWx5LlxuXHRcdGNvbnN0IHdvcmtJdGVtcyA9IGFzeW5jLnJ1bi53b3JrUXVldWVfO1xuXHRcdGFzeW5jLnJ1bi53b3JrUXVldWVfID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB3b3JrSXRlbXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IHdvcmtJdGVtID0gd29ya0l0ZW1zW2ldO1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0d29ya0l0ZW0uZm4uY2FsbCh3b3JrSXRlbS5zY29wZSk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdGFzeW5jLnRocm93RXhjZXB0aW9uKGUpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIFRoZXJlIGFyZSBubyBtb3JlIHdvcmsgaXRlbXMsIHJlc2V0IHRoZSB3b3JrIHF1ZXVlLlxuXHRhc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXyA9IGZhbHNlO1xufTtcblxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqIEBmaW5hbFxuICogQHN0cnVjdFxuICogQHByaXZhdGVcbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGZuXG4gKiBAcGFyYW0ge09iamVjdHxudWxsfHVuZGVmaW5lZH0gc2NvcGVcbiAqL1xuYXN5bmMucnVuLldvcmtJdGVtXyA9IGZ1bmN0aW9uKGZuLCBzY29wZSkge1xuXHQvKiogQGNvbnN0ICovXG5cdHRoaXMuZm4gPSBmbjtcblx0LyoqIEBjb25zdCAqL1xuXHR0aGlzLnNjb3BlID0gc2NvcGU7XG59O1xuXG4vKipcbiAqIEZpcmVzIHRoZSBwcm92aWRlZCBjYWxsYmFja3MgYXMgc29vbiBhcyBwb3NzaWJsZSBhZnRlciB0aGUgY3VycmVudCBKU1xuICogZXhlY3V0aW9uIGNvbnRleHQuIHNldFRpbWVvdXQo4oCmLCAwKSBhbHdheXMgdGFrZXMgYXQgbGVhc3QgNW1zIGZvciBsZWdhY3lcbiAqIHJlYXNvbnMuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKHRoaXM6U0NPUEUpfSBjYWxsYmFjayBDYWxsYmFjayBmdW5jdGlvbiB0byBmaXJlIGFzIHNvb24gYXNcbiAqICAgICBwb3NzaWJsZS5cbiAqIEBwYXJhbSB7U0NPUEU9fSBjb250ZXh0IE9iamVjdCBpbiB3aG9zZSBzY29wZSB0byBjYWxsIHRoZSBsaXN0ZW5lci5cbiAqIEB0ZW1wbGF0ZSBTQ09QRVxuICovXG5hc3luYy5uZXh0VGljayA9IGZ1bmN0aW9uKGNhbGxiYWNrLCBjb250ZXh0KSB7XG5cdGxldCBjYiA9IGNhbGxiYWNrO1xuXHRpZiAoY29udGV4dCkge1xuXHRcdGNiID0gY2FsbGJhY2suYmluZChjb250ZXh0KTtcblx0fVxuXHRjYiA9IGFzeW5jLm5leHRUaWNrLndyYXBDYWxsYmFja18oY2IpO1xuXHQvLyBMb29rIGZvciBhbmQgY2FjaGUgdGhlIGN1c3RvbSBmYWxsYmFjayB2ZXJzaW9uIG9mIHNldEltbWVkaWF0ZS5cblx0aWYgKCFhc3luYy5uZXh0VGljay5zZXRJbW1lZGlhdGVfKSB7XG5cdFx0aWYgKFxuXHRcdFx0dHlwZW9mIHNldEltbWVkaWF0ZSA9PT0gJ2Z1bmN0aW9uJyAmJlxuXHRcdFx0aXNTZXJ2ZXJTaWRlKHtjaGVja0VudjogZmFsc2V9KVxuXHRcdCkge1xuXHRcdFx0YXN5bmMubmV4dFRpY2suc2V0SW1tZWRpYXRlXyA9IHNldEltbWVkaWF0ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cdFx0XHRhc3luYy5uZXh0VGljay5zZXRJbW1lZGlhdGVfID0gYXN5bmMubmV4dFRpY2suZ2V0U2V0SW1tZWRpYXRlRW11bGF0b3JfKCk7XG5cdFx0fVxuXHR9XG5cdGFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8oY2IpO1xufTtcblxuLyoqXG4gKiBDYWNoZSBmb3IgdGhlIHNldEltbWVkaWF0ZSBpbXBsZW1lbnRhdGlvbi5cbiAqIEB0eXBlIHtmdW5jdGlvbihmdW5jdGlvbigpKX1cbiAqIEBwcml2YXRlXG4gKi9cbmFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8gPSBudWxsO1xuXG4vKipcbiAqIERldGVybWluZXMgdGhlIGJlc3QgcG9zc2libGUgaW1wbGVtZW50YXRpb24gdG8gcnVuIGEgZnVuY3Rpb24gYXMgc29vbiBhc1xuICogdGhlIEpTIGV2ZW50IGxvb3AgaXMgaWRsZS5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGZ1bmN0aW9uKCkpfSBUaGUgXCJzZXRJbW1lZGlhdGVcIiBpbXBsZW1lbnRhdGlvbi5cbiAqIEBwcml2YXRlXG4gKi9cbmFzeW5jLm5leHRUaWNrLmdldFNldEltbWVkaWF0ZUVtdWxhdG9yXyA9IGZ1bmN0aW9uKCkge1xuXHQvLyBDcmVhdGUgYSBwcml2YXRlIG1lc3NhZ2UgY2hhbm5lbCBhbmQgdXNlIGl0IHRvIHBvc3RNZXNzYWdlIGVtcHR5IG1lc3NhZ2VzXG5cdC8vIHRvIG91cnNlbHZlcy5cblx0bGV0IENoYW5uZWw7XG5cblx0Ly8gVmVyaWZ5IGlmIHZhcmlhYmxlIGlzIGRlZmluZWQgb24gdGhlIGN1cnJlbnQgcnVudGltZSAoaS5lLiwgbm9kZSwgYnJvd3NlcikuXG5cdC8vIENhbid0IHVzZSB0eXBlb2YgZW5jbG9zZWQgaW4gYSBmdW5jdGlvbiAoc3VjaCBhcyBjb3JlLmlzRnVuY3Rpb24pIG9yIGFuXG5cdC8vIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93biB3aGVuIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQgb24gYW4gZW52aXJvbm1lbnRcblx0Ly8gd2hlcmUgdGhlIHZhcmlhYmxlIGlzIHVuZGVmaW5lZC5cblx0aWYgKHR5cGVvZiBNZXNzYWdlQ2hhbm5lbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdENoYW5uZWwgPSBNZXNzYWdlQ2hhbm5lbDtcblx0fVxuXG5cdC8vIElmIE1lc3NhZ2VDaGFubmVsIGlzIG5vdCBhdmFpbGFibGUgYW5kIHdlIGFyZSBpbiBhIGJyb3dzZXIsIGltcGxlbWVudFxuXHQvLyBhbiBpZnJhbWUgYmFzZWQgcG9seWZpbGwgaW4gYnJvd3NlcnMgdGhhdCBoYXZlIHBvc3RNZXNzYWdlIGFuZFxuXHQvLyBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyLiBUaGUgbGF0dGVyIGV4Y2x1ZGVzIElFOCBiZWNhdXNlIGl0IGhhcyBhXG5cdC8vIHN5bmNocm9ub3VzIHBvc3RNZXNzYWdlIGltcGxlbWVudGF0aW9uLlxuXHRpZiAoXG5cdFx0dHlwZW9mIENoYW5uZWwgPT09ICd1bmRlZmluZWQnICYmXG5cdFx0dHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiZcblx0XHR3aW5kb3cucG9zdE1lc3NhZ2UgJiZcblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lclxuXHQpIHtcblx0XHQvKiogQGNvbnN0cnVjdG9yICovXG5cdFx0Q2hhbm5lbCA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0Ly8gTWFrZSBhbiBlbXB0eSwgaW52aXNpYmxlIGlmcmFtZS5cblx0XHRcdGNvbnN0IGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO1xuXHRcdFx0aWZyYW1lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0XHRpZnJhbWUuc3JjID0gJyc7XG5cdFx0XHRpZnJhbWUudGl0bGUgPSAnJztcblx0XHRcdGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZChpZnJhbWUpO1xuXHRcdFx0Y29uc3Qgd2luID0gaWZyYW1lLmNvbnRlbnRXaW5kb3c7XG5cdFx0XHRjb25zdCBkb2MgPSB3aW4uZG9jdW1lbnQ7XG5cdFx0XHRkb2Mub3BlbigpO1xuXHRcdFx0ZG9jLndyaXRlKCcnKTtcblx0XHRcdGRvYy5jbG9zZSgpO1xuXHRcdFx0Y29uc3QgbWVzc2FnZSA9ICdjYWxsSW1tZWRpYXRlJyArIE1hdGgucmFuZG9tKCk7XG5cdFx0XHRjb25zdCBvcmlnaW4gPSB3aW4ubG9jYXRpb24ucHJvdG9jb2wgKyAnLy8nICsgd2luLmxvY2F0aW9uLmhvc3Q7XG5cdFx0XHRjb25zdCBvbm1lc3NhZ2UgPSBmdW5jdGlvbihlKSB7XG5cdFx0XHRcdC8vIFZhbGlkYXRlIG9yaWdpbiBhbmQgbWVzc2FnZSB0byBtYWtlIHN1cmUgdGhhdCB0aGlzIG1lc3NhZ2Ugd2FzXG5cdFx0XHRcdC8vIGludGVuZGVkIGZvciB1cy5cblx0XHRcdFx0aWYgKGUub3JpZ2luICE9PSBvcmlnaW4gJiYgZS5kYXRhICE9PSBtZXNzYWdlKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMucG9ydDEub25tZXNzYWdlKCk7XG5cdFx0XHR9LmJpbmQodGhpcyk7XG5cdFx0XHR3aW4uYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9ubWVzc2FnZSwgZmFsc2UpO1xuXHRcdFx0dGhpcy5wb3J0MSA9IHt9O1xuXHRcdFx0dGhpcy5wb3J0MiA9IHtcblx0XHRcdFx0cG9zdE1lc3NhZ2U6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHdpbi5wb3N0TWVzc2FnZShtZXNzYWdlLCBvcmlnaW4pO1xuXHRcdFx0XHR9LFxuXHRcdFx0fTtcblx0XHR9O1xuXHR9XG5cdGlmICh0eXBlb2YgQ2hhbm5lbCAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRjb25zdCBjaGFubmVsID0gbmV3IENoYW5uZWwoKTtcblx0XHQvLyBVc2UgYSBmaWZvIGxpbmtlZCBsaXN0IHRvIGNhbGwgY2FsbGJhY2tzIGluIHRoZSByaWdodCBvcmRlci5cblx0XHRsZXQgaGVhZCA9IHt9O1xuXHRcdGxldCB0YWlsID0gaGVhZDtcblx0XHRjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0aGVhZCA9IGhlYWQubmV4dDtcblx0XHRcdGNvbnN0IGNiID0gaGVhZC5jYjtcblx0XHRcdGhlYWQuY2IgPSBudWxsO1xuXHRcdFx0Y2IoKTtcblx0XHR9O1xuXHRcdHJldHVybiBmdW5jdGlvbihjYikge1xuXHRcdFx0dGFpbC5uZXh0ID0ge1xuXHRcdFx0XHRjYjogY2IsXG5cdFx0XHR9O1xuXHRcdFx0dGFpbCA9IHRhaWwubmV4dDtcblx0XHRcdGNoYW5uZWwucG9ydDIucG9zdE1lc3NhZ2UoMCk7XG5cdFx0fTtcblx0fVxuXHQvLyBJbXBsZW1lbnRhdGlvbiBmb3IgSUU2LTg6IFNjcmlwdCBlbGVtZW50cyBmaXJlIGFuIGFzeW5jaHJvbm91c1xuXHQvLyBvbnJlYWR5c3RhdGVjaGFuZ2UgZXZlbnQgd2hlbiBpbnNlcnRlZCBpbnRvIHRoZSBET00uXG5cdGlmIChcblx0XHR0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnICYmXG5cdFx0J29ucmVhZHlzdGF0ZWNoYW5nZScgaW4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jylcblx0KSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uKGNiKSB7XG5cdFx0XHRsZXQgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG5cdFx0XHRzY3JpcHQub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdC8vIENsZWFuIHVwIGFuZCBjYWxsIHRoZSBjYWxsYmFjay5cblx0XHRcdFx0c2NyaXB0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG5cdFx0XHRcdHNjcmlwdC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHNjcmlwdCk7XG5cdFx0XHRcdHNjcmlwdCA9IG51bGw7XG5cdFx0XHRcdGNiKCk7XG5cdFx0XHRcdGNiID0gbnVsbDtcblx0XHRcdH07XG5cdFx0XHRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcblx0XHR9O1xuXHR9XG5cdC8vIEZhbGwgYmFjayB0byBzZXRUaW1lb3V0IHdpdGggMC4gSW4gYnJvd3NlcnMgdGhpcyBjcmVhdGVzIGEgZGVsYXkgb2YgNW1zXG5cdC8vIG9yIG1vcmUuXG5cdHJldHVybiBmdW5jdGlvbihjYikge1xuXHRcdHNldFRpbWVvdXQoY2IsIDApO1xuXHR9O1xufTtcblxuLyoqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdGhhdCBpcyBvdmVycmlkZWQgdG8gcHJvdGVjdCBjYWxsYmFja3Mgd2l0aCBlbnRyeSBwb2ludFxuICogbW9uaXRvciBpZiB0aGUgYXBwbGljYXRpb24gbW9uaXRvcnMgZW50cnkgcG9pbnRzLlxuICogQHBhcmFtIHtmdW5jdGlvbigpfSBjYWxsYmFjayBDYWxsYmFjayBmdW5jdGlvbiB0byBmaXJlIGFzIHNvb24gYXMgcG9zc2libGUuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbigpfSBUaGUgd3JhcHBlZCBjYWxsYmFjay5cbiAqIEBwcml2YXRlXG4gKi9cbmFzeW5jLm5leHRUaWNrLndyYXBDYWxsYmFja18gPSBmdW5jdGlvbihjYWxsYmFjaykge1xuXHRyZXR1cm4gY2FsbGJhY2s7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYztcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBEaXNwb3NhYmxlIHV0aWxpdHkuIFdoZW4gaW5oZXJpdGVkIHByb3ZpZGVzIHRoZSBgZGlzcG9zZWAgZnVuY3Rpb24gdG8gaXRzXG4gKiBzdWJjbGFzcywgd2hpY2ggaXMgcmVzcG9uc2libGUgZm9yIGRpc3Bvc2luZyBvZiBhbnkgb2JqZWN0IHJlZmVyZW5jZXNcbiAqIHdoZW4gYW4gaW5zdGFuY2Ugd29uJ3QgYmUgdXNlZCBhbnltb3JlLiBTdWJjbGFzc2VzIHNob3VsZCBvdmVycmlkZVxuICogYGRpc3Bvc2VJbnRlcm5hbGAgdG8gaW1wbGVtZW50IGFueSBzcGVjaWZpYyBkaXNwb3NpbmcgbG9naWMuXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuY2xhc3MgRGlzcG9zYWJsZSB7XG5cdC8qKlxuXHQgKiBEaXNwb3NhYmxlIGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHQvKipcblx0XHQgKiBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBpbnN0YW5jZSBoYXMgYWxyZWFkeSBiZWVuIGRpc3Bvc2VkLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmRpc3Bvc2VkXyA9IGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy4gQ2FsbHMgYGRpc3Bvc2VJbnRlcm5hbGAuXG5cdCAqL1xuXHRkaXNwb3NlKCkge1xuXHRcdGlmICghdGhpcy5kaXNwb3NlZF8pIHtcblx0XHRcdHRoaXMuZGlzcG9zZUludGVybmFsKCk7XG5cdFx0XHR0aGlzLmRpc3Bvc2VkXyA9IHRydWU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFN1YmNsYXNzZXMgc2hvdWxkIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGltcGxlbWVudCBhbnkgc3BlY2lmaWNcblx0ICogZGlzcG9zaW5nIGxvZ2ljIChsaWtlIGNsZWFyaW5nIHJlZmVyZW5jZXMgYW5kIGNhbGxpbmcgYGRpc3Bvc2VgIG9uIG90aGVyXG5cdCAqIGRpc3Bvc2FibGVzKS5cblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHt9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGlzIGluc3RhbmNlIGhhcyBhbHJlYWR5IGJlZW4gZGlzcG9zZWQuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRpc0Rpc3Bvc2VkKCkge1xuXHRcdHJldHVybiB0aGlzLmRpc3Bvc2VkXztcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBEaXNwb3NhYmxlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFNldCBvZiB1dGlsaXRpZXMgZm9yIG9iamVjdCBvcGVyYXRpb25zXG4gKi9cbmNsYXNzIG9iamVjdCB7XG5cdC8qKlxuXHQgKiBDb3BpZXMgYWxsIHRoZSBtZW1iZXJzIG9mIGEgc291cmNlIG9iamVjdCB0byBhIHRhcmdldCBvYmplY3QuXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSB0YXJnZXQgVGFyZ2V0IG9iamVjdC5cblx0ICogQHBhcmFtIHsuLi5PYmplY3R9IHZhcl9hcmdzIFRoZSBvYmplY3RzIGZyb20gd2hpY2ggdmFsdWVzIHdpbGwgYmUgY29waWVkLlxuXHQgKiBAcmV0dXJuIHtPYmplY3R9IFJldHVybnMgdGhlIHRhcmdldCBvYmplY3QgcmVmZXJlbmNlLlxuXHQgKi9cblx0c3RhdGljIG1peGluKHRhcmdldCwgLi4uYXJncykge1xuXHRcdGxldCBrZXk7XG5cdFx0bGV0IHNvdXJjZTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdHNvdXJjZSA9IGFyZ3NbaV07XG5cdFx0XHQvLyBQb3NzaWJsZSBwcm90b3R5cGUgY2hhaW4gbGVhaywgYnJlYWtzIDEgbWV0YWwtZG9tIGFuZFxuXHRcdFx0Ly8gMSBtZXRhbC1pbmNyZW1lbnRhbC1kb20gdGVzdCBpZiBndWFyZC1mb3ItaW4gcnVsZSBpcyBhZGRyZXNzZWRcblx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuXHRcdFx0Zm9yIChrZXkgaW4gc291cmNlKSB7XG5cdFx0XHRcdHRhcmdldFtrZXldID0gc291cmNlW2tleV07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0YXJnZXQ7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbiBvYmplY3QgYmFzZWQgb24gaXRzIGZ1bGx5IHF1YWxpZmllZCBleHRlcm5hbCBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUuXG5cdCAqIEBwYXJhbSB7b2JqZWN0PX0gc2NvcGUgVGhlIG9iamVjdCB3aXRoaW4gd2hpY2ggdG8gbG9vazsgZGVmYXVsdCBpc1xuXHQgKiAgICAgPGNvZGU+d2luZG93PC9jb2RlPi5cblx0ICogQHJldHVybiB7P30gVGhlIHZhbHVlIChvYmplY3Qgb3IgcHJpbWl0aXZlKSBvciwgaWYgbm90IGZvdW5kLCB1bmRlZmluZWQuXG5cdCAqL1xuXHRzdGF0aWMgZ2V0T2JqZWN0QnlOYW1lKG5hbWUsIHNjb3BlID0gd2luZG93KSB7XG5cdFx0Y29uc3QgcGFydHMgPSBuYW1lLnNwbGl0KCcuJyk7XG5cdFx0cmV0dXJuIHBhcnRzLnJlZHVjZSgocGFydCwga2V5KSA9PiBwYXJ0W2tleV0sIHNjb3BlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgbmV3IG9iamVjdCB3aXRoIHRoZSBzYW1lIGtleXMgYXMgdGhlIGdpdmVuIG9uZSwgYnV0IHdpdGhcblx0ICogdGhlaXIgdmFsdWVzIHNldCB0byB0aGUgcmV0dXJuIHZhbHVlcyBvZiB0aGUgc3BlY2lmaWVkIGZ1bmN0aW9uLlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IG9ialxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbihzdHJpbmcsICopfSBmblxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fVxuXHQgKi9cblx0c3RhdGljIG1hcChvYmosIGZuKSB7XG5cdFx0Y29uc3QgbWFwcGVkT2JqID0ge307XG5cdFx0Y29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRtYXBwZWRPYmpba2V5c1tpXV0gPSBmbihrZXlzW2ldLCBvYmpba2V5c1tpXV0pO1xuXHRcdH1cblx0XHRyZXR1cm4gbWFwcGVkT2JqO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgdHdvIGdpdmVuIG9iamVjdHMgYXJlIGVxdWFsLiBUaGlzIGlzIGRvbmUgdmlhIGEgc2hhbGxvd1xuXHQgKiBjaGVjaywgaW5jbHVkaW5nIG9ubHkgdGhlIGtleXMgZGlyZWN0bHkgY29udGFpbmVkIGJ5IHRoZSAyIG9iamVjdHMuXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBvYmoxXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBvYmoyXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRzdGF0aWMgc2hhbGxvd0VxdWFsKG9iajEsIG9iajIpIHtcblx0XHRpZiAob2JqMSA9PT0gb2JqMikge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Y29uc3Qga2V5czEgPSBPYmplY3Qua2V5cyhvYmoxKTtcblx0XHRjb25zdCBrZXlzMiA9IE9iamVjdC5rZXlzKG9iajIpO1xuXHRcdGlmIChrZXlzMS5sZW5ndGggIT09IGtleXMyLmxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwga2V5czEubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChvYmoxW2tleXMxW2ldXSAhPT0gb2JqMltrZXlzMVtpXV0pIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBvYmplY3Q7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogU2V0IG9mIHV0aWxpdGllcyBmb3Igc3RyaW5nIG9wZXJhdGlvbnNcbiAqL1xuY2xhc3Mgc3RyaW5nIHtcblx0LyoqXG5cdCAqIENvbXBhcmVzIHRoZSBnaXZlbiBzdHJpbmdzIHdpdGhvdXQgdGFraW5nIHRoZSBjYXNlIGludG8gYWNjb3VudC5cblx0ICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBzdHIxXG5cdCAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gc3RyMlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9IEVpdGhlciAtMSwgMCBvciAxLCBhY2NvcmRpbmcgdG8gaWYgdGhlIGZpcnN0IHN0cmluZyBpc1xuXHQgKiAgICAgXCJzbWFsbGVyXCIsIGVxdWFsIG9yIFwiYmlnZ2VyXCIgdGhhbiB0aGUgc2Vjb25kIGdpdmVuIHN0cmluZy5cblx0ICovXG5cdHN0YXRpYyBjYXNlSW5zZW5zaXRpdmVDb21wYXJlKHN0cjEsIHN0cjIpIHtcblx0XHRjb25zdCB0ZXN0MSA9IFN0cmluZyhzdHIxKS50b0xvd2VyQ2FzZSgpO1xuXHRcdGNvbnN0IHRlc3QyID0gU3RyaW5nKHN0cjIpLnRvTG93ZXJDYXNlKCk7XG5cblx0XHRpZiAodGVzdDEgPCB0ZXN0Mikge1xuXHRcdFx0cmV0dXJuIC0xO1xuXHRcdH0gZWxzZSBpZiAodGVzdDEgPT09IHRlc3QyKSB7XG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIDE7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGJyZWFraW5nIHNwYWNlcyBmcm9tIHRoZSBsZWZ0IGFuZCByaWdodCBvZiB0aGUgc3RyaW5nIGFuZFxuXHQgKiBjb2xsYXBzZXMgdGhlIHNlcXVlbmNlcyBvZiBicmVha2luZyBzcGFjZXMgaW4gdGhlIG1pZGRsZSBpbnRvIHNpbmdsZSBzcGFjZXMuXG5cdCAqIFRoZSBvcmlnaW5hbCBhbmQgdGhlIHJlc3VsdCBzdHJpbmdzIHJlbmRlciB0aGUgc2FtZSB3YXkgaW4gSFRNTC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHN0ciBBIHN0cmluZyBpbiB3aGljaCB0byBjb2xsYXBzZSBzcGFjZXMuXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gQ29weSBvZiB0aGUgc3RyaW5nIHdpdGggbm9ybWFsaXplZCBicmVha2luZyBzcGFjZXMuXG5cdCAqL1xuXHRzdGF0aWMgY29sbGFwc2VCcmVha2luZ1NwYWNlcyhzdHIpIHtcblx0XHRyZXR1cm4gc3RyXG5cdFx0XHQucmVwbGFjZSgvW1xcdFxcclxcbiBdKy9nLCAnICcpXG5cdFx0XHQucmVwbGFjZSgvXltcXHRcXHJcXG4gXSt8W1xcdFxcclxcbiBdKyQvZywgJycpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEVzY2FwZXMgY2hhcmFjdGVycyBpbiB0aGUgc3RyaW5nIHRoYXQgYXJlIG5vdCBzYWZlIHRvIHVzZSBpbiBhIFJlZ0V4cC5cblx0ICogQHBhcmFtIHsqfSBzdHIgVGhlIHN0cmluZyB0byBlc2NhcGUuIElmIG5vdCBhIHN0cmluZywgaXQgd2lsbCBiZSBjYXN0ZWRcblx0ICogICAgIHRvIG9uZS5cblx0ICogQHJldHVybiB7c3RyaW5nfSBBIFJlZ0V4cCBzYWZlLCBlc2NhcGVkIGNvcHkgb2Yge0Bjb2RlIHN9LlxuXHQgKi9cblx0c3RhdGljIGVzY2FwZVJlZ2V4KHN0cikge1xuXHRcdHJldHVybiBTdHJpbmcoc3RyKVxuXHRcdFx0LnJlcGxhY2UoLyhbLSgpW1xcXXt9Kz8qLiRefCw6IzwhXFxcXF0pL2csICdcXFxcJDEnKVxuXHRcdFx0LnJlcGxhY2UoL1xceDA4L2csICdcXFxceDA4Jyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgc3RyaW5nIHdpdGggYXQgbGVhc3QgNjQtYml0cyBvZiByYW5kb21uZXNzLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IEEgcmFuZG9tIHN0cmluZywgZS5nLiBzbjFzN3ZiNGdjaWMuXG5cdCAqL1xuXHRzdGF0aWMgZ2V0UmFuZG9tU3RyaW5nKCkge1xuXHRcdGNvbnN0IHggPSAyMTQ3NDgzNjQ4O1xuXHRcdHJldHVybiAoXG5cdFx0XHRNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB4KS50b1N0cmluZygzNikgK1xuXHRcdFx0TWF0aC5hYnMoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogeCkgXiBEYXRlLm5vdygpKS50b1N0cmluZygzNilcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGN1bGF0ZXMgdGhlIGhhc2hjb2RlIGZvciBhIHN0cmluZy4gVGhlIGhhc2hjb2RlIHZhbHVlIGlzIGNvbXB1dGVkIGJ5XG5cdCAqIHRoZSBzdW0gYWxnb3JpdGhtOiBzWzBdKjMxXihuLTEpICsgc1sxXSozMV4obi0yKSArIC4uLiArIHNbbi0xXS4gQSBuaWNlXG5cdCAqIHByb3BlcnR5IG9mIHVzaW5nIDMxIHByaW1lIGlzIHRoYXQgdGhlIG11bHRpcGxpY2F0aW9uIGNhbiBiZSByZXBsYWNlZCBieVxuXHQgKiBhIHNoaWZ0IGFuZCBhIHN1YnRyYWN0aW9uIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2U6IDMxKmkgPT0gKGk8PDUpLWkuXG5cdCAqIE1vZGVybiBWTXMgZG8gdGhpcyBzb3J0IG9mIG9wdGltaXphdGlvbiBhdXRvbWF0aWNhbGx5LlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdmFsIFRhcmdldCBzdHJpbmcuXG5cdCAqIEByZXR1cm4ge051bWJlcn0gUmV0dXJucyB0aGUgc3RyaW5nIGhhc2hjb2RlLlxuXHQgKi9cblx0c3RhdGljIGhhc2hDb2RlKHZhbCkge1xuXHRcdGxldCBoYXNoID0gMDtcblx0XHRmb3IgKGxldCBpID0gMCwgbGVuID0gdmFsLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRoYXNoID0gMzEgKiBoYXNoICsgdmFsLmNoYXJDb2RlQXQoaSk7XG5cdFx0XHRoYXNoICU9IDB4MTAwMDAwMDAwO1xuXHRcdH1cblx0XHRyZXR1cm4gaGFzaDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXBsYWNlcyBpbnRlcnZhbCBpbnRvIHRoZSBzdHJpbmcgd2l0aCBzcGVjaWZpZWQgdmFsdWUsIGUuZy5cblx0ICogYHJlcGxhY2VJbnRlcnZhbChcImFiY2RlXCIsIDEsIDQsIFwiXCIpYCByZXR1cm5zIFwiYWVcIi5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHN0ciBUaGUgaW5wdXQgc3RyaW5nLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gc3RhcnQgU3RhcnQgaW50ZXJ2YWwgcG9zaXRpb24gdG8gYmUgcmVwbGFjZWQuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBlbmQgRW5kIGludGVydmFsIHBvc2l0aW9uIHRvIGJlIHJlcGxhY2VkLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVGhlIHZhbHVlIHRoYXQgcmVwbGFjZXMgdGhlIHNwZWNpZmllZCBpbnRlcnZhbC5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0c3RhdGljIHJlcGxhY2VJbnRlcnZhbChzdHIsIHN0YXJ0LCBlbmQsIHZhbHVlKSB7XG5cdFx0cmV0dXJuIHN0ci5zdWJzdHJpbmcoMCwgc3RhcnQpICsgdmFsdWUgKyBzdHIuc3Vic3RyaW5nKGVuZCk7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgc3RyaW5nO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2lzRGVmfSBmcm9tICdtZXRhbCc7XG5cbmNvbnN0IE1FVEFMX0RBVEEgPSAnX19tZXRhbF9kYXRhX18nO1xuXG4vKipcbiAqIFNldCBvZiB1dGlsaXRpZXMgZm9yIGRvbSBkYXRhIG9wZXJhdGlvbnNcbiAqL1xuY2xhc3MgZG9tRGF0YSB7XG5cdC8qKlxuXHQgKiBHZXRzIE1ldGFsLmpzJ3MgZGF0YSBmb3IgdGhlIGdpdmVuIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHBhcmFtIHtzdHJpbmc9fSBuYW1lIE9wdGlvbmFsIHByb3BlcnR5IGZyb20gdGhlIGRhdGEgdG8gYmUgcmV0dXJuZWQuXG5cdCAqIEBwYXJhbSB7Kj19IGluaXRpYWxWYWx1ZSBPcHRpb25hbCB2YWx1ZSB0byB0aGUgc2V0IHRoZSByZXF1ZXN0ZWQgcHJvcGVydHlcblx0ICogICAgIHRvIGlmIGl0IGRvZXNuJ3QgZXhpc3QgeWV0IGluIHRoZSBkYXRhLlxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fVxuXHQgKi9cblx0c3RhdGljIGdldChlbGVtZW50LCBuYW1lLCBpbml0aWFsVmFsdWUpIHtcblx0XHRpZiAoIWVsZW1lbnRbTUVUQUxfREFUQV0pIHtcblx0XHRcdGVsZW1lbnRbTUVUQUxfREFUQV0gPSB7fTtcblx0XHR9XG5cdFx0aWYgKCFuYW1lKSB7XG5cdFx0XHRyZXR1cm4gZWxlbWVudFtNRVRBTF9EQVRBXTtcblx0XHR9XG5cdFx0aWYgKCFpc0RlZihlbGVtZW50W01FVEFMX0RBVEFdW25hbWVdKSAmJiBpc0RlZihpbml0aWFsVmFsdWUpKSB7XG5cdFx0XHRlbGVtZW50W01FVEFMX0RBVEFdW25hbWVdID0gaW5pdGlhbFZhbHVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZWxlbWVudFtNRVRBTF9EQVRBXVtuYW1lXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGVsZW1lbnQgaGFzIGRhdGEgc3RvcmVkIGluIGl0LlxuXHQgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRzdGF0aWMgaGFzKGVsZW1lbnQpIHtcblx0XHRyZXR1cm4gISFlbGVtZW50W01FVEFMX0RBVEFdO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgTWV0YWwuanMncyBkYXRhIGZvciB0aGUgZ2l2ZW4gZWxlbWVudC5cblx0ICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuXHQgKiBAcGFyYW0ge3N0cmluZz19IG5hbWUgUHJvcGVydHkgZnJvbSB0aGUgZGF0YSB0byBiZSBzZXQuXG5cdCAqIEBwYXJhbSB7Kj19IHZhbHVlIFZhbHVlIHRvIGJlIHNldCBvbiB0aGUgZWxlbWVudC5cblx0ICogQHJldHVybiB7IU9iamVjdHwqfVxuXHQgKi9cblx0c3RhdGljIHNldChlbGVtZW50LCBuYW1lLCB2YWx1ZSkge1xuXHRcdGlmICghZWxlbWVudFtNRVRBTF9EQVRBXSkge1xuXHRcdFx0ZWxlbWVudFtNRVRBTF9EQVRBXSA9IHt9O1xuXHRcdH1cblx0XHRpZiAoIW5hbWUgfHwgIWlzRGVmKHZhbHVlKSkge1xuXHRcdFx0cmV0dXJuIGVsZW1lbnRbTUVUQUxfREFUQV07XG5cdFx0fVxuXHRcdGVsZW1lbnRbTUVUQUxfREFUQV1bbmFtZV0gPSB2YWx1ZTtcblx0XHRyZXR1cm4gZWxlbWVudFtNRVRBTF9EQVRBXVtuYW1lXTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBkb21EYXRhO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge0Rpc3Bvc2FibGV9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBFdmVudEhhbmRsZSB1dGlsaXR5LiBIb2xkcyBpbmZvcm1hdGlvbiBhYm91dCBhbiBldmVudCBzdWJzY3JpcHRpb24sIGFuZFxuICogYWxsb3dzIHJlbW92aW5nIHRoZW0gZWFzaWx5LlxuICogRXZlbnRIYW5kbGUgaXMgYSBEaXNwb3NhYmxlLCBidXQgaXQncyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHRoZVxuICogRXZlbnRFbWl0dGVyIHRoYXQgY3JlYXRlZCBpdCBpcyBub3QgdGhlIG9uZSByZXNwb25zaWJsZSBmb3IgZGlzcG9zaW5nIGl0LlxuICogVGhhdCByZXNwb25zaWJpbGl0eSBpcyBmb3IgdGhlIGNvZGUgdGhhdCBob2xkcyBhIHJlZmVyZW5jZSB0byBpdC5cbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEhhbmRsZSBleHRlbmRzIERpc3Bvc2FibGUge1xuXHQvKipcblx0ICogRXZlbnRIYW5kbGUgY29uc3RydWN0b3Jcblx0ICogQHBhcmFtIHshRXZlbnRFbWl0dGVyfSBlbWl0dGVyIEVtaXR0ZXIgdGhlIGV2ZW50IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnQgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRoYXQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lciBUaGUgbGlzdGVuZXIgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnQuXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihlbWl0dGVyLCBldmVudCwgbGlzdGVuZXIpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIEV2ZW50RW1pdHRlciBpbnN0YW5jZSB0aGF0IHRoZSBldmVudCB3YXMgc3Vic2NyaWJlZCB0by5cblx0XHQgKiBAdHlwZSB7RXZlbnRFbWl0dGVyfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmVtaXR0ZXJfID0gZW1pdHRlcjtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0aGF0IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHRcdCAqIEB0eXBlIHtzdHJpbmd9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZXZlbnRfID0gZXZlbnQ7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgbGlzdGVuZXIgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnQuXG5cdFx0ICogQHR5cGUge0Z1bmN0aW9ufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmxpc3RlbmVyXyA9IGxpc3RlbmVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy5cblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdHRoaXMuZW1pdHRlcl8gPSBudWxsO1xuXHRcdHRoaXMubGlzdGVuZXJfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHRoZSBsaXN0ZW5lciBzdWJzY3JpcHRpb24gZnJvbSB0aGUgZW1pdHRlci5cblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyKCkge1xuXHRcdGlmICghdGhpcy5lbWl0dGVyXy5pc0Rpc3Bvc2VkKCkpIHtcblx0XHRcdHRoaXMuZW1pdHRlcl8ucmVtb3ZlTGlzdGVuZXIodGhpcy5ldmVudF8sIHRoaXMubGlzdGVuZXJfKTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRXZlbnRIYW5kbGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXJyYXksIERpc3Bvc2FibGUsIGlzRnVuY3Rpb24sIGlzU3RyaW5nfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgRXZlbnRIYW5kbGUgZnJvbSAnLi9FdmVudEhhbmRsZSc7XG5cbmNvbnN0IHNpbmdsZUFycmF5XyA9IFswXTtcblxuLyoqXG4gKiBFdmVudEVtaXR0ZXIgdXRpbGl0eS5cbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEVtaXR0ZXIgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblx0LyoqXG5cdCAqIEV2ZW50RW1pdHRlciBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGV2ZW50IGxpc3RlbmVycyBzY29wZWQgYnkgZXZlbnQgdHlwZS5cblx0XHQgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgIUFycmF5PCFmdW5jdGlvbigpPj59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZXZlbnRzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIYW5kbGVycyB0aGF0IGFyZSB0cmlnZ2VyZWQgd2hlbiBhbiBldmVudCBpcyBsaXN0ZW5lZCB0by5cblx0XHQgKiBAdHlwZSB7QXJyYXl9XG5cdFx0ICovXG5cdFx0dGhpcy5saXN0ZW5lckhhbmRsZXJzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBDb25maWd1cmF0aW9uIG9wdGlvbiB3aGljaCBkZXRlcm1pbmVzIGlmIGFuIGV2ZW50IGZhY2FkZSBzaG91bGQgYmUgc2VudFxuXHRcdCAqIGFzIGEgcGFyYW0gb2YgbGlzdGVuZXJzIHdoZW4gZW1pdHRpbmcgZXZlbnRzLiBJZiBzZXQgdG8gdHJ1ZSwgdGhlIGZhY2FkZVxuXHRcdCAqIHdpbGwgYmUgcGFzc2VkIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBvZiB0aGUgbGlzdGVuZXIuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuc2hvdWxkVXNlRmFjYWRlXyA9IGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBoYW5kbGVyIHRvIGdpdmVuIGhvbGRlciB2YXJpYWJsZS4gSWYgdGhlIGhvbGRlciBkb2Vzbid0IGhhdmUgYVxuXHQgKiB2YWx1ZSB5ZXQsIGl0IHdpbGwgcmVjZWl2ZSB0aGUgaGFuZGxlciBkaXJlY3RseS4gSWYgdGhlIGhvbGRlciBpcyBhbiBhcnJheSxcblx0ICogdGhlIHZhbHVlIHdpbGwganVzdCBiZSBhZGRlZCB0byBpdC4gT3RoZXJ3aXNlLCB0aGUgaG9sZGVyIHdpbGwgYmUgc2V0IHRvIGFcblx0ICogbmV3IGFycmF5IGNvbnRhaW5pbmcgaXRzIHByZXZpb3VzIHZhbHVlIHBsdXMgdGhlIG5ldyBoYW5kbGVyLlxuXHQgKiBAcGFyYW0geyp9IGhvbGRlclxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbigpfE9iamVjdH0gaGFuZGxlclxuXHQgKiBAcmV0dXJuIHsqfSBUaGUgaG9sZGVyJ3MgbmV3IHZhbHVlLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRhZGRIYW5kbGVyXyhob2xkZXIsIGhhbmRsZXIpIHtcblx0XHRpZiAoIWhvbGRlcikge1xuXHRcdFx0aG9sZGVyID0gaGFuZGxlcjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCFBcnJheS5pc0FycmF5KGhvbGRlcikpIHtcblx0XHRcdFx0aG9sZGVyID0gW2hvbGRlcl07XG5cdFx0XHR9XG5cdFx0XHRob2xkZXIucHVzaChoYW5kbGVyKTtcblx0XHR9XG5cdFx0cmV0dXJuIGhvbGRlcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQHBhcmFtIHshKEFycmF5fHN0cmluZyl9IGV2ZW50XG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IGRlZmF1bHRMaXN0ZW5lciBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBsaXN0ZW5lciBpcyBhIGRlZmF1bHRcblx0ICogICBhY3Rpb24gZm9yIHRoaXMgZXZlbnQuIERlZmF1bHQgYWN0aW9ucyBhcmUgcnVuIGxhc3QsIGFuZCBvbmx5IGlmIG5vIHByZXZpb3VzXG5cdCAqICAgbGlzdGVuZXIgY2FsbCBgcHJldmVudERlZmF1bHQoKWAgb24gdGhlIHJlY2VpdmVkIGV2ZW50IGZhY2FkZS5cblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuXHQgKi9cblx0YWRkTGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyLCBkZWZhdWx0TGlzdGVuZXIpIHtcblx0XHR0aGlzLnZhbGlkYXRlTGlzdGVuZXJfKGxpc3RlbmVyKTtcblxuXHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMudG9FdmVudHNBcnJheV8oZXZlbnQpO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmFkZFNpbmdsZUxpc3RlbmVyXyhldmVudHNbaV0sIGxpc3RlbmVyLCBkZWZhdWx0TGlzdGVuZXIpO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgRXZlbnRIYW5kbGUodGhpcywgZXZlbnQsIGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciBhIHNpbmdsZSBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IGRlZmF1bHRMaXN0ZW5lciBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBsaXN0ZW5lciBpcyBhIGRlZmF1bHRcblx0ICogICBhY3Rpb24gZm9yIHRoaXMgZXZlbnQuIERlZmF1bHQgYWN0aW9ucyBhcmUgcnVuIGxhc3QsIGFuZCBvbmx5IGlmIG5vIHByZXZpb3VzXG5cdCAqICAgbGlzdGVuZXIgY2FsbCBgcHJldmVudERlZmF1bHQoKWAgb24gdGhlIHJlY2VpdmVkIGV2ZW50IGZhY2FkZS5cblx0ICogQHBhcmFtIHtGdW5jdGlvbj19IG9yaWdpbiBUaGUgb3JpZ2luYWwgZnVuY3Rpb24gdGhhdCB3YXMgYWRkZWQgYXMgYVxuXHQgKiAgIGxpc3RlbmVyLCBpZiB0aGVyZSBpcyBhbnkuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFkZFNpbmdsZUxpc3RlbmVyXyhldmVudCwgbGlzdGVuZXIsIGRlZmF1bHRMaXN0ZW5lciwgb3JpZ2luKSB7XG5cdFx0dGhpcy5ydW5MaXN0ZW5lckhhbmRsZXJzXyhldmVudCk7XG5cdFx0aWYgKGRlZmF1bHRMaXN0ZW5lciB8fCBvcmlnaW4pIHtcblx0XHRcdGxpc3RlbmVyID0ge1xuXHRcdFx0XHRkZWZhdWx0OiBkZWZhdWx0TGlzdGVuZXIsXG5cdFx0XHRcdGZuOiBsaXN0ZW5lcixcblx0XHRcdFx0b3JpZ2luOiBvcmlnaW4sXG5cdFx0XHR9O1xuXHRcdH1cblx0XHR0aGlzLmV2ZW50c18gPSB0aGlzLmV2ZW50c18gfHwge307XG5cdFx0dGhpcy5ldmVudHNfW2V2ZW50XSA9IHRoaXMuYWRkSGFuZGxlcl8odGhpcy5ldmVudHNfW2V2ZW50XSwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEJ1aWxkcyBmYWNhZGUgZm9yIHRoZSBnaXZlbiBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4ge09iamVjdH1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0YnVpbGRGYWNhZGVfKGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuZ2V0U2hvdWxkVXNlRmFjYWRlKCkpIHtcblx0XHRcdGNvbnN0IGZhY2FkZSA9IHtcblx0XHRcdFx0cHJldmVudERlZmF1bHQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGZhY2FkZS5wcmV2ZW50ZWREZWZhdWx0ID0gdHJ1ZTtcblx0XHRcdFx0fSxcblx0XHRcdFx0dGFyZ2V0OiB0aGlzLFxuXHRcdFx0XHR0eXBlOiBldmVudCxcblx0XHRcdH07XG5cdFx0XHRyZXR1cm4gZmFjYWRlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwb3NlcyBvZiB0aGlzIGluc3RhbmNlJ3Mgb2JqZWN0IHJlZmVyZW5jZXMuXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHRoaXMuZXZlbnRzXyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogRXhlY3V0ZSBlYWNoIG9mIHRoZSBsaXN0ZW5lcnMgaW4gb3JkZXIgd2l0aCB0aGUgc3VwcGxpZWQgYXJndW1lbnRzLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHBhcmFtIHsqfSBvcHRfYXJncyBbYXJnMV0sIFthcmcyXSwgWy4uLl1cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIGV2ZW50IGhhZCBsaXN0ZW5lcnMsIGZhbHNlIG90aGVyd2lzZS5cblx0ICovXG5cdGVtaXQoZXZlbnQpIHtcblx0XHRjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLmdldFJhd0xpc3RlbmVyc18oZXZlbnQpO1xuXHRcdGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Y29uc3QgYXJncyA9IGFycmF5LnNsaWNlKGFyZ3VtZW50cywgMSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0XHR0aGlzLnJ1bkxpc3RlbmVyc18obGlzdGVuZXJzLCBhcmdzLCB0aGlzLmJ1aWxkRmFjYWRlXyhldmVudCkpO1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGxpc3RlbmVyIG9iamVjdHMgZm9yIHRoZSBnaXZlbiBldmVudCwgaWYgdGhlcmUgYXJlIGFueS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4geyFBcnJheX1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0Z2V0UmF3TGlzdGVuZXJzXyhldmVudCkge1xuXHRcdGNvbnN0IGRpcmVjdExpc3RlbmVycyA9IHRvQXJyYXkodGhpcy5ldmVudHNfICYmIHRoaXMuZXZlbnRzX1tldmVudF0pO1xuXHRcdHJldHVybiBkaXJlY3RMaXN0ZW5lcnMuY29uY2F0KFxuXHRcdFx0dG9BcnJheSh0aGlzLmV2ZW50c18gJiYgdGhpcy5ldmVudHNfWycqJ10pXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjb25maWd1cmF0aW9uIG9wdGlvbiB3aGljaCBkZXRlcm1pbmVzIGlmIGFuIGV2ZW50IGZhY2FkZSBzaG91bGRcblx0ICogYmUgc2VudCBhcyBhIHBhcmFtIG9mIGxpc3RlbmVycyB3aGVuIGVtaXR0aW5nIGV2ZW50cy4gSWYgc2V0IHRvIHRydWUsIHRoZVxuXHQgKiBmYWNhZGUgd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIHRoZSBsaXN0ZW5lci5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldFNob3VsZFVzZUZhY2FkZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5zaG91bGRVc2VGYWNhZGVfO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7QXJyYXl9IEFycmF5IG9mIGxpc3RlbmVycy5cblx0ICovXG5cdGxpc3RlbmVycyhldmVudCkge1xuXHRcdHJldHVybiB0aGlzLmdldFJhd0xpc3RlbmVyc18oZXZlbnQpLm1hcChcblx0XHRcdGxpc3RlbmVyID0+IChsaXN0ZW5lci5mbiA/IGxpc3RlbmVyLmZuIDogbGlzdGVuZXIpXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBmaXhlZCBudW1iZXIgb2YgdGltZXMgZm9yIHRoZVxuXHQgKiBldmVudHMuIEFmdGVyIGVhY2ggZXZlbnQgaXMgdHJpZ2dlcmVkIHRoZSBzcGVjaWZpZWQgYW1vdW50IG9mIHRpbWVzLCB0aGVcblx0ICogbGlzdGVuZXIgaXMgcmVtb3ZlZCBmb3IgaXQuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudFxuXHQgKiBAcGFyYW0ge251bWJlcn0gYW1vdW50IFRoZSBhbW91bnQgb2YgdGltZXMgdGhpcyBldmVudCBzaG91bGQgYmUgbGlzdGVuZWRcblx0ICogdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG5cdCAqL1xuXHRtYW55KGV2ZW50LCBhbW91bnQsIGxpc3RlbmVyKSB7XG5cdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMubWFueV8oZXZlbnRzW2ldLCBhbW91bnQsIGxpc3RlbmVyKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IEV2ZW50SGFuZGxlKHRoaXMsIGV2ZW50LCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGEgZml4ZWQgbnVtYmVyIG9mIHRpbWVzIGZvciBhIHNpbmdsZVxuXHQgKiBldmVudC4gQWZ0ZXIgdGhlIGV2ZW50IGlzIHRyaWdnZXJlZCB0aGUgc3BlY2lmaWVkIGFtb3VudCBvZiB0aW1lcywgdGhlXG5cdCAqIGxpc3RlbmVyIGlzIHJlbW92ZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0ge251bWJlcn0gYW1vdW50IFRoZSBhbW91bnQgb2YgdGltZXMgdGhpcyBldmVudCBzaG91bGQgYmUgbGlzdGVuZWRcblx0ICogdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRtYW55XyhldmVudCwgYW1vdW50LCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IHNlbGYgPSB0aGlzO1xuXG5cdFx0aWYgKGFtb3VudCA8PSAwKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0LyoqXG5cdFx0ICpcblx0XHQgKi9cblx0XHRmdW5jdGlvbiBoYW5kbGVySW50ZXJuYWwoKSB7XG5cdFx0XHRpZiAoLS1hbW91bnQgPT09IDApIHtcblx0XHRcdFx0c2VsZi5yZW1vdmVMaXN0ZW5lcihldmVudCwgaGFuZGxlckludGVybmFsKTtcblx0XHRcdH1cblx0XHRcdGxpc3RlbmVyLmFwcGx5KHNlbGYsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0XHR9XG5cblx0XHRzZWxmLmFkZFNpbmdsZUxpc3RlbmVyXyhldmVudCwgaGFuZGxlckludGVybmFsLCBmYWxzZSwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBhIGxpc3RlbmVyIG9iamVjdCBtYXRjaGVzIHRoZSBnaXZlbiBsaXN0ZW5lciBmdW5jdGlvbi4gVG8gbWF0Y2gsXG5cdCAqIGl0IG5lZWRzIHRvIGVpdGhlciBwb2ludCB0byB0aGF0IGxpc3RlbmVyIG9yIGhhdmUgaXQgYXMgaXRzIG9yaWdpbi5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBsaXN0ZW5lck9ialxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0bWF0Y2hlc0xpc3RlbmVyXyhsaXN0ZW5lck9iaiwgbGlzdGVuZXIpIHtcblx0XHRjb25zdCBmbiA9IGxpc3RlbmVyT2JqLmZuIHx8IGxpc3RlbmVyT2JqO1xuXHRcdHJldHVybiAoXG5cdFx0XHRmbiA9PT0gbGlzdGVuZXIgfHxcblx0XHRcdChsaXN0ZW5lck9iai5vcmlnaW4gJiYgbGlzdGVuZXJPYmoub3JpZ2luID09PSBsaXN0ZW5lcikgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQ2F1dGlvbjogY2hhbmdlcyBhcnJheSBpbmRpY2VzIGluIHRoZSBsaXN0ZW5lciBhcnJheSBiZWhpbmQgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRvZmYoZXZlbnQsIGxpc3RlbmVyKSB7XG5cdFx0dGhpcy52YWxpZGF0ZUxpc3RlbmVyXyhsaXN0ZW5lcik7XG5cdFx0aWYgKCF0aGlzLmV2ZW50c18pIHtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblxuXHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMudG9FdmVudHNBcnJheV8oZXZlbnQpO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmV2ZW50c19bZXZlbnRzW2ldXSA9IHRoaXMucmVtb3ZlTWF0Y2hpbmdMaXN0ZW5lck9ianNfKFxuXHRcdFx0XHR0b0FycmF5KHRoaXMuZXZlbnRzX1tldmVudHNbaV1dKSxcblx0XHRcdFx0bGlzdGVuZXJcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBlbmQgb2YgdGhlIGxpc3RlbmVycyBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudHMuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cblx0ICovXG5cdG9uKCkge1xuXHRcdHJldHVybiB0aGlzLmFkZExpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGhhbmRsZXIgdGhhdCBnZXRzIHRyaWdnZXJlZCB3aGVuIGFuIGV2ZW50IGlzIGxpc3RlbmVkIHRvIG9uIHRoaXNcblx0ICogaW5zdGFuY2UuXG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGhhbmRsZXJcblx0ICovXG5cdG9uTGlzdGVuZXIoaGFuZGxlcikge1xuXHRcdHRoaXMubGlzdGVuZXJIYW5kbGVyc18gPSB0aGlzLmFkZEhhbmRsZXJfKFxuXHRcdFx0dGhpcy5saXN0ZW5lckhhbmRsZXJzXyxcblx0XHRcdGhhbmRsZXJcblx0XHQpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIG9uZSB0aW1lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRzLiBUaGlzIGxpc3RlbmVyIGlzIGludm9rZWQgb25seSB0aGVcblx0ICogbmV4dCB0aW1lIGVhY2ggZXZlbnQgaXMgZmlyZWQsIGFmdGVyIHdoaWNoIGl0IGlzIHJlbW92ZWQuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cblx0ICovXG5cdG9uY2UoZXZlbnRzLCBsaXN0ZW5lcikge1xuXHRcdHJldHVybiB0aGlzLm1hbnkoZXZlbnRzLCAxLCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzLCBvciB0aG9zZSBvZiB0aGUgc3BlY2lmaWVkIGV2ZW50cy4gSXQncyBub3QgYSBnb29kXG5cdCAqIGlkZWEgdG8gcmVtb3ZlIGxpc3RlbmVycyB0aGF0IHdlcmUgYWRkZWQgZWxzZXdoZXJlIGluIHRoZSBjb2RlLFxuXHQgKiBlc3BlY2lhbGx5IHdoZW4gaXQncyBvbiBhbiBlbWl0dGVyIHRoYXQgeW91IGRpZG4ndCBjcmVhdGUuXG5cdCAqIEBwYXJhbSB7KEFycmF5fHN0cmluZyk9fSBldmVudFxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fSBSZXR1cm5zIGVtaXR0ZXIsIHNvIGNhbGxzIGNhbiBiZSBjaGFpbmVkLlxuXHQgKi9cblx0cmVtb3ZlQWxsTGlzdGVuZXJzKGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuZXZlbnRzXykge1xuXHRcdFx0aWYgKGV2ZW50KSB7XG5cdFx0XHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMudG9FdmVudHNBcnJheV8oZXZlbnQpO1xuXHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRcdHRoaXMuZXZlbnRzX1tldmVudHNbaV1dID0gbnVsbDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5ldmVudHNfID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhbGwgbGlzdGVuZXIgb2JqZWN0cyBmcm9tIHRoZSBnaXZlbiBhcnJheSB0aGF0IG1hdGNoIHRoZSBnaXZlblxuXHQgKiBsaXN0ZW5lciBmdW5jdGlvbi5cblx0ICogQHBhcmFtIHtBcnJheS48T2JqZWN0Pn0gbGlzdGVuZXJPYmpzXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHtBcnJheS48T2JqZWN0PnxPYmplY3R9IFRoZSBuZXcgbGlzdGVuZXJzIGFycmF5IGZvciB0aGlzIGV2ZW50LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRyZW1vdmVNYXRjaGluZ0xpc3RlbmVyT2Jqc18obGlzdGVuZXJPYmpzLCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IGZpbmFsTGlzdGVuZXJzID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0ZW5lck9ianMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmICghdGhpcy5tYXRjaGVzTGlzdGVuZXJfKGxpc3RlbmVyT2Jqc1tpXSwgbGlzdGVuZXIpKSB7XG5cdFx0XHRcdGZpbmFsTGlzdGVuZXJzLnB1c2gobGlzdGVuZXJPYmpzW2ldKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGZpbmFsTGlzdGVuZXJzLmxlbmd0aCA+IDAgPyBmaW5hbExpc3RlbmVycyA6IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQ2F1dGlvbjogY2hhbmdlcyBhcnJheSBpbmRpY2VzIGluIHRoZSBsaXN0ZW5lciBhcnJheSBiZWhpbmQgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRzXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fSBSZXR1cm5zIGVtaXR0ZXIsIHNvIGNhbGxzIGNhbiBiZSBjaGFpbmVkLlxuXHQgKi9cblx0cmVtb3ZlTGlzdGVuZXIoKSB7XG5cdFx0cmV0dXJuIHRoaXMub2ZmLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fVxuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBoYW5kbGVycyB3aGVuIGFuIGV2ZW50IGlzIGxpc3RlbmVkIHRvLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0cnVuTGlzdGVuZXJIYW5kbGVyc18oZXZlbnQpIHtcblx0XHRsZXQgaGFuZGxlcnMgPSB0aGlzLmxpc3RlbmVySGFuZGxlcnNfO1xuXHRcdGlmIChoYW5kbGVycykge1xuXHRcdFx0aGFuZGxlcnMgPSB0b0FycmF5KGhhbmRsZXJzKTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgaGFuZGxlcnMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0aGFuZGxlcnNbaV0oZXZlbnQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBnaXZlbiBsaXN0ZW5lcnMuXG5cdCAqIEBwYXJhbSB7IUFycmF5fSBsaXN0ZW5lcnNcblx0ICogQHBhcmFtIHshQXJyYXl9IGFyZ3Ncblx0ICogQHBhcmFtIHtPYmplY3R9IGZhY2FkZVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRydW5MaXN0ZW5lcnNfKGxpc3RlbmVycywgYXJncywgZmFjYWRlKSB7XG5cdFx0aWYgKGZhY2FkZSkge1xuXHRcdFx0YXJncy5wdXNoKGZhY2FkZSk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZGVmYXVsdExpc3RlbmVycyA9IFtdO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXS5mbiB8fCBsaXN0ZW5lcnNbaV07XG5cdFx0XHRpZiAobGlzdGVuZXJzW2ldLmRlZmF1bHQpIHtcblx0XHRcdFx0ZGVmYXVsdExpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoIWZhY2FkZSB8fCAhZmFjYWRlLnByZXZlbnRlZERlZmF1bHQpIHtcblx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgZGVmYXVsdExpc3RlbmVycy5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRkZWZhdWx0TGlzdGVuZXJzW2pdLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBjb25maWd1cmF0aW9uIG9wdGlvbiB3aGljaCBkZXRlcm1pbmVzIGlmIGFuIGV2ZW50IGZhY2FkZSBzaG91bGRcblx0ICogYmUgc2VudCBhcyBhIHBhcmFtIG9mIGxpc3RlbmVycyB3aGVuIGVtaXR0aW5nIGV2ZW50cy4gSWYgc2V0IHRvIHRydWUsIHRoZVxuXHQgKiBmYWNhZGUgd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIHRoZSBsaXN0ZW5lci5cblx0ICogQHBhcmFtIHtib29sZWFufSBzaG91bGRVc2VGYWNhZGVcblx0ICogQHJldHVybiB7IU9iamVjdH0gUmV0dXJucyBlbWl0dGVyLCBzbyBjYWxscyBjYW4gYmUgY2hhaW5lZC5cblx0ICovXG5cdHNldFNob3VsZFVzZUZhY2FkZShzaG91bGRVc2VGYWNhZGUpIHtcblx0XHR0aGlzLnNob3VsZFVzZUZhY2FkZV8gPSBzaG91bGRVc2VGYWNhZGU7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgdGhlIHBhcmFtZXRlciB0byBhbiBhcnJheSBpZiBvbmx5IG9uZSBldmVudCBpcyBnaXZlbi4gUmV1c2VzIHRoZVxuXHQgKiBzYW1lIGFycmF5IGVhY2ggdGltZSB0aGlzIGNvbnZlcnNpb24gaXMgZG9uZSwgdG8gYXZvaWQgdXNpbmcgbW9yZSBtZW1vcnlcblx0ICogdGhhbiBuZWNlc3NhcnkuXG5cdCAqIEBwYXJhbSAgeyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRzXG5cdCAqIEByZXR1cm4geyFBcnJheX1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dG9FdmVudHNBcnJheV8oZXZlbnRzKSB7XG5cdFx0aWYgKGlzU3RyaW5nKGV2ZW50cykpIHtcblx0XHRcdHNpbmdsZUFycmF5X1swXSA9IGV2ZW50cztcblx0XHRcdGV2ZW50cyA9IHNpbmdsZUFycmF5Xztcblx0XHR9XG5cdFx0cmV0dXJuIGV2ZW50cztcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGxpc3RlbmVyIGlzIHZhbGlkLCB0aHJvd2luZyBhbiBleGNlcHRpb24gd2hlbiBpdCdzIG5vdC5cblx0ICogQHBhcmFtICB7Kn0gbGlzdGVuZXJcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dmFsaWRhdGVMaXN0ZW5lcl8obGlzdGVuZXIpIHtcblx0XHRpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCdMaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0byBhbiBhcnJheVxuICogQHBhcmFtIHtPYmplY3R9IHZhbFxuICogQHJldHVybiB7QXJyYXl9XG4gKi9cbmZ1bmN0aW9uIHRvQXJyYXkodmFsKSB7XG5cdHZhbCA9IHZhbCB8fCBbXTtcblx0cmV0dXJuIEFycmF5LmlzQXJyYXkodmFsKSA/IHZhbCA6IFt2YWxdO1xufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEVtaXR0ZXI7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7RGlzcG9zYWJsZX0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEV2ZW50RW1pdHRlclByb3h5IHV0aWxpdHkuIEl0J3MgcmVzcG9uc2libGUgZm9yIGxpbmtpbmcgdHdvIEV2ZW50RW1pdHRlclxuICogaW5zdGFuY2VzIHRvZ2V0aGVyLCBlbWl0dGluZyBldmVudHMgZnJvbSB0aGUgZmlyc3QgZW1pdHRlciB0aHJvdWdoIHRoZVxuICogc2Vjb25kIG9uZS4gVGhhdCBtZWFucyB0aGF0IGxpc3RlbmluZyB0byBhIHN1cHBvcnRlZCBldmVudCBvbiB0aGUgdGFyZ2V0XG4gKiBlbWl0dGVyIHdpbGwgbWVhbiBsaXN0ZW5pbmcgdG8gaXQgb24gdGhlIG9yaWdpbiBlbWl0dGVyIGFzIHdlbGwuXG4gKiBAZXh0ZW5kcyB7RGlzcG9zYWJsZX1cbiAqL1xuY2xhc3MgRXZlbnRFbWl0dGVyUHJveHkgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblx0LyoqXG5cdCAqIEBwYXJhbSB7RXZlbnRFbWl0dGVyfSBvcmlnaW5FbWl0dGVyIEV2ZW50cyBvcmlnaW5hdGVkIG9uIHRoaXMgZW1pdHRlclxuXHQgKiB3aWxsIGJlIGZpcmVkIGZvciB0aGUgdGFyZ2V0IGVtaXR0ZXIncyBsaXN0ZW5lcnMgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtFdmVudEVtaXR0ZXJ9IHRhcmdldEVtaXR0ZXIgRXZlbnQgbGlzdGVuZXJzIGF0dGFjaGVkIHRvIHRoaXMgZW1pdHRlclxuXHQgKiB3aWxsIGFsc28gYmUgdHJpZ2dlcmVkIHdoZW4gdGhlIGV2ZW50IGlzIGZpcmVkIGJ5IHRoZSBvcmlnaW4gZW1pdHRlci5cblx0ICogQHBhcmFtIHtPYmplY3R9IGJsYWNrbGlzdCBPcHRpb25hbCBibGFja2xpc3Qgb2YgZXZlbnRzIHRoYXQgc2hvdWxkIG5vdCBiZVxuXHQgKiBwcm94aWVkLlxuXHQgKiBAcGFyYW0ge09iamVjdH0gd2hpdGVsaXN0XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihvcmlnaW5FbWl0dGVyLCB0YXJnZXRFbWl0dGVyLCBibGFja2xpc3QsIHdoaXRlbGlzdCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBNYXAgb2YgZXZlbnRzIHRoYXQgc2hvdWxkIG5vdCBiZSBwcm94aWVkLlxuXHRcdCAqIEB0eXBlIHtPYmplY3R9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYmxhY2tsaXN0XyA9IGJsYWNrbGlzdDtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBvcmlnaW4gZW1pdHRlci4gVGhpcyBlbWl0dGVyJ3MgZXZlbnRzIHdpbGwgYmUgcHJveGllZCB0aHJvdWdoIHRoZVxuXHRcdCAqIHRhcmdldCBlbWl0dGVyLlxuXHRcdCAqIEB0eXBlIHtFdmVudEVtaXR0ZXJ9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMub3JpZ2luRW1pdHRlcl8gPSBvcmlnaW5FbWl0dGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogQSBsaXN0IG9mIGV2ZW50cyB0aGF0IGFyZSBwZW5kaW5nIHRvIGJlIGxpc3RlbmVkIGJ5IGFuIGFjdHVhbCBvcmlnaW5cblx0XHQgKiBlbWl0dGVyLiBFdmVudHMgYXJlIHN0b3JlZCBoZXJlIHdoZW4gdGhlIG9yaWdpbiBkb2Vzbid0IGV4aXN0LCBzbyB0aGV5XG5cdFx0ICogY2FuIGJlIHNldCBvbiBhIG5ldyBvcmlnaW4gd2hlbiBvbmUgaXMgc2V0LlxuXHRcdCAqIEB0eXBlIHtBcnJheX1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wZW5kaW5nRXZlbnRzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBhIG1hcCBvZiBldmVudHMgZnJvbSB0aGUgb3JpZ2luIGVtaXR0ZXIgdGhhdCBhcmUgYWxyZWFkeSBiZWluZyBwcm94aWVkLlxuXHRcdCAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCAhRXZlbnRIYW5kbGU+fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSB0YXJnZXQgZW1pdHRlci4gVGhpcyBlbWl0dGVyIHdpbGwgZW1pdCBhbGwgZXZlbnRzIHRoYXQgY29tZSBmcm9tXG5cdFx0ICogdGhlIG9yaWdpbiBlbWl0dGVyLlxuXHRcdCAqIEB0eXBlIHtFdmVudEVtaXR0ZXJ9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudGFyZ2V0RW1pdHRlcl8gPSB0YXJnZXRFbWl0dGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogTWFwIG9mIGV2ZW50cyB0aGF0IHNob3VsZCBiZSBwcm94aWVkLiBJZiB3aGl0ZWxpc3QgaXMgc2V0IGJsYWNrbGlzdCBpcyBpZ25vcmVkLlxuXHRcdCAqIEB0eXBlIHtPYmplY3R9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMud2hpdGVsaXN0XyA9IHdoaXRlbGlzdDtcblxuXHRcdHRoaXMuc3RhcnRQcm94eV8oKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIHRoZSBnaXZlbiBsaXN0ZW5lciBmb3IgdGhlIGdpdmVuIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKX0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBUaGUgbGlzdGVuZWQgZXZlbnQncyBoYW5kbGUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFkZExpc3RlbmVyXyhldmVudCwgbGlzdGVuZXIpIHtcblx0XHRyZXR1cm4gdGhpcy5vcmlnaW5FbWl0dGVyXy5vbihldmVudCwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5yZW1vdmVMaXN0ZW5lcnNfKCk7XG5cdFx0dGhpcy5wcm94aWVkRXZlbnRzXyA9IG51bGw7XG5cdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyA9IG51bGw7XG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogRW1pdHMgdGhlIHNwZWNpZmllZCBldmVudCB0eXBlIG9uIHRoZSB0YXJnZXQgZW1pdHRlci5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0ZW1pdE9uVGFyZ2V0XyguLi5hcmdzKSB7XG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXy5lbWl0KC4uLmFyZ3MpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByb3hpZXMgdGhlIGdpdmVuIGV2ZW50IGZyb20gdGhlIG9yaWdpbiB0byB0aGUgdGFyZ2V0IGVtaXR0ZXIuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKi9cblx0cHJveHlFdmVudChldmVudCkge1xuXHRcdGlmICh0aGlzLnNob3VsZFByb3h5RXZlbnRfKGV2ZW50KSkge1xuXHRcdFx0dGhpcy50cnlUb0FkZExpc3RlbmVyXyhldmVudCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIHByb3h5IGxpc3RlbmVyIGZvciBhbGwgZXZlbnRzLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRyZW1vdmVMaXN0ZW5lcnNfKCkge1xuXHRcdGlmICh0aGlzLnByb3hpZWRFdmVudHNfKSB7XG5cdFx0XHRjb25zdCBldmVudHMgPSBPYmplY3Qua2V5cyh0aGlzLnByb3hpZWRFdmVudHNfKTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHRoaXMucHJveGllZEV2ZW50c19bZXZlbnRzW2ldXS5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzXyA9IG51bGw7XG5cdFx0fVxuXHRcdHRoaXMucGVuZGluZ0V2ZW50c18gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoYW5nZXMgdGhlIG9yaWdpbiBlbWl0dGVyLiBUaGlzIGF1dG9tYXRpY2FsbHkgZGV0YWNoZXMgYW55IGV2ZW50cyB0aGF0XG5cdCAqIHdlcmUgYWxyZWFkeSBiZWluZyBwcm94aWVkIGZyb20gdGhlIHByZXZpb3VzIGVtaXR0ZXIsIGFuZCBzdGFydHMgcHJveHlpbmdcblx0ICogdGhlbSBvbiB0aGUgbmV3IGVtaXR0ZXIgaW5zdGVhZC5cblx0ICogQHBhcmFtIHshRXZlbnRFbWl0dGVyfSBvcmlnaW5FbWl0dGVyXG5cdCAqL1xuXHRzZXRPcmlnaW5FbWl0dGVyKG9yaWdpbkVtaXR0ZXIpIHtcblx0XHRjb25zdCBldmVudHMgPVxuXHRcdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyAmJiB0aGlzLnByb3hpZWRFdmVudHNfXG5cdFx0XHRcdD8gT2JqZWN0LmtleXModGhpcy5wcm94aWVkRXZlbnRzXylcblx0XHRcdFx0OiB0aGlzLnBlbmRpbmdFdmVudHNfO1xuXHRcdHRoaXMub3JpZ2luRW1pdHRlcl8gPSBvcmlnaW5FbWl0dGVyO1xuXHRcdGlmIChldmVudHMpIHtcblx0XHRcdHRoaXMucmVtb3ZlTGlzdGVuZXJzXygpO1xuXHRcdFx0ZXZlbnRzLmZvckVhY2goZXZlbnQgPT4gdGhpcy5wcm94eUV2ZW50KGV2ZW50KSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZXZlbnQgc2hvdWxkIGJlIHByb3hpZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRzaG91bGRQcm94eUV2ZW50XyhldmVudCkge1xuXHRcdGlmICh0aGlzLndoaXRlbGlzdF8gJiYgIXRoaXMud2hpdGVsaXN0X1tldmVudF0pIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0aWYgKHRoaXMuYmxhY2tsaXN0XyAmJiB0aGlzLmJsYWNrbGlzdF9bZXZlbnRdKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiAhdGhpcy5wcm94aWVkRXZlbnRzXyB8fCAhdGhpcy5wcm94aWVkRXZlbnRzX1tldmVudF07XG5cdH1cblxuXHQvKipcblx0ICogU3RhcnRzIHByb3h5aW5nIGFsbCBldmVudHMgZnJvbSB0aGUgb3JpZ2luIHRvIHRoZSB0YXJnZXQgZW1pdHRlci5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0c3RhcnRQcm94eV8oKSB7XG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXy5vbkxpc3RlbmVyKHRoaXMucHJveHlFdmVudC5iaW5kKHRoaXMpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIG9yaWdpbiBlbWl0dGVyLCBpZiBpdCBleGlzdHMuIE90aGVyd2lzZSwgc3RvcmVzXG5cdCAqIHRoZSBwZW5kaW5nIGxpc3RlbmVyIHNvIGl0IGNhbiBiZSB1c2VkIG9uIGEgZnV0dXJlIG9yaWdpbiBlbWl0dGVyLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dHJ5VG9BZGRMaXN0ZW5lcl8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5vcmlnaW5FbWl0dGVyXykge1xuXHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzXyA9IHRoaXMucHJveGllZEV2ZW50c18gfHwge307XG5cdFx0XHR0aGlzLnByb3hpZWRFdmVudHNfW2V2ZW50XSA9IHRoaXMuYWRkTGlzdGVuZXJfKFxuXHRcdFx0XHRldmVudCxcblx0XHRcdFx0dGhpcy5lbWl0T25UYXJnZXRfLmJpbmQodGhpcywgZXZlbnQpXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnBlbmRpbmdFdmVudHNfID0gdGhpcy5wZW5kaW5nRXZlbnRzXyB8fCBbXTtcblx0XHRcdHRoaXMucGVuZGluZ0V2ZW50c18ucHVzaChldmVudCk7XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50RW1pdHRlclByb3h5O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge0Rpc3Bvc2FibGV9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBFdmVudEhhbmRsZXIgdXRpbGl0eS4gSXQncyB1c2VmdWwgZm9yIGVhc2lseSByZW1vdmluZyBhIGdyb3VwIG9mXG4gKiBsaXN0ZW5lcnMgZnJvbSBkaWZmZXJlbnQgRXZlbnRFbWl0dGVyIGluc3RhbmNlcy5cbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEhhbmRsZXIgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblx0LyoqXG5cdCAqIEV2ZW50SGFuZGxlciBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEFuIGFycmF5IHRoYXQgaG9sZHMgdGhlIGFkZGVkIGV2ZW50IGhhbmRsZXMsIHNvIHRoZSBsaXN0ZW5lcnMgY2FuIGJlXG5cdFx0ICogcmVtb3ZlZCBsYXRlci5cblx0XHQgKiBAdHlwZSB7QXJyYXkuPEV2ZW50SGFuZGxlPn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ldmVudEhhbmRsZXNfID0gW107XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBldmVudCBoYW5kbGVzIHRvIGJlIHJlbW92ZWQgbGF0ZXIgdGhyb3VnaCB0aGUgYHJlbW92ZUFsbExpc3RlbmVyc2Bcblx0ICogbWV0aG9kLlxuXHQgKiBAcGFyYW0gey4uLighRXZlbnRIYW5kbGUpfSB2YXJfYXJnc1xuXHQgKi9cblx0YWRkKC4uLmFyZ3MpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dGhpcy5ldmVudEhhbmRsZXNfLnB1c2goYXJnc1tpXSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy5cblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5ldmVudEhhbmRsZXNfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgdGhhdCBoYXZlIGJlZW4gYWRkZWQgdGhyb3VnaCB0aGUgYGFkZGAgbWV0aG9kLlxuXHQgKi9cblx0cmVtb3ZlQWxsTGlzdGVuZXJzKCkge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5ldmVudEhhbmRsZXNfLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmV2ZW50SGFuZGxlc19baV0ucmVtb3ZlTGlzdGVuZXIoKTtcblx0XHR9XG5cblx0XHR0aGlzLmV2ZW50SGFuZGxlc18gPSBbXTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEhhbmRsZXI7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXJyYXksIGlzU3RyaW5nfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgZG9tRGF0YSBmcm9tICcuL2RvbURhdGEnO1xuaW1wb3J0IHtFdmVudEhhbmRsZX0gZnJvbSAnbWV0YWwtZXZlbnRzJztcblxuLyoqXG4gKiBUaGlzIGlzIGEgc3BlY2lhbCBFdmVudEhhbmRsZSwgdGhhdCBpcyByZXNwb25zaWJsZSBmb3IgZG9tIGRlbGVnYXRlZCBldmVudHNcbiAqIChvbmx5IHRoZSBvbmVzIHRoYXQgcmVjZWl2ZSBhIHRhcmdldCBlbGVtZW50LCBub3QgYSBzZWxlY3RvciBzdHJpbmcpLlxuICogQGV4dGVuZHMge0V2ZW50SGFuZGxlfVxuICovXG5jbGFzcyBEb21EZWxlZ2F0ZWRFdmVudEhhbmRsZSBleHRlbmRzIEV2ZW50SGFuZGxlIHtcblx0LyoqXG5cdCAqIFRoZSBjb25zdHJ1Y3RvciBmb3IgYERvbURlbGVnYXRlZEV2ZW50SGFuZGxlYC5cblx0ICogQHBhcmFtIHshRXZlbnR9IGVtaXR0ZXIgRWxlbWVudCB0aGUgZXZlbnQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCB3YXMgc3Vic2NyaWJlZCB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmc9fSBzZWxlY3RvciBBbiBvcHRpb25hbCBzZWxlY3RvciB1c2VkIHdoZW4gZGVsZWdhdGluZ1xuXHQgKiAgICAgdGhlIGV2ZW50LlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKGVtaXR0ZXIsIGV2ZW50LCBsaXN0ZW5lciwgc2VsZWN0b3IpIHtcblx0XHRzdXBlcihlbWl0dGVyLCBldmVudCwgbGlzdGVuZXIpO1xuXHRcdHRoaXMuc2VsZWN0b3JfID0gc2VsZWN0b3I7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyKCkge1xuXHRcdGNvbnN0IGRlbGVnYXRpbmcgPSBkb21EYXRhLmdldCh0aGlzLmVtaXR0ZXJfLCAnZGVsZWdhdGluZycsIHt9KTtcblx0XHRjb25zdCBsaXN0ZW5lcnMgPSBkb21EYXRhLmdldCh0aGlzLmVtaXR0ZXJfLCAnbGlzdGVuZXJzJywge30pO1xuXHRcdGNvbnN0IHNlbGVjdG9yID0gdGhpcy5zZWxlY3Rvcl87XG5cdFx0Y29uc3QgYXJyID0gaXNTdHJpbmcoc2VsZWN0b3IpXG5cdFx0XHQ/IGRlbGVnYXRpbmdbdGhpcy5ldmVudF9dLnNlbGVjdG9yc1xuXHRcdFx0OiBsaXN0ZW5lcnM7XG5cdFx0Y29uc3Qga2V5ID0gaXNTdHJpbmcoc2VsZWN0b3IpID8gc2VsZWN0b3IgOiB0aGlzLmV2ZW50XztcblxuXHRcdGFycmF5LnJlbW92ZShhcnJba2V5XSB8fCBbXSwgdGhpcy5saXN0ZW5lcl8pO1xuXHRcdGlmIChhcnJba2V5XSAmJiBhcnJba2V5XS5sZW5ndGggPT09IDApIHtcblx0XHRcdGRlbGV0ZSBhcnJba2V5XTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7RXZlbnRIYW5kbGV9IGZyb20gJ21ldGFsLWV2ZW50cyc7XG5cbi8qKlxuICogVGhpcyBpcyBhIHNwZWNpYWwgRXZlbnRIYW5kbGUsIHRoYXQgaXMgcmVzcG9uc2libGUgZm9yIGRvbSBldmVudHMsIGluc3RlYWRcbiAqIG9mIEV2ZW50RW1pdHRlciBldmVudHMuXG4gKiBAZXh0ZW5kcyB7RXZlbnRIYW5kbGV9XG4gKi9cbmNsYXNzIERvbUV2ZW50SGFuZGxlIGV4dGVuZHMgRXZlbnRIYW5kbGUge1xuXHQvKipcblx0ICogVGhlIGNvbnN0cnVjdG9yIGZvciBgRG9tRXZlbnRIYW5kbGVgLlxuXHQgKiBAcGFyYW0geyFFdmVudEVtaXR0ZXJ9IGVtaXR0ZXIgRW1pdHRlciB0aGUgZXZlbnQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCB3YXMgc3Vic2NyaWJlZCB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0ICogQHBhcmFtIHtib29sZWFufSBjYXB0dXJlIEZsYWcgaW5kaWNhdGluZyBpZiBsaXN0ZW5lciBzaG91bGQgYmUgdHJpZ2dlcmVkXG5cdCAqICAgZHVyaW5nIGNhcHR1cmUgcGhhc2UsIGluc3RlYWQgb2YgZHVyaW5nIHRoZSBidWJibGluZyBwaGFzZS4gRGVmYXVsdHMgdG8gZmFsc2UuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoZW1pdHRlciwgZXZlbnQsIGxpc3RlbmVyLCBjYXB0dXJlKSB7XG5cdFx0c3VwZXIoZW1pdHRlciwgZXZlbnQsIGxpc3RlbmVyKTtcblx0XHR0aGlzLmNhcHR1cmVfID0gY2FwdHVyZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0cmVtb3ZlTGlzdGVuZXIoKSB7XG5cdFx0dGhpcy5lbWl0dGVyXy5yZW1vdmVFdmVudExpc3RlbmVyKFxuXHRcdFx0dGhpcy5ldmVudF8sXG5cdFx0XHR0aGlzLmxpc3RlbmVyXyxcblx0XHRcdHRoaXMuY2FwdHVyZV9cblx0XHQpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERvbUV2ZW50SGFuZGxlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge1xuXHRpc0RlZixcblx0aXNEZWZBbmROb3ROdWxsLFxuXHRpc0RvY3VtZW50LFxuXHRpc0RvY3VtZW50RnJhZ21lbnQsXG5cdGlzRWxlbWVudCxcblx0aXNPYmplY3QsXG5cdGlzU3RyaW5nLFxuXHRvYmplY3QsXG59IGZyb20gJ21ldGFsJztcbmltcG9ydCBkb21EYXRhIGZyb20gJy4vZG9tRGF0YSc7XG5pbXBvcnQgRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGUgZnJvbSAnLi9Eb21EZWxlZ2F0ZWRFdmVudEhhbmRsZSc7XG5pbXBvcnQgRG9tRXZlbnRIYW5kbGUgZnJvbSAnLi9Eb21FdmVudEhhbmRsZSc7XG5cbmNvbnN0IGVsZW1lbnRzQnlUYWdfID0ge307XG5jb25zdCBzdXBwb3J0Q2FjaGVfID0ge307XG5leHBvcnQgY29uc3QgY3VzdG9tRXZlbnRzID0ge307XG5cbmNvbnN0IExBU1RfQ09OVEFJTkVSID0gJ19fbWV0YWxfbGFzdF9jb250YWluZXJfXyc7XG5jb25zdCBVU0VfQ0FQVFVSRSA9IHtcblx0Ymx1cjogdHJ1ZSxcblx0ZXJyb3I6IHRydWUsXG5cdGZvY3VzOiB0cnVlLFxuXHRpbnZhbGlkOiB0cnVlLFxuXHRsb2FkOiB0cnVlLFxuXHRzY3JvbGw6IHRydWUsXG59O1xuXG4vKipcbiAqIEFkZHMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyB0byBhbiBlbGVtZW50LlxuICogQHBhcmFtIHshRWxlbWVudHwhTm9kZWxpc3R9IGVsZW1lbnRzIFRoZSBlbGVtZW50IG9yIGVsZW1lbnRzIHRvIGFkZCBDU1MgY2xhc3NlcyB0by5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIGFkZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZENsYXNzZXMoZWxlbWVudHMsIGNsYXNzZXMpIHtcblx0aWYgKCFpc09iamVjdChlbGVtZW50cykgfHwgIWlzU3RyaW5nKGNsYXNzZXMpKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0aWYgKCFlbGVtZW50cy5sZW5ndGgpIHtcblx0XHRlbGVtZW50cyA9IFtlbGVtZW50c107XG5cdH1cblxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKCdjbGFzc0xpc3QnIGluIGVsZW1lbnRzW2ldKSB7XG5cdFx0XHRhZGRDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhZGRDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIEFkZHMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyB0byBhbiBlbGVtZW50IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gYWRkIENTUyBjbGFzc2VzIHRvLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgQ1NTIGNsYXNzZXMgdG8gYWRkLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkQ2xhc3Nlc1dpdGhOYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpIHtcblx0Y2xhc3Nlcy5zcGxpdCgnICcpLmZvckVhY2goZnVuY3Rpb24oY2xhc3NOYW1lKSB7XG5cdFx0aWYgKGNsYXNzTmFtZSkge1xuXHRcdFx0ZWxlbWVudC5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuLyoqXG4gKiBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBFbGVtZW50LmNsYXNzTGlzdC5hZGQgZnVuY3Rpb24sIHRoaXMgbWV0aG9kXG4gKiBhZGRzIHRoZSByZXF1ZXN0ZWQgQ1NTIGNsYXNzZXMgdG8gYW4gZWxlbWVudCB3aXRob3V0IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gYWRkIENTUyBjbGFzc2VzIHRvLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgQ1NTIGNsYXNzZXMgdG8gYWRkLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkQ2xhc3Nlc1dpdGhvdXROYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpIHtcblx0Y29uc3QgZWxlbWVudENsYXNzTmFtZSA9IGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYDtcblx0bGV0IGNsYXNzZXNUb0FwcGVuZCA9ICcnO1xuXG5cdGNsYXNzZXMgPSBjbGFzc2VzLnNwbGl0KCcgJyk7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjbGFzc2VzLmxlbmd0aDsgaSsrKSB7XG5cdFx0Y29uc3QgY2xhc3NOYW1lID0gY2xhc3Nlc1tpXTtcblxuXHRcdGlmIChlbGVtZW50Q2xhc3NOYW1lLmluZGV4T2YoYCAke2NsYXNzTmFtZX0gYCkgPT09IC0xKSB7XG5cdFx0XHRjbGFzc2VzVG9BcHBlbmQgKz0gYCAke2NsYXNzTmFtZX1gO1xuXHRcdH1cblx0fVxuXG5cdGlmIChjbGFzc2VzVG9BcHBlbmQpIHtcblx0XHRlbGVtZW50LmNsYXNzTmFtZSA9IGVsZW1lbnQuY2xhc3NOYW1lICsgY2xhc3Nlc1RvQXBwZW5kO1xuXHR9XG59XG5cbi8qKlxuICogQWRkcyBhbiBldmVudCBsaXN0ZW5lciB0byB0aGUgZ2l2ZW4gZWxlbWVudCwgdG8gYmUgdHJpZ2dlcmVkIHZpYSBkZWxlZ2F0ZS5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGxpc3RlbmVyXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBhZGRFbGVtZW50TGlzdGVuZXJfKGVsZW1lbnQsIGV2ZW50TmFtZSwgbGlzdGVuZXIpIHtcblx0YWRkVG9BcnJfKGRvbURhdGEuZ2V0KGVsZW1lbnQsICdsaXN0ZW5lcnMnLCB7fSksIGV2ZW50TmFtZSwgbGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIEFkZHMgYW4gZXZlbnQgbGlzdGVuZXIgdG8gdGhlIGdpdmVuIGVsZW1lbnQsIHRvIGJlIHRyaWdnZXJlZCB2aWEgZGVsZWdhdGVcbiAqIHNlbGVjdG9ycy5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICogQHBhcmFtIHshZnVuY3Rpb24oKX0gbGlzdGVuZXJcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGFkZFNlbGVjdG9yTGlzdGVuZXJfKGVsZW1lbnQsIGV2ZW50TmFtZSwgc2VsZWN0b3IsIGxpc3RlbmVyKSB7XG5cdGNvbnN0IGRlbGVnYXRpbmdEYXRhID0gZG9tRGF0YS5nZXQoZWxlbWVudCwgJ2RlbGVnYXRpbmcnLCB7fSk7XG5cdGFkZFRvQXJyXyhkZWxlZ2F0aW5nRGF0YVtldmVudE5hbWVdLnNlbGVjdG9ycywgc2VsZWN0b3IsIGxpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBBZGRzIGEgdmFsdWUgdG8gYW4gYXJyYXkgaW5zaWRlIGFuIG9iamVjdCwgY3JlYXRpbmcgaXQgZmlyc3QgaWYgaXQgZG9lc24ndFxuICogeWV0IGV4aXN0LlxuICogQHBhcmFtIHshQXJyYXl9IGFyclxuICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICogQHBhcmFtIHsqfSB2YWx1ZVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkVG9BcnJfKGFyciwga2V5LCB2YWx1ZSkge1xuXHRpZiAoIWFycltrZXldKSB7XG5cdFx0YXJyW2tleV0gPSBbXTtcblx0fVxuXHRhcnJba2V5XS5wdXNoKHZhbHVlKTtcbn1cblxuLyoqXG4gKiBBdHRhY2hlcyBhIGRlbGVnYXRlIGxpc3RlbmVyLCB1bmxlc3MgdGhlcmUncyBhbHJlYWR5IG9uZSBhdHRhY2hlZC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGF0dGFjaERlbGVnYXRlRXZlbnRfKGVsZW1lbnQsIGV2ZW50TmFtZSkge1xuXHRsZXQgZGVsZWdhdGluZ0RhdGEgPSBkb21EYXRhLmdldChlbGVtZW50LCAnZGVsZWdhdGluZycsIHt9KTtcblx0aWYgKCFkZWxlZ2F0aW5nRGF0YVtldmVudE5hbWVdKSB7XG5cdFx0ZGVsZWdhdGluZ0RhdGFbZXZlbnROYW1lXSA9IHtcblx0XHRcdGhhbmRsZTogb24oXG5cdFx0XHRcdGVsZW1lbnQsXG5cdFx0XHRcdGV2ZW50TmFtZSxcblx0XHRcdFx0aGFuZGxlRGVsZWdhdGVFdmVudF8sXG5cdFx0XHRcdCEhVVNFX0NBUFRVUkVbZXZlbnROYW1lXVxuXHRcdFx0KSxcblx0XHRcdHNlbGVjdG9yczoge30sXG5cdFx0fTtcblx0fVxufVxuXG4vKipcbiAqIElFMTEgZG9lc24ndCBzdXBwb3J0IEVsZW1lbnQuY2xvc2VzdCBmdW5jdGlvbiwgdGhpcyBtZXRob2RcbiAqIGdldHMgdGhlIGNsb3Nlc3QgZWxlbWVudCB1cCB0aGUgdHJlZSBmcm9tIHRoZSBnaXZlbiBlbGVtZW50IChpbmNsdWRpbmdcbiAqIGl0c2VsZikgdGhhdCBtYXRjaGVzIHRoZSBzcGVjaWZpZWQgc2VsZWN0b3IsIG9yIG51bGwgaWYgbm9uZSBtYXRjaC5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcmV0dXJuIHtFbGVtZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xvc2VzdChlbGVtZW50LCBzZWxlY3Rvcikge1xuXHR3aGlsZSAoZWxlbWVudCAmJiAhbWF0Y2goZWxlbWVudCwgc2VsZWN0b3IpKSB7XG5cdFx0ZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcblx0fVxuXHRyZXR1cm4gZWxlbWVudDtcbn1cblxuLyoqXG4gKiBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBFbGVtZW50LmNsYXNzTGlzdC5hZGQgZnVuY3Rpb24sIHRoaXMgbWV0aG9kXG4gKiBhcHBlbmRzIGEgY2hpbGQgbm9kZSB3aXRoIHRleHQgb3Igb3RoZXIgbm9kZXMgdG8gYSBwYXJlbnQgbm9kZS4gSWZcbiAqIGNoaWxkIGlzIGEgSFRNTCBzdHJpbmcgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNvbnZlcnRlZCB0byBhIGRvY3VtZW50XG4gKiBmcmFnbWVudCBiZWZvcmUgYXBwZW5kaW5nIGl0IHRvIHRoZSBwYXJlbnQuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBwYXJlbnQgVGhlIG5vZGUgdG8gYXBwZW5kIG5vZGVzIHRvLlxuICogQHBhcmFtIHshKEVsZW1lbnR8Tm9kZUxpc3R8c3RyaW5nKX0gY2hpbGQgVGhlIHRoaW5nIHRvIGFwcGVuZCB0byB0aGUgcGFyZW50LlxuICogQHJldHVybiB7IUVsZW1lbnR9IFRoZSBhcHBlbmRlZCBjaGlsZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGVuZChwYXJlbnQsIGNoaWxkKSB7XG5cdGlmIChpc1N0cmluZyhjaGlsZCkpIHtcblx0XHRjaGlsZCA9IGJ1aWxkRnJhZ21lbnQoY2hpbGQpO1xuXHR9XG5cdGlmIChpc05vZGVMaXN0TGlrZShjaGlsZCkpIHtcblx0XHRjb25zdCBjaGlsZEFyciA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGNoaWxkKTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkQXJyLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRwYXJlbnQuYXBwZW5kQ2hpbGQoY2hpbGRBcnJbaV0pO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRwYXJlbnQuYXBwZW5kQ2hpbGQoY2hpbGQpO1xuXHR9XG5cdHJldHVybiBjaGlsZDtcbn1cblxuLyoqXG4gKiBIZWxwZXIgZm9yIGNvbnZlcnRpbmcgYSBIVE1MIHN0cmluZyBpbnRvIGEgZG9jdW1lbnQgZnJhZ21lbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gaHRtbFN0cmluZyBUaGUgSFRNTCBzdHJpbmcgdG8gY29udmVydC5cbiAqIEByZXR1cm4geyFFbGVtZW50fSBUaGUgcmVzdWx0aW5nIGRvY3VtZW50IGZyYWdtZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRGcmFnbWVudChodG1sU3RyaW5nKSB7XG5cdGNvbnN0IHRlbXBEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblx0dGVtcERpdi5pbm5lckhUTUwgPSBgPGJyPiR7aHRtbFN0cmluZ31gO1xuXHR0ZW1wRGl2LnJlbW92ZUNoaWxkKHRlbXBEaXYuZmlyc3RDaGlsZCk7XG5cblx0Y29uc3QgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cdHdoaWxlICh0ZW1wRGl2LmZpcnN0Q2hpbGQpIHtcblx0XHRmcmFnbWVudC5hcHBlbmRDaGlsZCh0ZW1wRGl2LmZpcnN0Q2hpbGQpO1xuXHR9XG5cdHJldHVybiBmcmFnbWVudDtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGZpcnN0IGVsZW1lbnQgY29udGFpbnMgdGhlIHNlY29uZCBvbmUuXG4gKiBAZGVwcmVjYXRlZCBVc2UgZWxlbWVudDEuY29udGFpbnMoZWxlbWVudDIpIGRpcmVjdGx5IGluc3RlYWQgb2YgdGhpcyBtZXRob2RcbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQxXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50MlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zKGVsZW1lbnQxLCBlbGVtZW50Mikge1xuXHRpZiAoaXNEb2N1bWVudChlbGVtZW50MSkpIHtcblx0XHQvLyBkb2N1bWVudC5jb250YWlucyBpcyBub3QgZGVmaW5lZCBvbiBJRTksIHNvIGNhbGwgaXQgb24gZG9jdW1lbnRFbGVtZW50IGluc3RlYWQuXG5cdFx0cmV0dXJuIGVsZW1lbnQxLmRvY3VtZW50RWxlbWVudC5jb250YWlucyhlbGVtZW50Mik7XG5cdH0gZWxzZSB7XG5cdFx0cmV0dXJuIGVsZW1lbnQxLmNvbnRhaW5zKGVsZW1lbnQyKTtcblx0fVxufVxuXG4vKipcbiAqIExpc3RlbnMgdG8gdGhlIHNwZWNpZmllZCBldmVudCBvbiB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQsIGJ1dCBvbmx5IGNhbGxzIHRoZVxuICogZ2l2ZW4gY2FsbGJhY2sgbGlzdGVuZXIgd2hlbiBpdCdzIHRyaWdnZXJlZCBieSBlbGVtZW50cyB0aGF0IG1hdGNoIHRoZVxuICogZ2l2ZW4gc2VsZWN0b3Igb3IgdGFyZ2V0IGVsZW1lbnQuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBET00gZWxlbWVudCB0aGUgZXZlbnQgc2hvdWxkIGJlIGxpc3RlbmVkIG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gbGlzdGVuIHRvLlxuICogQHBhcmFtIHshRWxlbWVudHxzdHJpbmd9IHNlbGVjdG9yT3JUYXJnZXQgRWl0aGVyIGFuIGVsZW1lbnQgb3IgY3NzIHNlbGVjdG9yXG4gKiAgICAgdGhhdCBzaG91bGQgbWF0Y2ggdGhlIGV2ZW50IGZvciB0aGUgbGlzdGVuZXIgdG8gYmUgdHJpZ2dlcmVkLlxuICogQHBhcmFtIHshZnVuY3Rpb24oIU9iamVjdCl9IGNhbGxiYWNrIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudFxuICogICAgIGlzIHRyaWdnZXJlZC4gSXQgd2lsbCByZWNlaXZlIHRoZSBub3JtYWxpemVkIGV2ZW50IG9iamVjdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbj19IGRlZmF1bHRMaXN0ZW5lciBPcHRpb25hbCBmbGFnIGluZGljYXRpbmcgaWYgdGhpcyBpcyBhIGRlZmF1bHRcbiAqICAgICBsaXN0ZW5lci4gVGhhdCBtZWFucyB0aGF0IGl0IHdvdWxkIG9ubHkgYmUgZXhlY3V0ZWQgYWZ0ZXIgYWxsIG5vblxuICogICAgIGRlZmF1bHQgbGlzdGVuZXJzLCBhbmQgb25seSBpZiB0aGUgZXZlbnQgaXNuJ3QgcHJldmVudGVkIHZpYVxuICogICAgIGBwcmV2ZW50RGVmYXVsdGAuXG4gKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWxlZ2F0ZShcblx0ZWxlbWVudCxcblx0ZXZlbnROYW1lLFxuXHRzZWxlY3Rvck9yVGFyZ2V0LFxuXHRjYWxsYmFjayxcblx0ZGVmYXVsdExpc3RlbmVyXG4pIHtcblx0Y29uc3QgY3VzdG9tQ29uZmlnID0gY3VzdG9tRXZlbnRzW2V2ZW50TmFtZV07XG5cdGlmIChjdXN0b21Db25maWcgJiYgY3VzdG9tQ29uZmlnLmRlbGVnYXRlKSB7XG5cdFx0ZXZlbnROYW1lID0gY3VzdG9tQ29uZmlnLm9yaWdpbmFsRXZlbnQ7XG5cdFx0Y2FsbGJhY2sgPSBjdXN0b21Db25maWcuaGFuZGxlci5iaW5kKGN1c3RvbUNvbmZpZywgY2FsbGJhY2spO1xuXHR9XG5cblx0aWYgKGRlZmF1bHRMaXN0ZW5lcikge1xuXHRcdC8vIFdyYXAgY2FsbGJhY2sgc28gd2UgZG9uJ3Qgc2V0IHByb3BlcnR5IGRpcmVjdGx5IG9uIGl0LlxuXHRcdGNhbGxiYWNrID0gY2FsbGJhY2suYmluZCgpO1xuXHRcdGNhbGxiYWNrLmRlZmF1bHRMaXN0ZW5lcl8gPSB0cnVlO1xuXHR9XG5cblx0YXR0YWNoRGVsZWdhdGVFdmVudF8oZWxlbWVudCwgZXZlbnROYW1lKTtcblx0aWYgKGlzU3RyaW5nKHNlbGVjdG9yT3JUYXJnZXQpKSB7XG5cdFx0YWRkU2VsZWN0b3JMaXN0ZW5lcl8oZWxlbWVudCwgZXZlbnROYW1lLCBzZWxlY3Rvck9yVGFyZ2V0LCBjYWxsYmFjayk7XG5cdH0gZWxzZSB7XG5cdFx0YWRkRWxlbWVudExpc3RlbmVyXyhzZWxlY3Rvck9yVGFyZ2V0LCBldmVudE5hbWUsIGNhbGxiYWNrKTtcblx0fVxuXG5cdHJldHVybiBuZXcgRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGUoXG5cdFx0aXNTdHJpbmcoc2VsZWN0b3JPclRhcmdldCkgPyBlbGVtZW50IDogc2VsZWN0b3JPclRhcmdldCxcblx0XHRldmVudE5hbWUsXG5cdFx0Y2FsbGJhY2ssXG5cdFx0aXNTdHJpbmcoc2VsZWN0b3JPclRhcmdldCkgPyBzZWxlY3Rvck9yVGFyZ2V0IDogbnVsbFxuXHQpO1xufVxuXG4vKipcbiAqIFZlcmlmaWVzIGlmIHRoZSBlbGVtZW50IGlzIGFibGUgdG8gdHJpZ2dlciB0aGUgQ2xpY2sgZXZlbnQsXG4gKiBzaW11bGF0aW5nIGJyb3dzZXJzIGJlaGF2aW91ciwgYXZvaWRpbmcgZXZlbnQgbGlzdGVuZXJzIHRvIGJlIGNhbGxlZCBieSB0cmlnZ2VyRXZlbnQgbWV0aG9kLlxuICogQHBhcmFtIHtFbGVtZW50fSBub2RlIEVsZW1lbnQgdG8gYmUgY2hlY2tlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIGV2ZW50IG5hbWUuXG4gKiBAcGFyYW0ge09iamVjdD19IGV2ZW50T2JqXG4gKiBAcHJpdmF0ZVxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNBYmxlVG9JbnRlcmFjdFdpdGhfKG5vZGUsIGV2ZW50TmFtZSwgZXZlbnRPYmopIHtcblx0aWYgKGV2ZW50T2JqICYmIGV2ZW50TmFtZSA9PT0gJ2NsaWNrJyAmJiBldmVudE9iai5idXR0b24gPT09IDIpIHtcblx0XHQvLyBGaXJlZm94IHRyaWdnZXJzIFwiY2xpY2tcIiBldmVudHMgb24gdGhlIGRvY3VtZW50IGZvciByaWdodCBjbGlja3MuIFRoaXNcblx0XHQvLyBjYXVzZXMgb3VyIGRlbGVnYXRlIGxvZ2ljIHRvIHRyaWdnZXIgaXQgZm9yIHJlZ3VsYXIgZWxlbWVudHMgdG9vLCB3aGljaFxuXHRcdC8vIHNob3VsZG4ndCBoYXBwZW4uIElnbm9yaW5nIHRoZW0gaGVyZS5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRjb25zdCBtYXRjaGVzU2VsZWN0b3IgPSBbXG5cdFx0J0JVVFRPTicsXG5cdFx0J0lOUFVUJyxcblx0XHQnU0VMRUNUJyxcblx0XHQnVEVYVEFSRUEnLFxuXHRcdCdGSUVMRFNFVCcsXG5cdF07XG5cdGlmIChldmVudE5hbWUgPT09ICdjbGljaycgJiYgbWF0Y2hlc1NlbGVjdG9yLmluZGV4T2Yobm9kZS50YWdOYW1lKSA+IC0xKSB7XG5cdFx0cmV0dXJuICEobm9kZS5kaXNhYmxlZCB8fCBwYXJlbnQobm9kZSwgJ2ZpZWxkc2V0W2Rpc2FibGVkXScpKTtcblx0fVxuXHRyZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBhIE5vZGVMaXN0IG9yIGxpa2Ugb25lLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgbGlrZSBhIE5vZGVMaXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNOb2RlTGlzdExpa2UodmFsKSB7XG5cdHJldHVybiAoXG5cdFx0aXNEZWZBbmROb3ROdWxsKHZhbCkgJiZcblx0XHR0eXBlb2YgdmFsLmxlbmd0aCA9PT0gJ251bWJlcicgJiZcblx0XHR0eXBlb2YgdmFsLml0ZW0gPT09ICdmdW5jdGlvbidcblx0KTtcbn1cblxuLyoqXG4gKiBJbnNlcnRzIG5vZGUgaW4gZG9jdW1lbnQgYXMgbGFzdCBlbGVtZW50LlxuICogQHBhcmFtIHtFbGVtZW50fSBub2RlIEVsZW1lbnQgdG8gcmVtb3ZlIGNoaWxkcmVuIGZyb20uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnRlckRvY3VtZW50KG5vZGUpIHtcblx0bm9kZSAmJiBhcHBlbmQoZG9jdW1lbnQuYm9keSwgbm9kZSk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBub2RlIGZyb20gZG9jdW1lbnQuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGUgRWxlbWVudCB0byByZW1vdmUgY2hpbGRyZW4gZnJvbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4aXREb2N1bWVudChub2RlKSB7XG5cdGlmIChub2RlICYmIG5vZGUucGFyZW50Tm9kZSkge1xuXHRcdG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcblx0fVxufVxuXG4vKipcbiAqIFRoaXMgaXMgY2FsbGVkIHdoZW4gYW4gZXZlbnQgaXMgdHJpZ2dlcmVkIGJ5IGEgZGVsZWdhdGUgbGlzdGVuZXIuIEFsbFxuICogbWF0Y2hpbmcgbGlzdGVuZXJzIG9mIHRoaXMgZXZlbnQgdHlwZSBmcm9tIGB0YXJnZXRgIHRvIGBjdXJyZW50VGFyZ2V0YCB3aWxsXG4gKiBiZSB0cmlnZ2VyZWQuXG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgVGhlIGV2ZW50IHBheWxvYWQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBGYWxzZSBpZiBhdCBsZWFzdCBvbmUgb2YgdGhlIHRyaWdnZXJlZCBjYWxsYmFja3MgcmV0dXJuc1xuICogICAgIGZhbHNlLCBvciB0cnVlIG90aGVyd2lzZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZURlbGVnYXRlRXZlbnRfKGV2ZW50KSB7XG5cdG5vcm1hbGl6ZURlbGVnYXRlRXZlbnRfKGV2ZW50KTtcblx0bGV0IHJldCA9IHRydWU7XG5cdGNvbnN0IGNvbnRhaW5lciA9IGV2ZW50LmN1cnJlbnRUYXJnZXQ7XG5cdGNvbnN0IGRlZkZucyA9IFtdO1xuXG5cdHJldCAmPSB0cmlnZ2VyRGVsZWdhdGVkTGlzdGVuZXJzXyhjb250YWluZXIsIGV2ZW50LCBkZWZGbnMpO1xuXHRyZXQgJj0gdHJpZ2dlckRlZmF1bHREZWxlZ2F0ZWRMaXN0ZW5lcnNfKGRlZkZucywgZXZlbnQpO1xuXG5cdGV2ZW50LmRlbGVnYXRlVGFyZ2V0ID0gbnVsbDtcblx0ZXZlbnRbTEFTVF9DT05UQUlORVJdID0gY29udGFpbmVyO1xuXHRyZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZWxlbWVudCBoYXMgdGhlIHJlcXVlc3RlZCBjc3MgY2xhc3MuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzQ2xhc3MoZWxlbWVudCwgY2xhc3NOYW1lKSB7XG5cdGlmICgnY2xhc3NMaXN0JyBpbiBlbGVtZW50KSB7XG5cdFx0cmV0dXJuIGhhc0NsYXNzV2l0aE5hdGl2ZV8oZWxlbWVudCwgY2xhc3NOYW1lKTtcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gaGFzQ2xhc3NXaXRob3V0TmF0aXZlXyhlbGVtZW50LCBjbGFzc05hbWUpO1xuXHR9XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IGhhcyB0aGUgcmVxdWVzdGVkIGNzcyBjbGFzcyB1c2luZyBjbGFzc0xpc3QuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gaGFzQ2xhc3NXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc05hbWUpIHtcblx0cmV0dXJuIChcblx0XHRjbGFzc05hbWUuaW5kZXhPZignICcpID09PSAtMSAmJiBlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhjbGFzc05hbWUpXG5cdCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IGhhcyB0aGUgcmVxdWVzdGVkIGNzcyBjbGFzcyB3aXRob3V0IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc05hbWVcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBoYXNDbGFzc1dpdGhvdXROYXRpdmVfKGVsZW1lbnQsIGNsYXNzTmFtZSkge1xuXHRyZXR1cm4gKFxuXHRcdGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYC5pbmRleE9mKGAgJHtjbGFzc05hbWV9IGApID49IDAgJiZcblx0XHRjbGFzc05hbWUuc3BsaXQoJyAnKS5sZW5ndGggPT09IDFcblx0KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGdpdmVuIGVsZW1lbnQgaXMgZW1wdHkgb3Igbm90LlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRW1wdHkoZWxlbWVudCkge1xuXHRyZXR1cm4gZWxlbWVudC5jaGlsZE5vZGVzLmxlbmd0aCA9PT0gMDtcbn1cblxuLyoqXG4gKiBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBFbGVtZW50Lm1hdGNoZXMgZnVuY3Rpb24sIHRoaXMgbWV0aG9kXG4gKiBjaGVjayBpZiBhbiBlbGVtZW50IG1hdGNoZXMgYSBnaXZlbiBzZWxlY3Rvci5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2goZWxlbWVudCwgc2VsZWN0b3IpIHtcblx0aWYgKCFlbGVtZW50IHx8IGVsZW1lbnQubm9kZVR5cGUgIT09IDEpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRjb25zdCBwID0gRWxlbWVudC5wcm90b3R5cGU7XG5cdGNvbnN0IG0gPVxuXHRcdHAubWF0Y2hlcyB8fFxuXHRcdHAud2Via2l0TWF0Y2hlc1NlbGVjdG9yIHx8XG5cdFx0cC5tb3pNYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRwLm1zTWF0Y2hlc1NlbGVjdG9yIHx8XG5cdFx0cC5vTWF0Y2hlc1NlbGVjdG9yO1xuXHRpZiAobSkge1xuXHRcdHJldHVybiBtLmNhbGwoZWxlbWVudCwgc2VsZWN0b3IpO1xuXHR9XG5cblx0cmV0dXJuIG1hdGNoRmFsbGJhY2tfKGVsZW1lbnQsIHNlbGVjdG9yKTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhbiBlbGVtZW50IG1hdGNoZXMgYSBnaXZlbiBzZWxlY3RvciwgdXNpbmcgYW4gaW50ZXJuYWwgaW1wbGVtZW50YXRpb25cbiAqIGluc3RlYWQgb2YgY2FsbGluZyBleGlzdGluZyBqYXZhc2NyaXB0IGZ1bmN0aW9ucy5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gbWF0Y2hGYWxsYmFja18oZWxlbWVudCwgc2VsZWN0b3IpIHtcblx0Y29uc3QgcGFyZW50Tm9kZSA9IGVsZW1lbnQucGFyZW50Tm9kZTtcblxuXHRpZiAocGFyZW50Tm9kZSkge1xuXHRcdGNvbnN0IG5vZGVzID0gcGFyZW50Tm9kZS5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKTtcblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyArK2kpIHtcblx0XHRcdGlmIChub2Rlc1tpXSA9PT0gZWxlbWVudCkge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbmV4dCBzaWJsaW5nIG9mIHRoZSBnaXZlbiBlbGVtZW50IHRoYXQgbWF0Y2hlcyB0aGUgc3BlY2lmaWVkXG4gKiBzZWxlY3Rvciwgb3IgbnVsbCBpZiB0aGVyZSBpcyBub25lLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHs/c3RyaW5nfSBzZWxlY3RvclxuICogQHJldHVybiB7RWxlbWVudHxudWxsfVxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV4dChlbGVtZW50LCBzZWxlY3Rvcikge1xuXHRkbyB7XG5cdFx0ZWxlbWVudCA9IGVsZW1lbnQubmV4dFNpYmxpbmc7XG5cdFx0aWYgKGVsZW1lbnQgJiYgbWF0Y2goZWxlbWVudCwgc2VsZWN0b3IpKSB7XG5cdFx0XHRyZXR1cm4gZWxlbWVudDtcblx0XHR9XG5cdH0gd2hpbGUgKGVsZW1lbnQpO1xuXHRyZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBOb3JtYWxpemVzIHRoZSBldmVudCBwYXlsb2FkIGZvciBkZWxlZ2F0ZSBsaXN0ZW5lcnMuXG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnRcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZURlbGVnYXRlRXZlbnRfKGV2ZW50KSB7XG5cdGV2ZW50LnN0b3BQcm9wYWdhdGlvbiA9IHN0b3BQcm9wYWdhdGlvbl87XG5cdGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbiA9IHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbl87XG59XG5cbi8qKlxuICogTGlzdGVucyB0byB0aGUgc3BlY2lmaWVkIGV2ZW50IG9uIHRoZSBnaXZlbiBET00gZWxlbWVudC4gVGhpcyBmdW5jdGlvbiBub3JtYWxpemVzXG4gKiBET00gZXZlbnQgcGF5bG9hZHMgYW5kIGZ1bmN0aW9ucyBzbyB0aGV5J2xsIHdvcmsgdGhlIHNhbWUgd2F5IG9uIGFsbCBzdXBwb3J0ZWRcbiAqIGJyb3dzZXJzLlxuICogQHBhcmFtIHshRWxlbWVudHxzdHJpbmd9IGVsZW1lbnQgVGhlIERPTSBlbGVtZW50IHRvIGxpc3RlbiB0byB0aGUgZXZlbnQgb24sIG9yXG4gKiAgIGEgc2VsZWN0b3IgdGhhdCBzaG91bGQgYmUgZGVsZWdhdGVkIG9uIHRoZSBlbnRpcmUgZG9jdW1lbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBsaXN0ZW4gdG8uXG4gKiBAcGFyYW0geyFmdW5jdGlvbighT2JqZWN0KX0gY2FsbGJhY2sgRnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzXG4gKiAgIHRyaWdnZXJlZC4gSXQgd2lsbCByZWNlaXZlIHRoZSBub3JtYWxpemVkIGV2ZW50IG9iamVjdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gY2FwdHVyZSBGbGFnIGluZGljYXRpbmcgaWYgbGlzdGVuZXIgc2hvdWxkIGJlIHRyaWdnZXJlZFxuICogICBkdXJpbmcgY2FwdHVyZSBwaGFzZSwgaW5zdGVhZCBvZiBkdXJpbmcgdGhlIGJ1YmJsaW5nIHBoYXNlLiBEZWZhdWx0cyB0byBmYWxzZS5cbiAqIEByZXR1cm4geyFEb21FdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uKGVsZW1lbnQsIGV2ZW50TmFtZSwgY2FsbGJhY2ssIGNhcHR1cmUpIHtcblx0aWYgKGlzU3RyaW5nKGVsZW1lbnQpKSB7XG5cdFx0cmV0dXJuIGRlbGVnYXRlKGRvY3VtZW50LCBldmVudE5hbWUsIGVsZW1lbnQsIGNhbGxiYWNrKTtcblx0fVxuXHRjb25zdCBjdXN0b21Db25maWcgPSBjdXN0b21FdmVudHNbZXZlbnROYW1lXTtcblx0aWYgKGN1c3RvbUNvbmZpZyAmJiBjdXN0b21Db25maWcuZXZlbnQpIHtcblx0XHRldmVudE5hbWUgPSBjdXN0b21Db25maWcub3JpZ2luYWxFdmVudDtcblx0XHRjYWxsYmFjayA9IGN1c3RvbUNvbmZpZy5oYW5kbGVyLmJpbmQoY3VzdG9tQ29uZmlnLCBjYWxsYmFjayk7XG5cdH1cblx0ZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIGNhcHR1cmUpO1xuXHRyZXR1cm4gbmV3IERvbUV2ZW50SGFuZGxlKGVsZW1lbnQsIGV2ZW50TmFtZSwgY2FsbGJhY2ssIGNhcHR1cmUpO1xufVxuXG4vKipcbiAqIElFMTEgZG9lc24ndCBzdXBwb3J0IG9uY2UgZXZlbnQgbGlzdGVuZXIgb3B0aW9uLCB0aGlzIG1ldGhvZFxuICogTGlzdGVucyB0byB0aGUgc3BlY2lmaWVkIGV2ZW50IG9uIHRoZSBnaXZlbiBET00gZWxlbWVudCBvbmNlLiBUaGlzXG4gKiBmdW5jdGlvbiBub3JtYWxpemVzIERPTSBldmVudCBwYXlsb2FkcyBhbmQgZnVuY3Rpb25zIHNvIHRoZXknbGwgd29yayB0aGVcbiAqIHNhbWUgd2F5IG9uIGFsbCBzdXBwb3J0ZWQgYnJvd3NlcnMuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBET00gZWxlbWVudCB0byBsaXN0ZW4gdG8gdGhlIGV2ZW50IG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gbGlzdGVuIHRvLlxuICogQHBhcmFtIHshZnVuY3Rpb24oIU9iamVjdCl9IGNhbGxiYWNrIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudFxuICogICBpcyB0cmlnZ2VyZWQuIEl0IHdpbGwgcmVjZWl2ZSB0aGUgbm9ybWFsaXplZCBldmVudCBvYmplY3QuXG4gKiBAcmV0dXJuIHshRG9tRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbmNlKGVsZW1lbnQsIGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcblx0Y29uc3QgZG9tRXZlbnRIYW5kbGUgPSBvbihlbGVtZW50LCBldmVudE5hbWUsIGZ1bmN0aW9uKCkge1xuXHRcdGRvbUV2ZW50SGFuZGxlLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0cmV0dXJuIGNhbGxiYWNrLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fSk7XG5cdHJldHVybiBkb21FdmVudEhhbmRsZTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBmaXJzdCBwYXJlbnQgZnJvbSB0aGUgZ2l2ZW4gZWxlbWVudCB0aGF0IG1hdGNoZXMgdGhlIHNwZWNpZmllZFxuICogc2VsZWN0b3IsIG9yIG51bGwgaWYgbm9uZSBtYXRjaC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICogQHJldHVybiB7RWxlbWVudH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcmVudChlbGVtZW50LCBzZWxlY3Rvcikge1xuXHRyZXR1cm4gY2xvc2VzdChlbGVtZW50LnBhcmVudE5vZGUsIHNlbGVjdG9yKTtcbn1cblxuLyoqXG4gKiBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBFbGVtZW50LnByZXBlbmQgZnVuY3Rpb24sIHRoaXMgbWV0aG9kXG4gKiBpbnNlcnRzIGEgbm9kZSBiZWZvcmUgZmlyc3QgY2hpbGQgb2YgdGhlIHBhcmVudC4gSWYgY2hpbGQgaXMgYSBIVE1MIHN0cmluZ1xuICogaXQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gZG9jdW1lbnQgZnJhZ21lbnQgYmVmb3JlIHByZXBlbmRpbmcgaXQgdG8gdGhlIHBhcmVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IHBhcmVudCBUaGUgbm9kZSB0byBwcmVwZW5kIHRvLlxuICogQHBhcmFtIHshKEVsZW1lbnR8Tm9kZUxpc3R8c3RyaW5nKX0gY2hpbGQgVGhlIHRoaW5nIHRvIHByZXBlbmQgdG8gdGhlIHBhcmVudC5cbiAqIEByZXR1cm4geyFFbGVtZW50fSBUaGUgcHJlcGVuZGVkIGNoaWxkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlcGVuZChwYXJlbnQsIGNoaWxkKSB7XG5cdGlmIChpc1N0cmluZyhjaGlsZCkpIHtcblx0XHRjaGlsZCA9IGJ1aWxkRnJhZ21lbnQoY2hpbGQpO1xuXHR9XG5cblx0aWYgKCFpc05vZGVMaXN0TGlrZShjaGlsZCkgJiYgIWlzRGVmQW5kTm90TnVsbChwYXJlbnQuZmlyc3RDaGlsZCkpIHtcblx0XHRyZXR1cm4gYXBwZW5kKHBhcmVudCwgY2hpbGQpO1xuXHR9XG5cblx0aWYgKGlzTm9kZUxpc3RMaWtlKGNoaWxkKSkge1xuXHRcdGNvbnN0IGNoaWxkQXJyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoY2hpbGQpO1xuXHRcdGZvciAobGV0IGkgPSBjaGlsZEFyci5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuXHRcdFx0cGFyZW50Lmluc2VydEJlZm9yZShjaGlsZEFycltpXSwgcGFyZW50LmZpcnN0Q2hpbGQpO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRwYXJlbnQuaW5zZXJ0QmVmb3JlKGNoaWxkLCBwYXJlbnQuZmlyc3RDaGlsZCk7XG5cdH1cblxuXHRyZXR1cm4gY2hpbGQ7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgY3VzdG9tIGV2ZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgY3VzdG9tIGV2ZW50LlxuICogQHBhcmFtIHshT2JqZWN0fSBjdXN0b21Db25maWcgQW4gb2JqZWN0IHdpdGggaW5mb3JtYXRpb24gYWJvdXQgaG93IHRoZSBldmVudFxuICogICBzaG91bGQgYmUgaGFuZGxlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCBjdXN0b21Db25maWcpIHtcblx0Y3VzdG9tRXZlbnRzW2V2ZW50TmFtZV0gPSBjdXN0b21Db25maWc7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBhbGwgdGhlIGNoaWxkIG5vZGVzIG9uIGEgRE9NIG5vZGUuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGUgRWxlbWVudCB0byByZW1vdmUgY2hpbGRyZW4gZnJvbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUNoaWxkcmVuKG5vZGUpIHtcblx0bGV0IGNoaWxkO1xuXHR3aGlsZSAoKGNoaWxkID0gbm9kZS5maXJzdENoaWxkKSkge1xuXHRcdG5vZGUucmVtb3ZlQ2hpbGQoY2hpbGQpO1xuXHR9XG59XG5cbi8qKlxuICogUmVtb3ZlcyB0aGUgcmVxdWVzdGVkIENTUyBjbGFzc2VzIGZyb20gYW4gZWxlbWVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR8IU5vZGVMaXN0fSBlbGVtZW50cyBUaGUgZWxlbWVudCBvciBlbGVtZW50cyB0byByZW1vdmUgQ1NTIGNsYXNzZXMgZnJvbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIHJlbW92ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUNsYXNzZXMoZWxlbWVudHMsIGNsYXNzZXMpIHtcblx0aWYgKCFpc09iamVjdChlbGVtZW50cykgfHwgIWlzU3RyaW5nKGNsYXNzZXMpKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0aWYgKCFlbGVtZW50cy5sZW5ndGgpIHtcblx0XHRlbGVtZW50cyA9IFtlbGVtZW50c107XG5cdH1cblxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKCdjbGFzc0xpc3QnIGluIGVsZW1lbnRzW2ldKSB7XG5cdFx0XHRyZW1vdmVDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZW1vdmVDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIFJlbW92ZXMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQgdXNpbmcgY2xhc3NMaXN0LlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB0byByZW1vdmUgQ1NTIGNsYXNzZXMgZnJvbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIHJlbW92ZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZUNsYXNzZXNXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGNsYXNzZXMuc3BsaXQoJyAnKS5mb3JFYWNoKGZ1bmN0aW9uKGNsYXNzTmFtZSkge1xuXHRcdGlmIChjbGFzc05hbWUpIHtcblx0XHRcdGVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuXHRcdH1cblx0fSk7XG59XG5cbi8qKlxuICogSUUxMSBkb2Vzbid0IHN1cHBvcnQgRWxlbWVudC5jbGFzc0xpc3QsIHRoaXMgbWV0aG9kXG4gKiByZW1vdmVzIHRoZSByZXF1ZXN0ZWQgQ1NTIGNsYXNzZXMgZnJvbSBhbiBlbGVtZW50IHdpdGhvdXQgdXNpbmcgY2xhc3NMaXN0LlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB0byByZW1vdmUgQ1NTIGNsYXNzZXMgZnJvbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIHJlbW92ZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZUNsYXNzZXNXaXRob3V0TmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGxldCBlbGVtZW50Q2xhc3NOYW1lID0gYCAke2VsZW1lbnQuY2xhc3NOYW1lfSBgO1xuXG5cdGNsYXNzZXMgPSBjbGFzc2VzLnNwbGl0KCcgJyk7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjbGFzc2VzLmxlbmd0aDsgaSsrKSB7XG5cdFx0ZWxlbWVudENsYXNzTmFtZSA9IGVsZW1lbnRDbGFzc05hbWUucmVwbGFjZShgICR7Y2xhc3Nlc1tpXX0gYCwgJyAnKTtcblx0fVxuXG5cdGVsZW1lbnQuY2xhc3NOYW1lID0gZWxlbWVudENsYXNzTmFtZS50cmltKCk7XG59XG5cbi8qKlxuICogUmVwbGFjZXMgdGhlIGZpcnN0IGVsZW1lbnQgd2l0aCB0aGUgc2Vjb25kLlxuICogQGRlcHJlY2F0ZWQgVXNlIGVsZW1lbnQxLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKGVsZW1lbnQyLCBlbGVtZW50MSlcbiAqIGRpcmVjdGx5IGluc3RlYWQgb2YgdGhpcyBtZXRob2RcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudDFcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudDJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2UoZWxlbWVudDEsIGVsZW1lbnQyKSB7XG5cdGlmIChlbGVtZW50MSAmJiBlbGVtZW50MiAmJiBlbGVtZW50MSAhPT0gZWxlbWVudDIgJiYgZWxlbWVudDEucGFyZW50Tm9kZSkge1xuXHRcdGVsZW1lbnQxLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKGVsZW1lbnQyLCBlbGVtZW50MSk7XG5cdH1cbn1cblxuLyoqXG4gKiBUaGUgZnVuY3Rpb24gdGhhdCByZXBsYWNlcyBgc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uX2AgZm9yIGV2ZW50cy5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbl8oKSB7XG5cdGNvbnN0IGV2ZW50ID0gdGhpczsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRldmVudC5zdG9wcGVkID0gdHJ1ZTtcblx0ZXZlbnQuc3RvcHBlZEltbWVkaWF0ZSA9IHRydWU7XG5cdEV2ZW50LnByb3RvdHlwZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24uY2FsbChldmVudCk7XG59XG5cbi8qKlxuICogVGhlIGZ1bmN0aW9uIHRoYXQgcmVwbGFjZXMgYHN0b3BQcm9wYWdhdGlvbmAgZm9yIGV2ZW50cy5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHN0b3BQcm9wYWdhdGlvbl8oKSB7XG5cdGNvbnN0IGV2ZW50ID0gdGhpczsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRldmVudC5zdG9wcGVkID0gdHJ1ZTtcblx0RXZlbnQucHJvdG90eXBlLnN0b3BQcm9wYWdhdGlvbi5jYWxsKGV2ZW50KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGdpdmVuIGVsZW1lbnQgc3VwcG9ydHMgdGhlIGdpdmVuIGV2ZW50IHR5cGUuXG4gKiBAcGFyYW0geyFFbGVtZW50fHN0cmluZ30gZWxlbWVudCBUaGUgRE9NIGVsZW1lbnQgb3IgZWxlbWVudCB0YWcgbmFtZSB0byBjaGVjay5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGNoZWNrLlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1cHBvcnRzRXZlbnQoZWxlbWVudCwgZXZlbnROYW1lKSB7XG5cdGlmIChjdXN0b21FdmVudHNbZXZlbnROYW1lXSkge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0aWYgKGlzU3RyaW5nKGVsZW1lbnQpKSB7XG5cdFx0aWYgKCFlbGVtZW50c0J5VGFnX1tlbGVtZW50XSkge1xuXHRcdFx0ZWxlbWVudHNCeVRhZ19bZWxlbWVudF0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGVsZW1lbnQpO1xuXHRcdH1cblx0XHRlbGVtZW50ID0gZWxlbWVudHNCeVRhZ19bZWxlbWVudF07XG5cdH1cblxuXHRjb25zdCB0YWcgPSBlbGVtZW50LnRhZ05hbWU7XG5cdGlmICghc3VwcG9ydENhY2hlX1t0YWddIHx8ICFzdXBwb3J0Q2FjaGVfW3RhZ10uaGFzT3duUHJvcGVydHkoZXZlbnROYW1lKSkge1xuXHRcdHN1cHBvcnRDYWNoZV9bdGFnXSA9IHN1cHBvcnRDYWNoZV9bdGFnXSB8fCB7fTtcblx0XHRzdXBwb3J0Q2FjaGVfW3RhZ11bZXZlbnROYW1lXSA9ICdvbicgKyBldmVudE5hbWUgaW4gZWxlbWVudDtcblx0fVxuXHRyZXR1cm4gc3VwcG9ydENhY2hlX1t0YWddW2V2ZW50TmFtZV07XG59XG5cbi8qKlxuICogVGhpcyB0cmlnZ2VycyBhbGwgZGVmYXVsdCBtYXRjaGVkIGRlbGVnYXRlZCBsaXN0ZW5lcnMgb2YgYSBnaXZlbiBldmVudCB0eXBlLlxuICogQHBhcmFtIHshQXJyYXl9IGRlZkZucyBBcnJheSB0byBjb2xsZWN0IGRlZmF1bHQgbGlzdGVuZXJzIGluLCBpbnN0ZWFkXG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnRcbiAqIEByZXR1cm4ge2Jvb2xlYW59IEZhbHNlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdHJpZ2dlcmVkIGNhbGxiYWNrcyByZXR1cm5zXG4gKiAgICAgZmFsc2UsIG9yIHRydWUgb3RoZXJ3aXNlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gdHJpZ2dlckRlZmF1bHREZWxlZ2F0ZWRMaXN0ZW5lcnNfKGRlZkZucywgZXZlbnQpIHtcblx0bGV0IHJldCA9IHRydWU7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBkZWZGbnMubGVuZ3RoICYmICFldmVudC5kZWZhdWx0UHJldmVudGVkOyBpKyspIHtcblx0XHRldmVudC5kZWxlZ2F0ZVRhcmdldCA9IGRlZkZuc1tpXS5lbGVtZW50O1xuXHRcdHJldCAmPSBkZWZGbnNbaV0uZm4oZXZlbnQpO1xuXHR9XG5cblx0cmV0dXJuIHJldDtcbn1cblxuLyoqXG4gKiBUaGlzIHRyaWdnZXJzIGFsbCBtYXRjaGVkIGRlbGVnYXRlZCBsaXN0ZW5lcnMgb2YgYSBnaXZlbiBldmVudCB0eXBlIHdoZW4gaXRzXG4gKiBkZWxlZ2F0ZWQgdGFyZ2V0IGlzIGFibGUgdG8gaW50ZXJhY3QuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBjb250YWluZXJcbiAqIEBwYXJhbSB7IUV2ZW50fSBldmVudFxuICogQHBhcmFtIHshQXJyYXl9IGRlZmF1bHRGbnMgQXJyYXkgdG8gY29sbGVjdCBkZWZhdWx0IGxpc3RlbmVycyBpbiwgaW5zdGVhZFxuICogICAgIG9mIHJ1bm5pbmcgdGhlbS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IEZhbHNlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdHJpZ2dlcmVkIGNhbGxiYWNrcyByZXR1cm5zXG4gKiAgICAgZmFsc2UsIG9yIHRydWUgb3RoZXJ3aXNlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gdHJpZ2dlckRlbGVnYXRlZExpc3RlbmVyc18oY29udGFpbmVyLCBldmVudCwgZGVmYXVsdEZucykge1xuXHRsZXQgcmV0ID0gdHJ1ZTtcblx0bGV0IGN1cnJFbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuXHRjb25zdCBsaW1pdCA9IGNvbnRhaW5lci5wYXJlbnROb2RlO1xuXG5cdHdoaWxlIChjdXJyRWxlbWVudCAmJiBjdXJyRWxlbWVudCAhPT0gbGltaXQgJiYgIWV2ZW50LnN0b3BwZWQpIHtcblx0XHRpZiAoaXNBYmxlVG9JbnRlcmFjdFdpdGhfKGN1cnJFbGVtZW50LCBldmVudC50eXBlLCBldmVudCkpIHtcblx0XHRcdGV2ZW50LmRlbGVnYXRlVGFyZ2V0ID0gY3VyckVsZW1lbnQ7XG5cdFx0XHRyZXQgJj0gdHJpZ2dlckVsZW1lbnRMaXN0ZW5lcnNfKGN1cnJFbGVtZW50LCBldmVudCwgZGVmYXVsdEZucyk7XG5cdFx0XHRyZXQgJj0gdHJpZ2dlclNlbGVjdG9yTGlzdGVuZXJzXyhcblx0XHRcdFx0Y29udGFpbmVyLFxuXHRcdFx0XHRjdXJyRWxlbWVudCxcblx0XHRcdFx0ZXZlbnQsXG5cdFx0XHRcdGRlZmF1bHRGbnNcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGN1cnJFbGVtZW50ID0gY3VyckVsZW1lbnQucGFyZW50Tm9kZTtcblx0fVxuXG5cdHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIGFyZ3VtZW50IHRvIGEgRE9NIGVsZW1lbnQuIFN0cmluZ3MgYXJlIGFzc3VtZWQgdG9cbiAqIGJlIHNlbGVjdG9ycywgYW5kIHNvIGEgbWF0Y2hlZCBlbGVtZW50IHdpbGwgYmUgcmV0dXJuZWQuIElmIHRoZSBhcmdcbiAqIGlzIGFscmVhZHkgYSBET00gZWxlbWVudCBpdCB3aWxsIGJlIHRoZSByZXR1cm4gdmFsdWUuXG4gKiBAcGFyYW0ge3N0cmluZ3xFbGVtZW50fERvY3VtZW50fSBzZWxlY3Rvck9yRWxlbWVudFxuICogQHJldHVybiB7RWxlbWVudH0gVGhlIGNvbnZlcnRlZCBlbGVtZW50LCBvciBudWxsIGlmIG5vbmUgd2FzIGZvdW5kLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9FbGVtZW50KHNlbGVjdG9yT3JFbGVtZW50KSB7XG5cdGlmIChcblx0XHRpc0VsZW1lbnQoc2VsZWN0b3JPckVsZW1lbnQpIHx8XG5cdFx0aXNEb2N1bWVudChzZWxlY3Rvck9yRWxlbWVudCkgfHxcblx0XHRpc0RvY3VtZW50RnJhZ21lbnQoc2VsZWN0b3JPckVsZW1lbnQpXG5cdCkge1xuXHRcdHJldHVybiBzZWxlY3Rvck9yRWxlbWVudDtcblx0fSBlbHNlIGlmIChpc1N0cmluZyhzZWxlY3Rvck9yRWxlbWVudCkpIHtcblx0XHRyZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvck9yRWxlbWVudCk7XG5cdH0gZWxzZSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cbn1cblxuLyoqXG4gKiBBZGRzIG9yIHJlbW92ZXMgb25lIG9yIG1vcmUgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQuIElmIGFueSBvZiB0aGUgY2xhc3Nlc1xuICogaXMgcHJlc2VudCwgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQsIG9yIGFkZGVkIG90aGVyd2lzZS5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgd2hpY2ggY2xhc3NlcyB3aWxsIGJlIHRvZ2dsZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NlcyBUaGUgY2xhc3NlcyB3aGljaCBoYXZlIHRvIGFkZGVkIG9yIHJlbW92ZWQgZnJvbSB0aGUgZWxlbWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvZ2dsZUNsYXNzZXMoZWxlbWVudCwgY2xhc3Nlcykge1xuXHRpZiAoIWlzT2JqZWN0KGVsZW1lbnQpIHx8ICFpc1N0cmluZyhjbGFzc2VzKSkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdGlmICgnY2xhc3NMaXN0JyBpbiBlbGVtZW50KSB7XG5cdFx0dG9nZ2xlQ2xhc3Nlc1dpdGhOYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpO1xuXHR9IGVsc2Uge1xuXHRcdHRvZ2dsZUNsYXNzZXNXaXRob3V0TmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKTtcblx0fVxufVxuXG4vKipcbiAqIEFkZHMgb3IgcmVtb3ZlcyBvbmUgb3IgbW9yZSBjbGFzc2VzIGZyb20gYW4gZWxlbWVudCB1c2luZyBjbGFzc0xpc3QuXG4gKiBJZiBhbnkgb2YgdGhlIGNsYXNzZXMgaXMgcHJlc2VudCwgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQsXG4gKiBvciBhZGRlZCBvdGhlcndpc2UuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHdoaWNoIGNsYXNzZXMgd2lsbCBiZSB0b2dnbGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgVGhlIGNsYXNzZXMgd2hpY2ggaGF2ZSB0byBhZGRlZCBvciByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0b2dnbGVDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudCwgY2xhc3Nlcykge1xuXHRjbGFzc2VzLnNwbGl0KCcgJykuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcblx0XHRlbGVtZW50LmNsYXNzTGlzdC50b2dnbGUoY2xhc3NOYW1lKTtcblx0fSk7XG59XG5cbi8qKlxuICogSUUxMSBkb2Vzbid0IHN1cHBvcnQgRWxlbWVudC5jbGFzc0xpc3QsIHRoaXMgbWV0aG9kXG4gKiBhZGRzIG9yIHJlbW92ZXMgb25lIG9yIG1vcmUgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQgd2l0aG91dCB1c2luZyBjbGFzc0xpc3QuXG4gKiBJZiBhbnkgb2YgdGhlIGNsYXNzZXMgaXMgcHJlc2VudCwgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQsXG4gKiBvciBhZGRlZCBvdGhlcndpc2UuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHdoaWNoIGNsYXNzZXMgd2lsbCBiZSB0b2dnbGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgVGhlIGNsYXNzZXMgd2hpY2ggaGF2ZSB0byBhZGRlZCBvciByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0b2dnbGVDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudCwgY2xhc3Nlcykge1xuXHRsZXQgZWxlbWVudENsYXNzTmFtZSA9IGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYDtcblxuXHRjbGFzc2VzID0gY2xhc3Nlcy5zcGxpdCgnICcpO1xuXG5cdGZvciAobGV0IGkgPSAwOyBpIDwgY2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuXHRcdGNvbnN0IGNsYXNzTmFtZSA9IGAgJHtjbGFzc2VzW2ldfSBgO1xuXHRcdGNvbnN0IGNsYXNzSW5kZXggPSBlbGVtZW50Q2xhc3NOYW1lLmluZGV4T2YoY2xhc3NOYW1lKTtcblxuXHRcdGlmIChjbGFzc0luZGV4ID09PSAtMSkge1xuXHRcdFx0ZWxlbWVudENsYXNzTmFtZSA9IGAke2VsZW1lbnRDbGFzc05hbWV9JHtjbGFzc2VzW2ldfSBgO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zdCBiZWZvcmUgPSBlbGVtZW50Q2xhc3NOYW1lLnN1YnN0cmluZygwLCBjbGFzc0luZGV4KTtcblx0XHRcdGNvbnN0IGFmdGVyID0gZWxlbWVudENsYXNzTmFtZS5zdWJzdHJpbmcoXG5cdFx0XHRcdGNsYXNzSW5kZXggKyBjbGFzc05hbWUubGVuZ3RoXG5cdFx0XHQpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdFx0XHRlbGVtZW50Q2xhc3NOYW1lID0gYCR7YmVmb3JlfSAke2FmdGVyfWA7XG5cdFx0fVxuXHR9XG5cblx0ZWxlbWVudC5jbGFzc05hbWUgPSBlbGVtZW50Q2xhc3NOYW1lLnRyaW0oKTtcbn1cblxuLyoqXG4gKiBUcmlnZ2VycyBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZ2l2ZW4gZXZlbnQgdHlwZSB0aGF0IGFyZSBzdG9yZWQgaW4gdGhlXG4gKiBzcGVjaWZpZWQgZWxlbWVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7IUV2ZW50fSBldmVudFxuICogQHBhcmFtIHshQXJyYXl9IGRlZmF1bHRGbnMgQXJyYXkgdG8gY29sbGVjdCBkZWZhdWx0IGxpc3RlbmVycyBpbiwgaW5zdGVhZFxuICogICAgIG9mIHJ1bm5pbmcgdGhlbS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IEZhbHNlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdHJpZ2dlcmVkIGNhbGxiYWNrcyByZXR1cm5zXG4gKiAgICAgZmFsc2UsIG9yIHRydWUgb3RoZXJ3aXNlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gdHJpZ2dlckVsZW1lbnRMaXN0ZW5lcnNfKGVsZW1lbnQsIGV2ZW50LCBkZWZhdWx0Rm5zKSB7XG5cdGNvbnN0IGxhc3RDb250YWluZXIgPSBldmVudFtMQVNUX0NPTlRBSU5FUl07XG5cdGlmICghaXNEZWYobGFzdENvbnRhaW5lcikgfHwgIWNvbnRhaW5zKGxhc3RDb250YWluZXIsIGVsZW1lbnQpKSB7XG5cdFx0Y29uc3QgbGlzdGVuZXJzID0gZG9tRGF0YS5nZXQoZWxlbWVudCwgJ2xpc3RlbmVycycsIHt9KVtldmVudC50eXBlXTtcblx0XHRyZXR1cm4gdHJpZ2dlckxpc3RlbmVyc18obGlzdGVuZXJzLCBldmVudCwgZWxlbWVudCwgZGVmYXVsdEZucyk7XG5cdH1cblx0cmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogVHJpZ2dlcnMgdGhlIHNwZWNpZmllZCBldmVudCBvbiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAqIE5PVEU6IFRoaXMgc2hvdWxkIG1vc3RseSBiZSB1c2VkIGZvciB0ZXN0aW5nLCBub3Qgb24gcmVhbCBjb2RlLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgbm9kZSB0aGF0IHNob3VsZCB0cmlnZ2VyIHRoZSBldmVudC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGJlIHRyaWdncmVkLlxuICogQHBhcmFtIHtPYmplY3Q9fSBldmVudE9iaiBBbiBvYmplY3Qgd2l0aCBkYXRhIHRoYXQgc2hvdWxkIGJlIG9uIHRoZVxuICogICB0cmlnZ2VyZWQgZXZlbnQncyBwYXlsb2FkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdHJpZ2dlckV2ZW50KGVsZW1lbnQsIGV2ZW50TmFtZSwgZXZlbnRPYmopIHtcblx0aWYgKGlzQWJsZVRvSW50ZXJhY3RXaXRoXyhlbGVtZW50LCBldmVudE5hbWUsIGV2ZW50T2JqKSkge1xuXHRcdGNvbnN0IHBheWxvYWQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnSFRNTEV2ZW50cycpO1xuXHRcdHBheWxvYWQuaW5pdEV2ZW50KGV2ZW50TmFtZSwgdHJ1ZSwgdHJ1ZSk7XG5cdFx0b2JqZWN0Lm1peGluKHBheWxvYWQsIGV2ZW50T2JqKTtcblx0XHRlbGVtZW50LmRpc3BhdGNoRXZlbnQocGF5bG9hZCk7XG5cdH1cbn1cblxuLyoqXG4gKiBUcmlnZ2VycyB0aGUgZ2l2ZW4gbGlzdGVuZXJzIGFycmF5LlxuICogQHBhcmFtIHtBcnJheTwhZnVuY3Rpb24oKT59IGxpc3RlbmVyc1xuICogQHBhcmFtIHshRXZlbnR9IGV2ZW50XG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0geyFBcnJheX0gZGVmYXVsdEZucyBBcnJheSB0byBjb2xsZWN0IGRlZmF1bHQgbGlzdGVuZXJzIGluLCBpbnN0ZWFkXG4gKiAgICAgb2YgcnVubmluZyB0aGVtLlxuICogQHJldHVybiB7Ym9vbGVhbn0gRmFsc2UgaWYgYXQgbGVhc3Qgb25lIG9mIHRoZSB0cmlnZ2VyZWQgY2FsbGJhY2tzIHJldHVybnNcbiAqICAgICBmYWxzZSwgb3IgdHJ1ZSBvdGhlcndpc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0cmlnZ2VyTGlzdGVuZXJzXyhsaXN0ZW5lcnMsIGV2ZW50LCBlbGVtZW50LCBkZWZhdWx0Rm5zKSB7XG5cdGxldCByZXQgPSB0cnVlO1xuXHRsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMgfHwgW107XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aCAmJiAhZXZlbnQuc3RvcHBlZEltbWVkaWF0ZTsgaSsrKSB7XG5cdFx0aWYgKGxpc3RlbmVyc1tpXS5kZWZhdWx0TGlzdGVuZXJfKSB7XG5cdFx0XHRkZWZhdWx0Rm5zLnB1c2goe1xuXHRcdFx0XHRlbGVtZW50LFxuXHRcdFx0XHRmbjogbGlzdGVuZXJzW2ldLFxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldCAmPSBsaXN0ZW5lcnNbaV0oZXZlbnQpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIFRyaWdnZXJzIGFsbCBzZWxlY3RvciBsaXN0ZW5lcnMgZm9yIHRoZSBnaXZlbiBldmVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGNvbnRhaW5lclxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHshRXZlbnR9IGV2ZW50XG4gKiBAcGFyYW0geyFBcnJheX0gZGVmYXVsdEZucyBBcnJheSB0byBjb2xsZWN0IGRlZmF1bHQgbGlzdGVuZXJzIGluLCBpbnN0ZWFkXG4gKiAgICAgb2YgcnVubmluZyB0aGVtLlxuICogQHJldHVybiB7Ym9vbGVhbn0gRmFsc2UgaWYgYXQgbGVhc3Qgb25lIG9mIHRoZSB0cmlnZ2VyZWQgY2FsbGJhY2tzIHJldHVybnNcbiAqICAgICBmYWxzZSwgb3IgdHJ1ZSBvdGhlcndpc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0cmlnZ2VyU2VsZWN0b3JMaXN0ZW5lcnNfKGNvbnRhaW5lciwgZWxlbWVudCwgZXZlbnQsIGRlZmF1bHRGbnMpIHtcblx0bGV0IHJldCA9IHRydWU7XG5cdGNvbnN0IGRhdGEgPSBkb21EYXRhLmdldChjb250YWluZXIsICdkZWxlZ2F0aW5nJywge30pO1xuXHRjb25zdCBtYXAgPSBkYXRhW2V2ZW50LnR5cGVdLnNlbGVjdG9ycztcblx0Y29uc3Qgc2VsZWN0b3JzID0gT2JqZWN0LmtleXMobWFwKTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3RvcnMubGVuZ3RoICYmICFldmVudC5zdG9wcGVkSW1tZWRpYXRlOyBpKyspIHtcblx0XHRpZiAobWF0Y2goZWxlbWVudCwgc2VsZWN0b3JzW2ldKSkge1xuXHRcdFx0Y29uc3QgbGlzdGVuZXJzID0gbWFwW3NlbGVjdG9yc1tpXV07XG5cdFx0XHRyZXQgJj0gdHJpZ2dlckxpc3RlbmVyc18obGlzdGVuZXJzLCBldmVudCwgZWxlbWVudCwgZGVmYXVsdEZucyk7XG5cdFx0fVxuXHR9XG5cdHJldHVybiByZXQ7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbi8vIFRoaXMgZmlsZSBleGlzdHMganVzdCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHksIG1ha2luZyBzdXJlIHRoYXQgb2xkXG4vLyBkZWZhdWx0IGltcG9ydHMgZm9yIHRoaXMgZmlsZSBzdGlsbCB3b3JrLiBJdCdzIGJlc3QgdG8gdXNlIHRoZSBuYW1lZCBleHBvcnRzXG4vLyBmb3IgZWFjaCBmdW5jdGlvbiBpbnN0ZWFkIHRob3VnaCwgc2luY2UgdGhhdCBhbGxvd3MgYnVuZGxlcnMgbGlrZSBSb2xsdXAgdG9cbi8vIHJlZHVjZSB0aGUgYnVuZGxlIHNpemUgYnkgcmVtb3ZpbmcgdW51c2VkIGNvZGUuXG5pbXBvcnQgKiBhcyBkb20gZnJvbSAnLi9kb21OYW1lZCc7XG5cbmV4cG9ydCBkZWZhdWx0IGRvbTtcbmV4cG9ydCB7ZG9tfTtcbmV4cG9ydCAqIGZyb20gJy4vZG9tTmFtZWQnO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2RlbGVnYXRlLCBvbiwgc3VwcG9ydHNFdmVudH0gZnJvbSAnLi9kb20nO1xuaW1wb3J0IHtFdmVudEVtaXR0ZXJQcm94eX0gZnJvbSAnbWV0YWwtZXZlbnRzJztcblxuLyoqXG4gKiBEb21FdmVudEVtaXR0ZXJQcm94eSB1dGlsaXR5LiBJdCBleHRlbmRzIGBFdmVudEVtaXR0ZXJQcm94eWAgdG8gYWxzbyBhY2NlcHRcbiAqIGRvbSBlbGVtZW50cyBhcyBvcmlnaW4gZW1pdHRlcnMuXG4gKiBAZXh0ZW5kcyB7RXZlbnRFbWl0dGVyUHJveHl9XG4gKi9cbmNsYXNzIERvbUV2ZW50RW1pdHRlclByb3h5IGV4dGVuZHMgRXZlbnRFbWl0dGVyUHJveHkge1xuXHQvKipcblx0ICogQWRkcyB0aGUgZ2l2ZW4gbGlzdGVuZXIgZm9yIHRoZSBnaXZlbiBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gVGhlIGxpc3RlbmVkIGV2ZW50J3MgaGFuZGxlLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0YWRkTGlzdGVuZXJfKGV2ZW50LCBsaXN0ZW5lcikge1xuXHRcdGlmICh0aGlzLm9yaWdpbkVtaXR0ZXJfLmFkZEV2ZW50TGlzdGVuZXIpIHtcblx0XHRcdGlmICh0aGlzLmlzRGVsZWdhdGVFdmVudF8oZXZlbnQpKSB7XG5cdFx0XHRcdGNvbnN0IGluZGV4ID0gZXZlbnQuaW5kZXhPZignOicsIDkpO1xuXHRcdFx0XHRjb25zdCBldmVudE5hbWUgPSBldmVudC5zdWJzdHJpbmcoOSwgaW5kZXgpO1xuXHRcdFx0XHRjb25zdCBzZWxlY3RvciA9IGV2ZW50LnN1YnN0cmluZyhpbmRleCArIDEpO1xuXHRcdFx0XHRyZXR1cm4gZGVsZWdhdGUoXG5cdFx0XHRcdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyxcblx0XHRcdFx0XHRldmVudE5hbWUsXG5cdFx0XHRcdFx0c2VsZWN0b3IsXG5cdFx0XHRcdFx0bGlzdGVuZXJcblx0XHRcdFx0KTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIG9uKHRoaXMub3JpZ2luRW1pdHRlcl8sIGV2ZW50LCBsaXN0ZW5lcik7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBzdXBlci5hZGRMaXN0ZW5lcl8oZXZlbnQsIGxpc3RlbmVyKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBldmVudCBpcyBvZiB0aGUgZGVsZWdhdGUgdHlwZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGlzRGVsZWdhdGVFdmVudF8oZXZlbnQpIHtcblx0XHRyZXR1cm4gZXZlbnQuc3Vic3RyKDAsIDkpID09PSAnZGVsZWdhdGU6Jztcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGV2ZW50IGlzIHN1cHBvcnRlZCBieSB0aGUgb3JpZ2luIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRpc1N1cHBvcnRlZERvbUV2ZW50XyhldmVudCkge1xuXHRcdGlmICghdGhpcy5vcmlnaW5FbWl0dGVyXyB8fCAhdGhpcy5vcmlnaW5FbWl0dGVyXy5hZGRFdmVudExpc3RlbmVyKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIChcblx0XHRcdCh0aGlzLmlzRGVsZWdhdGVFdmVudF8oZXZlbnQpICYmIGV2ZW50LmluZGV4T2YoJzonLCA5KSAhPT0gLTEpIHx8XG5cdFx0XHRzdXBwb3J0c0V2ZW50KHRoaXMub3JpZ2luRW1pdHRlcl8sIGV2ZW50KVxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBldmVudCBzaG91bGQgYmUgcHJveGllZC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRzaG91bGRQcm94eUV2ZW50XyhldmVudCkge1xuXHRcdHJldHVybiAoXG5cdFx0XHRzdXBlci5zaG91bGRQcm94eUV2ZW50XyhldmVudCkgJiYgdGhpcy5pc1N1cHBvcnRlZERvbUV2ZW50XyhldmVudClcblx0XHQpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRG9tRXZlbnRFbWl0dGVyUHJveHk7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXBwZW5kfSBmcm9tICcuL2RvbSc7XG5pbXBvcnQge3N0cmluZ30gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIENsYXNzIHdpdGggc3RhdGljIG1ldGhvZHMgcmVzcG9uc2libGUgZm9yIGRvaW5nIGJyb3dzZXIgZmVhdHVyZSBjaGVja3MuXG4gKi9cbmNsYXNzIGZlYXR1cmVzIHtcblx0LyoqXG5cdCAqIFNvbWUgYnJvd3NlcnMgc3RpbGwgc3VwcG9ydHMgcHJlZml4ZWQgYW5pbWF0aW9uIGV2ZW50cy4gVGhpcyBtZXRob2QgY2FuXG5cdCAqIGJlIHVzZWQgdG8gcmV0cmlldmUgdGhlIGN1cnJlbnQgYnJvd3NlciBldmVudCBuYW1lIGZvciBib3RoLCBhbmltYXRpb25cblx0ICogYW5kIHRyYW5zaXRpb24uXG5cdCAqIEByZXR1cm4ge29iamVjdH1cblx0ICovXG5cdHN0YXRpYyBjaGVja0FuaW1hdGlvbkV2ZW50TmFtZSgpIHtcblx0XHRpZiAoZmVhdHVyZXMuYW5pbWF0aW9uRXZlbnROYW1lXyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRmZWF0dXJlcy5hbmltYXRpb25FdmVudE5hbWVfID0ge1xuXHRcdFx0XHRhbmltYXRpb246IGZlYXR1cmVzLmNoZWNrQW5pbWF0aW9uRXZlbnROYW1lXygnYW5pbWF0aW9uJyksXG5cdFx0XHRcdHRyYW5zaXRpb246IGZlYXR1cmVzLmNoZWNrQW5pbWF0aW9uRXZlbnROYW1lXygndHJhbnNpdGlvbicpLFxuXHRcdFx0fTtcblx0XHR9XG5cdFx0cmV0dXJuIGZlYXR1cmVzLmFuaW1hdGlvbkV2ZW50TmFtZV87XG5cdH1cblxuXHQvKipcblx0ICogQHByb3RlY3RlZFxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBUeXBlIHRvIHRlc3Q6IGFuaW1hdGlvbiwgdHJhbnNpdGlvbi5cblx0ICogQHJldHVybiB7c3RyaW5nfSBCcm93c2VyIGV2ZW50IG5hbWUuXG5cdCAqL1xuXHRzdGF0aWMgY2hlY2tBbmltYXRpb25FdmVudE5hbWVfKHR5cGUpIHtcblx0XHRjb25zdCBwcmVmaXhlcyA9IFsnV2Via2l0JywgJ01TJywgJ08nLCAnJ107XG5cdFx0Y29uc3QgdHlwZVRpdGxlQ2FzZSA9IHN0cmluZy5yZXBsYWNlSW50ZXJ2YWwoXG5cdFx0XHR0eXBlLFxuXHRcdFx0MCxcblx0XHRcdDEsXG5cdFx0XHR0eXBlLnN1YnN0cmluZygwLCAxKS50b1VwcGVyQ2FzZSgpXG5cdFx0KTtcblx0XHRjb25zdCBzdWZmaXhlcyA9IFtcblx0XHRcdGAke3R5cGVUaXRsZUNhc2V9RW5kYCxcblx0XHRcdGAke3R5cGVUaXRsZUNhc2V9RW5kYCxcblx0XHRcdGAke3R5cGVUaXRsZUNhc2V9RW5kYCxcblx0XHRcdGAke3R5cGV9ZW5kYCxcblx0XHRdO1xuXHRcdGlmICghZmVhdHVyZXMuYW5pbWF0aW9uRWxlbWVudF8pIHtcblx0XHRcdGZlYXR1cmVzLmFuaW1hdGlvbkVsZW1lbnRfID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cdFx0fVxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgcHJlZml4ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChcblx0XHRcdFx0ZmVhdHVyZXMuYW5pbWF0aW9uRWxlbWVudF8uc3R5bGVbXG5cdFx0XHRcdFx0cHJlZml4ZXNbaV0gKyB0eXBlVGl0bGVDYXNlXG5cdFx0XHRcdF0gIT09IHVuZGVmaW5lZCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdFx0XHQpIHtcblx0XHRcdFx0cmV0dXJuIHByZWZpeGVzW2ldLnRvTG93ZXJDYXNlKCkgKyBzdWZmaXhlc1tpXTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGAke3R5cGV9ZW5kYDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTb21lIGJyb3dzZXJzIChsaWtlIElFMTEsIEVkZ2UpIGNoYW5nZSB0aGUgb3JkZXIgb2YgZWxlbWVudCBhdHRyaWJ1dGVzLCB3aGVuIGh0bWxcblx0ICogaXMgcmVuZGVyZWQuIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGNoZWNrIGlmIHRoaXMgYmVoYXZpb3IgaGFwcGVucyBvblxuXHQgKiB0aGUgY3VycmVudCBicm93c2VyLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0c3RhdGljIGNoZWNrQXR0ck9yZGVyQ2hhbmdlKCkge1xuXHRcdGlmIChmZWF0dXJlcy5hdHRyT3JkZXJDaGFuZ2VfID09PSB1bmRlZmluZWQpIHtcblx0XHRcdGNvbnN0IG9yaWdpbmFsQ29udGVudCA9ICc8ZGl2IGRhdGEtY29tcG9uZW50PVwiXCIgZGF0YS1yZWY9XCJcIj48L2Rpdj4nO1xuXHRcdFx0Y29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXHRcdFx0YXBwZW5kKGVsZW1lbnQsIG9yaWdpbmFsQ29udGVudCk7XG5cdFx0XHRmZWF0dXJlcy5hdHRyT3JkZXJDaGFuZ2VfID0gb3JpZ2luYWxDb250ZW50ICE9PSBlbGVtZW50LmlubmVySFRNTDtcblx0XHR9XG5cdFx0cmV0dXJuIGZlYXR1cmVzLmF0dHJPcmRlckNoYW5nZV87XG5cdH1cbn1cblxuZmVhdHVyZXMuYW5pbWF0aW9uRWxlbWVudF8gPSB1bmRlZmluZWQ7XG5mZWF0dXJlcy5hbmltYXRpb25FdmVudE5hbWVfID0gdW5kZWZpbmVkO1xuZmVhdHVyZXMuYXR0ck9yZGVyQ2hhbmdlXyA9IHVuZGVmaW5lZDtcblxuZXhwb3J0IGRlZmF1bHQgZmVhdHVyZXM7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXN5bmN9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7ZXhpdERvY3VtZW50LCBvbmNlfSBmcm9tICcuL2RvbSc7XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbnMgZm9yIHJ1bm5pbmcgamF2YXNjcmlwdCBjb2RlIGluIHRoZSBnbG9iYWwgc2NvcGUuXG4gKi9cbmNsYXNzIGdsb2JhbEV2YWwge1xuXHQvKipcblx0ICogRXZhbHVhdGVzIHRoZSBnaXZlbiBzdHJpbmcgaW4gdGhlIGdsb2JhbCBzY29wZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHRleHRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc2NyaXB0XG5cdCAqL1xuXHRzdGF0aWMgcnVuKHRleHQsIGFwcGVuZEZuKSB7XG5cdFx0Y29uc3Qgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG5cdFx0c2NyaXB0LnRleHQgPSB0ZXh0O1xuXHRcdGlmIChhcHBlbmRGbikge1xuXHRcdFx0YXBwZW5kRm4oc2NyaXB0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuXHRcdH1cblx0XHRleGl0RG9jdW1lbnQoc2NyaXB0KTtcblx0XHRyZXR1cm4gc2NyaXB0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0aGUgZ2l2ZW4gamF2YXNjcmlwdCBmaWxlIGluIHRoZSBnbG9iYWwgc2NvcGUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzcmMgVGhlIGZpbGUncyBwYXRoLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBkZWZhdWx0Rm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXG5cdCAqICAgd2hlbiB0aGUgc2NyaXB0IGhhcyBiZWVuIHJ1bi5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc2NyaXB0XG5cdCAqL1xuXHRzdGF0aWMgcnVuRmlsZShzcmMsIGRlZmF1bHRGbiwgYXBwZW5kRm4pIHtcblx0XHRjb25zdCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcblx0XHRzY3JpcHQuc3JjID0gc3JjO1xuXG5cdFx0Y29uc3QgY2FsbGJhY2sgPSBmdW5jdGlvbigpIHtcblx0XHRcdGV4aXREb2N1bWVudChzY3JpcHQpO1xuXHRcdFx0ZGVmYXVsdEZuICYmIGRlZmF1bHRGbigpO1xuXHRcdH07XG5cdFx0b25jZShzY3JpcHQsICdsb2FkJywgY2FsbGJhY2spO1xuXHRcdG9uY2Uoc2NyaXB0LCAnZXJyb3InLCBjYWxsYmFjayk7XG5cblx0XHRpZiAoYXBwZW5kRm4pIHtcblx0XHRcdGFwcGVuZEZuKHNjcmlwdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gc2NyaXB0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0aGUgY29kZSByZWZlcmVuY2VkIGJ5IHRoZSBnaXZlbiBzY3JpcHQgZWxlbWVudC5cblx0ICogQHBhcmFtIHshRWxlbWVudH0gc2NyaXB0XG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IGRlZmF1bHRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICogICB3aGVuIHRoZSBzY3JpcHQgaGFzIGJlZW4gcnVuLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBhcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKiBAcmV0dXJuIHtFbGVtZW50fSBzY3JpcHRcblx0ICovXG5cdHN0YXRpYyBydW5TY3JpcHQoc2NyaXB0LCBkZWZhdWx0Rm4sIGFwcGVuZEZuKSB7XG5cdFx0Y29uc3QgY2FsbGJhY2sgPSBmdW5jdGlvbigpIHtcblx0XHRcdGRlZmF1bHRGbiAmJiBkZWZhdWx0Rm4oKTtcblx0XHR9O1xuXHRcdGlmIChzY3JpcHQudHlwZSAmJiBzY3JpcHQudHlwZSAhPT0gJ3RleHQvamF2YXNjcmlwdCcpIHtcblx0XHRcdGFzeW5jLm5leHRUaWNrKGNhbGxiYWNrKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0ZXhpdERvY3VtZW50KHNjcmlwdCk7XG5cdFx0aWYgKHNjcmlwdC5zcmMpIHtcblx0XHRcdHJldHVybiBnbG9iYWxFdmFsLnJ1bkZpbGUoc2NyaXB0LnNyYywgZGVmYXVsdEZuLCBhcHBlbmRGbik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFzeW5jLm5leHRUaWNrKGNhbGxiYWNrKTtcblx0XHRcdHJldHVybiBnbG9iYWxFdmFsLnJ1bihzY3JpcHQudGV4dCwgYXBwZW5kRm4pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgYW55IHNjcmlwdCB0YWdzIHByZXNlbnQgaW4gdGhlIGdpdmVuIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gZGVmYXVsdEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHNjcmlwdCBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IGFwcGVuZEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGFwcGVuZCB0aGUgbm9kZVxuXHQgKiAgIGludG8gZG9jdW1lbnQuXG5cdCAqL1xuXHRzdGF0aWMgcnVuU2NyaXB0c0luRWxlbWVudChlbGVtZW50LCBkZWZhdWx0Rm4sIGFwcGVuZEZuKSB7XG5cdFx0Y29uc3Qgc2NyaXB0cyA9IGVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnc2NyaXB0Jyk7XG5cdFx0aWYgKHNjcmlwdHMubGVuZ3RoKSB7XG5cdFx0XHRnbG9iYWxFdmFsLnJ1blNjcmlwdHNJbk9yZGVyKHNjcmlwdHMsIDAsIGRlZmF1bHRGbiwgYXBwZW5kRm4pO1xuXHRcdH0gZWxzZSBpZiAoZGVmYXVsdEZuKSB7XG5cdFx0XHRhc3luYy5uZXh0VGljayhkZWZhdWx0Rm4pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBnaXZlbiBzY3JpcHRzIGVsZW1lbnRzIGluIHRoZSBvcmRlciB0aGF0IHRoZXkgYXBwZWFyLlxuXHQgKiBAcGFyYW0geyFOb2RlTGlzdH0gc2NyaXB0c1xuXHQgKiBAcGFyYW0ge251bWJlcn0gaW5kZXhcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gZGVmYXVsdEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHNjcmlwdCBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IGFwcGVuZEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGFwcGVuZCB0aGUgbm9kZVxuXHQgKiAgIGludG8gZG9jdW1lbnQuXG5cdCAqL1xuXHRzdGF0aWMgcnVuU2NyaXB0c0luT3JkZXIoc2NyaXB0cywgaW5kZXgsIGRlZmF1bHRGbiwgYXBwZW5kRm4pIHtcblx0XHRnbG9iYWxFdmFsLnJ1blNjcmlwdChcblx0XHRcdHNjcmlwdHMuaXRlbShpbmRleCksXG5cdFx0XHRmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKGluZGV4IDwgc2NyaXB0cy5sZW5ndGggLSAxKSB7XG5cdFx0XHRcdFx0Z2xvYmFsRXZhbC5ydW5TY3JpcHRzSW5PcmRlcihcblx0XHRcdFx0XHRcdHNjcmlwdHMsXG5cdFx0XHRcdFx0XHRpbmRleCArIDEsXG5cdFx0XHRcdFx0XHRkZWZhdWx0Rm4sXG5cdFx0XHRcdFx0XHRhcHBlbmRGblxuXHRcdFx0XHRcdCk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0XHRcdFx0fSBlbHNlIGlmIChkZWZhdWx0Rm4pIHtcblx0XHRcdFx0XHRhc3luYy5uZXh0VGljayhkZWZhdWx0Rm4pO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0YXBwZW5kRm5cblx0XHQpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGdsb2JhbEV2YWw7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7YXN5bmN9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7b25jZX0gZnJvbSAnLi9kb20nO1xuXG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb25zIGZvciBydW5uaW5nIHN0eWxlcy5cbiAqL1xuY2xhc3MgZ2xvYmFsRXZhbFN0eWxlcyB7XG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgdGhlIGdpdmVuIHN0eWxlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBhcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKiBAcmV0dXJuIHtFbGVtZW50fSBzdHlsZVxuXHQgKi9cblx0c3RhdGljIHJ1bih0ZXh0LCBhcHBlbmRGbikge1xuXHRcdGNvbnN0IHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcblx0XHRzdHlsZS5pbm5lckhUTUwgPSB0ZXh0O1xuXHRcdGlmIChhcHBlbmRGbikge1xuXHRcdFx0YXBwZW5kRm4oc3R5bGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHN0eWxlKTtcblx0XHR9XG5cdFx0cmV0dXJuIHN0eWxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0aGUgZ2l2ZW4gc3R5bGUgZmlsZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGhyZWYgVGhlIGZpbGUncyBwYXRoLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBkZWZhdWx0Rm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXG5cdCAqICAgd2hlbiB0aGUgc3R5bGVzIGhhcyBiZWVuIHJ1bi5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc3R5bGVcblx0ICovXG5cdHN0YXRpYyBydW5GaWxlKGhyZWYsIGRlZmF1bHRGbiwgYXBwZW5kRm4pIHtcblx0XHRjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGluaycpO1xuXHRcdGxpbmsucmVsID0gJ3N0eWxlc2hlZXQnO1xuXHRcdGxpbmsuaHJlZiA9IGhyZWY7XG5cdFx0Z2xvYmFsRXZhbFN0eWxlcy5ydW5TdHlsZShsaW5rLCBkZWZhdWx0Rm4sIGFwcGVuZEZuKTtcblx0XHRyZXR1cm4gbGluaztcblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgdGhlIGNvZGUgcmVmZXJlbmNlZCBieSB0aGUgZ2l2ZW4gc3R5bGUvbGluayBlbGVtZW50LlxuXHQgKiBAcGFyYW0geyFFbGVtZW50fSBzdHlsZVxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBkZWZhdWx0Rm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXG5cdCAqICAgd2hlbiB0aGUgc2NyaXB0IGhhcyBiZWVuIHJ1bi5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogIEByZXR1cm4ge0VsZW1lbnR9IHN0eWxlXG5cdCAqL1xuXHRzdGF0aWMgcnVuU3R5bGUoc3R5bGUsIGRlZmF1bHRGbiwgYXBwZW5kRm4pIHtcblx0XHRjb25zdCBjYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0ZGVmYXVsdEZuICYmIGRlZmF1bHRGbigpO1xuXHRcdH07XG5cdFx0aWYgKFxuXHRcdFx0c3R5bGUucmVsICYmXG5cdFx0XHRzdHlsZS5yZWwgIT09ICdzdHlsZXNoZWV0JyAmJlxuXHRcdFx0c3R5bGUucmVsICE9PSAnY2Fub25pY2FsJyAmJlxuXHRcdFx0c3R5bGUucmVsICE9PSAnYWx0ZXJuYXRlJ1xuXHRcdCkge1xuXHRcdFx0YXN5bmMubmV4dFRpY2soY2FsbGJhY2spO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChcblx0XHRcdHN0eWxlLnRhZ05hbWUgPT09ICdTVFlMRScgfHxcblx0XHRcdHN0eWxlLnJlbCA9PT0gJ2Nhbm9uaWNhbCcgfHxcblx0XHRcdHN0eWxlLnJlbCA9PT0gJ2FsdGVybmF0ZSdcblx0XHQpIHtcblx0XHRcdGFzeW5jLm5leHRUaWNrKGNhbGxiYWNrKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0b25jZShzdHlsZSwgJ2xvYWQnLCBjYWxsYmFjayk7XG5cdFx0XHRvbmNlKHN0eWxlLCAnZXJyb3InLCBjYWxsYmFjayk7XG5cdFx0fVxuXG5cdFx0aWYgKGFwcGVuZEZuKSB7XG5cdFx0XHRhcHBlbmRGbihzdHlsZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGUpO1xuXHRcdH1cblxuXHRcdHJldHVybiBzdHlsZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgYW55IHN0eWxlIHByZXNlbnQgaW4gdGhlIGdpdmVuIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gZGVmYXVsdEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZVxuXHQgKiAgIHN0eWxlIGhhcyBiZWVuIHJ1bi5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICovXG5cdHN0YXRpYyBydW5TdHlsZXNJbkVsZW1lbnQoZWxlbWVudCwgZGVmYXVsdEZuLCBhcHBlbmRGbikge1xuXHRcdGNvbnN0IHN0eWxlcyA9IGVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnc3R5bGUsbGluaycpO1xuXHRcdGlmIChzdHlsZXMubGVuZ3RoID09PSAwICYmIGRlZmF1bHRGbikge1xuXHRcdFx0YXN5bmMubmV4dFRpY2soZGVmYXVsdEZuKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRsZXQgbG9hZENvdW50ID0gMDtcblx0XHRjb25zdCBjYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKGRlZmF1bHRGbiAmJiArK2xvYWRDb3VudCA9PT0gc3R5bGVzLmxlbmd0aCkge1xuXHRcdFx0XHRhc3luYy5uZXh0VGljayhkZWZhdWx0Rm4pO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzdHlsZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGdsb2JhbEV2YWxTdHlsZXMucnVuU3R5bGUoc3R5bGVzW2ldLCBjYWxsYmFjaywgYXBwZW5kRm4pO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBnbG9iYWxFdmFsU3R5bGVzO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2lzU2VydmVyU2lkZX0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHtyZWdpc3RlckN1c3RvbUV2ZW50LCBjb250YWluc30gZnJvbSAnLi9kb20nO1xuaW1wb3J0IGZlYXR1cmVzIGZyb20gJy4vZmVhdHVyZXMnO1xuXG4vKipcbiAqIFJlZ2lzdGVyIGN1c3RvbSBldmVudHMgZm9yIGV2ZW50IGRlbGVnYXRpb24uXG4gKi9cbmZ1bmN0aW9uIHJlZ2lzdGVyRXZlbnRzKCkge1xuXHRjb25zdCBtb3VzZUV2ZW50TWFwID0ge1xuXHRcdG1vdXNlZW50ZXI6ICdtb3VzZW92ZXInLFxuXHRcdG1vdXNlbGVhdmU6ICdtb3VzZW91dCcsXG5cdFx0cG9pbnRlcmVudGVyOiAncG9pbnRlcm92ZXInLFxuXHRcdHBvaW50ZXJsZWF2ZTogJ3BvaW50ZXJvdXQnLFxuXHR9O1xuXHRPYmplY3Qua2V5cyhtb3VzZUV2ZW50TWFwKS5mb3JFYWNoKGZ1bmN0aW9uKGV2ZW50TmFtZSkge1xuXHRcdHJlZ2lzdGVyQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCB7XG5cdFx0XHRkZWxlZ2F0ZTogdHJ1ZSxcblx0XHRcdGhhbmRsZXI6IGZ1bmN0aW9uKGNhbGxiYWNrLCBldmVudCkge1xuXHRcdFx0XHRjb25zdCByZWxhdGVkID0gZXZlbnQucmVsYXRlZFRhcmdldDtcblx0XHRcdFx0Y29uc3QgdGFyZ2V0ID0gZXZlbnQuZGVsZWdhdGVUYXJnZXQ7XG5cdFx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuXHRcdFx0XHRpZiAoXG5cdFx0XHRcdFx0IXJlbGF0ZWQgfHxcblx0XHRcdFx0XHQocmVsYXRlZCAhPT0gdGFyZ2V0ICYmICFjb250YWlucyh0YXJnZXQsIHJlbGF0ZWQpKVxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHRldmVudC5jdXN0b21UeXBlID0gZXZlbnROYW1lO1xuXHRcdFx0XHRcdHJldHVybiBjYWxsYmFjayhldmVudCk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRvcmlnaW5hbEV2ZW50OiBtb3VzZUV2ZW50TWFwW2V2ZW50TmFtZV0sXG5cdFx0fSk7XG5cdH0pO1xuXG5cdGNvbnN0IGFuaW1hdGlvbkV2ZW50TWFwID0ge1xuXHRcdGFuaW1hdGlvbjogJ2FuaW1hdGlvbmVuZCcsXG5cdFx0dHJhbnNpdGlvbjogJ3RyYW5zaXRpb25lbmQnLFxuXHR9O1xuXHRPYmplY3Qua2V5cyhhbmltYXRpb25FdmVudE1hcCkuZm9yRWFjaChmdW5jdGlvbihldmVudFR5cGUpIHtcblx0XHRjb25zdCBldmVudE5hbWUgPSBhbmltYXRpb25FdmVudE1hcFtldmVudFR5cGVdO1xuXHRcdHJlZ2lzdGVyQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCB7XG5cdFx0XHRldmVudDogdHJ1ZSxcblx0XHRcdGRlbGVnYXRlOiB0cnVlLFxuXHRcdFx0aGFuZGxlcjogZnVuY3Rpb24oY2FsbGJhY2ssIGV2ZW50KSB7XG5cdFx0XHRcdGV2ZW50LmN1c3RvbVR5cGUgPSBldmVudE5hbWU7XG5cdFx0XHRcdHJldHVybiBjYWxsYmFjayhldmVudCk7XG5cdFx0XHR9LFxuXHRcdFx0b3JpZ2luYWxFdmVudDogZmVhdHVyZXMuY2hlY2tBbmltYXRpb25FdmVudE5hbWUoKVtldmVudFR5cGVdLFxuXHRcdH0pO1xuXHR9KTtcbn1cblxuaWYgKCFpc1NlcnZlclNpZGUoKSkge1xuXHRyZWdpc3RlckV2ZW50cygpO1xufVxuIiwidmFyIGdsb2JhbHMgPSBnbG9iYWxzIHx8IHt9O1xuXG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0Z2xvYmFscy53aW5kb3cgPSB3aW5kb3c7XG59XG5cbmlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG5cdGdsb2JhbHMuZG9jdW1lbnQgPSBkb2N1bWVudDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZ2xvYmFscztcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBBIGNvbGxlY3Rpb24gb2YgY29yZSB1dGlsaXR5IGZ1bmN0aW9ucy5cbiAqIEBjb25zdFxuICovXG5cbmxldCBjb21wYXRpYmlsaXR5TW9kZURhdGFfO1xuXG4vKipcbiAqIENvdW50ZXIgZm9yIHVuaXF1ZSBpZC5cbiAqIEB0eXBlIHtOdW1iZXJ9XG4gKiBAcHJpdmF0ZVxuICovXG5sZXQgdW5pcXVlSWRDb3VudGVyXyA9IDE7XG5cbi8qKlxuICogVW5pcXVlIGlkIHByb3BlcnR5IHByZWZpeC5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAcHJvdGVjdGVkXG4gKi9cbmV4cG9ydCBjb25zdCBVSURfUFJPUEVSVFkgPSBgY29yZV8keyhNYXRoLnJhbmRvbSgpICogMWU5KSA+Pj4gMH1gO1xuXG4vKipcbiAqIFdoZW4gZGVmaW5pbmcgYSBjbGFzcyBGb28gd2l0aCBhbiBhYnN0cmFjdCBtZXRob2QgYmFyKCksIHlvdSBjYW4gZG86XG4gKiBGb28ucHJvdG90eXBlLmJhciA9IGFic3RyYWN0TWV0aG9kXG4gKlxuICogTm93IGlmIGEgc3ViY2xhc3Mgb2YgRm9vIGZhaWxzIHRvIG92ZXJyaWRlIGJhcigpLCBhbiBlcnJvciB3aWxsIGJlIHRocm93blxuICogd2hlbiBiYXIoKSBpcyBpbnZva2VkLlxuICpcbiAqIEB0eXBlIHshRnVuY3Rpb259XG4gKiBAdGhyb3dzIHtFcnJvcn0gd2hlbiBpbnZva2VkIHRvIGluZGljYXRlIHRoZSBtZXRob2Qgc2hvdWxkIGJlIG92ZXJyaWRkZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhYnN0cmFjdE1ldGhvZCgpIHtcblx0dGhyb3cgRXJyb3IoJ1VuaW1wbGVtZW50ZWQgYWJzdHJhY3QgbWV0aG9kJyk7XG59XG5cbi8qKlxuICogRGlzYWJsZXMgTWV0YWwuanMncyBjb21wYXRpYmlsaXR5IG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkaXNhYmxlQ29tcGF0aWJpbGl0eU1vZGUoKSB7XG5cdGNvbXBhdGliaWxpdHlNb2RlRGF0YV8gPSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogRW5hYmxlcyBNZXRhbC5qcydzIGNvbXBhdGliaWxpdHkgbW9kZSB3aXRoIHRoZSBmb2xsb3dpbmcgZmVhdHVyZXMgZnJvbSByY1xuICogYW5kIDEueCB2ZXJzaW9uczpcbiAqICAgICAtIFVzaW5nIFwia2V5XCIgdG8gcmVmZXJlbmNlIGNvbXBvbmVudCBpbnN0YW5jZXMuIEluIHRoZSBjdXJyZW50IHZlcnNpb25cbiAqICAgICAgIHRoaXMgc2hvdWxkIGJlIGRvbmUgdmlhIFwicmVmXCIgaW5zdGVhZC4gVGhpcyBhbGxvd3Mgb2xkIGNvZGUgc3RpbGxcbiAqICAgICAgIHVzaW5nIFwia2V5XCIgdG8ga2VlcCB3b3JraW5nIGxpa2UgYmVmb3JlLiBOT1RFOiB0aGlzIG1heSBjYXVzZVxuICogICAgICAgcHJvYmxlbXMsIHNpbmNlIFwia2V5XCIgaXMgbWVhbnQgdG8gYmUgdXNlZCBkaWZmZXJlbnRseS4gT25seSB1c2UgdGhpc1xuICogICAgICAgaWYgaXQncyBub3QgcG9zc2libGUgdG8gdXBncmFkZSB0aGUgY29kZSB0byB1c2UgXCJyZWZcIiBpbnN0ZWFkLlxuICogQHBhcmFtIHtPYmplY3Q9fSBkYXRhIE9wdGlvbmFsIG9iamVjdCB3aXRoIGRhdGEgdG8gc3BlY2lmeSBtb3JlXG4gKiAgICAgZGV0YWlscywgc3VjaCBhczpcbiAqICAgICAgICAgLSByZW5kZXJlcnMge0FycmF5fSB0aGUgdGVtcGxhdGUgcmVuZGVyZXJzIHRoYXQgc2hvdWxkIGJlIGluXG4gKiAgICAgICAgICAgY29tcGF0aWJpbGl0eSBtb2RlLCBlaXRoZXIgdGhlaXIgY29uc3RydWN0b3JzIG9yIHN0cmluZ3NcbiAqICAgICAgICAgICByZXByZXNlbnRpbmcgdGhlbSAoZS5nLiAnc295JyBvciAnanN4JykuIEJ5IGRlZmF1bHQsIGFsbCB0aGUgb25lc1xuICogICAgICAgICAgIHRoYXQgZXh0ZW5kIGZyb20gSW5jcmVtZW50YWxEb21SZW5kZXJlci5cbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmFibGVDb21wYXRpYmlsaXR5TW9kZShkYXRhID0ge30pIHtcblx0Y29tcGF0aWJpbGl0eU1vZGVEYXRhXyA9IGRhdGE7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZGF0YSB1c2VkIGZvciBjb21wYXRpYmlsaXR5IG1vZGUsIG9yIG5vdGhpbmcgaWYgaXQgaGFzbid0IGJlZW5cbiAqIGVuYWJsZWQuXG4gKiBAcmV0dXJuIHtPYmplY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb21wYXRpYmlsaXR5TW9kZURhdGEoKSB7XG5cdC8vIENvbXBhdGliaWxpdHkgbW9kZSBjYW4gYmUgc2V0IHZpYSB0aGUgX19NRVRBTF9DT01QQVRJQklMSVRZX18gZ2xvYmFsIHZhci5cblx0aWYgKGNvbXBhdGliaWxpdHlNb2RlRGF0YV8gPT09IHVuZGVmaW5lZCkge1xuXHRcdGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuX19NRVRBTF9DT01QQVRJQklMSVRZX18pIHtcblx0XHRcdGVuYWJsZUNvbXBhdGliaWxpdHlNb2RlKHdpbmRvdy5fX01FVEFMX0NPTVBBVElCSUxJVFlfXyk7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBjb21wYXRpYmlsaXR5TW9kZURhdGFfO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGZpcnN0IGFyZ3VtZW50IGlmIGl0J3MgdHJ1dGh5LCBvciB0aGUgc2Vjb25kIG90aGVyd2lzZS5cbiAqIEBwYXJhbSB7Kn0gYVxuICogQHBhcmFtIHsqfSBiXG4gKiBAcmV0dXJuIHsqfVxuICogQHByb3RlY3RlZFxuICovXG5mdW5jdGlvbiBnZXRGaXJzdFRydXRoeV8oYSwgYikge1xuXHRyZXR1cm4gYSB8fCBiO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIG5hbWUgb2YgdGhlIGdpdmVuIGZ1bmN0aW9uLiBJZiB0aGUgY3VycmVudCBicm93c2VyIGRvZXNuJ3RcbiAqIHN1cHBvcnQgdGhlIGBuYW1lYCBwcm9wZXJ0eSwgdGhpcyB3aWxsIGNhbGN1bGF0ZSBpdCBmcm9tIHRoZSBmdW5jdGlvbidzXG4gKiBjb250ZW50IHN0cmluZy5cbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGZuXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRGdW5jdGlvbk5hbWUoZm4pIHtcblx0aWYgKCFmbi5uYW1lKSB7XG5cdFx0Y29uc3Qgc3RyID0gZm4udG9TdHJpbmcoKTtcblx0XHRmbi5uYW1lID0gc3RyLnN1YnN0cmluZyg5LCBzdHIuaW5kZXhPZignKCcpKTtcblx0fVxuXHRyZXR1cm4gZm4ubmFtZTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSB2YWx1ZSBvZiBhIHN0YXRpYyBwcm9wZXJ0eSBpbiB0aGUgZ2l2ZW4gY2xhc3MuIFRoZSB2YWx1ZSB3aWxsIGJlXG4gKiBpbmhlcml0ZWQgZnJvbSBhbmNlc3RvcnMgYXMgZXhwZWN0ZWQsIHVubGVzcyBhIGN1c3RvbSBtZXJnZSBmdW5jdGlvbiBpcyBnaXZlbixcbiAqIHdoaWNoIGNhbiBjaGFuZ2UgaG93IHRoZSBzdXBlciBjbGFzc2VzJyB2YWx1ZSBmb3IgdGhhdCBwcm9wZXJ0eSB3aWxsIGJlIG1lcmdlZFxuICogdG9nZXRoZXIuXG4gKiBUaGUgZmluYWwgbWVyZ2VkIHZhbHVlIHdpbGwgYmUgc3RvcmVkIGluIGFub3RoZXIgcHJvcGVydHksIHNvIHRoYXQgaXQgd29uJ3RcbiAqIGJlIHJlY2FsY3VsYXRlZCBldmVuIGlmIHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIG11bHRpcGxlIHRpbWVzLlxuICogQHBhcmFtIHshZnVuY3Rpb24oKX0gY3RvciBDbGFzcyBjb25zdHJ1Y3Rvci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eU5hbWUgUHJvcGVydHkgbmFtZSB0byBiZSBtZXJnZWQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCosICopOio9fSBtZXJnZUZuIEZ1bmN0aW9uIHRoYXQgcmVjZWl2ZXMgdGhlIG1lcmdlZFxuICogICAgIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSBzbyBmYXIgYW5kIHRoZSBuZXh0IHZhbHVlIHRvIGJlIG1lcmdlZCB0byBpdC5cbiAqICAgICBTaG91bGQgcmV0dXJuIHRoZXNlIHR3byBtZXJnZWQgdG9nZXRoZXIuIElmIG5vdCBwYXNzZWQgdGhlIGZpbmFsIHByb3BlcnR5XG4gKiAgICAgd2lsbCBiZSB0aGUgZmlyc3QgdHJ1dGh5IHZhbHVlIGFtb25nIGFuY2VzdG9ycy5cbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0YXRpY1Byb3BlcnR5KFxuXHRjdG9yLFxuXHRwcm9wZXJ0eU5hbWUsXG5cdG1lcmdlRm4gPSBnZXRGaXJzdFRydXRoeV9cbikge1xuXHRjb25zdCBtZXJnZWROYW1lID0gcHJvcGVydHlOYW1lICsgJ19NRVJHRUQnO1xuXHRpZiAoIWN0b3IuaGFzT3duUHJvcGVydHkobWVyZ2VkTmFtZSkpIHtcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcblx0XHRsZXQgbWVyZ2VkID0gY3Rvci5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eU5hbWUpXG5cdFx0XHQ/IGN0b3JbcHJvcGVydHlOYW1lXVxuXHRcdFx0OiBudWxsO1xuXHRcdGlmIChjdG9yLl9fcHJvdG9fXyAmJiAhY3Rvci5fX3Byb3RvX18uaXNQcm90b3R5cGVPZihGdW5jdGlvbikpIHtcblx0XHRcdG1lcmdlZCA9IG1lcmdlRm4oXG5cdFx0XHRcdG1lcmdlZCxcblx0XHRcdFx0Z2V0U3RhdGljUHJvcGVydHkoY3Rvci5fX3Byb3RvX18sIHByb3BlcnR5TmFtZSwgbWVyZ2VGbilcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGN0b3JbbWVyZ2VkTmFtZV0gPSBtZXJnZWQ7XG5cdH1cblx0cmV0dXJuIGN0b3JbbWVyZ2VkTmFtZV07XG59XG5cbi8qKlxuICogR2V0cyBhbiB1bmlxdWUgaWQuIElmIGBvYmplY3RgIGFyZ3VtZW50IGlzIHBhc3NlZCwgdGhlIG9iamVjdCBpc1xuICogbXV0YXRlZCB3aXRoIGFuIHVuaXF1ZSBpZC4gQ29uc2VjdXRpdmUgY2FsbHMgd2l0aCB0aGUgc2FtZSBvYmplY3RcbiAqIHJlZmVyZW5jZSB3b24ndCBtdXRhdGUgdGhlIG9iamVjdCBhZ2FpbiwgaW5zdGVhZCB0aGUgY3VycmVudCBvYmplY3QgdWlkXG4gKiByZXR1cm5zLiBTZWUge0BsaW5rIFVJRF9QUk9QRVJUWX0uXG4gKiBAcGFyYW0ge09iamVjdD19IG9iamVjdCBPcHRpb25hbCBvYmplY3QgdG8gYmUgbXV0YXRlZCB3aXRoIHRoZSB1aWQuIElmXG4gKiAgICAgbm90IHNwZWNpZmllZCB0aGlzIG1ldGhvZCBvbmx5IHJldHVybnMgdGhlIHVpZC5cbiAqIEBwYXJhbSB7Ym9vbGVhbj19IG5vSW5oZXJpdGFuY2UgT3B0aW9uYWwgZmxhZyBpbmRpY2F0aW5nIGlmIHRoaXNcbiAqICAgICBvYmplY3QncyB1aWQgcHJvcGVydHkgY2FuIGJlIGluaGVyaXRlZCBmcm9tIHBhcmVudHMgb3Igbm90LlxuICogQHRocm93cyB7RXJyb3J9IHdoZW4gaW52b2tlZCB0byBpbmRpY2F0ZSB0aGUgbWV0aG9kIHNob3VsZCBiZSBvdmVycmlkZGVuLlxuICogQHJldHVybiB7bnVtYmVyfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VWlkKG9iamVjdCwgbm9Jbmhlcml0YW5jZSkge1xuXHRpZiAob2JqZWN0KSB7XG5cdFx0bGV0IGlkID0gb2JqZWN0W1VJRF9QUk9QRVJUWV07XG5cdFx0aWYgKG5vSW5oZXJpdGFuY2UgJiYgIW9iamVjdC5oYXNPd25Qcm9wZXJ0eShVSURfUFJPUEVSVFkpKSB7XG5cdFx0XHRpZCA9IG51bGw7XG5cdFx0fVxuXHRcdHJldHVybiBpZCB8fCAob2JqZWN0W1VJRF9QUk9QRVJUWV0gPSB1bmlxdWVJZENvdW50ZXJfKyspO1xuXHR9XG5cdHJldHVybiB1bmlxdWVJZENvdW50ZXJfKys7XG59XG5cbi8qKlxuICogVGhlIGlkZW50aXR5IGZ1bmN0aW9uLiBSZXR1cm5zIGl0cyBmaXJzdCBhcmd1bWVudC5cbiAqIEBwYXJhbSB7Kj19IHJldHVyblZhbHVlIFRoZSBzaW5nbGUgdmFsdWUgdGhhdCB3aWxsIGJlIHJldHVybmVkLlxuICogQHJldHVybiB7P30gVGhlIGZpcnN0IGFyZ3VtZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaWRlbnRpdHlGdW5jdGlvbihyZXR1cm5WYWx1ZSkge1xuXHRyZXR1cm4gcmV0dXJuVmFsdWU7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYSBib29sZWFuLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgYm9vbGVhbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQm9vbGVhbih2YWwpIHtcblx0cmV0dXJuIHR5cGVvZiB2YWwgPT09ICdib29sZWFuJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBub3QgdW5kZWZpbmVkLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgZGVmaW5lZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGVmKHZhbCkge1xuXHRyZXR1cm4gdmFsICE9PSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIG5vdCB1bmRlZmluZWQgb3IgbnVsbC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEZWZBbmROb3ROdWxsKHZhbCkge1xuXHRyZXR1cm4gaXNEZWYodmFsKSAmJiAhaXNOdWxsKHZhbCk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgZG9jdW1lbnQuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRG9jdW1lbnQodmFsKSB7XG5cdHJldHVybiB2YWwgJiYgdHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsLm5vZGVUeXBlID09PSA5O1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIGRvY3VtZW50LWZyYWdtZW50LlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RvY3VtZW50RnJhZ21lbnQodmFsKSB7XG5cdHJldHVybiB2YWwgJiYgdHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsLm5vZGVUeXBlID09PSAxMTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBkb20gZWxlbWVudC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFbGVtZW50KHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbC5ub2RlVHlwZSA9PT0gMTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBhIGZ1bmN0aW9uLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgYSBmdW5jdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRnVuY3Rpb24odmFsKSB7XG5cdHJldHVybiB0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBudWxsLlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc051bGwodmFsKSB7XG5cdHJldHVybiB2YWwgPT09IG51bGw7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYSBudW1iZXIuXG4gKiBAcGFyYW0gez99IHZhbCBWYXJpYWJsZSB0byB0ZXN0LlxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB2YXJpYWJsZSBpcyBhIG51bWJlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTnVtYmVyKHZhbCkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ251bWJlcic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgd2luZG93LlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1dpbmRvdyh2YWwpIHtcblx0cmV0dXJuIHZhbCAhPT0gbnVsbCAmJiB2YWwgPT09IHZhbC53aW5kb3c7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYW4gb2JqZWN0LiBUaGlzIGluY2x1ZGVzIGFycmF5c1xuICogYW5kIGZ1bmN0aW9ucy5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGFuIG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzT2JqZWN0KHZhbCkge1xuXHRjb25zdCB0eXBlID0gdHlwZW9mIHZhbDtcblx0cmV0dXJuICh0eXBlID09PSAnb2JqZWN0JyAmJiB2YWwgIT09IG51bGwpIHx8IHR5cGUgPT09ICdmdW5jdGlvbic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgUHJvbWlzZS5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQcm9taXNlKHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHR5cGVvZiB2YWwudGhlbiA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBzdHJpbmcuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU3RyaW5nKHZhbCkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ3N0cmluZycgfHwgdmFsIGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG4vKipcbiAqIFNldHMgdG8gdHJ1ZSBpZiBydW5uaW5nIGluc2lkZSBOb2RlLmpzIGVudmlyb25tZW50IHdpdGggZXh0cmEgY2hlY2sgZm9yXG4gKiBgcHJvY2Vzcy5icm93c2VyYCB0byBza2lwIEthcm1hIHJ1bm5lciBlbnZpcm9ubWVudC4gS2FybWEgZW52aXJvbm1lbnQgaGFzXG4gKiBgcHJvY2Vzc2AgZGVmaW5lZCBldmVuIHRob3VnaCBpdCBydW5zIG9uIHRoZSBicm93c2VyLlxuICogQHBhcmFtIHs/T2JqZWN0fSBvcHRpb25zIENvbnRhaW5zIGBjaGVja0VudmAgcHJvcGVydHkgd2hpY2ggaWYgdHJ1ZSwgY2hlY2tzXG4gKiB0aGUgTk9ERV9FTlYgdmFyaWFibGUuIElmIE5PREVfRU5WIGVxdWFscyAndGVzdCcsIHRoZSBmdW5jdGlvbiByZXR1cm5zIGZhbHNlLlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2VydmVyU2lkZShvcHRpb25zID0ge2NoZWNrRW52OiB0cnVlfSkge1xuXHRsZXQgc2VydmVyU2lkZSA9IHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiAhcHJvY2Vzcy5icm93c2VyO1xuXHRpZiAoc2VydmVyU2lkZSAmJiBvcHRpb25zLmNoZWNrRW52KSB7XG5cdFx0c2VydmVyU2lkZSA9XG5cdFx0XHR0eXBlb2YgcHJvY2Vzcy5lbnYgIT09ICd1bmRlZmluZWQnICYmXG5cdFx0XHRwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Rlc3QnO1xuXHR9XG5cdHJldHVybiBzZXJ2ZXJTaWRlO1xufVxuXG4vKipcbiAqIE51bGwgZnVuY3Rpb24gdXNlZCBmb3IgZGVmYXVsdCB2YWx1ZXMgb2YgY2FsbGJhY2tzLCBldGMuXG4gKiBAcmV0dXJuIHt2b2lkfSBOb3RoaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbnVsbEZ1bmN0aW9uKCkge31cbiIsIid1c2Ugc3RyaWN0JztcblxuLy8gVGhpcyBmaWxlIGV4aXN0cyBqdXN0IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgbWFraW5nIHN1cmUgdGhhdCBvbGRcbi8vIGRlZmF1bHQgaW1wb3J0cyBmb3IgdGhpcyBmaWxlIHN0aWxsIHdvcmsuIEl0J3MgYmVzdCB0byB1c2UgdGhlIG5hbWVkIGV4cG9ydHNcbi8vIGZvciBlYWNoIGZ1bmN0aW9uIGluc3RlYWQgdGhvdWdoLCBzaW5jZSB0aGF0IGFsbG93cyBidW5kbGVycyBsaWtlIFJvbGx1cCB0b1xuLy8gcmVkdWNlIHRoZSBidW5kbGUgc2l6ZSBieSByZW1vdmluZyB1bnVzZWQgY29kZS5cbmltcG9ydCAqIGFzIGNvcmUgZnJvbSAnLi9jb3JlTmFtZWQnO1xuXG5leHBvcnQgZGVmYXVsdCBjb3JlO1xuZXhwb3J0IHtjb3JlfTtcbmV4cG9ydCAqIGZyb20gJy4vY29yZU5hbWVkJztcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBTZXQgb2YgdXRpbGl0aWVzIGZvciBhcnJheSBvcGVyYXRpb25zXG4gKi9cbmNsYXNzIGFycmF5IHtcblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gYXJyYXlzIGhhdmUgdGhlIHNhbWUgY29udGVudC5cblx0ICogQHBhcmFtIHshQXJyYXk8Kj59IGFycjFcblx0ICogQHBhcmFtIHshQXJyYXk8Kj59IGFycjJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdHN0YXRpYyBlcXVhbChhcnIxLCBhcnIyKSB7XG5cdFx0aWYgKGFycjEgPT09IGFycjIpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRpZiAoYXJyMS5sZW5ndGggIT09IGFycjIubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJyMS5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGFycjFbaV0gIT09IGFycjJbaV0pIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBmaXJzdCB2YWx1ZSBpbiB0aGUgZ2l2ZW4gYXJyYXkgdGhhdCBpc24ndCB1bmRlZmluZWQuXG5cdCAqIEBwYXJhbSB7IUFycmF5fSBhcnJcblx0ICogQHJldHVybiB7Kn1cblx0ICovXG5cdHN0YXRpYyBmaXJzdERlZmluZWRWYWx1ZShhcnIpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGFycltpXSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHJldHVybiBhcnJbaV07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRyYW5zZm9ybXMgdGhlIGlucHV0IG5lc3RlZCBhcnJheSB0byBiZWNvbWUgZmxhdC5cblx0ICogQHBhcmFtIHtBcnJheS48KnxBcnJheS48Kj4+fSBhcnIgTmVzdGVkIGFycmF5IHRvIGZsYXR0ZW4uXG5cdCAqIEBwYXJhbSB7QXJyYXkuPCo+PX0gb3V0cHV0IE9wdGlvbmFsIG91dHB1dCBhcnJheS5cblx0ICogQHJldHVybiB7QXJyYXkuPCo+fSBGbGF0IGFycmF5LlxuXHQgKi9cblx0c3RhdGljIGZsYXR0ZW4oYXJyLCBvdXRwdXQgPSBbXSkge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAoQXJyYXkuaXNBcnJheShhcnJbaV0pKSB7XG5cdFx0XHRcdGFycmF5LmZsYXR0ZW4oYXJyW2ldLCBvdXRwdXQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0b3V0cHV0LnB1c2goYXJyW2ldKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIG91dHB1dDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGEgcGFydGljdWxhciB2YWx1ZSBmcm9tIGFuIGFycmF5LlxuXHQgKiBAcGFyYW0ge0FycmF5LjxUPn0gYXJyIEFycmF5IGZyb20gd2hpY2ggdG8gcmVtb3ZlIHZhbHVlLlxuXHQgKiBAcGFyYW0ge1R9IG9iaiBPYmplY3QgdG8gcmVtb3ZlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIGFuIGVsZW1lbnQgd2FzIHJlbW92ZWQuXG5cdCAqIEB0ZW1wbGF0ZSBUXG5cdCAqL1xuXHRzdGF0aWMgcmVtb3ZlKGFyciwgb2JqKSB7XG5cdFx0Y29uc3QgaSA9IGFyci5pbmRleE9mKG9iaik7XG5cdFx0bGV0IHJ2O1xuXHRcdGlmICgocnYgPSBpID49IDApKSB7XG5cdFx0XHRhcnJheS5yZW1vdmVBdChhcnIsIGkpO1xuXHRcdH1cblx0XHRyZXR1cm4gcnY7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBmcm9tIGFuIGFycmF5IHRoZSBlbGVtZW50IGF0IGluZGV4IGlcblx0ICogQHBhcmFtIHtBcnJheX0gYXJyIEFycmF5IG9yIGFycmF5IGxpa2Ugb2JqZWN0IGZyb20gd2hpY2ggdG8gcmVtb3ZlIHZhbHVlLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gaSBUaGUgaW5kZXggdG8gcmVtb3ZlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIGFuIGVsZW1lbnQgd2FzIHJlbW92ZWQuXG5cdCAqL1xuXHRzdGF0aWMgcmVtb3ZlQXQoYXJyLCBpKSB7XG5cdFx0cmV0dXJuIEFycmF5LnByb3RvdHlwZS5zcGxpY2UuY2FsbChhcnIsIGksIDEpLmxlbmd0aCA9PT0gMTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTbGljZXMgdGhlIGdpdmVuIGFycmF5LCBqdXN0IGxpa2UgQXJyYXkucHJvdG90eXBlLnNsaWNlLCBidXQgdGhpc1xuXHQgKiBpcyBmYXN0ZXIgYW5kIHdvcmtpbmcgb24gYWxsIGFycmF5LWxpa2Ugb2JqZWN0cyAobGlrZSBhcmd1bWVudHMpLlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IGFyciBBcnJheS1saWtlIG9iamVjdCB0byBzbGljZS5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0IFRoZSBpbmRleCB0aGF0IHNob3VsZCBzdGFydCB0aGUgc2xpY2UuXG5cdCAqIEBwYXJhbSB7bnVtYmVyPX0gZW5kIFRoZSBpbmRleCB3aGVyZSB0aGUgc2xpY2Ugc2hvdWxkIGVuZCwgbm90XG5cdCAqICAgaW5jbHVkZWQgaW4gdGhlIGZpbmFsIGFycmF5LiBJZiBub3QgZ2l2ZW4sIGFsbCBlbGVtZW50cyBhZnRlciB0aGVcblx0ICogICBzdGFydCBpbmRleCB3aWxsIGJlIGluY2x1ZGVkLlxuXHQgKiBAcmV0dXJuIHshQXJyYXl9XG5cdCAqL1xuXHRzdGF0aWMgc2xpY2UoYXJyLCBzdGFydCwgZW5kID0gYXJyLmxlbmd0aCkge1xuXHRcdGNvbnN0IHNsaWNlZCA9IFtdO1xuXHRcdGZvciAobGV0IGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG5cdFx0XHRzbGljZWQucHVzaChhcnJbaV0pO1xuXHRcdH1cblx0XHRyZXR1cm4gc2xpY2VkO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGFycmF5O1xuIiwiLyogIVxuICogUG9seWZpbGwgZnJvbSBHb29nbGUncyBDbG9zdXJlIExpYnJhcnkuXG4gKiBDb3B5cmlnaHQgMjAxMyBUaGUgQ2xvc3VyZSBMaWJyYXJ5IEF1dGhvcnMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2lzU2VydmVyU2lkZX0gZnJvbSAnLi4vY29yZU5hbWVkJztcblxuY29uc3QgYXN5bmMgPSB7fTtcblxuLyoqXG4gKiBUaHJvdyBhbiBpdGVtIHdpdGhvdXQgaW50ZXJydXB0aW5nIHRoZSBjdXJyZW50IGV4ZWN1dGlvbiBjb250ZXh0LiAgRm9yXG4gKiBleGFtcGxlLCBpZiBwcm9jZXNzaW5nIGEgZ3JvdXAgb2YgaXRlbXMgaW4gYSBsb29wLCBzb21ldGltZXMgaXQgaXMgdXNlZnVsXG4gKiB0byByZXBvcnQgYW4gZXJyb3Igd2hpbGUgc3RpbGwgYWxsb3dpbmcgdGhlIHJlc3Qgb2YgdGhlIGJhdGNoIHRvIGJlXG4gKiBwcm9jZXNzZWQuXG4gKiBAcGFyYW0geyp9IGV4Y2VwdGlvblxuICovXG5hc3luYy50aHJvd0V4Y2VwdGlvbiA9IGZ1bmN0aW9uKGV4Y2VwdGlvbikge1xuXHQvLyBFYWNoIHRocm93IG5lZWRzIHRvIGJlIGluIGl0cyBvd24gY29udGV4dC5cblx0YXN5bmMubmV4dFRpY2soZnVuY3Rpb24oKSB7XG5cdFx0dGhyb3cgZXhjZXB0aW9uO1xuXHR9KTtcbn07XG5cbi8qKlxuICogRmlyZXMgdGhlIHByb3ZpZGVkIGNhbGxiYWNrIGp1c3QgYmVmb3JlIHRoZSBjdXJyZW50IGNhbGxzdGFjayB1bndpbmRzLCBvciBhc1xuICogc29vbiBhcyBwb3NzaWJsZSBhZnRlciB0aGUgY3VycmVudCBKUyBleGVjdXRpb24gY29udGV4dC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24odGhpczpUSElTKX0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7VEhJUz19IGNvbnRleHQgT2JqZWN0IHRvIHVzZSBhcyB0aGUgXCJ0aGlzIHZhbHVlXCIgd2hlbiBjYWxsaW5nXG4gKiAgICAgdGhlIHByb3ZpZGVkIGZ1bmN0aW9uLlxuICogQHRlbXBsYXRlIFRISVNcbiAqL1xuYXN5bmMucnVuID0gZnVuY3Rpb24oY2FsbGJhY2ssIGNvbnRleHQpIHtcblx0aWYgKCFhc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXykge1xuXHRcdC8vIE5vdGhpbmcgaXMgY3VycmVudGx5IHNjaGVkdWxlZCwgc2NoZWR1bGUgaXQgbm93LlxuXHRcdGFzeW5jLm5leHRUaWNrKGFzeW5jLnJ1bi5wcm9jZXNzV29ya1F1ZXVlKTtcblx0XHRhc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXyA9IHRydWU7XG5cdH1cblxuXHRhc3luYy5ydW4ud29ya1F1ZXVlXy5wdXNoKG5ldyBhc3luYy5ydW4uV29ya0l0ZW1fKGNhbGxiYWNrLCBjb250ZXh0KSk7XG59O1xuXG4vKiogQHByaXZhdGUge2Jvb2xlYW59ICovXG5hc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXyA9IGZhbHNlO1xuXG4vKiogQHByaXZhdGUgeyFBcnJheS48IWFzeW5jLnJ1bi5Xb3JrSXRlbV8+fSAqL1xuYXN5bmMucnVuLndvcmtRdWV1ZV8gPSBbXTtcblxuLyoqXG4gKiBSdW4gYW55IHBlbmRpbmcgYXN5bmMucnVuIHdvcmsgaXRlbXMuIFRoaXMgZnVuY3Rpb24gaXMgbm90IGludGVuZGVkXG4gKiBmb3IgZ2VuZXJhbCB1c2UsIGJ1dCBmb3IgdXNlIGJ5IGVudHJ5IHBvaW50IGhhbmRsZXJzIHRvIHJ1biBpdGVtcyBhaGVhZCBvZlxuICogYXN5bmMubmV4dFRpY2suXG4gKi9cbmFzeW5jLnJ1bi5wcm9jZXNzV29ya1F1ZXVlID0gZnVuY3Rpb24oKSB7XG5cdC8vIE5PVEU6IGFkZGl0aW9uYWwgd29yayBxdWV1ZSBpdGVtcyBtYXkgYmUgcHVzaGVkIHdoaWxlIHByb2Nlc3NpbmcuXG5cdHdoaWxlIChhc3luYy5ydW4ud29ya1F1ZXVlXy5sZW5ndGgpIHtcblx0XHQvLyBEb24ndCBsZXQgdGhlIHdvcmsgcXVldWUgZ3JvdyBpbmRlZmluaXRlbHkuXG5cdFx0Y29uc3Qgd29ya0l0ZW1zID0gYXN5bmMucnVuLndvcmtRdWV1ZV87XG5cdFx0YXN5bmMucnVuLndvcmtRdWV1ZV8gPSBbXTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHdvcmtJdGVtcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3Qgd29ya0l0ZW0gPSB3b3JrSXRlbXNbaV07XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR3b3JrSXRlbS5mbi5jYWxsKHdvcmtJdGVtLnNjb3BlKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0YXN5bmMudGhyb3dFeGNlcHRpb24oZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gVGhlcmUgYXJlIG5vIG1vcmUgd29yayBpdGVtcywgcmVzZXQgdGhlIHdvcmsgcXVldWUuXG5cdGFzeW5jLnJ1bi53b3JrUXVldWVTY2hlZHVsZWRfID0gZmFsc2U7XG59O1xuXG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICogQGZpbmFsXG4gKiBAc3RydWN0XG4gKiBAcHJpdmF0ZVxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb24oKX0gZm5cbiAqIEBwYXJhbSB7T2JqZWN0fG51bGx8dW5kZWZpbmVkfSBzY29wZVxuICovXG5hc3luYy5ydW4uV29ya0l0ZW1fID0gZnVuY3Rpb24oZm4sIHNjb3BlKSB7XG5cdC8qKiBAY29uc3QgKi9cblx0dGhpcy5mbiA9IGZuO1xuXHQvKiogQGNvbnN0ICovXG5cdHRoaXMuc2NvcGUgPSBzY29wZTtcbn07XG5cbi8qKlxuICogRmlyZXMgdGhlIHByb3ZpZGVkIGNhbGxiYWNrcyBhcyBzb29uIGFzIHBvc3NpYmxlIGFmdGVyIHRoZSBjdXJyZW50IEpTXG4gKiBleGVjdXRpb24gY29udGV4dC4gc2V0VGltZW91dCjigKYsIDApIGFsd2F5cyB0YWtlcyBhdCBsZWFzdCA1bXMgZm9yIGxlZ2FjeVxuICogcmVhc29ucy5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24odGhpczpTQ09QRSl9IGNhbGxiYWNrIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGZpcmUgYXMgc29vbiBhc1xuICogICAgIHBvc3NpYmxlLlxuICogQHBhcmFtIHtTQ09QRT19IGNvbnRleHQgT2JqZWN0IGluIHdob3NlIHNjb3BlIHRvIGNhbGwgdGhlIGxpc3RlbmVyLlxuICogQHRlbXBsYXRlIFNDT1BFXG4gKi9cbmFzeW5jLm5leHRUaWNrID0gZnVuY3Rpb24oY2FsbGJhY2ssIGNvbnRleHQpIHtcblx0bGV0IGNiID0gY2FsbGJhY2s7XG5cdGlmIChjb250ZXh0KSB7XG5cdFx0Y2IgPSBjYWxsYmFjay5iaW5kKGNvbnRleHQpO1xuXHR9XG5cdGNiID0gYXN5bmMubmV4dFRpY2sud3JhcENhbGxiYWNrXyhjYik7XG5cdC8vIExvb2sgZm9yIGFuZCBjYWNoZSB0aGUgY3VzdG9tIGZhbGxiYWNrIHZlcnNpb24gb2Ygc2V0SW1tZWRpYXRlLlxuXHRpZiAoIWFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8pIHtcblx0XHRpZiAoXG5cdFx0XHR0eXBlb2Ygc2V0SW1tZWRpYXRlID09PSAnZnVuY3Rpb24nICYmXG5cdFx0XHRpc1NlcnZlclNpZGUoe2NoZWNrRW52OiBmYWxzZX0pXG5cdFx0KSB7XG5cdFx0XHRhc3luYy5uZXh0VGljay5zZXRJbW1lZGlhdGVfID0gc2V0SW1tZWRpYXRlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcblx0XHRcdGFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8gPSBhc3luYy5uZXh0VGljay5nZXRTZXRJbW1lZGlhdGVFbXVsYXRvcl8oKTtcblx0XHR9XG5cdH1cblx0YXN5bmMubmV4dFRpY2suc2V0SW1tZWRpYXRlXyhjYik7XG59O1xuXG4vKipcbiAqIENhY2hlIGZvciB0aGUgc2V0SW1tZWRpYXRlIGltcGxlbWVudGF0aW9uLlxuICogQHR5cGUge2Z1bmN0aW9uKGZ1bmN0aW9uKCkpfVxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMubmV4dFRpY2suc2V0SW1tZWRpYXRlXyA9IG51bGw7XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB0aGUgYmVzdCBwb3NzaWJsZSBpbXBsZW1lbnRhdGlvbiB0byBydW4gYSBmdW5jdGlvbiBhcyBzb29uIGFzXG4gKiB0aGUgSlMgZXZlbnQgbG9vcCBpcyBpZGxlLlxuICogQHJldHVybiB7ZnVuY3Rpb24oZnVuY3Rpb24oKSl9IFRoZSBcInNldEltbWVkaWF0ZVwiIGltcGxlbWVudGF0aW9uLlxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMubmV4dFRpY2suZ2V0U2V0SW1tZWRpYXRlRW11bGF0b3JfID0gZnVuY3Rpb24oKSB7XG5cdC8vIENyZWF0ZSBhIHByaXZhdGUgbWVzc2FnZSBjaGFubmVsIGFuZCB1c2UgaXQgdG8gcG9zdE1lc3NhZ2UgZW1wdHkgbWVzc2FnZXNcblx0Ly8gdG8gb3Vyc2VsdmVzLlxuXHRsZXQgQ2hhbm5lbDtcblxuXHQvLyBWZXJpZnkgaWYgdmFyaWFibGUgaXMgZGVmaW5lZCBvbiB0aGUgY3VycmVudCBydW50aW1lIChpLmUuLCBub2RlLCBicm93c2VyKS5cblx0Ly8gQ2FuJ3QgdXNlIHR5cGVvZiBlbmNsb3NlZCBpbiBhIGZ1bmN0aW9uIChzdWNoIGFzIGNvcmUuaXNGdW5jdGlvbikgb3IgYW5cblx0Ly8gZXhjZXB0aW9uIHdpbGwgYmUgdGhyb3duIHdoZW4gdGhlIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBhbiBlbnZpcm9ubWVudFxuXHQvLyB3aGVyZSB0aGUgdmFyaWFibGUgaXMgdW5kZWZpbmVkLlxuXHRpZiAodHlwZW9mIE1lc3NhZ2VDaGFubmVsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0Q2hhbm5lbCA9IE1lc3NhZ2VDaGFubmVsO1xuXHR9XG5cblx0Ly8gSWYgTWVzc2FnZUNoYW5uZWwgaXMgbm90IGF2YWlsYWJsZSBhbmQgd2UgYXJlIGluIGEgYnJvd3NlciwgaW1wbGVtZW50XG5cdC8vIGFuIGlmcmFtZSBiYXNlZCBwb2x5ZmlsbCBpbiBicm93c2VycyB0aGF0IGhhdmUgcG9zdE1lc3NhZ2UgYW5kXG5cdC8vIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIuIFRoZSBsYXR0ZXIgZXhjbHVkZXMgSUU4IGJlY2F1c2UgaXQgaGFzIGFcblx0Ly8gc3luY2hyb25vdXMgcG9zdE1lc3NhZ2UgaW1wbGVtZW50YXRpb24uXG5cdGlmIChcblx0XHR0eXBlb2YgQ2hhbm5lbCA9PT0gJ3VuZGVmaW5lZCcgJiZcblx0XHR0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJlxuXHRcdHdpbmRvdy5wb3N0TWVzc2FnZSAmJlxuXHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG5cdCkge1xuXHRcdC8qKiBAY29uc3RydWN0b3IgKi9cblx0XHRDaGFubmVsID0gZnVuY3Rpb24oKSB7XG5cdFx0XHQvLyBNYWtlIGFuIGVtcHR5LCBpbnZpc2libGUgaWZyYW1lLlxuXHRcdFx0Y29uc3QgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG5cdFx0XHRpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcblx0XHRcdGlmcmFtZS5zcmMgPSAnJztcblx0XHRcdGlmcmFtZS50aXRsZSA9ICcnO1xuXHRcdFx0ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmFwcGVuZENoaWxkKGlmcmFtZSk7XG5cdFx0XHRjb25zdCB3aW4gPSBpZnJhbWUuY29udGVudFdpbmRvdztcblx0XHRcdGNvbnN0IGRvYyA9IHdpbi5kb2N1bWVudDtcblx0XHRcdGRvYy5vcGVuKCk7XG5cdFx0XHRkb2Mud3JpdGUoJycpO1xuXHRcdFx0ZG9jLmNsb3NlKCk7XG5cdFx0XHRjb25zdCBtZXNzYWdlID0gJ2NhbGxJbW1lZGlhdGUnICsgTWF0aC5yYW5kb20oKTtcblx0XHRcdGNvbnN0IG9yaWdpbiA9IHdpbi5sb2NhdGlvbi5wcm90b2NvbCArICcvLycgKyB3aW4ubG9jYXRpb24uaG9zdDtcblx0XHRcdGNvbnN0IG9ubWVzc2FnZSA9IGZ1bmN0aW9uKGUpIHtcblx0XHRcdFx0Ly8gVmFsaWRhdGUgb3JpZ2luIGFuZCBtZXNzYWdlIHRvIG1ha2Ugc3VyZSB0aGF0IHRoaXMgbWVzc2FnZSB3YXNcblx0XHRcdFx0Ly8gaW50ZW5kZWQgZm9yIHVzLlxuXHRcdFx0XHRpZiAoZS5vcmlnaW4gIT09IG9yaWdpbiAmJiBlLmRhdGEgIT09IG1lc3NhZ2UpIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5wb3J0MS5vbm1lc3NhZ2UoKTtcblx0XHRcdH0uYmluZCh0aGlzKTtcblx0XHRcdHdpbi5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25tZXNzYWdlLCBmYWxzZSk7XG5cdFx0XHR0aGlzLnBvcnQxID0ge307XG5cdFx0XHR0aGlzLnBvcnQyID0ge1xuXHRcdFx0XHRwb3N0TWVzc2FnZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0d2luLnBvc3RNZXNzYWdlKG1lc3NhZ2UsIG9yaWdpbik7XG5cdFx0XHRcdH0sXG5cdFx0XHR9O1xuXHRcdH07XG5cdH1cblx0aWYgKHR5cGVvZiBDaGFubmVsICE9PSAndW5kZWZpbmVkJykge1xuXHRcdGNvbnN0IGNoYW5uZWwgPSBuZXcgQ2hhbm5lbCgpO1xuXHRcdC8vIFVzZSBhIGZpZm8gbGlua2VkIGxpc3QgdG8gY2FsbCBjYWxsYmFja3MgaW4gdGhlIHJpZ2h0IG9yZGVyLlxuXHRcdGxldCBoZWFkID0ge307XG5cdFx0bGV0IHRhaWwgPSBoZWFkO1xuXHRcdGNoYW5uZWwucG9ydDEub25tZXNzYWdlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRoZWFkID0gaGVhZC5uZXh0O1xuXHRcdFx0Y29uc3QgY2IgPSBoZWFkLmNiO1xuXHRcdFx0aGVhZC5jYiA9IG51bGw7XG5cdFx0XHRjYigpO1xuXHRcdH07XG5cdFx0cmV0dXJuIGZ1bmN0aW9uKGNiKSB7XG5cdFx0XHR0YWlsLm5leHQgPSB7XG5cdFx0XHRcdGNiOiBjYixcblx0XHRcdH07XG5cdFx0XHR0YWlsID0gdGFpbC5uZXh0O1xuXHRcdFx0Y2hhbm5lbC5wb3J0Mi5wb3N0TWVzc2FnZSgwKTtcblx0XHR9O1xuXHR9XG5cdC8vIEltcGxlbWVudGF0aW9uIGZvciBJRTYtODogU2NyaXB0IGVsZW1lbnRzIGZpcmUgYW4gYXN5bmNocm9ub3VzXG5cdC8vIG9ucmVhZHlzdGF0ZWNoYW5nZSBldmVudCB3aGVuIGluc2VydGVkIGludG8gdGhlIERPTS5cblx0aWYgKFxuXHRcdHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiZcblx0XHQnb25yZWFkeXN0YXRlY2hhbmdlJyBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKVxuXHQpIHtcblx0XHRyZXR1cm4gZnVuY3Rpb24oY2IpIHtcblx0XHRcdGxldCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcblx0XHRcdHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0Ly8gQ2xlYW4gdXAgYW5kIGNhbGwgdGhlIGNhbGxiYWNrLlxuXHRcdFx0XHRzY3JpcHQub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbDtcblx0XHRcdFx0c2NyaXB0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc2NyaXB0KTtcblx0XHRcdFx0c2NyaXB0ID0gbnVsbDtcblx0XHRcdFx0Y2IoKTtcblx0XHRcdFx0Y2IgPSBudWxsO1xuXHRcdFx0fTtcblx0XHRcdGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuXHRcdH07XG5cdH1cblx0Ly8gRmFsbCBiYWNrIHRvIHNldFRpbWVvdXQgd2l0aCAwLiBJbiBicm93c2VycyB0aGlzIGNyZWF0ZXMgYSBkZWxheSBvZiA1bXNcblx0Ly8gb3IgbW9yZS5cblx0cmV0dXJuIGZ1bmN0aW9uKGNiKSB7XG5cdFx0c2V0VGltZW91dChjYiwgMCk7XG5cdH07XG59O1xuXG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbiB0aGF0IGlzIG92ZXJyaWRlZCB0byBwcm90ZWN0IGNhbGxiYWNrcyB3aXRoIGVudHJ5IHBvaW50XG4gKiBtb25pdG9yIGlmIHRoZSBhcHBsaWNhdGlvbiBtb25pdG9ycyBlbnRyeSBwb2ludHMuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGNhbGxiYWNrIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGZpcmUgYXMgc29vbiBhcyBwb3NzaWJsZS5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKCl9IFRoZSB3cmFwcGVkIGNhbGxiYWNrLlxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMubmV4dFRpY2sud3JhcENhbGxiYWNrXyA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG5cdHJldHVybiBjYWxsYmFjaztcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIERpc3Bvc2FibGUgdXRpbGl0eS4gV2hlbiBpbmhlcml0ZWQgcHJvdmlkZXMgdGhlIGBkaXNwb3NlYCBmdW5jdGlvbiB0byBpdHNcbiAqIHN1YmNsYXNzLCB3aGljaCBpcyByZXNwb25zaWJsZSBmb3IgZGlzcG9zaW5nIG9mIGFueSBvYmplY3QgcmVmZXJlbmNlc1xuICogd2hlbiBhbiBpbnN0YW5jZSB3b24ndCBiZSB1c2VkIGFueW1vcmUuIFN1YmNsYXNzZXMgc2hvdWxkIG92ZXJyaWRlXG4gKiBgZGlzcG9zZUludGVybmFsYCB0byBpbXBsZW1lbnQgYW55IHNwZWNpZmljIGRpc3Bvc2luZyBsb2dpYy5cbiAqIEBjb25zdHJ1Y3RvclxuICovXG5jbGFzcyBEaXNwb3NhYmxlIHtcblx0LyoqXG5cdCAqIERpc3Bvc2FibGUgY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdC8qKlxuXHRcdCAqIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGluc3RhbmNlIGhhcyBhbHJlYWR5IGJlZW4gZGlzcG9zZWQuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZGlzcG9zZWRfID0gZmFsc2U7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLiBDYWxscyBgZGlzcG9zZUludGVybmFsYC5cblx0ICovXG5cdGRpc3Bvc2UoKSB7XG5cdFx0aWYgKCF0aGlzLmRpc3Bvc2VkXykge1xuXHRcdFx0dGhpcy5kaXNwb3NlSW50ZXJuYWwoKTtcblx0XHRcdHRoaXMuZGlzcG9zZWRfID0gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU3ViY2xhc3NlcyBzaG91bGQgb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gaW1wbGVtZW50IGFueSBzcGVjaWZpY1xuXHQgKiBkaXNwb3NpbmcgbG9naWMgKGxpa2UgY2xlYXJpbmcgcmVmZXJlbmNlcyBhbmQgY2FsbGluZyBgZGlzcG9zZWAgb24gb3RoZXJcblx0ICogZGlzcG9zYWJsZXMpLlxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge31cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoaXMgaW5zdGFuY2UgaGFzIGFscmVhZHkgYmVlbiBkaXNwb3NlZC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGlzRGlzcG9zZWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZGlzcG9zZWRfO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERpc3Bvc2FibGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogU2V0IG9mIHV0aWxpdGllcyBmb3Igb2JqZWN0IG9wZXJhdGlvbnNcbiAqL1xuY2xhc3Mgb2JqZWN0IHtcblx0LyoqXG5cdCAqIENvcGllcyBhbGwgdGhlIG1lbWJlcnMgb2YgYSBzb3VyY2Ugb2JqZWN0IHRvIGEgdGFyZ2V0IG9iamVjdC5cblx0ICogQHBhcmFtIHtPYmplY3R9IHRhcmdldCBUYXJnZXQgb2JqZWN0LlxuXHQgKiBAcGFyYW0gey4uLk9iamVjdH0gdmFyX2FyZ3MgVGhlIG9iamVjdHMgZnJvbSB3aGljaCB2YWx1ZXMgd2lsbCBiZSBjb3BpZWQuXG5cdCAqIEByZXR1cm4ge09iamVjdH0gUmV0dXJucyB0aGUgdGFyZ2V0IG9iamVjdCByZWZlcmVuY2UuXG5cdCAqL1xuXHRzdGF0aWMgbWl4aW4odGFyZ2V0LCAuLi5hcmdzKSB7XG5cdFx0bGV0IGtleTtcblx0XHRsZXQgc291cmNlO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuXHRcdFx0c291cmNlID0gYXJnc1tpXTtcblx0XHRcdC8vIFBvc3NpYmxlIHByb3RvdHlwZSBjaGFpbiBsZWFrLCBicmVha3MgMSBtZXRhbC1kb20gYW5kXG5cdFx0XHQvLyAxIG1ldGFsLWluY3JlbWVudGFsLWRvbSB0ZXN0IGlmIGd1YXJkLWZvci1pbiBydWxlIGlzIGFkZHJlc3NlZFxuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cdFx0XHRmb3IgKGtleSBpbiBzb3VyY2UpIHtcblx0XHRcdFx0dGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRhcmdldDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGFuIG9iamVjdCBiYXNlZCBvbiBpdHMgZnVsbHkgcXVhbGlmaWVkIGV4dGVybmFsIG5hbWUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBmdWxseSBxdWFsaWZpZWQgbmFtZS5cblx0ICogQHBhcmFtIHtvYmplY3Q9fSBzY29wZSBUaGUgb2JqZWN0IHdpdGhpbiB3aGljaCB0byBsb29rOyBkZWZhdWx0IGlzXG5cdCAqICAgICA8Y29kZT53aW5kb3c8L2NvZGU+LlxuXHQgKiBAcmV0dXJuIHs/fSBUaGUgdmFsdWUgKG9iamVjdCBvciBwcmltaXRpdmUpIG9yLCBpZiBub3QgZm91bmQsIHVuZGVmaW5lZC5cblx0ICovXG5cdHN0YXRpYyBnZXRPYmplY3RCeU5hbWUobmFtZSwgc2NvcGUgPSB3aW5kb3cpIHtcblx0XHRjb25zdCBwYXJ0cyA9IG5hbWUuc3BsaXQoJy4nKTtcblx0XHRyZXR1cm4gcGFydHMucmVkdWNlKChwYXJ0LCBrZXkpID0+IHBhcnRba2V5XSwgc2NvcGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdpdGggdGhlIHNhbWUga2V5cyBhcyB0aGUgZ2l2ZW4gb25lLCBidXQgd2l0aFxuXHQgKiB0aGVpciB2YWx1ZXMgc2V0IHRvIHRoZSByZXR1cm4gdmFsdWVzIG9mIHRoZSBzcGVjaWZpZWQgZnVuY3Rpb24uXG5cdCAqIEBwYXJhbSB7IU9iamVjdH0gb2JqXG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKHN0cmluZywgKil9IGZuXG5cdCAqIEByZXR1cm4geyFPYmplY3R9XG5cdCAqL1xuXHRzdGF0aWMgbWFwKG9iaiwgZm4pIHtcblx0XHRjb25zdCBtYXBwZWRPYmogPSB7fTtcblx0XHRjb25zdCBrZXlzID0gT2JqZWN0LmtleXMob2JqKTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdG1hcHBlZE9ialtrZXlzW2ldXSA9IGZuKGtleXNbaV0sIG9ialtrZXlzW2ldXSk7XG5cdFx0fVxuXHRcdHJldHVybiBtYXBwZWRPYmo7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSB0d28gZ2l2ZW4gb2JqZWN0cyBhcmUgZXF1YWwuIFRoaXMgaXMgZG9uZSB2aWEgYSBzaGFsbG93XG5cdCAqIGNoZWNrLCBpbmNsdWRpbmcgb25seSB0aGUga2V5cyBkaXJlY3RseSBjb250YWluZWQgYnkgdGhlIDIgb2JqZWN0cy5cblx0ICogQHBhcmFtIHtPYmplY3R9IG9iajFcblx0ICogQHBhcmFtIHtPYmplY3R9IG9iajJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdHN0YXRpYyBzaGFsbG93RXF1YWwob2JqMSwgb2JqMikge1xuXHRcdGlmIChvYmoxID09PSBvYmoyKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRjb25zdCBrZXlzMSA9IE9iamVjdC5rZXlzKG9iajEpO1xuXHRcdGNvbnN0IGtleXMyID0gT2JqZWN0LmtleXMob2JqMik7XG5cdFx0aWYgKGtleXMxLmxlbmd0aCAhPT0ga2V5czIubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzMS5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKG9iajFba2V5czFbaV1dICE9PSBvYmoyW2tleXMxW2ldXSkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IG9iamVjdDtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBTZXQgb2YgdXRpbGl0aWVzIGZvciBzdHJpbmcgb3BlcmF0aW9uc1xuICovXG5jbGFzcyBzdHJpbmcge1xuXHQvKipcblx0ICogQ29tcGFyZXMgdGhlIGdpdmVuIHN0cmluZ3Mgd2l0aG91dCB0YWtpbmcgdGhlIGNhc2UgaW50byBhY2NvdW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHN0cjFcblx0ICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBzdHIyXG5cdCAqIEByZXR1cm4ge251bWJlcn0gRWl0aGVyIC0xLCAwIG9yIDEsIGFjY29yZGluZyB0byBpZiB0aGUgZmlyc3Qgc3RyaW5nIGlzXG5cdCAqICAgICBcInNtYWxsZXJcIiwgZXF1YWwgb3IgXCJiaWdnZXJcIiB0aGFuIHRoZSBzZWNvbmQgZ2l2ZW4gc3RyaW5nLlxuXHQgKi9cblx0c3RhdGljIGNhc2VJbnNlbnNpdGl2ZUNvbXBhcmUoc3RyMSwgc3RyMikge1xuXHRcdGNvbnN0IHRlc3QxID0gU3RyaW5nKHN0cjEpLnRvTG93ZXJDYXNlKCk7XG5cdFx0Y29uc3QgdGVzdDIgPSBTdHJpbmcoc3RyMikudG9Mb3dlckNhc2UoKTtcblxuXHRcdGlmICh0ZXN0MSA8IHRlc3QyKSB7XG5cdFx0XHRyZXR1cm4gLTE7XG5cdFx0fSBlbHNlIGlmICh0ZXN0MSA9PT0gdGVzdDIpIHtcblx0XHRcdHJldHVybiAwO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gMTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyB0aGUgYnJlYWtpbmcgc3BhY2VzIGZyb20gdGhlIGxlZnQgYW5kIHJpZ2h0IG9mIHRoZSBzdHJpbmcgYW5kXG5cdCAqIGNvbGxhcHNlcyB0aGUgc2VxdWVuY2VzIG9mIGJyZWFraW5nIHNwYWNlcyBpbiB0aGUgbWlkZGxlIGludG8gc2luZ2xlIHNwYWNlcy5cblx0ICogVGhlIG9yaWdpbmFsIGFuZCB0aGUgcmVzdWx0IHN0cmluZ3MgcmVuZGVyIHRoZSBzYW1lIHdheSBpbiBIVE1MLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyIEEgc3RyaW5nIGluIHdoaWNoIHRvIGNvbGxhcHNlIHNwYWNlcy5cblx0ICogQHJldHVybiB7c3RyaW5nfSBDb3B5IG9mIHRoZSBzdHJpbmcgd2l0aCBub3JtYWxpemVkIGJyZWFraW5nIHNwYWNlcy5cblx0ICovXG5cdHN0YXRpYyBjb2xsYXBzZUJyZWFraW5nU3BhY2VzKHN0cikge1xuXHRcdHJldHVybiBzdHJcblx0XHRcdC5yZXBsYWNlKC9bXFx0XFxyXFxuIF0rL2csICcgJylcblx0XHRcdC5yZXBsYWNlKC9eW1xcdFxcclxcbiBdK3xbXFx0XFxyXFxuIF0rJC9nLCAnJyk7XG5cdH1cblxuXHQvKipcblx0ICogRXNjYXBlcyBjaGFyYWN0ZXJzIGluIHRoZSBzdHJpbmcgdGhhdCBhcmUgbm90IHNhZmUgdG8gdXNlIGluIGEgUmVnRXhwLlxuXHQgKiBAcGFyYW0geyp9IHN0ciBUaGUgc3RyaW5nIHRvIGVzY2FwZS4gSWYgbm90IGEgc3RyaW5nLCBpdCB3aWxsIGJlIGNhc3RlZFxuXHQgKiAgICAgdG8gb25lLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IEEgUmVnRXhwIHNhZmUsIGVzY2FwZWQgY29weSBvZiB7QGNvZGUgc30uXG5cdCAqL1xuXHRzdGF0aWMgZXNjYXBlUmVnZXgoc3RyKSB7XG5cdFx0cmV0dXJuIFN0cmluZyhzdHIpXG5cdFx0XHQucmVwbGFjZSgvKFstKClbXFxde30rPyouJF58LDojPCFcXFxcXSkvZywgJ1xcXFwkMScpXG5cdFx0XHQucmVwbGFjZSgvXFx4MDgvZywgJ1xcXFx4MDgnKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYSBzdHJpbmcgd2l0aCBhdCBsZWFzdCA2NC1iaXRzIG9mIHJhbmRvbW5lc3MuXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gQSByYW5kb20gc3RyaW5nLCBlLmcuIHNuMXM3dmI0Z2NpYy5cblx0ICovXG5cdHN0YXRpYyBnZXRSYW5kb21TdHJpbmcoKSB7XG5cdFx0Y29uc3QgeCA9IDIxNDc0ODM2NDg7XG5cdFx0cmV0dXJuIChcblx0XHRcdE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHgpLnRvU3RyaW5nKDM2KSArXG5cdFx0XHRNYXRoLmFicyhNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB4KSBeIERhdGUubm93KCkpLnRvU3RyaW5nKDM2KVxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsY3VsYXRlcyB0aGUgaGFzaGNvZGUgZm9yIGEgc3RyaW5nLiBUaGUgaGFzaGNvZGUgdmFsdWUgaXMgY29tcHV0ZWQgYnlcblx0ICogdGhlIHN1bSBhbGdvcml0aG06IHNbMF0qMzFeKG4tMSkgKyBzWzFdKjMxXihuLTIpICsgLi4uICsgc1tuLTFdLiBBIG5pY2Vcblx0ICogcHJvcGVydHkgb2YgdXNpbmcgMzEgcHJpbWUgaXMgdGhhdCB0aGUgbXVsdGlwbGljYXRpb24gY2FuIGJlIHJlcGxhY2VkIGJ5XG5cdCAqIGEgc2hpZnQgYW5kIGEgc3VidHJhY3Rpb24gZm9yIGJldHRlciBwZXJmb3JtYW5jZTogMzEqaSA9PSAoaTw8NSktaS5cblx0ICogTW9kZXJuIFZNcyBkbyB0aGlzIHNvcnQgb2Ygb3B0aW1pemF0aW9uIGF1dG9tYXRpY2FsbHkuXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSB2YWwgVGFyZ2V0IHN0cmluZy5cblx0ICogQHJldHVybiB7TnVtYmVyfSBSZXR1cm5zIHRoZSBzdHJpbmcgaGFzaGNvZGUuXG5cdCAqL1xuXHRzdGF0aWMgaGFzaENvZGUodmFsKSB7XG5cdFx0bGV0IGhhc2ggPSAwO1xuXHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSB2YWwubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGhhc2ggPSAzMSAqIGhhc2ggKyB2YWwuY2hhckNvZGVBdChpKTtcblx0XHRcdGhhc2ggJT0gMHgxMDAwMDAwMDA7XG5cdFx0fVxuXHRcdHJldHVybiBoYXNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlcGxhY2VzIGludGVydmFsIGludG8gdGhlIHN0cmluZyB3aXRoIHNwZWNpZmllZCB2YWx1ZSwgZS5nLlxuXHQgKiBgcmVwbGFjZUludGVydmFsKFwiYWJjZGVcIiwgMSwgNCwgXCJcIilgIHJldHVybnMgXCJhZVwiLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyIFRoZSBpbnB1dCBzdHJpbmcuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBzdGFydCBTdGFydCBpbnRlcnZhbCBwb3NpdGlvbiB0byBiZSByZXBsYWNlZC5cblx0ICogQHBhcmFtIHtOdW1iZXJ9IGVuZCBFbmQgaW50ZXJ2YWwgcG9zaXRpb24gdG8gYmUgcmVwbGFjZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdGhhdCByZXBsYWNlcyB0aGUgc3BlY2lmaWVkIGludGVydmFsLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRzdGF0aWMgcmVwbGFjZUludGVydmFsKHN0ciwgc3RhcnQsIGVuZCwgdmFsdWUpIHtcblx0XHRyZXR1cm4gc3RyLnN1YnN0cmluZygwLCBzdGFydCkgKyB2YWx1ZSArIHN0ci5zdWJzdHJpbmcoZW5kKTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBzdHJpbmc7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogUGFyc2VzIHRoZSBnaXZlbiB1cmkgc3RyaW5nIGludG8gYW4gb2JqZWN0LlxuICogQHBhcmFtIHsqPX0gb3B0X3VyaSBPcHRpb25hbCBzdHJpbmcgVVJJIHRvIHBhcnNlXG4gKi9cbmZ1bmN0aW9uIHBhcnNlRnJvbUFuY2hvcihvcHRfdXJpKSB7XG5cdHZhciBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuXHRsaW5rLmhyZWYgPSBvcHRfdXJpO1xuXG5cdGlmKGxpbmsucHJvdG9jb2wgPT09ICc6JyB8fCAhLzovLnRlc3QobGluay5ocmVmKSkge1xuXHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYCR7b3B0X3VyaX0gaXMgbm90IGEgdmFsaWQgVVJMYCk7XG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdGhhc2g6IGxpbmsuaGFzaCxcblx0XHRob3N0bmFtZTogbGluay5ob3N0bmFtZSxcblx0XHRwYXNzd29yZDogbGluay5wYXNzd29yZCxcblx0XHRwYXRobmFtZTogbGluay5wYXRobmFtZVswXSA9PT0gJy8nID8gbGluay5wYXRobmFtZSA6ICcvJyArIGxpbmsucGF0aG5hbWUsXG5cdFx0cG9ydDogbGluay5wb3J0LFxuXHRcdHByb3RvY29sOiBsaW5rLnByb3RvY29sLFxuXHRcdHNlYXJjaDogbGluay5zZWFyY2gsXG5cdFx0dXNlcm5hbWU6IGxpbmsudXNlcm5hbWVcblx0fTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgcGFyc2VGcm9tQW5jaG9yO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBpc0Z1bmN0aW9uIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHBhcnNlRnJvbUFuY2hvciBmcm9tICcuL3BhcnNlRnJvbUFuY2hvcic7XG5cbi8qKlxuICogUGFyc2VzIHRoZSBnaXZlbiB1cmkgc3RyaW5nIGludG8gYW4gb2JqZWN0LiBUaGUgVVJMIGZ1bmN0aW9uIHdpbGwgYmUgdXNlZFxuICogd2hlbiBwcmVzZW50LCBvdGhlcndpc2Ugd2UnbGwgZmFsbCBiYWNrIHRvIHRoZSBhbmNob3Igbm9kZSBlbGVtZW50LlxuICogQHBhcmFtIHsqPX0gb3B0X3VyaSBPcHRpb25hbCBzdHJpbmcgVVJJIHRvIHBhcnNlXG4gKi9cbmZ1bmN0aW9uIHBhcnNlKG9wdF91cmkpIHtcblx0aWYgKGlzRnVuY3Rpb24oVVJMKSAmJiBVUkwubGVuZ3RoKSB7XG5cdFx0Y29uc3QgdXJsID0gbmV3IFVSTChvcHRfdXJpKTtcblxuXHRcdC8vIFNhZmFyaSBCcm93c2VycyB3aWxsIGNhcCBwb3J0IHRvIHRoZSBtYXggMTYtYml0IHVuc2lnbmVkIGludGVnZXIgKDY1NTM1KSBpbnN0ZWFkXG5cdFx0Ly8gb2YgdGhyb3dpbmcgYSBUeXBlRXJyb3IgYXMgcGVyIHNwZWMuIEl0IHdpbGwgc3RpbGwga2VlcCB0aGUgcG9ydCBudW1iZXIgaW4gdGhlXG5cdFx0Ly8gaHJlZiBhdHRyaWJ1dGUsIHNvIHdlIGNhbiB1c2UgdGhpcyBtaXNtYXRjaCB0byByYWlzZSB0aGUgZXhwZWN0ZWQgZXhjZXB0aW9uLlxuXHRcdGlmICh1cmwucG9ydCAmJiB1cmwuaHJlZi5pbmRleE9mKHVybC5wb3J0KSA9PT0gLTEpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYCR7b3B0X3VyaX0gaXMgbm90IGEgdmFsaWQgVVJMYCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVybDtcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gcGFyc2VGcm9tQW5jaG9yKG9wdF91cmkpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IHBhcnNlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlIH0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEEgY2FjaGVkIHJlZmVyZW5jZSB0byB0aGUgY3JlYXRlIGZ1bmN0aW9uLlxuICovXG52YXIgY3JlYXRlID0gT2JqZWN0LmNyZWF0ZTtcblxuLyoqXG4gKiBDYXNlIGluc2Vuc2l0aXZlIHN0cmluZyBNdWx0aW1hcCBpbXBsZW1lbnRhdGlvbi4gQWxsb3dzIG11bHRpcGxlIHZhbHVlcyBmb3JcbiAqIHRoZSBzYW1lIGtleSBuYW1lLlxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIE11bHRpTWFwIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cdFx0dGhpcy5rZXlzID0gY3JlYXRlKG51bGwpO1xuXHRcdHRoaXMudmFsdWVzID0gY3JlYXRlKG51bGwpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdmFsdWUgdG8gYSBrZXkgbmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHBhcmFtIHsqfSB2YWx1ZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRhZGQobmFtZSwgdmFsdWUpIHtcblx0XHR0aGlzLmtleXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IG5hbWU7XG5cdFx0dGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV0gfHwgW107XG5cdFx0dGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXS5wdXNoKHZhbHVlKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhcnMgbWFwIG5hbWVzIGFuZCB2YWx1ZXMuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGNsZWFyKCkge1xuXHRcdHRoaXMua2V5cyA9IGNyZWF0ZShudWxsKTtcblx0XHR0aGlzLnZhbHVlcyA9IGNyZWF0ZShudWxsKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgbWFwIGNvbnRhaW5zIGEgdmFsdWUgdG8gdGhlIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRjb250YWlucyhuYW1lKSB7XG5cdFx0cmV0dXJuIG5hbWUudG9Mb3dlckNhc2UoKSBpbiB0aGlzLnZhbHVlcztcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHRoaXMudmFsdWVzID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgYE11bHRpTWFwYCBpbnN0YW5jZSBmcm9tIHRoZSBnaXZlbiBvYmplY3QuXG5cdCAqIEBwYXJhbSB7IU9iamVjdH0gb2JqXG5cdCAqIEByZXR1cm4geyFNdWx0aU1hcH1cblx0ICovXG5cdHN0YXRpYyBmcm9tT2JqZWN0KG9iaikge1xuXHRcdHZhciBtYXAgPSBuZXcgTXVsdGlNYXAoKTtcblx0XHR2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRtYXAuc2V0KGtleXNbaV0sIG9ialtrZXlzW2ldXSk7XG5cdFx0fVxuXHRcdHJldHVybiBtYXA7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgZmlyc3QgYWRkZWQgdmFsdWUgZnJvbSBhIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAcmV0dXJuIHsqfVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRnZXQobmFtZSkge1xuXHRcdHZhciB2YWx1ZXMgPSB0aGlzLnZhbHVlc1tuYW1lLnRvTG93ZXJDYXNlKCldO1xuXHRcdGlmICh2YWx1ZXMpIHtcblx0XHRcdHJldHVybiB2YWx1ZXNbMF07XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYWxsIHZhbHVlcyBmcm9tIGEga2V5IG5hbWUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG5cdCAqIEByZXR1cm4ge0FycmF5LjwqPn1cblx0ICovXG5cdGdldEFsbChuYW1lKSB7XG5cdFx0cmV0dXJuIHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV07XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0cnVlIGlmIHRoZSBtYXAgaXMgZW1wdHksIGZhbHNlIG90aGVyd2lzZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGlzRW1wdHkoKSB7XG5cdFx0cmV0dXJuIHRoaXMuc2l6ZSgpID09PSAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYXJyYXkgb2Yga2V5IG5hbWVzLlxuXHQgKiBAcmV0dXJuIHtBcnJheS48c3RyaW5nPn1cblx0ICovXG5cdG5hbWVzKCkge1xuXHRcdHJldHVybiBPYmplY3Qua2V5cyh0aGlzLnZhbHVlcykubWFwKChrZXkpID0+IHRoaXMua2V5c1trZXldKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCB2YWx1ZXMgZnJvbSBhIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRyZW1vdmUobmFtZSkge1xuXHRcdGRlbGV0ZSB0aGlzLmtleXNbbmFtZS50b0xvd2VyQ2FzZSgpXTtcblx0XHRkZWxldGUgdGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB2YWx1ZSBvZiBhIGtleSBuYW1lLiBSZWxldmFudCB0byByZXBsYWNlIHRoZSBjdXJyZW50IHZhbHVlcyB3aXRoXG5cdCAqIGEgbmV3IG9uZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHBhcmFtIHsqfSB2YWx1ZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXQobmFtZSwgdmFsdWUpIHtcblx0XHR0aGlzLmtleXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IG5hbWU7XG5cdFx0dGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IFt2YWx1ZV07XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc2l6ZSBvZiB0aGUgbWFwIGtleSBuYW1lcy5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0c2l6ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5uYW1lcygpLmxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBwYXJzZWQgdmFsdWVzIGFzIGEgc3RyaW5nLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy52YWx1ZXMpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE11bHRpTWFwO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBhcnJheSB9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBHZW5lcmljIHRyZWUgbm9kZSBkYXRhIHN0cnVjdHVyZSB3aXRoIGFyYml0cmFyeSBudW1iZXIgb2YgY2hpbGQgbm9kZXMuXG4gKiBAcGFyYW0ge1Z9IHZhbHVlIFZhbHVlLlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmNsYXNzIFRyZWVOb2RlIHtcblxuXHRjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuXHRcdC8qKlxuXHRcdCAqIFRoZSB2YWx1ZS5cblx0XHQgKiBAcHJpdmF0ZSB7Vn1cblx0XHQgKi9cblx0XHR0aGlzLnZhbHVlXyA9IHZhbHVlO1xuXG5cdFx0LyoqXG5cdFx0ICogUmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgbm9kZSBvciBudWxsIGlmIGl0IGhhcyBubyBwYXJlbnQuXG5cdFx0ICogQHByaXZhdGUge1RyZWVOb2RlfVxuXHRcdCAqL1xuXHRcdHRoaXMucGFyZW50XyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBDaGlsZCBub2RlcyBvciBudWxsIGluIGNhc2Ugb2YgbGVhZiBub2RlLlxuXHRcdCAqIEBwcml2YXRlIHtBcnJheTwhVHJlZU5vZGU+fVxuXHRcdCAqL1xuXHRcdHRoaXMuY2hpbGRyZW5fID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBcHBlbmRzIGEgY2hpbGQgbm9kZSB0byB0aGlzIG5vZGUuXG5cdCAqIEBwYXJhbSB7IVRyZWVOb2RlfSBjaGlsZCBPcnBoYW4gY2hpbGQgbm9kZS5cblx0ICovXG5cdGFkZENoaWxkKGNoaWxkKSB7XG5cdFx0YXNzZXJ0Q2hpbGRIYXNOb1BhcmVudChjaGlsZCk7XG5cdFx0Y2hpbGQuc2V0UGFyZW50KHRoaXMpO1xuXHRcdHRoaXMuY2hpbGRyZW5fID0gdGhpcy5jaGlsZHJlbl8gfHwgW107XG5cdFx0dGhpcy5jaGlsZHJlbl8ucHVzaChjaGlsZCk7XG5cdH1cblxuXHQvKipcblx0ICogVGVsbHMgd2hldGhlciB0aGlzIG5vZGUgaXMgdGhlIGFuY2VzdG9yIG9mIHRoZSBnaXZlbiBub2RlLlxuXHQgKiBAcGFyYW0geyFUcmVlTm9kZX0gbm9kZSBBIG5vZGUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdGhpcyBub2RlIGlzIHRoZSBhbmNlc3RvciBvZiB7QGNvZGUgbm9kZX0uXG5cdCAqL1xuXHRjb250YWlucyhub2RlKSB7XG5cdFx0bGV0IGN1cnJlbnQgPSBub2RlLmdldFBhcmVudCgpO1xuXHRcdHdoaWxlIChjdXJyZW50KSB7XG5cdFx0XHRpZiAoY3VycmVudCA9PT0gdGhpcykge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdGN1cnJlbnQgPSBjdXJyZW50LmdldFBhcmVudCgpO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7IUFycmF5PFRyZWVOb2RlPn0gQWxsIGFuY2VzdG9yIG5vZGVzIGluIGJvdHRvbS11cCBvcmRlci5cblx0ICovXG5cdGdldEFuY2VzdG9ycygpIHtcblx0XHRsZXQgYW5jZXN0b3JzID0gW107XG5cdFx0bGV0IG5vZGUgPSB0aGlzLmdldFBhcmVudCgpO1xuXHRcdHdoaWxlIChub2RlKSB7XG5cdFx0XHRhbmNlc3RvcnMucHVzaChub2RlKTtcblx0XHRcdG5vZGUgPSBub2RlLmdldFBhcmVudCgpO1xuXHRcdH1cblx0XHRyZXR1cm4gYW5jZXN0b3JzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGNoaWxkIG5vZGUgb2YgdGhpcyBub2RlIGF0IHRoZSBnaXZlbiBpbmRleC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IENoaWxkIGluZGV4LlxuXHQgKiBAcmV0dXJuIHs/VHJlZU5vZGV9IFRoZSBub2RlIGF0IHRoZSBnaXZlbiBpbmRleFxuXHQgKiBvciBudWxsIGlmIG5vdCBmb3VuZC5cblx0ICovXG5cdGdldENoaWxkQXQoaW5kZXgpIHtcblx0XHRyZXR1cm4gdGhpcy5nZXRDaGlsZHJlbigpW2luZGV4XSB8fCBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4gez9BcnJheTwhVHJlZU5vZGU+fSBDaGlsZCBub2RlcyBvciBudWxsIGluIGNhc2Ugb2YgbGVhZiBub2RlLlxuXHQgKi9cblx0Z2V0Q2hpbGRyZW4oKSB7XG5cdFx0cmV0dXJuIHRoaXMuY2hpbGRyZW5fIHx8IFRyZWVOb2RlLkVNUFRZX0FSUkFZO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBjaGlsZHJlbi5cblx0ICovXG5cdGdldENoaWxkQ291bnQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0Q2hpbGRyZW4oKS5sZW5ndGg7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGFuY2VzdG9ycyBvZiB0aGUgbm9kZS5cblx0ICovXG5cdGdldERlcHRoKCkge1xuXHRcdGxldCBkZXB0aCA9IDA7XG5cdFx0bGV0IG5vZGUgPSB0aGlzO1xuXHRcdHdoaWxlIChub2RlLmdldFBhcmVudCgpKSB7XG5cdFx0XHRkZXB0aCsrO1xuXHRcdFx0bm9kZSA9IG5vZGUuZ2V0UGFyZW50KCk7XG5cdFx0fVxuXHRcdHJldHVybiBkZXB0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHs/VHJlZU5vZGV9IFBhcmVudCBub2RlIG9yIG51bGwgaWYgaXQgaGFzIG5vIHBhcmVudC5cblx0ICovXG5cdGdldFBhcmVudCgpIHtcblx0XHRyZXR1cm4gdGhpcy5wYXJlbnRfO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4geyFUcmVlTm9kZX0gVGhlIHJvb3Qgb2YgdGhlIHRyZWUgc3RydWN0dXJlLCBpLmUuIHRoZSBmYXJ0aGVzdFxuXHQgKiBhbmNlc3RvciBvZiB0aGUgbm9kZSBvciB0aGUgbm9kZSBpdHNlbGYgaWYgaXQgaGFzIG5vIHBhcmVudHMuXG5cdCAqL1xuXHRnZXRSb290KCkge1xuXHRcdGxldCByb290ID0gdGhpcztcblx0XHR3aGlsZSAocm9vdC5nZXRQYXJlbnQoKSkge1xuXHRcdFx0cm9vdCA9IHJvb3QuZ2V0UGFyZW50KCk7XG5cdFx0fVxuXHRcdHJldHVybiByb290O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHZhbHVlLlxuXHQgKiBAcmV0dXJuIHtWfSBUaGUgdmFsdWUuXG5cdCAqL1xuXHRnZXRWYWx1ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy52YWx1ZV87XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB0aGUgbm9kZSBpcyBhIGxlYWYgbm9kZS5cblx0ICovXG5cdGlzTGVhZigpIHtcblx0XHRyZXR1cm4gIXRoaXMuZ2V0Q2hpbGRDb3VudCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGdpdmVuIGNoaWxkIG5vZGUgb2YgdGhpcyBub2RlLlxuXHQgKiBAcGFyYW0ge1RyZWVOb2RlfSBjaGlsZCBUaGUgbm9kZSB0byByZW1vdmUuXG5cdCAqIEByZXR1cm4ge1RyZWVOb2RlfSBUaGUgcmVtb3ZlZCBub2RlIGlmIGFueSwgbnVsbCBvdGhlcndpc2UuXG5cdCAqL1xuXHRyZW1vdmVDaGlsZChjaGlsZCkge1xuXHRcdGlmIChhcnJheS5yZW1vdmUodGhpcy5nZXRDaGlsZHJlbigpLCBjaGlsZCkpIHtcblx0XHRcdHJldHVybiBjaGlsZDtcblx0XHR9XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgcGFyZW50IG5vZGUgb2YgdGhpcyBub2RlLiBUaGUgY2FsbGVycyBtdXN0IGVuc3VyZSB0aGF0IHRoZVxuXHQgKiBwYXJlbnQgbm9kZSBhbmQgb25seSB0aGF0IGhhcyB0aGlzIG5vZGUgYW1vbmcgaXRzIGNoaWxkcmVuLlxuXHQgKiBAcGFyYW0ge1RyZWVOb2RlfSBwYXJlbnQgVGhlIHBhcmVudCB0byBzZXQuIElmIG51bGwsIHRoZSBub2RlIHdpbGwgYmVcblx0ICogZGV0YWNoZWQgZnJvbSB0aGUgdHJlZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0c2V0UGFyZW50KHBhcmVudCkge1xuXHRcdHRoaXMucGFyZW50XyA9IHBhcmVudDtcblx0fVxuXG5cdC8qKlxuXHQgKiBUcmF2ZXJzZXMgdGhlIHN1YnRyZWUuIFRoZSBmaXJzdCBjYWxsYmFjayBzdGFydHMgd2l0aCB0aGlzIG5vZGUsXG5cdCAqIGFuZCB2aXNpdHMgdGhlIGRlc2NlbmRhbnQgbm9kZXMgZGVwdGgtZmlyc3QsIGluIHByZW9yZGVyLlxuXHQgKiBUaGUgc2Vjb25kIGNhbGxiYWNrLCBzdGFydHMgd2l0aCBkZWVwZXN0IGNoaWxkIHRoZW4gdmlzaXRzXG5cdCAqIHRoZSBhbmNlc3RvciBub2RlcyBkZXB0aC1maXJzdCwgaW4gcG9zdG9yZGVyLiBFLmcuXG5cdCAqXG5cdCAqICBcdCBBXG5cdCAqICAgIC8gXFxcblx0ICogICBCICAgQ1xuXHQgKiAgLyAgIC8gXFxcblx0ICogRCAgIEUgICBGXG5cdCAqXG5cdCAqIHByZW9yZGVyIC0+IFsnQScsICdCJywgJ0QnLCAnQycsICdFJywgJ0YnXVxuXHQgKiBwb3N0b3JkZXIgLT4gWydEJywgJ0InLCAnRScsICdGJywgJ0MnLCAnQSddXG5cdCAqXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb249fSBvcHRfcHJlb3JkZXJGbiBUaGUgY2FsbGJhY2sgdG8gZXhlY3V0ZSB3aGVuIHZpc2l0aW5nIGEgbm9kZS5cblx0ICogQHBhcmFtIHtmdW5jdGlvbj19IG9wdF9wb3N0b3JkZXJGbiBUaGUgY2FsbGJhY2sgdG8gZXhlY3V0ZSBiZWZvcmUgbGVhdmluZyBhIG5vZGUuXG5cdCAqL1xuXHR0cmF2ZXJzZShvcHRfcHJlb3JkZXJGbiwgb3B0X3Bvc3RvcmRlckZuKSB7XG5cdFx0aWYgKG9wdF9wcmVvcmRlckZuKSB7XG5cdFx0XHRvcHRfcHJlb3JkZXJGbih0aGlzKTtcblx0XHR9XG5cdFx0dGhpcy5nZXRDaGlsZHJlbigpLmZvckVhY2goKGNoaWxkKSA9PiBjaGlsZC50cmF2ZXJzZShvcHRfcHJlb3JkZXJGbiwgb3B0X3Bvc3RvcmRlckZuKSk7XG5cdFx0aWYgKG9wdF9wb3N0b3JkZXJGbikge1xuXHRcdFx0b3B0X3Bvc3RvcmRlckZuKHRoaXMpO1xuXHRcdH1cblx0fVxuXG59XG5cbi8qKlxuICogQ29uc3RhbnQgZm9yIGVtcHR5IGFycmF5IHRvIGF2b2lkIHVubmVjZXNzYXJ5IGFsbG9jYXRpb25zLlxuICogQHByaXZhdGVcbiAqL1xuVHJlZU5vZGUuRU1QVFlfQVJSQVkgPSBbXTtcblxuLyoqXG4gKiBBc3NlcnRzIHRoYXQgY2hpbGQgaGFzIG5vIHBhcmVudC5cbiAqIEBwYXJhbSB7VHJlZU5vZGV9IGNoaWxkIEEgY2hpbGQuXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBhc3NlcnRDaGlsZEhhc05vUGFyZW50ID0gZnVuY3Rpb24oY2hpbGQpIHtcblx0aWYgKGNoaWxkLmdldFBhcmVudCgpKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYWRkIGNoaWxkIHdpdGggcGFyZW50LicpO1xuXHR9XG59O1xuXG5leHBvcnQgZGVmYXVsdCBUcmVlTm9kZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaXNEZWYsIHN0cmluZyB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBwYXJzZSBmcm9tICcuL3BhcnNlJztcbmltcG9ydCB7IE11bHRpTWFwIH0gZnJvbSAnbWV0YWwtc3RydWN0cyc7XG5cbnZhciBwYXJzZUZuXyA9IHBhcnNlO1xuXG5jbGFzcyBVcmkge1xuXG5cdC8qKlxuXHQgKiBUaGlzIGNsYXNzIGNvbnRhaW5zIHNldHRlcnMgYW5kIGdldHRlcnMgZm9yIHRoZSBwYXJ0cyBvZiB0aGUgVVJJLlxuXHQgKiBUaGUgZm9sbG93aW5nIGZpZ3VyZSBkaXNwbGF5cyBhbiBleGFtcGxlIFVSSXMgYW5kIHRoZWlyIGNvbXBvbmVudCBwYXJ0cy5cblx0ICpcblx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aFxuXHQgKlx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilIzilIDilIDilIDilLTilIDilIDilIDilIDilJBcblx0ICpcdCAgYWJjOi8vZXhhbXBsZS5jb206MTIzL3BhdGgvZGF0YT9rZXk9dmFsdWUjZnJhZ2lkMVxuXHQgKlx0ICDilJTilKzilJggICDilJTilIDilIDilIDilIDilKzilIDilIDilIDilIDilJgg4pSU4pSs4pSYICAgICAgICAgICDilJTilIDilIDilIDilKzilIDilIDilIDilJgg4pSU4pSA4pSA4pSs4pSA4pSA4pSYXG5cdCAqIHByb3RvY29sICBob3N0bmFtZSAgcG9ydCAgICAgICAgICAgIHNlYXJjaCAgICBoYXNoXG5cdCAqICAgICAgICAgIOKUlOKUgOKUgOKUgOKUgOKUgOKUgOKUrOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUmFxuXHQgKiAgICAgICAgICAgICAgICBob3N0XG5cdCAqXG5cdCAqIEBwYXJhbSB7Kj19IG9wdF91cmkgT3B0aW9uYWwgc3RyaW5nIFVSSSB0byBwYXJzZVxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKG9wdF91cmkgPSAnJykge1xuXHRcdHRoaXMudXJsID0gVXJpLnBhcnNlKHRoaXMubWF5YmVBZGRQcm90b2NvbEFuZEhvc3RuYW1lXyhvcHRfdXJpKSk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBwYXJhbWV0ZXJzIHRvIHVyaSBmcm9tIGEgPGNvZGU+TXVsdGlNYXA8L2NvZGU+IGFzIHNvdXJjZS5cblx0ICogQHBhcmFtIHtNdWx0aU1hcH0gbXVsdGltYXAgVGhlIDxjb2RlPk11bHRpTWFwPC9jb2RlPiBjb250YWluaW5nIHRoZVxuXHQgKiAgIHBhcmFtZXRlcnMuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkUGFyYW1ldGVyc0Zyb21NdWx0aU1hcChtdWx0aW1hcCkge1xuXHRcdG11bHRpbWFwLm5hbWVzKCkuZm9yRWFjaCgobmFtZSkgPT4ge1xuXHRcdFx0bXVsdGltYXAuZ2V0QWxsKG5hbWUpLmZvckVhY2goKHZhbHVlKSA9PiB7XG5cdFx0XHRcdHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyB0aGUgdmFsdWUgb2YgdGhlIG5hbWVkIHF1ZXJ5IHBhcmFtZXRlcnMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIHBhcmFtZXRlciB0byBzZXQuXG5cdCAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG5ldyB2YWx1ZS4gV2lsbCBiZSBleHBsaWNpdGx5IGNhc3RlZCB0byBTdHJpbmcuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZFBhcmFtZXRlclZhbHVlKG5hbWUsIHZhbHVlKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdGlmIChpc0RlZih2YWx1ZSkpIHtcblx0XHRcdHZhbHVlID0gU3RyaW5nKHZhbHVlKTtcblx0XHR9XG5cdFx0dGhpcy5xdWVyeS5hZGQobmFtZSwgdmFsdWUpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIHZhbHVlcyBvZiB0aGUgbmFtZWQgcXVlcnkgcGFyYW1ldGVyLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZFBhcmFtZXRlclZhbHVlcyhuYW1lLCB2YWx1ZXMpIHtcblx0XHR2YWx1ZXMuZm9yRWFjaCgodmFsdWUpID0+IHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBFbnN1cmVzIHF1ZXJ5IGludGVybmFsIG1hcCBpcyBpbml0aWFsaXplZCBhbmQgc3luY2VkIHdpdGggaW5pdGlhbCB2YWx1ZVxuXHQgKiBleHRyYWN0ZWQgZnJvbSBVUkkgc2VhcmNoIHBhcnQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCkge1xuXHRcdGlmICh0aGlzLnF1ZXJ5KSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMucXVlcnkgPSBuZXcgTXVsdGlNYXAoKTtcblx0XHR2YXIgc2VhcmNoID0gdGhpcy51cmwuc2VhcmNoO1xuXHRcdGlmIChzZWFyY2gpIHtcblx0XHRcdHNlYXJjaC5zdWJzdHJpbmcoMSkuc3BsaXQoJyYnKS5mb3JFYWNoKChwYXJhbSkgPT4ge1xuXHRcdFx0XHR2YXIgW2tleSwgdmFsdWVdID0gcGFyYW0uc3BsaXQoJz0nKTtcblx0XHRcdFx0aWYgKGlzRGVmKHZhbHVlKSkge1xuXHRcdFx0XHRcdHZhbHVlID0gVXJpLnVybERlY29kZSh2YWx1ZSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5hZGRQYXJhbWV0ZXJWYWx1ZShrZXksIHZhbHVlKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBoYXNoIHBhcnQgb2YgdXJpLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRIYXNoKCkge1xuXHRcdHJldHVybiB0aGlzLnVybC5oYXNoIHx8ICcnO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGhvc3QgcGFydCBvZiB1cmkuIEUuZy4gPGNvZGU+W2hvc3RuYW1lXTpbcG9ydF08L2NvZGU+LlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRIb3N0KCkge1xuXHRcdHZhciBob3N0ID0gdGhpcy5nZXRIb3N0bmFtZSgpO1xuXHRcdGlmIChob3N0KSB7XG5cdFx0XHR2YXIgcG9ydCA9IHRoaXMuZ2V0UG9ydCgpO1xuXHRcdFx0aWYgKHBvcnQgJiYgcG9ydCAhPT0gJzgwJykge1xuXHRcdFx0XHRob3N0ICs9ICc6JyArIHBvcnQ7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBob3N0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGhvc3RuYW1lIHBhcnQgb2YgdXJpIHdpdGhvdXQgcHJvdG9jb2wgYW5kIHBvcnQuXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldEhvc3RuYW1lKCkge1xuXHRcdHZhciBob3N0bmFtZSA9IHRoaXMudXJsLmhvc3RuYW1lO1xuXHRcdGlmIChob3N0bmFtZSA9PT0gVXJpLkhPU1ROQU1FX1BMQUNFSE9MREVSKSB7XG5cdFx0XHRyZXR1cm4gJyc7XG5cdFx0fVxuXHRcdHJldHVybiBob3N0bmFtZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBvcmlnaW4gcGFydCBvZiB1cmkuIEUuZy4gPGNvZGU+aHR0cDovL1tob3N0bmFtZV06W3BvcnRdPC9jb2RlPi5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0T3JpZ2luKCkge1xuXHRcdHZhciBob3N0ID0gdGhpcy5nZXRIb3N0KCk7XG5cdFx0aWYgKGhvc3QpIHtcblx0XHRcdHJldHVybiB0aGlzLmdldFByb3RvY29sKCkgKyAnLy8nICsgaG9zdDtcblx0XHR9XG5cdFx0cmV0dXJuICcnO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGZpcnN0IHZhbHVlIGZvciBhIGdpdmVuIHBhcmFtZXRlciBvciB1bmRlZmluZWQgaWYgdGhlIGdpdmVuXG5cdCAqIHBhcmFtZXRlciBuYW1lIGRvZXMgbm90IGFwcGVhciBpbiB0aGUgcXVlcnkgc3RyaW5nLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGFyYW1OYW1lIFVuZXNjYXBlZCBwYXJhbWV0ZXIgbmFtZS5cblx0ICogQHJldHVybiB7c3RyaW5nfHVuZGVmaW5lZH0gVGhlIGZpcnN0IHZhbHVlIGZvciBhIGdpdmVuIHBhcmFtZXRlciBvclxuXHQgKiAgIHVuZGVmaW5lZCBpZiB0aGUgZ2l2ZW4gcGFyYW1ldGVyIG5hbWUgZG9lcyBub3QgYXBwZWFyIGluIHRoZSBxdWVyeVxuXHQgKiAgIHN0cmluZy5cblx0ICovXG5cdGdldFBhcmFtZXRlclZhbHVlKG5hbWUpIHtcblx0XHR0aGlzLmVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCk7XG5cdFx0cmV0dXJuIHRoaXMucXVlcnkuZ2V0KG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHZhbHVlPGI+czwvYj4gZm9yIGEgZ2l2ZW4gcGFyYW1ldGVyIGFzIGEgbGlzdCBvZiBkZWNvZGVkXG5cdCAqIHF1ZXJ5IHBhcmFtZXRlciB2YWx1ZXMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBwYXJhbWV0ZXIgdG8gZ2V0IHZhbHVlcyBmb3IuXG5cdCAqIEByZXR1cm4geyFBcnJheTw/Pn0gVGhlIHZhbHVlcyBmb3IgYSBnaXZlbiBwYXJhbWV0ZXIgYXMgYSBsaXN0IG9mIGRlY29kZWRcblx0ICogICBxdWVyeSBwYXJhbWV0ZXIgdmFsdWVzLlxuXHQgKi9cblx0Z2V0UGFyYW1ldGVyVmFsdWVzKG5hbWUpIHtcblx0XHR0aGlzLmVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCk7XG5cdFx0cmV0dXJuIHRoaXMucXVlcnkuZ2V0QWxsKG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIG5hbWU8Yj5zPC9iPiBvZiB0aGUgcGFyYW1ldGVycy5cblx0ICogQHJldHVybiB7IUFycmF5PHN0cmluZz59IFRoZSBuYW1lcyBmb3IgdGhlIHBhcmFtZXRlcnMgYXMgYSBsaXN0IG9mXG5cdCAqICAgc3RyaW5ncy5cblx0ICovXG5cdGdldFBhcmFtZXRlck5hbWVzKCkge1xuXHRcdHRoaXMuZW5zdXJlUXVlcnlJbml0aWFsaXplZF8oKTtcblx0XHRyZXR1cm4gdGhpcy5xdWVyeS5uYW1lcygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGZ1bmN0aW9uIGN1cnJlbnRseSBiZWluZyB1c2VkIHRvIHBhcnNlIFVSSXMuXG5cdCAqIEByZXR1cm4geyFmdW5jdGlvbigpfVxuXHQgKi9cblx0c3RhdGljIGdldFBhcnNlRm4oKSB7XG5cdFx0cmV0dXJuIHBhcnNlRm5fO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHBhdGhuYW1lIHBhcnQgb2YgdXJpLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRQYXRobmFtZSgpIHtcblx0XHRyZXR1cm4gdGhpcy51cmwucGF0aG5hbWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcG9ydCBudW1iZXIgcGFydCBvZiB1cmkgYXMgc3RyaW5nLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRQb3J0KCkge1xuXHRcdHJldHVybiB0aGlzLnVybC5wb3J0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHByb3RvY29sIHBhcnQgb2YgdXJpLiBFLmcuIDxjb2RlPmh0dHA6PC9jb2RlPi5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0UHJvdG9jb2woKSB7XG5cdFx0cmV0dXJuIHRoaXMudXJsLnByb3RvY29sO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHNlYXJjaCBwYXJ0IG9mIHVyaS4gU2VhcmNoIHZhbHVlIGlzIHJldHJpZXZlZCBmcm9tIHF1ZXJ5XG5cdCAqIHBhcmFtZXRlcnMuXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldFNlYXJjaCgpIHtcblx0XHR2YXIgc2VhcmNoID0gJyc7XG5cdFx0dmFyIHF1ZXJ5c3RyaW5nID0gJyc7XG5cdFx0dGhpcy5nZXRQYXJhbWV0ZXJOYW1lcygpLmZvckVhY2goKG5hbWUpID0+IHtcblx0XHRcdHRoaXMuZ2V0UGFyYW1ldGVyVmFsdWVzKG5hbWUpLmZvckVhY2goKHZhbHVlKSA9PiB7XG5cdFx0XHRcdHF1ZXJ5c3RyaW5nICs9IG5hbWU7XG5cdFx0XHRcdGlmIChpc0RlZih2YWx1ZSkpIHtcblx0XHRcdFx0XHRxdWVyeXN0cmluZyArPSAnPScgKyBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHF1ZXJ5c3RyaW5nICs9ICcmJztcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHRcdHF1ZXJ5c3RyaW5nID0gcXVlcnlzdHJpbmcuc2xpY2UoMCwgLTEpO1xuXHRcdGlmIChxdWVyeXN0cmluZykge1xuXHRcdFx0c2VhcmNoICs9ICc/JyArIHF1ZXJ5c3RyaW5nO1xuXHRcdH1cblx0XHRyZXR1cm4gc2VhcmNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB1cmkgY29udGFpbnMgdGhlIHBhcmFtZXRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGhhc1BhcmFtZXRlcihuYW1lKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdHJldHVybiB0aGlzLnF1ZXJ5LmNvbnRhaW5zKG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIHRoaXMgVVJMIHVuaXF1ZSBieSBhZGRpbmcgYSByYW5kb20gcGFyYW0gdG8gaXQuIFVzZWZ1bCBmb3IgYXZvaWRpbmdcblx0ICogY2FjaGUuXG5cdCAqL1xuXHRtYWtlVW5pcXVlKCkge1xuXHRcdHRoaXMuc2V0UGFyYW1ldGVyVmFsdWUoVXJpLlJBTkRPTV9QQVJBTSwgc3RyaW5nLmdldFJhbmRvbVN0cmluZygpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBhZGRzIHByb3RvY29sIGFuZCBhIGhvc3RuYW1lIHBsYWNlaG9sZGVyIG9uIGEgcGFyaWFsIFVSSSBpZiBuZWVkZWQuXG5cdCAqIFJlbGV2ZW50IGZvciBjb21wYXRpYmlsaXR5IHdpdGggPGNvZGU+VVJMPC9jb2RlPiBuYXRpdmUgb2JqZWN0LlxuXHQgKiBAcGFyYW0ge3N0cmluZz19IG9wdF91cmlcblx0ICogQHJldHVybiB7c3RyaW5nfSBVUkkgd2l0aCBwcm90b2NvbCBhbmQgaG9zdG5hbWUgcGxhY2Vob2xkZXIuXG5cdCAqL1xuXHRtYXliZUFkZFByb3RvY29sQW5kSG9zdG5hbWVfKG9wdF91cmkpIHtcblx0XHR2YXIgdXJsID0gb3B0X3VyaTtcblx0XHRpZiAob3B0X3VyaS5pbmRleE9mKCc6Ly8nKSA9PT0gLTEgJiZcblx0XHRcdG9wdF91cmkuaW5kZXhPZignamF2YXNjcmlwdDonKSAhPT0gMCkgeyAvLyBqc2hpbnQgaWdub3JlOmxpbmVcblxuXHRcdFx0dXJsID0gVXJpLkRFRkFVTFRfUFJPVE9DT0w7XG5cdFx0XHRpZiAob3B0X3VyaVswXSAhPT0gJy8nIHx8IG9wdF91cmlbMV0gIT09ICcvJykge1xuXHRcdFx0XHR1cmwgKz0gJy8vJztcblx0XHRcdH1cblxuXHRcdFx0c3dpdGNoIChvcHRfdXJpLmNoYXJBdCgwKSkge1xuXHRcdFx0XHRjYXNlICcuJzpcblx0XHRcdFx0Y2FzZSAnPyc6XG5cdFx0XHRcdGNhc2UgJyMnOlxuXHRcdFx0XHRcdHVybCArPSBVcmkuSE9TVE5BTUVfUExBQ0VIT0xERVI7XG5cdFx0XHRcdFx0dXJsICs9ICcvJztcblx0XHRcdFx0XHR1cmwgKz0gb3B0X3VyaTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnJzpcblx0XHRcdFx0Y2FzZSAnLyc6XG5cdFx0XHRcdFx0aWYgKG9wdF91cmlbMV0gIT09ICcvJykge1xuXHRcdFx0XHRcdFx0dXJsICs9IFVyaS5IT1NUTkFNRV9QTEFDRUhPTERFUjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dXJsICs9IG9wdF91cmk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0dXJsICs9IG9wdF91cmk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB1cmw7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2VzIHRoZSBnaXZlbiB1cmkgc3RyaW5nIGludG8gYW4gb2JqZWN0LlxuXHQgKiBAcGFyYW0geyo9fSBvcHRfdXJpIE9wdGlvbmFsIHN0cmluZyBVUkkgdG8gcGFyc2Vcblx0ICovXG5cdHN0YXRpYyBwYXJzZShvcHRfdXJpKSB7XG5cdFx0cmV0dXJuIHBhcnNlRm5fKG9wdF91cmkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIG5hbWVkIHF1ZXJ5IHBhcmFtZXRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIHBhcmFtZXRlciB0byByZW1vdmUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHJlbW92ZVBhcmFtZXRlcihuYW1lKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdHRoaXMucXVlcnkucmVtb3ZlKG5hbWUpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdW5pcXVlbmVzcyBwYXJhbWV0ZXIgb2YgdGhlIHVyaS5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0cmVtb3ZlVW5pcXVlKCkge1xuXHRcdHRoaXMucmVtb3ZlUGFyYW1ldGVyKFVyaS5SQU5ET01fUEFSQU0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGhhc2guXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBoYXNoXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldEhhc2goaGFzaCkge1xuXHRcdHRoaXMudXJsLmhhc2ggPSBoYXNoO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGhvc3RuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaG9zdG5hbWVcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0c2V0SG9zdG5hbWUoaG9zdG5hbWUpIHtcblx0XHR0aGlzLnVybC5ob3N0bmFtZSA9IGhvc3RuYW1lO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHZhbHVlIG9mIHRoZSBuYW1lZCBxdWVyeSBwYXJhbWV0ZXJzLCBjbGVhcmluZyBwcmV2aW91cyB2YWx1ZXNcblx0ICogZm9yIHRoYXQga2V5LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFBhcmFtZXRlclZhbHVlKG5hbWUsIHZhbHVlKSB7XG5cdFx0dGhpcy5yZW1vdmVQYXJhbWV0ZXIobmFtZSk7XG5cdFx0dGhpcy5hZGRQYXJhbWV0ZXJWYWx1ZShuYW1lLCB2YWx1ZSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgdmFsdWVzIG9mIHRoZSBuYW1lZCBxdWVyeSBwYXJhbWV0ZXJzLCBjbGVhcmluZyBwcmV2aW91cyB2YWx1ZXNcblx0ICogZm9yIHRoYXQga2V5LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFBhcmFtZXRlclZhbHVlcyhuYW1lLCB2YWx1ZXMpIHtcblx0XHR0aGlzLnJlbW92ZVBhcmFtZXRlcihuYW1lKTtcblx0XHR2YWx1ZXMuZm9yRWFjaCgodmFsdWUpID0+IHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwYXRobmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGhuYW1lXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFBhdGhuYW1lKHBhdGhuYW1lKSB7XG5cdFx0dGhpcy51cmwucGF0aG5hbWUgPSBwYXRobmFtZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwb3J0IG51bWJlci5cblx0ICogQHBhcmFtIHsqfSBwb3J0IFBvcnQgbnVtYmVyLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXRQb3J0KHBvcnQpIHtcblx0XHR0aGlzLnVybC5wb3J0ID0gcG9ydDtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgcGFyc2luZyB0aGUgb3JpZ2luYWwgc3RyaW5nIHVyaVxuXHQgKiBpbnRvIGFuIG9iamVjdC5cblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKX0gcGFyc2VGblxuXHQgKi9cblx0c3RhdGljIHNldFBhcnNlRm4ocGFyc2VGbikge1xuXHRcdHBhcnNlRm5fID0gcGFyc2VGbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwcm90b2NvbC4gSWYgbWlzc2luZyA8Y29kZT5odHRwOjwvY29kZT4gaXMgdXNlZCBhcyBkZWZhdWx0LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcHJvdG9jb2xcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0c2V0UHJvdG9jb2wocHJvdG9jb2wpIHtcblx0XHR0aGlzLnVybC5wcm90b2NvbCA9IHByb3RvY29sO1xuXHRcdGlmICh0aGlzLnVybC5wcm90b2NvbFt0aGlzLnVybC5wcm90b2NvbC5sZW5ndGggLSAxXSAhPT0gJzonKSB7XG5cdFx0XHR0aGlzLnVybC5wcm90b2NvbCArPSAnOic7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHN0cmluZyBmb3JtIG9mIHRoZSB1cmwuXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0dG9TdHJpbmcoKSB7XG5cdFx0dmFyIGhyZWYgPSAnJztcblx0XHR2YXIgaG9zdCA9IHRoaXMuZ2V0SG9zdCgpO1xuXHRcdGlmIChob3N0KSB7XG5cdFx0XHRocmVmICs9IHRoaXMuZ2V0UHJvdG9jb2woKSArICcvLyc7XG5cdFx0fVxuXHRcdGhyZWYgKz0gaG9zdCArIHRoaXMuZ2V0UGF0aG5hbWUoKSArIHRoaXMuZ2V0U2VhcmNoKCkgKyB0aGlzLmdldEhhc2goKTtcblx0XHRyZXR1cm4gaHJlZjtcblx0fVxuXG5cdC8qKlxuXHQgKiBKb2lucyB0aGUgZ2l2ZW4gcGF0aHMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlUGF0aFxuXHQgKiBAcGFyYW0gey4uLnN0cmluZ30gLi4ucGF0aHMgQW55IG51bWJlciBvZiBwYXRocyB0byBiZSBqb2luZWQgd2l0aCB0aGUgYmFzZSB1cmwuXG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBqb2luUGF0aHMoYmFzZVBhdGgsIC4uLnBhdGhzKSB7XG5cdFx0aWYgKGJhc2VQYXRoLmNoYXJBdChiYXNlUGF0aC5sZW5ndGggLSAxKSA9PT0gJy8nKSB7XG5cdFx0XHRiYXNlUGF0aCA9IGJhc2VQYXRoLnN1YnN0cmluZygwLCBiYXNlUGF0aC5sZW5ndGggLSAxKTtcblx0XHR9XG5cdFx0cGF0aHMgPSBwYXRocy5tYXAocGF0aCA9PiBwYXRoLmNoYXJBdCgwKSA9PT0gJy8nID8gcGF0aC5zdWJzdHJpbmcoMSkgOiBwYXRoKTtcblx0XHRyZXR1cm4gW2Jhc2VQYXRoXS5jb25jYXQocGF0aHMpLmpvaW4oJy8nKS5yZXBsYWNlKC9cXC8kLywgJycpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVSTC1kZWNvZGVzIHRoZSBzdHJpbmcuIFdlIG5lZWQgdG8gc3BlY2lhbGx5IGhhbmRsZSAnKydzIGJlY2F1c2Vcblx0ICogdGhlIGphdmFzY3JpcHQgbGlicmFyeSBkb2Vzbid0IGNvbnZlcnQgdGhlbSB0byBzcGFjZXMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byB1cmwgZGVjb2RlLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBkZWNvZGVkIHtAY29kZSBzdHJ9LlxuXHQgKi9cblx0c3RhdGljIHVybERlY29kZShzdHIpIHtcblx0XHRyZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHN0ci5yZXBsYWNlKC9cXCsvZywgJyAnKSk7XG5cdH1cblxufVxuXG4vKipcbiAqIERlZmF1bHQgcHJvdG9jb2wgdmFsdWUuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgaHR0cDpcbiAqIEBzdGF0aWNcbiAqL1xuY29uc3QgaXNTZWN1cmUgPSAoKSA9PlxuXHQodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiZcblx0XHR3aW5kb3cubG9jYXRpb24gJiZcblx0XHR3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgJiZcblx0XHR3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wuaW5kZXhPZignaHR0cHMnKSA9PT0gMCk7XG5cblVyaS5ERUZBVUxUX1BST1RPQ09MID0gaXNTZWN1cmUoKSA/ICdodHRwczonIDogJ2h0dHA6JztcblxuLyoqXG4gKiBIb3N0bmFtZSBwbGFjZWhvbGRlci4gUmVsZXZhbnQgdG8gaW50ZXJuYWwgdXNhZ2Ugb25seS5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cblVyaS5IT1NUTkFNRV9QTEFDRUhPTERFUiA9ICdob3N0bmFtZScgKyBEYXRlLm5vdygpO1xuXG4vKipcbiAqIE5hbWUgdXNlZCBieSB0aGUgcGFyYW0gZ2VuZXJhdGVkIGJ5IGBtYWtlVW5pcXVlYC5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cblVyaS5SQU5ET01fUEFSQU0gPSAnengnO1xuXG5leHBvcnQgZGVmYXVsdCBVcmk7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGV4aXREb2N1bWVudCB9IGZyb20gJ21ldGFsLWRvbSc7XG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IFVyaSBmcm9tICdtZXRhbC11cmknO1xuXG4vKipcbiAqIEEgY29sbGVjdGlvbiBvZiBzdGF0aWMgdXRpbGl0eSBmdW5jdGlvbnMuXG4gKiBAY29uc3RcbiAqL1xuY2xhc3MgdXRpbHMge1xuXG5cdC8qKlxuXHQgKiBDb3BpZXMgYXR0cmlidXRlcyBmb3JtIHNvdXJjZSBub2RlIHRvIHRhcmdldCBub2RlLlxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgY29weU5vZGVBdHRyaWJ1dGVzKHNvdXJjZSwgdGFyZ2V0KSB7XG5cdFx0QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoc291cmNlLmF0dHJpYnV0ZXMpLmZvckVhY2goKGF0dHJpYnV0ZSkgPT4gdGFyZ2V0LnNldEF0dHJpYnV0ZShhdHRyaWJ1dGUubmFtZSwgYXR0cmlidXRlLnZhbHVlKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgY3VycmVudCBicm93c2VyIHBhdGggaW5jbHVkaW5nIGhhc2hiYW5nLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0Q3VycmVudEJyb3dzZXJQYXRoKCkge1xuXHRcdHJldHVybiB0aGlzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCkgKyBnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5oYXNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGN1cnJlbnQgYnJvd3NlciBwYXRoIGV4Y2x1ZGluZyBoYXNoYmFuZy5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCkge1xuXHRcdHJldHVybiBnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSArIGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnNlYXJjaDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBnaXZlbiBub2RlIG9mZnNldCBjb29yZGluYXRlcy5cblx0ICogQHJldHVybiB7IW9iamVjdH1cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldE5vZGVPZmZzZXQobm9kZSkge1xuXHRcdGxldCBbb2Zmc2V0TGVmdCwgb2Zmc2V0VG9wXSA9IFswLCAwXTtcblx0XHRkbyB7XG5cdFx0XHRvZmZzZXRMZWZ0ICs9IG5vZGUub2Zmc2V0TGVmdDtcblx0XHRcdG9mZnNldFRvcCArPSBub2RlLm9mZnNldFRvcDtcblx0XHRcdG5vZGUgPSBub2RlLm9mZnNldFBhcmVudDtcblx0XHR9IHdoaWxlIChub2RlKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0b2Zmc2V0TGVmdCxcblx0XHRcdG9mZnNldFRvcFxuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogRXh0cmFjdHMgdGhlIHBhdGggcGFydCBvZiBhbiB1cmwuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBnZXRVcmxQYXRoKHVybCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHVybCk7XG5cdFx0cmV0dXJuIHVyaS5nZXRQYXRobmFtZSgpICsgdXJpLmdldFNlYXJjaCgpICsgdXJpLmdldEhhc2goKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFeHRyYWN0cyB0aGUgcGF0aCBwYXJ0IG9mIGFuIHVybCB3aXRob3V0IGhhc2hiYW5nLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0VXJsUGF0aFdpdGhvdXRIYXNoKHVybCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHVybCk7XG5cdFx0cmV0dXJuIHVyaS5nZXRQYXRobmFtZSgpICsgdXJpLmdldFNlYXJjaCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIHRoZSBwYXRoIHBhcnQgb2YgYW4gdXJsIHdpdGhvdXQgaGFzaGJhbmcgYW5kIHF1ZXJ5IHNlYXJjaC5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldFVybFBhdGhXaXRob3V0SGFzaEFuZFNlYXJjaCh1cmwpIHtcblx0XHR2YXIgdXJpID0gbmV3IFVyaSh1cmwpO1xuXHRcdHJldHVybiB1cmkuZ2V0UGF0aG5hbWUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdXJsIGlzIGluIHRoZSBzYW1lIGJyb3dzZXIgY3VycmVudCB1cmwgZXhjbHVkaW5nIHRoZSBoYXNoYmFuZy5cblx0ICogQHBhcmFtICB7IXN0cmluZ30gdXJsXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBpc0N1cnJlbnRCcm93c2VyUGF0aCh1cmwpIHtcblx0XHRpZiAodXJsKSB7XG5cdFx0XHRjb25zdCBjdXJyZW50QnJvd3NlclBhdGggPSB0aGlzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCk7XG5cdFx0XHQvLyB0aGUgZ2V0VXJsUGF0aCB3aWxsIGNyZWF0ZSBhIFVyaSBhbmQgd2lsbCBub3JtYWxpemUgdGhlIHBhdGggYW5kXG5cdFx0XHQvLyByZW1vdmUgdGhlIHRyYWlsbGluZyAnLycgZm9yIHByb3Blcmx5IGNvbXBhcmluZyBwYXRocy5cblx0XHRcdHJldHVybiB1dGlscy5nZXRVcmxQYXRoV2l0aG91dEhhc2godXJsKSA9PT0gdGhpcy5nZXRVcmxQYXRoKGN1cnJlbnRCcm93c2VyUGF0aCk7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgSFRNTDUgSGlzdG9yeSBhcGkgaXMgc3VwcG9ydGVkLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgaXNIdG1sNUhpc3RvcnlTdXBwb3J0ZWQoKSB7XG5cdFx0cmV0dXJuICEhKGdsb2JhbHMud2luZG93Lmhpc3RvcnkgJiYgZ2xvYmFscy53aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBhIGdpdmVuIHVybCBpcyBhIHZhbGlkIGh0dHAocykgdXJpIGFuZCByZXR1cm5zIHRoZSBmb3JtZWQgVXJpXG5cdCAqIG9yIGZhbHNlIGlmIHRoZSBwYXJzaW5nIGZhaWxlZFxuXHQgKiBAcmV0dXJuIHtVcml8Ym9vbGVhbn1cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGlzV2ViVXJpKHVybCkge1xuXHRcdHRyeSB7XG5cdFx0XHRyZXR1cm4gbmV3IFVyaSh1cmwpO1xuXHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0Y29uc29sZS5lcnJvcihgJHtlcnIubWVzc2FnZX0gJHt1cmx9YCk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYWxsIGF0dHJpYnV0ZXMgZm9ybSBub2RlLlxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgY2xlYXJOb2RlQXR0cmlidXRlcyhub2RlKSB7XG5cdFx0QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobm9kZS5hdHRyaWJ1dGVzKS5mb3JFYWNoKChhdHRyaWJ1dGUpID0+IG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJpYnV0ZS5uYW1lKSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlIGVsZW1lbnRzIGZyb20gdGhlIGRvY3VtZW50LlxuXHQgKiBAcGFyYW0geyFBcnJheTxFbGVtZW50Pn0gZWxlbWVudHNcblx0ICovXG5cdHN0YXRpYyByZW1vdmVFbGVtZW50c0Zyb21Eb2N1bWVudChlbGVtZW50cykge1xuXHRcdGVsZW1lbnRzLmZvckVhY2goKGVsZW1lbnQpID0+IGV4aXREb2N1bWVudChlbGVtZW50KSk7XG5cdH1cblxuXHQvKipcblx0KiBSZW1vdmVzIHRyYWlsaW5nIHNsYXNoIGluIHBhdGguXG5cdCogQHBhcmFtIHshc3RyaW5nfVxuXHQqIEByZXR1cm4ge3N0cmluZ31cblx0Ki9cblx0c3RhdGljIHJlbW92ZVBhdGhUcmFpbGluZ1NsYXNoKHBhdGgpIHtcblx0XHR2YXIgbGVuZ3RoID0gcGF0aCA/IHBhdGgubGVuZ3RoIDogMDtcblx0XHRpZiAobGVuZ3RoID4gMSAmJiBwYXRoW2xlbmd0aCAtIDFdID09PSAnLycpIHtcblx0XHRcdHBhdGggPSBwYXRoLnN1YnN0cigwLCBsZW5ndGggLSAxKTtcblx0XHR9XG5cdFx0cmV0dXJuIHBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIHJhbmRvbSBzdWZmaXggdG8gdGhlIGhyZWYgYXR0cmlidXRlIG9mIHRoZSBlbGVtZW50LlxuXHQgKiBAcGFyYW0geyFlbGVtZW50fSBlbGVtZW50XG5cdCAqIEByZXR1cm4ge2VsZW1lbnR9XG5cdCAqL1xuXHRzdGF0aWMgc2V0RWxlbWVudFdpdGhSYW5kb21IcmVmKGVsZW1lbnQpIHtcblx0XHRlbGVtZW50LmhyZWYgPSBlbGVtZW50LmhyZWYgKyAnP3E9JyArIE1hdGgucmFuZG9tKCk7XG5cdFx0cmV0dXJuIGVsZW1lbnQ7XG5cdH1cblxuXHQvKipcblx0ICogT3ZlcnJpZGVzIGRvY3VtZW50IHJlZmVycmVyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSByZWZlcnJlclxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgc2V0UmVmZXJyZXIocmVmZXJyZXIpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZ2xvYmFscy5kb2N1bWVudCwgJ3JlZmVycmVyJywge1xuXHRcdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdFx0Z2V0OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuIHJlZmVycmVyO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IHV0aWxzO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnQgZGVmYXVsdCB7XG5cdGJhc2VQYXRoOiAnZGF0YS1zZW5uYS1iYXNlLXBhdGgnLFxuXHRsaW5rU2VsZWN0b3I6ICdkYXRhLXNlbm5hLWxpbmstc2VsZWN0b3InLFxuXHRsb2FkaW5nQ3NzQ2xhc3M6ICdkYXRhLXNlbm5hLWxvYWRpbmctY3NzLWNsYXNzJyxcblx0c2VubmE6ICdkYXRhLXNlbm5hJyxcblx0ZGlzcGF0Y2g6ICdkYXRhLXNlbm5hLWRpc3BhdGNoJyxcblx0c3VyZmFjZTogJ2RhdGEtc2VubmEtc3VyZmFjZScsXG5cdHVwZGF0ZVNjcm9sbFBvc2l0aW9uOiAnZGF0YS1zZW5uYS11cGRhdGUtc2Nyb2xsLXBvc2l0aW9uJ1xufTsiLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7RGlzcG9zYWJsZX0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEV2ZW50SGFuZGxlIHV0aWxpdHkuIEhvbGRzIGluZm9ybWF0aW9uIGFib3V0IGFuIGV2ZW50IHN1YnNjcmlwdGlvbiwgYW5kXG4gKiBhbGxvd3MgcmVtb3ZpbmcgdGhlbSBlYXNpbHkuXG4gKiBFdmVudEhhbmRsZSBpcyBhIERpc3Bvc2FibGUsIGJ1dCBpdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgdGhlXG4gKiBFdmVudEVtaXR0ZXIgdGhhdCBjcmVhdGVkIGl0IGlzIG5vdCB0aGUgb25lIHJlc3BvbnNpYmxlIGZvciBkaXNwb3NpbmcgaXQuXG4gKiBUaGF0IHJlc3BvbnNpYmlsaXR5IGlzIGZvciB0aGUgY29kZSB0aGF0IGhvbGRzIGEgcmVmZXJlbmNlIHRvIGl0LlxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIEV2ZW50SGFuZGxlIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cdC8qKlxuXHQgKiBFdmVudEhhbmRsZSBjb25zdHJ1Y3RvclxuXHQgKiBAcGFyYW0geyFFdmVudEVtaXR0ZXJ9IGVtaXR0ZXIgRW1pdHRlciB0aGUgZXZlbnQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCB3YXMgc3Vic2NyaWJlZCB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0ICovXG5cdGNvbnN0cnVjdG9yKGVtaXR0ZXIsIGV2ZW50LCBsaXN0ZW5lcikge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgRXZlbnRFbWl0dGVyIGluc3RhbmNlIHRoYXQgdGhlIGV2ZW50IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHRcdCAqIEB0eXBlIHtFdmVudEVtaXR0ZXJ9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZW1pdHRlcl8gPSBlbWl0dGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRoYXQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdFx0ICogQHR5cGUge3N0cmluZ31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ldmVudF8gPSBldmVudDtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0XHQgKiBAdHlwZSB7RnVuY3Rpb259XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMubGlzdGVuZXJfID0gbGlzdGVuZXI7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0dGhpcy5lbWl0dGVyXyA9IG51bGw7XG5cdFx0dGhpcy5saXN0ZW5lcl8gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGxpc3RlbmVyIHN1YnNjcmlwdGlvbiBmcm9tIHRoZSBlbWl0dGVyLlxuXHQgKi9cblx0cmVtb3ZlTGlzdGVuZXIoKSB7XG5cdFx0aWYgKCF0aGlzLmVtaXR0ZXJfLmlzRGlzcG9zZWQoKSkge1xuXHRcdFx0dGhpcy5lbWl0dGVyXy5yZW1vdmVMaXN0ZW5lcih0aGlzLmV2ZW50XywgdGhpcy5saXN0ZW5lcl8pO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEhhbmRsZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHthcnJheSwgRGlzcG9zYWJsZSwgaXNGdW5jdGlvbiwgaXNTdHJpbmd9IGZyb20gJ21ldGFsJztcbmltcG9ydCBFdmVudEhhbmRsZSBmcm9tICcuL0V2ZW50SGFuZGxlJztcblxuY29uc3Qgc2luZ2xlQXJyYXlfID0gWzBdO1xuXG4vKipcbiAqIEV2ZW50RW1pdHRlciB1dGlsaXR5LlxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIEV2ZW50RW1pdHRlciBleHRlbmRzIERpc3Bvc2FibGUge1xuXHQvKipcblx0ICogRXZlbnRFbWl0dGVyIGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgZXZlbnQgbGlzdGVuZXJzIHNjb3BlZCBieSBldmVudCB0eXBlLlxuXHRcdCAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCAhQXJyYXk8IWZ1bmN0aW9uKCk+Pn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ldmVudHNfID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhhbmRsZXJzIHRoYXQgYXJlIHRyaWdnZXJlZCB3aGVuIGFuIGV2ZW50IGlzIGxpc3RlbmVkIHRvLlxuXHRcdCAqIEB0eXBlIHtBcnJheX1cblx0XHQgKi9cblx0XHR0aGlzLmxpc3RlbmVySGFuZGxlcnNfID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIENvbmZpZ3VyYXRpb24gb3B0aW9uIHdoaWNoIGRldGVybWluZXMgaWYgYW4gZXZlbnQgZmFjYWRlIHNob3VsZCBiZSBzZW50XG5cdFx0ICogYXMgYSBwYXJhbSBvZiBsaXN0ZW5lcnMgd2hlbiBlbWl0dGluZyBldmVudHMuIElmIHNldCB0byB0cnVlLCB0aGUgZmFjYWRlXG5cdFx0ICogd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIHRoZSBsaXN0ZW5lci5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5zaG91bGRVc2VGYWNhZGVfID0gZmFsc2U7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGhhbmRsZXIgdG8gZ2l2ZW4gaG9sZGVyIHZhcmlhYmxlLiBJZiB0aGUgaG9sZGVyIGRvZXNuJ3QgaGF2ZSBhXG5cdCAqIHZhbHVlIHlldCwgaXQgd2lsbCByZWNlaXZlIHRoZSBoYW5kbGVyIGRpcmVjdGx5LiBJZiB0aGUgaG9sZGVyIGlzIGFuIGFycmF5LFxuXHQgKiB0aGUgdmFsdWUgd2lsbCBqdXN0IGJlIGFkZGVkIHRvIGl0LiBPdGhlcndpc2UsIHRoZSBob2xkZXIgd2lsbCBiZSBzZXQgdG8gYVxuXHQgKiBuZXcgYXJyYXkgY29udGFpbmluZyBpdHMgcHJldmlvdXMgdmFsdWUgcGx1cyB0aGUgbmV3IGhhbmRsZXIuXG5cdCAqIEBwYXJhbSB7Kn0gaG9sZGVyXG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl8T2JqZWN0fSBoYW5kbGVyXG5cdCAqIEByZXR1cm4geyp9IFRoZSBob2xkZXIncyBuZXcgdmFsdWUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFkZEhhbmRsZXJfKGhvbGRlciwgaGFuZGxlcikge1xuXHRcdGlmICghaG9sZGVyKSB7XG5cdFx0XHRob2xkZXIgPSBoYW5kbGVyO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIUFycmF5LmlzQXJyYXkoaG9sZGVyKSkge1xuXHRcdFx0XHRob2xkZXIgPSBbaG9sZGVyXTtcblx0XHRcdH1cblx0XHRcdGhvbGRlci5wdXNoKGhhbmRsZXIpO1xuXHRcdH1cblx0XHRyZXR1cm4gaG9sZGVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0byB0aGUgZW5kIG9mIHRoZSBsaXN0ZW5lcnMgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRzLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gZGVmYXVsdExpc3RlbmVyIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGxpc3RlbmVyIGlzIGEgZGVmYXVsdFxuXHQgKiAgIGFjdGlvbiBmb3IgdGhpcyBldmVudC4gRGVmYXVsdCBhY3Rpb25zIGFyZSBydW4gbGFzdCwgYW5kIG9ubHkgaWYgbm8gcHJldmlvdXNcblx0ICogICBsaXN0ZW5lciBjYWxsIGBwcmV2ZW50RGVmYXVsdCgpYCBvbiB0aGUgcmVjZWl2ZWQgZXZlbnQgZmFjYWRlLlxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG5cdCAqL1xuXHRhZGRMaXN0ZW5lcihldmVudCwgbGlzdGVuZXIsIGRlZmF1bHRMaXN0ZW5lcikge1xuXHRcdHRoaXMudmFsaWRhdGVMaXN0ZW5lcl8obGlzdGVuZXIpO1xuXG5cdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuYWRkU2luZ2xlTGlzdGVuZXJfKGV2ZW50c1tpXSwgbGlzdGVuZXIsIGRlZmF1bHRMaXN0ZW5lcik7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBFdmVudEhhbmRsZSh0aGlzLCBldmVudCwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0byB0aGUgZW5kIG9mIHRoZSBsaXN0ZW5lcnMgYXJyYXkgZm9yIGEgc2luZ2xlIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gZGVmYXVsdExpc3RlbmVyIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGxpc3RlbmVyIGlzIGEgZGVmYXVsdFxuXHQgKiAgIGFjdGlvbiBmb3IgdGhpcyBldmVudC4gRGVmYXVsdCBhY3Rpb25zIGFyZSBydW4gbGFzdCwgYW5kIG9ubHkgaWYgbm8gcHJldmlvdXNcblx0ICogICBsaXN0ZW5lciBjYWxsIGBwcmV2ZW50RGVmYXVsdCgpYCBvbiB0aGUgcmVjZWl2ZWQgZXZlbnQgZmFjYWRlLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9uPX0gb3JpZ2luIFRoZSBvcmlnaW5hbCBmdW5jdGlvbiB0aGF0IHdhcyBhZGRlZCBhcyBhXG5cdCAqICAgbGlzdGVuZXIsIGlmIHRoZXJlIGlzIGFueS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0YWRkU2luZ2xlTGlzdGVuZXJfKGV2ZW50LCBsaXN0ZW5lciwgZGVmYXVsdExpc3RlbmVyLCBvcmlnaW4pIHtcblx0XHR0aGlzLnJ1bkxpc3RlbmVySGFuZGxlcnNfKGV2ZW50KTtcblx0XHRpZiAoZGVmYXVsdExpc3RlbmVyIHx8IG9yaWdpbikge1xuXHRcdFx0bGlzdGVuZXIgPSB7XG5cdFx0XHRcdGRlZmF1bHQ6IGRlZmF1bHRMaXN0ZW5lcixcblx0XHRcdFx0Zm46IGxpc3RlbmVyLFxuXHRcdFx0XHRvcmlnaW46IG9yaWdpbixcblx0XHRcdH07XG5cdFx0fVxuXHRcdHRoaXMuZXZlbnRzXyA9IHRoaXMuZXZlbnRzXyB8fCB7fTtcblx0XHR0aGlzLmV2ZW50c19bZXZlbnRdID0gdGhpcy5hZGRIYW5kbGVyXyh0aGlzLmV2ZW50c19bZXZlbnRdLCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQnVpbGRzIGZhY2FkZSBmb3IgdGhlIGdpdmVuIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7T2JqZWN0fVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRidWlsZEZhY2FkZV8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5nZXRTaG91bGRVc2VGYWNhZGUoKSkge1xuXHRcdFx0Y29uc3QgZmFjYWRlID0ge1xuXHRcdFx0XHRwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0ZmFjYWRlLnByZXZlbnRlZERlZmF1bHQgPSB0cnVlO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR0YXJnZXQ6IHRoaXMsXG5cdFx0XHRcdHR5cGU6IGV2ZW50LFxuXHRcdFx0fTtcblx0XHRcdHJldHVybiBmYWNhZGU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy5cblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5ldmVudHNfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBFeGVjdXRlIGVhY2ggb2YgdGhlIGxpc3RlbmVycyBpbiBvcmRlciB3aXRoIHRoZSBzdXBwbGllZCBhcmd1bWVudHMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0geyp9IG9wdF9hcmdzIFthcmcxXSwgW2FyZzJdLCBbLi4uXVxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBSZXR1cm5zIHRydWUgaWYgZXZlbnQgaGFkIGxpc3RlbmVycywgZmFsc2Ugb3RoZXJ3aXNlLlxuXHQgKi9cblx0ZW1pdChldmVudCkge1xuXHRcdGNvbnN0IGxpc3RlbmVycyA9IHRoaXMuZ2V0UmF3TGlzdGVuZXJzXyhldmVudCk7XG5cdFx0aWYgKGxpc3RlbmVycy5sZW5ndGggPT09IDApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRjb25zdCBhcmdzID0gYXJyYXkuc2xpY2UoYXJndW1lbnRzLCAxKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdHRoaXMucnVuTGlzdGVuZXJzXyhsaXN0ZW5lcnMsIGFyZ3MsIHRoaXMuYnVpbGRGYWNhZGVfKGV2ZW50KSk7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgbGlzdGVuZXIgb2JqZWN0cyBmb3IgdGhlIGdpdmVuIGV2ZW50LCBpZiB0aGVyZSBhcmUgYW55LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7IUFycmF5fVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRnZXRSYXdMaXN0ZW5lcnNfKGV2ZW50KSB7XG5cdFx0Y29uc3QgZGlyZWN0TGlzdGVuZXJzID0gdG9BcnJheSh0aGlzLmV2ZW50c18gJiYgdGhpcy5ldmVudHNfW2V2ZW50XSk7XG5cdFx0cmV0dXJuIGRpcmVjdExpc3RlbmVycy5jb25jYXQoXG5cdFx0XHR0b0FycmF5KHRoaXMuZXZlbnRzXyAmJiB0aGlzLmV2ZW50c19bJyonXSlcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9uIHdoaWNoIGRldGVybWluZXMgaWYgYW4gZXZlbnQgZmFjYWRlIHNob3VsZFxuXHQgKiBiZSBzZW50IGFzIGEgcGFyYW0gb2YgbGlzdGVuZXJzIHdoZW4gZW1pdHRpbmcgZXZlbnRzLiBJZiBzZXQgdG8gdHJ1ZSwgdGhlXG5cdCAqIGZhY2FkZSB3aWxsIGJlIHBhc3NlZCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgb2YgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0Z2V0U2hvdWxkVXNlRmFjYWRlKCkge1xuXHRcdHJldHVybiB0aGlzLnNob3VsZFVzZUZhY2FkZV87XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHtBcnJheX0gQXJyYXkgb2YgbGlzdGVuZXJzLlxuXHQgKi9cblx0bGlzdGVuZXJzKGV2ZW50KSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0UmF3TGlzdGVuZXJzXyhldmVudCkubWFwKFxuXHRcdFx0bGlzdGVuZXIgPT4gKGxpc3RlbmVyLmZuID8gbGlzdGVuZXIuZm4gOiBsaXN0ZW5lcilcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIGZpeGVkIG51bWJlciBvZiB0aW1lcyBmb3IgdGhlXG5cdCAqIGV2ZW50cy4gQWZ0ZXIgZWFjaCBldmVudCBpcyB0cmlnZ2VyZWQgdGhlIHNwZWNpZmllZCBhbW91bnQgb2YgdGltZXMsIHRoZVxuXHQgKiBsaXN0ZW5lciBpcyByZW1vdmVkIGZvciBpdC5cblx0ICogQHBhcmFtIHshKEFycmF5fHN0cmluZyl9IGV2ZW50XG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBhbW91bnQgVGhlIGFtb3VudCBvZiB0aW1lcyB0aGlzIGV2ZW50IHNob3VsZCBiZSBsaXN0ZW5lZFxuXHQgKiB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cblx0ICovXG5cdG1hbnkoZXZlbnQsIGFtb3VudCwgbGlzdGVuZXIpIHtcblx0XHRjb25zdCBldmVudHMgPSB0aGlzLnRvRXZlbnRzQXJyYXlfKGV2ZW50KTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dGhpcy5tYW55XyhldmVudHNbaV0sIGFtb3VudCwgbGlzdGVuZXIpO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgRXZlbnRIYW5kbGUodGhpcywgZXZlbnQsIGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBmaXhlZCBudW1iZXIgb2YgdGltZXMgZm9yIGEgc2luZ2xlXG5cdCAqIGV2ZW50LiBBZnRlciB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkIHRoZSBzcGVjaWZpZWQgYW1vdW50IG9mIHRpbWVzLCB0aGVcblx0ICogbGlzdGVuZXIgaXMgcmVtb3ZlZC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBhbW91bnQgVGhlIGFtb3VudCBvZiB0aW1lcyB0aGlzIGV2ZW50IHNob3VsZCBiZSBsaXN0ZW5lZFxuXHQgKiB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG1hbnlfKGV2ZW50LCBhbW91bnQsIGxpc3RlbmVyKSB7XG5cdFx0Y29uc3Qgc2VsZiA9IHRoaXM7XG5cblx0XHRpZiAoYW1vdW50IDw9IDApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvKipcblx0XHQgKlxuXHRcdCAqL1xuXHRcdGZ1bmN0aW9uIGhhbmRsZXJJbnRlcm5hbCgpIHtcblx0XHRcdGlmICgtLWFtb3VudCA9PT0gMCkge1xuXHRcdFx0XHRzZWxmLnJlbW92ZUxpc3RlbmVyKGV2ZW50LCBoYW5kbGVySW50ZXJuYWwpO1xuXHRcdFx0fVxuXHRcdFx0bGlzdGVuZXIuYXBwbHkoc2VsZiwgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdH1cblxuXHRcdHNlbGYuYWRkU2luZ2xlTGlzdGVuZXJfKGV2ZW50LCBoYW5kbGVySW50ZXJuYWwsIGZhbHNlLCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIGEgbGlzdGVuZXIgb2JqZWN0IG1hdGNoZXMgdGhlIGdpdmVuIGxpc3RlbmVyIGZ1bmN0aW9uLiBUbyBtYXRjaCxcblx0ICogaXQgbmVlZHMgdG8gZWl0aGVyIHBvaW50IHRvIHRoYXQgbGlzdGVuZXIgb3IgaGF2ZSBpdCBhcyBpdHMgb3JpZ2luLlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IGxpc3RlbmVyT2JqXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRtYXRjaGVzTGlzdGVuZXJfKGxpc3RlbmVyT2JqLCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IGZuID0gbGlzdGVuZXJPYmouZm4gfHwgbGlzdGVuZXJPYmo7XG5cdFx0cmV0dXJuIChcblx0XHRcdGZuID09PSBsaXN0ZW5lciB8fFxuXHRcdFx0KGxpc3RlbmVyT2JqLm9yaWdpbiAmJiBsaXN0ZW5lck9iai5vcmlnaW4gPT09IGxpc3RlbmVyKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRzLlxuXHQgKiBDYXV0aW9uOiBjaGFuZ2VzIGFycmF5IGluZGljZXMgaW4gdGhlIGxpc3RlbmVyIGFycmF5IGJlaGluZCB0aGUgbGlzdGVuZXIuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudFxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IU9iamVjdH0gUmV0dXJucyBlbWl0dGVyLCBzbyBjYWxscyBjYW4gYmUgY2hhaW5lZC5cblx0ICovXG5cdG9mZihldmVudCwgbGlzdGVuZXIpIHtcblx0XHR0aGlzLnZhbGlkYXRlTGlzdGVuZXJfKGxpc3RlbmVyKTtcblx0XHRpZiAoIXRoaXMuZXZlbnRzXykge1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuZXZlbnRzX1tldmVudHNbaV1dID0gdGhpcy5yZW1vdmVNYXRjaGluZ0xpc3RlbmVyT2Jqc18oXG5cdFx0XHRcdHRvQXJyYXkodGhpcy5ldmVudHNfW2V2ZW50c1tpXV0pLFxuXHRcdFx0XHRsaXN0ZW5lclxuXHRcdFx0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQHBhcmFtIHshKEFycmF5fHN0cmluZyl9IGV2ZW50c1xuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuXHQgKi9cblx0b24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgaGFuZGxlciB0aGF0IGdldHMgdHJpZ2dlcmVkIHdoZW4gYW4gZXZlbnQgaXMgbGlzdGVuZWQgdG8gb24gdGhpc1xuXHQgKiBpbnN0YW5jZS5cblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKX0gaGFuZGxlclxuXHQgKi9cblx0b25MaXN0ZW5lcihoYW5kbGVyKSB7XG5cdFx0dGhpcy5saXN0ZW5lckhhbmRsZXJzXyA9IHRoaXMuYWRkSGFuZGxlcl8oXG5cdFx0XHR0aGlzLmxpc3RlbmVySGFuZGxlcnNfLFxuXHRcdFx0aGFuZGxlclxuXHRcdCk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgb25lIHRpbWUgbGlzdGVuZXIgZm9yIHRoZSBldmVudHMuIFRoaXMgbGlzdGVuZXIgaXMgaW52b2tlZCBvbmx5IHRoZVxuXHQgKiBuZXh0IHRpbWUgZWFjaCBldmVudCBpcyBmaXJlZCwgYWZ0ZXIgd2hpY2ggaXQgaXMgcmVtb3ZlZC5cblx0ICogQHBhcmFtIHshKEFycmF5fHN0cmluZyl9IGV2ZW50c1xuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuXHQgKi9cblx0b25jZShldmVudHMsIGxpc3RlbmVyKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFueShldmVudHMsIDEsIGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMsIG9yIHRob3NlIG9mIHRoZSBzcGVjaWZpZWQgZXZlbnRzLiBJdCdzIG5vdCBhIGdvb2Rcblx0ICogaWRlYSB0byByZW1vdmUgbGlzdGVuZXJzIHRoYXQgd2VyZSBhZGRlZCBlbHNld2hlcmUgaW4gdGhlIGNvZGUsXG5cdCAqIGVzcGVjaWFsbHkgd2hlbiBpdCdzIG9uIGFuIGVtaXR0ZXIgdGhhdCB5b3UgZGlkbid0IGNyZWF0ZS5cblx0ICogQHBhcmFtIHsoQXJyYXl8c3RyaW5nKT19IGV2ZW50XG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRyZW1vdmVBbGxMaXN0ZW5lcnMoZXZlbnQpIHtcblx0XHRpZiAodGhpcy5ldmVudHNfKSB7XG5cdFx0XHRpZiAoZXZlbnQpIHtcblx0XHRcdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdFx0dGhpcy5ldmVudHNfW2V2ZW50c1tpXV0gPSBudWxsO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmV2ZW50c18gPSBudWxsO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lciBvYmplY3RzIGZyb20gdGhlIGdpdmVuIGFycmF5IHRoYXQgbWF0Y2ggdGhlIGdpdmVuXG5cdCAqIGxpc3RlbmVyIGZ1bmN0aW9uLlxuXHQgKiBAcGFyYW0ge0FycmF5LjxPYmplY3Q+fSBsaXN0ZW5lck9ianNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4ge0FycmF5LjxPYmplY3Q+fE9iamVjdH0gVGhlIG5ldyBsaXN0ZW5lcnMgYXJyYXkgZm9yIHRoaXMgZXZlbnQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHJlbW92ZU1hdGNoaW5nTGlzdGVuZXJPYmpzXyhsaXN0ZW5lck9ianMsIGxpc3RlbmVyKSB7XG5cdFx0Y29uc3QgZmluYWxMaXN0ZW5lcnMgPSBbXTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGxpc3RlbmVyT2Jqcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKCF0aGlzLm1hdGNoZXNMaXN0ZW5lcl8obGlzdGVuZXJPYmpzW2ldLCBsaXN0ZW5lcikpIHtcblx0XHRcdFx0ZmluYWxMaXN0ZW5lcnMucHVzaChsaXN0ZW5lck9ianNbaV0pO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gZmluYWxMaXN0ZW5lcnMubGVuZ3RoID4gMCA/IGZpbmFsTGlzdGVuZXJzIDogbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRzLlxuXHQgKiBDYXV0aW9uOiBjaGFuZ2VzIGFycmF5IGluZGljZXMgaW4gdGhlIGxpc3RlbmVyIGFycmF5IGJlaGluZCB0aGUgbGlzdGVuZXIuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRyZW1vdmVMaXN0ZW5lcigpIHtcblx0XHRyZXR1cm4gdGhpcy5vZmYuYXBwbHkodGhpcywgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHR9XG5cblx0LyoqXG5cdCAqIFJ1bnMgdGhlIGhhbmRsZXJzIHdoZW4gYW4gZXZlbnQgaXMgbGlzdGVuZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRydW5MaXN0ZW5lckhhbmRsZXJzXyhldmVudCkge1xuXHRcdGxldCBoYW5kbGVycyA9IHRoaXMubGlzdGVuZXJIYW5kbGVyc187XG5cdFx0aWYgKGhhbmRsZXJzKSB7XG5cdFx0XHRoYW5kbGVycyA9IHRvQXJyYXkoaGFuZGxlcnMpO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBoYW5kbGVycy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRoYW5kbGVyc1tpXShldmVudCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJ1bnMgdGhlIGdpdmVuIGxpc3RlbmVycy5cblx0ICogQHBhcmFtIHshQXJyYXl9IGxpc3RlbmVyc1xuXHQgKiBAcGFyYW0geyFBcnJheX0gYXJnc1xuXHQgKiBAcGFyYW0ge09iamVjdH0gZmFjYWRlXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHJ1bkxpc3RlbmVyc18obGlzdGVuZXJzLCBhcmdzLCBmYWNhZGUpIHtcblx0XHRpZiAoZmFjYWRlKSB7XG5cdFx0XHRhcmdzLnB1c2goZmFjYWRlKTtcblx0XHR9XG5cblx0XHRjb25zdCBkZWZhdWx0TGlzdGVuZXJzID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldLmZuIHx8IGxpc3RlbmVyc1tpXTtcblx0XHRcdGlmIChsaXN0ZW5lcnNbaV0uZGVmYXVsdCkge1xuXHRcdFx0XHRkZWZhdWx0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXIpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bGlzdGVuZXIuYXBwbHkodGhpcywgYXJncyk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICghZmFjYWRlIHx8ICFmYWNhZGUucHJldmVudGVkRGVmYXVsdCkge1xuXHRcdFx0Zm9yIChsZXQgaiA9IDA7IGogPCBkZWZhdWx0TGlzdGVuZXJzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdGRlZmF1bHRMaXN0ZW5lcnNbal0uYXBwbHkodGhpcywgYXJncyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9uIHdoaWNoIGRldGVybWluZXMgaWYgYW4gZXZlbnQgZmFjYWRlIHNob3VsZFxuXHQgKiBiZSBzZW50IGFzIGEgcGFyYW0gb2YgbGlzdGVuZXJzIHdoZW4gZW1pdHRpbmcgZXZlbnRzLiBJZiBzZXQgdG8gdHJ1ZSwgdGhlXG5cdCAqIGZhY2FkZSB3aWxsIGJlIHBhc3NlZCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgb2YgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IHNob3VsZFVzZUZhY2FkZVxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fSBSZXR1cm5zIGVtaXR0ZXIsIHNvIGNhbGxzIGNhbiBiZSBjaGFpbmVkLlxuXHQgKi9cblx0c2V0U2hvdWxkVXNlRmFjYWRlKHNob3VsZFVzZUZhY2FkZSkge1xuXHRcdHRoaXMuc2hvdWxkVXNlRmFjYWRlXyA9IHNob3VsZFVzZUZhY2FkZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyB0aGUgcGFyYW1ldGVyIHRvIGFuIGFycmF5IGlmIG9ubHkgb25lIGV2ZW50IGlzIGdpdmVuLiBSZXVzZXMgdGhlXG5cdCAqIHNhbWUgYXJyYXkgZWFjaCB0aW1lIHRoaXMgY29udmVyc2lvbiBpcyBkb25lLCB0byBhdm9pZCB1c2luZyBtb3JlIG1lbW9yeVxuXHQgKiB0aGFuIG5lY2Vzc2FyeS5cblx0ICogQHBhcmFtICB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHJldHVybiB7IUFycmF5fVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHR0b0V2ZW50c0FycmF5XyhldmVudHMpIHtcblx0XHRpZiAoaXNTdHJpbmcoZXZlbnRzKSkge1xuXHRcdFx0c2luZ2xlQXJyYXlfWzBdID0gZXZlbnRzO1xuXHRcdFx0ZXZlbnRzID0gc2luZ2xlQXJyYXlfO1xuXHRcdH1cblx0XHRyZXR1cm4gZXZlbnRzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gbGlzdGVuZXIgaXMgdmFsaWQsIHRocm93aW5nIGFuIGV4Y2VwdGlvbiB3aGVuIGl0J3Mgbm90LlxuXHQgKiBAcGFyYW0gIHsqfSBsaXN0ZW5lclxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHR2YWxpZGF0ZUxpc3RlbmVyXyhsaXN0ZW5lcikge1xuXHRcdGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoJ0xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIENvbnZlcnRzIHRvIGFuIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gdmFsXG4gKiBAcmV0dXJuIHtBcnJheX1cbiAqL1xuZnVuY3Rpb24gdG9BcnJheSh2YWwpIHtcblx0dmFsID0gdmFsIHx8IFtdO1xuXHRyZXR1cm4gQXJyYXkuaXNBcnJheSh2YWwpID8gdmFsIDogW3ZhbF07XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50RW1pdHRlcjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHtEaXNwb3NhYmxlfSBmcm9tICdtZXRhbCc7XG5cbi8qKlxuICogRXZlbnRFbWl0dGVyUHJveHkgdXRpbGl0eS4gSXQncyByZXNwb25zaWJsZSBmb3IgbGlua2luZyB0d28gRXZlbnRFbWl0dGVyXG4gKiBpbnN0YW5jZXMgdG9nZXRoZXIsIGVtaXR0aW5nIGV2ZW50cyBmcm9tIHRoZSBmaXJzdCBlbWl0dGVyIHRocm91Z2ggdGhlXG4gKiBzZWNvbmQgb25lLiBUaGF0IG1lYW5zIHRoYXQgbGlzdGVuaW5nIHRvIGEgc3VwcG9ydGVkIGV2ZW50IG9uIHRoZSB0YXJnZXRcbiAqIGVtaXR0ZXIgd2lsbCBtZWFuIGxpc3RlbmluZyB0byBpdCBvbiB0aGUgb3JpZ2luIGVtaXR0ZXIgYXMgd2VsbC5cbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEVtaXR0ZXJQcm94eSBleHRlbmRzIERpc3Bvc2FibGUge1xuXHQvKipcblx0ICogQHBhcmFtIHtFdmVudEVtaXR0ZXJ9IG9yaWdpbkVtaXR0ZXIgRXZlbnRzIG9yaWdpbmF0ZWQgb24gdGhpcyBlbWl0dGVyXG5cdCAqIHdpbGwgYmUgZmlyZWQgZm9yIHRoZSB0YXJnZXQgZW1pdHRlcidzIGxpc3RlbmVycyBhcyB3ZWxsLlxuXHQgKiBAcGFyYW0ge0V2ZW50RW1pdHRlcn0gdGFyZ2V0RW1pdHRlciBFdmVudCBsaXN0ZW5lcnMgYXR0YWNoZWQgdG8gdGhpcyBlbWl0dGVyXG5cdCAqIHdpbGwgYWxzbyBiZSB0cmlnZ2VyZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWQgYnkgdGhlIG9yaWdpbiBlbWl0dGVyLlxuXHQgKiBAcGFyYW0ge09iamVjdH0gYmxhY2tsaXN0IE9wdGlvbmFsIGJsYWNrbGlzdCBvZiBldmVudHMgdGhhdCBzaG91bGQgbm90IGJlXG5cdCAqIHByb3hpZWQuXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSB3aGl0ZWxpc3Rcblx0ICovXG5cdGNvbnN0cnVjdG9yKG9yaWdpbkVtaXR0ZXIsIHRhcmdldEVtaXR0ZXIsIGJsYWNrbGlzdCwgd2hpdGVsaXN0KSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIE1hcCBvZiBldmVudHMgdGhhdCBzaG91bGQgbm90IGJlIHByb3hpZWQuXG5cdFx0ICogQHR5cGUge09iamVjdH1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ibGFja2xpc3RfID0gYmxhY2tsaXN0O1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG9yaWdpbiBlbWl0dGVyLiBUaGlzIGVtaXR0ZXIncyBldmVudHMgd2lsbCBiZSBwcm94aWVkIHRocm91Z2ggdGhlXG5cdFx0ICogdGFyZ2V0IGVtaXR0ZXIuXG5cdFx0ICogQHR5cGUge0V2ZW50RW1pdHRlcn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyA9IG9yaWdpbkVtaXR0ZXI7XG5cblx0XHQvKipcblx0XHQgKiBBIGxpc3Qgb2YgZXZlbnRzIHRoYXQgYXJlIHBlbmRpbmcgdG8gYmUgbGlzdGVuZWQgYnkgYW4gYWN0dWFsIG9yaWdpblxuXHRcdCAqIGVtaXR0ZXIuIEV2ZW50cyBhcmUgc3RvcmVkIGhlcmUgd2hlbiB0aGUgb3JpZ2luIGRvZXNuJ3QgZXhpc3QsIHNvIHRoZXlcblx0XHQgKiBjYW4gYmUgc2V0IG9uIGEgbmV3IG9yaWdpbiB3aGVuIG9uZSBpcyBzZXQuXG5cdFx0ICogQHR5cGUge0FycmF5fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnBlbmRpbmdFdmVudHNfID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGEgbWFwIG9mIGV2ZW50cyBmcm9tIHRoZSBvcmlnaW4gZW1pdHRlciB0aGF0IGFyZSBhbHJlYWR5IGJlaW5nIHByb3hpZWQuXG5cdFx0ICogQHR5cGUge09iamVjdDxzdHJpbmcsICFFdmVudEhhbmRsZT59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucHJveGllZEV2ZW50c18gPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIHRhcmdldCBlbWl0dGVyLiBUaGlzIGVtaXR0ZXIgd2lsbCBlbWl0IGFsbCBldmVudHMgdGhhdCBjb21lIGZyb21cblx0XHQgKiB0aGUgb3JpZ2luIGVtaXR0ZXIuXG5cdFx0ICogQHR5cGUge0V2ZW50RW1pdHRlcn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXyA9IHRhcmdldEVtaXR0ZXI7XG5cblx0XHQvKipcblx0XHQgKiBNYXAgb2YgZXZlbnRzIHRoYXQgc2hvdWxkIGJlIHByb3hpZWQuIElmIHdoaXRlbGlzdCBpcyBzZXQgYmxhY2tsaXN0IGlzIGlnbm9yZWQuXG5cdFx0ICogQHR5cGUge09iamVjdH1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy53aGl0ZWxpc3RfID0gd2hpdGVsaXN0O1xuXG5cdFx0dGhpcy5zdGFydFByb3h5XygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIGdpdmVuIGxpc3RlbmVyIGZvciB0aGUgZ2l2ZW4gZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbigpfSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IFRoZSBsaXN0ZW5lZCBldmVudCdzIGhhbmRsZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0YWRkTGlzdGVuZXJfKGV2ZW50LCBsaXN0ZW5lcikge1xuXHRcdHJldHVybiB0aGlzLm9yaWdpbkVtaXR0ZXJfLm9uKGV2ZW50LCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLnJlbW92ZUxpc3RlbmVyc18oKTtcblx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gbnVsbDtcblx0XHR0aGlzLm9yaWdpbkVtaXR0ZXJfID0gbnVsbDtcblx0XHR0aGlzLnRhcmdldEVtaXR0ZXJfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBFbWl0cyB0aGUgc3BlY2lmaWVkIGV2ZW50IHR5cGUgb24gdGhlIHRhcmdldCBlbWl0dGVyLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRlbWl0T25UYXJnZXRfKC4uLmFyZ3MpIHtcblx0XHR0aGlzLnRhcmdldEVtaXR0ZXJfLmVtaXQoLi4uYXJncyk7XG5cdH1cblxuXHQvKipcblx0ICogUHJveGllcyB0aGUgZ2l2ZW4gZXZlbnQgZnJvbSB0aGUgb3JpZ2luIHRvIHRoZSB0YXJnZXQgZW1pdHRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqL1xuXHRwcm94eUV2ZW50KGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuc2hvdWxkUHJveHlFdmVudF8oZXZlbnQpKSB7XG5cdFx0XHR0aGlzLnRyeVRvQWRkTGlzdGVuZXJfKGV2ZW50KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyB0aGUgcHJveHkgbGlzdGVuZXIgZm9yIGFsbCBldmVudHMuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyc18oKSB7XG5cdFx0aWYgKHRoaXMucHJveGllZEV2ZW50c18pIHtcblx0XHRcdGNvbnN0IGV2ZW50cyA9IE9iamVjdC5rZXlzKHRoaXMucHJveGllZEV2ZW50c18pO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzX1tldmVudHNbaV1dLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gbnVsbDtcblx0XHR9XG5cdFx0dGhpcy5wZW5kaW5nRXZlbnRzXyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogQ2hhbmdlcyB0aGUgb3JpZ2luIGVtaXR0ZXIuIFRoaXMgYXV0b21hdGljYWxseSBkZXRhY2hlcyBhbnkgZXZlbnRzIHRoYXRcblx0ICogd2VyZSBhbHJlYWR5IGJlaW5nIHByb3hpZWQgZnJvbSB0aGUgcHJldmlvdXMgZW1pdHRlciwgYW5kIHN0YXJ0cyBwcm94eWluZ1xuXHQgKiB0aGVtIG9uIHRoZSBuZXcgZW1pdHRlciBpbnN0ZWFkLlxuXHQgKiBAcGFyYW0geyFFdmVudEVtaXR0ZXJ9IG9yaWdpbkVtaXR0ZXJcblx0ICovXG5cdHNldE9yaWdpbkVtaXR0ZXIob3JpZ2luRW1pdHRlcikge1xuXHRcdGNvbnN0IGV2ZW50cyA9XG5cdFx0XHR0aGlzLm9yaWdpbkVtaXR0ZXJfICYmIHRoaXMucHJveGllZEV2ZW50c19cblx0XHRcdFx0PyBPYmplY3Qua2V5cyh0aGlzLnByb3hpZWRFdmVudHNfKVxuXHRcdFx0XHQ6IHRoaXMucGVuZGluZ0V2ZW50c187XG5cdFx0dGhpcy5vcmlnaW5FbWl0dGVyXyA9IG9yaWdpbkVtaXR0ZXI7XG5cdFx0aWYgKGV2ZW50cykge1xuXHRcdFx0dGhpcy5yZW1vdmVMaXN0ZW5lcnNfKCk7XG5cdFx0XHRldmVudHMuZm9yRWFjaChldmVudCA9PiB0aGlzLnByb3h5RXZlbnQoZXZlbnQpKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBldmVudCBzaG91bGQgYmUgcHJveGllZC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHNob3VsZFByb3h5RXZlbnRfKGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMud2hpdGVsaXN0XyAmJiAhdGhpcy53aGl0ZWxpc3RfW2V2ZW50XSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRpZiAodGhpcy5ibGFja2xpc3RfICYmIHRoaXMuYmxhY2tsaXN0X1tldmVudF0pIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuICF0aGlzLnByb3hpZWRFdmVudHNfIHx8ICF0aGlzLnByb3hpZWRFdmVudHNfW2V2ZW50XTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTdGFydHMgcHJveHlpbmcgYWxsIGV2ZW50cyBmcm9tIHRoZSBvcmlnaW4gdG8gdGhlIHRhcmdldCBlbWl0dGVyLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRzdGFydFByb3h5XygpIHtcblx0XHR0aGlzLnRhcmdldEVtaXR0ZXJfLm9uTGlzdGVuZXIodGhpcy5wcm94eUV2ZW50LmJpbmQodGhpcykpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0byB0aGUgb3JpZ2luIGVtaXR0ZXIsIGlmIGl0IGV4aXN0cy4gT3RoZXJ3aXNlLCBzdG9yZXNcblx0ICogdGhlIHBlbmRpbmcgbGlzdGVuZXIgc28gaXQgY2FuIGJlIHVzZWQgb24gYSBmdXR1cmUgb3JpZ2luIGVtaXR0ZXIuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHR0cnlUb0FkZExpc3RlbmVyXyhldmVudCkge1xuXHRcdGlmICh0aGlzLm9yaWdpbkVtaXR0ZXJfKSB7XG5cdFx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gdGhpcy5wcm94aWVkRXZlbnRzXyB8fCB7fTtcblx0XHRcdHRoaXMucHJveGllZEV2ZW50c19bZXZlbnRdID0gdGhpcy5hZGRMaXN0ZW5lcl8oXG5cdFx0XHRcdGV2ZW50LFxuXHRcdFx0XHR0aGlzLmVtaXRPblRhcmdldF8uYmluZCh0aGlzLCBldmVudClcblx0XHRcdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMucGVuZGluZ0V2ZW50c18gPSB0aGlzLnBlbmRpbmdFdmVudHNfIHx8IFtdO1xuXHRcdFx0dGhpcy5wZW5kaW5nRXZlbnRzXy5wdXNoKGV2ZW50KTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRXZlbnRFbWl0dGVyUHJveHk7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7RGlzcG9zYWJsZX0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEV2ZW50SGFuZGxlciB1dGlsaXR5LiBJdCdzIHVzZWZ1bCBmb3IgZWFzaWx5IHJlbW92aW5nIGEgZ3JvdXAgb2ZcbiAqIGxpc3RlbmVycyBmcm9tIGRpZmZlcmVudCBFdmVudEVtaXR0ZXIgaW5zdGFuY2VzLlxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIEV2ZW50SGFuZGxlciBleHRlbmRzIERpc3Bvc2FibGUge1xuXHQvKipcblx0ICogRXZlbnRIYW5kbGVyIGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogQW4gYXJyYXkgdGhhdCBob2xkcyB0aGUgYWRkZWQgZXZlbnQgaGFuZGxlcywgc28gdGhlIGxpc3RlbmVycyBjYW4gYmVcblx0XHQgKiByZW1vdmVkIGxhdGVyLlxuXHRcdCAqIEB0eXBlIHtBcnJheS48RXZlbnRIYW5kbGU+fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmV2ZW50SGFuZGxlc18gPSBbXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGV2ZW50IGhhbmRsZXMgdG8gYmUgcmVtb3ZlZCBsYXRlciB0aHJvdWdoIHRoZSBgcmVtb3ZlQWxsTGlzdGVuZXJzYFxuXHQgKiBtZXRob2QuXG5cdCAqIEBwYXJhbSB7Li4uKCFFdmVudEhhbmRsZSl9IHZhcl9hcmdzXG5cdCAqL1xuXHRhZGQoLi4uYXJncykge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmV2ZW50SGFuZGxlc18ucHVzaChhcmdzW2ldKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLmV2ZW50SGFuZGxlc18gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyB0aGF0IGhhdmUgYmVlbiBhZGRlZCB0aHJvdWdoIHRoZSBgYWRkYCBtZXRob2QuXG5cdCAqL1xuXHRyZW1vdmVBbGxMaXN0ZW5lcnMoKSB7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmV2ZW50SGFuZGxlc18ubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuZXZlbnRIYW5kbGVzX1tpXS5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdH1cblxuXHRcdHRoaXMuZXZlbnRIYW5kbGVzXyA9IFtdO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50SGFuZGxlcjtcbiIsIi8qIVxuICogUHJvbWlzZXMgcG9seWZpbGwgZnJvbSBHb29nbGUncyBDbG9zdXJlIExpYnJhcnkuXG4gKlxuICogICAgICBDb3B5cmlnaHQgMjAxMyBUaGUgQ2xvc3VyZSBMaWJyYXJ5IEF1dGhvcnMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogTk9URShlZHVhcmRvKTogUHJvbWlzZSBzdXBwb3J0IGlzIG5vdCByZWFkeSBvbiBhbGwgc3VwcG9ydGVkIGJyb3dzZXJzLFxuICogdGhlcmVmb3JlIG1ldGFsLXByb21pc2UgaXMgdGVtcG9yYXJpbHkgdXNpbmcgR29vZ2xlJ3MgcHJvbWlzZXMgYXMgcG9seWZpbGwuXG4gKiBJdCBzdXBwb3J0cyBjYW5jZWxsYWJsZSBwcm9taXNlcyBhbmQgaGFzIGNsZWFuIGFuZCBmYXN0IGltcGxlbWVudGF0aW9uLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaXNEZWYsIGlzRnVuY3Rpb24sIGlzT2JqZWN0IH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgYXN5bmMgfSBmcm9tICdtZXRhbCc7XG5cbi8qKlxuICogUHJvdmlkZXMgYSBtb3JlIHN0cmljdCBpbnRlcmZhY2UgZm9yIFRoZW5hYmxlcyBpbiB0ZXJtcyBvZlxuICogaHR0cDovL3Byb21pc2VzYXBsdXMuY29tIGZvciBpbnRlcm9wIHdpdGgge0BzZWUgQ2FuY2VsbGFibGVQcm9taXNlfS5cbiAqXG4gKiBAaW50ZXJmYWNlXG4gKiBAZXh0ZW5kcyB7SVRoZW5hYmxlLjxUWVBFPn1cbiAqIEB0ZW1wbGF0ZSBUWVBFXG4gKi9cbnZhciBUaGVuYWJsZSA9IGZ1bmN0aW9uKCkge307XG5cbi8qKlxuICogQWRkcyBjYWxsYmFja3MgdGhhdCB3aWxsIG9wZXJhdGUgb24gdGhlIHJlc3VsdCBvZiB0aGUgVGhlbmFibGUsIHJldHVybmluZyBhXG4gKiBuZXcgY2hpbGQgUHJvbWlzZS5cbiAqXG4gKiBJZiB0aGUgVGhlbmFibGUgaXMgZnVsZmlsbGVkLCB0aGUge0Bjb2RlIG9uRnVsZmlsbGVkfSBjYWxsYmFjayB3aWxsIGJlXG4gKiBpbnZva2VkIHdpdGggdGhlIGZ1bGZpbGxtZW50IHZhbHVlIGFzIGFyZ3VtZW50LCBhbmQgdGhlIGNoaWxkIFByb21pc2Ugd2lsbFxuICogYmUgZnVsZmlsbGVkIHdpdGggdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgY2FsbGJhY2suIElmIHRoZSBjYWxsYmFjayB0aHJvd3NcbiAqIGFuIGV4Y2VwdGlvbiwgdGhlIGNoaWxkIFByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSB0aHJvd24gdmFsdWVcbiAqIGluc3RlYWQuXG4gKlxuICogSWYgdGhlIFRoZW5hYmxlIGlzIHJlamVjdGVkLCB0aGUge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrIHdpbGwgYmUgaW52b2tlZFxuICogd2l0aCB0aGUgcmVqZWN0aW9uIHJlYXNvbiBhcyBhcmd1bWVudCwgYW5kIHRoZSBjaGlsZCBQcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWRcbiAqIHdpdGggdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgY2FsbGJhY2sgb3IgdGhyb3duIHZhbHVlLlxuICpcbiAqIEBwYXJhbSB7PyhmdW5jdGlvbih0aGlzOlRISVMsIFRZUEUpOlxuICogICAgICAgICAgICAgKFJFU1VMVHxJVGhlbmFibGUuPFJFU1VMVD58VGhlbmFibGUpKT19IG9wdF9vbkZ1bGZpbGxlZCBBXG4gKiAgICAgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGludm9rZWQgd2l0aCB0aGUgZnVsZmlsbG1lbnQgdmFsdWUgaWYgdGhlIFByb21pc2VcbiAqICAgICBpcyBmdWxsZmlsbGVkLlxuICogQHBhcmFtIHs/KGZ1bmN0aW9uKCopOiAqKT19IG9wdF9vblJlamVjdGVkIEEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGludm9rZWRcbiAqICAgICB3aXRoIHRoZSByZWplY3Rpb24gcmVhc29uIGlmIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLlxuICogQHBhcmFtIHtUSElTPX0gb3B0X2NvbnRleHQgQW4gb3B0aW9uYWwgY29udGV4dCBvYmplY3QgdGhhdCB3aWxsIGJlIHRoZVxuICogICAgIGV4ZWN1dGlvbiBjb250ZXh0IGZvciB0aGUgY2FsbGJhY2tzLiBCeSBkZWZhdWx0LCBmdW5jdGlvbnMgYXJlIGV4ZWN1dGVkXG4gKiAgICAgd2l0aCB0aGUgZGVmYXVsdCB0aGlzLlxuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZS48UkVTVUxUPn0gQSBuZXcgUHJvbWlzZSB0aGF0IHdpbGwgcmVjZWl2ZSB0aGVcbiAqICAgICByZXN1bHQgb2YgdGhlIGZ1bGZpbGxtZW50IG9yIHJlamVjdGlvbiBjYWxsYmFjay5cbiAqIEB0ZW1wbGF0ZSBSRVNVTFQsVEhJU1xuICovXG5UaGVuYWJsZS5wcm90b3R5cGUudGhlbiA9IGZ1bmN0aW9uKCkge307XG5cblxuLyoqXG4gKiBBbiBleHBhbmRvIHByb3BlcnR5IHRvIGluZGljYXRlIHRoYXQgYW4gb2JqZWN0IGltcGxlbWVudHNcbiAqIHtAY29kZSBUaGVuYWJsZX0uXG4gKlxuICoge0BzZWUgYWRkSW1wbGVtZW50YXRpb259LlxuICpcbiAqIEBjb25zdFxuICovXG5UaGVuYWJsZS5JTVBMRU1FTlRFRF9CWV9QUk9QID0gJyRnb29nX1RoZW5hYmxlJztcblxuXG4vKipcbiAqIE1hcmtzIGEgZ2l2ZW4gY2xhc3MgKGNvbnN0cnVjdG9yKSBhcyBhbiBpbXBsZW1lbnRhdGlvbiBvZiBUaGVuYWJsZSwgc29cbiAqIHRoYXQgd2UgY2FuIHF1ZXJ5IHRoYXQgZmFjdCBhdCBydW50aW1lLiBUaGUgY2xhc3MgbXVzdCBoYXZlIGFscmVhZHlcbiAqIGltcGxlbWVudGVkIHRoZSBpbnRlcmZhY2UuXG4gKiBFeHBvcnRzIGEgJ3RoZW4nIG1ldGhvZCBvbiB0aGUgY29uc3RydWN0b3IgcHJvdG90eXBlLCBzbyB0aGF0IHRoZSBvYmplY3RzXG4gKiBhbHNvIGltcGxlbWVudCB0aGUgZXh0ZXJuIHtAc2VlIFRoZW5hYmxlfSBpbnRlcmZhY2UgZm9yIGludGVyb3Agd2l0aFxuICogb3RoZXIgUHJvbWlzZSBpbXBsZW1lbnRhdGlvbnMuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKG5ldzpUaGVuYWJsZSwuLi5bP10pfSBjdG9yIFRoZSBjbGFzcyBjb25zdHJ1Y3Rvci4gVGhlXG4gKiAgICAgY29ycmVzcG9uZGluZyBjbGFzcyBtdXN0IGhhdmUgYWxyZWFkeSBpbXBsZW1lbnRlZCB0aGUgaW50ZXJmYWNlLlxuICovXG5UaGVuYWJsZS5hZGRJbXBsZW1lbnRhdGlvbiA9IGZ1bmN0aW9uKGN0b3IpIHtcbiAgY3Rvci5wcm90b3R5cGUudGhlbiA9IGN0b3IucHJvdG90eXBlLnRoZW47XG4gIGN0b3IucHJvdG90eXBlLiRnb29nX1RoZW5hYmxlID0gdHJ1ZTtcbn07XG5cblxuLyoqXG4gKiBAcGFyYW0geyp9IG9iamVjdFxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciBhIGdpdmVuIGluc3RhbmNlIGltcGxlbWVudHMge0Bjb2RlIFRoZW5hYmxlfS5cbiAqICAgICBUaGUgY2xhc3Mvc3VwZXJjbGFzcyBvZiB0aGUgaW5zdGFuY2UgbXVzdCBjYWxsIHtAY29kZSBhZGRJbXBsZW1lbnRhdGlvbn0uXG4gKi9cblRoZW5hYmxlLmlzSW1wbGVtZW50ZWRCeSA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICBpZiAoIW9iamVjdCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICB0cnkge1xuICAgIHJldHVybiAhIW9iamVjdC4kZ29vZ19UaGVuYWJsZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIFByb3BlcnR5IGFjY2VzcyBzZWVtcyB0byBiZSBmb3JiaWRkZW4uXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5cbi8qKlxuICogTGlrZSBiaW5kKCksIGV4Y2VwdCB0aGF0IGEgJ3RoaXMgb2JqZWN0JyBpcyBub3QgcmVxdWlyZWQuIFVzZWZ1bCB3aGVuIHRoZVxuICogdGFyZ2V0IGZ1bmN0aW9uIGlzIGFscmVhZHkgYm91bmQuXG4gKlxuICogVXNhZ2U6XG4gKiB2YXIgZyA9IHBhcnRpYWwoZiwgYXJnMSwgYXJnMik7XG4gKiBnKGFyZzMsIGFyZzQpO1xuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEEgZnVuY3Rpb24gdG8gcGFydGlhbGx5IGFwcGx5LlxuICogQHBhcmFtIHsuLi4qfSB2YXJfYXJncyBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0aGF0IGFyZSBwYXJ0aWFsbHkgYXBwbGllZCB0byBmbi5cbiAqIEByZXR1cm4geyFGdW5jdGlvbn0gQSBwYXJ0aWFsbHktYXBwbGllZCBmb3JtIG9mIHRoZSBmdW5jdGlvbiBiaW5kKCkgd2FzXG4gKiAgICAgaW52b2tlZCBhcyBhIG1ldGhvZCBvZi5cbiAqL1xudmFyIHBhcnRpYWwgPSBmdW5jdGlvbihmbikge1xuICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAvLyBDbG9uZSB0aGUgYXJyYXkgKHdpdGggc2xpY2UoKSkgYW5kIGFwcGVuZCBhZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgIC8vIHRvIHRoZSBleGlzdGluZyBhcmd1bWVudHMuXG4gICAgdmFyIG5ld0FyZ3MgPSBhcmdzLnNsaWNlKCk7XG4gICAgbmV3QXJncy5wdXNoLmFwcGx5KG5ld0FyZ3MsIGFyZ3VtZW50cyk7XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIG5ld0FyZ3MpO1xuICB9O1xufTtcblxuLyoqXG4gKiBQcm9taXNlcyBwcm92aWRlIGEgcmVzdWx0IHRoYXQgbWF5IGJlIHJlc29sdmVkIGFzeW5jaHJvbm91c2x5LiBBIFByb21pc2UgbWF5XG4gKiBiZSByZXNvbHZlZCBieSBiZWluZyBmdWxmaWxsZWQgb3IgcmVqZWN0ZWQgd2l0aCBhIHZhbHVlLCB3aGljaCB3aWxsIGJlIGtub3duXG4gKiBhcyB0aGUgZnVsZmlsbG1lbnQgdmFsdWUgb3IgdGhlIHJlamVjdGlvbiByZWFzb24uIFdoZXRoZXIgZnVsZmlsbGVkIG9yXG4gKiByZWplY3RlZCwgdGhlIFByb21pc2UgcmVzdWx0IGlzIGltbXV0YWJsZSBvbmNlIGl0IGlzIHNldC5cbiAqXG4gKiBQcm9taXNlcyBtYXkgcmVwcmVzZW50IHJlc3VsdHMgb2YgYW55IHR5cGUsIGluY2x1ZGluZyB1bmRlZmluZWQuIFJlamVjdGlvblxuICogcmVhc29ucyBhcmUgdHlwaWNhbGx5IEVycm9ycywgYnV0IG1heSBhbHNvIGJlIG9mIGFueSB0eXBlLiBDbG9zdXJlIFByb21pc2VzXG4gKiBhbGxvdyBmb3Igb3B0aW9uYWwgdHlwZSBhbm5vdGF0aW9ucyB0aGF0IGVuZm9yY2UgdGhhdCBmdWxmaWxsbWVudCB2YWx1ZXMgYXJlXG4gKiBvZiB0aGUgYXBwcm9wcmlhdGUgdHlwZXMgYXQgY29tcGlsZSB0aW1lLlxuICpcbiAqIFRoZSByZXN1bHQgb2YgYSBQcm9taXNlIGlzIGFjY2Vzc2libGUgYnkgY2FsbGluZyB7QGNvZGUgdGhlbn0gYW5kIHJlZ2lzdGVyaW5nXG4gKiB7QGNvZGUgb25GdWxmaWxsZWR9IGFuZCB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2tzLiBPbmNlIHRoZSBQcm9taXNlXG4gKiByZXNvbHZlcywgdGhlIHJlbGV2YW50IGNhbGxiYWNrcyBhcmUgaW52b2tlZCB3aXRoIHRoZSBmdWxmaWxsbWVudCB2YWx1ZSBvclxuICogcmVqZWN0aW9uIHJlYXNvbiBhcyBhcmd1bWVudC4gQ2FsbGJhY2tzIGFyZSBhbHdheXMgaW52b2tlZCBpbiB0aGUgb3JkZXIgdGhleVxuICogd2VyZSByZWdpc3RlcmVkLCBldmVuIHdoZW4gYWRkaXRpb25hbCB7QGNvZGUgdGhlbn0gY2FsbHMgYXJlIG1hZGUgZnJvbSBpbnNpZGVcbiAqIGFub3RoZXIgY2FsbGJhY2suIEEgY2FsbGJhY2sgaXMgYWx3YXlzIHJ1biBhc3luY2hyb25vdXNseSBzb21ldGltZSBhZnRlciB0aGVcbiAqIHNjb3BlIGNvbnRhaW5pbmcgdGhlIHJlZ2lzdGVyaW5nIHtAY29kZSB0aGVufSBpbnZvY2F0aW9uIGhhcyByZXR1cm5lZC5cbiAqXG4gKiBJZiBhIFByb21pc2UgaXMgcmVzb2x2ZWQgd2l0aCBhbm90aGVyIFByb21pc2UsIHRoZSBmaXJzdCBQcm9taXNlIHdpbGwgYmxvY2tcbiAqIHVudGlsIHRoZSBzZWNvbmQgaXMgcmVzb2x2ZWQsIGFuZCB0aGVuIGFzc3VtZXMgdGhlIHNhbWUgcmVzdWx0IGFzIHRoZSBzZWNvbmRcbiAqIFByb21pc2UuIFRoaXMgYWxsb3dzIFByb21pc2VzIHRvIGRlcGVuZCBvbiB0aGUgcmVzdWx0cyBvZiBvdGhlciBQcm9taXNlcyxcbiAqIGxpbmtpbmcgdG9nZXRoZXIgbXVsdGlwbGUgYXN5bmNocm9ub3VzIG9wZXJhdGlvbnMuXG4gKlxuICogVGhpcyBpbXBsZW1lbnRhdGlvbiBpcyBjb21wYXRpYmxlIHdpdGggdGhlIFByb21pc2VzL0ErIHNwZWNpZmljYXRpb24gYW5kXG4gKiBwYXNzZXMgdGhhdCBzcGVjaWZpY2F0aW9uJ3MgY29uZm9ybWFuY2UgdGVzdCBzdWl0ZS4gQSBDbG9zdXJlIFByb21pc2UgbWF5IGJlXG4gKiByZXNvbHZlZCB3aXRoIGEgUHJvbWlzZSBpbnN0YW5jZSAob3Igc3VmZmljaWVudGx5IGNvbXBhdGlibGUgUHJvbWlzZS1saWtlXG4gKiBvYmplY3QpIGNyZWF0ZWQgYnkgb3RoZXIgUHJvbWlzZSBpbXBsZW1lbnRhdGlvbnMuIEZyb20gdGhlIHNwZWNpZmljYXRpb24sXG4gKiBQcm9taXNlLWxpa2Ugb2JqZWN0cyBhcmUga25vd24gYXMgXCJUaGVuYWJsZXNcIi5cbiAqXG4gKiBAc2VlIGh0dHA6Ly9wcm9taXNlc2FwbHVzLmNvbS9cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKFxuICogICAgICAgICAgICAgdGhpczpSRVNPTFZFUl9DT05URVhULFxuICogICAgICAgICAgICAgZnVuY3Rpb24oKFRZUEV8SVRoZW5hYmxlLjxUWVBFPnxUaGVuYWJsZSkpLFxuICogICAgICAgICAgICAgZnVuY3Rpb24oKikpOiB2b2lkfSByZXNvbHZlclxuICogICAgIEluaXRpYWxpemF0aW9uIGZ1bmN0aW9uIHRoYXQgaXMgaW52b2tlZCBpbW1lZGlhdGVseSB3aXRoIHtAY29kZSByZXNvbHZlfVxuICogICAgIGFuZCB7QGNvZGUgcmVqZWN0fSBmdW5jdGlvbnMgYXMgYXJndW1lbnRzLiBUaGUgUHJvbWlzZSBpcyByZXNvbHZlZCBvclxuICogICAgIHJlamVjdGVkIHdpdGggdGhlIGZpcnN0IGFyZ3VtZW50IHBhc3NlZCB0byBlaXRoZXIgZnVuY3Rpb24uXG4gKiBAcGFyYW0ge1JFU09MVkVSX0NPTlRFWFQ9fSBvcHRfY29udGV4dCBBbiBvcHRpb25hbCBjb250ZXh0IGZvciBleGVjdXRpbmcgdGhlXG4gKiAgICAgcmVzb2x2ZXIgZnVuY3Rpb24uIElmIHVuc3BlY2lmaWVkLCB0aGUgcmVzb2x2ZXIgZnVuY3Rpb24gd2lsbCBiZSBleGVjdXRlZFxuICogICAgIGluIHRoZSBkZWZhdWx0IHNjb3BlLlxuICogQGNvbnN0cnVjdG9yXG4gKiBAc3RydWN0XG4gKiBAZmluYWxcbiAqIEBpbXBsZW1lbnRzIHtUaGVuYWJsZS48VFlQRT59XG4gKiBAdGVtcGxhdGUgVFlQRSxSRVNPTFZFUl9DT05URVhUXG4gKi9cbnZhciBDYW5jZWxsYWJsZVByb21pc2UgPSBmdW5jdGlvbihyZXNvbHZlciwgb3B0X2NvbnRleHQpIHtcbiAgLyoqXG4gICAqIFRoZSBpbnRlcm5hbCBzdGF0ZSBvZiB0aGlzIFByb21pc2UuIEVpdGhlciBQRU5ESU5HLCBGVUxGSUxMRUQsIFJFSkVDVEVELCBvclxuICAgKiBCTE9DS0VELlxuICAgKiBAcHJpdmF0ZSB7Q2FuY2VsbGFibGVQcm9taXNlLlN0YXRlX31cbiAgICovXG4gIHRoaXMuc3RhdGVfID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5QRU5ESU5HO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVzb2x2ZWQgcmVzdWx0IG9mIHRoZSBQcm9taXNlLiBJbW11dGFibGUgb25jZSBzZXQgd2l0aCBlaXRoZXIgYVxuICAgKiBmdWxmaWxsbWVudCB2YWx1ZSBvciByZWplY3Rpb24gcmVhc29uLlxuICAgKiBAcHJpdmF0ZSB7Kn1cbiAgICovXG4gIHRoaXMucmVzdWx0XyA9IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogRm9yIFByb21pc2VzIGNyZWF0ZWQgYnkgY2FsbGluZyB7QGNvZGUgdGhlbigpfSwgdGhlIG9yaWdpbmF0aW5nIHBhcmVudC5cbiAgICogQHByaXZhdGUge0NhbmNlbGxhYmxlUHJvbWlzZX1cbiAgICovXG4gIHRoaXMucGFyZW50XyA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFRoZSBsaXN0IG9mIHtAY29kZSBvbkZ1bGZpbGxlZH0gYW5kIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFja3MgYWRkZWQgdG9cbiAgICogdGhpcyBQcm9taXNlIGJ5IGNhbGxzIHRvIHtAY29kZSB0aGVuKCl9LlxuICAgKiBAcHJpdmF0ZSB7QXJyYXkuPENhbmNlbGxhYmxlUHJvbWlzZS5DYWxsYmFja0VudHJ5Xz59XG4gICAqL1xuICB0aGlzLmNhbGxiYWNrRW50cmllc18gPSBudWxsO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBQcm9taXNlIGlzIGluIHRoZSBxdWV1ZSBvZiBQcm9taXNlcyB0byBleGVjdXRlLlxuICAgKiBAcHJpdmF0ZSB7Ym9vbGVhbn1cbiAgICovXG4gIHRoaXMuZXhlY3V0aW5nXyA9IGZhbHNlO1xuXG4gIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA+IDApIHtcbiAgICAvKipcbiAgICAgKiBBIHRpbWVvdXQgSUQgdXNlZCB3aGVuIHRoZSB7QGNvZGUgVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWX0gaXMgZ3JlYXRlclxuICAgICAqIHRoYW4gMCBtaWxsaXNlY29uZHMuIFRoZSBJRCBpcyBzZXQgd2hlbiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZCwgYW5kXG4gICAgICogY2xlYXJlZCBvbmx5IGlmIGFuIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFjayBpcyBpbnZva2VkIGZvciB0aGVcbiAgICAgKiBQcm9taXNlIChvciBvbmUgb2YgaXRzIGRlc2NlbmRhbnRzKSBiZWZvcmUgdGhlIGRlbGF5IGlzIGV4Y2VlZGVkLlxuICAgICAqXG4gICAgICogSWYgdGhlIHJlamVjdGlvbiBpcyBub3QgaGFuZGxlZCBiZWZvcmUgdGhlIHRpbWVvdXQgY29tcGxldGVzLCB0aGVcbiAgICAgKiByZWplY3Rpb24gcmVhc29uIGlzIHBhc3NlZCB0byB0aGUgdW5oYW5kbGVkIHJlamVjdGlvbiBoYW5kbGVyLlxuICAgICAqIEBwcml2YXRlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy51bmhhbmRsZWRSZWplY3Rpb25JZF8gPSAwO1xuICB9IGVsc2UgaWYgKENhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZID09PSAwKSB7XG4gICAgLyoqXG4gICAgICogV2hlbiB0aGUge0Bjb2RlIFVOSEFORExFRF9SRUpFQ1RJT05fREVMQVl9IGlzIHNldCB0byAwIG1pbGxpc2Vjb25kcywgYVxuICAgICAqIGJvb2xlYW4gdGhhdCBpcyBzZXQgaWYgdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQsIGFuZCByZXNldCB0byBmYWxzZSBpZiBhblxuICAgICAqIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFjayBpcyBpbnZva2VkIGZvciB0aGUgUHJvbWlzZSAob3Igb25lIG9mIGl0c1xuICAgICAqIGRlc2NlbmRhbnRzKS4gSWYgdGhlIHJlamVjdGlvbiBpcyBub3QgaGFuZGxlZCBiZWZvcmUgdGhlIG5leHQgdGltZXN0ZXAsXG4gICAgICogdGhlIHJlamVjdGlvbiByZWFzb24gaXMgcGFzc2VkIHRvIHRoZSB1bmhhbmRsZWQgcmVqZWN0aW9uIGhhbmRsZXIuXG4gICAgICogQHByaXZhdGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgdGhpcy5oYWRVbmhhbmRsZWRSZWplY3Rpb25fID0gZmFsc2U7XG4gIH1cblxuICB0cnkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICByZXNvbHZlci5jYWxsKFxuICAgICAgb3B0X2NvbnRleHQsIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHNlbGYucmVzb2x2ZV8oQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5GVUxGSUxMRUQsIHZhbHVlKTtcbiAgICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikge1xuICAgICAgICBzZWxmLnJlc29sdmVfKENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQsIHJlYXNvbik7XG4gICAgICB9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRoaXMucmVzb2x2ZV8oQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCwgZSk7XG4gIH1cbn07XG5cbi8qKlxuICogVGhlIGRlbGF5IGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgYSByZWplY3RlZCBQcm9taXNlJ3MgcmVhc29uIGlzIHBhc3NlZCB0b1xuICogdGhlIHJlamVjdGlvbiBoYW5kbGVyLiBCeSBkZWZhdWx0LCB0aGUgcmVqZWN0aW9uIGhhbmRsZXIgcmV0aHJvd3MgdGhlXG4gKiByZWplY3Rpb24gcmVhc29uIHNvIHRoYXQgaXQgYXBwZWFycyBpbiB0aGUgZGV2ZWxvcGVyIGNvbnNvbGUgb3JcbiAqIHtAY29kZSB3aW5kb3cub25lcnJvcn0gaGFuZGxlci5cbiAqIFJlamVjdGlvbnMgYXJlIHJldGhyb3duIGFzIHF1aWNrbHkgYXMgcG9zc2libGUgYnkgZGVmYXVsdC4gQSBuZWdhdGl2ZSB2YWx1ZVxuICogZGlzYWJsZXMgcmVqZWN0aW9uIGhhbmRsaW5nIGVudGlyZWx5LlxuICogQHR5cGUge251bWJlcn1cbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLlVOSEFORExFRF9SRUpFQ1RJT05fREVMQVkgPSAwO1xuXG5cbi8qKlxuICogVGhlIHBvc3NpYmxlIGludGVybmFsIHN0YXRlcyBmb3IgYSBQcm9taXNlLiBUaGVzZSBzdGF0ZXMgYXJlIG5vdCBkaXJlY3RseVxuICogb2JzZXJ2YWJsZSB0byBleHRlcm5hbCBjYWxsZXJzLlxuICogQGVudW0ge251bWJlcn1cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8gPSB7XG4gIC8qKiBUaGUgUHJvbWlzZSBpcyB3YWl0aW5nIGZvciByZXNvbHV0aW9uLiAqL1xuICBQRU5ESU5HOiAwLFxuXG4gIC8qKiBUaGUgUHJvbWlzZSBpcyBibG9ja2VkIHdhaXRpbmcgZm9yIHRoZSByZXN1bHQgb2YgYW5vdGhlciBUaGVuYWJsZS4gKi9cbiAgQkxPQ0tFRDogMSxcblxuICAvKiogVGhlIFByb21pc2UgaGFzIGJlZW4gcmVzb2x2ZWQgd2l0aCBhIGZ1bGZpbGxtZW50IHZhbHVlLiAqL1xuICBGVUxGSUxMRUQ6IDIsXG5cbiAgLyoqIFRoZSBQcm9taXNlIGhhcyBiZWVuIHJlc29sdmVkIHdpdGggYSByZWplY3Rpb24gcmVhc29uLiAqL1xuICBSRUpFQ1RFRDogM1xufTtcblxuXG4vKipcbiAqIFR5cGVkZWYgZm9yIGVudHJpZXMgaW4gdGhlIGNhbGxiYWNrIGNoYWluLiBFYWNoIGNhbGwgdG8ge0Bjb2RlIHRoZW59LFxuICoge0Bjb2RlIHRoZW5DYXRjaH0sIG9yIHtAY29kZSB0aGVuQWx3YXlzfSBjcmVhdGVzIGFuIGVudHJ5IGNvbnRhaW5pbmcgdGhlXG4gKiBmdW5jdGlvbnMgdGhhdCBtYXkgYmUgaW52b2tlZCBvbmNlIHRoZSBQcm9taXNlIGlzIHJlc29sdmVkLlxuICpcbiAqIEB0eXBlZGVmIHt7XG4gKiAgIGNoaWxkOiBDYW5jZWxsYWJsZVByb21pc2UsXG4gKiAgIG9uRnVsZmlsbGVkOiBmdW5jdGlvbigqKSxcbiAqICAgb25SZWplY3RlZDogZnVuY3Rpb24oKilcbiAqIH19XG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuQ2FsbGJhY2tFbnRyeV8gPSBudWxsO1xuXG5cbi8qKlxuICogQHBhcmFtIHsoVFlQRXxUaGVuYWJsZS48VFlQRT58VGhlbmFibGUpPX0gb3B0X3ZhbHVlXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlLjxUWVBFPn0gQSBuZXcgUHJvbWlzZSB0aGF0IGlzIGltbWVkaWF0ZWx5IHJlc29sdmVkXG4gKiAgICAgd2l0aCB0aGUgZ2l2ZW4gdmFsdWUuXG4gKiBAdGVtcGxhdGUgVFlQRVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSA9IGZ1bmN0aW9uKG9wdF92YWx1ZSkge1xuICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7XG4gICAgICByZXNvbHZlKG9wdF92YWx1ZSk7XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQHBhcmFtIHsqPX0gb3B0X3JlYXNvblxuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZX0gQSBuZXcgUHJvbWlzZSB0aGF0IGlzIGltbWVkaWF0ZWx5IHJlamVjdGVkIHdpdGggdGhlXG4gKiAgICAgZ2l2ZW4gcmVhc29uLlxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucmVqZWN0ID0gZnVuY3Rpb24ob3B0X3JlYXNvbikge1xuICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIHJlamVjdChvcHRfcmVhc29uKTtcbiAgICB9KTtcbn07XG5cblxuLyoqXG4gKiBAcGFyYW0geyFBcnJheS48IShUaGVuYWJsZS48VFlQRT58VGhlbmFibGUpPn0gcHJvbWlzZXNcbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2UuPFRZUEU+fSBBIFByb21pc2UgdGhhdCByZWNlaXZlcyB0aGUgcmVzdWx0IG9mIHRoZVxuICogICAgIGZpcnN0IFByb21pc2UgKG9yIFByb21pc2UtbGlrZSkgaW5wdXQgdG8gY29tcGxldGUuXG4gKiBAdGVtcGxhdGUgVFlQRVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucmFjZSA9IGZ1bmN0aW9uKHByb21pc2VzKSB7XG4gIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgaWYgKCFwcm9taXNlcy5sZW5ndGgpIHtcbiAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIgaSA9IDAsIHByb21pc2U7IChwcm9taXNlID0gcHJvbWlzZXNbaV0pOyBpKyspIHtcbiAgICAgICAgcHJvbWlzZS50aGVuKHJlc29sdmUsIHJlamVjdCk7XG4gICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQHBhcmFtIHshQXJyYXkuPCEoVGhlbmFibGUuPFRZUEU+fFRoZW5hYmxlKT59IHByb21pc2VzXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlLjwhQXJyYXkuPFRZUEU+Pn0gQSBQcm9taXNlIHRoYXQgcmVjZWl2ZXMgYSBsaXN0IG9mXG4gKiAgICAgZXZlcnkgZnVsZmlsbGVkIHZhbHVlIG9uY2UgZXZlcnkgaW5wdXQgUHJvbWlzZSAob3IgUHJvbWlzZS1saWtlKSBpc1xuICogICAgIHN1Y2Nlc3NmdWxseSBmdWxmaWxsZWQsIG9yIGlzIHJlamVjdGVkIGJ5IHRoZSBmaXJzdCByZWplY3Rpb24gcmVzdWx0LlxuICogQHRlbXBsYXRlIFRZUEVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLmFsbCA9IGZ1bmN0aW9uKHByb21pc2VzKSB7XG4gIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdmFyIHRvRnVsZmlsbCA9IHByb21pc2VzLmxlbmd0aDtcbiAgICAgIHZhciB2YWx1ZXMgPSBbXTtcblxuICAgICAgaWYgKCF0b0Z1bGZpbGwpIHtcbiAgICAgICAgcmVzb2x2ZSh2YWx1ZXMpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBvbkZ1bGZpbGwgPSBmdW5jdGlvbihpbmRleCwgdmFsdWUpIHtcbiAgICAgICAgdG9GdWxmaWxsLS07XG4gICAgICAgIHZhbHVlc1tpbmRleF0gPSB2YWx1ZTtcbiAgICAgICAgaWYgKHRvRnVsZmlsbCA9PT0gMCkge1xuICAgICAgICAgIHJlc29sdmUodmFsdWVzKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgdmFyIG9uUmVqZWN0ID0gZnVuY3Rpb24ocmVhc29uKSB7XG4gICAgICAgIHJlamVjdChyZWFzb24pO1xuICAgICAgfTtcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIHByb21pc2U7IChwcm9taXNlID0gcHJvbWlzZXNbaV0pOyBpKyspIHtcbiAgICAgICAgcHJvbWlzZS50aGVuKHBhcnRpYWwob25GdWxmaWxsLCBpKSwgb25SZWplY3QpO1xuICAgICAgfVxuICAgIH0pO1xufTtcblxuXG4vKipcbiAqIEBwYXJhbSB7IUFycmF5LjwhKFRoZW5hYmxlLjxUWVBFPnxUaGVuYWJsZSk+fSBwcm9taXNlc1xuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZS48VFlQRT59IEEgUHJvbWlzZSB0aGF0IHJlY2VpdmVzIHRoZSB2YWx1ZSBvZlxuICogICAgIHRoZSBmaXJzdCBpbnB1dCB0byBiZSBmdWxmaWxsZWQsIG9yIGlzIHJlamVjdGVkIHdpdGggYSBsaXN0IG9mIGV2ZXJ5XG4gKiAgICAgcmVqZWN0aW9uIHJlYXNvbiBpZiBhbGwgaW5wdXRzIGFyZSByZWplY3RlZC5cbiAqIEB0ZW1wbGF0ZSBUWVBFXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5maXJzdEZ1bGZpbGxlZCA9IGZ1bmN0aW9uKHByb21pc2VzKSB7XG4gIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdmFyIHRvUmVqZWN0ID0gcHJvbWlzZXMubGVuZ3RoO1xuICAgICAgdmFyIHJlYXNvbnMgPSBbXTtcblxuICAgICAgaWYgKCF0b1JlamVjdCkge1xuICAgICAgICByZXNvbHZlKHVuZGVmaW5lZCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIG9uRnVsZmlsbCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJlc29sdmUodmFsdWUpO1xuICAgICAgfTtcblxuICAgICAgdmFyIG9uUmVqZWN0ID0gZnVuY3Rpb24oaW5kZXgsIHJlYXNvbikge1xuICAgICAgICB0b1JlamVjdC0tO1xuICAgICAgICByZWFzb25zW2luZGV4XSA9IHJlYXNvbjtcbiAgICAgICAgaWYgKHRvUmVqZWN0ID09PSAwKSB7XG4gICAgICAgICAgcmVqZWN0KHJlYXNvbnMpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBmb3IgKHZhciBpID0gMCwgcHJvbWlzZTsgKHByb21pc2UgPSBwcm9taXNlc1tpXSk7IGkrKykge1xuICAgICAgICBwcm9taXNlLnRoZW4ob25GdWxmaWxsLCBwYXJ0aWFsKG9uUmVqZWN0LCBpKSk7XG4gICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQWRkcyBjYWxsYmFja3MgdGhhdCB3aWxsIG9wZXJhdGUgb24gdGhlIHJlc3VsdCBvZiB0aGUgUHJvbWlzZSwgcmV0dXJuaW5nIGFcbiAqIG5ldyBjaGlsZCBQcm9taXNlLlxuICpcbiAqIElmIHRoZSBQcm9taXNlIGlzIGZ1bGZpbGxlZCwgdGhlIHtAY29kZSBvbkZ1bGZpbGxlZH0gY2FsbGJhY2sgd2lsbCBiZSBpbnZva2VkXG4gKiB3aXRoIHRoZSBmdWxmaWxsbWVudCB2YWx1ZSBhcyBhcmd1bWVudCwgYW5kIHRoZSBjaGlsZCBQcm9taXNlIHdpbGwgYmVcbiAqIGZ1bGZpbGxlZCB3aXRoIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGNhbGxiYWNrLiBJZiB0aGUgY2FsbGJhY2sgdGhyb3dzIGFuXG4gKiBleGNlcHRpb24sIHRoZSBjaGlsZCBQcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWQgd2l0aCB0aGUgdGhyb3duIHZhbHVlIGluc3RlYWQuXG4gKlxuICogSWYgdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQsIHRoZSB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2sgd2lsbCBiZSBpbnZva2VkXG4gKiB3aXRoIHRoZSByZWplY3Rpb24gcmVhc29uIGFzIGFyZ3VtZW50LCBhbmQgdGhlIGNoaWxkIFByb21pc2Ugd2lsbCBiZSByZWplY3RlZFxuICogd2l0aCB0aGUgcmV0dXJuIHZhbHVlIChvciB0aHJvd24gdmFsdWUpIG9mIHRoZSBjYWxsYmFjay5cbiAqXG4gKiBAb3ZlcnJpZGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS50aGVuID0gZnVuY3Rpb24ob3B0X29uRnVsZmlsbGVkLCBvcHRfb25SZWplY3RlZCwgb3B0X2NvbnRleHQpIHtcbiAgcmV0dXJuIHRoaXMuYWRkQ2hpbGRQcm9taXNlXyhcbiAgICBpc0Z1bmN0aW9uKG9wdF9vbkZ1bGZpbGxlZCkgPyBvcHRfb25GdWxmaWxsZWQgOiBudWxsLFxuICAgIGlzRnVuY3Rpb24ob3B0X29uUmVqZWN0ZWQpID8gb3B0X29uUmVqZWN0ZWQgOiBudWxsLFxuICAgIG9wdF9jb250ZXh0KTtcbn07XG5UaGVuYWJsZS5hZGRJbXBsZW1lbnRhdGlvbihDYW5jZWxsYWJsZVByb21pc2UpO1xuXG5cbi8qKlxuICogQWRkcyBhIGNhbGxiYWNrIHRoYXQgd2lsbCBiZSBpbnZva2VkIHdoZXRoZXIgdGhlIFByb21pc2UgaXMgZnVsZmlsbGVkIG9yXG4gKiByZWplY3RlZC4gVGhlIGNhbGxiYWNrIHJlY2VpdmVzIG5vIGFyZ3VtZW50LCBhbmQgbm8gbmV3IGNoaWxkIFByb21pc2UgaXNcbiAqIGNyZWF0ZWQuIFRoaXMgaXMgdXNlZnVsIGZvciBlbnN1cmluZyB0aGF0IGNsZWFudXAgdGFrZXMgcGxhY2UgYWZ0ZXIgY2VydGFpblxuICogYXN5bmNocm9ub3VzIG9wZXJhdGlvbnMuIENhbGxiYWNrcyBhZGRlZCB3aXRoIHtAY29kZSB0aGVuQWx3YXlzfSB3aWxsIGJlXG4gKiBleGVjdXRlZCBpbiB0aGUgc2FtZSBvcmRlciB3aXRoIG90aGVyIGNhbGxzIHRvIHtAY29kZSB0aGVufSxcbiAqIHtAY29kZSB0aGVuQWx3YXlzfSwgb3Ige0Bjb2RlIHRoZW5DYXRjaH0uXG4gKlxuICogU2luY2UgaXQgZG9lcyBub3QgcHJvZHVjZSBhIG5ldyBjaGlsZCBQcm9taXNlLCBjYW5jZWxsYXRpb24gcHJvcGFnYXRpb24gaXNcbiAqIG5vdCBwcmV2ZW50ZWQgYnkgYWRkaW5nIGNhbGxiYWNrcyB3aXRoIHtAY29kZSB0aGVuQWx3YXlzfS4gQSBQcm9taXNlIHRoYXQgaGFzXG4gKiBhIGNsZWFudXAgaGFuZGxlciBhZGRlZCB3aXRoIHtAY29kZSB0aGVuQWx3YXlzfSB3aWxsIGJlIGNhbmNlbGVkIGlmIGFsbCBvZlxuICogaXRzIGNoaWxkcmVuIGNyZWF0ZWQgYnkge0Bjb2RlIHRoZW59IChvciB7QGNvZGUgdGhlbkNhdGNofSkgYXJlIGNhbmNlbGVkLlxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb24odGhpczpUSElTKTogdm9pZH0gb25SZXNvbHZlZCBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBpbnZva2VkXG4gKiAgICAgd2hlbiB0aGUgUHJvbWlzZSBpcyByZXNvbHZlZC5cbiAqIEBwYXJhbSB7VEhJUz19IG9wdF9jb250ZXh0IEFuIG9wdGlvbmFsIGNvbnRleHQgb2JqZWN0IHRoYXQgd2lsbCBiZSB0aGVcbiAqICAgICBleGVjdXRpb24gY29udGV4dCBmb3IgdGhlIGNhbGxiYWNrcy4gQnkgZGVmYXVsdCwgZnVuY3Rpb25zIGFyZSBleGVjdXRlZFxuICogICAgIGluIHRoZSBnbG9iYWwgc2NvcGUuXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlLjxUWVBFPn0gVGhpcyBQcm9taXNlLCBmb3IgY2hhaW5pbmcgYWRkaXRpb25hbCBjYWxscy5cbiAqIEB0ZW1wbGF0ZSBUSElTXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudGhlbkFsd2F5cyA9IGZ1bmN0aW9uKG9uUmVzb2x2ZWQsIG9wdF9jb250ZXh0KSB7XG4gIHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuICAgIHRyeSB7XG4gICAgICAvLyBFbnN1cmUgdGhhdCBubyBhcmd1bWVudHMgYXJlIHBhc3NlZCB0byBvblJlc29sdmVkLlxuICAgICAgb25SZXNvbHZlZC5jYWxsKG9wdF9jb250ZXh0KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIENhbmNlbGxhYmxlUHJvbWlzZS5oYW5kbGVSZWplY3Rpb25fLmNhbGwobnVsbCwgZXJyKTtcbiAgICB9XG4gIH07XG5cbiAgdGhpcy5hZGRDYWxsYmFja0VudHJ5Xyh7XG4gICAgY2hpbGQ6IG51bGwsXG4gICAgb25SZWplY3RlZDogY2FsbGJhY2ssXG4gICAgb25GdWxmaWxsZWQ6IGNhbGxiYWNrXG4gIH0pO1xuICByZXR1cm4gdGhpcztcbn07XG5cblxuLyoqXG4gKiBBZGRzIGEgY2FsbGJhY2sgdGhhdCB3aWxsIGJlIGludm9rZWQgb25seSBpZiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZC4gVGhpc1xuICogaXMgZXF1aXZhbGVudCB0byB7QGNvZGUgdGhlbihudWxsLCBvblJlamVjdGVkKX0uXG4gKlxuICogQHBhcmFtIHshZnVuY3Rpb24odGhpczpUSElTLCAqKTogKn0gb25SZWplY3RlZCBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZVxuICogICAgIGludm9rZWQgd2l0aCB0aGUgcmVqZWN0aW9uIHJlYXNvbiBpZiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZC5cbiAqIEBwYXJhbSB7VEhJUz19IG9wdF9jb250ZXh0IEFuIG9wdGlvbmFsIGNvbnRleHQgb2JqZWN0IHRoYXQgd2lsbCBiZSB0aGVcbiAqICAgICBleGVjdXRpb24gY29udGV4dCBmb3IgdGhlIGNhbGxiYWNrcy4gQnkgZGVmYXVsdCwgZnVuY3Rpb25zIGFyZSBleGVjdXRlZFxuICogICAgIGluIHRoZSBnbG9iYWwgc2NvcGUuXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlfSBBIG5ldyBQcm9taXNlIHRoYXQgd2lsbCByZWNlaXZlIHRoZSByZXN1bHQgb2YgdGhlXG4gKiAgICAgY2FsbGJhY2suXG4gKiBAdGVtcGxhdGUgVEhJU1xuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnRoZW5DYXRjaCA9IGZ1bmN0aW9uKG9uUmVqZWN0ZWQsIG9wdF9jb250ZXh0KSB7XG4gIHJldHVybiB0aGlzLmFkZENoaWxkUHJvbWlzZV8obnVsbCwgb25SZWplY3RlZCwgb3B0X2NvbnRleHQpO1xufTtcblxuLyoqXG4gKiBBbGlhcyBvZiB7QGxpbmsgQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS50aGVuQ2F0Y2h9XG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuY2F0Y2ggPSBDYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnRoZW5DYXRjaDtcblxuXG4vKipcbiAqIENhbmNlbHMgdGhlIFByb21pc2UgaWYgaXQgaXMgc3RpbGwgcGVuZGluZyBieSByZWplY3RpbmcgaXQgd2l0aCBhIGNhbmNlbFxuICogRXJyb3IuIE5vIGFjdGlvbiBpcyBwZXJmb3JtZWQgaWYgdGhlIFByb21pc2UgaXMgYWxyZWFkeSByZXNvbHZlZC5cbiAqXG4gKiBBbGwgY2hpbGQgUHJvbWlzZXMgb2YgdGhlIGNhbmNlbGVkIFByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSBzYW1lXG4gKiBjYW5jZWwgZXJyb3IsIGFzIHdpdGggbm9ybWFsIFByb21pc2UgcmVqZWN0aW9uLiBJZiB0aGUgUHJvbWlzZSB0byBiZSBjYW5jZWxlZFxuICogaXMgdGhlIG9ubHkgY2hpbGQgb2YgYSBwZW5kaW5nIFByb21pc2UsIHRoZSBwYXJlbnQgUHJvbWlzZSB3aWxsIGFsc28gYmVcbiAqIGNhbmNlbGVkLiBDYW5jZWxsYXRpb24gbWF5IHByb3BhZ2F0ZSB1cHdhcmQgdGhyb3VnaCBtdWx0aXBsZSBnZW5lcmF0aW9ucy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZz19IG9wdF9tZXNzYWdlIEFuIG9wdGlvbmFsIGRlYnVnZ2luZyBtZXNzYWdlIGZvciBkZXNjcmliaW5nIHRoZVxuICogICAgIGNhbmNlbGxhdGlvbiByZWFzb24uXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuY2FuY2VsID0gZnVuY3Rpb24ob3B0X21lc3NhZ2UpIHtcbiAgaWYgKHRoaXMuc3RhdGVfID09PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkcpIHtcbiAgICBhc3luYy5ydW4oZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgZXJyID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcihvcHRfbWVzc2FnZSk7XG4gICAgICBlcnIuSVNfQ0FOQ0VMTEFUSU9OX0VSUk9SID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2FuY2VsSW50ZXJuYWxfKGVycik7XG4gICAgfSwgdGhpcyk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBDYW5jZWxzIHRoaXMgUHJvbWlzZSB3aXRoIHRoZSBnaXZlbiBlcnJvci5cbiAqXG4gKiBAcGFyYW0geyFFcnJvcn0gZXJyIFRoZSBjYW5jZWxsYXRpb24gZXJyb3IuXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmNhbmNlbEludGVybmFsXyA9IGZ1bmN0aW9uKGVycikge1xuICBpZiAodGhpcy5zdGF0ZV8gPT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORykge1xuICAgIGlmICh0aGlzLnBhcmVudF8pIHtcbiAgICAgIC8vIENhbmNlbCB0aGUgUHJvbWlzZSBhbmQgcmVtb3ZlIGl0IGZyb20gdGhlIHBhcmVudCdzIGNoaWxkIGxpc3QuXG4gICAgICB0aGlzLnBhcmVudF8uY2FuY2VsQ2hpbGRfKHRoaXMsIGVycik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVzb2x2ZV8oQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCwgZXJyKTtcbiAgICB9XG4gIH1cbn07XG5cblxuLyoqXG4gKiBDYW5jZWxzIGEgY2hpbGQgUHJvbWlzZSBmcm9tIHRoZSBsaXN0IG9mIGNhbGxiYWNrIGVudHJpZXMuIElmIHRoZSBQcm9taXNlIGhhc1xuICogbm90IGFscmVhZHkgYmVlbiByZXNvbHZlZCwgcmVqZWN0IGl0IHdpdGggYSBjYW5jZWwgZXJyb3IuIElmIHRoZXJlIGFyZSBub1xuICogb3RoZXIgY2hpbGRyZW4gaW4gdGhlIGxpc3Qgb2YgY2FsbGJhY2sgZW50cmllcywgcHJvcGFnYXRlIHRoZSBjYW5jZWxsYXRpb25cbiAqIGJ5IGNhbmNlbGluZyB0aGlzIFByb21pc2UgYXMgd2VsbC5cbiAqXG4gKiBAcGFyYW0geyFDYW5jZWxsYWJsZVByb21pc2V9IGNoaWxkUHJvbWlzZSBUaGUgUHJvbWlzZSB0byBjYW5jZWwuXG4gKiBAcGFyYW0geyFFcnJvcn0gZXJyIFRoZSBjYW5jZWwgZXJyb3IgdG8gdXNlIGZvciByZWplY3RpbmcgdGhlIFByb21pc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmNhbmNlbENoaWxkXyA9IGZ1bmN0aW9uKGNoaWxkUHJvbWlzZSwgZXJyKSB7XG4gIGlmICghdGhpcy5jYWxsYmFja0VudHJpZXNfKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBjaGlsZENvdW50ID0gMDtcbiAgdmFyIGNoaWxkSW5kZXggPSAtMTtcblxuICAvLyBGaW5kIHRoZSBjYWxsYmFjayBlbnRyeSBmb3IgdGhlIGNoaWxkUHJvbWlzZSwgYW5kIGNvdW50IHdoZXRoZXIgdGhlcmUgYXJlXG4gIC8vIGFkZGl0aW9uYWwgY2hpbGQgUHJvbWlzZXMuXG4gIGZvciAodmFyIGkgPSAwLCBlbnRyeTsgKGVudHJ5ID0gdGhpcy5jYWxsYmFja0VudHJpZXNfW2ldKTsgaSsrKSB7XG4gICAgdmFyIGNoaWxkID0gZW50cnkuY2hpbGQ7XG4gICAgaWYgKGNoaWxkKSB7XG4gICAgICBjaGlsZENvdW50Kys7XG4gICAgICBpZiAoY2hpbGQgPT09IGNoaWxkUHJvbWlzZSkge1xuICAgICAgICBjaGlsZEluZGV4ID0gaTtcbiAgICAgIH1cbiAgICAgIGlmIChjaGlsZEluZGV4ID49IDAgJiYgY2hpbGRDb3VudCA+IDEpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gSWYgdGhlIGNoaWxkIFByb21pc2Ugd2FzIHRoZSBvbmx5IGNoaWxkLCBjYW5jZWwgdGhpcyBQcm9taXNlIGFzIHdlbGwuXG4gIC8vIE90aGVyd2lzZSwgcmVqZWN0IG9ubHkgdGhlIGNoaWxkIFByb21pc2Ugd2l0aCB0aGUgY2FuY2VsIGVycm9yLlxuICBpZiAoY2hpbGRJbmRleCA+PSAwKSB7XG4gICAgaWYgKHRoaXMuc3RhdGVfID09PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkcgJiYgY2hpbGRDb3VudCA9PT0gMSkge1xuICAgICAgdGhpcy5jYW5jZWxJbnRlcm5hbF8oZXJyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGNhbGxiYWNrRW50cnkgPSB0aGlzLmNhbGxiYWNrRW50cmllc18uc3BsaWNlKGNoaWxkSW5kZXgsIDEpWzBdO1xuICAgICAgdGhpcy5leGVjdXRlQ2FsbGJhY2tfKFxuICAgICAgICBjYWxsYmFja0VudHJ5LCBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVELCBlcnIpO1xuICAgIH1cbiAgfVxufTtcblxuXG4vKipcbiAqIEFkZHMgYSBjYWxsYmFjayBlbnRyeSB0byB0aGUgY3VycmVudCBQcm9taXNlLCBhbmQgc2NoZWR1bGVzIGNhbGxiYWNrXG4gKiBleGVjdXRpb24gaWYgdGhlIFByb21pc2UgaGFzIGFscmVhZHkgYmVlbiByZXNvbHZlZC5cbiAqXG4gKiBAcGFyYW0ge0NhbmNlbGxhYmxlUHJvbWlzZS5DYWxsYmFja0VudHJ5X30gY2FsbGJhY2tFbnRyeSBSZWNvcmQgY29udGFpbmluZ1xuICogICAgIHtAY29kZSBvbkZ1bGZpbGxlZH0gYW5kIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFja3MgdG8gZXhlY3V0ZSBhZnRlclxuICogICAgIHRoZSBQcm9taXNlIGlzIHJlc29sdmVkLlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5hZGRDYWxsYmFja0VudHJ5XyA9IGZ1bmN0aW9uKGNhbGxiYWNrRW50cnkpIHtcbiAgaWYgKCghdGhpcy5jYWxsYmFja0VudHJpZXNfIHx8ICF0aGlzLmNhbGxiYWNrRW50cmllc18ubGVuZ3RoKSAmJlxuICAgICh0aGlzLnN0YXRlXyA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5GVUxGSUxMRUQgfHxcbiAgICB0aGlzLnN0YXRlXyA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCkpIHtcbiAgICB0aGlzLnNjaGVkdWxlQ2FsbGJhY2tzXygpO1xuICB9XG4gIGlmICghdGhpcy5jYWxsYmFja0VudHJpZXNfKSB7XG4gICAgdGhpcy5jYWxsYmFja0VudHJpZXNfID0gW107XG4gIH1cbiAgdGhpcy5jYWxsYmFja0VudHJpZXNfLnB1c2goY2FsbGJhY2tFbnRyeSk7XG59O1xuXG5cbi8qKlxuICogQ3JlYXRlcyBhIGNoaWxkIFByb21pc2UgYW5kIGFkZHMgaXQgdG8gdGhlIGNhbGxiYWNrIGVudHJ5IGxpc3QuIFRoZSByZXN1bHQgb2ZcbiAqIHRoZSBjaGlsZCBQcm9taXNlIGlzIGRldGVybWluZWQgYnkgdGhlIHN0YXRlIG9mIHRoZSBwYXJlbnQgUHJvbWlzZSBhbmQgdGhlXG4gKiByZXN1bHQgb2YgdGhlIHtAY29kZSBvbkZ1bGZpbGxlZH0gb3Ige0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrcyBhc1xuICogc3BlY2lmaWVkIGluIHRoZSBQcm9taXNlIHJlc29sdXRpb24gcHJvY2VkdXJlLlxuICpcbiAqIEBzZWUgaHR0cDovL3Byb21pc2VzYXBsdXMuY29tLyN0aGVfX21ldGhvZFxuICpcbiAqIEBwYXJhbSB7P2Z1bmN0aW9uKHRoaXM6VEhJUywgVFlQRSk6XG4gKiAgICAgICAgICAoUkVTVUxUfENhbmNlbGxhYmxlUHJvbWlzZS48UkVTVUxUPnxUaGVuYWJsZSl9IG9uRnVsZmlsbGVkIEEgY2FsbGJhY2sgdGhhdFxuICogICAgIHdpbGwgYmUgaW52b2tlZCBpZiB0aGUgUHJvbWlzZSBpcyBmdWxsZmlsbGVkLCBvciBudWxsLlxuICogQHBhcmFtIHs/ZnVuY3Rpb24odGhpczpUSElTLCAqKTogKn0gb25SZWplY3RlZCBBIGNhbGxiYWNrIHRoYXQgd2lsbCBiZVxuICogICAgIGludm9rZWQgaWYgdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQsIG9yIG51bGwuXG4gKiBAcGFyYW0ge1RISVM9fSBvcHRfY29udGV4dCBBbiBvcHRpb25hbCBleGVjdXRpb24gY29udGV4dCBmb3IgdGhlIGNhbGxiYWNrcy5cbiAqICAgICBpbiB0aGUgZGVmYXVsdCBjYWxsaW5nIGNvbnRleHQuXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlfSBUaGUgY2hpbGQgUHJvbWlzZS5cbiAqIEB0ZW1wbGF0ZSBSRVNVTFQsVEhJU1xuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5hZGRDaGlsZFByb21pc2VfID0gZnVuY3Rpb24oXG5vbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgb3B0X2NvbnRleHQpIHtcblxuICB2YXIgY2FsbGJhY2tFbnRyeSA9IHtcbiAgICBjaGlsZDogbnVsbCxcbiAgICBvbkZ1bGZpbGxlZDogbnVsbCxcbiAgICBvblJlamVjdGVkOiBudWxsXG4gIH07XG5cbiAgY2FsbGJhY2tFbnRyeS5jaGlsZCA9IG5ldyBDYW5jZWxsYWJsZVByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgLy8gSW52b2tlIG9uRnVsZmlsbGVkLCBvciByZXNvbHZlIHdpdGggdGhlIHBhcmVudCdzIHZhbHVlIGlmIGFic2VudC5cbiAgICBjYWxsYmFja0VudHJ5Lm9uRnVsZmlsbGVkID0gb25GdWxmaWxsZWQgPyBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG9uRnVsZmlsbGVkLmNhbGwob3B0X2NvbnRleHQsIHZhbHVlKTtcbiAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgfVxuICAgIH0gOiByZXNvbHZlO1xuXG4gICAgLy8gSW52b2tlIG9uUmVqZWN0ZWQsIG9yIHJlamVjdCB3aXRoIHRoZSBwYXJlbnQncyByZWFzb24gaWYgYWJzZW50LlxuICAgIGNhbGxiYWNrRW50cnkub25SZWplY3RlZCA9IG9uUmVqZWN0ZWQgPyBmdW5jdGlvbihyZWFzb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBvblJlamVjdGVkLmNhbGwob3B0X2NvbnRleHQsIHJlYXNvbik7XG4gICAgICAgIGlmICghaXNEZWYocmVzdWx0KSAmJiByZWFzb24uSVNfQ0FOQ0VMTEFUSU9OX0VSUk9SKSB7XG4gICAgICAgICAgLy8gUHJvcGFnYXRlIGNhbmNlbGxhdGlvbiB0byBjaGlsZHJlbiBpZiBubyBvdGhlciByZXN1bHQgaXMgcmV0dXJuZWQuXG4gICAgICAgICAgcmVqZWN0KHJlYXNvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9XG4gICAgfSA6IHJlamVjdDtcbiAgfSk7XG5cbiAgY2FsbGJhY2tFbnRyeS5jaGlsZC5wYXJlbnRfID0gdGhpcztcbiAgdGhpcy5hZGRDYWxsYmFja0VudHJ5XyhcbiAgICAvKiogQHR5cGUge0NhbmNlbGxhYmxlUHJvbWlzZS5DYWxsYmFja0VudHJ5X30gKi8gKGNhbGxiYWNrRW50cnkpKTtcbiAgcmV0dXJuIGNhbGxiYWNrRW50cnkuY2hpbGQ7XG59O1xuXG5cbi8qKlxuICogVW5ibG9ja3MgdGhlIFByb21pc2UgYW5kIGZ1bGZpbGxzIGl0IHdpdGggdGhlIGdpdmVuIHZhbHVlLlxuICpcbiAqIEBwYXJhbSB7VFlQRX0gdmFsdWVcbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudW5ibG9ja0FuZEZ1bGZpbGxfID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgaWYgKHRoaXMuc3RhdGVfICE9PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkJMT0NLRUQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbmNlbGxhYmxlUHJvbWlzZSBpcyBub3QgYmxvY2tlZC4nKTtcbiAgfVxuICB0aGlzLnN0YXRlXyA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORztcbiAgdGhpcy5yZXNvbHZlXyhDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkZVTEZJTExFRCwgdmFsdWUpO1xufTtcblxuXG4vKipcbiAqIFVuYmxvY2tzIHRoZSBQcm9taXNlIGFuZCByZWplY3RzIGl0IHdpdGggdGhlIGdpdmVuIHJlamVjdGlvbiByZWFzb24uXG4gKlxuICogQHBhcmFtIHsqfSByZWFzb25cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudW5ibG9ja0FuZFJlamVjdF8gPSBmdW5jdGlvbihyZWFzb24pIHtcbiAgaWYgKHRoaXMuc3RhdGVfICE9PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkJMT0NLRUQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbmNlbGxhYmxlUHJvbWlzZSBpcyBub3QgYmxvY2tlZC4nKTtcbiAgfVxuICB0aGlzLnN0YXRlXyA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORztcbiAgdGhpcy5yZXNvbHZlXyhDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVELCByZWFzb24pO1xufTtcblxuXG4vKipcbiAqIEF0dGVtcHRzIHRvIHJlc29sdmUgYSBQcm9taXNlIHdpdGggYSBnaXZlbiByZXNvbHV0aW9uIHN0YXRlIGFuZCB2YWx1ZS4gVGhpc1xuICogaXMgYSBuby1vcCBpZiB0aGUgZ2l2ZW4gUHJvbWlzZSBoYXMgYWxyZWFkeSBiZWVuIHJlc29sdmVkLlxuICpcbiAqIElmIHRoZSBnaXZlbiByZXN1bHQgaXMgYSBUaGVuYWJsZSAoc3VjaCBhcyBhbm90aGVyIFByb21pc2UpLCB0aGUgUHJvbWlzZSB3aWxsXG4gKiBiZSByZXNvbHZlZCB3aXRoIHRoZSBzYW1lIHN0YXRlIGFuZCByZXN1bHQgYXMgdGhlIFRoZW5hYmxlIG9uY2UgaXQgaXMgaXRzZWxmXG4gKiByZXNvbHZlZC5cbiAqXG4gKiBJZiB0aGUgZ2l2ZW4gcmVzdWx0IGlzIG5vdCBhIFRoZW5hYmxlLCB0aGUgUHJvbWlzZSB3aWxsIGJlIGZ1bGZpbGxlZCBvclxuICogcmVqZWN0ZWQgd2l0aCB0aGF0IHJlc3VsdCBiYXNlZCBvbiB0aGUgZ2l2ZW4gc3RhdGUuXG4gKlxuICogQHNlZSBodHRwOi8vcHJvbWlzZXNhcGx1cy5jb20vI3RoZV9wcm9taXNlX3Jlc29sdXRpb25fcHJvY2VkdXJlXG4gKlxuICogQHBhcmFtIHtDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVffSBzdGF0ZVxuICogQHBhcmFtIHsqfSB4IFRoZSByZXN1bHQgdG8gYXBwbHkgdG8gdGhlIFByb21pc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnJlc29sdmVfID0gZnVuY3Rpb24oc3RhdGUsIHgpIHtcbiAgaWYgKHRoaXMuc3RhdGVfICE9PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkcpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAodGhpcyA9PT0geCkge1xuICAgIHN0YXRlID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRDtcbiAgICB4ID0gbmV3IFR5cGVFcnJvcignQ2FuY2VsbGFibGVQcm9taXNlIGNhbm5vdCByZXNvbHZlIHRvIGl0c2VsZicpO1xuXG4gIH0gZWxzZSBpZiAoVGhlbmFibGUuaXNJbXBsZW1lbnRlZEJ5KHgpKSB7XG4gICAgeCA9IC8qKiBAdHlwZSB7IVRoZW5hYmxlfSAqLyAoeCk7XG4gICAgdGhpcy5zdGF0ZV8gPSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkJMT0NLRUQ7XG4gICAgeC50aGVuKHRoaXMudW5ibG9ja0FuZEZ1bGZpbGxfLCB0aGlzLnVuYmxvY2tBbmRSZWplY3RfLCB0aGlzKTtcbiAgICByZXR1cm47XG5cbiAgfSBlbHNlIGlmIChpc09iamVjdCh4KSkge1xuICAgIHRyeSB7XG4gICAgICB2YXIgdGhlbiA9IHgudGhlbjtcbiAgICAgIGlmIChpc0Z1bmN0aW9uKHRoZW4pKSB7XG4gICAgICAgIHRoaXMudHJ5VGhlbl8oeCwgdGhlbik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBzdGF0ZSA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQ7XG4gICAgICB4ID0gZTtcbiAgICB9XG4gIH1cblxuICB0aGlzLnJlc3VsdF8gPSB4O1xuICB0aGlzLnN0YXRlXyA9IHN0YXRlO1xuICB0aGlzLnNjaGVkdWxlQ2FsbGJhY2tzXygpO1xuXG4gIGlmIChzdGF0ZSA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCAmJiAheC5JU19DQU5DRUxMQVRJT05fRVJST1IpIHtcbiAgICBDYW5jZWxsYWJsZVByb21pc2UuYWRkVW5oYW5kbGVkUmVqZWN0aW9uXyh0aGlzLCB4KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEF0dGVtcHRzIHRvIGNhbGwgdGhlIHtAY29kZSB0aGVufSBtZXRob2Qgb24gYW4gb2JqZWN0IGluIHRoZSBob3BlcyB0aGF0IGl0IGlzXG4gKiBhIFByb21pc2UtY29tcGF0aWJsZSBpbnN0YW5jZS4gVGhpcyBhbGxvd3MgaW50ZXJvcGVyYXRpb24gYmV0d2VlbiBkaWZmZXJlbnRcbiAqIFByb21pc2UgaW1wbGVtZW50YXRpb25zLCBob3dldmVyIGEgbm9uLWNvbXBsaWFudCBvYmplY3QgbWF5IGNhdXNlIGEgUHJvbWlzZVxuICogdG8gaGFuZyBpbmRlZmluaXRlbHkuIElmIHRoZSB7QGNvZGUgdGhlbn0gbWV0aG9kIHRocm93cyBhbiBleGNlcHRpb24sIHRoZVxuICogZGVwZW5kZW50IFByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSB0aHJvd24gdmFsdWUuXG4gKlxuICogQHNlZSBodHRwOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTcwXG4gKlxuICogQHBhcmFtIHtUaGVuYWJsZX0gdGhlbmFibGUgQW4gb2JqZWN0IHdpdGggYSB7QGNvZGUgdGhlbn0gbWV0aG9kIHRoYXQgbWF5IGJlXG4gKiAgICAgY29tcGF0aWJsZSB3aXRoIHRoZSBQcm9taXNlL0ErIHNwZWNpZmljYXRpb24uXG4gKiBAcGFyYW0geyFGdW5jdGlvbn0gdGhlbiBUaGUge0Bjb2RlIHRoZW59IG1ldGhvZCBvZiB0aGUgVGhlbmFibGUgb2JqZWN0LlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS50cnlUaGVuXyA9IGZ1bmN0aW9uKHRoZW5hYmxlLCB0aGVuKSB7XG4gIHRoaXMuc3RhdGVfID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5CTE9DS0VEO1xuICB2YXIgcHJvbWlzZSA9IHRoaXM7XG4gIHZhciBjYWxsZWQgPSBmYWxzZTtcblxuICB2YXIgcmVzb2x2ZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgaWYgKCFjYWxsZWQpIHtcbiAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgICBwcm9taXNlLnVuYmxvY2tBbmRGdWxmaWxsXyh2YWx1ZSk7XG4gICAgfVxuICB9O1xuXG4gIHZhciByZWplY3QgPSBmdW5jdGlvbihyZWFzb24pIHtcbiAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgIHByb21pc2UudW5ibG9ja0FuZFJlamVjdF8ocmVhc29uKTtcbiAgICB9XG4gIH07XG5cbiAgdHJ5IHtcbiAgICB0aGVuLmNhbGwodGhlbmFibGUsIHJlc29sdmUsIHJlamVjdCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZWplY3QoZSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBFeGVjdXRlcyB0aGUgcGVuZGluZyBjYWxsYmFja3Mgb2YgYSByZXNvbHZlZCBQcm9taXNlIGFmdGVyIGEgdGltZW91dC5cbiAqXG4gKiBTZWN0aW9uIDIuMi40IG9mIHRoZSBQcm9taXNlcy9BKyBzcGVjaWZpY2F0aW9uIHJlcXVpcmVzIHRoYXQgUHJvbWlzZVxuICogY2FsbGJhY2tzIG11c3Qgb25seSBiZSBpbnZva2VkIGZyb20gYSBjYWxsIHN0YWNrIHRoYXQgb25seSBjb250YWlucyBQcm9taXNlXG4gKiBpbXBsZW1lbnRhdGlvbiBjb2RlLCB3aGljaCB3ZSBhY2NvbXBsaXNoIGJ5IGludm9raW5nIGNhbGxiYWNrIGV4ZWN1dGlvbiBhZnRlclxuICogYSB0aW1lb3V0LiBJZiB7QGNvZGUgc3RhcnRFeGVjdXRpb25ffSBpcyBjYWxsZWQgbXVsdGlwbGUgdGltZXMgZm9yIHRoZSBzYW1lXG4gKiBQcm9taXNlLCB0aGUgY2FsbGJhY2sgY2hhaW4gd2lsbCBiZSBldmFsdWF0ZWQgb25seSBvbmNlLiBBZGRpdGlvbmFsIGNhbGxiYWNrc1xuICogbWF5IGJlIGFkZGVkIGR1cmluZyB0aGUgZXZhbHVhdGlvbiBwaGFzZSwgYW5kIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIHNhbWVcbiAqIGV2ZW50IGxvb3AuXG4gKlxuICogQWxsIFByb21pc2VzIGFkZGVkIHRvIHRoZSB3YWl0aW5nIGxpc3QgZHVyaW5nIHRoZSBzYW1lIGJyb3dzZXIgZXZlbnQgbG9vcFxuICogd2lsbCBiZSBleGVjdXRlZCBpbiBvbmUgYmF0Y2ggdG8gYXZvaWQgdXNpbmcgYSBzZXBhcmF0ZSB0aW1lb3V0IHBlciBQcm9taXNlLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuc2NoZWR1bGVDYWxsYmFja3NfID0gZnVuY3Rpb24oKSB7XG4gIGlmICghdGhpcy5leGVjdXRpbmdfKSB7XG4gICAgdGhpcy5leGVjdXRpbmdfID0gdHJ1ZTtcbiAgICBhc3luYy5ydW4odGhpcy5leGVjdXRlQ2FsbGJhY2tzXywgdGhpcyk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBFeGVjdXRlcyBhbGwgcGVuZGluZyBjYWxsYmFja3MgZm9yIHRoaXMgUHJvbWlzZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmV4ZWN1dGVDYWxsYmFja3NfID0gZnVuY3Rpb24oKSB7XG4gIHdoaWxlICh0aGlzLmNhbGxiYWNrRW50cmllc18gJiYgdGhpcy5jYWxsYmFja0VudHJpZXNfLmxlbmd0aCkge1xuICAgIHZhciBlbnRyaWVzID0gdGhpcy5jYWxsYmFja0VudHJpZXNfO1xuICAgIHRoaXMuY2FsbGJhY2tFbnRyaWVzXyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbnRyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLmV4ZWN1dGVDYWxsYmFja18oZW50cmllc1tpXSwgdGhpcy5zdGF0ZV8sIHRoaXMucmVzdWx0Xyk7XG4gICAgfVxuICB9XG4gIHRoaXMuZXhlY3V0aW5nXyA9IGZhbHNlO1xufTtcblxuXG4vKipcbiAqIEV4ZWN1dGVzIGEgcGVuZGluZyBjYWxsYmFjayBmb3IgdGhpcyBQcm9taXNlLiBJbnZva2VzIGFuIHtAY29kZSBvbkZ1bGZpbGxlZH1cbiAqIG9yIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFjayBiYXNlZCBvbiB0aGUgcmVzb2x2ZWQgc3RhdGUgb2YgdGhlIFByb21pc2UuXG4gKlxuICogQHBhcmFtIHshQ2FuY2VsbGFibGVQcm9taXNlLkNhbGxiYWNrRW50cnlffSBjYWxsYmFja0VudHJ5IEFuIGVudHJ5IGNvbnRhaW5pbmcgdGhlXG4gKiAgICAgb25GdWxmaWxsZWQgYW5kL29yIG9uUmVqZWN0ZWQgY2FsbGJhY2tzIGZvciB0aGlzIHN0ZXAuXG4gKiBAcGFyYW0ge0NhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV99IHN0YXRlIFRoZSByZXNvbHV0aW9uIHN0YXR1cyBvZiB0aGUgUHJvbWlzZSxcbiAqICAgICBlaXRoZXIgRlVMRklMTEVEIG9yIFJFSkVDVEVELlxuICogQHBhcmFtIHsqfSByZXN1bHQgVGhlIHJlc29sdmVkIHJlc3VsdCBvZiB0aGUgUHJvbWlzZS5cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuZXhlY3V0ZUNhbGxiYWNrXyA9IGZ1bmN0aW9uKFxuY2FsbGJhY2tFbnRyeSwgc3RhdGUsIHJlc3VsdCkge1xuICBpZiAoc3RhdGUgPT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uRlVMRklMTEVEKSB7XG4gICAgY2FsbGJhY2tFbnRyeS5vbkZ1bGZpbGxlZChyZXN1bHQpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMucmVtb3ZlVW5oYW5kbGVkUmVqZWN0aW9uXygpO1xuICAgIGNhbGxiYWNrRW50cnkub25SZWplY3RlZChyZXN1bHQpO1xuICB9XG59O1xuXG5cbi8qKlxuICogTWFya3MgdGhpcyByZWplY3RlZCBQcm9taXNlIGFzIGhhdmluZyBiZWluZyBoYW5kbGVkLiBBbHNvIG1hcmtzIGFueSBwYXJlbnRcbiAqIFByb21pc2VzIGluIHRoZSByZWplY3RlZCBzdGF0ZSBhcyBoYW5kbGVkLiBUaGUgcmVqZWN0aW9uIGhhbmRsZXIgd2lsbCBub1xuICogbG9uZ2VyIGJlIGludm9rZWQgZm9yIHRoaXMgUHJvbWlzZSAoaWYgaXQgaGFzIG5vdCBiZWVuIGNhbGxlZCBhbHJlYWR5KS5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnJlbW92ZVVuaGFuZGxlZFJlamVjdGlvbl8gPSBmdW5jdGlvbigpIHtcbiAgdmFyIHA7XG4gIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA+IDApIHtcbiAgICBmb3IgKHAgPSB0aGlzOyBwICYmIHAudW5oYW5kbGVkUmVqZWN0aW9uSWRfOyBwID0gcC5wYXJlbnRfKSB7XG4gICAgICBjbGVhclRpbWVvdXQocC51bmhhbmRsZWRSZWplY3Rpb25JZF8pO1xuICAgICAgcC51bmhhbmRsZWRSZWplY3Rpb25JZF8gPSAwO1xuICAgIH1cbiAgfSBlbHNlIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA9PT0gMCkge1xuICAgIGZvciAocCA9IHRoaXM7IHAgJiYgcC5oYWRVbmhhbmRsZWRSZWplY3Rpb25fOyBwID0gcC5wYXJlbnRfKSB7XG4gICAgICBwLmhhZFVuaGFuZGxlZFJlamVjdGlvbl8gPSBmYWxzZTtcbiAgICB9XG4gIH1cbn07XG5cblxuLyoqXG4gKiBNYXJrcyB0aGlzIHJlamVjdGVkIFByb21pc2UgYXMgdW5oYW5kbGVkLiBJZiBubyB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2tcbiAqIGlzIGNhbGxlZCBmb3IgdGhpcyBQcm9taXNlIGJlZm9yZSB0aGUge0Bjb2RlIFVOSEFORExFRF9SRUpFQ1RJT05fREVMQVl9XG4gKiBleHBpcmVzLCB0aGUgcmVhc29uIHdpbGwgYmUgcGFzc2VkIHRvIHRoZSB1bmhhbmRsZWQgcmVqZWN0aW9uIGhhbmRsZXIuIFRoZVxuICogaGFuZGxlciB0eXBpY2FsbHkgcmV0aHJvd3MgdGhlIHJlamVjdGlvbiByZWFzb24gc28gdGhhdCBpdCBiZWNvbWVzIHZpc2libGUgaW5cbiAqIHRoZSBkZXZlbG9wZXIgY29uc29sZS5cbiAqXG4gKiBAcGFyYW0geyFDYW5jZWxsYWJsZVByb21pc2V9IHByb21pc2UgVGhlIHJlamVjdGVkIFByb21pc2UuXG4gKiBAcGFyYW0geyp9IHJlYXNvbiBUaGUgUHJvbWlzZSByZWplY3Rpb24gcmVhc29uLlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLmFkZFVuaGFuZGxlZFJlamVjdGlvbl8gPSBmdW5jdGlvbihwcm9taXNlLCByZWFzb24pIHtcbiAgaWYgKENhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZID4gMCkge1xuICAgIHByb21pc2UudW5oYW5kbGVkUmVqZWN0aW9uSWRfID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgIENhbmNlbGxhYmxlUHJvbWlzZS5oYW5kbGVSZWplY3Rpb25fLmNhbGwobnVsbCwgcmVhc29uKTtcbiAgICB9LCBDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSk7XG5cbiAgfSBlbHNlIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA9PT0gMCkge1xuICAgIHByb21pc2UuaGFkVW5oYW5kbGVkUmVqZWN0aW9uXyA9IHRydWU7XG4gICAgYXN5bmMucnVuKGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHByb21pc2UuaGFkVW5oYW5kbGVkUmVqZWN0aW9uXykge1xuICAgICAgICBDYW5jZWxsYWJsZVByb21pc2UuaGFuZGxlUmVqZWN0aW9uXy5jYWxsKG51bGwsIHJlYXNvbik7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBBIG1ldGhvZCB0aGF0IGlzIGludm9rZWQgd2l0aCB0aGUgcmVqZWN0aW9uIHJlYXNvbnMgZm9yIFByb21pc2VzIHRoYXQgYXJlXG4gKiByZWplY3RlZCBidXQgaGF2ZSBubyB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2tzIHJlZ2lzdGVyZWQgeWV0LlxuICogQHR5cGUge2Z1bmN0aW9uKCopfVxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLmhhbmRsZVJlamVjdGlvbl8gPSBhc3luYy50aHJvd0V4Y2VwdGlvbjtcblxuXG4vKipcbiAqIFNldHMgYSBoYW5kbGVyIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2l0aCByZWFzb25zIGZyb20gdW5oYW5kbGVkIHJlamVjdGVkXG4gKiBQcm9taXNlcy4gSWYgdGhlIHJlamVjdGVkIFByb21pc2UgKG9yIG9uZSBvZiBpdHMgZGVzY2VuZGFudHMpIGhhcyBhblxuICoge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrIHJlZ2lzdGVyZWQsIHRoZSByZWplY3Rpb24gd2lsbCBiZSBjb25zaWRlcmVkXG4gKiBoYW5kbGVkLCBhbmQgdGhlIHJlamVjdGlvbiBoYW5kbGVyIHdpbGwgbm90IGJlIGNhbGxlZC5cbiAqXG4gKiBCeSBkZWZhdWx0LCB1bmhhbmRsZWQgcmVqZWN0aW9ucyBhcmUgcmV0aHJvd24gc28gdGhhdCB0aGUgZXJyb3IgbWF5IGJlXG4gKiBjYXB0dXJlZCBieSB0aGUgZGV2ZWxvcGVyIGNvbnNvbGUgb3IgYSB7QGNvZGUgd2luZG93Lm9uZXJyb3J9IGhhbmRsZXIuXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbigqKX0gaGFuZGxlciBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2l0aCByZWFzb25zIGZyb21cbiAqICAgICByZWplY3RlZCBQcm9taXNlcy4gRGVmYXVsdHMgdG8ge0Bjb2RlIGFzeW5jLnRocm93RXhjZXB0aW9ufS5cbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnNldFVuaGFuZGxlZFJlamVjdGlvbkhhbmRsZXIgPSBmdW5jdGlvbihoYW5kbGVyKSB7XG4gIENhbmNlbGxhYmxlUHJvbWlzZS5oYW5kbGVSZWplY3Rpb25fID0gaGFuZGxlcjtcbn07XG5cblxuXG4vKipcbiAqIEVycm9yIHVzZWQgYXMgYSByZWplY3Rpb24gcmVhc29uIGZvciBjYW5jZWxlZCBQcm9taXNlcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZz19IG9wdF9tZXNzYWdlXG4gKiBAY29uc3RydWN0b3JcbiAqIEBleHRlbmRzIHtFcnJvcn1cbiAqIEBmaW5hbFxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuQ2FuY2VsbGF0aW9uRXJyb3IgPSBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3Iob3B0X21lc3NhZ2UpIHtcbiAgICAgc3VwZXIob3B0X21lc3NhZ2UpO1xuXG4gICAgIGlmIChvcHRfbWVzc2FnZSkge1xuICAgICAgIHRoaXMubWVzc2FnZSA9IG9wdF9tZXNzYWdlO1xuICAgICB9XG4gICB9XG59O1xuXG4vKiogQG92ZXJyaWRlICovXG5DYW5jZWxsYWJsZVByb21pc2UuQ2FuY2VsbGF0aW9uRXJyb3IucHJvdG90eXBlLm5hbWUgPSAnY2FuY2VsJztcblxuZXhwb3J0IHtDYW5jZWxsYWJsZVByb21pc2V9O1xuZXhwb3J0IGRlZmF1bHQgQ2FuY2VsbGFibGVQcm9taXNlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAgKiBEZWJvdW5jZXMgZnVuY3Rpb24gZXhlY3V0aW9uLlxuICAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGZuXG4gICogQHBhcmFtIHtudW1iZXJ9IGRlbGF5XG4gICogQHJldHVybiB7IWZ1bmN0aW9uKCl9XG4gICovXG5mdW5jdGlvbiBkZWJvdW5jZShmbiwgZGVsYXkpIHtcblx0cmV0dXJuIGZ1bmN0aW9uIGRlYm91bmNlZCgpIHtcblx0XHR2YXIgYXJncyA9IGFyZ3VtZW50cztcblx0XHRjYW5jZWxEZWJvdW5jZShkZWJvdW5jZWQpO1xuXHRcdGRlYm91bmNlZC5pZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRmbi5hcHBseShudWxsLCBhcmdzKTtcblx0XHR9LCBkZWxheSk7XG5cdH07XG59XG5cbi8qKlxuICogQ2FuY2VscyB0aGUgc2NoZWR1bGVkIGRlYm91bmNlZCBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gY2FuY2VsRGVib3VuY2UoZGVib3VuY2VkKSB7XG5cdGNsZWFyVGltZW91dChkZWJvdW5jZWQuaWQpO1xufVxuXG5leHBvcnQgZGVmYXVsdCBkZWJvdW5jZTtcbmV4cG9ydCB7IGNhbmNlbERlYm91bmNlLCBkZWJvdW5jZSB9O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgY29yZSBmcm9tICdtZXRhbCc7XG5cbmNvbnN0IFJFR0VYID0gLyhbXFwvXSk/KD86KD86XFw6KFxcdyspKD86XFwoKCg/OlxcXFwufFteXFxcXCgpXSkqKVxcKSk/fFxcKCgoPzpcXFxcLnxbXlxcXFwoKV0pKylcXCkpKFsrKj9dKT8pL2c7XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIGFycmF5IG9mIHJlZ2V4IG1hdGNoZXMgdG8gYSBtb3JlIHJlYWRhYmxlIG9iamVjdCBmb3JtYXQuXG4gKiBAcGFyYW0geyFBcnJheTxzdHJpbmc+fSBtYXRjaGVzXG4gKiBAcmV0dXJuIHshT2JqZWN0fVxuICovXG5mdW5jdGlvbiBjb252ZXJ0TWF0Y2hlc1RvT2JqKG1hdGNoZXMpIHtcblx0cmV0dXJuIHtcblx0XHRtYXRjaDogbWF0Y2hlc1swXSxcblx0XHRwcmVmaXg6IG1hdGNoZXNbMV0sXG5cdFx0bmFtZTogbWF0Y2hlc1syXSxcblx0XHRwYXJhbVBhdHRlcm46IG1hdGNoZXNbM10sXG5cdFx0dW5uYW1lZFBhdHRlcm46IG1hdGNoZXNbNF0sXG5cdFx0bW9kaWZpZXI6IG1hdGNoZXNbNV1cblx0fTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gdG9rZW5zIHBhcnNlZCBmcm9tIGEgcm91dGUgZm9ybWF0IHN0cmluZyB0byBhIHJlZ2V4LlxuICogQHBhcmFtIHshQXJyYXk8c3RyaW5nfCFPYmplY3Q+fSB0b2tlbnNcbiAqIEByZXR1cm4geyFSZWdFeHB9XG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRUb2tlbnNUb1JlZ2V4KHRva2Vucykge1xuXHRsZXQgcmVnZXggPSAnJztcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcblx0XHRpZiAoY29yZS5pc1N0cmluZyh0b2tlbnNbaV0pKSB7XG5cdFx0XHRyZWdleCArPSBlc2NhcGUodG9rZW5zW2ldKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bGV0IGNhcHR1cmUgPSBlbmNsb3NlTm9uQ2FwdHVyaW5nR3JvdXAodG9rZW5zW2ldLnBhdHRlcm4pO1xuXHRcdFx0aWYgKHRva2Vuc1tpXS5yZXBlYXQpIHtcblx0XHRcdFx0Y2FwdHVyZSArPSBlbmNsb3NlTm9uQ2FwdHVyaW5nR3JvdXAoJ1xcXFwvJyArIGNhcHR1cmUpICsgJyonO1xuXHRcdFx0fVxuXHRcdFx0Y2FwdHVyZSA9IGVzY2FwZSh0b2tlbnNbaV0ucHJlZml4KSArIGAoJHtjYXB0dXJlfSlgO1xuXHRcdFx0aWYgKHRva2Vuc1tpXS5vcHRpb25hbCkge1xuXHRcdFx0XHRpZiAoIXRva2Vuc1tpXS5wYXJ0aWFsKSB7XG5cdFx0XHRcdFx0Y2FwdHVyZSA9IGVuY2xvc2VOb25DYXB0dXJpbmdHcm91cChjYXB0dXJlKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjYXB0dXJlICs9ICc/Jztcblx0XHRcdH1cblx0XHRcdHJlZ2V4ICs9IGNhcHR1cmU7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBuZXcgUmVnRXhwKCdeJyArIG1ha2VUcmFpbGluZ1NsYXNoT3B0aW9uYWwocmVnZXgpICsgJyQnKTtcbn1cblxuLyoqXG4gKiBFbmNsb3NlcyB0aGUgZ2l2ZW4gcmVnZXggcGF0dGVybiBpbnRvIGEgbm9uIGNhcHR1cmluZyBncm91cC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXR0ZXJuXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIGVuY2xvc2VOb25DYXB0dXJpbmdHcm91cChwYXR0ZXJuKSB7XG5cdHJldHVybiBgKD86JHtwYXR0ZXJufSlgO1xufVxuXG4vKipcbiAqIEVzY2FwZXMgdGhlIGdpdmVuIHN0cmluZyB0byBzaG93IHVwIGluIHRoZSBwYXRoIHJlZ2V4LlxuICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiBlc2NhcGUoc3RyKSB7XG5cdHJldHVybiBzdHIucmVwbGFjZSgvKFsuKyo/PV4hOiR7fSgpW1xcXXxcXC9cXFxcXSkvZywgJ1xcXFwkMScpO1xufVxuXG4vKipcbiAqIE1ha2VzIHRyYWlsaW5nIHNsYXNoIG9wdGlvbmFsIG9uIHBhdGhzLlxuICogQHBhcmFtIHtzdHJpbmd9IHJlZ2V4XG4gKiBAcGFyYW0ge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gbWFrZVRyYWlsaW5nU2xhc2hPcHRpb25hbChyZWdleCkge1xuXHRpZiAoL1xcLyQvLnRlc3QocmVnZXgpKSB7XG5cdFx0cmVnZXggKz0gJz8nO1xuXHR9IGVsc2Uge1xuXHRcdHJlZ2V4ICs9ICdcXFxcLz8nO1xuXHR9XG5cdHJldHVybiByZWdleDtcbn1cblxuLyoqXG4gKiBQYXJzZXMgdGhlIGdpdmVuIHJvdXRlIGZvcm1hdCBzdHJpbmcgaW50byB0b2tlbnMgcmVwcmVzZW50aW5nIGl0cyBjb250ZW50cy5cbiAqIEBwYXJhbSB7IUFycmF5fHN0cmluZ30gcm91dGVPclRva2VucyBFaXRoZXIgYSByb3V0ZSBmb3JtYXQgc3RyaW5nIG9yIHRva2Vuc1xuICogICAgIHByZXZpb3VzbHkgcGFyc2VkIHZpYSB0aGUgYHBhcnNlYCBmdW5jdGlvbi5cbiAqIEByZXR1cm4geyFBcnJheTxzdHJpbmd8IU9iamVjdD59IEFuIGFycmF5IG9mIHRva2VucyB0aGF0IGNhbiBiZSBlaXRoZXIgcGxhaW5cbiAqICAgICBzdHJpbmdzIChwYXJ0IG9mIHRoZSByb3V0ZSkgb3Igb2JqZWN0cyBjb250YWluaW5nIGluZm9ybWF0aW9ucyBvbiBwYXJhbXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZShyb3V0ZU9yVG9rZW5zKSB7XG5cdGlmICghY29yZS5pc1N0cmluZyhyb3V0ZU9yVG9rZW5zKSkge1xuXHRcdHJldHVybiByb3V0ZU9yVG9rZW5zO1xuXHR9XG5cblx0Y29uc3Qgcm91dGUgPSByb3V0ZU9yVG9rZW5zO1xuXHRsZXQgdW5uYW1lZENvdW50ID0gMDtcblx0Y29uc3QgdG9rZW5zID0gW107XG5cdGxldCBjdXJyUGF0aCA9ICcnO1xuXHRsZXQgaW5kZXggPSAwO1xuXG5cdGxldCBtYXRjaGVzID0gUkVHRVguZXhlYyhyb3V0ZSk7XG5cdHdoaWxlIChtYXRjaGVzKSB7XG5cdFx0Y29uc3QgZGF0YSA9IGNvbnZlcnRNYXRjaGVzVG9PYmoobWF0Y2hlcyk7XG5cblx0XHRjdXJyUGF0aCA9IHJvdXRlLnNsaWNlKGluZGV4LCBtYXRjaGVzLmluZGV4KTtcblx0XHRpbmRleCA9IG1hdGNoZXMuaW5kZXggKyBkYXRhLm1hdGNoLmxlbmd0aDtcblx0XHR0b2tlbnMucHVzaChjdXJyUGF0aCk7XG5cblx0XHR0b2tlbnMucHVzaCh7XG5cdFx0XHRuYW1lOiBkYXRhLm5hbWUgPyBkYXRhLm5hbWUgOiAnJyArIHVubmFtZWRDb3VudCsrLFxuXHRcdFx0cGFydGlhbDogcm91dGVbaW5kZXhdICYmIHJvdXRlW2luZGV4XSAhPT0gZGF0YS5wcmVmaXgsXG5cdFx0XHRwcmVmaXg6IGRhdGEucHJlZml4IHx8ICcnLFxuXHRcdFx0cGF0dGVybjogZGF0YS5wYXJhbVBhdHRlcm4gfHwgZGF0YS51bm5hbWVkUGF0dGVybiB8fCAnW15cXFxcL10rJyxcblx0XHRcdHJlcGVhdDogZGF0YS5tb2RpZmllciA9PT0gJyonIHx8IGRhdGEubW9kaWZpZXIgPT09ICcrJyxcblx0XHRcdG9wdGlvbmFsOiBkYXRhLm1vZGlmaWVyID09PSAnKicgfHwgZGF0YS5tb2RpZmllciA9PT0gJz8nXG5cdFx0fSk7XG5cblx0XHRtYXRjaGVzID0gUkVHRVguZXhlYyhyb3V0ZSk7XG5cdH1cblxuXHRpZiAoaW5kZXggPCByb3V0ZS5sZW5ndGgpIHtcblx0XHR0b2tlbnMucHVzaChyb3V0ZS5zdWJzdHIoaW5kZXgpKTtcblx0fVxuXHRyZXR1cm4gdG9rZW5zO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIHRoZSBnaXZlbiByb3V0ZSBmb3JtYXQgc3RyaW5nIHRvIGEgcmVnZXggdGhhdCBjYW4gZXh0cmFjdCBwYXJhbVxuICogZGF0YSBmcm9tIHBhdGhzIG1hdGNoaW5nIGl0LlxuICogQHBhcmFtIHshQXJyYXl8c3RyaW5nfSByb3V0ZU9yVG9rZW5zIEVpdGhlciBhIHJvdXRlIGZvcm1hdCBzdHJpbmcgb3IgdG9rZW5zXG4gKiAgICAgcHJldmlvdXNseSBwYXJzZWQgdmlhIHRoZSBgcGFyc2VgIGZ1bmN0aW9uLlxuICogQHJldHVybiB7IVJlZ0V4cH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvUmVnZXgocm91dGVPclRva2Vucykge1xuXHRyZXR1cm4gY29udmVydFRva2Vuc1RvUmVnZXgocGFyc2Uocm91dGVPclRva2VucykpO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIGRhdGEgZnJvbSB0aGUgZ2l2ZW4gcGF0aCBhY2NvcmRpbmcgdG8gdGhlIHNwZWNpZmllZCByb3V0ZSBmb3JtYXQuXG4gKiBAcGFyYW0geyFBcnJheXxzdHJpbmd9IHJvdXRlT3JUb2tlbnMgRWl0aGVyIGEgcm91dGUgZm9ybWF0IHN0cmluZyBvciB0b2tlbnNcbiAqICAgICBwcmV2aW91c2x5IHBhcnNlZCB2aWEgdGhlIGBwYXJzZWAgZnVuY3Rpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gVGhlIHBhdGggdG8gZXh0cmFjdCBwYXJhbSBkYXRhIGZyb20uXG4gKiBAcmV0dXJuIHtPYmplY3Q8c3RyaW5nLCBzdHJpbmc+fSBUaGUgZGF0YSBvYmplY3QsIG9yIG51bGwgaWYgdGhlIHBhdGggZG9lc24ndFxuICogICAgIG1hdGNoIHRoZSBnaXZlbiBmb3JtYXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0RGF0YShyb3V0ZU9yVG9rZW5zLCBwYXRoKSB7XG5cdGNvbnN0IGRhdGEgPSB7fTtcblx0Y29uc3QgdG9rZW5zID0gcGFyc2Uocm91dGVPclRva2Vucyk7XG5cdGNvbnN0IG1hdGNoID0gcGF0aC5tYXRjaChjb252ZXJ0VG9rZW5zVG9SZWdleCh0b2tlbnMpKTtcblxuXHRpZiAoIW1hdGNoKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHRsZXQgcGFyYW1JbmRleCA9IDE7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKCFjb3JlLmlzU3RyaW5nKHRva2Vuc1tpXSkpIHtcblx0XHRcdGxldCB2YWx1ZSA9IG1hdGNoW3BhcmFtSW5kZXgrK107XG5cdFx0XHRpZiAoY29yZS5pc0RlZih2YWx1ZSkpIHtcblx0XHRcdFx0aWYgKHRva2Vuc1tpXS5yZXBlYXQpIHtcblx0XHRcdFx0XHR2YWx1ZSA9IHZhbHVlLnNwbGl0KCcvJyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZGF0YVt0b2tlbnNbaV0ubmFtZV0gPSB2YWx1ZTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0cmV0dXJuIGRhdGE7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmQW5kTm90TnVsbCwgaXNGdW5jdGlvbiwgaXNTdHJpbmcgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBleHRyYWN0RGF0YSwgcGFyc2UsIHRvUmVnZXggfSBmcm9tICdtZXRhbC1wYXRoLXBhcnNlcic7XG5cbmNsYXNzIFJvdXRlIHtcblxuXHQvKipcblx0ICogUm91dGUgY2xhc3MuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ3xSZWdFeHB8RnVuY3Rpb259IHBhdGhcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGhhbmRsZXJcblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihwYXRoLCBoYW5kbGVyKSB7XG5cdFx0aWYgKCFpc0RlZkFuZE5vdE51bGwocGF0aCkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignUm91dGUgcGF0aCBub3Qgc3BlY2lmaWVkLicpO1xuXHRcdH1cblx0XHRpZiAoIWlzRnVuY3Rpb24oaGFuZGxlcikpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignUm91dGUgaGFuZGxlciBpcyBub3QgYSBmdW5jdGlvbi4nKTtcblx0XHR9XG5cblx0XHQvKipcblx0XHQgKiBEZWZpbmVzIHRoZSBoYW5kbGVyIHdoaWNoIHdpbGwgZXhlY3V0ZSBvbmNlIGEgVVJMIGluIHRoZSBhcHBsaWNhdGlvblxuXHRcdCAqIG1hdGNoZXMgdGhlIHBhdGguXG5cdFx0ICogQHR5cGUgeyFGdW5jdGlvbn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5oYW5kbGVyID0gaGFuZGxlcjtcblxuXHRcdC8qKlxuXHRcdCAqIERlZmluZXMgdGhlIHBhdGggd2hpY2ggd2lsbCB0cmlnZ2VyIHRoZSByb3V0ZSBoYW5kbGVyLlxuXHRcdCAqIEB0eXBlIHshc3RyaW5nfFJlZ0V4cHxGdW5jdGlvbn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wYXRoID0gcGF0aDtcblx0fVxuXG5cdC8qKlxuXHQqIEJ1aWxkcyBwYXJzZWQgZGF0YSAocmVnZXggYW5kIHRva2VucykgZm9yIHRoaXMgcm91dGUuXG5cdCogQHJldHVybiB7IU9iamVjdH1cblx0KiBAcHJvdGVjdGVkXG5cdCovXG5cdGJ1aWxkUGFyc2VkRGF0YV8oKSB7XG5cdFx0aWYgKCF0aGlzLnBhcnNlZERhdGFfKSB7XG5cdFx0XHR2YXIgdG9rZW5zID0gcGFyc2UodGhpcy5wYXRoKTtcblx0XHRcdHZhciByZWdleCA9IHRvUmVnZXgodG9rZW5zKTtcblx0XHRcdHRoaXMucGFyc2VkRGF0YV8gPSB7XG5cdFx0XHRcdHJlZ2V4LFxuXHRcdFx0XHR0b2tlbnNcblx0XHRcdH07XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLnBhcnNlZERhdGFfO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIHBhcmFtIGRhdGEgZnJvbSB0aGUgZ2l2ZW4gcGF0aCwgYWNjb3JkaW5nIHRvIHRoaXMgcm91dGUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIFRoZSB1cmwgcGF0aCB0byBleHRyYWN0IHBhcmFtcyBmcm9tLlxuXHQgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBleHRyYWN0ZWQgZGF0YSwgaWYgdGhlIHBhdGggbWF0Y2hlcyB0aGlzIHJvdXRlLCBvclxuXHQgKiAgICAgbnVsbCBvdGhlcndpc2UuXG5cdCAqL1xuXHRleHRyYWN0UGFyYW1zKHBhdGgpIHtcblx0XHRpZiAoaXNTdHJpbmcodGhpcy5wYXRoKSkge1xuXHRcdFx0cmV0dXJuIGV4dHJhY3REYXRhKHRoaXMuYnVpbGRQYXJzZWREYXRhXygpLnRva2VucywgcGF0aCk7XG5cdFx0fVxuXHRcdHJldHVybiB7fTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByb3V0ZSBoYW5kbGVyLlxuXHQgKiBAcmV0dXJuIHshRnVuY3Rpb259XG5cdCAqL1xuXHRnZXRIYW5kbGVyKCkge1xuXHRcdHJldHVybiB0aGlzLmhhbmRsZXI7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcm91dGUgcGF0aC5cblx0ICogQHJldHVybiB7IXN0cmluZ3xSZWdFeHB8RnVuY3Rpb259XG5cdCAqL1xuXHRnZXRQYXRoKCkge1xuXHRcdHJldHVybiB0aGlzLnBhdGg7XG5cdH1cblxuXHQvKipcbiBcdCAqIE1hdGNoZXMgaWYgdGhlIHJvdXRlciBjYW4gaGFuZGxlIHRoZSB0ZXN0ZWQgcGF0aC5cbiBcdCAqIEBwYXJhbSB7IXN0cmluZ30gdmFsdWUgUGF0aCB0byB0ZXN0IChtYXkgY29udGFpbiB0aGUgcXVlcnlzdHJpbmcgcGFydCkuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiBtYXRjaGVzIGFueSByb3V0ZS5cblx0ICovXG5cdG1hdGNoZXNQYXRoKHZhbHVlKSB7XG5cdFx0dmFyIHBhdGggPSB0aGlzLnBhdGg7XG5cblx0XHRpZiAoaXNGdW5jdGlvbihwYXRoKSkge1xuXHRcdFx0cmV0dXJuIHBhdGgodmFsdWUpO1xuXHRcdH1cblx0XHRpZiAoaXNTdHJpbmcocGF0aCkpIHtcblx0XHRcdHBhdGggPSB0aGlzLmJ1aWxkUGFyc2VkRGF0YV8oKS5yZWdleDtcblx0XHR9XG5cdFx0aWYgKHBhdGggaW5zdGFuY2VvZiBSZWdFeHApIHtcblx0XHRcdHJldHVybiB2YWx1ZS5zZWFyY2gocGF0aCkgPiAtMTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBSb3V0ZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgRGlzcG9zYWJsZSB9IGZyb20gJ21ldGFsJztcblxuY2xhc3MgQ2FjaGVhYmxlIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cblx0LyoqXG5cdCAqIEFic3RyYWN0IGNsYXNzIGZvciBkZWZpbmluZyBjYWNoZWFibGUgYmVoYXZpb3IuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBjYWNoZWQgZGF0YS5cblx0XHQgKiBAdHlwZSB7IU9iamVjdH1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuY2FjaGUgPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgd2hldGhlciBjbGFzcyBpcyBjYWNoZWFibGUuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQGRlZmF1bHQgZmFsc2Vcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5jYWNoZWFibGUgPSBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGNvbnRlbnQgdG8gdGhlIGNhY2hlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gY29udGVudCBDb250ZW50IHRvIGJlIGNhY2hlZC5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkQ2FjaGUoY29udGVudCkge1xuXHRcdGlmICh0aGlzLmNhY2hlYWJsZSkge1xuXHRcdFx0dGhpcy5jYWNoZSA9IGNvbnRlbnQ7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENsZWFycyB0aGUgY2FjaGUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGNsZWFyQ2FjaGUoKSB7XG5cdFx0dGhpcy5jYWNoZSA9IG51bGw7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLmNsZWFyQ2FjaGUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjYWNoZWQgY29udGVudC5cblx0ICogQHJldHVybiB7T2JqZWN0fSBDYWNoZWQgY29udGVudC5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0Z2V0Q2FjaGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY2FjaGU7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgY2xhc3MgaXMgY2FjaGVhYmxlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBSZXR1cm5zIHRydWUgd2hlbiBjbGFzcyBpcyBjYWNoZWFibGUsIGZhbHNlIG90aGVyd2lzZS5cblx0ICovXG5cdGlzQ2FjaGVhYmxlKCkge1xuXHRcdHJldHVybiB0aGlzLmNhY2hlYWJsZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHdoZXRoZXIgdGhlIGNsYXNzIGlzIGNhY2hlYWJsZS5cblx0ICogQHBhcmFtIHtib29sZWFufSBjYWNoZWFibGVcblx0ICovXG5cdHNldENhY2hlYWJsZShjYWNoZWFibGUpIHtcblx0XHRpZiAoIWNhY2hlYWJsZSkge1xuXHRcdFx0dGhpcy5jbGVhckNhY2hlKCk7XG5cdFx0fVxuXHRcdHRoaXMuY2FjaGVhYmxlID0gY2FjaGVhYmxlO1xuXHR9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgQ2FjaGVhYmxlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBnZXRVaWQgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBnbG9iYWxFdmFsIH0gZnJvbSAnbWV0YWwtZG9tJztcbmltcG9ydCBDYWNoZWFibGUgZnJvbSAnLi4vY2FjaGVhYmxlL0NhY2hlYWJsZSc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuXG5jbGFzcyBTY3JlZW4gZXh0ZW5kcyBDYWNoZWFibGUge1xuXG5cdC8qKlxuXHQgKiBTY3JlZW4gY2xhc3MgaXMgYSBzcGVjaWFsIHR5cGUgb2Ygcm91dGUgaGFuZGxlciB0aGF0IHByb3ZpZGVzIGhlbHBlclxuXHQgKiB1dGlsaXRpZXMgdGhhdCBhZGRzIGxpZmVjeWNsZSBhbmQgbWV0aG9kcyB0byBwcm92aWRlIGNvbnRlbnQgdG8gZWFjaFxuXHQgKiByZWdpc3RlcmVkIHN1cmZhY2UuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKiBAZXh0ZW5kcyB7Q2FjaGVhYmxlfVxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBzY3JlZW4gaWQuXG5cdFx0ICogQHR5cGUge3N0cmluZ31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5pZCA9IHRoaXMubWFrZUlkXyhnZXRVaWQoKSk7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgc2NyZWVuIG1ldGEgdGFncy4gUmVsZXZhbnQgd2hlbiB0aGUgbWV0YSB0YWdzXG5cdFx0ICogc2hvdWxkIGJlIHVwZGF0ZWQgd2hlbiBzY3JlZW4gaXMgcmVuZGVyZWQuXG5cdFx0ICovXG5cdFx0dGhpcy5tZXRhcyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgc2NyZWVuIHRpdGxlLiBSZWxldmFudCB3aGVuIHRoZSBwYWdlIHRpdGxlIHNob3VsZCBiZVxuXHRcdCAqIHVwYWRhdGVkIHdoZW4gc2NyZWVuIGlzIHJlbmRlcmVkLlxuXHRcdCAqIEB0eXBlIHs/c3RyaW5nPX1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudGl0bGUgPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpcmVzIHdoZW4gdGhlIHNjcmVlbiBpcyBhY3RpdmUuIEFsbG93cyBhIHNjcmVlbiB0byBwZXJmb3JtIGFueSBzZXR1cFxuXHQgKiB0aGF0IHJlcXVpcmVzIGl0cyBET00gdG8gYmUgdmlzaWJsZS4gTGlmZWN5Y2xlLlxuXHQgKi9cblx0YWN0aXZhdGUoKSB7XG5cdFx0Y29uc29sZS5sb2coJ1NjcmVlbiBbJyArIHRoaXMgKyAnXSBhY3RpdmF0ZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdpdmVzIHRoZSBTY3JlZW4gYSBjaGFuY2UgdG8gY2FuY2VsIHRoZSBuYXZpZ2F0aW9uIGFuZCBzdG9wIGl0c2VsZiBmcm9tXG5cdCAqIGFjdGl2YXRpbmcuIENhbiBiZSB1c2VkLCBmb3IgZXhhbXBsZSwgdG8gcHJldmVudCBuYXZpZ2F0aW9uIGlmIGEgdXNlclxuXHQgKiBpcyBub3QgYXV0aGVudGljYXRlZC4gTGlmZWN5Y2xlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFuPXw/Q2FuY2VsbGFibGVQcm9taXNlPX0gSWYgcmV0dXJucyBvciByZXNvbHZlcyB0byB0cnVlLFxuXHQgKiAgICAgdGhlIGN1cnJlbnQgc2NyZWVuIGlzIGxvY2tlZCBhbmQgdGhlIG5leHQgbmFnaXZhdGlvbiBpbnRlcnJ1cHRlZC5cblx0ICovXG5cdGJlZm9yZUFjdGl2YXRlKCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gYmVmb3JlQWN0aXZhdGUnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHaXZlcyB0aGUgU2NyZWVuIGEgY2hhbmNlIHRvIGNhbmNlbCB0aGUgbmF2aWdhdGlvbiBhbmQgc3RvcCBpdHNlbGYgZnJvbVxuXHQgKiBiZWluZyBkZWFjdGl2YXRlZC4gQ2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCBpZiB0aGUgc2NyZWVuIGhhcyB1bnNhdmVkXG5cdCAqIHN0YXRlLiBMaWZlY3ljbGUuIENsZWFuLXVwIHNob3VsZCBub3QgYmUgcHJlZm9ybWVkIGhlcmUsIHNpbmNlIHRoZVxuXHQgKiBuYXZpZ2F0aW9uIG1heSBzdGlsbCBiZSBjYW5jZWxsZWQuIERvIGNsZWFuLXVwIGluIGRlYWN0aXZhdGUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW49fD9DYW5jZWxsYWJsZVByb21pc2U9fSBJZiByZXR1cm5zIG9yIHJlc29sdmVzIHRvIHRydWUsXG5cdCAqICAgICB0aGUgY3VycmVudCBzY3JlZW4gaXMgbG9ja2VkIGFuZCB0aGUgbmV4dCBuYWdpdmF0aW9uIGludGVycnVwdGVkLlxuXHQgKi9cblx0YmVmb3JlRGVhY3RpdmF0ZSgpIHtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGJlZm9yZURlYWN0aXZhdGUnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHaXZlcyB0aGUgU2NyZWVuIGEgY2hhbmNlIGZvcm1hdCB0aGUgcGF0aCBiZWZvcmUgaGlzdG9yeSB1cGRhdGUuXG5cdCAqIEBwYXRoIHshc3RyaW5nfSBwYXRoIE5hdmlnYXRpb24gcGF0aC5cblx0ICogQHJldHVybiB7IXN0cmluZ30gTmF2aWdhdGlvbiBwYXRoIHRvIHVzZSBvbiBoaXN0b3J5LlxuXHQgKi9cblx0YmVmb3JlVXBkYXRlSGlzdG9yeVBhdGgocGF0aCkge1xuXHRcdHJldHVybiBwYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdpdmVzIHRoZSBTY3JlZW4gYSBjaGFuY2UgZm9ybWF0IHRoZSBzdGF0ZSBiZWZvcmUgaGlzdG9yeSB1cGRhdGUuXG5cdCAqIEBwYXRoIHshb2JqZWN0fSBzdGF0ZSBIaXN0b3J5IHN0YXRlLlxuXHQgKiBAcmV0dXJuIHshb2JqZWN0fSBIaXN0b3J5IHN0YXRlIHRvIHVzZSBvbiBoaXN0b3J5LlxuXHQgKi9cblx0YmVmb3JlVXBkYXRlSGlzdG9yeVN0YXRlKHN0YXRlKSB7XG5cdFx0cmV0dXJuIHN0YXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBkbyBhbnkgY2xlYW51cCBuZWNlc3NhcnkgYWZ0ZXIgaXQgaGFzIGJlZW5cblx0ICogZGVhY3RpdmF0ZWQsIGZvciBleGFtcGxlIGNhbmNlbGxpbmcgb3V0c3RhbmRpbmcgcmVxdWVzdHMgb3Igc3RvcHBpbmdcblx0ICogdGltZXJzLiBMaWZlY3ljbGUuXG5cdCAqL1xuXHRkZWFjdGl2YXRlKCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZGVhY3RpdmF0ZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2UgYSBzY3JlZW4sIGVpdGhlciBhZnRlciBpdCBpcyBkZWFjdGl2YXRlZCAoaW4gdGhlIGNhc2Ugb2YgYVxuXHQgKiBub24tY2FjaGVhYmxlIHZpZXcpIG9yIHdoZW4gdGhlIEFwcCBpcyBpdHNlbGYgZGlzcG9zZWQgZm9yIHdoYXRldmVyXG5cdCAqIHJlYXNvbi4gTGlmZWN5Y2xlLlxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHN1cGVyLmRpc3Bvc2VJbnRlcm5hbCgpO1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZGlzcG9zZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBldmFsdWF0ZSBzY3JpcHRzIGJlZm9yZSB0aGUgZWxlbWVudCBpcyBtYWRlIHZpc2libGUuXG5cdCAqIExpZmVjeWNsZS5cblx0ICogQHBhcmFtIHshb2JqZWN0fSBzdXJmYWNlcyBNYXAgb2Ygc3VyZmFjZXMgdG8gZmxpcCBrZXllZCBieSBzdXJmYWNlIGlkLlxuXHQgKiBAcmV0dXJuIHs/Q2FuY2VsbGFibGVQcm9taXNlPX0gVGhpcyBjYW4gcmV0dXJuIGEgcHJvbWlzZSwgd2hpY2ggd2lsbFxuXHQgKiAgICAgcGF1c2UgdGhlIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHRldmFsdWF0ZVNjcmlwdHMoc3VyZmFjZXMpIHtcblx0XHRPYmplY3Qua2V5cyhzdXJmYWNlcykuZm9yRWFjaChzSWQgPT4ge1xuXHRcdFx0aWYgKHN1cmZhY2VzW3NJZF0uYWN0aXZlQ2hpbGQpIHtcblx0XHRcdFx0Z2xvYmFsRXZhbC5ydW5TY3JpcHRzSW5FbGVtZW50KHN1cmZhY2VzW3NJZF0uYWN0aXZlQ2hpbGQpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBldmFsdWF0ZSBzdHlsZXMgYmVmb3JlIHRoZSBlbGVtZW50IGlzIG1hZGUgdmlzaWJsZS5cblx0ICogTGlmZWN5Y2xlLlxuXHQgKiBAcGFyYW0geyFvYmplY3R9IHN1cmZhY2VzIE1hcCBvZiBzdXJmYWNlcyB0byBmbGlwIGtleWVkIGJ5IHN1cmZhY2UgaWQuXG5cdCAqIEByZXR1cm4gez9DYW5jZWxsYWJsZVByb21pc2U9fSBUaGlzIGNhbiByZXR1cm4gYSBwcm9taXNlLCB3aGljaCB3aWxsXG5cdCAqICAgICBwYXVzZSB0aGUgbmF2aWdhdGlvbiB1bnRpbCBpdCBpcyByZXNvbHZlZC5cblx0ICovXG5cdGV2YWx1YXRlU3R5bGVzKCkge1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBwZXJmb3JtIGFueSBzZXR1cCBpbW1lZGlhdGVseSBiZWZvcmUgdGhlIGVsZW1lbnQgaXNcblx0ICogbWFkZSB2aXNpYmxlLiBMaWZlY3ljbGUuXG5cdCAqIEBwYXJhbSB7IW9iamVjdH0gc3VyZmFjZXMgTWFwIG9mIHN1cmZhY2VzIHRvIGZsaXAga2V5ZWQgYnkgc3VyZmFjZSBpZC5cblx0ICogQHJldHVybiB7P0NhbmNlbGxhYmxlUHJvbWlzZT19IFRoaXMgY2FuIHJldHVybiBhIHByb21pc2UsIHdoaWNoIHdpbGwgcGF1c2UgdGhlXG5cdCAqICAgICBuYXZpZ2F0aW9uIHVudGlsIGl0IGlzIHJlc29sdmVkLlxuXHQgKi9cblx0ZmxpcChzdXJmYWNlcykge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZmxpcCcpO1xuXG5cdFx0dmFyIHRyYW5zaXRpb25zID0gW107XG5cblx0XHRPYmplY3Qua2V5cyhzdXJmYWNlcykuZm9yRWFjaChzSWQgPT4ge1xuXHRcdFx0dmFyIHN1cmZhY2UgPSBzdXJmYWNlc1tzSWRdO1xuXHRcdFx0dmFyIGRlZmVycmVkID0gc3VyZmFjZS5zaG93KHRoaXMuaWQpO1xuXHRcdFx0dHJhbnNpdGlvbnMucHVzaChkZWZlcnJlZCk7XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLmFsbCh0cmFuc2l0aW9ucyk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc2NyZWVuIGlkLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRJZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzY3JlZW4gbWV0YSB0YWdzLlxuXHQgKiBAcmV0dXJuIHtOb2RlTGlzdHxOb2RlfVxuXHQgKi9cblx0Z2V0TWV0YXMoKSB7XG5cdFx0cmV0dXJuIHRoaXMubWV0YXM7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgY29udGVudCBmb3IgdGhlIGdpdmVuIHN1cmZhY2UsIG9yIG51bGwgaWYgdGhlIHN1cmZhY2UgaXNuJ3Rcblx0ICogdXNlZCBieSB0aGlzIHNjcmVlbi4gVGhpcyB3aWxsIGJlIGNhbGxlZCB3aGVuIGEgc2NyZWVuIGlzIGluaXRpYWxseVxuXHQgKiBjb25zdHJ1Y3RlZCBvciwgaWYgYSBzY3JlZW4gaXMgbm9uLWNhY2hlYWJsZSwgd2hlbiBuYXZpZ2F0ZWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc3VyZmFjZUlkIFRoZSBpZCBvZiB0aGUgc3VyZmFjZSBET00gZWxlbWVudC5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBwYXJhbXMgUGFyYW1zIGV4dHJhY3RlZCBmcm9tIHRoZSBjdXJyZW50IHBhdGguXG5cdCAqIEByZXR1cm4gez9zdHJpbmd8RWxlbWVudD19IFRoaXMgY2FuIHJldHVybiBhIHN0cmluZyBvciBub2RlIHJlcHJlc2VudGluZ1xuXHQgKiAgICAgdGhlIGNvbnRlbnQgb2YgdGhlIHN1cmZhY2UuIElmIHJldHVybnMgZmFsc3kgdmFsdWVzIHN1cmZhY2UgZGVmYXVsdFxuXHQgKiAgICAgY29udGVudCBpcyByZXN0b3JlZC5cblx0ICovXG5cdGdldFN1cmZhY2VDb250ZW50KCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZ2V0U3VyZmFjZUNvbnRlbnQnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzY3JlZW4gdGl0bGUuXG5cdCAqIEByZXR1cm4gez9zdHJpbmc9fVxuXHQgKi9cblx0Z2V0VGl0bGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMudGl0bGU7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbGwgY29udGVudHMgZm9yIHRoZSBzdXJmYWNlcy4gVGhpcyB3aWxsIHBhc3MgdGhlIGxvYWRlZCBjb250ZW50XG5cdCAqIHRvIDxjb2RlPlNjcmVlbi5sb2FkPC9jb2RlPiB3aXRoIGFsbCBpbmZvcm1hdGlvbiB5b3Vcblx0ICogbmVlZCB0byBmdWxmaWxsIHRoZSBzdXJmYWNlcy4gTGlmZWN5Y2xlLlxuXHQgKiBAcGFyYW0geyFzdHJpbmc9fSBwYXRoIFRoZSByZXF1ZXN0ZWQgcGF0aC5cblx0ICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZX0gVGhpcyBjYW4gcmV0dXJuIGEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGVcblx0ICogICAgIGNvbnRlbnRzIG9mIHRoZSBzdXJmYWNlcyBvciBhIHByb21pc2UsIHdoaWNoIHdpbGwgcGF1c2UgdGhlIG5hdmlnYXRpb25cblx0ICogICAgIHVudGlsIGl0IGlzIHJlc29sdmVkLiBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9hZGluZyBhc3luYyBjb250ZW50LlxuXHQgKi9cblx0bG9hZCgpIHtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGxvYWQnKTtcblx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYWtlcyB0aGUgaWQgZm9yIHRoZSBzY3JlZW4uXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaWQgVGhlIHNjcmVlbiBpZCB0aGUgY29udGVudCBiZWxvbmdzIHRvby5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0bWFrZUlkXyhpZCkge1xuXHRcdHJldHVybiAnc2NyZWVuXycgKyBpZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBzY3JlZW4gaWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaWRcblx0ICovXG5cdHNldElkKGlkKSB7XG5cdFx0dGhpcy5pZCA9IGlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHNjcmVlbiBtZXRhIHRhZ3MuXG5cdCAqIEBwYXJhbSB7Tm9kZUxpc3R8Tm9kZX0gbWV0YXNcblx0ICovXG5cdHNldE1ldGFzKG1ldGFzKSB7XG5cdFx0dGhpcy5tZXRhcyA9IG1ldGFzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHNjcmVlbiB0aXRsZS5cblx0ICogQHBhcmFtIHs/c3RyaW5nPX0gdGl0bGVcblx0ICovXG5cdHNldFRpdGxlKHRpdGxlKSB7XG5cdFx0dGhpcy50aXRsZSA9IHRpdGxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdHRvU3RyaW5nKCkge1xuXHRcdHJldHVybiB0aGlzLmlkO1xuXHR9XG5cbn1cblxuLyoqXG4gKiBAcGFyYW0geyp9IG9iamVjdFxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciBhIGdpdmVuIGluc3RhbmNlIGltcGxlbWVudHNcbiAqIDxjb2RlPlNjcmVlbjwvY29kZT4uXG4gKi9cblNjcmVlbi5pc0ltcGxlbWVudGVkQnkgPSBmdW5jdGlvbihvYmplY3QpIHtcblx0cmV0dXJuIG9iamVjdCBpbnN0YW5jZW9mIFNjcmVlbjtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IFNjcmVlbjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IGdsb2JhbHMgZnJvbSAnLi4vZ2xvYmFscy9nbG9iYWxzJztcbmltcG9ydCB7IERpc3Bvc2FibGUsIGlzRGVmQW5kTm90TnVsbCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7IGFwcGVuZCwgcmVtb3ZlQ2hpbGRyZW4sIGV4aXREb2N1bWVudCB9IGZyb20gJ21ldGFsLWRvbSc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuXG5jbGFzcyBTdXJmYWNlIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cblx0LyoqXG5cdCAqIFN1cmZhY2UgY2xhc3MgcmVwcmVzZW50aW5nIHRoZSByZWZlcmVuY2VzIHRvIGVsZW1lbnRzIG9uIHRoZSBwYWdlIHRoYXRcblx0ICogY2FuIHBvdGVudGlhbGx5IGJlIHVwZGF0ZWQgYnkgPGNvZGU+QXBwPC9jb2RlPi5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGlkXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoaWQpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0aWYgKCFpZCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTdXJmYWNlIGVsZW1lbnQgaWQgbm90IHNwZWNpZmllZC4gQSBzdXJmYWNlIGVsZW1lbnQgcmVxdWlyZXMgYSB2YWxpZCBpZC4nKTtcblx0XHR9XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgYWN0aXZlIGNoaWxkIGVsZW1lbnQuXG5cdFx0ICogQHR5cGUge0VsZW1lbnR9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmFjdGl2ZUNoaWxkID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBkZWZhdWx0IGNoaWxkIGVsZW1lbnQuXG5cdFx0ICogQHR5cGUge0VsZW1lbnR9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmRlZmF1bHRDaGlsZCA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgZWxlbWVudCB3aXRoIHRoZSBzcGVjaWZpZWQgc3VyZmFjZSBpZCwgaWYgbm90IGZvdW5kIGNyZWF0ZXMgYVxuXHRcdCAqIG5ldyBlbGVtZW50IHdpdGggdGhlIHNwZWNpZmllZCBpZC5cblx0XHQgKiBAdHlwZSB7RWxlbWVudH1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZWxlbWVudCA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgc3VyZmFjZSBpZC5cblx0XHQgKiBAdHlwZSB7U3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5pZCA9IGlkO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGRlZmF1bHQgdHJhbnNpdGlvbkZuIGZvciB0aGUgc3VyZmFjZXMuXG5cdFx0ICogQHBhcmFtIHs/RWxlbWVudD19IGZyb20gVGhlIHZpc2libGUgc3VyZmFjZSBlbGVtZW50LlxuXHRcdCAqIEBwYXJhbSB7P0VsZW1lbnQ9fSB0byBUaGUgc3VyZmFjZSBlbGVtZW50IHRvIGJlIGZsaXBwZWQuXG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdHRoaXMudHJhbnNpdGlvbkZuID0gbnVsbDtcblxuXHRcdHRoaXMuZGVmYXVsdENoaWxkID0gdGhpcy5nZXRDaGlsZChTdXJmYWNlLkRFRkFVTFQpO1xuXHRcdHRoaXMubWF5YmVXcmFwQ29udGVudEFzRGVmYXVsdF8oKTtcblx0XHR0aGlzLmFjdGl2ZUNoaWxkID0gdGhpcy5kZWZhdWx0Q2hpbGQ7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBzY3JlZW4gY29udGVudCB0byBhIHN1cmZhY2UuIElmIGNvbnRlbnQgaGFzbid0IGJlZW4gcGFzc2VkLCBzZWUgaWZcblx0ICogYW4gZWxlbWVudCBleGlzdHMgaW4gdGhlIERPTSB0aGF0IG1hdGNoZXMgdGhlIGlkLiBCeSBjb252ZW50aW9uLCB0aGVcblx0ICogZWxlbWVudCBzaG91bGQgYWxyZWFkeSBiZSBuZXN0ZWQgaW4gdGhlIHJpZ2h0IGVsZW1lbnQgYW5kIHNob3VsZCBoYXZlIGFuXG5cdCAqIGlkIHRoYXQgaXMgYSBjb25jYXRlbnRhdGlvbiBvZiB0aGUgc3VyZmFjZSBpZCArICctJyArIHRoZSBzY3JlZW4gaWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2NyZWVuSWQgVGhlIHNjcmVlbiBpZCB0aGUgY29udGVudCBiZWxvbmdzIHRvby5cblx0ICogQHBhcmFtIHs/c3RyaW5nfEVsZW1lbnQ9fSBvcHRfY29udGVudCBUaGUgc3RyaW5nIGNvbnRlbnQgb3IgZWxlbWVudCB0b1xuXHQgKiAgICAgYWRkIGJlIGFkZGVkIGFzIHN1cmZhY2UgY29udGVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH1cblx0ICovXG5cdGFkZENvbnRlbnQoc2NyZWVuSWQsIG9wdF9jb250ZW50KSB7XG5cdFx0dmFyIGNoaWxkID0gdGhpcy5kZWZhdWx0Q2hpbGQ7XG5cblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKG9wdF9jb250ZW50KSkge1xuXHRcdFx0Y2hpbGQgPSB0aGlzLmdldENoaWxkKHNjcmVlbklkKTtcblx0XHRcdGlmIChjaGlsZCkge1xuXHRcdFx0XHRyZW1vdmVDaGlsZHJlbihjaGlsZCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjaGlsZCA9IHRoaXMuY3JlYXRlQ2hpbGQoc2NyZWVuSWQpO1xuXHRcdFx0XHR0aGlzLnRyYW5zaXRpb24oY2hpbGQsIG51bGwpO1xuXHRcdFx0fVxuXHRcdFx0YXBwZW5kKGNoaWxkLCBvcHRfY29udGVudCk7XG5cdFx0fVxuXG5cdFx0dmFyIGVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnQoKTtcblxuXHRcdGlmIChlbGVtZW50ICYmIGNoaWxkKSB7XG5cdFx0XHRhcHBlbmQoZWxlbWVudCwgY2hpbGQpO1xuXHRcdH1cblxuXHRcdHJldHVybiBjaGlsZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGNoaWxkIG5vZGUgZm9yIHRoZSBzdXJmYWNlLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQuXG5cdCAqIEByZXR1cm4ge0VsZW1lbnR9XG5cdCAqL1xuXHRjcmVhdGVDaGlsZChzY3JlZW5JZCkge1xuXHRcdHZhciBjaGlsZCA9IGdsb2JhbHMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cdFx0Y2hpbGQuc2V0QXR0cmlidXRlKCdpZCcsIHRoaXMubWFrZUlkXyhzY3JlZW5JZCkpO1xuXHRcdHJldHVybiBjaGlsZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGNoaWxkIG5vZGUgb2YgdGhlIHN1cmZhY2UuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2NyZWVuSWQgVGhlIHNjcmVlbiBpZC5cblx0ICogQHJldHVybiB7P0VsZW1lbnR9XG5cdCAqL1xuXHRnZXRDaGlsZChzY3JlZW5JZCkge1xuXHRcdHJldHVybiBnbG9iYWxzLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMubWFrZUlkXyhzY3JlZW5JZCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHN1cmZhY2UgZWxlbWVudCBmcm9tIGVsZW1lbnQsIGFuZCBzZXRzIGl0IHRvIHRoZSBlbCBwcm9wZXJ0eSBvZlxuXHQgKiB0aGUgY3VycmVudCBpbnN0YW5jZS5cblx0ICogPGNvZGU+dGhpcy5lbGVtZW50PC9jb2RlPiB3aWxsIGJlIHVzZWQuXG5cdCAqIEByZXR1cm4gez9FbGVtZW50fSBUaGUgY3VycmVudCBzdXJmYWNlIGVsZW1lbnQuXG5cdCAqL1xuXHRnZXRFbGVtZW50KCkge1xuXHRcdGlmICh0aGlzLmVsZW1lbnQpIHtcblx0XHRcdHJldHVybiB0aGlzLmVsZW1lbnQ7XG5cdFx0fVxuXHRcdHRoaXMuZWxlbWVudCA9IGdsb2JhbHMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5pZCk7XG5cdFx0cmV0dXJuIHRoaXMuZWxlbWVudDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzdXJmYWNlIGlkLlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqL1xuXHRnZXRJZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzdXJmYWNlIHRyYW5zaXRpb24gZnVuY3Rpb24uXG5cdCAqIFNlZSA8Y29kZT5TdXJmYWNlLmRlZmF1bHRUcmFuc2l0aW9uPC9jb2RlPi5cblx0ICogQHJldHVybiB7P0Z1bmN0aW9uPX0gVGhlIHRyYW5zaXRpb24gZnVuY3Rpb24uXG5cdCAqL1xuXHRnZXRUcmFuc2l0aW9uRm4oKSB7XG5cdFx0cmV0dXJuIHRoaXMudHJhbnNpdGlvbkZuO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIHRoZSBpZCBmb3IgdGhlIGVsZW1lbnQgdGhhdCBob2xkcyBjb250ZW50IGZvciBhIHNjcmVlbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzY3JlZW5JZCBUaGUgc2NyZWVuIGlkIHRoZSBjb250ZW50IGJlbG9uZ3MgdG9vLlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRtYWtlSWRfKHNjcmVlbklkKSB7XG5cdFx0cmV0dXJuIHRoaXMuaWQgKyAnLScgKyBzY3JlZW5JZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZiBkZWZhdWx0IGNoaWxkIGlzIG1pc3NpbmcsIHdyYXBzIHN1cmZhY2UgY29udGVudCBhcyBkZWZhdWx0IGNoaWxkLiBJZlxuXHQgKiBzdXJmYWNlIGhhdmUgc3RhdGljIGNvbnRlbnQsIG1ha2Ugc3VyZSB0byBwbGFjZSBhXG5cdCAqIDxjb2RlPnN1cmZhY2VJZC1kZWZhdWx0PC9jb2RlPiBlbGVtZW50IGluc2lkZSBzdXJmYWNlLCBvbmx5IGNvbnRlbnRzXG5cdCAqIGluc2lkZSB0aGUgZGVmYXVsdCBjaGlsZCB3aWxsIGJlIHJlcGxhY2VkIGJ5IG5hdmlnYXRpb24uXG5cdCAqL1xuXHRtYXliZVdyYXBDb250ZW50QXNEZWZhdWx0XygpIHtcblx0XHR2YXIgZWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudCgpO1xuXHRcdGlmIChlbGVtZW50ICYmICF0aGlzLmRlZmF1bHRDaGlsZCkge1xuXHRcdFx0dmFyIGZyYWdtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cdFx0XHR3aGlsZSAoZWxlbWVudC5maXJzdENoaWxkKSB7XG5cdFx0XHRcdGZyYWdtZW50LmFwcGVuZENoaWxkKGVsZW1lbnQuZmlyc3RDaGlsZCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmRlZmF1bHRDaGlsZCA9IHRoaXMuYWRkQ29udGVudChTdXJmYWNlLkRFRkFVTFQsIGZyYWdtZW50KTtcblx0XHRcdHRoaXMudHJhbnNpdGlvbihudWxsLCB0aGlzLmRlZmF1bHRDaGlsZCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHN1cmZhY2UgaWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaWRcblx0ICovXG5cdHNldElkKGlkKSB7XG5cdFx0dGhpcy5pZCA9IGlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHN1cmZhY2UgdHJhbnNpdGlvbiBmdW5jdGlvbi5cblx0ICogU2VlIDxjb2RlPlN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb248L2NvZGU+LlxuXHQgKiBAcGFyYW0gez9GdW5jdGlvbj19IHRyYW5zaXRpb25GbiBUaGUgdHJhbnNpdGlvbiBmdW5jdGlvbi5cblx0ICovXG5cdHNldFRyYW5zaXRpb25Gbih0cmFuc2l0aW9uRm4pIHtcblx0XHR0aGlzLnRyYW5zaXRpb25GbiA9IHRyYW5zaXRpb25Gbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBTaG93cyBzY3JlZW4gY29udGVudCBmcm9tIGEgc3VyZmFjZS5cblx0ICogQHBhcmFtIHtTdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQgdG8gc2hvdy5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBQYXVzZXMgdGhlIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHRzaG93KHNjcmVlbklkKSB7XG5cdFx0dmFyIGZyb20gPSB0aGlzLmFjdGl2ZUNoaWxkO1xuXHRcdHZhciB0byA9IHRoaXMuZ2V0Q2hpbGQoc2NyZWVuSWQpO1xuXHRcdGlmICghdG8pIHtcblx0XHRcdHRvID0gdGhpcy5kZWZhdWx0Q2hpbGQ7XG5cdFx0fVxuXHRcdHRoaXMuYWN0aXZlQ2hpbGQgPSB0bztcblx0XHRyZXR1cm4gdGhpcy50cmFuc2l0aW9uKGZyb20sIHRvKS50aGVuQWx3YXlzKCgpID0+IHtcblx0XHRcdGlmIChmcm9tICYmIGZyb20gIT09IHRvKSB7XG5cdFx0XHRcdGV4aXREb2N1bWVudChmcm9tKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHNjcmVlbiBjb250ZW50IGZyb20gYSBzdXJmYWNlLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQgdG8gcmVtb3ZlLlxuXHQgKi9cblx0cmVtb3ZlKHNjcmVlbklkKSB7XG5cdFx0dmFyIGNoaWxkID0gdGhpcy5nZXRDaGlsZChzY3JlZW5JZCk7XG5cdFx0aWYgKGNoaWxkKSB7XG5cdFx0XHRleGl0RG9jdW1lbnQoY2hpbGQpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqL1xuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbnZva2VzIHRoZSB0cmFuc2l0aW9uIGZ1bmN0aW9uIHNwZWNpZmllZCBvbiA8Y29kZT50cmFuc2l0aW9uPC9jb2RlPiBhdHRyaWJ1dGUuXG5cdCAqIEBwYXJhbSB7P0VsZW1lbnQ9fSBmcm9tXG5cdCAqIEBwYXJhbSB7P0VsZW1lbnQ9fSB0b1xuXHQgKiBAcmV0dXJuIHs/Q2FuY2VsbGFibGVQcm9taXNlPX0gVGhpcyBjYW4gcmV0dXJuIGEgcHJvbWlzZSwgd2hpY2ggd2lsbCBwYXVzZSB0aGVcblx0ICogICAgIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHR0cmFuc2l0aW9uKGZyb20sIHRvKSB7XG5cdFx0dmFyIHRyYW5zaXRpb25GbiA9IHRoaXMudHJhbnNpdGlvbkZuIHx8IFN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb247XG5cdFx0cmV0dXJuIENhbmNlbGxhYmxlUHJvbWlzZS5yZXNvbHZlKHRyYW5zaXRpb25Gbi5jYWxsKHRoaXMsIGZyb20sIHRvKSk7XG5cdH1cblxufVxuXG4vKipcbiAgICogSG9sZHMgdGhlIGRlZmF1bHQgc3VyZmFjZSBuYW1lLiBFbGVtZW50cyBvbiB0aGUgcGFnZSBtdXN0IGNvbnRhaW4gYSBjaGlsZFxuICAgKiBlbGVtZW50IGNvbnRhaW5pbmcgdGhlIGRlZmF1bHQgY29udGVudCwgdGhpcyBlbGVtZW50IG11c3QgYmUgYXMgZm9sbG93aW5nOlxuICAgKlxuICAgKiBFeGFtcGxlOlxuICAgKiA8Y29kZT5cbiAgICogICA8ZGl2IGlkPVwibXlzdXJmYWNlXCI+XG4gICAqICAgICA8ZGl2IGlkPVwibXlzdXJmYWNlLWRlZmF1bHRcIj5EZWZhdWx0IHN1cmZhY2UgY29udGVudC48L2Rpdj5cbiAgICogICA8L2Rpdj5cbiAgICogPC9jb2RlPlxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCBjb250ZW50IGlzIHJlbGV2YW50IGZvciB0aGUgaW5pdGlhbCBwYWdlIGNvbnRlbnQuIFdoZW4gYVxuICAgKiBzY3JlZW4gZG9lc24ndCBwcm92aWRlIGNvbnRlbnQgZm9yIHRoZSBzdXJmYWNlIHRoZSBkZWZhdWx0IGNvbnRlbnQgaXNcbiAgICogcmVzdG9yZWQgaW50byB0aGUgcGFnZS5cbiAgICpcbiAgICogQHR5cGUgeyFTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQHN0YXRpY1xuICAgKi9cblN1cmZhY2UuREVGQVVMVCA9ICdkZWZhdWx0JztcblxuLyoqXG4gKiBIb2xkcyB0aGUgZGVmYXVsdCB0cmFuc2l0aW9uIGZvciBhbGwgc3VyZmFjZXMuIEVhY2ggc3VyZmFjZSBjb3VsZCBoYXZlIGl0c1xuICogb3duIHRyYW5zaXRpb24uXG4gKlxuICogRXhhbXBsZTpcbiAqXG4gKiA8Y29kZT5cbiAqIHN1cmZhY2Uuc2V0VHJhbnNpdGlvbkZuKGZ1bmN0aW9uKGZyb20sIHRvKSB7XG4gKiAgIGlmIChmcm9tKSB7XG4gKiAgICAgZnJvbS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICogICAgIGZyb20uY2xhc3NMaXN0LnJlbW92ZSgnZmxpcHBlZCcpO1xuICogICB9XG4gKiAgIGlmICh0bykge1xuICogICAgIHRvLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICogICAgIHRvLmNsYXNzTGlzdC5hZGQoJ2ZsaXBwZWQnKTtcbiAqICAgfVxuICogICByZXR1cm4gbnVsbDtcbiAqIH0pO1xuICogPC9jb2RlPlxuICpcbiAqIEBwYXJhbSB7P0VsZW1lbnQ9fSBmcm9tIFRoZSB2aXNpYmxlIHN1cmZhY2UgZWxlbWVudC5cbiAqIEBwYXJhbSB7P0VsZW1lbnQ9fSB0byBUaGUgc3VyZmFjZSBlbGVtZW50IHRvIGJlIGZsaXBwZWQuXG4gKiBAc3RhdGljXG4gKi9cblN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb24gPSBmdW5jdGlvbihmcm9tLCB0bykge1xuXHRpZiAoZnJvbSkge1xuXHRcdGZyb20uc3R5bGUuZGlzcGxheSA9ICdub25lJztcblx0XHRmcm9tLmNsYXNzTGlzdC5yZW1vdmUoJ2ZsaXBwZWQnKTtcblx0fVxuXHRpZiAodG8pIHtcblx0XHR0by5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblx0XHR0by5jbGFzc0xpc3QuYWRkKCdmbGlwcGVkJyk7XG5cdH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IFN1cmZhY2U7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGFkZENsYXNzZXMsIGRlbGVnYXRlLCBtYXRjaCwgb24sIHJlbW92ZUNsYXNzZXMgfSBmcm9tICdtZXRhbC1kb20nO1xuaW1wb3J0IHsgYXJyYXksIGFzeW5jLCBpc0RlZkFuZE5vdE51bGwsIGlzU3RyaW5nLCBvYmplY3QgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIsIEV2ZW50SGFuZGxlciB9IGZyb20gJ21ldGFsLWV2ZW50cyc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuaW1wb3J0IGRlYm91bmNlIGZyb20gJ21ldGFsLWRlYm91bmNlJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgUm91dGUgZnJvbSAnLi4vcm91dGUvUm91dGUnO1xuaW1wb3J0IFNjcmVlbiBmcm9tICcuLi9zY3JlZW4vU2NyZWVuJztcbmltcG9ydCBTdXJmYWNlIGZyb20gJy4uL3N1cmZhY2UvU3VyZmFjZSc7XG5pbXBvcnQgVXJpIGZyb20gJ21ldGFsLXVyaSc7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi4vdXRpbHMvdXRpbHMnO1xuXG5jb25zdCBOYXZpZ2F0aW9uU3RyYXRlZ3kgPSB7XG5cdElNTUVESUFURTogJ2ltbWVkaWF0ZScsXG5cdFNDSEVEVUxFX0xBU1Q6ICdzY2hlZHVsZUxhc3QnXG59O1xuXG5jbGFzcyBBcHAgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuXG5cdC8qKlxuXHQgKiBBcHAgY2xhc3MgdGhhdCBoYW5kbGUgcm91dGVzIGFuZCBzY3JlZW5zIGxpZmVjeWNsZS5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqIEBleHRlbmRzIHtFdmVudEVtaXR0ZXJ9XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGFjdGl2ZSBzY3JlZW4uXG5cdFx0ICogQHR5cGUgez9TY3JlZW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYWN0aXZlU2NyZWVuID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBhY3RpdmUgcGF0aCBjb250YWluaW5nIHRoZSBxdWVyeSBwYXJhbWV0ZXJzLlxuXHRcdCAqIEB0eXBlIHs/c3RyaW5nfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmFjdGl2ZVBhdGggPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogQWxsb3dzIHByZXZlbnQgbmF2aWdhdGUgZnJvbSBkb20gcHJldmVudGVkIGV2ZW50LlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IHRydWVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5hbGxvd1ByZXZlbnROYXZpZ2F0ZSA9IHRydWU7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBsaW5rIGJhc2UgcGF0aC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCAnJ1xuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmJhc2VQYXRoID0gJyc7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgdmFsdWUgb2YgdGhlIGJyb3dzZXIgcGF0aCBiZWZvcmUgYSBuYXZpZ2F0aW9uIGlzIHBlcmZvcm1lZC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCB0aGUgY3VycmVudCBicm93c2VyIHBhdGguXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYnJvd3NlclBhdGhCZWZvcmVOYXZpZ2F0ZSA9IHV0aWxzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCk7XG5cblx0XHQvKipcblx0XHQgKiBDYXB0dXJlcyBzY3JvbGwgcG9zaXRpb24gZnJvbSBzY3JvbGwgZXZlbnQuXG5cdFx0ICogQHR5cGUgeyFib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IHRydWVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5jYXB0dXJlU2Nyb2xsUG9zaXRpb25Gcm9tU2Nyb2xsRXZlbnQgPSB0cnVlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGRlZmF1bHQgcGFnZSB0aXRsZS5cblx0XHQgKiBAdHlwZSB7c3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5kZWZhdWx0VGl0bGUgPSBnbG9iYWxzLmRvY3VtZW50LnRpdGxlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGZvcm0gc2VsZWN0b3IgdG8gZGVmaW5lIGZvcm1zIHRoYXQgYXJlIHJvdXRlZC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBmb3JtW2VuY3R5cGU9XCJtdWx0aXBhcnQvZm9ybS1kYXRhXCJdOm5vdChbZGF0YS1zZW5uYS1vZmZdKVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmZvcm1TZWxlY3RvciA9ICdmb3JtW2VuY3R5cGU9XCJtdWx0aXBhcnQvZm9ybS1kYXRhXCJdOm5vdChbZGF0YS1zZW5uYS1vZmZdKSc7XG5cblx0XHQvKipcblx0XHQgKiBXaGVuIGVuYWJsZWQsIHRoZSByb3V0ZSBtYXRjaGluZyBpZ25vcmVzIHF1ZXJ5IHN0cmluZyBmcm9tIHRoZSBwYXRoLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoID0gZmFsc2U7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgbGluayBzZWxlY3RvciB0byBkZWZpbmUgbGlua3MgdGhhdCBhcmUgcm91dGVkLlxuXHRcdCAqIEB0eXBlIHshc3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IGE6bm90KFtkYXRhLXNlbm5hLW9mZl0pXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMubGlua1NlbGVjdG9yID0gJ2E6bm90KFtkYXRhLXNlbm5hLW9mZl0pOm5vdChbdGFyZ2V0PVwiX2JsYW5rXCJdKSc7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgbG9hZGluZyBjc3MgY2xhc3MuXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgc2VubmEtbG9hZGluZ1xuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmxvYWRpbmdDc3NDbGFzcyA9ICdzZW5uYS1sb2FkaW5nJztcblxuXHRcdC8qKlxuXHRcdCAqIFVzaW5nIHRoZSBIaXN0b3J5IEFQSSB0byBtYW5hZ2UgeW91ciBVUkxzIGlzIGF3ZXNvbWUgYW5kLCBhcyBpdCBoYXBwZW5zLFxuXHRcdCAqIGEgY3J1Y2lhbCBmZWF0dXJlIG9mIGdvb2Qgd2ViIGFwcHMuIE9uZSBvZiBpdHMgZG93bnNpZGVzLCBob3dldmVyLCBpc1xuXHRcdCAqIHRoYXQgc2Nyb2xsIHBvc2l0aW9ucyBhcmUgc3RvcmVkIGFuZCB0aGVuLCBtb3JlIGltcG9ydGFudGx5LCByZXN0b3JlZFxuXHRcdCAqIHdoZW5ldmVyIHlvdSB0cmF2ZXJzZSB0aGUgaGlzdG9yeS4gVGhpcyBvZnRlbiBtZWFucyB1bnNpZ2h0bHkganVtcHMgYXNcblx0XHQgKiB0aGUgc2Nyb2xsIHBvc2l0aW9uIGNoYW5nZXMgYXV0b21hdGljYWxseSwgYW5kIGVzcGVjaWFsbHkgc28gaWYgeW91ciBhcHBcblx0XHQgKiBkb2VzIHRyYW5zaXRpb25zLCBvciBjaGFuZ2VzIHRoZSBjb250ZW50cyBvZiB0aGUgcGFnZSBpbiBhbnkgd2F5LlxuXHRcdCAqIFVsdGltYXRlbHkgdGhpcyBsZWFkcyB0byBhbiBob3JyaWJsZSB1c2VyIGV4cGVyaWVuY2UuIFRoZSBnb29kIG5ld3MgaXMsXG5cdFx0ICogaG93ZXZlciwgdGhhdCB0aGVyZeKAmXMgYSBwb3RlbnRpYWwgZml4OiBoaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uLlxuXHRcdCAqIGh0dHBzOi8vZGV2ZWxvcGVycy5nb29nbGUuY29tL3dlYi91cGRhdGVzLzIwMTUvMDkvaGlzdG9yeS1hcGktc2Nyb2xsLXJlc3RvcmF0aW9uXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMubmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25TdXBwb3J0ZWQgPSAoJ3Njcm9sbFJlc3RvcmF0aW9uJyBpbiBnbG9iYWxzLndpbmRvdy5oaXN0b3J5KTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gc2V0IHRvIE5hdmlnYXRpb25TdHJhdGVneS5TQ0hFRFVMRV9MQVNUIG1lYW5zIHRoYXQgdGhlIGN1cnJlbnQgbmF2aWdhdGlvblxuXHRcdCAqIGNhbm5vdCBiZSBDYW5jZWxsZWQgdG8gc3RhcnQgYW5vdGhlciBhbmQgd2lsbCBiZSBxdWV1ZWQgaW5cblx0XHQgKiBzY2hlZHVsZWROYXZpZ2F0aW9uUXVldWUuIFdoZW4gTmF2aWdhdGlvblN0cmF0ZWd5LklNTUVESUFURSBtZWFucyB0aGF0IGFsbFxuXHRcdCAqIG5hdmlnYXRpb24gd2lsbCBiZSBjYW5jZWxsZWQgdG8gc3RhcnQgYW5vdGhlci5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBpbW1lZGlhdGVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5uYXZpZ2F0aW9uU3RyYXRlZ3kgPSBOYXZpZ2F0aW9uU3RyYXRlZ3kuSU1NRURJQVRFO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hlbiBzZXQgdG8gdHJ1ZSB0aGVyZSBpcyBhIHBlbmRpbmdOYXZpZ2F0ZSB0aGF0IGhhcyBub3QgeWV0IGJlZW5cblx0XHQgKiByZXNvbHZlZCBvciByZWplY3RlZC5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmlzTmF2aWdhdGlvblBlbmRpbmcgPSBmYWxzZTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGEgZGVmZXJyZWQgd2l0aCB0aGUgY3VycmVudCBuYXZpZ2F0aW9uLlxuXHRcdCAqIEB0eXBlIHs/Q2FuY2VsbGFibGVQcm9taXNlfVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUgPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHdpbmRvdyBob3Jpem9udGFsIHNjcm9sbCBwb3NpdGlvbiB3aGVuIHRoZSBuYXZpZ2F0aW9uIHVzaW5nXG5cdFx0ICogYmFjayBvciBmb3J3YXJkIGhhcHBlbnMgdG8gYmUgcmVzdG9yZWQgYWZ0ZXIgdGhlIHN1cmZhY2VzIGFyZSB1cGRhdGVkLlxuXHRcdCAqIEB0eXBlIHshTnVtYmVyfVxuXHRcdCAqIEBkZWZhdWx0IDBcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wb3BzdGF0ZVNjcm9sbExlZnQgPSAwO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHdpbmRvdyB2ZXJ0aWNhbCBzY3JvbGwgcG9zaXRpb24gd2hlbiB0aGUgbmF2aWdhdGlvbiB1c2luZ1xuXHRcdCAqIGJhY2sgb3IgZm9yd2FyZCBoYXBwZW5zIHRvIGJlIHJlc3RvcmVkIGFmdGVyIHRoZSBzdXJmYWNlcyBhcmUgdXBkYXRlZC5cblx0XHQgKiBAdHlwZSB7IU51bWJlcn1cblx0XHQgKiBAZGVmYXVsdCAwXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucG9wc3RhdGVTY3JvbGxUb3AgPSAwO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHJlZGlyZWN0IHBhdGggY29udGFpbmluZyB0aGUgcXVlcnkgcGFyYW1ldGVycy5cblx0XHQgKiBAdHlwZSB7P3N0cmluZ31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5yZWRpcmVjdFBhdGggPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHNjcmVlbiByb3V0ZXMgY29uZmlndXJhdGlvbi5cblx0XHQgKiBAdHlwZSB7P0FycmF5fVxuXHRcdCAqIEBkZWZhdWx0IFtdXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucm91dGVzID0gW107XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBhIHF1ZXVlIHRoYXQgc3RvcmVzIGV2ZXJ5IERPTSBldmVudCB0aGF0IGNhbiBpbml0aWF0ZSBhIG5hdmlnYXRpb24uXG5cdFx0ICogQHR5cGUgeyFFdmVudH1cblx0XHQgKiBAZGVmYXVsdCBbXVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnNjaGVkdWxlZE5hdmlnYXRpb25RdWV1ZSA9IFtdO1xuXG5cdFx0LyoqXG5cdFx0ICogTWFwcyB0aGUgc2NyZWVuIGluc3RhbmNlcyBieSB0aGUgdXJsIGNvbnRhaW5pbmcgdGhlIHBhcmFtZXRlcnMuXG5cdFx0ICogQHR5cGUgez9PYmplY3R9XG5cdFx0ICogQGRlZmF1bHQge31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5zY3JlZW5zID0ge307XG5cblx0XHQvKipcblx0XHQgKiBXaGVuIHNldCB0byB0cnVlIHRoZSBmaXJzdCBlcnJvbmVvdXMgcG9wc3RhdGUgZmlyZWQgb24gcGFnZSBsb2FkIHdpbGwgYmVcblx0XHQgKiBpZ25vcmVkLCBvbmx5IGlmIDxjb2RlPmdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc3RhdGU8L2NvZGU+IGlzIGFsc29cblx0XHQgKiA8Y29kZT5udWxsPC9jb2RlPi5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnNraXBMb2FkUG9wc3RhdGUgPSBmYWxzZTtcblxuXHRcdC8qKlxuXHRcdCAqIE1hcHMgdGhhdCBpbmRleCB0aGUgc3VyZmFjZXMgaW5zdGFuY2VzIGJ5IHRoZSBzdXJmYWNlIGlkLlxuXHRcdCAqIEB0eXBlIHs/T2JqZWN0fVxuXHRcdCAqIEBkZWZhdWx0IHt9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuc3VyZmFjZXMgPSB7fTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gc2V0IHRvIHRydWUsIG1vdmVzIHRoZSBzY3JvbGwgcG9zaXRpb24gYWZ0ZXIgcG9wc3RhdGUsIG9yIHRvIHRoZVxuXHRcdCAqIHRvcCBvZiB0aGUgdmlld3BvcnQgZm9yIG5ldyBuYXZpZ2F0aW9uLiBJZiBmYWxzZSwgdGhlIGJyb3dzZXIgd2lsbFxuXHRcdCAqIHRha2UgY2FyZSBvZiBzY3JvbGwgcmVzdG9yYXRpb24uXG5cdFx0ICogQHR5cGUgeyFib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IHRydWVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy51cGRhdGVTY3JvbGxQb3NpdGlvbiA9IHRydWU7XG5cblx0XHR0aGlzLmFwcEV2ZW50SGFuZGxlcnNfID0gbmV3IEV2ZW50SGFuZGxlcigpO1xuXG5cdFx0dGhpcy5hcHBFdmVudEhhbmRsZXJzXy5hZGQoXG5cdFx0XHRvbihnbG9iYWxzLndpbmRvdywgJ3Njcm9sbCcsIGRlYm91bmNlKHRoaXMub25TY3JvbGxfLmJpbmQodGhpcyksIDEwMCkpLFxuXHRcdFx0b24oZ2xvYmFscy53aW5kb3csICdsb2FkJywgdGhpcy5vbkxvYWRfLmJpbmQodGhpcykpLFxuXHRcdFx0b24oZ2xvYmFscy53aW5kb3csICdwb3BzdGF0ZScsIHRoaXMub25Qb3BzdGF0ZV8uYmluZCh0aGlzKSlcblx0XHQpO1xuXG5cdFx0dGhpcy5vbignc3RhcnROYXZpZ2F0ZScsIHRoaXMub25TdGFydE5hdmlnYXRlXyk7XG5cdFx0dGhpcy5vbignYmVmb3JlTmF2aWdhdGUnLCB0aGlzLm9uQmVmb3JlTmF2aWdhdGVfKTtcblx0XHR0aGlzLm9uKCdiZWZvcmVOYXZpZ2F0ZScsIHRoaXMub25CZWZvcmVOYXZpZ2F0ZURlZmF1bHRfLCB0cnVlKTtcblx0XHR0aGlzLm9uKCdiZWZvcmVVbmxvYWQnLCB0aGlzLm9uQmVmb3JlVW5sb2FkRGVmYXVsdF8pO1xuXG5cdFx0dGhpcy5zZXRMaW5rU2VsZWN0b3IodGhpcy5saW5rU2VsZWN0b3IpO1xuXHRcdHRoaXMuc2V0Rm9ybVNlbGVjdG9yKHRoaXMuZm9ybVNlbGVjdG9yKTtcblxuXHRcdHRoaXMubWF5YmVPdmVybG9hZEJlZm9yZVVubG9hZF8oKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIG9uZSBvciBtb3JlIHNjcmVlbnMgdG8gdGhlIGFwcGxpY2F0aW9uLlxuXHQgKlxuXHQgKiBFeGFtcGxlOlxuXHQgKlxuXHQgKiA8Y29kZT5cblx0ICogICBhcHAuYWRkUm91dGVzKHsgcGF0aDogJy9mb28nLCBoYW5kbGVyOiBGb29TY3JlZW4gfSk7XG5cdCAqICAgb3Jcblx0ICogICBhcHAuYWRkUm91dGVzKFt7IHBhdGg6ICcvZm9vJywgaGFuZGxlcjogZnVuY3Rpb24ocm91dGUpIHsgcmV0dXJuIG5ldyBGb29TY3JlZW4oKTsgfSB9XSk7XG5cdCAqIDwvY29kZT5cblx0ICpcblx0ICogQHBhcmFtIHtPYmplY3R9IG9yIHtBcnJheX0gcm91dGVzIFNpbmdsZSBvYmplY3Qgb3IgYW4gYXJyYXkgb2Ygb2JqZWN0LlxuXHQgKiAgICAgRWFjaCBvYmplY3Qgc2hvdWxkIGNvbnRhaW4gPGNvZGU+cGF0aDwvY29kZT4gYW5kIDxjb2RlPnNjcmVlbjwvY29kZT4uXG5cdCAqICAgICBUaGUgPGNvZGU+cGF0aDwvY29kZT4gc2hvdWxkIGJlIGEgc3RyaW5nIG9yIGEgcmVnZXggdGhhdCBtYXBzIHRoZVxuXHQgKiAgICAgbmF2aWdhdGlvbiByb3V0ZSB0byBhIHNjcmVlbiBjbGFzcyBkZWZpbml0aW9uIChub3QgYW4gaW5zdGFuY2UpLCBlLmc6XG5cdCAqICAgICAgICAgPGNvZGU+eyBwYXRoOiBcIi9ob21lOnBhcmFtMVwiLCBoYW5kbGVyOiBNeVNjcmVlbiB9PC9jb2RlPlxuXHQgKiAgICAgICAgIDxjb2RlPnsgcGF0aDogL2Zvby4rLywgaGFuZGxlcjogTXlTY3JlZW4gfTwvY29kZT5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkUm91dGVzKHJvdXRlcykge1xuXHRcdGlmICghQXJyYXkuaXNBcnJheShyb3V0ZXMpKSB7XG5cdFx0XHRyb3V0ZXMgPSBbcm91dGVzXTtcblx0XHR9XG5cdFx0cm91dGVzLmZvckVhY2goKHJvdXRlKSA9PiB7XG5cdFx0XHRpZiAoIShyb3V0ZSBpbnN0YW5jZW9mIFJvdXRlKSkge1xuXHRcdFx0XHRyb3V0ZSA9IG5ldyBSb3V0ZShyb3V0ZS5wYXRoLCByb3V0ZS5oYW5kbGVyKTtcblx0XHRcdH1cblx0XHRcdHRoaXMucm91dGVzLnB1c2gocm91dGUpO1xuXHRcdH0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgb25lIG9yIG1vcmUgc3VyZmFjZXMgdG8gdGhlIGFwcGxpY2F0aW9uLlxuXHQgKiBAcGFyYW0ge1N1cmZhY2V8U3RyaW5nfEFycmF5LjxTdXJmYWNlfFN0cmluZz59IHN1cmZhY2VzXG5cdCAqICAgICBTdXJmYWNlIGVsZW1lbnQgaWQgb3Igc3VyZmFjZSBpbnN0YW5jZS4gWW91IGNhbiBhbHNvIHBhc3MgYW4gQXJyYXlcblx0ICogICAgIHdoaWNoY29udGFpbnMgc3VyZmFjZSBpbnN0YW5jZXMgb3IgaWQuIEluIGNhc2Ugb2YgSUQsIHRoZXNlIHNob3VsZCBiZVxuXHQgKiAgICAgdGhlIGlkIG9mIHN1cmZhY2UgZWxlbWVudC5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkU3VyZmFjZXMoc3VyZmFjZXMpIHtcblx0XHRpZiAoIUFycmF5LmlzQXJyYXkoc3VyZmFjZXMpKSB7XG5cdFx0XHRzdXJmYWNlcyA9IFtzdXJmYWNlc107XG5cdFx0fVxuXHRcdHN1cmZhY2VzLmZvckVhY2goKHN1cmZhY2UpID0+IHtcblx0XHRcdGlmIChpc1N0cmluZyhzdXJmYWNlKSkge1xuXHRcdFx0XHRzdXJmYWNlID0gbmV3IFN1cmZhY2Uoc3VyZmFjZSk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnN1cmZhY2VzW3N1cmZhY2UuZ2V0SWQoKV0gPSBzdXJmYWNlO1xuXHRcdH0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgaWYgY2FuIG5hdmlnYXRlIHRvIHBhdGguXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gdXJsXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRjYW5OYXZpZ2F0ZSh1cmwpIHtcblx0XHRjb25zdCB1cmkgPSB1dGlscy5pc1dlYlVyaSh1cmwpO1xuXG5cdFx0aWYgKCF1cmkpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRjb25zdCBwYXRoID0gdXRpbHMuZ2V0VXJsUGF0aCh1cmwpO1xuXG5cdFx0aWYgKCF0aGlzLmlzTGlua1NhbWVPcmlnaW5fKHVyaS5nZXRIb3N0KCkpKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnT2Zmc2l0ZSBsaW5rIGNsaWNrZWQnKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0aWYgKCF0aGlzLmlzU2FtZUJhc2VQYXRoXyhwYXRoKSkge1xuXHRcdFx0Y29uc29sZS5sb2coJ0xpbmsgY2xpY2tlZCBvdXRzaWRlIGFwcFxcJ3MgYmFzZSBwYXRoJyk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdC8vIFByZXZlbnRzIG5hdmlnYXRpb24gaWYgaXQncyBhIGhhc2ggY2hhbmdlIG9uIHRoZSBzYW1lIHVybC5cblx0XHRpZiAodXJpLmdldEhhc2goKSAmJiB1dGlscy5pc0N1cnJlbnRCcm93c2VyUGF0aChwYXRoKSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRpZiAoIXRoaXMuZmluZFJvdXRlKHBhdGgpKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnTm8gcm91dGUgZm9yICcgKyBwYXRoKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhciBzY3JlZW5zIGNhY2hlLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRjbGVhclNjcmVlbnNDYWNoZSgpIHtcblx0XHRPYmplY3Qua2V5cyh0aGlzLnNjcmVlbnMpLmZvckVhY2goKHBhdGgpID0+IHtcblx0XHRcdGlmIChwYXRoID09PSB0aGlzLmFjdGl2ZVBhdGgpIHtcblx0XHRcdFx0dGhpcy5hY3RpdmVTY3JlZW4uY2xlYXJDYWNoZSgpO1xuXHRcdFx0fSBlbHNlIGlmICghKHRoaXMuaXNOYXZpZ2F0aW9uUGVuZGluZyAmJiB0aGlzLnBlbmRpbmdOYXZpZ2F0ZS5wYXRoID09PSBwYXRoKSkge1xuXHRcdFx0XHR0aGlzLnJlbW92ZVNjcmVlbihwYXRoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXRyaWV2ZXMgb3IgY3JlYXRlIGEgc2NyZWVuIGluc3RhbmNlIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHJldHVybiB7U2NyZWVufVxuXHQgKi9cblx0Y3JlYXRlU2NyZWVuSW5zdGFuY2UocGF0aCwgcm91dGUpIHtcblx0XHRpZiAoIXRoaXMucGVuZGluZ05hdmlnYXRlICYmIHBhdGggPT09IHRoaXMuYWN0aXZlUGF0aCkge1xuXHRcdFx0Y29uc29sZS5sb2coJ0FscmVhZHkgYXQgZGVzdGluYXRpb24sIHJlZnJlc2ggbmF2aWdhdGlvbicpO1xuXHRcdFx0cmV0dXJuIHRoaXMuYWN0aXZlU2NyZWVuO1xuXHRcdH1cblx0XHQvKiBqc2hpbnQgbmV3Y2FwOiBmYWxzZSAqL1xuXHRcdHZhciBzY3JlZW4gPSB0aGlzLnNjcmVlbnNbcGF0aF07XG5cdFx0aWYgKCFzY3JlZW4pIHtcblx0XHRcdHZhciBoYW5kbGVyID0gcm91dGUuZ2V0SGFuZGxlcigpO1xuXHRcdFx0aWYgKGhhbmRsZXIgPT09IFNjcmVlbiB8fCBTY3JlZW4uaXNJbXBsZW1lbnRlZEJ5KGhhbmRsZXIucHJvdG90eXBlKSkge1xuXHRcdFx0XHRzY3JlZW4gPSBuZXcgaGFuZGxlcigpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2NyZWVuID0gaGFuZGxlcihyb3V0ZSkgfHwgbmV3IFNjcmVlbigpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc29sZS5sb2coJ0NyZWF0ZSBzY3JlZW4gZm9yIFsnICsgcGF0aCArICddIFsnICsgc2NyZWVuICsgJ10nKTtcblx0XHR9XG5cdFx0cmV0dXJuIHNjcmVlbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbikge1xuXHRcdFx0dGhpcy5yZW1vdmVTY3JlZW4odGhpcy5hY3RpdmVQYXRoKTtcblx0XHR9XG5cdFx0dGhpcy5jbGVhclNjcmVlbnNDYWNoZSgpO1xuXHRcdHRoaXMuZm9ybUV2ZW50SGFuZGxlcl8ucmVtb3ZlTGlzdGVuZXIoKTtcblx0XHR0aGlzLmxpbmtFdmVudEhhbmRsZXJfLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0dGhpcy5hcHBFdmVudEhhbmRsZXJzXy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcblx0XHRzdXBlci5kaXNwb3NlSW50ZXJuYWwoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwYXRjaGVzIHRvIHRoZSBmaXJzdCByb3V0ZSBoYW5kbGVyIHRoYXQgbWF0Y2hlcyB0aGUgY3VycmVudCBwYXRoLCBpZlxuXHQgKiBhbnkuXG5cdCAqIEByZXR1cm4ge0NhbmNlbGxhYmxlUHJvbWlzZX0gUmV0dXJucyBhIHBlbmRpbmcgcmVxdWVzdCBjYW5jZWxsYWJsZSBwcm9taXNlLlxuXHQgKi9cblx0ZGlzcGF0Y2goKSB7XG5cdFx0cmV0dXJuIHRoaXMubmF2aWdhdGUodXRpbHMuZ2V0Q3VycmVudEJyb3dzZXJQYXRoKCksIHRydWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0cyBuYXZpZ2F0aW9uIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3JlcGxhY2VIaXN0b3J5IFJlcGxhY2VzIGJyb3dzZXIgaGlzdG9yeS5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBSZXR1cm5zIGEgcGVuZGluZyByZXF1ZXN0IGNhbmNlbGxhYmxlIHByb21pc2UuXG5cdCAqL1xuXHRkb05hdmlnYXRlXyhwYXRoLCBvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHR2YXIgcm91dGUgPSB0aGlzLmZpbmRSb3V0ZShwYXRoKTtcblx0XHRpZiAoIXJvdXRlKSB7XG5cdFx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZSA9IENhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcignTm8gcm91dGUgZm9yICcgKyBwYXRoKSk7XG5cdFx0XHRyZXR1cm4gdGhpcy5wZW5kaW5nTmF2aWdhdGU7XG5cdFx0fVxuXG5cdFx0Y29uc29sZS5sb2coJ05hdmlnYXRlIHRvIFsnICsgcGF0aCArICddJyk7XG5cblx0XHR0aGlzLnN0b3BQZW5kaW5nTmF2aWdhdGVfKCk7XG5cdFx0dGhpcy5pc05hdmlnYXRpb25QZW5kaW5nID0gdHJ1ZTtcblxuXHRcdHZhciBuZXh0U2NyZWVuID0gdGhpcy5jcmVhdGVTY3JlZW5JbnN0YW5jZShwYXRoLCByb3V0ZSk7XG5cblx0XHRyZXR1cm4gdGhpcy5tYXliZVByZXZlbnREZWFjdGl2YXRlXygpXG5cdFx0XHQudGhlbigoKSA9PiB0aGlzLm1heWJlUHJldmVudEFjdGl2YXRlXyhuZXh0U2NyZWVuKSlcblx0XHRcdC50aGVuKCgpID0+IG5leHRTY3JlZW4ubG9hZChwYXRoKSlcblx0XHRcdC50aGVuKCgpID0+IHtcblx0XHRcdFx0Ly8gQXQgdGhpcyBwb2ludCB3ZSBjYW5ub3Qgc3RvcCBuYXZpZ2F0aW9uIGFuZCBhbGwgcmVjZWl2ZWRcblx0XHRcdFx0Ly8gbmF2aWdhdGUgY2FuZGlkYXRlcyB3aWxsIGJlIHF1ZXVlZCBhdCBzY2hlZHVsZWROYXZpZ2F0aW9uUXVldWUuXG5cdFx0XHRcdHRoaXMubmF2aWdhdGlvblN0cmF0ZWd5ID0gTmF2aWdhdGlvblN0cmF0ZWd5LlNDSEVEVUxFX0xBU1Q7XG5cblx0XHRcdFx0aWYgKHRoaXMuYWN0aXZlU2NyZWVuKSB7XG5cdFx0XHRcdFx0dGhpcy5hY3RpdmVTY3JlZW4uZGVhY3RpdmF0ZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMucHJlcGFyZU5hdmlnYXRlSGlzdG9yeV8ocGF0aCwgbmV4dFNjcmVlbiwgb3B0X3JlcGxhY2VIaXN0b3J5KTtcblx0XHRcdFx0dGhpcy5wcmVwYXJlTmF2aWdhdGVTdXJmYWNlc18oXG5cdFx0XHRcdFx0bmV4dFNjcmVlbixcblx0XHRcdFx0XHR0aGlzLnN1cmZhY2VzLFxuXHRcdFx0XHRcdHRoaXMuZXh0cmFjdFBhcmFtcyhyb3V0ZSwgcGF0aClcblx0XHRcdFx0KTtcblx0XHRcdH0pXG5cdFx0XHQudGhlbigoKSA9PiBuZXh0U2NyZWVuLmV2YWx1YXRlU3R5bGVzKHRoaXMuc3VyZmFjZXMpKVxuXHRcdFx0LnRoZW4oKCkgPT4gbmV4dFNjcmVlbi5mbGlwKHRoaXMuc3VyZmFjZXMpKVxuXHRcdFx0LnRoZW4oKCkgPT4gbmV4dFNjcmVlbi5ldmFsdWF0ZVNjcmlwdHModGhpcy5zdXJmYWNlcykpXG5cdFx0XHQudGhlbigoKSA9PiB0aGlzLm1heWJlVXBkYXRlU2Nyb2xsUG9zaXRpb25TdGF0ZV8oKSlcblx0XHRcdC50aGVuKCgpID0+IHRoaXMuc3luY1Njcm9sbFBvc2l0aW9uU3luY1RoZW5Bc3luY18oKSlcblx0XHRcdC50aGVuKCgpID0+IHRoaXMuZmluYWxpemVOYXZpZ2F0ZV8ocGF0aCwgbmV4dFNjcmVlbikpXG5cdFx0XHQudGhlbigoKSA9PiB0aGlzLm1heWJlT3ZlcmxvYWRCZWZvcmVVbmxvYWRfKCkpXG5cdFx0XHQuY2F0Y2goKHJlYXNvbikgPT4ge1xuXHRcdFx0XHR0aGlzLmlzTmF2aWdhdGlvblBlbmRpbmcgPSBmYWxzZTtcblx0XHRcdFx0dGhpcy5oYW5kbGVOYXZpZ2F0ZUVycm9yXyhwYXRoLCBuZXh0U2NyZWVuLCByZWFzb24pO1xuXHRcdFx0XHR0aHJvdyByZWFzb247XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW5BbHdheXMoKCkgPT4ge1xuXHRcdFx0XHR0aGlzLm5hdmlnYXRpb25TdHJhdGVneSA9IE5hdmlnYXRpb25TdHJhdGVneS5JTU1FRElBVEU7XG5cblx0XHRcdFx0aWYgKHRoaXMuc2NoZWR1bGVkTmF2aWdhdGlvblF1ZXVlLmxlbmd0aCkge1xuXHRcdFx0XHRcdGNvbnN0IHNjaGVkdWxlZE5hdmlnYXRpb24gPSB0aGlzLnNjaGVkdWxlZE5hdmlnYXRpb25RdWV1ZS5zaGlmdCgpO1xuXHRcdFx0XHRcdHRoaXMubWF5YmVOYXZpZ2F0ZV8oc2NoZWR1bGVkTmF2aWdhdGlvbi5ocmVmLCBzY2hlZHVsZWROYXZpZ2F0aW9uKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogRXh0cmFjdHMgcGFyYW1zIGFjY29yZGluZyB0byB0aGUgZ2l2ZW4gcGF0aCBhbmQgcm91dGUuXG5cdCAqIEBwYXJhbSB7IVJvdXRlfSByb3V0ZVxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGF0aFxuXHQgKiBAcGFyYW0geyFPYmplY3R9XG5cdCAqL1xuXHRleHRyYWN0UGFyYW1zKHJvdXRlLCBwYXRoKSB7XG5cdFx0cmV0dXJuIHJvdXRlLmV4dHJhY3RQYXJhbXModGhpcy5nZXRSb3V0ZVBhdGgocGF0aCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpbmFsaXplcyBhIHNjcmVlbiBuYXZpZ2F0aW9uLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcGFyYW0geyFTY3JlZW59IG5leHRTY3JlZW5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0ZmluYWxpemVOYXZpZ2F0ZV8ocGF0aCwgbmV4dFNjcmVlbikge1xuXHRcdG5leHRTY3JlZW4uYWN0aXZhdGUoKTtcblxuXHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbiAmJiAhdGhpcy5hY3RpdmVTY3JlZW4uaXNDYWNoZWFibGUoKSkge1xuXHRcdFx0aWYgKHRoaXMuYWN0aXZlU2NyZWVuICE9PSBuZXh0U2NyZWVuKSB7XG5cdFx0XHRcdHRoaXMucmVtb3ZlU2NyZWVuKHRoaXMuYWN0aXZlUGF0aCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5hY3RpdmVQYXRoID0gcGF0aDtcblx0XHR0aGlzLmFjdGl2ZVNjcmVlbiA9IG5leHRTY3JlZW47XG5cdFx0dGhpcy5icm93c2VyUGF0aEJlZm9yZU5hdmlnYXRlID0gdXRpbHMuZ2V0Q3VycmVudEJyb3dzZXJQYXRoV2l0aG91dEhhc2goKTtcblx0XHR0aGlzLnNjcmVlbnNbcGF0aF0gPSBuZXh0U2NyZWVuO1xuXHRcdHRoaXMuaXNOYXZpZ2F0aW9uUGVuZGluZyA9IGZhbHNlO1xuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gbnVsbDtcblx0XHRnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQgPSBudWxsO1xuXHRcdGdsb2JhbHMuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCA9IG51bGw7XG5cdFx0Y29uc29sZS5sb2coJ05hdmlnYXRpb24gZG9uZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpbmRzIGEgcm91dGUgZm9yIHRoZSB0ZXN0IHBhdGguIFJldHVybnMgdHJ1ZSBpZiBtYXRjaGVzIGhhcyBhIHJvdXRlLFxuXHQgKiBvdGhlcndpc2UgcmV0dXJucyBudWxsLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcmV0dXJuIHs/T2JqZWN0fSBSb3V0ZSBoYW5kbGVyIGlmIG1hdGNoIGFueSBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiB0aGVcblx0ICogICAgIHBhdGggaXMgdGhlIHNhbWUgYXMgdGhlIGN1cnJlbnQgdXJsIGFuZCB0aGUgcGF0aCBjb250YWlucyBhIGZyYWdtZW50LlxuXHQgKi9cblx0ZmluZFJvdXRlKHBhdGgpIHtcblx0XHRwYXRoID0gdGhpcy5nZXRSb3V0ZVBhdGgocGF0aCk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnJvdXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIHJvdXRlID0gdGhpcy5yb3V0ZXNbaV07XG5cdFx0XHRpZiAocm91dGUubWF0Y2hlc1BhdGgocGF0aCkpIHtcblx0XHRcdFx0cmV0dXJuIHJvdXRlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYWxsb3cgcHJldmVudCBuYXZpZ2F0ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldEFsbG93UHJldmVudE5hdmlnYXRlKCkge1xuXHRcdHJldHVybiB0aGlzLmFsbG93UHJldmVudE5hdmlnYXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgbGluayBiYXNlIHBhdGguXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqL1xuXHRnZXRCYXNlUGF0aCgpIHtcblx0XHRyZXR1cm4gdGhpcy5iYXNlUGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBkZWZhdWx0IHBhZ2UgdGl0bGUuXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gZGVmYXVsdFRpdGxlXG5cdCAqL1xuXHRnZXREZWZhdWx0VGl0bGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZGVmYXVsdFRpdGxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGZvcm0gc2VsZWN0b3IuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqL1xuXHRnZXRGb3JtU2VsZWN0b3IoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZm9ybVNlbGVjdG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrIGlmIHJvdXRlIG1hdGNoaW5nIGlzIGlnbm9yaW5nIHF1ZXJ5IHN0cmluZyBmcm9tIHRoZSByb3V0ZSBwYXRoLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0Z2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKCkge1xuXHRcdHJldHVybiB0aGlzLmlnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBsaW5rIHNlbGVjdG9yLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKi9cblx0Z2V0TGlua1NlbGVjdG9yKCkge1xuXHRcdHJldHVybiB0aGlzLmxpbmtTZWxlY3Rvcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBsb2FkaW5nIGNzcyBjbGFzcy5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICovXG5cdGdldExvYWRpbmdDc3NDbGFzcygpIHtcblx0XHRyZXR1cm4gdGhpcy5sb2FkaW5nQ3NzQ2xhc3M7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgZ2l2ZW4gcGF0aCBmb3JtYXR0ZWQgdG8gYmUgbWF0Y2hlZCBieSBhIHJvdXRlLiBUaGlzIHdpbGwsXG5cdCAqIGZvciBleGFtcGxlLCByZW1vdmUgdGhlIGJhc2UgcGF0aCBmcm9tIGl0LCBidXQgbWFrZSBzdXJlIGl0IHdpbGwgZW5kXG5cdCAqIHdpdGggYSAnLycuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldFJvdXRlUGF0aChwYXRoKSB7XG5cdFx0aWYgKHRoaXMuZ2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKCkpIHtcblx0XHRcdHBhdGggPSB1dGlscy5nZXRVcmxQYXRoV2l0aG91dEhhc2hBbmRTZWFyY2gocGF0aCk7XG5cdFx0XHRyZXR1cm4gdXRpbHMuZ2V0VXJsUGF0aFdpdGhvdXRIYXNoQW5kU2VhcmNoKHBhdGguc3Vic3RyKHRoaXMuYmFzZVBhdGgubGVuZ3RoKSk7XG5cdFx0fVxuXG5cdFx0cGF0aCA9IHV0aWxzLmdldFVybFBhdGhXaXRob3V0SGFzaChwYXRoKTtcblx0XHRyZXR1cm4gdXRpbHMuZ2V0VXJsUGF0aFdpdGhvdXRIYXNoKHBhdGguc3Vic3RyKHRoaXMuYmFzZVBhdGgubGVuZ3RoKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgdXBkYXRlIHNjcm9sbCBwb3NpdGlvbiB2YWx1ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldFVwZGF0ZVNjcm9sbFBvc2l0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLnVwZGF0ZVNjcm9sbFBvc2l0aW9uO1xuXHR9XG5cblx0LyoqXG5cdCAqIEhhbmRsZSBuYXZpZ2F0aW9uIGVycm9yLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcGFyYW0geyFTY3JlZW59IG5leHRTY3JlZW5cblx0ICogQHBhcmFtIHshRXJyb3J9IGVycm9yXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGhhbmRsZU5hdmlnYXRlRXJyb3JfKHBhdGgsIG5leHRTY3JlZW4sIGVycm9yKSB7XG5cdFx0Y29uc29sZS5sb2coJ05hdmlnYXRpb24gZXJyb3IgZm9yIFsnICsgbmV4dFNjcmVlbiArICddICgnICsgZXJyb3Iuc3RhY2sgKyAnKScpO1xuXHRcdHRoaXMuZW1pdCgnbmF2aWdhdGlvbkVycm9yJywge1xuXHRcdFx0ZXJyb3IsXG5cdFx0XHRuZXh0U2NyZWVuLFxuXHRcdFx0cGF0aFxuXHRcdH0pO1xuXHRcdGlmICghdXRpbHMuaXNDdXJyZW50QnJvd3NlclBhdGgocGF0aCkpIHtcblx0XHRcdGlmICh0aGlzLmlzTmF2aWdhdGlvblBlbmRpbmcgJiYgdGhpcy5wZW5kaW5nTmF2aWdhdGUpIHtcblx0XHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUudGhlbkFsd2F5cygoKSA9PiB0aGlzLnJlbW92ZVNjcmVlbihwYXRoKSwgdGhpcyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnJlbW92ZVNjcmVlbihwYXRoKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIGFwcCBoYXMgcm91dGVzLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0aGFzUm91dGVzKCkge1xuXHRcdHJldHVybiB0aGlzLnJvdXRlcy5sZW5ndGggPiAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRlc3RzIGlmIGhvc3QgaXMgYW4gb2Zmc2l0ZSBsaW5rLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IGhvc3QgTGluayBob3N0IHRvIGNvbXBhcmUgd2l0aFxuXHQgKiAgICAgPGNvZGU+Z2xvYmFscy53aW5kb3cubG9jYXRpb24uaG9zdDwvY29kZT4uXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGlzTGlua1NhbWVPcmlnaW5fKGhvc3QpIHtcblx0XHRjb25zdCBob3N0VXJpID0gbmV3IFVyaShob3N0KTtcblx0XHRjb25zdCBsb2NhdGlvbkhvc3RVcmkgPSBuZXcgVXJpKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhvc3QpO1xuXG5cdFx0cmV0dXJuIGhvc3RVcmkuZ2V0UG9ydCgpID09PSBsb2NhdGlvbkhvc3RVcmkuZ2V0UG9ydCgpICYmIGhvc3RVcmkuZ2V0SG9zdG5hbWUoKSA9PT0gbG9jYXRpb25Ib3N0VXJpLmdldEhvc3RuYW1lKCk7XG5cdH1cblxuXHQvKipcblx0ICogVGVzdHMgaWYgbGluayBlbGVtZW50IGhhcyB0aGUgc2FtZSBhcHAncyBiYXNlIHBhdGguXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBMaW5rIHBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0aXNTYW1lQmFzZVBhdGhfKHBhdGgpIHtcblx0XHRyZXR1cm4gcGF0aC5pbmRleE9mKHRoaXMuYmFzZVBhdGgpID09PSAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIExvY2sgdGhlIGRvY3VtZW50IHNjcm9sbCBpbiBvcmRlciB0byBhdm9pZCB0aGUgYnJvd3NlciBuYXRpdmUgYmFjayBhbmRcblx0ICogZm9yd2FyZCBuYXZpZ2F0aW9uIHRvIGNoYW5nZSB0aGUgc2Nyb2xsIHBvc2l0aW9uLiBJbiB0aGUgZW5kIG9mXG5cdCAqIG5hdmlnYXRpb24gbGlmZWN5Y2xlIHNjcm9sbCBpcyByZXBvc2l0aW9uZWQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGxvY2tIaXN0b3J5U2Nyb2xsUG9zaXRpb25fKCkge1xuXHRcdHZhciBzdGF0ZSA9IGdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc3RhdGU7XG5cdFx0aWYgKCFzdGF0ZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvLyBCcm93c2VycyBhcmUgaW5jb25zaXN0ZW50IHdoZW4gcmUtcG9zaXRpb25pbmcgdGhlIHNjcm9sbCBoaXN0b3J5IG9uXG5cdFx0Ly8gcG9wc3RhdGUuIEF0IHNvbWUgYnJvd3NlcnMsIGhpc3Rvcnkgc2Nyb2xsIGhhcHBlbnMgYmVmb3JlIHBvcHN0YXRlLCB0aGVuXG5cdFx0Ly8gbG9jayB0aGUgc2Nyb2xsIG9uIHRoZSBsYXN0IGtub3duIHBvc2l0aW9uIGFzIHNvb24gYXMgcG9zc2libGUgYWZ0ZXIgdGhlXG5cdFx0Ly8gY3VycmVudCBKUyBleGVjdXRpb24gY29udGV4dCBhbmQgY2FwdHVyZSB0aGUgY3VycmVudCB2YWx1ZS4gU29tZSBvdGhlcnMsXG5cdFx0Ly8gaGlzdG9yeSBzY3JvbGwgaGFwcGVucyBhZnRlciBwb3BzdGF0ZSwgaW4gdGhpcyBjYXNlLCB3ZSBiaW5kIGFuIG9uY2Vcblx0XHQvLyBzY3JvbGwgZXZlbnQgdG8gbG9jayB0aGUgbGFzIGtub3duIHBvc2l0aW9uLiBMYXN0bHksIHRoZSBwcmV2aW91cyB0d29cblx0XHQvLyBiZWhhdmlvcnMgY2FuIGhhcHBlbiBldmVuIG9uIHRoZSBzYW1lIGJyb3dzZXIsIGhlbmNlIHRoZSByYWNlIHdpbGwgZGVjaWRlXG5cdFx0Ly8gdGhlIHdpbm5lci5cblx0XHR2YXIgd2lubmVyID0gZmFsc2U7XG5cdFx0dmFyIHN3aXRjaFNjcm9sbFBvc2l0aW9uUmFjZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0Z2xvYmFscy5kb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBzd2l0Y2hTY3JvbGxQb3NpdGlvblJhY2UsIGZhbHNlKTtcblx0XHRcdGlmICghd2lubmVyKSB7XG5cdFx0XHRcdGdsb2JhbHMud2luZG93LnNjcm9sbFRvKHN0YXRlLnNjcm9sbExlZnQsIHN0YXRlLnNjcm9sbFRvcCk7XG5cdFx0XHRcdHdpbm5lciA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRhc3luYy5uZXh0VGljayhzd2l0Y2hTY3JvbGxQb3NpdGlvblJhY2UpO1xuXHRcdGdsb2JhbHMuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgc3dpdGNoU2Nyb2xsUG9zaXRpb25SYWNlLCBmYWxzZSk7XG5cdH1cblxuXHQvKipcblx0ICogSWYgc3VwcG9ydGVkIGJ5IHRoZSBicm93c2VyLCBkaXNhYmxlcyBuYXRpdmUgc2Nyb2xsIHJlc3RvcmF0aW9uIGFuZFxuXHQgKiBzdG9yZXMgY3VycmVudCB2YWx1ZS5cblx0ICovXG5cdG1heWJlRGlzYWJsZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uKCkge1xuXHRcdGlmICh0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uU3VwcG9ydGVkKSB7XG5cdFx0XHR0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uXyA9IGdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc2Nyb2xsUmVzdG9yYXRpb247XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uID0gJ21hbnVhbCc7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gZXZhbHVhdGUgaWYgaXMgcG9zc2libGUgdG8gcXVldWUgcmVjZWl2ZWRcblx0ICogIGRvbSBldmVudCB0byBzY2hlZHVsZU5hdmlnYXRpb25RdWV1ZSBhbmQgZW5xdWV1ZSBpdC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGhyZWYgSW5mb3JtYXRpb24gYWJvdXQgdGhlIGxpbmsncyBocmVmLlxuXHQgKiBAcGFyYW0ge0V2ZW50fSBldmVudCBEb20gZXZlbnQgdGhhdCBpbml0aWF0ZWQgdGhlIG5hdmlnYXRpb24uXG5cdCAqL1xuXHRtYXliZVNjaGVkdWxlTmF2aWdhdGlvbl8oaHJlZiwgZXZlbnQpIHtcblx0XHRpZiAodGhpcy5pc05hdmlnYXRpb25QZW5kaW5nICYmIHRoaXMubmF2aWdhdGlvblN0cmF0ZWd5ID09PSBOYXZpZ2F0aW9uU3RyYXRlZ3kuU0NIRURVTEVfTEFTVCkge1xuXHRcdFx0dGhpcy5zY2hlZHVsZWROYXZpZ2F0aW9uUXVldWUgPSBbb2JqZWN0Lm1peGluKHtcblx0XHRcdFx0aHJlZixcblx0XHRcdFx0aXNTY2hlZHVsZWROYXZpZ2F0aW9uOiB0cnVlXG5cdFx0XHR9LCBldmVudCldO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBuYXZpZ2F0ZSB0byBhIHBhdGguXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBocmVmIEluZm9ybWF0aW9uIGFib3V0IHRoZSBsaW5rJ3MgaHJlZi5cblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnQgRG9tIGV2ZW50IHRoYXQgaW5pdGlhdGVkIHRoZSBuYXZpZ2F0aW9uLlxuXHQgKi9cblx0bWF5YmVOYXZpZ2F0ZV8oaHJlZiwgZXZlbnQpIHtcblx0XHRpZiAoIXRoaXMuY2FuTmF2aWdhdGUoaHJlZikpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCBpc05hdmlnYXRpb25TY2hlZHVsZWQgPSB0aGlzLm1heWJlU2NoZWR1bGVOYXZpZ2F0aW9uXyhocmVmLCBldmVudCk7XG5cblx0XHRpZiAoaXNOYXZpZ2F0aW9uU2NoZWR1bGVkKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBuYXZpZ2F0ZUZhaWxlZCA9IGZhbHNlO1xuXHRcdHRyeSB7XG5cdFx0XHR0aGlzLm5hdmlnYXRlKHV0aWxzLmdldFVybFBhdGgoaHJlZiksIGZhbHNlLCBldmVudCk7XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHQvLyBEbyBub3QgcHJldmVudCBsaW5rIG5hdmlnYXRpb24gaW4gY2FzZSBzb21lIHN5bmNocm9ub3VzIGVycm9yIG9jY3Vyc1xuXHRcdFx0bmF2aWdhdGVGYWlsZWQgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICghbmF2aWdhdGVGYWlsZWQgJiYgIWV2ZW50LmlzU2NoZWR1bGVkTmF2aWdhdGlvbikge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIHdoZXRoZXIgdGhlIG9uYmVmb3JldW5sb2FkIGdsb2JhbCBldmVudCBoYW5kbGVyIGlzIG92ZXJsb2FkZWRcblx0ICogYnkgY2xpZW50IGNvZGUuIElmIHNvLCBpdCByZXBsYWNlcyB3aXRoIGEgZnVuY3Rpb24gdGhhdCBoYWx0cyB0aGUgbm9ybWFsXG5cdCAqIGV2ZW50IGZsb3cgaW4gcmVsYXRpb24gd2l0aCB0aGUgY2xpZW50IG9uYmVmb3JldW5sb2FkIGZ1bmN0aW9uLlxuXHQgKiBUaGlzIGNhbiBiZSBpbiBtb3N0IHBhcnQgdXNlZCB0byBwcmVtYXR1cmVseSB0ZXJtaW5hdGUgbmF2aWdhdGlvbiB0byBvdGhlciBwYWdlc1xuXHQgKiBhY2NvcmRpbmcgdG8gdGhlIGdpdmVuIGNvbnN0cmFpdChzKS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0bWF5YmVPdmVybG9hZEJlZm9yZVVubG9hZF8oKSB7XG5cdFx0aWYgKCdmdW5jdGlvbicgPT09IHR5cGVvZiB3aW5kb3cub25iZWZvcmV1bmxvYWQpIHtcblx0XHRcdHdpbmRvdy5fb25iZWZvcmV1bmxvYWQgPSB3aW5kb3cub25iZWZvcmV1bmxvYWQ7XG5cblx0XHRcdHdpbmRvdy5vbmJlZm9yZXVubG9hZCA9IGV2ZW50ID0+IHtcblx0XHRcdFx0dGhpcy5lbWl0KCdiZWZvcmVVbmxvYWQnLCBldmVudCk7XG5cdFx0XHRcdGlmIChldmVudCAmJiBldmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cblx0XHRcdC8vIG1hcmsgdGhlIHVwZGF0ZWQgaGFuZGxlciBkdWUgdW53YW50ZWQgcmVjdXJzaW9uXG5cdFx0XHR3aW5kb3cub25iZWZvcmV1bmxvYWQuX292ZXJsb2FkZWQgPSB0cnVlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDYW5jZWxzIG5hdmlnYXRpb24gaWYgbmV4dFNjcmVlbidzIGJlZm9yZUFjdGl2YXRlIGxpZmVjeWNsZSBtZXRob2Rcblx0ICogcmVzb2x2ZXMgdG8gdHJ1ZS5cblx0ICogQHBhcmFtIHshU2NyZWVufSBuZXh0U2NyZWVuXG5cdCAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2V9XG5cdCAqL1xuXHRtYXliZVByZXZlbnRBY3RpdmF0ZV8obmV4dFNjcmVlbikge1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdHJldHVybiBuZXh0U2NyZWVuLmJlZm9yZUFjdGl2YXRlKCk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4ocHJldmVudCA9PiB7XG5cdFx0XHRcdGlmIChwcmV2ZW50KSB7XG5cdFx0XHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUgPSBDYW5jZWxsYWJsZVByb21pc2UucmVqZWN0KG5ldyBDYW5jZWxsYWJsZVByb21pc2UuQ2FuY2VsbGF0aW9uRXJyb3IoJ0NhbmNlbGxlZCBieSBuZXh0IHNjcmVlbicpKTtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5wZW5kaW5nTmF2aWdhdGU7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbmNlbHMgbmF2aWdhdGlvbiBpZiBhY3RpdmVTY3JlZW4ncyBiZWZvcmVEZWFjdGl2YXRlIGxpZmVjeWNsZVxuXHQgKiBtZXRob2QgcmVzb2x2ZXMgdG8gdHJ1ZS5cblx0ICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZX1cblx0ICovXG5cdG1heWJlUHJldmVudERlYWN0aXZhdGVfKCkge1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpXG5cdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbikge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLmFjdGl2ZVNjcmVlbi5iZWZvcmVEZWFjdGl2YXRlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pXG5cdFx0XHQudGhlbihwcmV2ZW50ID0+IHtcblx0XHRcdFx0aWYgKHByZXZlbnQpIHtcblx0XHRcdFx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZSA9IENhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcignQ2FuY2VsbGVkIGJ5IGFjdGl2ZSBzY3JlZW4nKSk7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXMucGVuZGluZ05hdmlnYXRlO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSByZXBvc2l0aW9uIHNjcm9sbCB0byBoYXNoZWQgYW5jaG9yLlxuXHQgKi9cblx0bWF5YmVSZXBvc2l0aW9uU2Nyb2xsVG9IYXNoZWRBbmNob3IoKSB7XG5cdFx0Y29uc3QgaGFzaCA9IGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdFx0aWYgKGhhc2gpIHtcblx0XHRcdGxldCBhbmNob3JFbGVtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChoYXNoLnN1YnN0cmluZygxKSk7XG5cdFx0XHRpZiAoYW5jaG9yRWxlbWVudCkge1xuXHRcdFx0XHRjb25zdCB7b2Zmc2V0TGVmdCwgb2Zmc2V0VG9wfSA9IHV0aWxzLmdldE5vZGVPZmZzZXQoYW5jaG9yRWxlbWVudCk7XG5cdFx0XHRcdGdsb2JhbHMud2luZG93LnNjcm9sbFRvKG9mZnNldExlZnQsIG9mZnNldFRvcCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIElmIHN1cHBvcnRlZCBieSB0aGUgYnJvd3NlciwgcmVzdG9yZXMgbmF0aXZlIHNjcm9sbCByZXN0b3JhdGlvbiB0byB0aGVcblx0ICogdmFsdWUgY2FwdHVyZWQgYnkgYG1heWJlRGlzYWJsZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uYC5cblx0ICovXG5cdG1heWJlUmVzdG9yZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uKCkge1xuXHRcdGlmICh0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uU3VwcG9ydGVkICYmIHRoaXMubmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25fKSB7XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uID0gdGhpcy5uYXRpdmVTY3JvbGxSZXN0b3JhdGlvbl87XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHJlc3RvcmUgcmVkaXJlY3RlZCBwYXRoIGhhc2ggaW4gY2FzZSBib3RoIHRoZSBjdXJyZW50IHBhdGggYW5kXG5cdCAqIHRoZSBnaXZlbiBwYXRoIGFyZSB0aGUgc2FtZS5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggYmVmb3JlIG5hdmlnYXRpb24uXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcmVkaXJlY3RQYXRoIFBhdGggYWZ0ZXIgbmF2aWdhdGlvbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBoYXNoIEhhc2ggdG8gYmUgYWRkZWQgdG8gdGhlIHBhdGguXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9IFJldHVybnMgdGhlIHBhdGggd2l0aCB0aGUgaGFzaCByZXN0b3JlZC5cblx0ICovXG5cdG1heWJlUmVzdG9yZVJlZGlyZWN0UGF0aEhhc2hfKHBhdGgsIHJlZGlyZWN0UGF0aCwgaGFzaCkge1xuXHRcdGlmIChyZWRpcmVjdFBhdGggPT09IHV0aWxzLmdldFVybFBhdGhXaXRob3V0SGFzaChwYXRoKSkge1xuXHRcdFx0cmV0dXJuIHJlZGlyZWN0UGF0aCArIGhhc2g7XG5cdFx0fVxuXHRcdHJldHVybiByZWRpcmVjdFBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogTWF5YmUgdXBkYXRlIHNjcm9sbCBwb3NpdGlvbiBpbiBoaXN0b3J5IHN0YXRlIHRvIGFuY2hvciBvbiBwYXRoLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIGFuY2hvclxuXHQgKi9cblx0bWF5YmVVcGRhdGVTY3JvbGxQb3NpdGlvblN0YXRlXygpIHtcblx0XHR2YXIgaGFzaCA9IGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdFx0dmFyIGFuY2hvckVsZW1lbnQgPSBnbG9iYWxzLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGhhc2guc3Vic3RyaW5nKDEpKTtcblx0XHRpZiAoYW5jaG9yRWxlbWVudCkge1xuXHRcdFx0Y29uc3Qge29mZnNldExlZnQsIG9mZnNldFRvcH0gPSB1dGlscy5nZXROb2RlT2Zmc2V0KGFuY2hvckVsZW1lbnQpO1xuXHRcdFx0dGhpcy5zYXZlSGlzdG9yeUN1cnJlbnRQYWdlU2Nyb2xsUG9zaXRpb25fKG9mZnNldFRvcCwgb2Zmc2V0TGVmdCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE5hdmlnYXRlcyB0byB0aGUgc3BlY2lmaWVkIHBhdGggaWYgdGhlcmUgaXMgYSByb3V0ZSBoYW5kbGVyIHRoYXQgbWF0Y2hlcy5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggdG8gbmF2aWdhdGUgY29udGFpbmluZyB0aGUgYmFzZSBwYXRoLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfcmVwbGFjZUhpc3RvcnkgUmVwbGFjZXMgYnJvd3NlciBoaXN0b3J5LlxuXHQgKiBAcGFyYW0ge0V2ZW50PX0gZXZlbnQgT3B0aW9uYWwgZXZlbnQgb2JqZWN0IHRoYXQgdHJpZ2dlcmVkIHRoZSBuYXZpZ2F0aW9uLlxuXHQgKiBAcmV0dXJuIHtDYW5jZWxsYWJsZVByb21pc2V9IFJldHVybnMgYSBwZW5kaW5nIHJlcXVlc3QgY2FuY2VsbGFibGUgcHJvbWlzZS5cblx0ICovXG5cdG5hdmlnYXRlKHBhdGgsIG9wdF9yZXBsYWNlSGlzdG9yeSwgb3B0X2V2ZW50KSB7XG5cdFx0aWYgKCF1dGlscy5pc0h0bWw1SGlzdG9yeVN1cHBvcnRlZCgpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0hUTUw1IEhpc3RvcnkgaXMgbm90IHN1cHBvcnRlZC4gU2VubmEgd2lsbCBub3QgaW50ZXJjZXB0IG5hdmlnYXRpb24uJyk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdF9ldmVudCkge1xuXHRcdFx0Z2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50ID0gb3B0X2V2ZW50LmNhcHR1cmVkRm9ybUVsZW1lbnQ7XG5cdFx0XHRnbG9iYWxzLmNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQgPSBvcHRfZXZlbnQuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudDtcblx0XHR9XG5cblx0XHQvLyBXaGVuIHJlbG9hZGluZyB0aGUgc2FtZSBwYXRoIGRvIHJlcGxhY2VTdGF0ZSBpbnN0ZWFkIG9mIHB1c2hTdGF0ZSB0b1xuXHRcdC8vIGF2b2lkIHBvbGx1dGluZyBoaXN0b3J5IHdpdGggc3RhdGVzIHdpdGggdGhlIHNhbWUgcGF0aC5cblx0XHRpZiAocGF0aCA9PT0gdGhpcy5hY3RpdmVQYXRoKSB7XG5cdFx0XHRvcHRfcmVwbGFjZUhpc3RvcnkgPSB0cnVlO1xuXHRcdH1cblxuXHRcdHRoaXMuZW1pdCgnYmVmb3JlTmF2aWdhdGUnLCB7XG5cdFx0XHRldmVudDogb3B0X2V2ZW50LFxuXHRcdFx0cGF0aDogcGF0aCxcblx0XHRcdHJlcGxhY2VIaXN0b3J5OiAhIW9wdF9yZXBsYWNlSGlzdG9yeVxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIHRoaXMucGVuZGluZ05hdmlnYXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEJlZm9yZXMgbmF2aWdhdGlvbiB0byBhIHBhdGguXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBFdmVudCBmYWNhZGUgY29udGFpbmluZyA8Y29kZT5wYXRoPC9jb2RlPiBhbmRcblx0ICogICAgIDxjb2RlPnJlcGxhY2VIaXN0b3J5PC9jb2RlPi5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25CZWZvcmVOYXZpZ2F0ZV8oZXZlbnQpIHtcblx0XHRpZiAoZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50KSB7XG5cdFx0XHRldmVudC5mb3JtID0gZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50O1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBCZWZvcmVzIG5hdmlnYXRpb24gdG8gYSBwYXRoLiBSdW5zIGFmdGVyIGV4dGVybmFsIGxpc3RlbmVycy5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZSBjb250YWluaW5nIDxjb2RlPnBhdGg8L2NvZGU+IGFuZFxuXHQgKiAgICAgPGNvZGU+cmVwbGFjZUhpc3Rvcnk8L2NvZGU+LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvbkJlZm9yZU5hdmlnYXRlRGVmYXVsdF8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5wZW5kaW5nTmF2aWdhdGUpIHtcblx0XHRcdGlmICh0aGlzLnBlbmRpbmdOYXZpZ2F0ZS5wYXRoID09PSBldmVudC5wYXRoIHx8IHRoaXMubmF2aWdhdGlvblN0cmF0ZWd5ID09PSBOYXZpZ2F0aW9uU3RyYXRlZ3kuU0NIRURVTEVfTEFTVCkge1xuXHRcdFx0XHRjb25zb2xlLmxvZygnV2FpdGluZy4uLicpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5lbWl0KCdiZWZvcmVVbmxvYWQnLCBldmVudCk7XG5cblx0XHR0aGlzLmVtaXQoJ3N0YXJ0TmF2aWdhdGUnLCB7XG5cdFx0XHRmb3JtOiBldmVudC5mb3JtLFxuXHRcdFx0cGF0aDogZXZlbnQucGF0aCxcblx0XHRcdHJlcGxhY2VIaXN0b3J5OiBldmVudC5yZXBsYWNlSGlzdG9yeVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEN1c3RvbSBldmVudCBoYW5kbGVyIHRoYXQgZXhlY3V0ZXMgdGhlIG9yaWdpbmFsIGxpc3RlbmVyIHRoYXQgaGFzIGJlZW5cblx0ICogYWRkZWQgYnkgdGhlIGNsaWVudCBjb2RlIGFuZCB0ZXJtaW5hdGVzIHRoZSBuYXZpZ2F0aW9uIGFjY29yZGluZ2x5LlxuXHQgKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgb3JpZ2luYWwgRXZlbnQgZmFjYWRlLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvbkJlZm9yZVVubG9hZERlZmF1bHRfKGV2ZW50KSB7XG5cdFx0dmFyIGZ1bmMgPSB3aW5kb3cuX29uYmVmb3JldW5sb2FkO1xuXHRcdGlmIChmdW5jICYmICFmdW5jLl9vdmVybG9hZGVkICYmIGZ1bmMoKSkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogSW50ZXJjZXB0cyBkb2N1bWVudCBjbGlja3MgYW5kIHRlc3QgbGluayBlbGVtZW50cyBpbiBvcmRlciB0byBkZWNpZGVcblx0ICogd2hldGhlciBTdXJmYWNlIGFwcCBjYW4gbmF2aWdhdGUuXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBFdmVudCBmYWNhZGVcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25Eb2NDbGlja0RlbGVnYXRlXyhldmVudCkge1xuXHRcdGlmIChldmVudC5hbHRLZXkgfHwgZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5IHx8IGV2ZW50LnNoaWZ0S2V5IHx8IGV2ZW50LmJ1dHRvbikge1xuXHRcdFx0Y29uc29sZS5sb2coJ05hdmlnYXRlIGFib3J0ZWQsIGludmFsaWQgbW91c2UgYnV0dG9uIG9yIG1vZGlmaWVyIGtleSBwcmVzc2VkLicpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLm1heWJlTmF2aWdhdGVfKGV2ZW50LmRlbGVnYXRlVGFyZ2V0LmhyZWYsIGV2ZW50KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbnRlcmNlcHRzIGRvY3VtZW50IGZvcm0gc3VibWl0cyBhbmQgdGVzdCBhY3Rpb24gcGF0aCBpbiBvcmRlciB0byBkZWNpZGVcblx0ICogd2hldGhlciBTdXJmYWNlIGFwcCBjYW4gbmF2aWdhdGUuXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBFdmVudCBmYWNhZGVcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25Eb2NTdWJtaXREZWxlZ2F0ZV8oZXZlbnQpIHtcblx0XHR2YXIgZm9ybSA9IGV2ZW50LmRlbGVnYXRlVGFyZ2V0O1xuXHRcdGlmIChmb3JtLm1ldGhvZCA9PT0gJ2dldCcpIHtcblx0XHRcdGNvbnNvbGUubG9nKCdHRVQgbWV0aG9kIG5vdCBzdXBwb3J0ZWQnKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0ZXZlbnQuY2FwdHVyZWRGb3JtRWxlbWVudCA9IGZvcm07XG5cdFx0Y29uc3QgYnV0dG9uU2VsZWN0b3IgPSAnYnV0dG9uOm5vdChbdHlwZV0pLGJ1dHRvblt0eXBlPXN1Ym1pdF0saW5wdXRbdHlwZT1zdWJtaXRdJztcblx0XHRpZiAobWF0Y2goZ2xvYmFscy5kb2N1bWVudC5hY3RpdmVFbGVtZW50LCBidXR0b25TZWxlY3RvcikpIHtcblx0XHRcdGV2ZW50LmNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQgPSBnbG9iYWxzLmRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGV2ZW50LmNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQgPSBmb3JtLnF1ZXJ5U2VsZWN0b3IoYnV0dG9uU2VsZWN0b3IpO1xuXHRcdH1cblx0XHR0aGlzLm1heWJlTmF2aWdhdGVfKGZvcm0uYWN0aW9uLCBldmVudCk7XG5cdH1cblxuXHQvKipcblx0ICogTGlzdGVucyB0byB0aGUgd2luZG93J3MgbG9hZCBldmVudCBpbiBvcmRlciB0byBhdm9pZCBpc3N1ZXMgd2l0aCBzb21lIGJyb3dzZXJzXG5cdCAqIHRoYXQgdHJpZ2dlciBwb3BzdGF0ZSBjYWxscyBvbiB0aGUgZmlyc3QgbG9hZC4gRm9yIG1vcmUgaW5mb3JtYXRpb24gc2VlXG5cdCAqIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjQyMTc2OS9wb3BzdGF0ZS1vbi1wYWdlcy1sb2FkLWluLWNocm9tZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25Mb2FkXygpIHtcblx0XHR0aGlzLnNraXBMb2FkUG9wc3RhdGUgPSB0cnVlO1xuXHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0Ly8gVGhlIHRpbWVvdXQgZW5zdXJlcyB0aGF0IHBvcHN0YXRlIGV2ZW50cyB3aWxsIGJlIHVuYmxvY2tlZCByaWdodFxuXHRcdFx0Ly8gYWZ0ZXIgdGhlIGxvYWQgZXZlbnQgb2NjdXJlZCwgYnV0IG5vdCBpbiB0aGUgc2FtZSBldmVudC1sb29wIGN5Y2xlLlxuXHRcdFx0dGhpcy5za2lwTG9hZFBvcHN0YXRlID0gZmFsc2U7XG5cdFx0fSwgMCk7XG5cdFx0Ly8gVHJ5IHRvIHJlcG9zaXRpb24gc2Nyb2xsIHRvIHRoZSBoYXNoZWQgYW5jaG9yIHdoZW4gcGFnZSBsb2Fkcy5cblx0XHR0aGlzLm1heWJlUmVwb3NpdGlvblNjcm9sbFRvSGFzaGVkQW5jaG9yKCk7XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlcyBicm93c2VyIGhpc3RvcnkgY2hhbmdlcyBhbmQgZmlyZXMgYXBwJ3MgbmF2aWdhdGlvbiBpZiB0aGUgc3RhdGVcblx0ICogYmVsb3dzIHRvIHVzLiBJZiB3ZSBkZXRlY3QgYSBwb3BzdGF0ZSBhbmQgdGhlIHN0YXRlIGlzIDxjb2RlPm51bGw8L2NvZGU+LFxuXHQgKiBhc3N1bWUgaXQgaXMgbmF2aWdhdGluZyB0byBhbiBleHRlcm5hbCBwYWdlIG9yIHRvIGEgcGFnZSB3ZSBkb24ndCBoYXZlXG5cdCAqIHJvdXRlLCB0aGVuIDxjb2RlPmdsb2JhbHMud2luZG93LmxvY2F0aW9uLnJlbG9hZCgpPC9jb2RlPiBpcyBpbnZva2VkIGluIG9yZGVyIHRvXG5cdCAqIHJlbG9hZCB0aGUgY29udGVudCB0byB0aGUgY3VycmVudCB1cmwuXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBFdmVudCBmYWNhZGVcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25Qb3BzdGF0ZV8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5za2lwTG9hZFBvcHN0YXRlKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gRG8gbm90IG5hdmlnYXRlIGlmIHRoZSBwb3BzdGF0ZSB3YXMgdHJpZ2dlcmVkIGJ5IGEgaGFzaCBjaGFuZ2UuXG5cdFx0aWYgKHV0aWxzLmlzQ3VycmVudEJyb3dzZXJQYXRoKHRoaXMuYnJvd3NlclBhdGhCZWZvcmVOYXZpZ2F0ZSkpIHtcblx0XHRcdHRoaXMubWF5YmVSZXBvc2l0aW9uU2Nyb2xsVG9IYXNoZWRBbmNob3IoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgc3RhdGUgPSBldmVudC5zdGF0ZTtcblxuXHRcdGlmICghc3RhdGUpIHtcblx0XHRcdGlmIChnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5oYXNoKSB7XG5cdFx0XHRcdC8vIElmIHNlbm5hIGlzIG9uIGFuIHJlZGlyZWN0IHBhdGggYW5kIGEgaGFzaCBwb3BzdGF0ZSBoYXBwZW5zXG5cdFx0XHRcdC8vIHRvIGEgZGlmZmVyZW50IHVybCwgcmVsb2FkIHRoZSBicm93c2VyLiBUaGlzIGJlaGF2aW9yIGRvZXNuJ3Rcblx0XHRcdFx0Ly8gcmVxdWlyZSBzZW5uYSB0byByb3V0ZSBoYXNoZWQgbGlua3MgYW5kIGlzIGNsb3NlciB0byBuYXRpdmVcblx0XHRcdFx0Ly8gYnJvd3NlciBiZWhhdmlvci5cblx0XHRcdFx0aWYgKHRoaXMucmVkaXJlY3RQYXRoICYmICF1dGlscy5pc0N1cnJlbnRCcm93c2VyUGF0aCh0aGlzLnJlZGlyZWN0UGF0aCkpIHtcblx0XHRcdFx0XHR0aGlzLnJlbG9hZFBhZ2UoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHQvLyBBbHdheXMgdHJ5IHRvIHJlcG9zaXRpb24gc2Nyb2xsIHRvIHRoZSBoYXNoZWQgYW5jaG9yIHdoZW5cblx0XHRcdFx0Ly8gaGFzaCBwb3BzdGF0ZSBoYXBwZW5zLlxuXHRcdFx0XHR0aGlzLm1heWJlUmVwb3NpdGlvblNjcm9sbFRvSGFzaGVkQW5jaG9yKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnJlbG9hZFBhZ2UoKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoc3RhdGUuc2VubmEpIHtcblx0XHRcdGNvbnNvbGUubG9nKCdIaXN0b3J5IG5hdmlnYXRpb24gdG8gWycgKyBzdGF0ZS5wYXRoICsgJ10nKTtcblx0XHRcdHRoaXMucG9wc3RhdGVTY3JvbGxUb3AgPSBzdGF0ZS5zY3JvbGxUb3A7XG5cdFx0XHR0aGlzLnBvcHN0YXRlU2Nyb2xsTGVmdCA9IHN0YXRlLnNjcm9sbExlZnQ7XG5cdFx0XHRpZiAoIXRoaXMubmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25TdXBwb3J0ZWQpIHtcblx0XHRcdFx0dGhpcy5sb2NrSGlzdG9yeVNjcm9sbFBvc2l0aW9uXygpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5vbmNlKCdlbmROYXZpZ2F0ZScsICgpID0+IHtcblx0XHRcdFx0aWYgKHN0YXRlLnJlZmVycmVyKSB7XG5cdFx0XHRcdFx0dXRpbHMuc2V0UmVmZXJyZXIoc3RhdGUucmVmZXJyZXIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdGNvbnN0IHVyaSA9IG5ldyBVcmkoc3RhdGUucGF0aCk7XG5cdFx0XHR1cmkuc2V0SG9zdG5hbWUoZ2xvYmFscy53aW5kb3cubG9jYXRpb24uaG9zdG5hbWUpO1xuXHRcdFx0dXJpLnNldFBvcnQoZ2xvYmFscy53aW5kb3cubG9jYXRpb24ucG9ydCk7XG5cdFx0XHRjb25zdCBpc05hdmlnYXRpb25TY2hlZHVsZWQgPSB0aGlzLm1heWJlU2NoZWR1bGVOYXZpZ2F0aW9uXyh1cmkudG9TdHJpbmcoKSwge30pO1xuXHRcdFx0aWYgKGlzTmF2aWdhdGlvblNjaGVkdWxlZCkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHR0aGlzLm5hdmlnYXRlKHN0YXRlLnBhdGgsIHRydWUpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBMaXN0ZW5zIGRvY3VtZW50IHNjcm9sbCBjaGFuZ2VzIGluIG9yZGVyIHRvIGNhcHR1cmUgdGhlIHBvc3NpYmxlIGxvY2tcblx0ICogc2Nyb2xsIHBvc2l0aW9uIGZvciBoaXN0b3J5IHNjcm9sbGluZy5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25TY3JvbGxfKCkge1xuXHRcdGlmICh0aGlzLmNhcHR1cmVTY3JvbGxQb3NpdGlvbkZyb21TY3JvbGxFdmVudCkge1xuXHRcdFx0dGhpcy5zYXZlSGlzdG9yeUN1cnJlbnRQYWdlU2Nyb2xsUG9zaXRpb25fKGdsb2JhbHMud2luZG93LnBhZ2VZT2Zmc2V0LCBnbG9iYWxzLndpbmRvdy5wYWdlWE9mZnNldCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0cyBuYXZpZ2F0aW9uIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZSBjb250YWluaW5nIDxjb2RlPnBhdGg8L2NvZGU+IGFuZFxuXHQgKiAgICAgPGNvZGU+cmVwbGFjZUhpc3Rvcnk8L2NvZGU+LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvblN0YXJ0TmF2aWdhdGVfKGV2ZW50KSB7XG5cdFx0dGhpcy5tYXliZURpc2FibGVOYXRpdmVTY3JvbGxSZXN0b3JhdGlvbigpO1xuXHRcdHRoaXMuY2FwdHVyZVNjcm9sbFBvc2l0aW9uRnJvbVNjcm9sbEV2ZW50ID0gZmFsc2U7XG5cdFx0YWRkQ2xhc3NlcyhnbG9iYWxzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgdGhpcy5sb2FkaW5nQ3NzQ2xhc3MpO1xuXG5cdFx0dmFyIGVuZE5hdmlnYXRlUGF5bG9hZCA9IHtcblx0XHRcdGZvcm06IGV2ZW50LmZvcm0sXG5cdFx0XHRwYXRoOiBldmVudC5wYXRoXG5cdFx0fTtcblxuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gdGhpcy5kb05hdmlnYXRlXyhldmVudC5wYXRoLCBldmVudC5yZXBsYWNlSGlzdG9yeSlcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdGVuZE5hdmlnYXRlUGF5bG9hZC5lcnJvciA9IHJlYXNvbjtcblx0XHRcdFx0dGhyb3cgcmVhc29uO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuQWx3YXlzKCgpID0+IHtcblx0XHRcdFx0aWYgKCF0aGlzLnBlbmRpbmdOYXZpZ2F0ZSAmJiAhdGhpcy5zY2hlZHVsZWROYXZpZ2F0aW9uUXVldWUubGVuZ3RoKSB7XG5cdFx0XHRcdFx0cmVtb3ZlQ2xhc3NlcyhnbG9iYWxzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgdGhpcy5sb2FkaW5nQ3NzQ2xhc3MpO1xuXHRcdFx0XHRcdHRoaXMubWF5YmVSZXN0b3JlTmF0aXZlU2Nyb2xsUmVzdG9yYXRpb24oKTtcblx0XHRcdFx0XHR0aGlzLmNhcHR1cmVTY3JvbGxQb3NpdGlvbkZyb21TY3JvbGxFdmVudCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5lbWl0KCdlbmROYXZpZ2F0ZScsIGVuZE5hdmlnYXRlUGF5bG9hZCk7XG5cdFx0XHR9KTtcblxuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlLnBhdGggPSBldmVudC5wYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByZWZldGNoZXMgdGhlIHNwZWNpZmllZCBwYXRoIGlmIHRoZXJlIGlzIGEgcm91dGUgaGFuZGxlciB0aGF0IG1hdGNoZXMuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIHRvIG5hdmlnYXRlIGNvbnRhaW5pbmcgdGhlIGJhc2UgcGF0aC5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBSZXR1cm5zIGEgcGVuZGluZyByZXF1ZXN0IGNhbmNlbGxhYmxlIHByb21pc2UuXG5cdCAqL1xuXHRwcmVmZXRjaChwYXRoKSB7XG5cdFx0dmFyIHJvdXRlID0gdGhpcy5maW5kUm91dGUocGF0aCk7XG5cdFx0aWYgKCFyb3V0ZSkge1xuXHRcdFx0cmV0dXJuIENhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcignTm8gcm91dGUgZm9yICcgKyBwYXRoKSk7XG5cdFx0fVxuXG5cdFx0Y29uc29sZS5sb2coJ1ByZWZldGNoaW5nIFsnICsgcGF0aCArICddJyk7XG5cblx0XHR2YXIgbmV4dFNjcmVlbiA9IHRoaXMuY3JlYXRlU2NyZWVuSW5zdGFuY2UocGF0aCwgcm91dGUpO1xuXG5cdFx0cmV0dXJuIG5leHRTY3JlZW4ubG9hZChwYXRoKVxuXHRcdFx0LnRoZW4oKCkgPT4gdGhpcy5zY3JlZW5zW3BhdGhdID0gbmV4dFNjcmVlbilcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdHRoaXMuaGFuZGxlTmF2aWdhdGVFcnJvcl8ocGF0aCwgbmV4dFNjcmVlbiwgcmVhc29uKTtcblx0XHRcdFx0dGhyb3cgcmVhc29uO1xuXHRcdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUHJlcGFyZXMgc2NyZWVuIGZsaXAuIFVwZGF0ZXMgaGlzdG9yeSBzdGF0ZSBhbmQgc3VyZmFjZXMgY29udGVudC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHBhcmFtIHshU2NyZWVufSBuZXh0U2NyZWVuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9yZXBsYWNlSGlzdG9yeSBSZXBsYWNlcyBicm93c2VyIGhpc3RvcnkuXG5cdCAqL1xuXHRwcmVwYXJlTmF2aWdhdGVIaXN0b3J5XyhwYXRoLCBuZXh0U2NyZWVuLCBvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHRsZXQgdGl0bGUgPSBuZXh0U2NyZWVuLmdldFRpdGxlKCk7XG5cdFx0aWYgKCFpc1N0cmluZyh0aXRsZSkpIHtcblx0XHRcdHRpdGxlID0gdGhpcy5nZXREZWZhdWx0VGl0bGUoKTtcblx0XHR9XG5cdFx0bGV0IHJlZGlyZWN0UGF0aCA9IG5leHRTY3JlZW4uYmVmb3JlVXBkYXRlSGlzdG9yeVBhdGgocGF0aCk7XG5cdFx0Y29uc3QgaGFzaCA9IG5ldyBVcmkocGF0aCkuZ2V0SGFzaCgpO1xuXHRcdHJlZGlyZWN0UGF0aCA9IHRoaXMubWF5YmVSZXN0b3JlUmVkaXJlY3RQYXRoSGFzaF8ocGF0aCwgcmVkaXJlY3RQYXRoLCBoYXNoKTtcblx0XHRjb25zdCBoaXN0b3J5U3RhdGUgPSB7XG5cdFx0XHRmb3JtOiBpc0RlZkFuZE5vdE51bGwoZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50KSxcblx0XHRcdHBhdGgsXG5cdFx0XHRyZWRpcmVjdFBhdGgsXG5cdFx0XHRzY3JvbGxMZWZ0OiAwLFxuXHRcdFx0c2Nyb2xsVG9wOiAwLFxuXHRcdFx0c2VubmE6IHRydWVcblx0XHR9O1xuXHRcdGlmIChvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHRcdGhpc3RvcnlTdGF0ZS5zY3JvbGxUb3AgPSB0aGlzLnBvcHN0YXRlU2Nyb2xsVG9wO1xuXHRcdFx0aGlzdG9yeVN0YXRlLnNjcm9sbExlZnQgPSB0aGlzLnBvcHN0YXRlU2Nyb2xsTGVmdDtcblx0XHR9XG5cdFx0dGhpcy51cGRhdGVIaXN0b3J5Xyh0aXRsZSwgcmVkaXJlY3RQYXRoLCBuZXh0U2NyZWVuLmJlZm9yZVVwZGF0ZUhpc3RvcnlTdGF0ZShoaXN0b3J5U3RhdGUpLCBvcHRfcmVwbGFjZUhpc3RvcnkpO1xuXHRcdHRoaXMucmVkaXJlY3RQYXRoID0gcmVkaXJlY3RQYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByZXBhcmVzIHNjcmVlbiBmbGlwLiBVcGRhdGVzIGhpc3Rvcnkgc3RhdGUgYW5kIHN1cmZhY2VzIGNvbnRlbnQuXG5cdCAqIEBwYXJhbSB7IVNjcmVlbn0gbmV4dFNjcmVlblxuXHQgKiBAcGFyYW0geyFPYmplY3R9IHN1cmZhY2VzIE1hcCBvZiBzdXJmYWNlcyB0byBmbGlwIGtleWVkIGJ5IHN1cmZhY2UgaWQuXG5cdCAqIEBwYXJhbSB7IU9iamVjdH0gcGFyYW1zIFBhcmFtcyBleHRyYWN0ZWQgZnJvbSB0aGUgY3VycmVudCBwYXRoLlxuXHQgKi9cblx0cHJlcGFyZU5hdmlnYXRlU3VyZmFjZXNfKG5leHRTY3JlZW4sIHN1cmZhY2VzLCBwYXJhbXMpIHtcblx0XHRPYmplY3Qua2V5cyhzdXJmYWNlcykuZm9yRWFjaCgoaWQpID0+IHtcblx0XHRcdHZhciBzdXJmYWNlQ29udGVudCA9IG5leHRTY3JlZW4uZ2V0U3VyZmFjZUNvbnRlbnQoaWQsIHBhcmFtcyk7XG5cdFx0XHRzdXJmYWNlc1tpZF0uYWRkQ29udGVudChuZXh0U2NyZWVuLmdldElkKCksIHN1cmZhY2VDb250ZW50KTtcblx0XHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyBuZXh0U2NyZWVuLmdldElkKCkgKyAnXSBhZGQgY29udGVudCB0byBzdXJmYWNlICcgK1xuXHRcdFx0XHQnWycgKyBzdXJmYWNlc1tpZF0gKyAnXSBbJyArIChpc0RlZkFuZE5vdE51bGwoc3VyZmFjZUNvbnRlbnQpID8gJy4uLicgOiAnZW1wdHknKSArICddJyk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVsb2FkcyB0aGUgcGFnZSBieSBwZXJmb3JtaW5nIGB3aW5kb3cubG9jYXRpb24ucmVsb2FkKClgLlxuXHQgKi9cblx0cmVsb2FkUGFnZSgpIHtcblx0XHRnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHJvdXRlIGluc3RhbmNlIGZyb20gYXBwIHJvdXRlcy5cblx0ICogQHBhcmFtIHtSb3V0ZX0gcm91dGVcblx0ICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhbiBlbGVtZW50IHdhcyByZW1vdmVkLlxuXHQgKi9cblx0cmVtb3ZlUm91dGUocm91dGUpIHtcblx0XHRyZXR1cm4gYXJyYXkucmVtb3ZlKHRoaXMucm91dGVzLCByb3V0ZSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhIHNjcmVlbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICovXG5cdHJlbW92ZVNjcmVlbihwYXRoKSB7XG5cdFx0dmFyIHNjcmVlbiA9IHRoaXMuc2NyZWVuc1twYXRoXTtcblx0XHRpZiAoc2NyZWVuKSB7XG5cdFx0XHRPYmplY3Qua2V5cyh0aGlzLnN1cmZhY2VzKS5mb3JFYWNoKChzdXJmYWNlSWQpID0+IHRoaXMuc3VyZmFjZXNbc3VyZmFjZUlkXS5yZW1vdmUoc2NyZWVuLmdldElkKCkpKTtcblx0XHRcdHNjcmVlbi5kaXNwb3NlKCk7XG5cdFx0XHRkZWxldGUgdGhpcy5zY3JlZW5zW3BhdGhdO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTYXZlcyBnaXZlbiBzY3JvbGwgcG9zaXRpb24gaW50byBoaXN0b3J5IHN0YXRlLlxuXHQgKiBAcGFyYW0geyFudW1iZXJ9IHNjcm9sbFRvcCBOdW1iZXIgY29udGFpbmluZyB0aGUgdG9wIHNjcm9sbCBwb3NpdGlvbiB0byBiZSBzYXZlZC5cblx0ICogQHBhcmFtIHshbnVtYmVyfSBzY3JvbGxMZWZ0IE51bWJlciBjb250YWluaW5nIHRoZSBsZWZ0IHNjcm9sbCBwb3NpdGlvbiB0byBiZSBzYXZlZC5cblx0ICovXG5cdHNhdmVIaXN0b3J5Q3VycmVudFBhZ2VTY3JvbGxQb3NpdGlvbl8oc2Nyb2xsVG9wLCBzY3JvbGxMZWZ0KSB7XG5cdFx0dmFyIHN0YXRlID0gZ2xvYmFscy53aW5kb3cuaGlzdG9yeS5zdGF0ZTtcblx0XHRpZiAoc3RhdGUgJiYgc3RhdGUuc2VubmEpIHtcblx0XHRcdFtzdGF0ZS5zY3JvbGxUb3AsIHN0YXRlLnNjcm9sbExlZnRdID0gW3Njcm9sbFRvcCwgc2Nyb2xsTGVmdF07XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShzdGF0ZSwgbnVsbCwgbnVsbCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgYWxsb3cgcHJldmVudCBuYXZpZ2F0ZS5cblx0ICogQHBhcmFtIHtib29sZWFufSBhbGxvd1ByZXZlbnROYXZpZ2F0ZVxuXHQgKi9cblx0c2V0QWxsb3dQcmV2ZW50TmF2aWdhdGUoYWxsb3dQcmV2ZW50TmF2aWdhdGUpIHtcblx0XHR0aGlzLmFsbG93UHJldmVudE5hdmlnYXRlID0gYWxsb3dQcmV2ZW50TmF2aWdhdGU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyBsaW5rIGJhc2UgcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoXG5cdCAqL1xuXHRzZXRCYXNlUGF0aChiYXNlUGF0aCkge1xuXHRcdHRoaXMuYmFzZVBhdGggPSB1dGlscy5yZW1vdmVQYXRoVHJhaWxpbmdTbGFzaChiYXNlUGF0aCk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgZGVmYXVsdCBwYWdlIHRpdGxlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZGVmYXVsdFRpdGxlXG5cdCAqL1xuXHRzZXREZWZhdWx0VGl0bGUoZGVmYXVsdFRpdGxlKSB7XG5cdFx0dGhpcy5kZWZhdWx0VGl0bGUgPSBkZWZhdWx0VGl0bGU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgZm9ybSBzZWxlY3Rvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBmb3JtU2VsZWN0b3Jcblx0ICovXG5cdHNldEZvcm1TZWxlY3Rvcihmb3JtU2VsZWN0b3IpIHtcblx0XHR0aGlzLmZvcm1TZWxlY3RvciA9IGZvcm1TZWxlY3Rvcjtcblx0XHRpZiAodGhpcy5mb3JtRXZlbnRIYW5kbGVyXykge1xuXHRcdFx0dGhpcy5mb3JtRXZlbnRIYW5kbGVyXy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdH1cblx0XHR0aGlzLmZvcm1FdmVudEhhbmRsZXJfID0gZGVsZWdhdGUoZG9jdW1lbnQsICdzdWJtaXQnLCB0aGlzLmZvcm1TZWxlY3RvciwgdGhpcy5vbkRvY1N1Ym1pdERlbGVnYXRlXy5iaW5kKHRoaXMpLCB0aGlzLmFsbG93UHJldmVudE5hdmlnYXRlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIGlmIHJvdXRlIG1hdGNoaW5nIHNob3VsZCBpZ25vcmUgcXVlcnkgc3RyaW5nIGZyb20gdGhlIHJvdXRlIHBhdGguXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoXG5cdCAqL1xuXHRzZXRJZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGgoaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKSB7XG5cdFx0dGhpcy5pZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGggPSBpZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgbGluayBzZWxlY3Rvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBsaW5rU2VsZWN0b3Jcblx0ICovXG5cdHNldExpbmtTZWxlY3RvcihsaW5rU2VsZWN0b3IpIHtcblx0XHR0aGlzLmxpbmtTZWxlY3RvciA9IGxpbmtTZWxlY3Rvcjtcblx0XHRpZiAodGhpcy5saW5rRXZlbnRIYW5kbGVyXykge1xuXHRcdFx0dGhpcy5saW5rRXZlbnRIYW5kbGVyXy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdH1cblx0XHR0aGlzLmxpbmtFdmVudEhhbmRsZXJfID0gZGVsZWdhdGUoZG9jdW1lbnQsICdjbGljaycsIHRoaXMubGlua1NlbGVjdG9yLCB0aGlzLm9uRG9jQ2xpY2tEZWxlZ2F0ZV8uYmluZCh0aGlzKSwgdGhpcy5hbGxvd1ByZXZlbnROYXZpZ2F0ZSk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgbG9hZGluZyBjc3MgY2xhc3MuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gbG9hZGluZ0Nzc0NsYXNzXG5cdCAqL1xuXHRzZXRMb2FkaW5nQ3NzQ2xhc3MobG9hZGluZ0Nzc0NsYXNzKSB7XG5cdFx0dGhpcy5sb2FkaW5nQ3NzQ2xhc3MgPSBsb2FkaW5nQ3NzQ2xhc3M7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgdXBkYXRlIHNjcm9sbCBwb3NpdGlvbiB2YWx1ZS5cblx0ICogQHBhcmFtIHtib29sZWFufSB1cGRhdGVTY3JvbGxQb3NpdGlvblxuXHQgKi9cblx0c2V0VXBkYXRlU2Nyb2xsUG9zaXRpb24odXBkYXRlU2Nyb2xsUG9zaXRpb24pIHtcblx0XHR0aGlzLnVwZGF0ZVNjcm9sbFBvc2l0aW9uID0gdXBkYXRlU2Nyb2xsUG9zaXRpb247XG5cdH1cblxuXHQvKipcblx0ICogQ2FuY2VscyBwZW5kaW5nIG5hdmlnYXRlIHdpdGggPGNvZGU+Q2FuY2VsIHBlbmRpbmcgbmF2aWdhdGlvbjwvY29kZT4gZXJyb3IuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHN0b3BQZW5kaW5nTmF2aWdhdGVfKCkge1xuXHRcdGlmICh0aGlzLnBlbmRpbmdOYXZpZ2F0ZSkge1xuXHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUuY2FuY2VsKCdDYW5jZWwgcGVuZGluZyBuYXZpZ2F0aW9uJyk7XG5cdFx0fVxuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTeW5jIGRvY3VtZW50IHNjcm9sbCBwb3NpdGlvbiB0d2ljZSwgdGhlIGZpcnN0IG9uZSBzeW5jaHJvbm91cyBhbmQgdGhlblxuXHQgKiBvbmUgaW5zaWRlIDxjb2RlPmFzeW5jLm5leHRUaWNrPC9jb2RlPi4gUmVsZXZhbnQgdG8gYnJvd3NlcnMgdGhhdCBmaXJlc1xuXHQgKiBzY3JvbGwgcmVzdG9yYXRpb24gYXN5bmNocm9ub3VzbHkgYWZ0ZXIgcG9wc3RhdGUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQHJldHVybiB7P0NhbmNlbGxhYmxlUHJvbWlzZT19XG5cdCAqL1xuXHRzeW5jU2Nyb2xsUG9zaXRpb25TeW5jVGhlbkFzeW5jXygpIHtcblx0XHR2YXIgc3RhdGUgPSBnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnN0YXRlO1xuXHRcdGlmICghc3RhdGUpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgc2Nyb2xsVG9wID0gc3RhdGUuc2Nyb2xsVG9wO1xuXHRcdHZhciBzY3JvbGxMZWZ0ID0gc3RhdGUuc2Nyb2xsTGVmdDtcblxuXHRcdHZhciBzeW5jID0gKCkgPT4ge1xuXHRcdFx0aWYgKHRoaXMudXBkYXRlU2Nyb2xsUG9zaXRpb24pIHtcblx0XHRcdFx0Z2xvYmFscy53aW5kb3cuc2Nyb2xsVG8oc2Nyb2xsTGVmdCwgc2Nyb2xsVG9wKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0cmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUpID0+IHN5bmMoKSAmIGFzeW5jLm5leHRUaWNrKCgpID0+IHN5bmMoKSAmIHJlc29sdmUoKSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZXMgb3IgcmVwbGFjZSBicm93c2VyIGhpc3RvcnkuXG5cdCAqIEBwYXJhbSB7P3N0cmluZ30gdGl0bGUgRG9jdW1lbnQgdGl0bGUuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIGNvbnRhaW5pbmcgdGhlIHF1ZXJ5c3RyaW5nIHBhcnQuXG5cdCAqIEBwYXJhbSB7IW9iamVjdH0gc3RhdGVcblx0ICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3JlcGxhY2VIaXN0b3J5IFJlcGxhY2VzIGJyb3dzZXIgaGlzdG9yeS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dXBkYXRlSGlzdG9yeV8odGl0bGUsIHBhdGgsIHN0YXRlLCBvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHRjb25zdCByZWZlcnJlciA9IGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhyZWY7XG5cblx0XHRpZiAoc3RhdGUpIHtcblx0XHRcdHN0YXRlLnJlZmVycmVyID0gcmVmZXJyZXI7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdF9yZXBsYWNlSGlzdG9yeSkge1xuXHRcdFx0Z2xvYmFscy53aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGUoc3RhdGUsIHRpdGxlLCBwYXRoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Z2xvYmFscy53aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUoc3RhdGUsIHRpdGxlLCBwYXRoKTtcblx0XHR9XG5cblx0XHR1dGlscy5zZXRSZWZlcnJlcihyZWZlcnJlcik7XG5cblx0XHRsZXQgdGl0bGVOb2RlID0gZ2xvYmFscy5kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCd0aXRsZScpO1xuXHRcdGlmICh0aXRsZU5vZGUpIHtcblx0XHRcdHRpdGxlTm9kZS5pbm5lckhUTUwgPSB0aXRsZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Z2xvYmFscy5kb2N1bWVudC50aXRsZSA9IHRpdGxlO1xuXHRcdH1cblx0fVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEFwcDtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaXNEZWYsIGlzRGVmQW5kTm90TnVsbCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBVcmkgZnJvbSAnbWV0YWwtdXJpJztcbmltcG9ydCB7IENhbmNlbGxhYmxlUHJvbWlzZSBhcyBQcm9taXNlIH0gZnJvbSAnbWV0YWwtcHJvbWlzZSc7XG5cbmNsYXNzIEFqYXgge1xuXG5cdC8qKlxuXHQgKiBYbWxIdHRwUmVxdWVzdCdzIGdldEFsbFJlc3BvbnNlSGVhZGVycygpIG1ldGhvZCByZXR1cm5zIGEgc3RyaW5nIG9mXG5cdCAqIHJlc3BvbnNlIGhlYWRlcnMgYWNjb3JkaW5nIHRvIHRoZSBmb3JtYXQgZGVzY3JpYmVkIG9uIHRoZSBzcGVjOlxuXHQgKiB7QGxpbmsgaHR0cDovL3d3dy53My5vcmcvVFIvWE1MSHR0cFJlcXVlc3QvI3RoZS1nZXRhbGxyZXNwb25zZWhlYWRlcnMtbWV0aG9kfS5cblx0ICogVGhpcyBtZXRob2QgcGFyc2VzIHRoYXQgc3RyaW5nIGludG8gYSB1c2VyLWZyaWVuZGx5IG5hbWUvdmFsdWUgcGFpclxuXHQgKiBvYmplY3QuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBhbGxIZWFkZXJzIEFsbCBoZWFkZXJzIGFzIHN0cmluZy5cblx0ICogQHJldHVybiB7IUFycmF5LjxPYmplY3Q8c3RyaW5nLCBzdHJpbmc+Pn1cblx0ICovXG5cdHN0YXRpYyBwYXJzZVJlc3BvbnNlSGVhZGVycyhhbGxIZWFkZXJzKSB7XG5cdFx0dmFyIGhlYWRlcnMgPSBbXTtcblx0XHRpZiAoIWFsbEhlYWRlcnMpIHtcblx0XHRcdHJldHVybiBoZWFkZXJzO1xuXHRcdH1cblx0XHR2YXIgcGFpcnMgPSBhbGxIZWFkZXJzLnNwbGl0KCdcXHUwMDBkXFx1MDAwYScpO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcGFpcnMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHZhciBpbmRleCA9IHBhaXJzW2ldLmluZGV4T2YoJ1xcdTAwM2FcXHUwMDIwJyk7XG5cdFx0XHRpZiAoaW5kZXggPiAwKSB7XG5cdFx0XHRcdHZhciBuYW1lID0gcGFpcnNbaV0uc3Vic3RyaW5nKDAsIGluZGV4KTtcblx0XHRcdFx0dmFyIHZhbHVlID0gcGFpcnNbaV0uc3Vic3RyaW5nKGluZGV4ICsgMik7XG5cdFx0XHRcdGhlYWRlcnMucHVzaCh7XG5cdFx0XHRcdFx0bmFtZTogbmFtZSxcblx0XHRcdFx0XHR2YWx1ZTogdmFsdWVcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBoZWFkZXJzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlcXVlc3RzIHRoZSB1cmwgdXNpbmcgWE1MSHR0cFJlcXVlc3QuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gdXJsXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gbWV0aG9kXG5cdCAqIEBwYXJhbSB7P3N0cmluZ30gYm9keVxuXHQgKiBAcGFyYW0ge011bHRpTWFwPX0gb3B0X2hlYWRlcnNcblx0ICogQHBhcmFtIHtNdWx0aU1hcD19IG9wdF9wYXJhbXNcblx0ICogQHBhcmFtIHtudW1iZXI9fSBvcHRfdGltZW91dFxuXHQgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfc3luY1xuXHQgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfd2l0aENyZWRlbnRpYWxzXG5cdCAqIEByZXR1cm4ge1Byb21pc2V9IERlZmVycmVkIGFqYXggcmVxdWVzdC5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0c3RhdGljIHJlcXVlc3QodXJsLCBtZXRob2QsIGJvZHksIG9wdF9oZWFkZXJzLCBvcHRfcGFyYW1zLCBvcHRfdGltZW91dCwgb3B0X3N5bmMsIG9wdF93aXRoQ3JlZGVudGlhbHMpIHtcblx0XHR1cmwgPSB1cmwgfHwgJyc7XG5cdFx0bWV0aG9kID0gbWV0aG9kIHx8ICdHRVQnO1xuXG5cdFx0dmFyIHJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcblx0XHR2YXIgcHJldmlvdXNSZWFkeVN0YXRlID0gMDtcblxuXHRcdHZhciBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cdFx0XHRyZXF1ZXN0Lm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAocmVxdWVzdC5hYm9ydGVkKSB7XG5cdFx0XHRcdFx0cmVxdWVzdC5vbmVycm9yKCk7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJlc29sdmUocmVxdWVzdCk7XG5cdFx0XHR9O1xuXHRcdFx0cmVxdWVzdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKHByZXZpb3VzUmVhZHlTdGF0ZSAmJiBwcmV2aW91c1JlYWR5U3RhdGUgPCAzICYmIDQgPT09IHJlcXVlc3QucmVhZHlTdGF0ZSkge1xuXHRcdFx0XHRcdHJlcXVlc3QudGVybWluYXRlZFByZW1hdHVyZWx5ID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRwcmV2aW91c1JlYWR5U3RhdGUgPSByZXF1ZXN0LnJlYWR5U3RhdGU7XG5cdFx0XHR9O1xuXHRcdFx0cmVxdWVzdC5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBtZXNzYWdlID0gJ1JlcXVlc3QgZXJyb3InO1xuXHRcdFx0XHRpZiAocmVxdWVzdC50ZXJtaW5hdGVkUHJlbWF0dXJlbHkpIHtcblx0XHRcdFx0XHRtZXNzYWdlID0gJ1JlcXVlc3QgdGVybWluYXRlZCBwcmVtYXR1cmVseSc7XG5cdFx0XHRcdH0gXG5cdFx0XHRcdHZhciBlcnJvciA9IG5ldyBFcnJvcihtZXNzYWdlKTtcblx0XHRcdFx0ZXJyb3IucmVxdWVzdCA9IHJlcXVlc3Q7XG5cdFx0XHRcdHJlamVjdChlcnJvcik7XG5cdFx0XHR9O1xuXHRcdH0pLnRoZW5DYXRjaChmdW5jdGlvbihyZWFzb24pIHtcblx0XHRcdHJlcXVlc3QuYWJvcnQoKTtcblx0XHRcdHRocm93IHJlYXNvbjtcblx0XHR9KS50aGVuQWx3YXlzKGZ1bmN0aW9uKCkge1xuXHRcdFx0Y2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXHRcdH0pO1xuXG5cdFx0dXJsID0gbmV3IFVyaSh1cmwpO1xuXG5cdFx0aWYgKG9wdF9wYXJhbXMpIHtcblx0XHRcdHVybC5hZGRQYXJhbWV0ZXJzRnJvbU11bHRpTWFwKG9wdF9wYXJhbXMpLnRvU3RyaW5nKCk7XG5cdFx0fVxuXG5cdFx0dXJsID0gdXJsLnRvU3RyaW5nKCk7XG5cblx0XHRyZXF1ZXN0Lm9wZW4obWV0aG9kLCB1cmwsICFvcHRfc3luYyk7XG5cblx0XHRpZiAob3B0X3dpdGhDcmVkZW50aWFscykge1xuXHRcdFx0cmVxdWVzdC53aXRoQ3JlZGVudGlhbHMgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmIChvcHRfaGVhZGVycykge1xuXHRcdFx0b3B0X2hlYWRlcnMubmFtZXMoKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcblx0XHRcdFx0cmVxdWVzdC5zZXRSZXF1ZXN0SGVhZGVyKG5hbWUsIG9wdF9oZWFkZXJzLmdldEFsbChuYW1lKS5qb2luKCcsICcpKTtcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdHJlcXVlc3Quc2VuZChpc0RlZihib2R5KSA/IGJvZHkgOiBudWxsKTtcblxuXHRcdGlmIChpc0RlZkFuZE5vdE51bGwob3B0X3RpbWVvdXQpKSB7XG5cdFx0XHR2YXIgdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHByb21pc2UuY2FuY2VsKCdSZXF1ZXN0IHRpbWVvdXQnKTtcblx0XHRcdH0sIG9wdF90aW1lb3V0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gcHJvbWlzZTtcblx0fVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEFqYXg7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogSG9sZHMgdmFsdWUgZXJyb3IgbWVzc2FnZXMuXG4gKiBAY29uc3RcbiAqL1xuY2xhc3MgZXJyb3JzIHtcbn1cblxuLyoqXG4gKiBJbnZhbGlkIHN0YXR1cyBlcnJvciBtZXNzYWdlLlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBzdGF0aWNcbiAqL1xuZXJyb3JzLklOVkFMSURfU1RBVFVTID0gJ0ludmFsaWQgc3RhdHVzIGNvZGUnO1xuXG4vKipcbiAqIFJlcXVlc3QgZXJyb3IgbWVzc2FnZS5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cbmVycm9ycy5SRVFVRVNUX0VSUk9SID0gJ1JlcXVlc3QgZXJyb3InO1xuXG4vKipcbiAqIFJlcXVlc3QgdGltZW91dCBlcnJvciBtZXNzYWdlLlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBzdGF0aWNcbiAqL1xuZXJyb3JzLlJFUVVFU1RfVElNRU9VVCA9ICdSZXF1ZXN0IHRpbWVvdXQnO1xuXG4vKipcbiAqIFJlcXVlc3QgaXMgYmxvY2tlZCBieSBDT1JTIGlzc3VlIG1lc3NhZ2UuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQHN0YXRpY1xuICovXG5lcnJvcnMuUkVRVUVTVF9QUkVNQVRVUkVfVEVSTUlOQVRJT04gPSAnUmVxdWVzdCB0ZXJtaW5hdGVkIHByZW1hdHVyZWx5JztcblxuZXhwb3J0IGRlZmF1bHQgZXJyb3JzO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge2lzU2VydmVyU2lkZX0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIE1ldGFsLmpzIGJyb3dzZXIgdXNlciBhZ2VudCBkZXRlY3Rpb24uIEl0J3MgZXh0cmVtZWx5IHJlY29tbWVuZGVkIHRoZSB1c2FnZVxuICogb2YgZmVhdHVyZSBjaGVja2luZyBvdmVyIGJyb3dzZXIgdXNlciBhZ2VudCBzbmlmZmluZy4gVW5mb3J0dW5hdGVseSwgaW4gc29tZVxuICogc2l0dWF0aW9ucyBmZWF0dXJlIGNoZWNraW5nIGNhbiBiZSBzbG93IG9yIGV2ZW4gaW1wb3NzaWJsZSwgdGhlcmVmb3JlIHVzZVxuICogdGhpcyB1dGlsaXR5IHdpdGggY2F1dGlvbi5cbiAqIEBzZWUgPGEgaHJlZj1cImh0dHA6Ly93d3cudXNlcmFnZW50c3RyaW5nLmNvbS9cIj5Vc2VyIGFnZW50IHN0cmluZ3M8L2E+LlxuICovXG5jbGFzcyBVQSB7XG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBuYXRpdmUgdXNlckFnZW50IHN0cmluZyBmcm9tIG5hdmlnYXRvciBpZiBpdCBleGlzdHMuIElmXG5cdCAqIG5hdmlnYXRvciBvciBuYXZpZ2F0b3IudXNlckFnZW50IHN0cmluZyBpcyBtaXNzaW5nLCByZXR1cm5zIGFuIGVtcHR5XG5cdCAqIHN0cmluZy5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0TmF0aXZlVXNlckFnZW50KCkge1xuXHRcdGxldCBuYXZpZ2F0b3IgPSBVQS5nbG9iYWxzLndpbmRvdyAmJiBVQS5nbG9iYWxzLndpbmRvdy5uYXZpZ2F0b3I7XG5cdFx0aWYgKG5hdmlnYXRvcikge1xuXHRcdFx0bGV0IHVzZXJBZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XG5cdFx0XHRpZiAodXNlckFnZW50KSB7XG5cdFx0XHRcdHJldHVybiB1c2VyQWdlbnQ7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiAnJztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBuYXRpdmUgcGxhdGZvcm0gc3RyaW5nIGZyb20gbmF2aWdhdG9yIGlmIGl0IGV4aXN0cy4gSWZcblx0ICogbmF2aWdhdG9yIG9yIG5hdmlnYXRvci5wbGF0Zm9ybSBzdHJpbmcgaXMgbWlzc2luZywgcmV0dXJucyBhbiBlbXB0eVxuXHQgKiBzdHJpbmcuXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICogQHByaXZhdGVcblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldE5hdGl2ZVBsYXRmb3JtKCkge1xuXHRcdGxldCBuYXZpZ2F0b3IgPSBVQS5nbG9iYWxzLndpbmRvdyAmJiBVQS5nbG9iYWxzLndpbmRvdy5uYXZpZ2F0b3I7XG5cdFx0aWYgKG5hdmlnYXRvcikge1xuXHRcdFx0bGV0IHBsYXRmb3JtID0gbmF2aWdhdG9yLnBsYXRmb3JtO1xuXHRcdFx0aWYgKHBsYXRmb3JtKSB7XG5cdFx0XHRcdHJldHVybiBwbGF0Zm9ybTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuICcnO1xuXHR9XG5cblx0LyoqXG5cdCAqIFdoZXRoZXIgdGhlIHBsYXRmb3JtIGNvbnRhaW5zIHRoZSBnaXZlbiBzdHJpbmcsIGlnbm9yaW5nIGNhc2UuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByaXZhdGVcblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIG1hdGNoUGxhdGZvcm0oc3RyKSB7XG5cdFx0cmV0dXJuIFVBLnBsYXRmb3JtLmluZGV4T2Yoc3RyKSAhPT0gLTE7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgdXNlciBhZ2VudCBjb250YWlucyB0aGUgZ2l2ZW4gc3RyaW5nLCBpZ25vcmluZyBjYXNlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcml2YXRlXG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBtYXRjaFVzZXJBZ2VudChzdHIpIHtcblx0XHRyZXR1cm4gVUEudXNlckFnZW50LmluZGV4T2Yoc3RyKSAhPT0gLTE7XG5cdH1cblxuXHQvKipcblx0ICogVGVzdHMgdGhlIHVzZXIgYWdlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyQWdlbnQgVGhlIHVzZXIgYWdlbnQgc3RyaW5nLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGxhdGZvcm1cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIHRlc3RVc2VyQWdlbnQodXNlckFnZW50ID0gJycsIHBsYXRmb3JtID0gJycpIHtcblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgdXNlciBhZ2VudCB2YWx1ZSBleHRyYWN0ZWQgZnJvbSBicm93c2VyIG5hdGl2ZSB1c2VyIGFnZW50LlxuXHRcdCAqIEB0eXBlIHtzdHJpbmd9XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLnVzZXJBZ2VudCA9IHVzZXJBZ2VudDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBwbGF0Zm9ybSB2YWx1ZSBleHRyYWN0ZWQgZnJvbSBicm93c2VyIG5hdGl2ZSBwbGF0Zm9ybS5cblx0XHQgKiBAdHlwZSB7c3RyaW5nfVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIE9TIGlzIE1hYy5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNNYWMgPSBVQS5tYXRjaFBsYXRmb3JtKCdNYWMnKTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBPUyBpcyBXaW4uXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzV2luID0gVUEubWF0Y2hQbGF0Zm9ybSgnV2luJyk7XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgYnJvd3NlciBpcyBPcGVyYS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNPcGVyYSA9IFVBLm1hdGNoVXNlckFnZW50KCdPcGVyYScpIHx8IFVBLm1hdGNoVXNlckFnZW50KCdPUFInKTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBicm93c2VyIGlzIElFLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc0llID0gVUEubWF0Y2hVc2VyQWdlbnQoJ1RyaWRlbnQnKSB8fCBVQS5tYXRjaFVzZXJBZ2VudCgnTVNJRScpO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgRWRnZS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNFZGdlID0gVUEubWF0Y2hVc2VyQWdlbnQoJ0VkZ2UnKTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBicm93c2VyIGlzIElFIG9yIEVkZ2UuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzSWVPckVkZ2UgPSBVQS5pc0llIHx8IFVBLmlzRWRnZTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBicm93c2VyIGlzIENocm9tZS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNDaHJvbWUgPVxuXHRcdFx0KFVBLm1hdGNoVXNlckFnZW50KCdDaHJvbWUnKSB8fCBVQS5tYXRjaFVzZXJBZ2VudCgnQ3JpT1MnKSkgJiZcblx0XHRcdCFVQS5pc09wZXJhICYmXG5cdFx0XHQhVUEuaXNFZGdlO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgU2FmYXJpLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc1NhZmFyaSA9XG5cdFx0XHRVQS5tYXRjaFVzZXJBZ2VudCgnU2FmYXJpJykgJiZcblx0XHRcdCEoVUEuaXNDaHJvbWUgfHwgVUEuaXNPcGVyYSB8fCBVQS5pc0VkZ2UpO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgRmlyZWZveC5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNGaXJlZm94ID0gVUEubWF0Y2hVc2VyQWdlbnQoJ0ZpcmVmb3gnKTtcblx0fVxufVxuXG4vKipcbiAqIEV4cG9zZXMgZ2xvYmFsIHJlZmVyZW5jZXMuXG4gKiBAdHlwZSB7b2JqZWN0fVxuICogQHN0YXRpY1xuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoVUEsICdnbG9iYWxzJywge1xuXHR3cml0YWJsZTogdHJ1ZSxcblx0dmFsdWU6IHtcblx0XHR3aW5kb3c6IGlzU2VydmVyU2lkZSgpID8gbnVsbCA6IHdpbmRvdyxcblx0fSxcbn0pO1xuXG5VQS50ZXN0VXNlckFnZW50KFVBLmdldE5hdGl2ZVVzZXJBZ2VudCgpLCBVQS5nZXROYXRpdmVQbGF0Zm9ybSgpKTtcblxuZXhwb3J0IGRlZmF1bHQgVUE7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmQW5kTm90TnVsbCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBBamF4IGZyb20gJ21ldGFsLWFqYXgnO1xuaW1wb3J0IHsgTXVsdGlNYXAgfSBmcm9tICdtZXRhbC1zdHJ1Y3RzJztcbmltcG9ydCBDYW5jZWxsYWJsZVByb21pc2UgZnJvbSAnbWV0YWwtcHJvbWlzZSc7XG5pbXBvcnQgZXJyb3JzIGZyb20gJy4uL2Vycm9ycy9lcnJvcnMnO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4uL3V0aWxzL3V0aWxzJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgU2NyZWVuIGZyb20gJy4vU2NyZWVuJztcbmltcG9ydCBVcmkgZnJvbSAnbWV0YWwtdXJpJztcbmltcG9ydCBVQSBmcm9tICdtZXRhbC11c2VyYWdlbnQnO1xuXG5jbGFzcyBSZXF1ZXN0U2NyZWVuIGV4dGVuZHMgU2NyZWVuIHtcblxuXHQvKipcblx0ICogUmVxdWVzdCBzY3JlZW4gYWJzdHJhY3QgY2xhc3MgdG8gcGVyZm9ybSBpbyBvcGVyYXRpb25zIG9uIGRlc2NlbmRhbnRcblx0ICogc2NyZWVucy5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqIEBleHRlbmRzIHtTY3JlZW59XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogQGluaGVyaXREb2Ncblx0XHQgKiBAZGVmYXVsdCB0cnVlXG5cdFx0ICovXG5cdFx0dGhpcy5jYWNoZWFibGUgPSB0cnVlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgZGVmYXVsdCBodHRwIGhlYWRlcnMgdG8gc2V0IG9uIHJlcXVlc3QuXG5cdFx0ICogQHR5cGUgez9PYmplY3Q9fVxuXHRcdCAqIEBkZWZhdWx0IHtcblx0XHQgKiAgICdYLVBKQVgnOiAndHJ1ZScsXG5cdFx0ICogICAnWC1SZXF1ZXN0ZWQtV2l0aCc6ICdYTUxIdHRwUmVxdWVzdCdcblx0XHQgKiB9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuaHR0cEhlYWRlcnMgPSB7XG5cdFx0XHQnWC1QSkFYJzogJ3RydWUnLFxuXHRcdFx0J1gtUmVxdWVzdGVkLVdpdGgnOiAnWE1MSHR0cFJlcXVlc3QnXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGRlZmF1bHQgaHR0cCBtZXRob2QgdG8gcGVyZm9ybSB0aGUgcmVxdWVzdC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBSZXF1ZXN0U2NyZWVuLkdFVFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmh0dHBNZXRob2QgPSBSZXF1ZXN0U2NyZWVuLkdFVDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBYSFIgb2JqZWN0IHJlc3BvbnNpYmxlIGZvciB0aGUgcmVxdWVzdC5cblx0XHQgKiBAdHlwZSB7WE1MSHR0cFJlcXVlc3R9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnJlcXVlc3QgPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHJlcXVlc3QgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuXG5cdFx0ICogQHR5cGUgeyFudW1iZXJ9XG5cdFx0ICogQGRlZmF1bHQgMzAwMDBcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy50aW1lb3V0ID0gMzAwMDA7XG5cdH1cblxuXHQvKipcblx0ICogQXNzZXJ0cyB0aGF0IHJlc3BvbnNlIHN0YXR1cyBjb2RlIGlzIHZhbGlkLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gc3RhdHVzXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFzc2VydFZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlKHN0YXR1cykge1xuXHRcdGlmICghdGhpcy5pc1ZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlKHN0YXR1cykpIHtcblx0XHRcdHZhciBlcnJvciA9IG5ldyBFcnJvcihlcnJvcnMuSU5WQUxJRF9TVEFUVVMpO1xuXHRcdFx0ZXJyb3IuaW52YWxpZFN0YXR1cyA9IHRydWU7XG5cdFx0XHRlcnJvci5zdGF0dXNDb2RlID0gc3RhdHVzO1xuXHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRiZWZvcmVVcGRhdGVIaXN0b3J5UGF0aChwYXRoKSB7XG5cdFx0dmFyIHJlZGlyZWN0UGF0aCA9IHRoaXMuZ2V0UmVxdWVzdFBhdGgoKTtcblx0XHRpZiAocmVkaXJlY3RQYXRoICYmIHJlZGlyZWN0UGF0aCAhPT0gcGF0aCkge1xuXHRcdFx0cmV0dXJuIHJlZGlyZWN0UGF0aDtcblx0XHR9XG5cdFx0cmV0dXJuIHBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGJlZm9yZVVwZGF0ZUhpc3RvcnlTdGF0ZShzdGF0ZSkge1xuXHRcdC8vIElmIHN0YXRlIGlzIG91cnMgYW5kIG5hdmlnYXRlIHRvIHBvc3Qtd2l0aG91dC1yZWRpcmVjdC1nZXQgc2V0XG5cdFx0Ly8gaGlzdG9yeSBzdGF0ZSB0byBudWxsLCB0aGF0IHdheSBTZW5uYSB3aWxsIHJlbG9hZCB0aGUgcGFnZSBvblxuXHRcdC8vIHBvcHN0YXRlIHNpbmNlIGl0IGNhbm5vdCBwcmVkaWN0IHBvc3QgZGF0YS5cblx0XHRpZiAoc3RhdGUuc2VubmEgJiYgc3RhdGUuZm9ybSAmJiBzdGF0ZS5yZWRpcmVjdFBhdGggPT09IHN0YXRlLnBhdGgpIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblx0XHRyZXR1cm4gc3RhdGU7XG5cdH1cblxuXHQvKipcblx0ICogRm9ybWF0cyBsb2FkIHBhdGggYmVmb3JlIGludm9raW5nIGFqYXggY2FsbC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGhcblx0ICogQHJldHVybiB7c3RyaW5nfSBGb3JtYXR0ZWQgcGF0aDtcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0Zm9ybWF0TG9hZFBhdGgocGF0aCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHBhdGgpO1xuXG5cdFx0dXJpLnNldEhvc3RuYW1lKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhvc3RuYW1lKTtcblx0XHR1cmkuc2V0UHJvdG9jb2woZ2xvYmFscy53aW5kb3cubG9jYXRpb24ucHJvdG9jb2wpO1xuXG5cdFx0aWYgKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnBvcnQpIHtcblx0XHRcdHVyaS5zZXRQb3J0KGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnBvcnQpO1xuXHRcdH1cblxuXHRcdGlmIChVQS5pc0llT3JFZGdlICYmIHRoaXMuaHR0cE1ldGhvZCA9PT0gUmVxdWVzdFNjcmVlbi5HRVQpIHtcblx0XHRcdHJldHVybiB1cmkubWFrZVVuaXF1ZSgpLnRvU3RyaW5nKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVyaS50b1N0cmluZygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGh0dHAgaGVhZGVycy5cblx0ICogQHJldHVybiB7P09iamVjdD19XG5cdCAqL1xuXHRnZXRIdHRwSGVhZGVycygpIHtcblx0XHRyZXR1cm4gdGhpcy5odHRwSGVhZGVycztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBodHRwIG1ldGhvZC5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICovXG5cdGdldEh0dHBNZXRob2QoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaHR0cE1ldGhvZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHJlcXVlc3QgcGF0aC5cblx0ICogQHJldHVybiB7c3RyaW5nPX1cblx0ICovXG5cdGdldFJlcXVlc3RQYXRoKCkge1xuXHRcdHZhciByZXF1ZXN0ID0gdGhpcy5nZXRSZXF1ZXN0KCk7XG5cdFx0aWYgKHJlcXVlc3QpIHtcblx0XHRcdHZhciByZXF1ZXN0UGF0aCA9IHJlcXVlc3QucmVxdWVzdFBhdGg7XG5cdFx0XHR2YXIgcmVzcG9uc2VVcmwgPSB0aGlzLm1heWJlRXh0cmFjdFJlc3BvbnNlVXJsRnJvbVJlcXVlc3QocmVxdWVzdCk7XG5cdFx0XHRpZiAocmVzcG9uc2VVcmwpIHtcblx0XHRcdFx0cmVxdWVzdFBhdGggPSByZXNwb25zZVVybDtcblx0XHRcdH1cblx0XHRcdGlmIChVQS5pc0llT3JFZGdlICYmIHRoaXMuaHR0cE1ldGhvZCA9PT0gUmVxdWVzdFNjcmVlbi5HRVQpIHtcblx0XHRcdFx0cmVxdWVzdFBhdGggPSBuZXcgVXJpKHJlcXVlc3RQYXRoKS5yZW1vdmVVbmlxdWUoKS50b1N0cmluZygpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHV0aWxzLmdldFVybFBhdGgocmVxdWVzdFBhdGgpO1xuXHRcdH1cblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByZXF1ZXN0IG9iamVjdC5cblx0ICogQHJldHVybiB7P09iamVjdH1cblx0ICovXG5cdGdldFJlcXVlc3QoKSB7XG5cdFx0cmV0dXJuIHRoaXMucmVxdWVzdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByZXF1ZXN0IHRpbWVvdXQuXG5cdCAqIEByZXR1cm4geyFudW1iZXJ9XG5cdCAqL1xuXHRnZXRUaW1lb3V0KCkge1xuXHRcdHJldHVybiB0aGlzLnRpbWVvdXQ7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHJlc3BvbnNlIHN1Y2NlZWRlZC4gQW55IHN0YXR1cyBjb2RlIDJ4eCBvciAzeHggaXMgY29uc2lkZXJlZFxuXHQgKiB2YWxpZC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHN0YXR1c0NvZGVcblx0ICovXG5cdGlzVmFsaWRSZXNwb25zZVN0YXR1c0NvZGUoc3RhdHVzQ29kZSkge1xuXHRcdHJldHVybiBzdGF0dXNDb2RlID49IDIwMCAmJiBzdGF0dXNDb2RlIDw9IDM5OTtcblx0fVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBmb3JtIGRhdGFcbiAgICogVGhpcyBtZXRob2QgY2FuIGJlIGV4dGVuZGVkIGluIG9yZGVyIHRvIGhhdmUgYSBjdXN0b20gaW1wbGVtZW50YXRpb24gb2YgdGhlIGZvcm0gcGFyYW1zXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGZvcm1FbGVtZW50XG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnRcbiAgICogQHJldHVybiB7IUZvcm1EYXRhfVxuICAgKi9cblx0Z2V0Rm9ybURhdGEoZm9ybUVsZW1lbnQsIHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnQpIHtcbiAgICBsZXQgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoZm9ybUVsZW1lbnQpO1xuICAgIHRoaXMubWF5YmVBcHBlbmRTdWJtaXRCdXR0b25WYWx1ZV8oZm9ybURhdGEsIHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnQpO1xuICAgIHJldHVybiBmb3JtRGF0YTtcbiAgfVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0bG9hZChwYXRoKSB7XG5cdFx0Y29uc3QgY2FjaGUgPSB0aGlzLmdldENhY2hlKCk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChjYWNoZSkpIHtcblx0XHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZShjYWNoZSk7XG5cdFx0fVxuXHRcdGxldCBib2R5ID0gbnVsbDtcblx0XHRsZXQgaHR0cE1ldGhvZCA9IHRoaXMuaHR0cE1ldGhvZDtcblx0XHRjb25zdCBoZWFkZXJzID0gbmV3IE11bHRpTWFwKCk7XG5cdFx0T2JqZWN0LmtleXModGhpcy5odHRwSGVhZGVycykuZm9yRWFjaChoZWFkZXIgPT4gaGVhZGVycy5hZGQoaGVhZGVyLCB0aGlzLmh0dHBIZWFkZXJzW2hlYWRlcl0pKTtcblx0XHRpZiAoZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50KSB7XG5cdFx0XHR0aGlzLmFkZFNhZmFyaVhIUlBvbHlmaWxsKCk7XG5cdFx0XHRib2R5ID0gdGhpcy5nZXRGb3JtRGF0YShnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQsIGdsb2JhbHMuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCk7XG5cdFx0XHRodHRwTWV0aG9kID0gUmVxdWVzdFNjcmVlbi5QT1NUO1xuXHRcdFx0aWYgKFVBLmlzSWVPckVkZ2UpIHtcblx0XHRcdFx0aGVhZGVycy5hZGQoJ0lmLU5vbmUtTWF0Y2gnLCAnXCIwXCInKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0Y29uc3QgcmVxdWVzdFBhdGggPSB0aGlzLmZvcm1hdExvYWRQYXRoKHBhdGgpO1xuXHRcdHJldHVybiBBamF4XG5cdFx0XHQucmVxdWVzdChyZXF1ZXN0UGF0aCwgaHR0cE1ldGhvZCwgYm9keSwgaGVhZGVycywgbnVsbCwgdGhpcy50aW1lb3V0KVxuXHRcdFx0LnRoZW4oeGhyID0+IHtcblx0XHRcdFx0dGhpcy5yZW1vdmVTYWZhcmlYSFJQb2x5ZmlsbCgpO1xuXHRcdFx0XHR0aGlzLnNldFJlcXVlc3QoeGhyKTtcblx0XHRcdFx0dGhpcy5hc3NlcnRWYWxpZFJlc3BvbnNlU3RhdHVzQ29kZSh4aHIuc3RhdHVzKTtcblx0XHRcdFx0aWYgKGh0dHBNZXRob2QgPT09IFJlcXVlc3RTY3JlZW4uR0VUICYmIHRoaXMuaXNDYWNoZWFibGUoKSkge1xuXHRcdFx0XHRcdHRoaXMuYWRkQ2FjaGUoeGhyLnJlc3BvbnNlVGV4dCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0eGhyLnJlcXVlc3RQYXRoID0gcmVxdWVzdFBhdGg7XG5cdFx0XHRcdHJldHVybiB4aHIucmVzcG9uc2VUZXh0O1xuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdHRoaXMucmVtb3ZlU2FmYXJpWEhSUG9seWZpbGwoKTtcblx0XHRcdFx0c3dpdGNoIChyZWFzb24ubWVzc2FnZSkge1xuXHRcdFx0XHRcdGNhc2UgZXJyb3JzLlJFUVVFU1RfVElNRU9VVDpcblx0XHRcdFx0XHRcdHJlYXNvbi50aW1lb3V0ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgZXJyb3JzLlJFUVVFU1RfRVJST1I6XG5cdFx0XHRcdFx0XHRyZWFzb24ucmVxdWVzdEVycm9yID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgZXJyb3JzLlJFUVVFU1RfUFJFTUFUVVJFX1RFUk1JTkFUSU9OOlxuXHRcdFx0XHRcdFx0cmVhc29uLnJlcXVlc3RFcnJvciA9IHRydWU7XG5cdFx0XHRcdFx0XHRyZWFzb24ucmVxdWVzdFByZW1hdHVyZVRlcm1pbmF0aW9uID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRocm93IHJlYXNvbjtcblx0XHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYWRpdGlvbmFsIGRhdGEgdG8gdGhlIGJvZHkgb2YgdGhlIHJlcXVlc3QgaW4gY2FzZSBhIHN1Ym1pdCBidXR0b25cblx0ICogaXMgY2FwdHVyZWQgZHVyaW5nIGZvcm0gc3VibWlzc2lvbi5cblx0ICogQHBhcmFtIHshRm9ybURhdGF9IGJvZHkgVGhlIEZvcm1EYXRhIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHshRWxlbWVudH0gc3VibWl0dGVkQnV0dG9uRWxlbWVudFxuICAgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRtYXliZUFwcGVuZFN1Ym1pdEJ1dHRvblZhbHVlXyhmb3JtRGF0YSwgc3VibWl0dGVkQnV0dG9uRWxlbWVudCkge1xuXHRcdGlmIChzdWJtaXR0ZWRCdXR0b25FbGVtZW50ICYmIHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnQubmFtZSkge1xuICAgICAgZm9ybURhdGEuYXBwZW5kKHN1Ym1pdHRlZEJ1dHRvbkVsZW1lbnQubmFtZSwgc3VibWl0dGVkQnV0dG9uRWxlbWVudC52YWx1ZSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBmb2xsb3dpbmcgbWV0aG9kIHRyaWVzIHRvIGV4dHJhY3QgdGhlIHJlc3BvbnNlIHVybCB2YWx1ZSBieSBjaGVja2luZ1xuXHQgKiB0aGUgY3VzdG9tIHJlc3BvbnNlIGhlYWRlciAnWC1SZXF1ZXN0LVVSTCcgaWYgcHJvcGVyIHZhbHVlIGlzIG5vdCBwcmVzZW50XG5cdCAqIGluIFhNTEh0dHBSZXF1ZXN0LiBUaGUgdmFsdWUgb2YgcmVzcG9uc2VVUkwgd2lsbCBiZSB0aGUgZmluYWwgVVJMXG5cdCAqIG9idGFpbmVkIGFmdGVyIGFueSByZWRpcmVjdHMuIEludGVybmV0IEV4cGxvcmVyLCBFZGdlIGFuZCBTYWZhcmkgPD0gN1xuXHQgKiBkb2VzIG5vdCB5ZXQgc3VwcG9ydCB0aGUgZmVhdHVyZS4gRm9yIG1vcmUgaW5mb3JtYXRpb24gc2VlOlxuXHQgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvWE1MSHR0cFJlcXVlc3QvcmVzcG9uc2VVUkxcblx0ICogaHR0cHM6Ly94aHIuc3BlYy53aGF0d2cub3JnLyN0aGUtcmVzcG9uc2V1cmwtYXR0cmlidXRlXG5cdCAqIEBwYXJhbSB7WE1MSHR0cFJlcXVlc3R9IHJlcXVlc3Rcblx0ICogQHJldHVybiB7P3N0cmluZ30gUmVzcG9uc2UgdXJsIGJlc3QgbWF0Y2guXG5cdCAqL1xuXHRtYXliZUV4dHJhY3RSZXNwb25zZVVybEZyb21SZXF1ZXN0KHJlcXVlc3QpIHtcblx0XHR2YXIgcmVzcG9uc2VVcmwgPSByZXF1ZXN0LnJlc3BvbnNlVVJMO1xuXHRcdGlmIChyZXNwb25zZVVybCkge1xuXHRcdFx0cmV0dXJuIHJlc3BvbnNlVXJsO1xuXHRcdH1cblx0XHRyZXR1cm4gcmVxdWVzdC5nZXRSZXNwb25zZUhlYWRlcihSZXF1ZXN0U2NyZWVuLlhfUkVRVUVTVF9VUkxfSEVBREVSKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGlzIGZ1bmN0aW9uIHNldCBhdHRyaWJ1dGUgZGF0YS1zYWZhcmktdGVtcC1kaXNhYmxlZCB0byBcblx0ICogdHJ1ZSBhbmQgc2V0IGRpc2FibGUgYXR0cmlidXRlIG9mIGFuIGlucHV0IHR5cGU9XCJmaWxlXCIgdGFnXG5cdCAqIGlzIHVzZWQgYXMgYSBwb2x5ZmlsbCBmb3IgaU9TIDExLjMgU2FmYXJpIC8gbWFjT1MgU2FmYXJpIDExLjEgXG5cdCAqIGVtcHR5IDxpbnB1dCB0eXBlPVwiZmlsZVwiPiBYSFIgYnVnLlxuXHQgKiBodHRwczovL2dpdGh1Yi5jb20vcmFpbHMvcmFpbHMvaXNzdWVzLzMyNDQwXG5cdCAqIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xODQ0OTBcblx0ICovXG5cdGFkZFNhZmFyaVhIUlBvbHlmaWxsKCkge1xuXHRcdGlmIChnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQgJiYgVUEuaXNTYWZhcmkpIHtcblx0XHRcdGxldCBpbnB1dHMgPSBnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnaW5wdXRbdHlwZT1cImZpbGVcIl06bm90KFtkaXNhYmxlZF0pJyk7XG5cdFx0XHRmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgaW5wdXRzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRsZXQgaW5wdXQgPSBpbnB1dHNbaW5kZXhdO1xuXHRcdFx0XHRpZiAoaW5wdXQuZmlsZXMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpbnB1dC5zZXRBdHRyaWJ1dGUoJ2RhdGEtc2FmYXJpLXRlbXAtZGlzYWJsZWQnLCAndHJ1ZScpO1xuXHRcdFx0XHRpbnB1dC5zZXRBdHRyaWJ1dGUoJ2Rpc2FibGVkJywgJycpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBUaGlzIGZ1bmN0aW9uIHJlbW92ZSBhdHRyaWJ1dGUgZGF0YS1zYWZhcmktdGVtcC1kaXNhYmxlZCBhbmQgZGlzYWJsZSBhdHRyaWJ1dGVcblx0ICogb2YgYW4gaW5wdXQgdHlwZT1cImZpbGVcIiB0YWcgaXMgdXNlZCBhcyBhIHBvbHlmaWxsIGZvciBpT1MgMTEuMyBTYWZhcmkgLyBtYWNPUyBTYWZhcmkgMTEuMVxuXHQgKiBlbXB0eSA8aW5wdXQgdHlwZT1cImZpbGVcIj4gWEhSIGJ1Zy5cblx0ICogaHR0cHM6Ly9naXRodWIuY29tL3JhaWxzL3JhaWxzL2lzc3Vlcy8zMjQ0MFxuXHQgKiBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTg0NDkwXG5cdCAqL1xuXHRyZW1vdmVTYWZhcmlYSFJQb2x5ZmlsbCgpIHtcblx0XHRpZiAoZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50ICYmIFVBLmlzU2FmYXJpKSB7XG5cdFx0XHRsZXQgaW5wdXRzID0gZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2lucHV0W3R5cGU9XCJmaWxlXCJdW2RhdGEtc2FmYXJpLXRlbXAtZGlzYWJsZWRdJyk7XG5cdFx0XHRmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgaW5wdXRzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRjb25zdCBpbnB1dCA9IGlucHV0c1tpbmRleF07XG5cdFx0XHRcdGlucHV0LnJlbW92ZUF0dHJpYnV0ZSgnZGF0YS1zYWZhcmktdGVtcC1kaXNhYmxlZCcpO1xuXHRcdFx0XHRpbnB1dC5yZW1vdmVBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGh0dHAgaGVhZGVycy5cblx0ICogQHBhcmFtIHs/T2JqZWN0PX0gaHR0cEhlYWRlcnNcblx0ICovXG5cdHNldEh0dHBIZWFkZXJzKGh0dHBIZWFkZXJzKSB7XG5cdFx0dGhpcy5odHRwSGVhZGVycyA9IGh0dHBIZWFkZXJzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGh0dHAgbWV0aG9kLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IGh0dHBNZXRob2Rcblx0ICovXG5cdHNldEh0dHBNZXRob2QoaHR0cE1ldGhvZCkge1xuXHRcdHRoaXMuaHR0cE1ldGhvZCA9IGh0dHBNZXRob2QudG9Mb3dlckNhc2UoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSByZXF1ZXN0IG9iamVjdC5cblx0ICogQHBhcmFtIHs/T2JqZWN0fSByZXF1ZXN0XG5cdCAqL1xuXHRzZXRSZXF1ZXN0KHJlcXVlc3QpIHtcblx0XHR0aGlzLnJlcXVlc3QgPSByZXF1ZXN0O1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHJlcXVlc3QgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuXG5cdCAqIEBwYXJhbSB7IW51bWJlcn0gdGltZW91dFxuXHQgKi9cblx0c2V0VGltZW91dCh0aW1lb3V0KSB7XG5cdFx0dGhpcy50aW1lb3V0ID0gdGltZW91dDtcblx0fVxuXG59XG5cbi8qKlxuICogSG9sZHMgdmFsdWUgZm9yIG1ldGhvZCBnZXQuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgJ2dldCdcbiAqIEBzdGF0aWNcbiAqL1xuUmVxdWVzdFNjcmVlbi5HRVQgPSAnZ2V0JztcblxuLyoqXG4gKiBIb2xkcyB2YWx1ZSBmb3IgbWV0aG9kIHBvc3QuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgJ3Bvc3QnXG4gKiBAc3RhdGljXG4gKi9cblJlcXVlc3RTY3JlZW4uUE9TVCA9ICdwb3N0JztcblxuLyoqXG4gKiBGYWxsYmFjayBodHRwIGhlYWRlciB0byByZXRyaWV2ZSByZXNwb25zZSByZXF1ZXN0IHVybC5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAZGVmYXVsdCAnWC1SZXF1ZXN0LVVSTCdcbiAqIEBzdGF0aWNcbiAqL1xuUmVxdWVzdFNjcmVlbi5YX1JFUVVFU1RfVVJMX0hFQURFUiA9ICdYLVJlcXVlc3QtVVJMJztcblxuZXhwb3J0IGRlZmF1bHQgUmVxdWVzdFNjcmVlbjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgYnVpbGRGcmFnbWVudCwgZ2xvYmFsRXZhbCwgZ2xvYmFsRXZhbFN0eWxlcywgbWF0Y2ggfSBmcm9tICdtZXRhbC1kb20nO1xuaW1wb3J0IENhbmNlbGxhYmxlUHJvbWlzZSBmcm9tICdtZXRhbC1wcm9taXNlJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgUmVxdWVzdFNjcmVlbiBmcm9tICcuL1JlcXVlc3RTY3JlZW4nO1xuaW1wb3J0IFN1cmZhY2UgZnJvbSAnLi4vc3VyZmFjZS9TdXJmYWNlJztcbmltcG9ydCBVQSBmcm9tICdtZXRhbC11c2VyYWdlbnQnO1xuaW1wb3J0IFVyaSBmcm9tICdtZXRhbC11cmknO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4uL3V0aWxzL3V0aWxzJztcblxuY2xhc3MgSHRtbFNjcmVlbiBleHRlbmRzIFJlcXVlc3RTY3JlZW4ge1xuXG5cdC8qKlxuXHQgKiBTY3JlZW4gY2xhc3MgdGhhdCBwZXJmb3JtIGEgcmVxdWVzdCBhbmQgZXh0cmFjdHMgc3VyZmFjZSBjb250ZW50cyBmcm9tXG5cdCAqIHRoZSByZXNwb25zZSBjb250ZW50LlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICogQGV4dGVuZHMge1JlcXVlc3RTY3JlZW59XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIG1ldGEgc2VsZWN0b3IuIFJlbGV2YW50IHRvIGV4dHJhY3QgPGNvZGU+bWV0YTwvY29kZT4gdGFnc1xuXHRcdCAqIGVsZW1lbnRzIGZyb20gcmVxdWVzdCBmcmFnbWVudHMgdG8gdXNlIGFzIHRoZSBzY3JlZW4uXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgbWV0YVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLm1ldGFUYWdzU2VsZWN0b3IgPSAnbWV0YSc7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgdGl0bGUgc2VsZWN0b3IuIFJlbGV2YW50IHRvIGV4dHJhY3QgdGhlIDxjb2RlPjx0aXRsZT48L2NvZGU+XG5cdFx0ICogZWxlbWVudCBmcm9tIHJlcXVlc3QgZnJhZ21lbnRzIHRvIHVzZSBhcyB0aGUgc2NyZWVuIHRpdGxlLlxuXHRcdCAqIEB0eXBlIHshc3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IHRpdGxlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudGl0bGVTZWxlY3RvciA9ICd0aXRsZSc7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGFjdGl2YXRlKCkge1xuXHRcdHN1cGVyLmFjdGl2YXRlKCk7XG5cdFx0dGhpcy5yZWxlYXNlVmlydHVhbERvY3VtZW50KCk7XG5cdFx0dGhpcy5wZW5kaW5nU3R5bGVzID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGxvY2F0ZXMgdmlydHVhbCBkb2N1bWVudCBmb3IgY29udGVudC4gQWZ0ZXIgYWxsb2NhdGVkIHZpcnR1YWwgZG9jdW1lbnRcblx0ICogY2FuIGJlIGFjY2Vzc2VkIGJ5IDxjb2RlPnRoaXMudmlydHVhbERvY3VtZW50PC9jb2RlPi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBodG1sU3RyaW5nXG5cdCAqL1xuXHRhbGxvY2F0ZVZpcnR1YWxEb2N1bWVudEZvckNvbnRlbnQoaHRtbFN0cmluZykge1xuXHRcdGlmICghdGhpcy52aXJ0dWFsRG9jdW1lbnQpIHtcblx0XHRcdHRoaXMudmlydHVhbERvY3VtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdodG1sJyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5jb3B5Tm9kZUF0dHJpYnV0ZXNGcm9tQ29udGVudF8oaHRtbFN0cmluZywgdGhpcy52aXJ0dWFsRG9jdW1lbnQpO1xuXG5cdFx0dGhpcy52aXJ0dWFsRG9jdW1lbnQuaW5uZXJIVE1MID0gaHRtbFN0cmluZztcblx0fVxuXG5cdC8qKlxuXHQgKiBDdXN0b21pemVzIGxvZ2ljIHRvIGFwcGVuZCBzdHlsZXMgaW50byBkb2N1bWVudC4gUmVsZXZhbnQgdG8gd2hlblxuXHQgKiB0cmFja2luZyBhIHN0eWxlIGJ5IGlkIG1ha2Ugc3VyZSB0byByZS1wb3NpdGlvbnMgdGhlIG5ldyBzdHlsZSBpbiB0aGVcblx0ICogc2FtZSBkb20gb3JkZXIuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbmV3U3R5bGVcblx0ICovXG5cdGFwcGVuZFN0eWxlSW50b0RvY3VtZW50XyhuZXdTdHlsZSkge1xuXHRcdHZhciBpc1RlbXBvcmFyeVN0eWxlID0gbWF0Y2gobmV3U3R5bGUsIEh0bWxTY3JlZW4uc2VsZWN0b3JzLnN0eWxlc1RlbXBvcmFyeSk7XG5cdFx0aWYgKGlzVGVtcG9yYXJ5U3R5bGUpIHtcblx0XHRcdHRoaXMucGVuZGluZ1N0eWxlcy5wdXNoKG5ld1N0eWxlKTtcblx0XHR9XG5cdFx0aWYgKG5ld1N0eWxlLmlkKSB7XG5cdFx0XHR2YXIgc3R5bGVJbkRvYyA9IGdsb2JhbHMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQobmV3U3R5bGUuaWQpO1xuXHRcdFx0aWYgKHN0eWxlSW5Eb2MpIHtcblx0XHRcdFx0c3R5bGVJbkRvYy5wYXJlbnROb2RlLmluc2VydEJlZm9yZShuZXdTdHlsZSwgc3R5bGVJbkRvYy5uZXh0U2libGluZyk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cdFx0Z2xvYmFscy5kb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKG5ld1N0eWxlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZiBib2R5IGlzIHVzZWQgYXMgc3VyZmFjZSBmb3JjZXMgdGhlIHJlcXVlc3RlZCBkb2N1bWVudHMgdG8gaGF2ZSBzYW1lIGlkXG5cdCAqIG9mIHRoZSBpbml0aWFsIHBhZ2UuXG5cdCAqL1xuXHRhc3NlcnRTYW1lQm9keUlkSW5WaXJ0dWFsRG9jdW1lbnQoKSB7XG5cdFx0dmFyIGJvZHlTdXJmYWNlID0gdGhpcy52aXJ0dWFsRG9jdW1lbnQucXVlcnlTZWxlY3RvcignYm9keScpO1xuXHRcdGlmICghZ2xvYmFscy5kb2N1bWVudC5ib2R5LmlkKSB7XG5cdFx0XHRnbG9iYWxzLmRvY3VtZW50LmJvZHkuaWQgPSAnc2VubmFfc3VyZmFjZV8nICsgZ2V0VWlkKCk7XG5cdFx0fVxuXHRcdGlmIChib2R5U3VyZmFjZSkge1xuXHRcdFx0Ym9keVN1cmZhY2UuaWQgPSBnbG9iYWxzLmRvY3VtZW50LmJvZHkuaWQ7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENvcGllcyBhdHRyaWJ1dGVzIGZyb20gdGhlIDxodG1sPiB0YWcgb2YgY29udGVudCB0byB0aGUgZ2l2ZW4gbm9kZS5cblx0ICovXG5cdGNvcHlOb2RlQXR0cmlidXRlc0Zyb21Db250ZW50Xyhjb250ZW50LCBub2RlKSB7XG5cdFx0Y29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvWzxdXFxzKmh0bWwvaWcsICc8c2VubmEnKTtcblx0XHRjb250ZW50ID0gY29udGVudC5yZXBsYWNlKC9cXC9odG1sXFxzKlxcPi9pZywgJy9zZW5uYT4nKTtcblx0XHRsZXQgcGxhY2Vob2xkZXI7XG5cdFx0aWYgKFVBLmlzSWUpIHtcblx0XHRcdGNvbnN0IHRlbXBOb2RlID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVSYW5nZSgpLmNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudChjb250ZW50KTtcblx0XHRcdHBsYWNlaG9sZGVyID0gdGVtcE5vZGUucXVlcnlTZWxlY3Rvcignc2VubmEnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bm9kZS5pbm5lckhUTUwgPSBjb250ZW50O1xuXHRcdFx0cGxhY2Vob2xkZXIgPSBub2RlLnF1ZXJ5U2VsZWN0b3IoJ3Nlbm5hJyk7XG5cdFx0fVxuXG5cdFx0aWYgKHBsYWNlaG9sZGVyKSB7XG5cdFx0XHR1dGlscy5jbGVhck5vZGVBdHRyaWJ1dGVzKG5vZGUpO1xuXHRcdFx0dXRpbHMuY29weU5vZGVBdHRyaWJ1dGVzKHBsYWNlaG9sZGVyLCBub2RlKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQE92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5kaXNwb3NlUGVuZGluZ1N0eWxlcygpO1xuXHRcdHN1cGVyLmRpc3Bvc2VJbnRlcm5hbCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIHBlbmRpbmcgc3R5bGVzIGlmIHNjcmVlbiBnZXQgZGlzcG9zZWQgcHJpb3IgdG8gaXRzIGxvYWRpbmcuXG5cdCAqL1xuXHRkaXNwb3NlUGVuZGluZ1N0eWxlcygpIHtcblx0XHRpZiAodGhpcy5wZW5kaW5nU3R5bGVzKSB7XG5cdFx0XHR1dGlscy5yZW1vdmVFbGVtZW50c0Zyb21Eb2N1bWVudCh0aGlzLnBlbmRpbmdTdHlsZXMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAT3ZlcnJpZGVcblx0ICovXG5cdGV2YWx1YXRlU2NyaXB0cyhzdXJmYWNlcykge1xuXHRcdHZhciBldmFsdWF0ZVRyYWNrZWRTY3JpcHRzID0gdGhpcy5ldmFsdWF0ZVRyYWNrZWRSZXNvdXJjZXNfKFxuXHRcdFx0Z2xvYmFsRXZhbC5ydW5TY3JpcHRzSW5FbGVtZW50LCBIdG1sU2NyZWVuLnNlbGVjdG9ycy5zY3JpcHRzLFxuXHRcdFx0SHRtbFNjcmVlbi5zZWxlY3RvcnMuc2NyaXB0c1RlbXBvcmFyeSwgSHRtbFNjcmVlbi5zZWxlY3RvcnMuc2NyaXB0c1Blcm1hbmVudCk7XG5cblx0XHRyZXR1cm4gZXZhbHVhdGVUcmFja2VkU2NyaXB0cy50aGVuKCgpID0+IHN1cGVyLmV2YWx1YXRlU2NyaXB0cyhzdXJmYWNlcykpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBPdmVycmlkZVxuXHQgKi9cblx0ZXZhbHVhdGVTdHlsZXMoc3VyZmFjZXMpIHtcblx0XHR0aGlzLnBlbmRpbmdTdHlsZXMgPSBbXTtcblx0XHR2YXIgZXZhbHVhdGVUcmFja2VkU3R5bGVzID0gdGhpcy5ldmFsdWF0ZVRyYWNrZWRSZXNvdXJjZXNfKFxuXHRcdFx0Z2xvYmFsRXZhbFN0eWxlcy5ydW5TdHlsZXNJbkVsZW1lbnQsIEh0bWxTY3JlZW4uc2VsZWN0b3JzLnN0eWxlcyxcblx0XHRcdEh0bWxTY3JlZW4uc2VsZWN0b3JzLnN0eWxlc1RlbXBvcmFyeSwgSHRtbFNjcmVlbi5zZWxlY3RvcnMuc3R5bGVzUGVybWFuZW50LFxuXHRcdFx0dGhpcy5hcHBlbmRTdHlsZUludG9Eb2N1bWVudF8uYmluZCh0aGlzKSk7XG5cblx0XHRyZXR1cm4gZXZhbHVhdGVUcmFja2VkU3R5bGVzLnRoZW4oKCkgPT4gc3VwZXIuZXZhbHVhdGVTdHlsZXMoc3VyZmFjZXMpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGxvd3MgYSBzY3JlZW4gdG8gZXZhbHVhdGUgdGhlIGZhdmljb24gc3R5bGUgYmVmb3JlIHRoZSBzY3JlZW4gYmVjb21lcyB2aXNpYmxlLlxuXHQgKiBAcmV0dXJuIHtDYW5jZWxsYWJsZVByb21pc2V9XG5cdCAqL1xuXHRldmFsdWF0ZUZhdmljb25fKCkge1xuXHRcdGNvbnN0IHJlc291cmNlc0luVmlydHVhbCA9IHRoaXMudmlydHVhbFF1ZXJ5U2VsZWN0b3JBbGxfKEh0bWxTY3JlZW4uc2VsZWN0b3JzLmZhdmljb24pO1xuXHRcdGNvbnN0IHJlc291cmNlc0luRG9jdW1lbnQgPSB0aGlzLnF1ZXJ5U2VsZWN0b3JBbGxfKEh0bWxTY3JlZW4uc2VsZWN0b3JzLmZhdmljb24pO1xuXG5cdFx0cmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUpID0+IHtcblx0XHRcdHV0aWxzLnJlbW92ZUVsZW1lbnRzRnJvbURvY3VtZW50KHJlc291cmNlc0luRG9jdW1lbnQpO1xuXHRcdFx0dGhpcy5ydW5GYXZpY29uSW5FbGVtZW50XyhyZXNvdXJjZXNJblZpcnR1YWwpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKTtcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgdHJhY2tlZCByZXNvdXJjZXMgaW5zaWRlIGluY29taW5nIGZyYWdtZW50IGFuZCByZW1vdmUgZXhpc3Rpbmdcblx0ICogdGVtcG9yYXJ5IHJlc291cmNlcy5cblx0ICogQHBhcmFtIHs/ZnVuY3Rpb24oKX0gYXBwZW5kRm4gRnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlIGludG8gZG9jdW1lbnQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3IgU2VsZWN0b3IgdXNlZCB0byBmaW5kIHJlc291cmNlcyB0byB0cmFjay5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzZWxlY3RvclRlbXBvcmFyeSBTZWxlY3RvciB1c2VkIHRvIGZpbmQgdGVtcG9yYXJ5XG5cdCAqICAgICByZXNvdXJjZXMgdG8gdHJhY2suXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3JQZXJtYW5lbnQgU2VsZWN0b3IgdXNlZCB0byBmaW5kIHBlcm1hbmVudFxuXHQgKiAgICAgcmVzb3VyY2VzIHRvIHRyYWNrLlxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbn0gb3B0X2FwcGVuZFJlc291cmNlRm4gT3B0aW9uYWwgZnVuY3Rpb24gdXNlZCB0b1xuXHQgKiAgICAgZXZhbHVhdGUgZnJhZ21lbnQgY29udGFpbmluZyByZXNvdXJjZXMuXG5cdCAqIEByZXR1cm4ge0NhbmNlbGxhYmxlUHJvbWlzZX0gRGVmZXJyZWQgdGhhdCB3YWl0cyByZXNvdXJjZXMgZXZhbHVhdGlvbiB0b1xuXHQgKiAgICAgY29tcGxldGUuXG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRldmFsdWF0ZVRyYWNrZWRSZXNvdXJjZXNfKGV2YWx1YXRvckZuLCBzZWxlY3Rvciwgc2VsZWN0b3JUZW1wb3JhcnksIHNlbGVjdG9yUGVybWFuZW50LCBvcHRfYXBwZW5kUmVzb3VyY2VGbikge1xuXHRcdHZhciB0cmFja2VkID0gdGhpcy52aXJ0dWFsUXVlcnlTZWxlY3RvckFsbF8oc2VsZWN0b3IpO1xuXHRcdHZhciB0ZW1wb3Jhcmllc0luRG9jID0gdGhpcy5xdWVyeVNlbGVjdG9yQWxsXyhzZWxlY3RvclRlbXBvcmFyeSk7XG5cdFx0dmFyIHBlcm1hbmVudHNJbkRvYyA9IHRoaXMucXVlcnlTZWxlY3RvckFsbF8oc2VsZWN0b3JQZXJtYW5lbnQpO1xuXG5cdFx0Ly8gQWRkcyBwZXJtYW5lbnQgcmVzb3VyY2VzIGluIGRvY3VtZW50IHRvIGNhY2hlLlxuXHRcdHBlcm1hbmVudHNJbkRvYy5mb3JFYWNoKChyZXNvdXJjZSkgPT4ge1xuXHRcdFx0dmFyIHJlc291cmNlS2V5ID0gdGhpcy5nZXRSZXNvdXJjZUtleV8ocmVzb3VyY2UpO1xuXHRcdFx0aWYgKHJlc291cmNlS2V5KSB7XG5cdFx0XHRcdEh0bWxTY3JlZW4ucGVybWFuZW50UmVzb3VyY2VzSW5Eb2NbcmVzb3VyY2VLZXldID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHZhciBmcmFnID0gYnVpbGRGcmFnbWVudCgpO1xuXHRcdHRyYWNrZWQuZm9yRWFjaCgocmVzb3VyY2UpID0+IHtcblx0XHRcdHZhciByZXNvdXJjZUtleSA9IHRoaXMuZ2V0UmVzb3VyY2VLZXlfKHJlc291cmNlKTtcblx0XHRcdC8vIERvIG5vdCBsb2FkIHBlcm1hbmVudCByZXNvdXJjZXMgaWYgYWxyZWFkeSBpbiBkb2N1bWVudC5cblx0XHRcdGlmICghSHRtbFNjcmVlbi5wZXJtYW5lbnRSZXNvdXJjZXNJbkRvY1tyZXNvdXJjZUtleV0pIHtcblx0XHRcdFx0ZnJhZy5hcHBlbmRDaGlsZChyZXNvdXJjZSk7XG5cdFx0XHR9XG5cdFx0XHQvLyBJZiByZXNvdXJjZSBoYXMga2V5IGFuZCBpcyBwZXJtYW5lbnQgYWRkIHRvIGNhY2hlLlxuXHRcdFx0aWYgKHJlc291cmNlS2V5ICYmIG1hdGNoKHJlc291cmNlLCBzZWxlY3RvclBlcm1hbmVudCkpIHtcblx0XHRcdFx0SHRtbFNjcmVlbi5wZXJtYW5lbnRSZXNvdXJjZXNJbkRvY1tyZXNvdXJjZUtleV0gPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUpID0+IHtcblx0XHRcdGV2YWx1YXRvckZuKGZyYWcsICgpID0+IHtcblx0XHRcdFx0dXRpbHMucmVtb3ZlRWxlbWVudHNGcm9tRG9jdW1lbnQodGVtcG9yYXJpZXNJbkRvYyk7XG5cdFx0XHRcdHJlc29sdmUoKTtcblx0XHRcdH0sIG9wdF9hcHBlbmRSZXNvdXJjZUZuKTtcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAT3ZlcnJpZGVcblx0ICovXG5cdGZsaXAoc3VyZmFjZXMpIHtcblx0XHRyZXR1cm4gc3VwZXIuZmxpcChzdXJmYWNlcykudGhlbigoKSA9PiB7XG5cdFx0XHR1dGlscy5jbGVhck5vZGVBdHRyaWJ1dGVzKGdsb2JhbHMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KTtcblx0XHRcdHV0aWxzLmNvcHlOb2RlQXR0cmlidXRlcyh0aGlzLnZpcnR1YWxEb2N1bWVudCwgZ2xvYmFscy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpO1xuXHRcdFx0dGhpcy5ldmFsdWF0ZUZhdmljb25fKCk7XG5cdFx0XHR0aGlzLnVwZGF0ZU1ldGFUYWdzXygpO1xuXHRcdH0pO1xuXHR9XG5cblx0dXBkYXRlTWV0YVRhZ3NfKCkge1xuXHRcdGNvbnN0IGN1cnJlbnRNZXRhTm9kZXMgPSB0aGlzLnF1ZXJ5U2VsZWN0b3JBbGxfKCdtZXRhJyk7XG5cdFx0Y29uc3QgbWV0YXNGcm9tVmlydHVhbERvY3VtZW50ID0gdGhpcy5tZXRhcztcblx0XHRpZiAoY3VycmVudE1ldGFOb2Rlcykge1xuXHRcdFx0dXRpbHMucmVtb3ZlRWxlbWVudHNGcm9tRG9jdW1lbnQoY3VycmVudE1ldGFOb2Rlcyk7XG5cdFx0XHRpZiAobWV0YXNGcm9tVmlydHVhbERvY3VtZW50KSB7XG5cdFx0XHRcdG1ldGFzRnJvbVZpcnR1YWxEb2N1bWVudC5mb3JFYWNoKChtZXRhKSA9PiBnbG9iYWxzLmRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQobWV0YSkpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBFeHRyYWN0cyBhIGtleSB0byBpZGVudGlmeSB0aGUgcmVzb3VyY2UgYmFzZWQgb24gaXRzIGF0dHJpYnV0ZXMuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gcmVzb3VyY2Vcblx0ICogQHJldHVybiB7c3RyaW5nfSBFeHRyYWN0ZWQga2V5IGJhc2VkIG9uIHJlc291cmNlIGF0dHJpYnV0ZXMgaW4gb3JkZXIgb2Zcblx0ICogICAgIHByZWZlcmVuY2U6IGlkLCBocmVmLCBzcmMuXG5cdCAqL1xuXHRnZXRSZXNvdXJjZUtleV8ocmVzb3VyY2UpIHtcblx0XHRyZXR1cm4gcmVzb3VyY2UuaWQgfHwgcmVzb3VyY2UuaHJlZiB8fCByZXNvdXJjZS5zcmMgfHwgJyc7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGdldFN1cmZhY2VDb250ZW50KHN1cmZhY2VJZCkge1xuXHRcdHZhciBzdXJmYWNlID0gdGhpcy52aXJ0dWFsRG9jdW1lbnQucXVlcnlTZWxlY3RvcignIycgKyBzdXJmYWNlSWQpO1xuXHRcdGlmIChzdXJmYWNlKSB7XG5cdFx0XHR2YXIgZGVmYXVsdENoaWxkID0gc3VyZmFjZS5xdWVyeVNlbGVjdG9yKCcjJyArIHN1cmZhY2VJZCArICctJyArIFN1cmZhY2UuREVGQVVMVCk7XG5cdFx0XHRpZiAoZGVmYXVsdENoaWxkKSB7XG5cdFx0XHRcdHJldHVybiBkZWZhdWx0Q2hpbGQuaW5uZXJIVE1MO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHN1cmZhY2UuaW5uZXJIVE1MOyAvLyBJZiBkZWZhdWx0IGNvbnRlbnQgbm90IGZvdW5kLCB1c2Ugc3VyZmFjZSBjb250ZW50XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHRpdGxlIHNlbGVjdG9yLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKi9cblx0Z2V0VGl0bGVTZWxlY3RvcigpIHtcblx0XHRyZXR1cm4gdGhpcy50aXRsZVNlbGVjdG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRsb2FkKHBhdGgpIHtcblx0XHRyZXR1cm4gc3VwZXIubG9hZChwYXRoKVxuXHRcdFx0LnRoZW4oY29udGVudCA9PiB7XG5cdFx0XHRcdHRoaXMuYWxsb2NhdGVWaXJ0dWFsRG9jdW1lbnRGb3JDb250ZW50KGNvbnRlbnQpO1xuXHRcdFx0XHR0aGlzLnJlc29sdmVUaXRsZUZyb21WaXJ0dWFsRG9jdW1lbnQoKTtcblx0XHRcdFx0dGhpcy5yZXNvbHZlTWV0YVRhZ3NGcm9tVmlydHVhbERvY3VtZW50KCk7XG5cdFx0XHRcdHRoaXMuYXNzZXJ0U2FtZUJvZHlJZEluVmlydHVhbERvY3VtZW50KCk7XG5cdFx0XHRcdGlmIChVQS5pc0llKSB7XG5cdFx0XHRcdFx0dGhpcy5tYWtlVGVtcG9yYXJ5U3R5bGVzSHJlZnNVbmlxdWVfKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIGNvbnRlbnQ7XG5cdFx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBRdWVyaWVzIHRlbXBvcmFyeSBzdHlsZXMgZnJvbSB2aXJ0dWFsIGRvY3VtZW50LCBhbmQgbWFrZXMgdGhlbSB1bmlxdWUuXG5cdCAqIFRoaXMgaXMgbmVjZXNzYXJ5IGZvciBjYWNoaW5nIGFuZCBsb2FkIGV2ZW50IGZpcmluZyBpc3N1ZXMgc3BlY2lmaWMgdG9cblx0ICogSUUxMS4gaHR0cHM6Ly9kZXZlbG9wZXIubWljcm9zb2Z0LmNvbS9lbi11cy9taWNyb3NvZnQtZWRnZS9wbGF0Zm9ybS9pc3N1ZXMvNzk0MDE3MS9cblx0ICovXG5cdG1ha2VUZW1wb3JhcnlTdHlsZXNIcmVmc1VuaXF1ZV8oKSB7XG5cdFx0dmFyIHRlbXBvcmFyaWVzSW5Eb2MgPSB0aGlzLnZpcnR1YWxRdWVyeVNlbGVjdG9yQWxsXyhIdG1sU2NyZWVuLnNlbGVjdG9ycy5zdHlsZXNUZW1wb3JhcnkpO1xuXHRcdHRlbXBvcmFyaWVzSW5Eb2MuZm9yRWFjaCgoc3R5bGUpID0+IHRoaXMucmVwbGFjZVN0eWxlQW5kTWFrZVVuaXF1ZV8oc3R5bGUpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgbmV3IGVsZW1lbnQgZnJvbSBnaXZlbiwgY29waWVzIGF0dHJpYnV0ZXMsIG11dGF0ZXMgaHJlZiB0byBiZVxuXHQgKiB1bmlxdWUgdG8gcHJldmVudCBjYWNoaW5nIGFuZCBtb3JlIHRoYW4gb25lIGxvYWQvZXJyb3IgZXZlbnQgZnJvbSBmaXJpbmcuXG5cdCAqL1xuXHRyZXBsYWNlU3R5bGVBbmRNYWtlVW5pcXVlXyhzdHlsZSkge1xuXHRcdGlmIChzdHlsZS5ocmVmKSB7XG5cdFx0XHR2YXIgbmV3U3R5bGUgPSBnbG9iYWxzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoc3R5bGUudGFnTmFtZSk7XG5cdFx0XHRzdHlsZS5ocmVmID0gbmV3IFVyaShzdHlsZS5ocmVmKS5tYWtlVW5pcXVlKCkudG9TdHJpbmcoKTtcblx0XHRcdHV0aWxzLmNvcHlOb2RlQXR0cmlidXRlcyhzdHlsZSwgbmV3U3R5bGUpO1xuXHRcdFx0c3R5bGUucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3U3R5bGUsIHN0eWxlKTtcblx0XHRcdHN0eWxlLmRpc2FibGVkID0gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyB0aGUgZmF2aWNvbiBlbGVtZW50cyB0byB0aGUgZG9jdW1lbnQuXG5cdCAqIEBwYXJhbSB7IUFycmF5PEVsZW1lbnQ+fSBlbGVtZW50c1xuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcmV0dXJuIHtDYW5jZWxsYWJsZVByb21pc2V9XG5cdCAqL1xuXHRydW5GYXZpY29uSW5FbGVtZW50XyhlbGVtZW50cykge1xuXHRcdHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKChyZXNvbHZlKSA9PiB7XG5cdFx0XHRlbGVtZW50cy5mb3JFYWNoKChlbGVtZW50KSA9PiBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKFxuXHRcdFx0XHRVQS5pc0llID8gZWxlbWVudCA6IHV0aWxzLnNldEVsZW1lbnRXaXRoUmFuZG9tSHJlZihlbGVtZW50KVxuXHRcdFx0KSk7XG5cdFx0XHRyZXNvbHZlKCk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUXVlcmllcyBlbGVtZW50cyBmcm9tIHZpcnR1YWwgZG9jdW1lbnQgYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgZWxlbWVudHMuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3Jcblx0ICogQHJldHVybiB7YXJyYXkuPEVsZW1lbnQ+fVxuXHQgKi9cblx0dmlydHVhbFF1ZXJ5U2VsZWN0b3JBbGxfKHNlbGVjdG9yKSB7XG5cdFx0cmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMudmlydHVhbERvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBRdWVyaWVzIGVsZW1lbnRzIGZyb20gZG9jdW1lbnQgYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgZWxlbWVudHMuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3Jcblx0ICogQHJldHVybiB7YXJyYXkuPEVsZW1lbnQ+fVxuXHQgKi9cblx0cXVlcnlTZWxlY3RvckFsbF8oc2VsZWN0b3IpIHtcblx0XHRyZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZ2xvYmFscy5kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVsZWFzZXMgdmlydHVhbCBkb2N1bWVudCBhbGxvY2F0ZWQgZm9yIGNvbnRlbnQuXG5cdCAqL1xuXHRyZWxlYXNlVmlydHVhbERvY3VtZW50KCkge1xuXHRcdHRoaXMudmlydHVhbERvY3VtZW50ID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXNvbHZlcyB0aXRsZSBmcm9tIGFsbG9jYXRlZCB2aXJ0dWFsIGRvY3VtZW50LlxuXHQgKi9cblx0cmVzb2x2ZVRpdGxlRnJvbVZpcnR1YWxEb2N1bWVudCgpIHtcblx0XHRjb25zdCB0aXRsZSA9IHRoaXMudmlydHVhbERvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy50aXRsZVNlbGVjdG9yKTtcblx0XHRpZiAodGl0bGUpIHtcblx0XHRcdHRoaXMuc2V0VGl0bGUodGl0bGUudGV4dENvbnRlbnQudHJpbSgpKTtcblx0XHR9XG5cdH1cblxuXHRyZXNvbHZlTWV0YVRhZ3NGcm9tVmlydHVhbERvY3VtZW50KCkge1xuXHRcdGNvbnN0IG1ldGFzID0gdGhpcy52aXJ0dWFsUXVlcnlTZWxlY3RvckFsbF8odGhpcy5tZXRhVGFnc1NlbGVjdG9yKTtcblx0XHRpZiAobWV0YXMpIHtcblx0XHRcdHRoaXMuc2V0TWV0YXMobWV0YXMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB0aXRsZSBzZWxlY3Rvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSB0aXRsZVNlbGVjdG9yXG5cdCAqL1xuXHRzZXRUaXRsZVNlbGVjdG9yKHRpdGxlU2VsZWN0b3IpIHtcblx0XHR0aGlzLnRpdGxlU2VsZWN0b3IgPSB0aXRsZVNlbGVjdG9yO1xuXHR9XG5cbn1cblxuLyoqXG4gKiBIZWxwZXIgc2VsZWN0b3IgZm9yIGlnbm9yZSBmYXZpY29uIHdoZW4gZXhpc3QgZGF0YS1zZW5uYS10cmFjay5cbiAqL1xuY29uc3QgaWdub3JlRmF2aWNvbiA9ICc6bm90KFtyZWw9XCJTaG9ydGN1dCBJY29uXCJdKTpub3QoW3JlbD1cInNob3J0Y3V0IGljb25cIl0pOm5vdChbcmVsPVwiaWNvblwiXSk6bm90KFtocmVmJD1cImZhdmljb24uaWNvblwiXSknO1xuXG4vKipcbiAqIEhlbHBlciBzZWxlY3RvcnMgZm9yIHRyYWNraW5nIHJlc291cmNlcy5cbiAqIEB0eXBlIHtvYmplY3R9XG4gKiBAcHJvdGVjdGVkXG4gKiBAc3RhdGljXG4gKi9cbkh0bWxTY3JlZW4uc2VsZWN0b3JzID0ge1xuXHRmYXZpY29uOiAnbGlua1tyZWw9XCJTaG9ydGN1dCBJY29uXCJdLGxpbmtbcmVsPVwic2hvcnRjdXQgaWNvblwiXSxsaW5rW3JlbD1cImljb25cIl0sbGlua1tocmVmJD1cImZhdmljb24uaWNvblwiXScsXG5cdHNjcmlwdHM6ICdzY3JpcHRbZGF0YS1zZW5uYS10cmFja10nLFxuXHRzY3JpcHRzUGVybWFuZW50OiAnc2NyaXB0W2RhdGEtc2VubmEtdHJhY2s9XCJwZXJtYW5lbnRcIl0nLFxuXHRzY3JpcHRzVGVtcG9yYXJ5OiAnc2NyaXB0W2RhdGEtc2VubmEtdHJhY2s9XCJ0ZW1wb3JhcnlcIl0nLFxuXHRzdHlsZXM6IGBzdHlsZVtkYXRhLXNlbm5hLXRyYWNrXSxsaW5rW2RhdGEtc2VubmEtdHJhY2tdJHtpZ25vcmVGYXZpY29ufWAsXG5cdHN0eWxlc1Blcm1hbmVudDogYHN0eWxlW2RhdGEtc2VubmEtdHJhY2s9XCJwZXJtYW5lbnRcIl0sbGlua1tkYXRhLXNlbm5hLXRyYWNrPVwicGVybWFuZW50XCJdJHtpZ25vcmVGYXZpY29ufWAsXG5cdHN0eWxlc1RlbXBvcmFyeTogYHN0eWxlW2RhdGEtc2VubmEtdHJhY2s9XCJ0ZW1wb3JhcnlcIl0sbGlua1tkYXRhLXNlbm5hLXRyYWNrPVwidGVtcG9yYXJ5XCJdJHtpZ25vcmVGYXZpY29ufWBcbn07XG5cbi8qKlxuICogQ2FjaGVzIHBlcm1hbmVudCByZXNvdXJjZSBrZXlzLlxuICogQHR5cGUge29iamVjdH1cbiAqIEBwcm90ZWN0ZWRcbiAqIEBzdGF0aWNcbiAqL1xuSHRtbFNjcmVlbi5wZXJtYW5lbnRSZXNvdXJjZXNJbkRvYyA9IHt9O1xuXG5leHBvcnQgZGVmYXVsdCBIdG1sU2NyZWVuO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlLCBnZXRVaWQsIGlzRGVmQW5kTm90TnVsbCwgaXNFbGVtZW50LCBvYmplY3QgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgZGF0YUF0dHJpYnV0ZXMgZnJvbSAnLi9kYXRhQXR0cmlidXRlcyc7XG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IEFwcCBmcm9tICcuL0FwcCc7XG5pbXBvcnQgSHRtbFNjcmVlbiBmcm9tICcuLi9zY3JlZW4vSHRtbFNjcmVlbic7XG5pbXBvcnQgUm91dGUgZnJvbSAnLi4vcm91dGUvUm91dGUnO1xuXG5jbGFzcyBBcHBEYXRhQXR0cmlidXRlSGFuZGxlciBleHRlbmRzIERpc3Bvc2FibGUge1xuXG5cdC8qKlxuXHQgKiBJbml0aWxpemVzIEFwcCwgcmVnaXN0ZXIgc3VyZmFjZXMgYW5kIHJvdXRlcyBmcm9tIGRhdGEgYXR0cmlidXRlcy5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGFwcCByZWZlcmVuY2UgaW5pdGlhbGl6ZWQgYnkgZGF0YSBhdHRyaWJ1dGVzLlxuXHRcdCAqIEB0eXBlIHtBcHB9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdHRoaXMuYXBwID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBiYXNlIGVsZW1lbnQgdG8gc2VhcmNoIGluaXRpYWxpemF0aW9uIGRhdGEgYXR0cmlidXRlcy4gVGhpc1xuXHRcdCAqIGVsZW1lbnQgaXMgdGhlIGNvbnRhaW5lciB1c2VkIHRvIGVuYWJsZSBpbml0aWFsaXphdGlvbiBiYXNlZCBvbiB0aGVcblx0XHQgKiBwcmVzZW5jZSBvZiBgZGF0YS1zZW5uYWAgYXR0cmlidXRlLlxuXHRcdCAqIEB0eXBlIHtFbGVtZW50fVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHR0aGlzLmJhc2VFbGVtZW50ID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbml0cyBhcHBsaWNhdGlvbiBiYXNlZCBvbiBpbmZvcm1hdGlvbiBzY2FubmVkIGZyb20gZG9jdW1lbnQuXG5cdCAqL1xuXHRoYW5kbGUoKSB7XG5cdFx0aWYgKCFpc0VsZW1lbnQodGhpcy5iYXNlRWxlbWVudCkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignU2VubmEgZGF0YSBhdHRyaWJ1dGUgaGFuZGxlciBiYXNlIGVsZW1lbnQgJyArXG5cdFx0XHRcdCdub3Qgc2V0IG9yIGludmFsaWQsIHRyeSBzZXR0aW5nIGEgdmFsaWQgZWxlbWVudCB0aGF0ICcgK1xuXHRcdFx0XHQnY29udGFpbnMgYSBgZGF0YS1zZW5uYWAgYXR0cmlidXRlLicpO1xuXHRcdH1cblxuXHRcdGlmICghdGhpcy5iYXNlRWxlbWVudC5oYXNBdHRyaWJ1dGUoZGF0YUF0dHJpYnV0ZXMuc2VubmEpKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnU2VubmEgd2FzIG5vdCBpbml0aWFsaXplZCBmcm9tIGRhdGEgYXR0cmlidXRlcy4gJyArXG5cdFx0XHRcdCdJbiBvcmRlciB0byBlbmFibGUgaXRzIHVzYWdlIGZyb20gZGF0YSBhdHRyaWJ1dGVzIHRyeSBzZXR0aW5nICcgK1xuXHRcdFx0XHQnaW4gdGhlIGJhc2UgZWxlbWVudCwgZS5nLiBgPGJvZHkgZGF0YS1zZW5uYT5gLicpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLmFwcCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTZW5uYSBhcHAgd2FzIGFscmVhZHkgaW5pdGlhbGl6ZWQuJyk7XG5cdFx0fVxuXG5cdFx0Y29uc29sZS5sb2coJ1Nlbm5hIGluaXRpYWxpemVkIGZyb20gZGF0YSBhdHRyaWJ1dGUuJyk7XG5cblx0XHR0aGlzLmFwcCA9IG5ldyBBcHAoKTtcblx0XHR0aGlzLm1heWJlQWRkUm91dGVzXygpO1xuXHRcdHRoaXMubWF5YmVBZGRTdXJmYWNlc18oKTtcblx0XHR0aGlzLm1heWJlU2V0QmFzZVBhdGhfKCk7XG5cdFx0dGhpcy5tYXliZVNldExpbmtTZWxlY3Rvcl8oKTtcblx0XHR0aGlzLm1heWJlU2V0TG9hZGluZ0Nzc0NsYXNzXygpO1xuXHRcdHRoaXMubWF5YmVTZXRVcGRhdGVTY3JvbGxQb3NpdGlvbl8oKTtcblx0XHR0aGlzLm1heWJlRGlzcGF0Y2hfKCk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHRpZiAodGhpcy5hcHApIHtcblx0XHRcdHRoaXMuYXBwLmRpc3Bvc2UoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgYXBwIHJlZmVyZW5jZS5cblx0ICogQHJldHVybiB7QXBwfVxuXHQgKi9cblx0Z2V0QXBwKCkge1xuXHRcdHJldHVybiB0aGlzLmFwcDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBiYXNlIGVsZW1lbnQuXG5cdCAqIEByZXR1cm4ge0VsZW1lbnR9IGJhc2VFbGVtZW50XG5cdCAqL1xuXHRnZXRCYXNlRWxlbWVudCgpIHtcblx0XHRyZXR1cm4gdGhpcy5iYXNlRWxlbWVudDtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBhZGRzIGFwcCByb3V0ZXMgZnJvbSBsaW5rIGVsZW1lbnRzIHRoYXQgYXJlIGBzZW5uYS1yb3V0ZWAuXG5cdCAqL1xuXHRtYXliZUFkZFJvdXRlc18oKSB7XG5cdFx0dmFyIHJvdXRlc1NlbGVjdG9yID0gJ2xpbmtbcmVsPVwic2VubmEtcm91dGVcIl0nO1xuXHRcdHRoaXMucXVlcnlTZWxlY3RvckFsbEFzQXJyYXlfKHJvdXRlc1NlbGVjdG9yKS5mb3JFYWNoKChsaW5rKSA9PiB0aGlzLm1heWJlUGFyc2VMaW5rUm91dGVfKGxpbmspKTtcblx0XHRpZiAoIXRoaXMuYXBwLmhhc1JvdXRlcygpKSB7XG5cdFx0XHR0aGlzLmFwcC5hZGRSb3V0ZXMobmV3IFJvdXRlKC8uKi8sIEh0bWxTY3JlZW4pKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBjYW5cXCd0IGZpbmQgcm91dGUgZWxlbWVudHMsIGFkZGluZyBkZWZhdWx0LicpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBhZGRzIGFwcCBzdXJmYWNlcyBieSBzY2FubmluZyBgZGF0YS1zZW5uYS1zdXJmYWNlYCBkYXRhIGF0dHJpYnV0ZS5cblx0ICovXG5cdG1heWJlQWRkU3VyZmFjZXNfKCkge1xuXHRcdHZhciBzdXJmYWNlc1NlbGVjdG9yID0gJ1snICsgZGF0YUF0dHJpYnV0ZXMuc3VyZmFjZSArICddJztcblx0XHR0aGlzLnF1ZXJ5U2VsZWN0b3JBbGxBc0FycmF5XyhzdXJmYWNlc1NlbGVjdG9yKS5mb3JFYWNoKChzdXJmYWNlRWxlbWVudCkgPT4ge1xuXHRcdFx0dGhpcy51cGRhdGVFbGVtZW50SWRJZlNwZWNpYWxTdXJmYWNlXyhzdXJmYWNlRWxlbWVudCk7XG5cdFx0XHR0aGlzLmFwcC5hZGRTdXJmYWNlcyhzdXJmYWNlRWxlbWVudC5pZCk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcGF0Y2hlcyBhcHAgbmF2aWdhdGlvbiB0byB0aGUgY3VycmVudCBwYXRoIHdoZW4gaW5pdGlhbGl6ZXMuXG5cdCAqL1xuXHRtYXliZURpc3BhdGNoXygpIHtcblx0XHRpZiAodGhpcy5iYXNlRWxlbWVudC5oYXNBdHRyaWJ1dGUoZGF0YUF0dHJpYnV0ZXMuZGlzcGF0Y2gpKSB7XG5cdFx0XHR0aGlzLmFwcC5kaXNwYXRjaCgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGFwcCByb3V0ZSBieSBwYXJzaW5nIHZhbGlkIGxpbmsgZWxlbWVudHMuIEEgdmFsaWQgbGluayBlbGVtZW50IGlzIG9mXG5cdCAqIHRoZSBraW5kIGByZWw9XCJzZW5uYS1yb3V0ZVwiYC5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBsaW5rXG5cdCAqL1xuXHRtYXliZVBhcnNlTGlua1JvdXRlXyhsaW5rKSB7XG5cdFx0dmFyIHJvdXRlID0gbmV3IFJvdXRlKHRoaXMubWF5YmVQYXJzZUxpbmtSb3V0ZVBhdGhfKGxpbmspLCB0aGlzLm1heWJlUGFyc2VMaW5rUm91dGVIYW5kbGVyXyhsaW5rKSk7XG5cdFx0dGhpcy5hcHAuYWRkUm91dGVzKHJvdXRlKTtcblx0XHRjb25zb2xlLmxvZygnU2VubmEgc2Nhbm5lZCByb3V0ZSAnICsgcm91dGUuZ2V0UGF0aCgpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBwYXJzZSBsaW5rIHJvdXRlIGhhbmRsZXIuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbGlua1xuXHQgKiBAcmV0dXJuIHs/c3RyaW5nfVxuXHQgKi9cblx0bWF5YmVQYXJzZUxpbmtSb3V0ZUhhbmRsZXJfKGxpbmspIHtcblx0XHR2YXIgaGFuZGxlciA9IGxpbmsuZ2V0QXR0cmlidXRlKCd0eXBlJyk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChoYW5kbGVyKSkge1xuXHRcdFx0aGFuZGxlciA9IG9iamVjdC5nZXRPYmplY3RCeU5hbWUoaGFuZGxlcik7XG5cdFx0fVxuXHRcdHJldHVybiBoYW5kbGVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHBhcnNlIGxpbmsgcm91dGUgcGF0aC5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBsaW5rXG5cdCAqIEByZXR1cm4gez9zdHJpbmd9XG5cdCAqL1xuXHRtYXliZVBhcnNlTGlua1JvdXRlUGF0aF8obGluaykge1xuXHRcdHZhciBwYXRoID0gbGluay5nZXRBdHRyaWJ1dGUoJ2hyZWYnKTtcblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKHBhdGgpKSB7XG5cdFx0XHRpZiAocGF0aC5pbmRleE9mKCdyZWdleDonKSA9PT0gMCkge1xuXHRcdFx0XHRwYXRoID0gbmV3IFJlZ0V4cChwYXRoLnN1YnN0cmluZyg2KSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBwYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHNldHMgYXBwIGJhc2UgcGF0aCBmcm9tIGBkYXRhLXNlbm5hLWJhc2UtcGF0aGAgZGF0YSBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldEJhc2VQYXRoXygpIHtcblx0XHR2YXIgYmFzZVBhdGggPSB0aGlzLmJhc2VFbGVtZW50LmdldEF0dHJpYnV0ZShkYXRhQXR0cmlidXRlcy5iYXNlUGF0aCk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChiYXNlUGF0aCkpIHtcblx0XHRcdHRoaXMuYXBwLnNldEJhc2VQYXRoKGJhc2VQYXRoKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIGJhc2UgcGF0aCAnICsgYmFzZVBhdGgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBzZXRzIGFwcCBsaW5rIHNlbGVjdG9yIGZyb20gYGRhdGEtc2VubmEtbGluay1zZWxlY3RvcmAgZGF0YVxuXHQgKiBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldExpbmtTZWxlY3Rvcl8oKSB7XG5cdFx0dmFyIGxpbmtTZWxlY3RvciA9IHRoaXMuYmFzZUVsZW1lbnQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGVzLmxpbmtTZWxlY3Rvcik7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChsaW5rU2VsZWN0b3IpKSB7XG5cdFx0XHR0aGlzLmFwcC5zZXRMaW5rU2VsZWN0b3IobGlua1NlbGVjdG9yKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIGxpbmsgc2VsZWN0b3IgJyArIGxpbmtTZWxlY3Rvcik7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHNldHMgYXBwIGxpbmsgbG9hZGluZyBjc3MgY2xhc3MgZnJvbSBgZGF0YS1zZW5uYS1sb2FkaW5nLWNzcy1jbGFzc2Bcblx0ICogZGF0YSBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldExvYWRpbmdDc3NDbGFzc18oKSB7XG5cdFx0dmFyIGxvYWRpbmdDc3NDbGFzcyA9IHRoaXMuYmFzZUVsZW1lbnQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGVzLmxvYWRpbmdDc3NDbGFzcyk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChsb2FkaW5nQ3NzQ2xhc3MpKSB7XG5cdFx0XHR0aGlzLmFwcC5zZXRMb2FkaW5nQ3NzQ2xhc3MobG9hZGluZ0Nzc0NsYXNzKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIGxvYWRpbmcgY3NzIGNsYXNzICcgKyBsb2FkaW5nQ3NzQ2xhc3MpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBzZXRzIGFwcCB1cGRhdGUgc2Nyb2xsIHBvc2l0aW9uIGZyb21cblx0ICogYGRhdGEtc2VubmEtdXBkYXRlLXNjcm9sbC1wb3NpdGlvbmAgZGF0YSBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldFVwZGF0ZVNjcm9sbFBvc2l0aW9uXygpIHtcblx0XHR2YXIgdXBkYXRlU2Nyb2xsUG9zaXRpb24gPSB0aGlzLmJhc2VFbGVtZW50LmdldEF0dHJpYnV0ZShkYXRhQXR0cmlidXRlcy51cGRhdGVTY3JvbGxQb3NpdGlvbik7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbCh1cGRhdGVTY3JvbGxQb3NpdGlvbikpIHtcblx0XHRcdGlmICh1cGRhdGVTY3JvbGxQb3NpdGlvbiA9PT0gJ2ZhbHNlJykge1xuXHRcdFx0XHR0aGlzLmFwcC5zZXRVcGRhdGVTY3JvbGxQb3NpdGlvbihmYWxzZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmFwcC5zZXRVcGRhdGVTY3JvbGxQb3NpdGlvbih0cnVlKTtcblx0XHRcdH1cblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIHVwZGF0ZSBzY3JvbGwgcG9zaXRpb24gJyArIHVwZGF0ZVNjcm9sbFBvc2l0aW9uKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUXVlcmllcyBlbGVtZW50cyBmcm9tIGRvY3VtZW50IGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIGVsZW1lbnRzLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNlbGVjdG9yXG5cdCAqIEByZXR1cm4ge2FycmF5LjxFbGVtZW50Pn1cblx0ICovXG5cdHF1ZXJ5U2VsZWN0b3JBbGxBc0FycmF5XyhzZWxlY3Rvcikge1xuXHRcdHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChnbG9iYWxzLmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIGVsZW1lbnQgaWQgaWYgaGFuZGxlZCBhcyBzcGVjaWFsIHN1cmZhY2UgZWxlbWVudC4gU29tZSBzdXJmYWNlc1xuXHQgKiBhcmUgc2xpZ2h0bHkgZGlmZmVyZW50IGZyb20gb3RoZXJzLCBsaWtlIHdoZW4gdGhyZWF0aW5nIDxjb2RlPmJvZHk8L2NvZGU+XG5cdCAqIGFzIHN1cmZhY2UuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuXHQgKi9cblx0dXBkYXRlRWxlbWVudElkSWZTcGVjaWFsU3VyZmFjZV8oZWxlbWVudCkge1xuXHRcdGlmICghZWxlbWVudC5pZCAmJiBlbGVtZW50ID09PSBnbG9iYWxzLmRvY3VtZW50LmJvZHkpIHtcblx0XHRcdGVsZW1lbnQuaWQgPSAnc2VubmFfc3VyZmFjZV8nICsgZ2V0VWlkKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGJhc2UgZWxlbWVudC5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBiYXNlRWxlbWVudFxuXHQgKi9cblx0c2V0QmFzZUVsZW1lbnQoYmFzZUVsZW1lbnQpIHtcblx0XHR0aGlzLmJhc2VFbGVtZW50ID0gYmFzZUVsZW1lbnQ7XG5cdH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBBcHBEYXRhQXR0cmlidXRlSGFuZGxlcjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IGdsb2JhbHMgZnJvbSAnLi4vZ2xvYmFscy9nbG9iYWxzJztcbmltcG9ydCBBcHBEYXRhQXR0cmlidXRlSGFuZGxlciBmcm9tICcuL0FwcERhdGFBdHRyaWJ1dGVIYW5kbGVyJztcblxuLyoqXG4gKiBEYXRhIGF0dHJpYnV0ZSBoYW5kbGVyLlxuICogQHR5cGUge0FwcERhdGFBdHRyaWJ1dGVIYW5kbGVyfVxuICovXG52YXIgZGF0YUF0dHJpYnV0ZUhhbmRsZXIgPSBuZXcgQXBwRGF0YUF0dHJpYnV0ZUhhbmRsZXIoKTtcblxuZ2xvYmFscy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZnVuY3Rpb24oKSB7XG5cdGRhdGFBdHRyaWJ1dGVIYW5kbGVyLnNldEJhc2VFbGVtZW50KGdsb2JhbHMuZG9jdW1lbnQuYm9keSk7XG5cdGRhdGFBdHRyaWJ1dGVIYW5kbGVyLmhhbmRsZSgpO1xufSk7XG5cbmV4cG9ydCBkZWZhdWx0IGRhdGFBdHRyaWJ1dGVIYW5kbGVyOyIsIi8qKlxuICogQHJldHVybnMgU3RyaW5nIGNvbnRhaW5pbmcgdGhlIGN1cnJlbnQgc2VubmEgdmVyc2lvblxuICovXG5cbmNvbnN0IHZlcnNpb24gPSAnPCU9IHZlcnNpb24gJT4nO1xuXG5leHBvcnQgZGVmYXVsdCB2ZXJzaW9uOyJdLCJuYW1lcyI6WyJpc0RlZiIsInZhbCIsInVuZGVmaW5lZCIsImlzRGVmQW5kTm90TnVsbCIsImlzTnVsbCIsImlzRG9jdW1lbnQiLCJub2RlVHlwZSIsImlzRnVuY3Rpb24iLCJpc09iamVjdCIsInR5cGUiLCJpc1N0cmluZyIsIlN0cmluZyIsImlzU2VydmVyU2lkZSIsIm9wdGlvbnMiLCJjaGVja0VudiIsInNlcnZlclNpZGUiLCJwcm9jZXNzIiwiYnJvd3NlciIsImVudiIsIk5PREVfRU5WIiwiYXJyYXkiLCJhcnIxIiwiYXJyMiIsImxlbmd0aCIsImkiLCJhcnIiLCJvdXRwdXQiLCJBcnJheSIsImlzQXJyYXkiLCJmbGF0dGVuIiwicHVzaCIsIm9iaiIsImluZGV4T2YiLCJydiIsInJlbW92ZUF0IiwicHJvdG90eXBlIiwic3BsaWNlIiwiY2FsbCIsInN0YXJ0IiwiZW5kIiwic2xpY2VkIiwiYXN5bmMiLCJ0aHJvd0V4Y2VwdGlvbiIsImV4Y2VwdGlvbiIsIm5leHRUaWNrIiwicnVuIiwiY2FsbGJhY2siLCJjb250ZXh0Iiwid29ya1F1ZXVlU2NoZWR1bGVkXyIsInByb2Nlc3NXb3JrUXVldWUiLCJ3b3JrUXVldWVfIiwiV29ya0l0ZW1fIiwid29ya0l0ZW1zIiwid29ya0l0ZW0iLCJmbiIsInNjb3BlIiwiZSIsImNiIiwiYmluZCIsIndyYXBDYWxsYmFja18iLCJzZXRJbW1lZGlhdGVfIiwic2V0SW1tZWRpYXRlIiwiZ2V0U2V0SW1tZWRpYXRlRW11bGF0b3JfIiwiQ2hhbm5lbCIsIk1lc3NhZ2VDaGFubmVsIiwid2luZG93IiwicG9zdE1lc3NhZ2UiLCJhZGRFdmVudExpc3RlbmVyIiwiaWZyYW1lIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50Iiwic3R5bGUiLCJkaXNwbGF5Iiwic3JjIiwidGl0bGUiLCJkb2N1bWVudEVsZW1lbnQiLCJhcHBlbmRDaGlsZCIsIndpbiIsImNvbnRlbnRXaW5kb3ciLCJkb2MiLCJvcGVuIiwid3JpdGUiLCJjbG9zZSIsIm1lc3NhZ2UiLCJNYXRoIiwicmFuZG9tIiwib3JpZ2luIiwibG9jYXRpb24iLCJwcm90b2NvbCIsImhvc3QiLCJvbm1lc3NhZ2UiLCJkYXRhIiwicG9ydDEiLCJwb3J0MiIsImNoYW5uZWwiLCJoZWFkIiwidGFpbCIsIm5leHQiLCJzY3JpcHQiLCJvbnJlYWR5c3RhdGVjaGFuZ2UiLCJwYXJlbnROb2RlIiwicmVtb3ZlQ2hpbGQiLCJEaXNwb3NhYmxlIiwiZGlzcG9zZWRfIiwiZGlzcG9zZUludGVybmFsIiwib2JqZWN0IiwidGFyZ2V0Iiwia2V5Iiwic291cmNlIiwiYXJncyIsIm5hbWUiLCJwYXJ0cyIsInNwbGl0IiwicmVkdWNlIiwicGFydCIsIm1hcHBlZE9iaiIsImtleXMiLCJPYmplY3QiLCJvYmoxIiwib2JqMiIsImtleXMxIiwia2V5czIiLCJzdHJpbmciLCJzdHIxIiwic3RyMiIsInRlc3QxIiwidG9Mb3dlckNhc2UiLCJ0ZXN0MiIsInN0ciIsInJlcGxhY2UiLCJ4IiwiZmxvb3IiLCJ0b1N0cmluZyIsImFicyIsIkRhdGUiLCJub3ciLCJoYXNoIiwibGVuIiwiY2hhckNvZGVBdCIsInZhbHVlIiwic3Vic3RyaW5nIiwiTUVUQUxfREFUQSIsImRvbURhdGEiLCJlbGVtZW50IiwiaW5pdGlhbFZhbHVlIiwiRXZlbnRIYW5kbGUiLCJlbWl0dGVyIiwiZXZlbnQiLCJsaXN0ZW5lciIsImVtaXR0ZXJfIiwiZXZlbnRfIiwibGlzdGVuZXJfIiwicmVtb3ZlTGlzdGVuZXIiLCJpc0Rpc3Bvc2VkIiwic2luZ2xlQXJyYXlfIiwiRXZlbnRFbWl0dGVyIiwiZXZlbnRzXyIsImxpc3RlbmVySGFuZGxlcnNfIiwic2hvdWxkVXNlRmFjYWRlXyIsImhvbGRlciIsImhhbmRsZXIiLCJkZWZhdWx0TGlzdGVuZXIiLCJ2YWxpZGF0ZUxpc3RlbmVyXyIsImV2ZW50cyIsInRvRXZlbnRzQXJyYXlfIiwiYWRkU2luZ2xlTGlzdGVuZXJfIiwicnVuTGlzdGVuZXJIYW5kbGVyc18iLCJhZGRIYW5kbGVyXyIsImdldFNob3VsZFVzZUZhY2FkZSIsImZhY2FkZSIsInByZXZlbnRlZERlZmF1bHQiLCJsaXN0ZW5lcnMiLCJnZXRSYXdMaXN0ZW5lcnNfIiwic2xpY2UiLCJhcmd1bWVudHMiLCJydW5MaXN0ZW5lcnNfIiwiYnVpbGRGYWNhZGVfIiwiZGlyZWN0TGlzdGVuZXJzIiwidG9BcnJheSIsImNvbmNhdCIsIm1hcCIsImFtb3VudCIsIm1hbnlfIiwic2VsZiIsImhhbmRsZXJJbnRlcm5hbCIsImFwcGx5IiwibGlzdGVuZXJPYmoiLCJyZW1vdmVNYXRjaGluZ0xpc3RlbmVyT2Jqc18iLCJhZGRMaXN0ZW5lciIsIm1hbnkiLCJsaXN0ZW5lck9ianMiLCJmaW5hbExpc3RlbmVycyIsIm1hdGNoZXNMaXN0ZW5lcl8iLCJvZmYiLCJoYW5kbGVycyIsImRlZmF1bHRMaXN0ZW5lcnMiLCJkZWZhdWx0IiwiaiIsInNob3VsZFVzZUZhY2FkZSIsIlR5cGVFcnJvciIsIkV2ZW50RW1pdHRlclByb3h5Iiwib3JpZ2luRW1pdHRlciIsInRhcmdldEVtaXR0ZXIiLCJibGFja2xpc3QiLCJ3aGl0ZWxpc3QiLCJibGFja2xpc3RfIiwib3JpZ2luRW1pdHRlcl8iLCJwZW5kaW5nRXZlbnRzXyIsInByb3hpZWRFdmVudHNfIiwidGFyZ2V0RW1pdHRlcl8iLCJ3aGl0ZWxpc3RfIiwic3RhcnRQcm94eV8iLCJvbiIsInJlbW92ZUxpc3RlbmVyc18iLCJlbWl0Iiwic2hvdWxkUHJveHlFdmVudF8iLCJ0cnlUb0FkZExpc3RlbmVyXyIsImZvckVhY2giLCJwcm94eUV2ZW50Iiwib25MaXN0ZW5lciIsImFkZExpc3RlbmVyXyIsImVtaXRPblRhcmdldF8iLCJFdmVudEhhbmRsZXIiLCJldmVudEhhbmRsZXNfIiwiRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGUiLCJzZWxlY3RvciIsInNlbGVjdG9yXyIsImRlbGVnYXRpbmciLCJnZXQiLCJzZWxlY3RvcnMiLCJyZW1vdmUiLCJEb21FdmVudEhhbmRsZSIsImNhcHR1cmUiLCJjYXB0dXJlXyIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJlbGVtZW50c0J5VGFnXyIsInN1cHBvcnRDYWNoZV8iLCJjdXN0b21FdmVudHMiLCJMQVNUX0NPTlRBSU5FUiIsIlVTRV9DQVBUVVJFIiwiYWRkQ2xhc3NlcyIsImVsZW1lbnRzIiwiY2xhc3NlcyIsImFkZENsYXNzZXNXaXRoTmF0aXZlXyIsImNsYXNzTmFtZSIsImNsYXNzTGlzdCIsImFkZCIsImFkZENsYXNzZXNXaXRob3V0TmF0aXZlXyIsImVsZW1lbnRDbGFzc05hbWUiLCJjbGFzc2VzVG9BcHBlbmQiLCJhZGRFbGVtZW50TGlzdGVuZXJfIiwiZXZlbnROYW1lIiwiYWRkU2VsZWN0b3JMaXN0ZW5lcl8iLCJkZWxlZ2F0aW5nRGF0YSIsImFkZFRvQXJyXyIsImF0dGFjaERlbGVnYXRlRXZlbnRfIiwiaGFuZGxlRGVsZWdhdGVFdmVudF8iLCJjbG9zZXN0IiwibWF0Y2giLCJhcHBlbmQiLCJwYXJlbnQiLCJjaGlsZCIsImJ1aWxkRnJhZ21lbnQiLCJpc05vZGVMaXN0TGlrZSIsImNoaWxkQXJyIiwiaHRtbFN0cmluZyIsInRlbXBEaXYiLCJpbm5lckhUTUwiLCJmaXJzdENoaWxkIiwiZnJhZ21lbnQiLCJjcmVhdGVEb2N1bWVudEZyYWdtZW50IiwiY29udGFpbnMiLCJlbGVtZW50MSIsImVsZW1lbnQyIiwiZGVsZWdhdGUiLCJzZWxlY3Rvck9yVGFyZ2V0IiwiY3VzdG9tQ29uZmlnIiwib3JpZ2luYWxFdmVudCIsImRlZmF1bHRMaXN0ZW5lcl8iLCJpc0FibGVUb0ludGVyYWN0V2l0aF8iLCJub2RlIiwiZXZlbnRPYmoiLCJidXR0b24iLCJtYXRjaGVzU2VsZWN0b3IiLCJ0YWdOYW1lIiwiZGlzYWJsZWQiLCJpdGVtIiwiZXhpdERvY3VtZW50IiwicmV0IiwiY29udGFpbmVyIiwiY3VycmVudFRhcmdldCIsImRlZkZucyIsInRyaWdnZXJEZWxlZ2F0ZWRMaXN0ZW5lcnNfIiwidHJpZ2dlckRlZmF1bHREZWxlZ2F0ZWRMaXN0ZW5lcnNfIiwiZGVsZWdhdGVUYXJnZXQiLCJwIiwiRWxlbWVudCIsIm0iLCJtYXRjaGVzIiwid2Via2l0TWF0Y2hlc1NlbGVjdG9yIiwibW96TWF0Y2hlc1NlbGVjdG9yIiwibXNNYXRjaGVzU2VsZWN0b3IiLCJvTWF0Y2hlc1NlbGVjdG9yIiwibWF0Y2hGYWxsYmFja18iLCJub2RlcyIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJub3JtYWxpemVEZWxlZ2F0ZUV2ZW50XyIsInN0b3BQcm9wYWdhdGlvbiIsInN0b3BQcm9wYWdhdGlvbl8iLCJzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24iLCJzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb25fIiwib25jZSIsImRvbUV2ZW50SGFuZGxlIiwicmVnaXN0ZXJDdXN0b21FdmVudCIsInJlbW92ZUNoaWxkcmVuIiwicmVtb3ZlQ2xhc3NlcyIsInJlbW92ZUNsYXNzZXNXaXRoTmF0aXZlXyIsInJlbW92ZUNsYXNzZXNXaXRob3V0TmF0aXZlXyIsInRyaW0iLCJzdG9wcGVkIiwic3RvcHBlZEltbWVkaWF0ZSIsInN1cHBvcnRzRXZlbnQiLCJ0YWciLCJoYXNPd25Qcm9wZXJ0eSIsImRlZmF1bHRQcmV2ZW50ZWQiLCJkZWZhdWx0Rm5zIiwiY3VyckVsZW1lbnQiLCJsaW1pdCIsInRyaWdnZXJFbGVtZW50TGlzdGVuZXJzXyIsInRyaWdnZXJTZWxlY3Rvckxpc3RlbmVyc18iLCJsYXN0Q29udGFpbmVyIiwidHJpZ2dlckxpc3RlbmVyc18iLCJEb21FdmVudEVtaXR0ZXJQcm94eSIsImlzRGVsZWdhdGVFdmVudF8iLCJpbmRleCIsInN1YnN0ciIsImJhYmVsSGVscGVycy5nZXQiLCJpc1N1cHBvcnRlZERvbUV2ZW50XyIsImZlYXR1cmVzIiwiYW5pbWF0aW9uRXZlbnROYW1lXyIsImNoZWNrQW5pbWF0aW9uRXZlbnROYW1lXyIsInByZWZpeGVzIiwidHlwZVRpdGxlQ2FzZSIsInJlcGxhY2VJbnRlcnZhbCIsInRvVXBwZXJDYXNlIiwic3VmZml4ZXMiLCJhbmltYXRpb25FbGVtZW50XyIsImF0dHJPcmRlckNoYW5nZV8iLCJvcmlnaW5hbENvbnRlbnQiLCJnbG9iYWxFdmFsIiwidGV4dCIsImFwcGVuZEZuIiwiZGVmYXVsdEZuIiwicnVuRmlsZSIsInNjcmlwdHMiLCJydW5TY3JpcHRzSW5PcmRlciIsInJ1blNjcmlwdCIsImdsb2JhbEV2YWxTdHlsZXMiLCJocmVmIiwibGluayIsInJlbCIsInJ1blN0eWxlIiwic3R5bGVzIiwibG9hZENvdW50IiwicmVnaXN0ZXJFdmVudHMiLCJtb3VzZUV2ZW50TWFwIiwicmVsYXRlZCIsInJlbGF0ZWRUYXJnZXQiLCJjdXN0b21UeXBlIiwiYW5pbWF0aW9uRXZlbnRNYXAiLCJldmVudFR5cGUiLCJjaGVja0FuaW1hdGlvbkV2ZW50TmFtZSIsImdsb2JhbHMiLCJjb21wYXRpYmlsaXR5TW9kZURhdGFfIiwidW5pcXVlSWRDb3VudGVyXyIsIlVJRF9QUk9QRVJUWSIsImFic3RyYWN0TWV0aG9kIiwiRXJyb3IiLCJkaXNhYmxlQ29tcGF0aWJpbGl0eU1vZGUiLCJlbmFibGVDb21wYXRpYmlsaXR5TW9kZSIsImdldENvbXBhdGliaWxpdHlNb2RlRGF0YSIsIl9fTUVUQUxfQ09NUEFUSUJJTElUWV9fIiwiZ2V0Rmlyc3RUcnV0aHlfIiwiYSIsImIiLCJnZXRGdW5jdGlvbk5hbWUiLCJnZXRTdGF0aWNQcm9wZXJ0eSIsImN0b3IiLCJwcm9wZXJ0eU5hbWUiLCJtZXJnZUZuIiwibWVyZ2VkTmFtZSIsIm1lcmdlZCIsIl9fcHJvdG9fXyIsImlzUHJvdG90eXBlT2YiLCJGdW5jdGlvbiIsImdldFVpZCIsIm5vSW5oZXJpdGFuY2UiLCJpZCIsImlkZW50aXR5RnVuY3Rpb24iLCJyZXR1cm5WYWx1ZSIsImlzQm9vbGVhbiIsImlzRG9jdW1lbnRGcmFnbWVudCIsImlzRWxlbWVudCIsImlzTnVtYmVyIiwiaXNXaW5kb3ciLCJpc1Byb21pc2UiLCJ0aGVuIiwibnVsbEZ1bmN0aW9uIiwicGFyc2VGcm9tQW5jaG9yIiwib3B0X3VyaSIsInRlc3QiLCJob3N0bmFtZSIsInBhc3N3b3JkIiwicGF0aG5hbWUiLCJwb3J0Iiwic2VhcmNoIiwidXNlcm5hbWUiLCJwYXJzZSIsIlVSTCIsInVybCIsImNyZWF0ZSIsIk11bHRpTWFwIiwidmFsdWVzIiwic2l6ZSIsIm5hbWVzIiwiSlNPTiIsInN0cmluZ2lmeSIsInNldCIsIlRyZWVOb2RlIiwidmFsdWVfIiwicGFyZW50XyIsImNoaWxkcmVuXyIsInNldFBhcmVudCIsImN1cnJlbnQiLCJnZXRQYXJlbnQiLCJhbmNlc3RvcnMiLCJnZXRDaGlsZHJlbiIsIkVNUFRZX0FSUkFZIiwiZGVwdGgiLCJyb290IiwiZ2V0Q2hpbGRDb3VudCIsIm9wdF9wcmVvcmRlckZuIiwib3B0X3Bvc3RvcmRlckZuIiwidHJhdmVyc2UiLCJhc3NlcnRDaGlsZEhhc05vUGFyZW50IiwicGFyc2VGbl8iLCJVcmkiLCJtYXliZUFkZFByb3RvY29sQW5kSG9zdG5hbWVfIiwibXVsdGltYXAiLCJnZXRBbGwiLCJhZGRQYXJhbWV0ZXJWYWx1ZSIsImVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfIiwicXVlcnkiLCJwYXJhbSIsInVybERlY29kZSIsImdldEhvc3RuYW1lIiwiZ2V0UG9ydCIsIkhPU1ROQU1FX1BMQUNFSE9MREVSIiwiZ2V0SG9zdCIsImdldFByb3RvY29sIiwicXVlcnlzdHJpbmciLCJnZXRQYXJhbWV0ZXJOYW1lcyIsImdldFBhcmFtZXRlclZhbHVlcyIsImVuY29kZVVSSUNvbXBvbmVudCIsInNldFBhcmFtZXRlclZhbHVlIiwiUkFORE9NX1BBUkFNIiwiZ2V0UmFuZG9tU3RyaW5nIiwiREVGQVVMVF9QUk9UT0NPTCIsImNoYXJBdCIsInJlbW92ZVBhcmFtZXRlciIsImdldFBhdGhuYW1lIiwiZ2V0U2VhcmNoIiwiZ2V0SGFzaCIsInBhcnNlRm4iLCJiYXNlUGF0aCIsInBhdGhzIiwicGF0aCIsImpvaW4iLCJkZWNvZGVVUklDb21wb25lbnQiLCJpc1NlY3VyZSIsInV0aWxzIiwiYXR0cmlidXRlcyIsImF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZSIsImdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoIiwib2Zmc2V0TGVmdCIsIm9mZnNldFRvcCIsIm9mZnNldFBhcmVudCIsInVyaSIsImN1cnJlbnRCcm93c2VyUGF0aCIsImdldFVybFBhdGhXaXRob3V0SGFzaCIsImdldFVybFBhdGgiLCJoaXN0b3J5IiwicHVzaFN0YXRlIiwiZXJyIiwiZXJyb3IiLCJyZW1vdmVBdHRyaWJ1dGUiLCJyZWZlcnJlciIsImRlZmluZVByb3BlcnR5IiwiVGhlbmFibGUiLCJJTVBMRU1FTlRFRF9CWV9QUk9QIiwiYWRkSW1wbGVtZW50YXRpb24iLCIkZ29vZ19UaGVuYWJsZSIsImlzSW1wbGVtZW50ZWRCeSIsInBhcnRpYWwiLCJuZXdBcmdzIiwiQ2FuY2VsbGFibGVQcm9taXNlIiwicmVzb2x2ZXIiLCJvcHRfY29udGV4dCIsInN0YXRlXyIsIlN0YXRlXyIsIlBFTkRJTkciLCJyZXN1bHRfIiwiY2FsbGJhY2tFbnRyaWVzXyIsImV4ZWN1dGluZ18iLCJVTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZIiwidW5oYW5kbGVkUmVqZWN0aW9uSWRfIiwiaGFkVW5oYW5kbGVkUmVqZWN0aW9uXyIsInJlc29sdmVfIiwiRlVMRklMTEVEIiwicmVhc29uIiwiUkVKRUNURUQiLCJDYWxsYmFja0VudHJ5XyIsInJlc29sdmUiLCJvcHRfdmFsdWUiLCJyZWplY3QiLCJvcHRfcmVhc29uIiwicmFjZSIsInByb21pc2VzIiwicHJvbWlzZSIsImFsbCIsInRvRnVsZmlsbCIsIm9uRnVsZmlsbCIsIm9uUmVqZWN0IiwiZmlyc3RGdWxmaWxsZWQiLCJ0b1JlamVjdCIsInJlYXNvbnMiLCJvcHRfb25GdWxmaWxsZWQiLCJvcHRfb25SZWplY3RlZCIsImFkZENoaWxkUHJvbWlzZV8iLCJ0aGVuQWx3YXlzIiwib25SZXNvbHZlZCIsImhhbmRsZVJlamVjdGlvbl8iLCJhZGRDYWxsYmFja0VudHJ5XyIsInRoZW5DYXRjaCIsIm9uUmVqZWN0ZWQiLCJjYXRjaCIsImNhbmNlbCIsIm9wdF9tZXNzYWdlIiwiQ2FuY2VsbGF0aW9uRXJyb3IiLCJJU19DQU5DRUxMQVRJT05fRVJST1IiLCJjYW5jZWxJbnRlcm5hbF8iLCJjYW5jZWxDaGlsZF8iLCJjaGlsZFByb21pc2UiLCJjaGlsZENvdW50IiwiY2hpbGRJbmRleCIsImVudHJ5IiwiY2FsbGJhY2tFbnRyeSIsImV4ZWN1dGVDYWxsYmFja18iLCJzY2hlZHVsZUNhbGxiYWNrc18iLCJvbkZ1bGZpbGxlZCIsInJlc3VsdCIsInVuYmxvY2tBbmRGdWxmaWxsXyIsIkJMT0NLRUQiLCJ1bmJsb2NrQW5kUmVqZWN0XyIsInN0YXRlIiwidHJ5VGhlbl8iLCJhZGRVbmhhbmRsZWRSZWplY3Rpb25fIiwidGhlbmFibGUiLCJjYWxsZWQiLCJleGVjdXRlQ2FsbGJhY2tzXyIsImVudHJpZXMiLCJyZW1vdmVVbmhhbmRsZWRSZWplY3Rpb25fIiwic2V0VGltZW91dCIsInNldFVuaGFuZGxlZFJlamVjdGlvbkhhbmRsZXIiLCJkZWJvdW5jZSIsImRlbGF5IiwiZGVib3VuY2VkIiwiY2FuY2VsRGVib3VuY2UiLCJSRUdFWCIsImNvbnZlcnRNYXRjaGVzVG9PYmoiLCJjb252ZXJ0VG9rZW5zVG9SZWdleCIsInRva2VucyIsInJlZ2V4IiwiY29yZSIsImVzY2FwZSIsImVuY2xvc2VOb25DYXB0dXJpbmdHcm91cCIsInBhdHRlcm4iLCJyZXBlYXQiLCJwcmVmaXgiLCJvcHRpb25hbCIsIlJlZ0V4cCIsIm1ha2VUcmFpbGluZ1NsYXNoT3B0aW9uYWwiLCJyb3V0ZU9yVG9rZW5zIiwicm91dGUiLCJ1bm5hbWVkQ291bnQiLCJjdXJyUGF0aCIsImV4ZWMiLCJwYXJhbVBhdHRlcm4iLCJ1bm5hbWVkUGF0dGVybiIsIm1vZGlmaWVyIiwidG9SZWdleCIsImV4dHJhY3REYXRhIiwicGFyYW1JbmRleCIsIlJvdXRlIiwicGFyc2VkRGF0YV8iLCJidWlsZFBhcnNlZERhdGFfIiwiQ2FjaGVhYmxlIiwiY2FjaGUiLCJjYWNoZWFibGUiLCJjb250ZW50IiwiY2xlYXJDYWNoZSIsIlNjcmVlbiIsIm1ha2VJZF8iLCJtZXRhcyIsImxvZyIsInN1cmZhY2VzIiwic0lkIiwiYWN0aXZlQ2hpbGQiLCJydW5TY3JpcHRzSW5FbGVtZW50IiwidHJhbnNpdGlvbnMiLCJzdXJmYWNlIiwiZGVmZXJyZWQiLCJzaG93IiwiU3VyZmFjZSIsImRlZmF1bHRDaGlsZCIsInRyYW5zaXRpb25GbiIsImdldENoaWxkIiwiREVGQVVMVCIsIm1heWJlV3JhcENvbnRlbnRBc0RlZmF1bHRfIiwic2NyZWVuSWQiLCJvcHRfY29udGVudCIsImNyZWF0ZUNoaWxkIiwidHJhbnNpdGlvbiIsImdldEVsZW1lbnQiLCJnZXRFbGVtZW50QnlJZCIsImFkZENvbnRlbnQiLCJmcm9tIiwidG8iLCJkZWZhdWx0VHJhbnNpdGlvbiIsIk5hdmlnYXRpb25TdHJhdGVneSIsIkFwcCIsImFjdGl2ZVNjcmVlbiIsImFjdGl2ZVBhdGgiLCJhbGxvd1ByZXZlbnROYXZpZ2F0ZSIsImJyb3dzZXJQYXRoQmVmb3JlTmF2aWdhdGUiLCJjYXB0dXJlU2Nyb2xsUG9zaXRpb25Gcm9tU2Nyb2xsRXZlbnQiLCJkZWZhdWx0VGl0bGUiLCJmb3JtU2VsZWN0b3IiLCJpZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGgiLCJsaW5rU2VsZWN0b3IiLCJsb2FkaW5nQ3NzQ2xhc3MiLCJuYXRpdmVTY3JvbGxSZXN0b3JhdGlvblN1cHBvcnRlZCIsIm5hdmlnYXRpb25TdHJhdGVneSIsIklNTUVESUFURSIsImlzTmF2aWdhdGlvblBlbmRpbmciLCJwZW5kaW5nTmF2aWdhdGUiLCJwb3BzdGF0ZVNjcm9sbExlZnQiLCJwb3BzdGF0ZVNjcm9sbFRvcCIsInJlZGlyZWN0UGF0aCIsInJvdXRlcyIsInNjaGVkdWxlZE5hdmlnYXRpb25RdWV1ZSIsInNjcmVlbnMiLCJza2lwTG9hZFBvcHN0YXRlIiwidXBkYXRlU2Nyb2xsUG9zaXRpb24iLCJhcHBFdmVudEhhbmRsZXJzXyIsIm9uU2Nyb2xsXyIsIm9uTG9hZF8iLCJvblBvcHN0YXRlXyIsIm9uU3RhcnROYXZpZ2F0ZV8iLCJvbkJlZm9yZU5hdmlnYXRlXyIsIm9uQmVmb3JlTmF2aWdhdGVEZWZhdWx0XyIsIm9uQmVmb3JlVW5sb2FkRGVmYXVsdF8iLCJzZXRMaW5rU2VsZWN0b3IiLCJzZXRGb3JtU2VsZWN0b3IiLCJtYXliZU92ZXJsb2FkQmVmb3JlVW5sb2FkXyIsImdldElkIiwiaXNXZWJVcmkiLCJpc0xpbmtTYW1lT3JpZ2luXyIsImlzU2FtZUJhc2VQYXRoXyIsImlzQ3VycmVudEJyb3dzZXJQYXRoIiwiZmluZFJvdXRlIiwicmVtb3ZlU2NyZWVuIiwic2NyZWVuIiwiZ2V0SGFuZGxlciIsImNsZWFyU2NyZWVuc0NhY2hlIiwiZm9ybUV2ZW50SGFuZGxlcl8iLCJsaW5rRXZlbnRIYW5kbGVyXyIsInJlbW92ZUFsbExpc3RlbmVycyIsIm5hdmlnYXRlIiwiZ2V0Q3VycmVudEJyb3dzZXJQYXRoIiwib3B0X3JlcGxhY2VIaXN0b3J5Iiwic3RvcFBlbmRpbmdOYXZpZ2F0ZV8iLCJuZXh0U2NyZWVuIiwiY3JlYXRlU2NyZWVuSW5zdGFuY2UiLCJtYXliZVByZXZlbnREZWFjdGl2YXRlXyIsIm1heWJlUHJldmVudEFjdGl2YXRlXyIsImxvYWQiLCJTQ0hFRFVMRV9MQVNUIiwiZGVhY3RpdmF0ZSIsInByZXBhcmVOYXZpZ2F0ZUhpc3RvcnlfIiwicHJlcGFyZU5hdmlnYXRlU3VyZmFjZXNfIiwiZXh0cmFjdFBhcmFtcyIsImV2YWx1YXRlU3R5bGVzIiwiZmxpcCIsImV2YWx1YXRlU2NyaXB0cyIsIm1heWJlVXBkYXRlU2Nyb2xsUG9zaXRpb25TdGF0ZV8iLCJzeW5jU2Nyb2xsUG9zaXRpb25TeW5jVGhlbkFzeW5jXyIsImZpbmFsaXplTmF2aWdhdGVfIiwiaGFuZGxlTmF2aWdhdGVFcnJvcl8iLCJzY2hlZHVsZWROYXZpZ2F0aW9uIiwic2hpZnQiLCJtYXliZU5hdmlnYXRlXyIsImdldFJvdXRlUGF0aCIsImFjdGl2YXRlIiwiaXNDYWNoZWFibGUiLCJjYXB0dXJlZEZvcm1FbGVtZW50IiwiY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCIsIm1hdGNoZXNQYXRoIiwiZ2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoIiwiZ2V0VXJsUGF0aFdpdGhvdXRIYXNoQW5kU2VhcmNoIiwic3RhY2siLCJob3N0VXJpIiwibG9jYXRpb25Ib3N0VXJpIiwid2lubmVyIiwic3dpdGNoU2Nyb2xsUG9zaXRpb25SYWNlIiwic2Nyb2xsVG8iLCJzY3JvbGxMZWZ0Iiwic2Nyb2xsVG9wIiwibmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25fIiwic2Nyb2xsUmVzdG9yYXRpb24iLCJtaXhpbiIsImNhbk5hdmlnYXRlIiwiaXNOYXZpZ2F0aW9uU2NoZWR1bGVkIiwibWF5YmVTY2hlZHVsZU5hdmlnYXRpb25fIiwicHJldmVudERlZmF1bHQiLCJuYXZpZ2F0ZUZhaWxlZCIsImlzU2NoZWR1bGVkTmF2aWdhdGlvbiIsIm9uYmVmb3JldW5sb2FkIiwiX29uYmVmb3JldW5sb2FkIiwiX292ZXJsb2FkZWQiLCJiZWZvcmVBY3RpdmF0ZSIsInByZXZlbnQiLCJiZWZvcmVEZWFjdGl2YXRlIiwiYW5jaG9yRWxlbWVudCIsImdldE5vZGVPZmZzZXQiLCJzYXZlSGlzdG9yeUN1cnJlbnRQYWdlU2Nyb2xsUG9zaXRpb25fIiwib3B0X2V2ZW50IiwiaXNIdG1sNUhpc3RvcnlTdXBwb3J0ZWQiLCJmb3JtIiwicmVwbGFjZUhpc3RvcnkiLCJmdW5jIiwiYWx0S2V5IiwiY3RybEtleSIsIm1ldGFLZXkiLCJzaGlmdEtleSIsIm1ldGhvZCIsImJ1dHRvblNlbGVjdG9yIiwiYWN0aXZlRWxlbWVudCIsInF1ZXJ5U2VsZWN0b3IiLCJhY3Rpb24iLCJtYXliZVJlcG9zaXRpb25TY3JvbGxUb0hhc2hlZEFuY2hvciIsInJlbG9hZFBhZ2UiLCJzZW5uYSIsImxvY2tIaXN0b3J5U2Nyb2xsUG9zaXRpb25fIiwic2V0UmVmZXJyZXIiLCJzZXRIb3N0bmFtZSIsInNldFBvcnQiLCJwYWdlWU9mZnNldCIsInBhZ2VYT2Zmc2V0IiwibWF5YmVEaXNhYmxlTmF0aXZlU2Nyb2xsUmVzdG9yYXRpb24iLCJlbmROYXZpZ2F0ZVBheWxvYWQiLCJkb05hdmlnYXRlXyIsIm1heWJlUmVzdG9yZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uIiwiZ2V0VGl0bGUiLCJnZXREZWZhdWx0VGl0bGUiLCJiZWZvcmVVcGRhdGVIaXN0b3J5UGF0aCIsIm1heWJlUmVzdG9yZVJlZGlyZWN0UGF0aEhhc2hfIiwiaGlzdG9yeVN0YXRlIiwidXBkYXRlSGlzdG9yeV8iLCJiZWZvcmVVcGRhdGVIaXN0b3J5U3RhdGUiLCJwYXJhbXMiLCJzdXJmYWNlQ29udGVudCIsImdldFN1cmZhY2VDb250ZW50IiwicmVsb2FkIiwic3VyZmFjZUlkIiwiZGlzcG9zZSIsInJlcGxhY2VTdGF0ZSIsInJlbW92ZVBhdGhUcmFpbGluZ1NsYXNoIiwib25Eb2NTdWJtaXREZWxlZ2F0ZV8iLCJvbkRvY0NsaWNrRGVsZWdhdGVfIiwic3luYyIsInRpdGxlTm9kZSIsIkFqYXgiLCJhbGxIZWFkZXJzIiwiaGVhZGVycyIsInBhaXJzIiwiYm9keSIsIm9wdF9oZWFkZXJzIiwib3B0X3BhcmFtcyIsIm9wdF90aW1lb3V0Iiwib3B0X3N5bmMiLCJvcHRfd2l0aENyZWRlbnRpYWxzIiwicmVxdWVzdCIsIlhNTEh0dHBSZXF1ZXN0IiwicHJldmlvdXNSZWFkeVN0YXRlIiwiUHJvbWlzZSIsIm9ubG9hZCIsImFib3J0ZWQiLCJvbmVycm9yIiwicmVhZHlTdGF0ZSIsInRlcm1pbmF0ZWRQcmVtYXR1cmVseSIsImFib3J0IiwidGltZW91dCIsImFkZFBhcmFtZXRlcnNGcm9tTXVsdGlNYXAiLCJ3aXRoQ3JlZGVudGlhbHMiLCJzZXRSZXF1ZXN0SGVhZGVyIiwic2VuZCIsImVycm9ycyIsIklOVkFMSURfU1RBVFVTIiwiUkVRVUVTVF9FUlJPUiIsIlJFUVVFU1RfVElNRU9VVCIsIlJFUVVFU1RfUFJFTUFUVVJFX1RFUk1JTkFUSU9OIiwiVUEiLCJuYXZpZ2F0b3IiLCJ1c2VyQWdlbnQiLCJwbGF0Zm9ybSIsImlzTWFjIiwibWF0Y2hQbGF0Zm9ybSIsImlzV2luIiwiaXNPcGVyYSIsIm1hdGNoVXNlckFnZW50IiwiaXNJZSIsImlzRWRnZSIsImlzSWVPckVkZ2UiLCJpc0Nocm9tZSIsImlzU2FmYXJpIiwiaXNGaXJlZm94IiwidGVzdFVzZXJBZ2VudCIsImdldE5hdGl2ZVVzZXJBZ2VudCIsImdldE5hdGl2ZVBsYXRmb3JtIiwiUmVxdWVzdFNjcmVlbiIsImh0dHBIZWFkZXJzIiwiaHR0cE1ldGhvZCIsIkdFVCIsInN0YXR1cyIsImlzVmFsaWRSZXNwb25zZVN0YXR1c0NvZGUiLCJpbnZhbGlkU3RhdHVzIiwic3RhdHVzQ29kZSIsImdldFJlcXVlc3RQYXRoIiwic2V0UHJvdG9jb2wiLCJtYWtlVW5pcXVlIiwiZ2V0UmVxdWVzdCIsInJlcXVlc3RQYXRoIiwicmVzcG9uc2VVcmwiLCJtYXliZUV4dHJhY3RSZXNwb25zZVVybEZyb21SZXF1ZXN0IiwicmVtb3ZlVW5pcXVlIiwiZm9ybUVsZW1lbnQiLCJzdWJtaXR0ZWRCdXR0b25FbGVtZW50IiwiZm9ybURhdGEiLCJGb3JtRGF0YSIsIm1heWJlQXBwZW5kU3VibWl0QnV0dG9uVmFsdWVfIiwiZ2V0Q2FjaGUiLCJoZWFkZXIiLCJhZGRTYWZhcmlYSFJQb2x5ZmlsbCIsImdldEZvcm1EYXRhIiwiUE9TVCIsImZvcm1hdExvYWRQYXRoIiwicmVtb3ZlU2FmYXJpWEhSUG9seWZpbGwiLCJzZXRSZXF1ZXN0IiwieGhyIiwiYXNzZXJ0VmFsaWRSZXNwb25zZVN0YXR1c0NvZGUiLCJhZGRDYWNoZSIsInJlc3BvbnNlVGV4dCIsInJlcXVlc3RFcnJvciIsInJlcXVlc3RQcmVtYXR1cmVUZXJtaW5hdGlvbiIsInJlc3BvbnNlVVJMIiwiZ2V0UmVzcG9uc2VIZWFkZXIiLCJYX1JFUVVFU1RfVVJMX0hFQURFUiIsImlucHV0cyIsImlucHV0IiwiZmlsZXMiLCJIdG1sU2NyZWVuIiwibWV0YVRhZ3NTZWxlY3RvciIsInRpdGxlU2VsZWN0b3IiLCJyZWxlYXNlVmlydHVhbERvY3VtZW50IiwicGVuZGluZ1N0eWxlcyIsInZpcnR1YWxEb2N1bWVudCIsImNvcHlOb2RlQXR0cmlidXRlc0Zyb21Db250ZW50XyIsIm5ld1N0eWxlIiwiaXNUZW1wb3JhcnlTdHlsZSIsInN0eWxlc1RlbXBvcmFyeSIsInN0eWxlSW5Eb2MiLCJpbnNlcnRCZWZvcmUiLCJuZXh0U2libGluZyIsImJvZHlTdXJmYWNlIiwicGxhY2Vob2xkZXIiLCJ0ZW1wTm9kZSIsImNyZWF0ZVJhbmdlIiwiY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50IiwiY2xlYXJOb2RlQXR0cmlidXRlcyIsImNvcHlOb2RlQXR0cmlidXRlcyIsImRpc3Bvc2VQZW5kaW5nU3R5bGVzIiwicmVtb3ZlRWxlbWVudHNGcm9tRG9jdW1lbnQiLCJldmFsdWF0ZVRyYWNrZWRTY3JpcHRzIiwiZXZhbHVhdGVUcmFja2VkUmVzb3VyY2VzXyIsInNjcmlwdHNUZW1wb3JhcnkiLCJzY3JpcHRzUGVybWFuZW50IiwiZXZhbHVhdGVUcmFja2VkU3R5bGVzIiwicnVuU3R5bGVzSW5FbGVtZW50Iiwic3R5bGVzUGVybWFuZW50IiwiYXBwZW5kU3R5bGVJbnRvRG9jdW1lbnRfIiwicmVzb3VyY2VzSW5WaXJ0dWFsIiwidmlydHVhbFF1ZXJ5U2VsZWN0b3JBbGxfIiwiZmF2aWNvbiIsInJlc291cmNlc0luRG9jdW1lbnQiLCJxdWVyeVNlbGVjdG9yQWxsXyIsInJ1bkZhdmljb25JbkVsZW1lbnRfIiwiZXZhbHVhdG9yRm4iLCJzZWxlY3RvclRlbXBvcmFyeSIsInNlbGVjdG9yUGVybWFuZW50Iiwib3B0X2FwcGVuZFJlc291cmNlRm4iLCJ0cmFja2VkIiwidGVtcG9yYXJpZXNJbkRvYyIsInBlcm1hbmVudHNJbkRvYyIsInJlc291cmNlIiwicmVzb3VyY2VLZXkiLCJnZXRSZXNvdXJjZUtleV8iLCJwZXJtYW5lbnRSZXNvdXJjZXNJbkRvYyIsImZyYWciLCJldmFsdWF0ZUZhdmljb25fIiwidXBkYXRlTWV0YVRhZ3NfIiwiY3VycmVudE1ldGFOb2RlcyIsIm1ldGFzRnJvbVZpcnR1YWxEb2N1bWVudCIsIm1ldGEiLCJhbGxvY2F0ZVZpcnR1YWxEb2N1bWVudEZvckNvbnRlbnQiLCJyZXNvbHZlVGl0bGVGcm9tVmlydHVhbERvY3VtZW50IiwicmVzb2x2ZU1ldGFUYWdzRnJvbVZpcnR1YWxEb2N1bWVudCIsImFzc2VydFNhbWVCb2R5SWRJblZpcnR1YWxEb2N1bWVudCIsIm1ha2VUZW1wb3JhcnlTdHlsZXNIcmVmc1VuaXF1ZV8iLCJyZXBsYWNlU3R5bGVBbmRNYWtlVW5pcXVlXyIsInJlcGxhY2VDaGlsZCIsInNldEVsZW1lbnRXaXRoUmFuZG9tSHJlZiIsInNldFRpdGxlIiwidGV4dENvbnRlbnQiLCJzZXRNZXRhcyIsImlnbm9yZUZhdmljb24iLCJBcHBEYXRhQXR0cmlidXRlSGFuZGxlciIsImFwcCIsImJhc2VFbGVtZW50IiwiaGFzQXR0cmlidXRlIiwiZGF0YUF0dHJpYnV0ZXMiLCJtYXliZUFkZFJvdXRlc18iLCJtYXliZUFkZFN1cmZhY2VzXyIsIm1heWJlU2V0QmFzZVBhdGhfIiwibWF5YmVTZXRMaW5rU2VsZWN0b3JfIiwibWF5YmVTZXRMb2FkaW5nQ3NzQ2xhc3NfIiwibWF5YmVTZXRVcGRhdGVTY3JvbGxQb3NpdGlvbl8iLCJtYXliZURpc3BhdGNoXyIsInJvdXRlc1NlbGVjdG9yIiwicXVlcnlTZWxlY3RvckFsbEFzQXJyYXlfIiwibWF5YmVQYXJzZUxpbmtSb3V0ZV8iLCJoYXNSb3V0ZXMiLCJhZGRSb3V0ZXMiLCJzdXJmYWNlc1NlbGVjdG9yIiwic3VyZmFjZUVsZW1lbnQiLCJ1cGRhdGVFbGVtZW50SWRJZlNwZWNpYWxTdXJmYWNlXyIsImFkZFN1cmZhY2VzIiwiZGlzcGF0Y2giLCJtYXliZVBhcnNlTGlua1JvdXRlUGF0aF8iLCJtYXliZVBhcnNlTGlua1JvdXRlSGFuZGxlcl8iLCJnZXRQYXRoIiwiZ2V0QXR0cmlidXRlIiwiZ2V0T2JqZWN0QnlOYW1lIiwic2V0QmFzZVBhdGgiLCJzZXRMb2FkaW5nQ3NzQ2xhc3MiLCJzZXRVcGRhdGVTY3JvbGxQb3NpdGlvbiIsImRhdGFBdHRyaWJ1dGVIYW5kbGVyIiwic2V0QmFzZUVsZW1lbnQiLCJoYW5kbGUiLCJ2ZXJzaW9uIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkE7Ozs7O0FBS0E7Ozs7Ozs7Ozs7OztBQVlBOzs7OztBQU9BOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkE7Ozs7Ozs7QUFTQTs7QUFVQSxBQVdBOzs7Ozs7O0FBT0E7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"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3517c31..a1a4b21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "senna", - "version": "2.7.8", + "version": "2.7.9", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 77df38c..d93c474 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "senna", - "version": "2.7.8", + "version": "2.7.9", "description": "A blazing-fast Single Page Application engine", "license": "BSD-3-Clause", "repository": "liferay/senna.js",