diff --git a/build/amd/metal-path-parser/src/pathParser.js b/build/amd/metal-path-parser/src/pathParser.js index 79b00ac..3687bdb 100644 --- a/build/amd/metal-path-parser/src/pathParser.js +++ b/build/amd/metal-path-parser/src/pathParser.js @@ -77,7 +77,7 @@ define(['exports', 'metal/src/metal'], function (exports, _metal) { * @return {string} */ function escape(str) { - return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1'); + return str.replace(/([.+*?=^!:()[\]|\/\\])/g, '\\$1'); } /** diff --git a/build/amd/senna/src/senna.js b/build/amd/senna/src/senna.js index 4b90145..e2dfcf3 100644 --- a/build/amd/senna/src/senna.js +++ b/build/amd/senna/src/senna.js @@ -1,10 +1,10 @@ -define(['exports', './utils/utils', './app/dataAttributeHandler', './app/App', './screen/HtmlScreen', './screen/RequestScreen', './route/Route', './screen/Screen'], function (exports, _utils, _dataAttributeHandler, _App, _HtmlScreen, _RequestScreen, _Route, _Screen) { +define(['exports', './utils/utils', './app/dataAttributeHandler', './app/App', './screen/HtmlScreen', './screen/RequestScreen', './route/Route', './screen/Screen', './version'], function (exports, _utils, _dataAttributeHandler, _App, _HtmlScreen, _RequestScreen, _Route, _Screen, _version) { 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); - exports.Screen = exports.RequestScreen = exports.Route = exports.HtmlScreen = exports.App = exports.utils = exports.dataAttributeHandler = undefined; + exports.version = exports.Screen = exports.RequestScreen = exports.Route = exports.HtmlScreen = exports.App = exports.utils = exports.dataAttributeHandler = undefined; var _utils2 = _interopRequireDefault(_utils); @@ -20,6 +20,8 @@ define(['exports', './utils/utils', './app/dataAttributeHandler', './app/App', ' var _Screen2 = _interopRequireDefault(_Screen); + var _version2 = _interopRequireDefault(_version); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj @@ -34,5 +36,6 @@ define(['exports', './utils/utils', './app/dataAttributeHandler', './app/App', ' exports.Route = _Route2.default; exports.RequestScreen = _RequestScreen2.default; exports.Screen = _Screen2.default; + exports.version = _version2.default; }); //# sourceMappingURL=senna.js.map diff --git a/build/amd/senna/src/senna.js.map b/build/amd/senna/src/senna.js.map index 19ced12..e76cbe3 100644 --- a/build/amd/senna/src/senna.js.map +++ b/build/amd/senna/src/senna.js.map @@ -1 +1 @@ -{"version":3,"sources":["senna.js"],"names":["dataAttributeHandler","utils","App","HtmlScreen","Route","RequestScreen","Screen"],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAWSA,oB;UAAsBC,K;UAAOC,G;UAAKC,U;UAAYC,K;UAAOC,a;UAAeC,M","file":"src/senna.js","sourcesContent":["'use strict';\n\nimport utils from './utils/utils';\nimport dataAttributeHandler from './app/dataAttributeHandler';\nimport App from './app/App';\nimport HtmlScreen from './screen/HtmlScreen';\nimport RequestScreen from './screen/RequestScreen';\nimport Route from './route/Route';\nimport Screen from './screen/Screen';\n\nexport default App;\nexport { dataAttributeHandler, utils, App, HtmlScreen, Route, RequestScreen, Screen };"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["senna.js"],"names":["dataAttributeHandler","utils","App","HtmlScreen","Route","RequestScreen","Screen","version"],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAYSA,oB;UAAsBC,K;UAAOC,G;UAAKC,U;UAAYC,K;UAAOC,a;UAAeC,M;UAAQC,O","file":"src/senna.js","sourcesContent":["'use strict';\n\nimport utils from './utils/utils';\nimport dataAttributeHandler from './app/dataAttributeHandler';\nimport App from './app/App';\nimport HtmlScreen from './screen/HtmlScreen';\nimport RequestScreen from './screen/RequestScreen';\nimport Route from './route/Route';\nimport Screen from './screen/Screen';\nimport version from './version';\n\nexport default App;\nexport { dataAttributeHandler, utils, App, HtmlScreen, Route, RequestScreen, Screen, version };"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/amd/senna/src/version.js b/build/amd/senna/src/version.js new file mode 100644 index 0000000..2b7b6f3 --- /dev/null +++ b/build/amd/senna/src/version.js @@ -0,0 +1,9 @@ +define(['exports'], function (exports) { + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.default = '2.4.2'; +}); +//# sourceMappingURL=version.js.map diff --git a/build/amd/senna/src/version.js.map b/build/amd/senna/src/version.js.map new file mode 100644 index 0000000..347d793 --- /dev/null +++ b/build/amd/senna/src/version.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["version.js"],"names":[],"mappings":";;;;;;oBAGe,gB","file":"src/version.js","sourcesContent":["/**\n * @returns String current senna version\n */\nexport default '<%= version %>';"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/globals/senna-debug.js b/build/globals/senna-debug.js index 5c0c631..28bf5e5 100644 --- a/build/globals/senna-debug.js +++ b/build/globals/senna-debug.js @@ -5575,7 +5575,7 @@ function encloseNonCapturingGroup(pattern) { * @return {string} */ function escape(str) { - return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1'); + return str.replace(/([.+*?=^!:()[\]|\/\\])/g, '\\$1'); } /** @@ -9434,6 +9434,11 @@ globals.document.addEventListener('DOMContentLoaded', function () { dataAttributeHandler.handle(); }); +/** + * @returns String current senna version + */ +var version = '2.4.2'; + exports['default'] = App$1; exports.dataAttributeHandler = dataAttributeHandler; exports.utils = utils; @@ -9442,6 +9447,7 @@ exports.HtmlScreen = HtmlScreen; exports.Route = Route; exports.RequestScreen = RequestScreen; exports.Screen = Screen; +exports.version = version; Object.defineProperty(exports, '__esModule', { value: true }); diff --git a/build/globals/senna-min.js b/build/globals/senna-min.js index 4ccd031..e2733bd 100644 --- a/build/globals/senna-min.js +++ b/build/globals/senna-min.js @@ -5,7 +5,7 @@ * @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(){throw Error("Unimplemented abstract method")}function n(){Ce=void 0}function r(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};Ce=e}function i(){return"undefined"!=typeof window&&window.__METAL_COMPATIBILITY__&&r(window.__METAL_COMPATIBILITY__),Ce}function a(e,t){return e||t}function o(e){if(!e.name){var t=e.toString();e.name=t.substring(9,t.indexOf("("))}return e.name}function s(e,t,n){var r=t+"_MERGED";if(!e.hasOwnProperty(r)){var i=e.hasOwnProperty(t)?e[t]:null;if(e.__proto__&&!e.__proto__.isPrototypeOf(Function)){var o=n||a;i=o(i,s(e.__proto__,t,o))}e[r]=i}return e[r]}function u(e,t){if(e){var n=e[Re];return t&&!e.hasOwnProperty(Re)&&(n=null),n||(e[Re]=Ae++)}return Ae++}function l(e){return e}function c(e){return"boolean"==typeof e}function h(e){return void 0!==e}function f(e){return h(e)&&!m(e)}function d(e){return e&&"object"===("undefined"==typeof e?"undefined":ge(e))&&9===e.nodeType}function v(e){return e&&"object"===("undefined"==typeof e?"undefined":ge(e))&&11===e.nodeType}function p(e){return e&&"object"===("undefined"==typeof e?"undefined":ge(e))&&1===e.nodeType}function y(e){return"function"==typeof e}function m(e){return null===e}function _(e){return"number"==typeof e}function g(e){return null!==e&&e===e.window}function k(e){var t="undefined"==typeof e?"undefined":ge(e);return"object"===t&&null!==e||"function"===t}function E(e){return e&&"object"===("undefined"==typeof e?"undefined":ge(e))&&"function"==typeof e.then}function S(e){return"string"==typeof e||e instanceof String}function b(){return"undefined"!=typeof process&&"undefined"!=typeof process.env&&"test"!==process.env.NODE_ENV&&!process.browser}function P(){}function w(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 C(e){if(y(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 w(e)}function A(e){return e=e||[],Array.isArray(e)?e:[e]}function R(e,t){if(k(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 j(e,t){return d(e)?e.documentElement.contains(t):e.contains(t)}function F(e,t,n,r,i){var a=tt[t];return a&&a.delegate&&(t=a.originalEvent,r=a.handler.bind(a,r)),i&&(r=r.bind(),r.defaultListener_=!0),D(e,t),S(n)?N(e,t,n,r):O(n,t,r),new $e(S(n)?e:n,t,r,S(n)?n:null)}function M(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||z(e,"fieldset[disabled]"))}function q(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function B(e){W(e);var t=!0,n=e.currentTarget,r=[];return t&=ie(n,e,r),t&=re(r,e),e.delegateTarget=null,e[nt]=n,t}function Q(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):V(e,t)}function V(e,t){for(var n=document.querySelectorAll(t,e.parentNode),r=0;r>>0),Le=Object.freeze({UID_PROPERTY:Re,abstractMethod:t,disableCompatibilityMode:n,enableCompatibilityMode:r,getCompatibilityModeData:i,getFunctionName:o,getStaticProperty:s,getUid:u,identityFunction:l,isBoolean:c,isDef:h,isDefAndNotNull:f,isDocument:d,isDocumentFragment:v,isElement:p,isFunction:y,isNull:m,isNumber:_,isWindow:g,isObject:k,isPromise:E,isString:S,isServerSide:b,nullFunction:P}),Te=function(){function e(){ke(this,e)}return Ee(e,null,[{key:"equal",value:function(e,t){if(e===t)return!0;if(e.length!==t.length)return!1;for(var n=0;n=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,n){for(var r=[],i=h(n)?n:e.length,a=t;a0&&void 0!==arguments[0]?arguments[0]:"";ke(this,e),this.url=e.parse(this.maybeAddProtocolAndHostname_(t))}return Ee(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_(),h(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 Ue;var n=this.url.search;n&&n.substring(1).split("&").forEach(function(n){var r=n.split("="),i=we(r,2),a=i[0],o=i[1];h(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,h(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,De.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 Fe}},{key:"parse",value:function(e){return Fe(e)}},{key:"setParseFn",value:function(e){Fe=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}}]),e}(),Qe={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"},Ve="__metal_data__",We=function(){function e(){ke(this,e)}return Ee(e,null,[{key:"get",value:function(e,t,n){return e[Ve]||(e[Ve]={}),t?(!e[Ve][t]&&n&&(e[Ve][t]=n),e[Ve][t]):e[Ve]}},{key:"has",value:function(e){return!!e[Ve]}}]),e}(),Je=function(e){function t(e,n,r){ke(this,t);var i=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return i.emitter_=e,i.event_=n,i.listener_=r,i}return be(t,e),Ee(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}(Ne),Ye=[0],ze=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.events_=null,e.listenerHandlers_=null,e.shouldUseFacade_=!1,e}return be(t,e),Ee(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=A(t);for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};Ce=e}function i(){return"undefined"!=typeof window&&window.__METAL_COMPATIBILITY__&&r(window.__METAL_COMPATIBILITY__),Ce}function a(e,t){return e||t}function o(e){if(!e.name){var t=e.toString();e.name=t.substring(9,t.indexOf("("))}return e.name}function s(e,t,n){var r=t+"_MERGED";if(!e.hasOwnProperty(r)){var i=e.hasOwnProperty(t)?e[t]:null;if(e.__proto__&&!e.__proto__.isPrototypeOf(Function)){var o=n||a;i=o(i,s(e.__proto__,t,o))}e[r]=i}return e[r]}function u(e,t){if(e){var n=e[Re];return t&&!e.hasOwnProperty(Re)&&(n=null),n||(e[Re]=Ae++)}return Ae++}function l(e){return e}function c(e){return"boolean"==typeof e}function h(e){return void 0!==e}function f(e){return h(e)&&!m(e)}function d(e){return e&&"object"===("undefined"==typeof e?"undefined":ge(e))&&9===e.nodeType}function v(e){return e&&"object"===("undefined"==typeof e?"undefined":ge(e))&&11===e.nodeType}function p(e){return e&&"object"===("undefined"==typeof e?"undefined":ge(e))&&1===e.nodeType}function y(e){return"function"==typeof e}function m(e){return null===e}function _(e){return"number"==typeof e}function g(e){return null!==e&&e===e.window}function k(e){var t="undefined"==typeof e?"undefined":ge(e);return"object"===t&&null!==e||"function"===t}function E(e){return e&&"object"===("undefined"==typeof e?"undefined":ge(e))&&"function"==typeof e.then}function S(e){return"string"==typeof e||e instanceof String}function b(){return"undefined"!=typeof process&&"undefined"!=typeof process.env&&"test"!==process.env.NODE_ENV&&!process.browser}function P(){}function w(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 C(e){if(y(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 w(e)}function A(e){return e=e||[],Array.isArray(e)?e:[e]}function R(e,t){if(k(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 j(e,t){return d(e)?e.documentElement.contains(t):e.contains(t)}function F(e,t,n,r,i){var a=tt[t];return a&&a.delegate&&(t=a.originalEvent,r=a.handler.bind(a,r)),i&&(r=r.bind(),r.defaultListener_=!0),D(e,t),S(n)?N(e,t,n,r):O(n,t,r),new $e(S(n)?e:n,t,r,S(n)?n:null)}function M(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||z(e,"fieldset[disabled]"))}function q(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function B(e){W(e);var t=!0,n=e.currentTarget,r=[];return t&=ie(n,e,r),t&=re(r,e),e.delegateTarget=null,e[nt]=n,t}function Q(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):V(e,t)}function V(e,t){for(var n=document.querySelectorAll(t,e.parentNode),r=0;r>>0),Le=Object.freeze({UID_PROPERTY:Re,abstractMethod:t,disableCompatibilityMode:n,enableCompatibilityMode:r,getCompatibilityModeData:i,getFunctionName:o,getStaticProperty:s,getUid:u,identityFunction:l,isBoolean:c,isDef:h,isDefAndNotNull:f,isDocument:d,isDocumentFragment:v,isElement:p,isFunction:y,isNull:m,isNumber:_,isWindow:g,isObject:k,isPromise:E,isString:S,isServerSide:b,nullFunction:P}),Te=function(){function e(){ke(this,e)}return Ee(e,null,[{key:"equal",value:function(e,t){if(e===t)return!0;if(e.length!==t.length)return!1;for(var n=0;n=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,n){for(var r=[],i=h(n)?n:e.length,a=t;a0&&void 0!==arguments[0]?arguments[0]:"";ke(this,e),this.url=e.parse(this.maybeAddProtocolAndHostname_(t))}return Ee(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_(),h(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 Ue;var n=this.url.search;n&&n.substring(1).split("&").forEach(function(n){var r=n.split("="),i=we(r,2),a=i[0],o=i[1];h(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,h(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,De.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 Fe}},{key:"parse",value:function(e){return Fe(e)}},{key:"setParseFn",value:function(e){Fe=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}}]),e}(),Qe={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"},Ve="__metal_data__",We=function(){function e(){ke(this,e)}return Ee(e,null,[{key:"get",value:function(e,t,n){return e[Ve]||(e[Ve]={}),t?(!e[Ve][t]&&n&&(e[Ve][t]=n),e[Ve][t]):e[Ve]}},{key:"has",value:function(e){return!!e[Ve]}}]),e}(),Je=function(e){function t(e,n,r){ke(this,t);var i=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return i.emitter_=e,i.event_=n,i.listener_=r,i}return be(t,e),Ee(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}(Ne),Ye=[0],ze=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.events_=null,e.listenerHandlers_=null,e.shouldUseFacade_=!1,e}return be(t,e),Ee(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=A(t);for(var n=0;n0?this.unhandledRejectionId_=0:0===Ct.UNHANDLED_REJECTION_DELAY&&(this.hadUnhandledRejection_=!1);try{var n=this;e.call(t,function(e){n.resolve_(Ct.State_.FULFILLED,e)},function(e){n.resolve_(Ct.State_.REJECTED,e)})}catch(r){this.resolve_(Ct.State_.REJECTED,r)}};ht.UNHANDLED_REJECTION_DELAY=0,ht.State_={PENDING:0,BLOCKED:1,FULFILLED:2,REJECTED:3},ht.CallbackEntry_=null,ht.resolve=function(e){return new ht(function(t){t(e)})},ht.reject=function(e){return new ht(function(t,n){n(e)})},ht.race=function(e){return new ht(function(t,n){e.length||t(void 0);for(var r,i=0;r=e[i];i++)r.then(t,n)})},ht.all=function(e){return new ht(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(ct(o,u),s)})},ht.firstFulfilled=function(e){return new ht(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,ct(s,u))})},ht.prototype.then=function(e,t,n){return this.addChildPromise_(y(e)?e:null,y(t)?t:null,n)},lt.addImplementation(ht),ht.prototype.thenAlways=function(e,t){var n=function(){try{e.call(t)}catch(n){ht.handleRejection_.call(null,n)}};return this.addCallbackEntry_({child:null,onRejected:n,onFulfilled:n}),this},ht.prototype.thenCatch=function(e,t){return this.addChildPromise_(null,e,t)},ht.prototype["catch"]=ht.prototype.thenCatch,ht.prototype.cancel=function(e){this.state_===ht.State_.PENDING&&Oe.run(function(){var t=new ht.CancellationError(e);t.IS_CANCELLATION_ERROR=!0,this.cancelInternal_(t)},this)},ht.prototype.cancelInternal_=function(e){this.state_===ht.State_.PENDING&&(this.parent_?this.parent_.cancelChild_(this,e):this.resolve_(ht.State_.REJECTED,e))},ht.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_===ht.State_.PENDING&&1===r)this.cancelInternal_(t);else{var s=this.callbackEntries_.splice(i,1)[0];this.executeCallback_(s,ht.State_.REJECTED,t)}}},ht.prototype.addCallbackEntry_=function(e){this.callbackEntries_&&this.callbackEntries_.length||this.state_!==ht.State_.FULFILLED&&this.state_!==ht.State_.REJECTED||this.scheduleCallbacks_(),this.callbackEntries_||(this.callbackEntries_=[]),this.callbackEntries_.push(e)},ht.prototype.addChildPromise_=function(e,t,n){var r={child:null,onFulfilled:null,onRejected:null};return r.child=new ht(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);!h(r)&&e.IS_CANCELLATION_ERROR?a(e):i(r)}catch(o){a(o)}}:a}),r.child.parent_=this,this.addCallbackEntry_(r),r.child},ht.prototype.unblockAndFulfill_=function(e){if(this.state_!==ht.State_.BLOCKED)throw new Error("CancellablePromise is not blocked.");this.state_=ht.State_.PENDING,this.resolve_(ht.State_.FULFILLED,e)},ht.prototype.unblockAndReject_=function(e){if(this.state_!==ht.State_.BLOCKED)throw new Error("CancellablePromise is not blocked.");this.state_=ht.State_.PENDING,this.resolve_(ht.State_.REJECTED,e)},ht.prototype.resolve_=function(e,t){if(this.state_===ht.State_.PENDING){if(this===t)e=ht.State_.REJECTED,t=new TypeError("CancellablePromise cannot resolve to itself");else{if(lt.isImplementedBy(t))return t=t,this.state_=ht.State_.BLOCKED,void t.then(this.unblockAndFulfill_,this.unblockAndReject_,this);if(k(t))try{var n=t.then;if(y(n))return void this.tryThen_(t,n)}catch(r){e=ht.State_.REJECTED,t=r}}this.result_=t,this.state_=e,this.scheduleCallbacks_(),e!==ht.State_.REJECTED||t.IS_CANCELLATION_ERROR||ht.addUnhandledRejection_(this,t)}},ht.prototype.tryThen_=function(e,t){this.state_=ht.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)}},ht.prototype.scheduleCallbacks_=function(){this.executing_||(this.executing_=!0,Oe.run(this.executeCallbacks_,this))},ht.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===ht.UNHANDLED_REJECTION_DELAY)for(e=this;e&&e.hadUnhandledRejection_;e=e.parent_)e.hadUnhandledRejection_=!1},ht.addUnhandledRejection_=function(e,t){ht.UNHANDLED_REJECTION_DELAY>0?e.unhandledRejectionId_=setTimeout(function(){ht.handleRejection_.call(null,t)},ht.UNHANDLED_REJECTION_DELAY):0===ht.UNHANDLED_REJECTION_DELAY&&(e.hadUnhandledRejection_=!0,Oe.run(function(){e.hadUnhandledRejection_&&ht.handleRejection_.call(null,t)}))},ht.handleRejection_=Oe.throwException,ht.setUnhandledRejectionHandler=function(e){ht.handleRejection_=e},ht.CancellationError=function(e){function t(e){ke(this,t);var n=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return e&&(n.message=e),n}return be(t,e),t}(Error),ht.CancellationError.prototype.name="cancel";var ft=/([\/])?(?:(?:\:(\w+)(?:\(((?:\\.|[^\\()])*)\))?|\(((?:\\.|[^\\()])+)\))([+*?])?)/g,dt=function(){function e(t,n){if(ke(this,e),!f(t))throw new Error("Route path not specified.");if(!y(n))throw new Error("Route handler is not a function.");this.handler=n,this.path=t}return Ee(e,[{key:"buildParsedData_",value:function(){if(!this.parsedData_){var e=pe(this.path),t=ye(e);this.parsedData_={regex:t,tokens:e}}return this.parsedData_}},{key:"extractParams",value:function(e){return S(this.path)?me(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 y(t)?t(e):(S(t)&&(t=this.buildParsedData_().regex),t instanceof RegExp&&e.search(t)>-1)}}]),e}(),vt=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.cache=null,e.cacheable=!1,e}return be(t,e),Ee(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}(Ne),pt=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.id=e.makeId_(u()),e.title=null,e}return be(t,e),Ee(t,[{key:"activate",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(){Se(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&&at.runScriptsInElement(e[t].activeChild)}),ht.resolve()}},{key:"evaluateStyles",value:function(){return ht.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)}),ht.all(n)}},{key:"getId",value:function(){return this.id}},{key:"getSurfaceContent",value:function(){}},{key:"getTitle",value:function(){return this.title}},{key:"load",value:function(){return ht.resolve()}},{key:"makeId_",value:function(e){return"screen_"+e}},{key:"setId",value:function(e){this.id=e}},{key:"setTitle",value:function(e){this.title=e}},{key:"toString",value:function(){return this.id}}]),t}(vt);pt.isImplementedBy=function(e){return e instanceof pt};var yt=function(e){function t(e){ke(this,t);var n=Pe(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 be(t,e),Ee(t,[{key:"addContent",value:function(e,t){var n=this.defaultChild;f(t)&&(n=this.getChild(e),n?K(n):(n=this.createChild(e),this.transition(n,null)),U(n,t));var r=this.getElement();return r&&n&&U(r,n),n}},{key:"createChild",value:function(e){var t=_e.document.createElement("div");return t.setAttribute("id",this.makeId_(e)),t}},{key:"getChild",value:function(e){return _e.document.getElementById(this.makeId_(e))}},{key:"getElement",value:function(){return this.element?this.element:(this.element=_e.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=_e.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&&q(t)})}},{key:"remove",value:function(e){var t=this.getChild(e);t&&q(t)}},{key:"toString",value:function(){return this.id}},{key:"transition",value:function(e,n){var r=this.transitionFn||t.defaultTransition;return ht.resolve(r.call(this,e,n))}}]),t}(Ne);yt.DEFAULT="default",yt.defaultTransition=function(e,t){e&&(e.style.display="none",e.classList.remove("flipped")),t&&(t.style.display="block",t.classList.add("flipped"))};var mt=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.activeScreen=null,e.activePath=null,e.allowPreventNavigate=!0,e.basePath="",e.browserPathBeforeNavigate=Be.getCurrentBrowserPathWithoutHash(),e.captureScrollPositionFromScrollEvent=!0,e.defaultTitle=_e.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 _e.window.history,e.isNavigationPending=!1,e.pendingNavigate=null,e.popstateScrollLeft=0,e.popstateScrollTop=0,e.redirectPath=null,e.routes=[],e.screens={},e.skipLoadPopstate=!1,e.surfaces={},e.updateScrollPosition=!0,e.appEventHandlers_=new Ke,e.appEventHandlers_.add(J(_e.window,"scroll",ue(e.onScroll_.bind(e),100)),J(_e.window,"load",e.onLoad_.bind(e)),J(_e.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 be(t,e),Ee(t,[{key:"addRoutes",value:function(e){var t=this;return Array.isArray(e)||(e=[e]),e.forEach(function(e){e instanceof dt||(e=new dt(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){S(e)&&(e=new yt(e)),t.surfaces[e.getId()]=e}),this}},{key:"canNavigate",value:function(e){var t=Be.isWebUri(e);if(!t)return!1;var n=Be.getUrlPath(e);return!!this.isLinkSameOrigin_(t.getHostname())&&(!!this.isSameBasePath_(n)&&((!t.getHash()||!Be.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.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===pt||pt.isImplementedBy(r.prototype)?new r:r(t)||new pt}return n}},{key:"disposeInternal",value:function(){this.activeScreen&&this.removeScreen(this.activePath),this.clearScreensCache(),this.formEventHandler_.removeListener(),this.linkEventHandler_.removeListener(),this.appEventHandlers_.removeAllListeners(),Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"disposeInternal",this).call(this)}},{key:"dispatch",value:function(){return this.navigate(Be.getCurrentBrowserPath(),!0)}},{key:"doNavigate_",value:function(e,t){var n=this;if(this.activeScreen&&this.activeScreen.beforeDeactivate())return this.pendingNavigate=ht.reject(new ht.CancellationError("Cancelled by active screen")),this.pendingNavigate;var r=this.findRoute(e);if(!r)return this.pendingNavigate=ht.reject(new ht.CancellationError("No route for "+e)),this.pendingNavigate;this.stopPendingNavigate_(),this.isNavigationPending=!0;var i=this.createScreenInstance(e,r);return i.load(e).then(function(){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})}},{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=Be.getCurrentBrowserPathWithoutHash(),this.screens[e]=t,this.isNavigationPending=!1,this.pendingNavigate=null,_e.capturedFormElement=null,_e.capturedFormButtonElement=null}},{key:"findRoute",value:function(e){e=this.getRoutePath(e);for(var t=0;t0}},{key:"isLinkSameOrigin_",value:function(e){return e===_e.window.location.hostname}},{key:"isSameBasePath_",value:function(e){return 0===e.indexOf(this.basePath)}},{key:"lockHistoryScrollPosition_",value:function(){var e=_e.window.history.state;if(e){var t=!1,n=function r(){_e.document.removeEventListener("scroll",r,!1),t||(_e.window.scrollTo(e.scrollLeft,e.scrollTop),t=!0)};Oe.nextTick(n),_e.document.addEventListener("scroll",n,!1)}}},{key:"maybeDisableNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&(this.nativeScrollRestoration_=_e.window.history.scrollRestoration,_e.window.history.scrollRestoration="manual")}},{key:"maybeNavigate_",value:function(e,t){if(this.canNavigate(e)){_e.capturedFormElement=t.capturedFormElement,_e.capturedFormButtonElement=t.capturedFormButtonElement;var n=!1;try{this.navigate(Be.getUrlPath(e),!1,t)}catch(r){n=!0}n||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:"maybeRepositionScrollToHashedAnchor",value:function(){var e=_e.window.location.hash;if(e){var t=_e.document.getElementById(e.substring(1));if(t){var n=Be.getNodeOffset(t),r=n.offsetLeft,i=n.offsetTop;_e.window.scrollTo(r,i)}}}},{key:"maybeRestoreNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&this.nativeScrollRestoration_&&(_e.window.history.scrollRestoration=this.nativeScrollRestoration_)}},{key:"maybeRestoreRedirectPathHash_",value:function(e,t,n){return t===Be.getUrlPathWithoutHash(e)?t+n:t}},{key:"maybeUpdateScrollPositionState_",value:function(){var e=_e.window.location.hash,t=_e.document.getElementById(e.substring(1));if(t){var n=Be.getNodeOffset(t),r=n.offsetLeft,i=n.offsetTop;this.saveHistoryCurrentPageScrollPosition_(i,r)}}},{key:"navigate",value:function(e,t,n){if(!Be.isHtml5HistorySupported())throw new Error("HTML5 History is not supported. Senna will not intercept navigation.");return e===this.activePath&&(t=!0),this.emit("beforeNavigate",{event:n,path:e,replaceHistory:!!t}),this.pendingNavigate}},{key:"onBeforeNavigate_",value:function(e){_e.capturedFormElement&&(e.form=_e.capturedFormElement)}},{key:"onBeforeNavigateDefault_",value:function(e){this.pendingNavigate&&this.pendingNavigate.path===e.path||(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]";Q(_e.document.activeElement,n)?e.capturedFormButtonElement=_e.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(Be.isCurrentBrowserPath(this.browserPathBeforeNavigate))return void this.maybeRepositionScrollToHashedAnchor();var t=e.state;return t?void(t.senna&&(this.popstateScrollTop=t.scrollTop,this.popstateScrollLeft=t.scrollLeft,this.nativeScrollRestorationSupported||this.lockHistoryScrollPosition_(),this.navigate(t.path,!0))):void(_e.window.location.hash?(this.redirectPath&&!Be.isCurrentBrowserPath(this.redirectPath)&&this.reloadPage(),this.maybeRepositionScrollToHashedAnchor()):this.reloadPage())}}},{key:"onScroll_",value:function(){this.captureScrollPositionFromScrollEvent&&this.saveHistoryCurrentPageScrollPosition_(_e.window.pageYOffset,_e.window.pageXOffset)}},{key:"onStartNavigate_",value:function(e){var t=this;this.maybeDisableNativeScrollRestoration(),this.captureScrollPositionFromScrollEvent=!1,R(_e.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||($(_e.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 ht.reject(new ht.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();S(r)||(r=this.getDefaultTitle());var i=t.beforeUpdateHistoryPath(e),a={form:f(_e.capturedFormElement),path:e,redirectPath:i,scrollLeft:0,scrollTop:0,senna:!0};n&&(a.scrollTop=this.popstateScrollTop,a.scrollLeft=this.popstateScrollLeft);var o=new Me(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(){_e.window.location.reload()}},{key:"removeRoute",value:function(e){return Te.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=_e.window.history.state;if(n&&n.senna){var r=[e,t];n.scrollTop=r[0],n.scrollLeft=r[1],_e.window.history.replaceState(n,null,null)}}},{key:"setAllowPreventNavigate",value:function(e){this.allowPreventNavigate=e}},{key:"setBasePath",value:function(e){this.basePath=Be.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_=F(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_=F(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=_e.window.history.state;if(t){var n=t.scrollTop,r=t.scrollLeft,i=function(){e.updateScrollPosition&&_e.window.scrollTo(r,n)};return new ht(function(e){return i()&Oe.nextTick(function(){return i()&e()})})}}},{key:"updateHistory_",value:function(e,t,n,r){r?_e.window.history.replaceState(n,e,t):_e.window.history.pushState(n,e,t);var i=_e.document.querySelector("title");i?i.innerHTML=e:_e.document.title=e}}]),t}(ze),_t=function(){function e(){ke(this,e)}return Ee(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 ht(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(d)});if(e=new Me(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(h(r)?r:null),f(o))var d=setTimeout(function(){c.cancel("Request timeout")},o);return c}}]),e}(),gt=function At(){ke(this,At)};gt.INVALID_STATUS="Invalid status code",gt.REQUEST_ERROR="Request error",gt.REQUEST_TIMEOUT="Request timeout",gt.REQUEST_PREMATURE_TERMINATION="Request terminated prematurely";var kt=function(){function e(){ke(this,e)}return Ee(e,null,[{key:"getNativeUserAgent",value:function(){var t=e.globals.window.navigator;if(t){var n=t.userAgent;if(n)return n}return""}},{key:"getNativePlatform",value:function(){var t=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}();kt.globals={window:window},kt.testUserAgent(kt.getNativeUserAgent(),kt.getNativePlatform());var Et=function(e){function t(){ke(this,t);var e=Pe(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 be(t,e),Ee(t,[{key:"assertValidResponseStatusCode",value:function(e){if(!this.isValidResponseStatusCode(e)){var t=new Error(gt.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 Me(e);return n.setHostname(_e.window.location.hostname),n.setProtocol(_e.window.location.protocol),_e.window.location.port&&n.setPort(_e.window.location.port),kt.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),kt.isIeOrEdge&&this.httpMethod===t.GET&&(n=new Me(n).removeUnique().toString()),Be.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:"load",value:function(e){var n=this,r=this.getCache();if(f(r))return ht.resolve(r);var i=null,a=this.httpMethod,o=new Ue;Object.keys(this.httpHeaders).forEach(function(e){return o.add(e,n.httpHeaders[e])}),_e.capturedFormElement&&(i=new FormData(_e.capturedFormElement),this.maybeAppendSubmitButtonValue_(i),a=t.POST,kt.isIeOrEdge&&o.add("If-None-Match",'"0"'));var s=this.formatLoadPath(e);return _t.request(s,a,i,o,null,this.timeout).then(function(e){return 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(e.message){case gt.REQUEST_TIMEOUT:e.timeout=!0;break;case gt.REQUEST_ERROR:e.requestError=!0;break;case gt.REQUEST_PREMATURE_TERMINATION:e.requestError=!0,e.requestPrematureTermination=!0}throw e})}},{key:"maybeAppendSubmitButtonValue_",value:function(e){var t=_e.capturedFormButtonElement;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:"setHttpHeaders",value:function(e){this.httpHeaders=e}},{key:"setHttpMethod",value:function(e){this.httpMethod=e.toLowerCase()}},{key:"setRequest",value:function(e){this.request=e}},{key:"setTimeout",value:function(e){this.timeout=e}}]),t}(pt);Et.GET="get",Et.POST="post",Et.X_REQUEST_URL_HEADER="X-Request-URL";var St=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.titleSelector="title",e}return be(t,e),Ee(t,[{key:"activate",value:function(){Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"activate",this).call(this),this.releaseVirtualDocument(),this.pendingStyles=null}},{key:"allocateVirtualDocumentForContent",value:function(e){this.virtualDocument||(this.virtualDocument=_e.document.createElement("html")),this.copyNodeAttributesFromContent_(e,this.virtualDocument),this.virtualDocument.innerHTML=e}},{key:"appendStyleIntoDocument_",value:function(e){var n=Q(e,t.selectors.stylesTemporary);if(n&&this.pendingStyles.push(e),e.id){var r=_e.document.getElementById(e.id);if(r)return void r.parentNode.insertBefore(e,r.nextSibling)}_e.document.head.appendChild(e)}},{key:"assertSameBodyIdInVirtualDocument",value:function(){var e=this.virtualDocument.querySelector("body");_e.document.body.id||(_e.document.body.id="senna_surface_"+u()),e&&(e.id=_e.document.body.id)}},{key:"copyNodeAttributesFromContent_",value:function(e,t){e=e.replace(/[<]\s*html/gi,"/gi,"/senna>"),t.innerHTML=e;var n=t.querySelector("senna");n&&(Be.clearNodeAttributes(t),Be.copyNodeAttributes(n,t))}},{key:"disposeInternal",value:function(){this.disposePendingStyles(),Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"disposeInternal",this).call(this)}},{key:"disposePendingStyles",value:function(){this.pendingStyles&&this.pendingStyles.forEach(function(e){return q(e)})}},{key:"evaluateScripts",value:function(e){var n=this,r=this.evaluateTrackedResources_(at.runScriptsInElement,t.selectors.scripts,t.selectors.scriptsTemporary,t.selectors.scriptsPermanent);return r.then(function(){return Se(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_(ot.runStylesInElement,t.selectors.styles,t.selectors.stylesTemporary,t.selectors.stylesPermanent,this.appendStyleIntoDocument_.bind(this));return r.then(function(){return Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"evaluateStyles",n).call(n,e)})}},{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=x();return s.forEach(function(e){var n=o.getResourceKey_(e);t.permanentResourcesInDoc[n]||c.appendChild(e),n&&Q(e,i)&&(t.permanentResourcesInDoc[n]=!0)}),new ht(function(t){e(c,function(){u.forEach(function(e){return q(e)}),t()},a)})}},{key:"flip",value:function(e){var n=this;return Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"flip",this).call(this,e).then(function(){Be.clearNodeAttributes(document.documentElement),Be.copyNodeAttributes(n.virtualDocument,document.documentElement)})}},{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+"-"+yt.DEFAULT);return n?n.innerHTML:t.innerHTML}}},{key:"getTitleSelector",value:function(){return this.titleSelector}},{key:"load",value:function(e){var n=this;return Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"load",this).call(this,e).then(function(e){return n.allocateVirtualDocumentForContent(e),n.resolveTitleFromVirtualDocument(),n.assertSameBodyIdInVirtualDocument(),kt.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=_e.document.createElement(e.tagName);e.href=new Me(e.href).makeUnique().toString(),Be.copyNodeAttributes(e,t),e.parentNode.replaceChild(t,e),e.disabled=!0}}},{key:"virtualQuerySelectorAll_",value:function(e){return Array.prototype.slice.call(this.virtualDocument.querySelectorAll(e))}},{key:"querySelectorAll_",value:function(e){return Array.prototype.slice.call(_e.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:"setTitleSelector",value:function(e){this.titleSelector=e}}]),t}(Et);St.selectors={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]",stylesPermanent:'style[data-senna-track="permanent"],link[data-senna-track="permanent"]',stylesTemporary:'style[data-senna-track="temporary"],link[data-senna-track="temporary"]'},St.permanentResourcesInDoc={};var bt=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.app=null,e.baseElement=null,e}return be(t,e),Ee(t,[{key:"handle",value:function(){if(!p(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(Qe.senna)){if(this.app)throw new Error("Senna app was already initialized.");this.app=new mt,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 dt(/.*/,St))}},{key:"maybeAddSurfaces_",value:function(){var e=this,t="["+Qe.surface+"]";this.querySelectorAllAsArray_(t).forEach(function(t){e.updateElementIdIfSpecialSurface_(t),e.app.addSurfaces(t.id)})}},{key:"maybeDispatch_",value:function(){this.baseElement.hasAttribute(Qe.dispatch)&&this.app.dispatch()}},{key:"maybeParseLinkRoute_",value:function(e){var t=new dt(this.maybeParseLinkRoutePath_(e),this.maybeParseLinkRouteHandler_(e));this.app.addRoutes(t)}},{key:"maybeParseLinkRouteHandler_",value:function(e){var t=e.getAttribute("type");return f(t)&&(t=Ie.getObjectByName(t)),t}},{key:"maybeParseLinkRoutePath_",value:function(e){var t=e.getAttribute("href");return f(t)&&0===t.indexOf("regex:")&&(t=new RegExp(t.substring(6))),t}},{key:"maybeSetBasePath_",value:function(){var e=this.baseElement.getAttribute(Qe.basePath);f(e)&&this.app.setBasePath(e)}},{key:"maybeSetLinkSelector_",value:function(){var e=this.baseElement.getAttribute(Qe.linkSelector);f(e)&&this.app.setLinkSelector(e)}},{key:"maybeSetLoadingCssClass_",value:function(){var e=this.baseElement.getAttribute(Qe.loadingCssClass);f(e)&&this.app.setLoadingCssClass(e)}},{key:"maybeSetUpdateScrollPosition_",value:function(){var e=this.baseElement.getAttribute(Qe.updateScrollPosition);f(e)&&("false"===e?this.app.setUpdateScrollPosition(!1):this.app.setUpdateScrollPosition(!0))}},{key:"querySelectorAllAsArray_",value:function(e){return Array.prototype.slice.call(_e.document.querySelectorAll(e))}},{key:"updateElementIdIfSpecialSurface_",value:function(e){e.id||e!==_e.document.body||(e.id="senna_surface_"+u())}},{key:"setBaseElement",value:function(e){this.baseElement=e}}]),t}(Ne),Pt=new bt;_e.document.addEventListener("DOMContentLoaded",function(){Pt.setBaseElement(_e.document.body),Pt.handle()}),e["default"]=mt,e.dataAttributeHandler=Pt,e.utils=Be,e.App=mt,e.HtmlScreen=St,e.Route=dt,e.RequestScreen=Et,e.Screen=pt,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file +var lt=function(){};lt.prototype.then=function(){},lt.IMPLEMENTED_BY_PROP="$goog_Thenable",lt.addImplementation=function(e){e.prototype.then=e.prototype.then,e.prototype.$goog_Thenable=!0},lt.isImplementedBy=function(e){if(!e)return!1;try{return!!e.$goog_Thenable}catch(t){return!1}};var ct=function(e){var t=Array.prototype.slice.call(arguments,1);return function(){var n=t.slice();return n.push.apply(n,arguments),e.apply(this,n)}},ht=function At(e,t){this.state_=At.State_.PENDING,this.result_=void 0,this.parent_=null,this.callbackEntries_=null,this.executing_=!1,At.UNHANDLED_REJECTION_DELAY>0?this.unhandledRejectionId_=0:0===At.UNHANDLED_REJECTION_DELAY&&(this.hadUnhandledRejection_=!1);try{var n=this;e.call(t,function(e){n.resolve_(At.State_.FULFILLED,e)},function(e){n.resolve_(At.State_.REJECTED,e)})}catch(r){this.resolve_(At.State_.REJECTED,r)}};ht.UNHANDLED_REJECTION_DELAY=0,ht.State_={PENDING:0,BLOCKED:1,FULFILLED:2,REJECTED:3},ht.CallbackEntry_=null,ht.resolve=function(e){return new ht(function(t){t(e)})},ht.reject=function(e){return new ht(function(t,n){n(e)})},ht.race=function(e){return new ht(function(t,n){e.length||t(void 0);for(var r,i=0;r=e[i];i++)r.then(t,n)})},ht.all=function(e){return new ht(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(ct(o,u),s)})},ht.firstFulfilled=function(e){return new ht(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,ct(s,u))})},ht.prototype.then=function(e,t,n){return this.addChildPromise_(y(e)?e:null,y(t)?t:null,n)},lt.addImplementation(ht),ht.prototype.thenAlways=function(e,t){var n=function(){try{e.call(t)}catch(n){ht.handleRejection_.call(null,n)}};return this.addCallbackEntry_({child:null,onRejected:n,onFulfilled:n}),this},ht.prototype.thenCatch=function(e,t){return this.addChildPromise_(null,e,t)},ht.prototype["catch"]=ht.prototype.thenCatch,ht.prototype.cancel=function(e){this.state_===ht.State_.PENDING&&Oe.run(function(){var t=new ht.CancellationError(e);t.IS_CANCELLATION_ERROR=!0,this.cancelInternal_(t)},this)},ht.prototype.cancelInternal_=function(e){this.state_===ht.State_.PENDING&&(this.parent_?this.parent_.cancelChild_(this,e):this.resolve_(ht.State_.REJECTED,e))},ht.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_===ht.State_.PENDING&&1===r)this.cancelInternal_(t);else{var s=this.callbackEntries_.splice(i,1)[0];this.executeCallback_(s,ht.State_.REJECTED,t)}}},ht.prototype.addCallbackEntry_=function(e){this.callbackEntries_&&this.callbackEntries_.length||this.state_!==ht.State_.FULFILLED&&this.state_!==ht.State_.REJECTED||this.scheduleCallbacks_(),this.callbackEntries_||(this.callbackEntries_=[]),this.callbackEntries_.push(e)},ht.prototype.addChildPromise_=function(e,t,n){var r={child:null,onFulfilled:null,onRejected:null};return r.child=new ht(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);!h(r)&&e.IS_CANCELLATION_ERROR?a(e):i(r)}catch(o){a(o)}}:a}),r.child.parent_=this,this.addCallbackEntry_(r),r.child},ht.prototype.unblockAndFulfill_=function(e){if(this.state_!==ht.State_.BLOCKED)throw new Error("CancellablePromise is not blocked.");this.state_=ht.State_.PENDING,this.resolve_(ht.State_.FULFILLED,e)},ht.prototype.unblockAndReject_=function(e){if(this.state_!==ht.State_.BLOCKED)throw new Error("CancellablePromise is not blocked.");this.state_=ht.State_.PENDING,this.resolve_(ht.State_.REJECTED,e)},ht.prototype.resolve_=function(e,t){if(this.state_===ht.State_.PENDING){if(this===t)e=ht.State_.REJECTED,t=new TypeError("CancellablePromise cannot resolve to itself");else{if(lt.isImplementedBy(t))return t=t,this.state_=ht.State_.BLOCKED,void t.then(this.unblockAndFulfill_,this.unblockAndReject_,this);if(k(t))try{var n=t.then;if(y(n))return void this.tryThen_(t,n)}catch(r){e=ht.State_.REJECTED,t=r}}this.result_=t,this.state_=e,this.scheduleCallbacks_(),e!==ht.State_.REJECTED||t.IS_CANCELLATION_ERROR||ht.addUnhandledRejection_(this,t)}},ht.prototype.tryThen_=function(e,t){this.state_=ht.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)}},ht.prototype.scheduleCallbacks_=function(){this.executing_||(this.executing_=!0,Oe.run(this.executeCallbacks_,this))},ht.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===ht.UNHANDLED_REJECTION_DELAY)for(e=this;e&&e.hadUnhandledRejection_;e=e.parent_)e.hadUnhandledRejection_=!1},ht.addUnhandledRejection_=function(e,t){ht.UNHANDLED_REJECTION_DELAY>0?e.unhandledRejectionId_=setTimeout(function(){ht.handleRejection_.call(null,t)},ht.UNHANDLED_REJECTION_DELAY):0===ht.UNHANDLED_REJECTION_DELAY&&(e.hadUnhandledRejection_=!0,Oe.run(function(){e.hadUnhandledRejection_&&ht.handleRejection_.call(null,t)}))},ht.handleRejection_=Oe.throwException,ht.setUnhandledRejectionHandler=function(e){ht.handleRejection_=e},ht.CancellationError=function(e){function t(e){ke(this,t);var n=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return e&&(n.message=e),n}return be(t,e),t}(Error),ht.CancellationError.prototype.name="cancel";var ft=/([\/])?(?:(?:\:(\w+)(?:\(((?:\\.|[^\\()])*)\))?|\(((?:\\.|[^\\()])+)\))([+*?])?)/g,dt=function(){function e(t,n){if(ke(this,e),!f(t))throw new Error("Route path not specified.");if(!y(n))throw new Error("Route handler is not a function.");this.handler=n,this.path=t}return Ee(e,[{key:"buildParsedData_",value:function(){if(!this.parsedData_){var e=pe(this.path),t=ye(e);this.parsedData_={regex:t,tokens:e}}return this.parsedData_}},{key:"extractParams",value:function(e){return S(this.path)?me(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 y(t)?t(e):(S(t)&&(t=this.buildParsedData_().regex),t instanceof RegExp&&e.search(t)>-1)}}]),e}(),vt=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.cache=null,e.cacheable=!1,e}return be(t,e),Ee(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}(Ne),pt=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.id=e.makeId_(u()),e.title=null,e}return be(t,e),Ee(t,[{key:"activate",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(){Se(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&&at.runScriptsInElement(e[t].activeChild)}),ht.resolve()}},{key:"evaluateStyles",value:function(){return ht.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)}),ht.all(n)}},{key:"getId",value:function(){return this.id}},{key:"getSurfaceContent",value:function(){}},{key:"getTitle",value:function(){return this.title}},{key:"load",value:function(){return ht.resolve()}},{key:"makeId_",value:function(e){return"screen_"+e}},{key:"setId",value:function(e){this.id=e}},{key:"setTitle",value:function(e){this.title=e}},{key:"toString",value:function(){return this.id}}]),t}(vt);pt.isImplementedBy=function(e){return e instanceof pt};var yt=function(e){function t(e){ke(this,t);var n=Pe(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 be(t,e),Ee(t,[{key:"addContent",value:function(e,t){var n=this.defaultChild;f(t)&&(n=this.getChild(e),n?K(n):(n=this.createChild(e),this.transition(n,null)),U(n,t));var r=this.getElement();return r&&n&&U(r,n),n}},{key:"createChild",value:function(e){var t=_e.document.createElement("div");return t.setAttribute("id",this.makeId_(e)),t}},{key:"getChild",value:function(e){return _e.document.getElementById(this.makeId_(e))}},{key:"getElement",value:function(){return this.element?this.element:(this.element=_e.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=_e.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&&q(t)})}},{key:"remove",value:function(e){var t=this.getChild(e);t&&q(t)}},{key:"toString",value:function(){return this.id}},{key:"transition",value:function(e,n){var r=this.transitionFn||t.defaultTransition;return ht.resolve(r.call(this,e,n))}}]),t}(Ne);yt.DEFAULT="default",yt.defaultTransition=function(e,t){e&&(e.style.display="none",e.classList.remove("flipped")),t&&(t.style.display="block",t.classList.add("flipped"))};var mt=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.activeScreen=null,e.activePath=null,e.allowPreventNavigate=!0,e.basePath="",e.browserPathBeforeNavigate=Be.getCurrentBrowserPathWithoutHash(),e.captureScrollPositionFromScrollEvent=!0,e.defaultTitle=_e.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 _e.window.history,e.isNavigationPending=!1,e.pendingNavigate=null,e.popstateScrollLeft=0,e.popstateScrollTop=0,e.redirectPath=null,e.routes=[],e.screens={},e.skipLoadPopstate=!1,e.surfaces={},e.updateScrollPosition=!0,e.appEventHandlers_=new Ke,e.appEventHandlers_.add(J(_e.window,"scroll",ue(e.onScroll_.bind(e),100)),J(_e.window,"load",e.onLoad_.bind(e)),J(_e.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 be(t,e),Ee(t,[{key:"addRoutes",value:function(e){var t=this;return Array.isArray(e)||(e=[e]),e.forEach(function(e){e instanceof dt||(e=new dt(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){S(e)&&(e=new yt(e)),t.surfaces[e.getId()]=e}),this}},{key:"canNavigate",value:function(e){var t=Be.isWebUri(e);if(!t)return!1;var n=Be.getUrlPath(e);return!!this.isLinkSameOrigin_(t.getHostname())&&(!!this.isSameBasePath_(n)&&((!t.getHash()||!Be.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.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===pt||pt.isImplementedBy(r.prototype)?new r:r(t)||new pt}return n}},{key:"disposeInternal",value:function(){this.activeScreen&&this.removeScreen(this.activePath),this.clearScreensCache(),this.formEventHandler_.removeListener(),this.linkEventHandler_.removeListener(),this.appEventHandlers_.removeAllListeners(),Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"disposeInternal",this).call(this)}},{key:"dispatch",value:function(){return this.navigate(Be.getCurrentBrowserPath(),!0)}},{key:"doNavigate_",value:function(e,t){var n=this;if(this.activeScreen&&this.activeScreen.beforeDeactivate())return this.pendingNavigate=ht.reject(new ht.CancellationError("Cancelled by active screen")),this.pendingNavigate;var r=this.findRoute(e);if(!r)return this.pendingNavigate=ht.reject(new ht.CancellationError("No route for "+e)),this.pendingNavigate;this.stopPendingNavigate_(),this.isNavigationPending=!0;var i=this.createScreenInstance(e,r);return i.load(e).then(function(){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})}},{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=Be.getCurrentBrowserPathWithoutHash(),this.screens[e]=t,this.isNavigationPending=!1,this.pendingNavigate=null,_e.capturedFormElement=null,_e.capturedFormButtonElement=null}},{key:"findRoute",value:function(e){e=this.getRoutePath(e);for(var t=0;t0}},{key:"isLinkSameOrigin_",value:function(e){return e===_e.window.location.hostname}},{key:"isSameBasePath_",value:function(e){return 0===e.indexOf(this.basePath)}},{key:"lockHistoryScrollPosition_",value:function(){var e=_e.window.history.state;if(e){var t=!1,n=function r(){_e.document.removeEventListener("scroll",r,!1),t||(_e.window.scrollTo(e.scrollLeft,e.scrollTop),t=!0)};Oe.nextTick(n),_e.document.addEventListener("scroll",n,!1)}}},{key:"maybeDisableNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&(this.nativeScrollRestoration_=_e.window.history.scrollRestoration,_e.window.history.scrollRestoration="manual")}},{key:"maybeNavigate_",value:function(e,t){if(this.canNavigate(e)){_e.capturedFormElement=t.capturedFormElement,_e.capturedFormButtonElement=t.capturedFormButtonElement;var n=!1;try{this.navigate(Be.getUrlPath(e),!1,t)}catch(r){n=!0}n||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:"maybeRepositionScrollToHashedAnchor",value:function(){var e=_e.window.location.hash;if(e){var t=_e.document.getElementById(e.substring(1));if(t){var n=Be.getNodeOffset(t),r=n.offsetLeft,i=n.offsetTop;_e.window.scrollTo(r,i)}}}},{key:"maybeRestoreNativeScrollRestoration",value:function(){this.nativeScrollRestorationSupported&&this.nativeScrollRestoration_&&(_e.window.history.scrollRestoration=this.nativeScrollRestoration_)}},{key:"maybeRestoreRedirectPathHash_",value:function(e,t,n){return t===Be.getUrlPathWithoutHash(e)?t+n:t}},{key:"maybeUpdateScrollPositionState_",value:function(){var e=_e.window.location.hash,t=_e.document.getElementById(e.substring(1));if(t){var n=Be.getNodeOffset(t),r=n.offsetLeft,i=n.offsetTop;this.saveHistoryCurrentPageScrollPosition_(i,r)}}},{key:"navigate",value:function(e,t,n){if(!Be.isHtml5HistorySupported())throw new Error("HTML5 History is not supported. Senna will not intercept navigation.");return e===this.activePath&&(t=!0),this.emit("beforeNavigate",{event:n,path:e,replaceHistory:!!t}),this.pendingNavigate}},{key:"onBeforeNavigate_",value:function(e){_e.capturedFormElement&&(e.form=_e.capturedFormElement)}},{key:"onBeforeNavigateDefault_",value:function(e){this.pendingNavigate&&this.pendingNavigate.path===e.path||(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]";Q(_e.document.activeElement,n)?e.capturedFormButtonElement=_e.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(Be.isCurrentBrowserPath(this.browserPathBeforeNavigate))return void this.maybeRepositionScrollToHashedAnchor();var t=e.state;return t?void(t.senna&&(this.popstateScrollTop=t.scrollTop,this.popstateScrollLeft=t.scrollLeft,this.nativeScrollRestorationSupported||this.lockHistoryScrollPosition_(),this.navigate(t.path,!0))):void(_e.window.location.hash?(this.redirectPath&&!Be.isCurrentBrowserPath(this.redirectPath)&&this.reloadPage(),this.maybeRepositionScrollToHashedAnchor()):this.reloadPage())}}},{key:"onScroll_",value:function(){this.captureScrollPositionFromScrollEvent&&this.saveHistoryCurrentPageScrollPosition_(_e.window.pageYOffset,_e.window.pageXOffset)}},{key:"onStartNavigate_",value:function(e){var t=this;this.maybeDisableNativeScrollRestoration(),this.captureScrollPositionFromScrollEvent=!1,R(_e.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||($(_e.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 ht.reject(new ht.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();S(r)||(r=this.getDefaultTitle());var i=t.beforeUpdateHistoryPath(e),a={form:f(_e.capturedFormElement),path:e,redirectPath:i,scrollLeft:0,scrollTop:0,senna:!0};n&&(a.scrollTop=this.popstateScrollTop,a.scrollLeft=this.popstateScrollLeft);var o=new Me(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(){_e.window.location.reload()}},{key:"removeRoute",value:function(e){return Te.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=_e.window.history.state;if(n&&n.senna){var r=[e,t];n.scrollTop=r[0],n.scrollLeft=r[1],_e.window.history.replaceState(n,null,null)}}},{key:"setAllowPreventNavigate",value:function(e){this.allowPreventNavigate=e}},{key:"setBasePath",value:function(e){this.basePath=Be.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_=F(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_=F(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=_e.window.history.state;if(t){var n=t.scrollTop,r=t.scrollLeft,i=function(){e.updateScrollPosition&&_e.window.scrollTo(r,n)};return new ht(function(e){return i()&Oe.nextTick(function(){return i()&e()})})}}},{key:"updateHistory_",value:function(e,t,n,r){r?_e.window.history.replaceState(n,e,t):_e.window.history.pushState(n,e,t);var i=_e.document.querySelector("title");i?i.innerHTML=e:_e.document.title=e}}]),t}(ze),_t=function(){function e(){ke(this,e)}return Ee(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 ht(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(d)});if(e=new Me(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(h(r)?r:null),f(o))var d=setTimeout(function(){c.cancel("Request timeout")},o);return c}}]),e}(),gt=function Rt(){ke(this,Rt)};gt.INVALID_STATUS="Invalid status code",gt.REQUEST_ERROR="Request error",gt.REQUEST_TIMEOUT="Request timeout",gt.REQUEST_PREMATURE_TERMINATION="Request terminated prematurely";var kt=function(){function e(){ke(this,e)}return Ee(e,null,[{key:"getNativeUserAgent",value:function(){var t=e.globals.window.navigator;if(t){var n=t.userAgent;if(n)return n}return""}},{key:"getNativePlatform",value:function(){var t=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}();kt.globals={window:window},kt.testUserAgent(kt.getNativeUserAgent(),kt.getNativePlatform());var Et=function(e){function t(){ke(this,t);var e=Pe(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 be(t,e),Ee(t,[{key:"assertValidResponseStatusCode",value:function(e){if(!this.isValidResponseStatusCode(e)){var t=new Error(gt.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 Me(e);return n.setHostname(_e.window.location.hostname),n.setProtocol(_e.window.location.protocol),_e.window.location.port&&n.setPort(_e.window.location.port),kt.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),kt.isIeOrEdge&&this.httpMethod===t.GET&&(n=new Me(n).removeUnique().toString()),Be.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:"load",value:function(e){var n=this,r=this.getCache();if(f(r))return ht.resolve(r);var i=null,a=this.httpMethod,o=new Ue;Object.keys(this.httpHeaders).forEach(function(e){return o.add(e,n.httpHeaders[e])}),_e.capturedFormElement&&(i=new FormData(_e.capturedFormElement),this.maybeAppendSubmitButtonValue_(i),a=t.POST,kt.isIeOrEdge&&o.add("If-None-Match",'"0"'));var s=this.formatLoadPath(e);return _t.request(s,a,i,o,null,this.timeout).then(function(e){return 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(e.message){case gt.REQUEST_TIMEOUT:e.timeout=!0;break;case gt.REQUEST_ERROR:e.requestError=!0;break;case gt.REQUEST_PREMATURE_TERMINATION:e.requestError=!0,e.requestPrematureTermination=!0}throw e})}},{key:"maybeAppendSubmitButtonValue_",value:function(e){var t=_e.capturedFormButtonElement;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:"setHttpHeaders",value:function(e){this.httpHeaders=e}},{key:"setHttpMethod",value:function(e){this.httpMethod=e.toLowerCase()}},{key:"setRequest",value:function(e){this.request=e}},{key:"setTimeout",value:function(e){this.timeout=e}}]),t}(pt);Et.GET="get",Et.POST="post",Et.X_REQUEST_URL_HEADER="X-Request-URL";var St=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.titleSelector="title",e}return be(t,e),Ee(t,[{key:"activate",value:function(){Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"activate",this).call(this),this.releaseVirtualDocument(),this.pendingStyles=null}},{key:"allocateVirtualDocumentForContent",value:function(e){this.virtualDocument||(this.virtualDocument=_e.document.createElement("html")),this.copyNodeAttributesFromContent_(e,this.virtualDocument),this.virtualDocument.innerHTML=e}},{key:"appendStyleIntoDocument_",value:function(e){var n=Q(e,t.selectors.stylesTemporary);if(n&&this.pendingStyles.push(e),e.id){var r=_e.document.getElementById(e.id);if(r)return void r.parentNode.insertBefore(e,r.nextSibling)}_e.document.head.appendChild(e)}},{key:"assertSameBodyIdInVirtualDocument",value:function(){var e=this.virtualDocument.querySelector("body");_e.document.body.id||(_e.document.body.id="senna_surface_"+u()),e&&(e.id=_e.document.body.id)}},{key:"copyNodeAttributesFromContent_",value:function(e,t){e=e.replace(/[<]\s*html/gi,"/gi,"/senna>"),t.innerHTML=e;var n=t.querySelector("senna");n&&(Be.clearNodeAttributes(t),Be.copyNodeAttributes(n,t))}},{key:"disposeInternal",value:function(){this.disposePendingStyles(),Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"disposeInternal",this).call(this)}},{key:"disposePendingStyles",value:function(){this.pendingStyles&&this.pendingStyles.forEach(function(e){return q(e)})}},{key:"evaluateScripts",value:function(e){var n=this,r=this.evaluateTrackedResources_(at.runScriptsInElement,t.selectors.scripts,t.selectors.scriptsTemporary,t.selectors.scriptsPermanent);return r.then(function(){return Se(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_(ot.runStylesInElement,t.selectors.styles,t.selectors.stylesTemporary,t.selectors.stylesPermanent,this.appendStyleIntoDocument_.bind(this));return r.then(function(){return Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"evaluateStyles",n).call(n,e)})}},{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=x();return s.forEach(function(e){var n=o.getResourceKey_(e);t.permanentResourcesInDoc[n]||c.appendChild(e),n&&Q(e,i)&&(t.permanentResourcesInDoc[n]=!0)}),new ht(function(t){e(c,function(){u.forEach(function(e){return q(e)}),t()},a)})}},{key:"flip",value:function(e){var n=this;return Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"flip",this).call(this,e).then(function(){Be.clearNodeAttributes(document.documentElement),Be.copyNodeAttributes(n.virtualDocument,document.documentElement)})}},{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+"-"+yt.DEFAULT);return n?n.innerHTML:t.innerHTML}}},{key:"getTitleSelector",value:function(){return this.titleSelector}},{key:"load",value:function(e){var n=this;return Se(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"load",this).call(this,e).then(function(e){return n.allocateVirtualDocumentForContent(e),n.resolveTitleFromVirtualDocument(),n.assertSameBodyIdInVirtualDocument(),kt.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=_e.document.createElement(e.tagName);e.href=new Me(e.href).makeUnique().toString(),Be.copyNodeAttributes(e,t),e.parentNode.replaceChild(t,e),e.disabled=!0}}},{key:"virtualQuerySelectorAll_",value:function(e){return Array.prototype.slice.call(this.virtualDocument.querySelectorAll(e))}},{key:"querySelectorAll_",value:function(e){return Array.prototype.slice.call(_e.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:"setTitleSelector",value:function(e){this.titleSelector=e}}]),t}(Et);St.selectors={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]",stylesPermanent:'style[data-senna-track="permanent"],link[data-senna-track="permanent"]',stylesTemporary:'style[data-senna-track="temporary"],link[data-senna-track="temporary"]'},St.permanentResourcesInDoc={};var bt=function(e){function t(){ke(this,t);var e=Pe(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.app=null,e.baseElement=null,e}return be(t,e),Ee(t,[{key:"handle",value:function(){if(!p(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(Qe.senna)){if(this.app)throw new Error("Senna app was already initialized.");this.app=new mt,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 dt(/.*/,St))}},{key:"maybeAddSurfaces_",value:function(){var e=this,t="["+Qe.surface+"]";this.querySelectorAllAsArray_(t).forEach(function(t){e.updateElementIdIfSpecialSurface_(t),e.app.addSurfaces(t.id)})}},{key:"maybeDispatch_",value:function(){this.baseElement.hasAttribute(Qe.dispatch)&&this.app.dispatch()}},{key:"maybeParseLinkRoute_",value:function(e){var t=new dt(this.maybeParseLinkRoutePath_(e),this.maybeParseLinkRouteHandler_(e));this.app.addRoutes(t)}},{key:"maybeParseLinkRouteHandler_",value:function(e){var t=e.getAttribute("type");return f(t)&&(t=Ie.getObjectByName(t)),t}},{key:"maybeParseLinkRoutePath_",value:function(e){var t=e.getAttribute("href");return f(t)&&0===t.indexOf("regex:")&&(t=new RegExp(t.substring(6))),t}},{key:"maybeSetBasePath_",value:function(){var e=this.baseElement.getAttribute(Qe.basePath);f(e)&&this.app.setBasePath(e)}},{key:"maybeSetLinkSelector_",value:function(){var e=this.baseElement.getAttribute(Qe.linkSelector);f(e)&&this.app.setLinkSelector(e)}},{key:"maybeSetLoadingCssClass_",value:function(){var e=this.baseElement.getAttribute(Qe.loadingCssClass);f(e)&&this.app.setLoadingCssClass(e)}},{key:"maybeSetUpdateScrollPosition_",value:function(){var e=this.baseElement.getAttribute(Qe.updateScrollPosition);f(e)&&("false"===e?this.app.setUpdateScrollPosition(!1):this.app.setUpdateScrollPosition(!0))}},{key:"querySelectorAllAsArray_",value:function(e){return Array.prototype.slice.call(_e.document.querySelectorAll(e))}},{key:"updateElementIdIfSpecialSurface_",value:function(e){e.id||e!==_e.document.body||(e.id="senna_surface_"+u())}},{key:"setBaseElement",value:function(e){this.baseElement=e}}]),t}(Ne),Pt=new bt;_e.document.addEventListener("DOMContentLoaded",function(){Pt.setBaseElement(_e.document.body),Pt.handle()});var wt="2.4.2";e["default"]=mt,e.dataAttributeHandler=Pt,e.utils=Be,e.App=mt,e.HtmlScreen=St,e.Route=dt,e.RequestScreen=Et,e.Screen=pt,e.version=wt,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 3ebef59..f38c0c2 100644 --- a/build/globals/senna.js +++ b/build/globals/senna.js @@ -5575,7 +5575,7 @@ function encloseNonCapturingGroup(pattern) { * @return {string} */ function escape(str) { - return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1'); + return str.replace(/([.+*?=^!:()[\]|\/\\])/g, '\\$1'); } /** @@ -9434,6 +9434,11 @@ globals.document.addEventListener('DOMContentLoaded', function () { dataAttributeHandler.handle(); }); +/** + * @returns String current senna version + */ +var version = '2.4.2'; + exports['default'] = App$1; exports.dataAttributeHandler = dataAttributeHandler; exports.utils = utils; @@ -9442,6 +9447,7 @@ exports.HtmlScreen = HtmlScreen; exports.Route = Route; exports.RequestScreen = RequestScreen; exports.Screen = Screen; +exports.version = version; Object.defineProperty(exports, '__esModule', { value: true }); diff --git a/build/globals/senna.js.map b/build/globals/senna.js.map index 35d42d3..0cb2dae 100644 --- a/build/globals/senna.js.map +++ b/build/globals/senna.js.map @@ -1 +1 @@ -{"version":3,"file":"senna.js","sources":["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-dom/src/domData.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-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","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"],"sourcesContent":["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=} opt_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(opt_data = {}) {\n\tcompatibilityModeData_ = opt_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(*, *):*=} opt_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 */\nexport function getStaticProperty(ctor, propertyName, opt_mergeFn) {\n\tconst mergedName = propertyName + '_MERGED';\n\tif (!ctor.hasOwnProperty(mergedName)) {\n\t\tlet merged = ctor.hasOwnProperty(propertyName) ? ctor[propertyName] : null;\n\t\tif (ctor.__proto__ && !ctor.__proto__.isPrototypeOf(Function)) {\n\t\t\tconst mergeFn = opt_mergeFn || getFirstTruthy_;\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 `opt_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=} opt_object Optional object to be mutated with the uid. If\n * not specified this method only returns the uid.\n * @param {boolean=} opt_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 */\nexport function getUid(opt_object, opt_noInheritance) {\n\tif (opt_object) {\n\t\tlet id = opt_object[UID_PROPERTY];\n\t\tif (opt_noInheritance && !opt_object.hasOwnProperty(UID_PROPERTY)) {\n\t\t\tid = null;\n\t\t}\n\t\treturn id || (opt_object[UID_PROPERTY] = uniqueIdCounter_++);\n\t}\n\treturn uniqueIdCounter_++;\n}\n\n/**\n * The identity function. Returns its first argument.\n * @param {*=} opt_returnValue The single value that will be returned.\n * @return {?} The first argument.\n */\nexport function identityFunction(opt_returnValue) {\n\treturn opt_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 * @return {boolean}\n */\nexport function isServerSide() {\n\treturn typeof process !== 'undefined' &&\n\t\ttypeof process.env !== 'undefined' &&\n\t\tprocess.env.NODE_ENV !== 'test' &&\n\t\t!process.browser;\n}\n\n/**\n * Null function used for default values of callbacks, etc.\n * @return {void} Nothing.\n */\nexport function nullFunction() {\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 core from './coreNamed';\n\nexport default core;\nexport { core };\nexport * from './coreNamed';\n","'use strict';\n\nimport { isDef } from '../core';\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.<*>} opt_output Optional output array.\n\t * @return {Array.<*>} Flat array.\n\t */\n\tstatic flatten(arr, opt_output) {\n\t\tvar output = opt_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=} opt_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, opt_end) {\n\t\tconst sliced = [];\n\t\tconst end = isDef(opt_end) ? opt_end : arr.length;\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\nconst async = {};\n\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/**\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=} opt_context Object to use as the \"this value\" when calling\n * the provided function.\n * @template THIS\n */\nasync.run = function(callback, opt_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(\n\t\tnew async.run.WorkItem_(callback, opt_context));\n};\n\n\n/** @private {boolean} */\nasync.run.workQueueScheduled_ = false;\n\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/**\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/**\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=} opt_context Object in whose scope to call the listener.\n * @template SCOPE\n */\nasync.nextTick = function(callback, opt_context) {\n\tlet cb = callback;\n\tif (opt_context) {\n\t\tcb = callback.bind(opt_context);\n\t}\n\tcb = async.nextTick.wrapCallback_(cb);\n\t// Introduced and currently only supported by IE10.\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 setImmediate === 'function') {\n\t\tsetImmediate(cb);\n\t\treturn;\n\t}\n\t// Look for and cache the custom fallback version of setImmediate.\n\tif (!async.nextTick.setImmediate_) {\n\t\tasync.nextTick.setImmediate_ = async.nextTick.getSetImmediateEmulator_();\n\t}\n\tasync.nextTick.setImmediate_(cb);\n};\n\n\n/**\n * Cache for the setImmediate implementation.\n * @type {function(function())}\n * @private\n */\nasync.nextTick.setImmediate_ = null;\n\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 (typeof Channel === 'undefined' && typeof window !== 'undefined' &&\n\t\twindow.postMessage && window.addEventListener) {\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\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 (typeof document !== 'undefined' && 'onreadystatechange' in\n\t\tdocument.createElement('script')) {\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/**\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(opt_returnValue) {\n\treturn opt_returnValue;\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\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\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) {\n\t\tlet key, source;\n\t\tfor (let i = 1; i < arguments.length; i++) {\n\t\t\tsource = arguments[i];\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=} opt_obj 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, opt_obj) {\n\t\tconst scope = opt_obj || 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 * @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\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.replace(/[\\t\\r\\n ]+/g, ' ').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 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* 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\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\nconst METAL_DATA = '__metal_data__';\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=} opt_name Optional property from the data to be returned.\n\t * @param {*} opt_initialVal Optinal 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, opt_name, opt_initialVal) {\n\t\tif (!element[METAL_DATA]) {\n\t\t\telement[METAL_DATA] = {};\n\t\t}\n\t\tif (!opt_name) {\n\t\t\treturn element[METAL_DATA];\n\t\t}\n\t\tif (!element[METAL_DATA][opt_name] && opt_initialVal) {\n\t\t\telement[METAL_DATA][opt_name] = opt_initialVal;\n\t\t}\n\t\treturn element[METAL_DATA][opt_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\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 * @param {!EventEmitter} emitter Emitter the event was subscribed to.\n * @param {string} event The name of the event that was subscribed to.\n * @param {!Function} listener The listener subscribed to the event.\n * @constructor\n * @extends {Disposable}\n */\nclass EventHandle extends Disposable {\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 * @constructor\n * @extends {Disposable}\n */\nclass EventEmitter extends Disposable {\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} opt_default 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, opt_default) {\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, opt_default);\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} opt_default 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 * @param {Function=} opt_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, opt_default, opt_origin) {\n\t\tthis.runListenerHandlers_(event);\n\t\tif (opt_default || opt_origin) {\n\t\t\tlistener = {\n\t\t\t\tdefault: opt_default,\n\t\t\t\tfn: listener,\n\t\t\t\torigin: opt_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);\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(toArray(this.events_ && this.events_['*']));\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\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);\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 fn === listener ||\n\t\t\t(listenerObj.origin && listenerObj.origin === listener);\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\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);\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()}\n\t */\n\tonListener(handler) {\n\t\tthis.listenerHandlers_ = this.addHandler_(this.listenerHandlers_, handler);\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)=} opt_events\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveAllListeners(opt_events) {\n\t\tif (this.events_) {\n\t\t\tif (opt_events) {\n\t\t\t\tconst events = this.toEventsArray_(opt_events);\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);\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\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 * @param {EventEmitter} originEmitter Events originated on this emitter\n * will be fired for the target emitter's listeners as well.\n * @param {EventEmitter} targetEmitter Event listeners attached to this emitter\n * will also be triggered when the event is fired by the origin emitter.\n * @param {Object} opt_blacklist Optional blacklist of events that should not be\n * proxied.\n * @constructor\n * @extends {Disposable}\n */\nclass EventEmitterProxy extends Disposable {\n\tconstructor(originEmitter, targetEmitter, opt_blacklist, opt_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_ = opt_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_ = opt_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_() {\n\t\tthis.targetEmitter_.emit.apply(this.targetEmitter_, arguments);\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 = this.originEmitter_ && this.proxiedEvents_ ?\n\t\t\tObject.keys(this.proxiedEvents_) :\n\t\t\tthis.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 * @constructor\n * @extends {Disposable}\n */\nclass EventHandler extends Disposable {\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() {\n\t\tfor (let i = 0; i < arguments.length; i++) {\n\t\t\tthis.eventHandles_.push(arguments[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=} opt_selector An optional selector used when delegating\n\t * the event.\n\t * @constructor\n\t */\n\tconstructor(emitter, event, listener, opt_selector) {\n\t\tsuper(emitter, event, listener);\n\t\tthis.selector_ = opt_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) ? delegating[this.event_].selectors : 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} opt_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, opt_capture) {\n\t\tsuper(emitter, event, listener);\n\t\tthis.capture_ = opt_capture;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tremoveListener() {\n\t\tthis.emitter_.removeEventListener(this.event_, this.listener_, this.capture_);\n\t}\n}\n\nexport default DomEventHandle;\n","'use strict';\n\nimport { isDef, isDocument, isDocumentFragment, isElement, isObject, isString, object } 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 * 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 * 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 * 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 (child instanceof NodeList) {\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 * @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=} opt_default 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(element, eventName, selectorOrTarget, callback, opt_default) {\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 (opt_default) {\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 * @private\n */\nfunction isAbleToInteractWith_(node, eventName, opt_eventObj) {\n\tif (opt_eventObj && eventName === 'click' && opt_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 = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'FIELDSET'];\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 * 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 element.classList.contains(className);\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 (` ${element.className} `).indexOf(` ${className} `) >= 0;\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 * 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 = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.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 nodes = document.querySelectorAll(selector, element.parentNode);\n\tfor (let i = 0; i < nodes.length; ++i) {\n\t\tif (nodes[i] === element) {\n\t\t\treturn true;\n\t\t}\n\t}\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 */\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} opt_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, opt_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, opt_capture);\n\treturn new DomEventHandle(element, eventName, callback, opt_capture);\n}\n\n/**\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);\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 * 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 * 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 * @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.insertBefore(element2, element1);\n\t\telement1.parentNode.removeChild(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} defaultFns 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_(container, currElement, event, defaultFns);\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 (isElement(selectorOrElement) || isDocument(selectorOrElement) || isDocumentFragment(selectorOrElement)) {\n\t\treturn selectorOrElement;\n\t} else if (isString(selectorOrElement)) {\n\t\tif (selectorOrElement[0] === '#' && selectorOrElement.indexOf(' ') === -1) {\n\t\t\treturn document.getElementById(selectorOrElement.substr(1));\n\t\t} else {\n\t\t\treturn document.querySelector(selectorOrElement);\n\t\t}\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 * 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(classIndex + className.length);\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=} opt_eventObj An object with data that should be on the\n * triggered event's payload.\n */\nexport function triggerEvent(element, eventName, opt_eventObj) {\n\tif (isAbleToInteractWith_(element, eventName, opt_eventObj)) {\n\t\tconst eventObj = document.createEvent('HTMLEvents');\n\t\teventObj.initEvent(eventName, true, true);\n\t\tobject.mixin(eventObj, opt_eventObj);\n\t\telement.dispatchEvent(eventObj);\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(this.originEmitter_, eventName, selector, listener);\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 */\n\tisSupportedDomEvent_(event) {\n\t\tif (!this.originEmitter_ || !this.originEmitter_.addEventListener) {\n\t\t\treturn true;\n\t\t}\n\t\treturn (this.isDelegateEvent_(event) && event.indexOf(':', 9) !== -1) ||\n\t\t\tsupportsEvent(this.originEmitter_, event);\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 super.shouldProxyEvent_(event) && this.isSupportedDomEvent_(event);\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(type, 0, 1, type.substring(0, 1).toUpperCase());\n\t\tconst suffixes = [`${typeTitleCase}End`, `${typeTitleCase}End`, `${typeTitleCase}End`, `${type}end`];\n\t\tfor (let i = 0; i < prefixes.length; i++) {\n\t\t\tif (features.animationElement_.style[prefixes[i] + typeTitleCase] !== undefined) {\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 IE9) 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_ = document.createElement('div');\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()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic run(text, opt_appendFn) {\n\t\tconst script = document.createElement('script');\n\t\tscript.text = text;\n\t\tif (opt_appendFn) {\n\t\t\topt_appendFn(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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic runFile(src, opt_callback, opt_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\topt_callback && opt_callback();\n\t\t};\n\t\tonce(script, 'load', callback);\n\t\tonce(script, 'error', callback);\n\n\t\tif (opt_appendFn) {\n\t\t\topt_appendFn(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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic runScript(script, opt_callback, opt_appendFn) {\n\t\tconst callback = function() {\n\t\t\topt_callback && opt_callback();\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, opt_callback, opt_appendFn);\n\t\t} else {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn globalEval.run(script.text, opt_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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runScriptsInElement(element, opt_callback, opt_appendFn) {\n\t\tconst scripts = element.querySelectorAll('script');\n\t\tif (scripts.length) {\n\t\t\tglobalEval.runScriptsInOrder(scripts, 0, opt_callback, opt_appendFn);\n\t\t} else if (opt_callback) {\n\t\t\tasync.nextTick(opt_callback);\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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runScriptsInOrder(scripts, index, opt_callback, opt_appendFn) {\n\t\tglobalEval.runScript(scripts.item(index), function() {\n\t\t\tif (index < scripts.length - 1) {\n\t\t\t\tglobalEval.runScriptsInOrder(scripts, index + 1, opt_callback, opt_appendFn);\n\t\t\t} else if (opt_callback) {\n\t\t\t\tasync.nextTick(opt_callback);\n\t\t\t}\n\t\t}, opt_appendFn);\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()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic run(text, opt_appendFn) {\n\t\tconst style = document.createElement('style');\n\t\tstyle.innerHTML = text;\n\t\tif (opt_appendFn) {\n\t\t\topt_appendFn(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()=} opt_callback Optional function to be called\n\t * when the styles has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic runFile(href, opt_callback, opt_appendFn) {\n\t\tconst link = document.createElement('link');\n\t\tlink.rel = 'stylesheet';\n\t\tlink.href = href;\n\t\tglobalEvalStyles.runStyle(link, opt_callback, opt_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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic runStyle(style, opt_callback, opt_appendFn) {\n\t\tconst callback = function() {\n\t\t\topt_callback && opt_callback();\n\t\t};\n\t\tif (style.rel && style.rel !== 'stylesheet') {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn;\n\t\t}\n\n\t\tif (style.tagName === 'STYLE') {\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 (opt_appendFn) {\n\t\t\topt_appendFn(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()=} opt_callback Optional function to be called when the\n\t * style has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runStylesInElement(element, opt_callback, opt_appendFn) {\n\t\tconst styles = element.querySelectorAll('style,link');\n\t\tif (styles.length === 0 && opt_callback) {\n\t\t\tasync.nextTick(opt_callback);\n\t\t\treturn;\n\t\t}\n\n\t\tlet loadCount = 0;\n\t\tconst callback = function() {\n\t\t\tif (opt_callback && ++loadCount === styles.length) {\n\t\t\t\tasync.nextTick(opt_callback);\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, opt_appendFn);\n\t\t}\n\t}\n}\n\nexport default globalEvalStyles;\n","'use strict';\n\nimport { registerCustomEvent, contains } from './dom';\nimport features from './features';\n\nconst mouseEventMap = {\n\tmouseenter: 'mouseover',\n\tmouseleave: 'mouseout',\n\tpointerenter: 'pointerover',\n\tpointerleave: 'pointerout'\n};\nObject.keys(mouseEventMap).forEach(function(eventName) {\n\tregisterCustomEvent(eventName, {\n\t\tdelegate: true,\n\t\thandler: function(callback, event) {\n\t\t\tconst related = event.relatedTarget;\n\t\t\tconst target = event.delegateTarget;\n\t\t\tif (!related || (related !== target && !contains(target, related))) {\n\t\t\t\tevent.customType = eventName;\n\t\t\t\treturn callback(event);\n\t\t\t}\n\t\t},\n\t\toriginalEvent: mouseEventMap[eventName]\n\t});\n});\n\nconst animationEventMap = {\n\tanimation: 'animationend',\n\ttransition: 'transitionend'\n};\nObject.keys(animationEventMap).forEach(function(eventType) {\n\tconst eventName = animationEventMap[eventType];\n\tregisterCustomEvent(eventName, {\n\t\tevent: true,\n\t\tdelegate: true,\n\t\thandler: function(callback, event) {\n\t\t\tevent.customType = eventName;\n\t\t\treturn callback(event);\n\t\t},\n\t\toriginalEvent: features.checkAnimationEventName()[eventType]\n\t});\n});\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 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 * 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=} If returns true, the current screen is locked and the\n\t * 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 * 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 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 } 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\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 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 * 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.getHostname())) {\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 {\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\tif (this.activeScreen && this.activeScreen.beforeDeactivate()) {\n\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by active screen'));\n\t\t\treturn this.pendingNavigate;\n\t\t}\n\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 nextScreen.load(path)\n\t\t\t.then(() => {\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}\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 + ')');\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 hostname is an offsite link.\n\t * @param {!string} hostname Link hostname to compare with\n\t * globals.window.location.hostname.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisLinkSameOrigin_(hostname) {\n\t\treturn hostname === globals.window.location.hostname;\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 * 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\tglobals.capturedFormElement = event.capturedFormElement;\n\t\tglobals.capturedFormButtonElement = event.capturedFormButtonElement;\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) {\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 * 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\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) {\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.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) {\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\tthis.pendingNavigate = null;\n\t\t}\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\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\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\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\tvar navigator = UA.globals.window.navigator;\n\t\tif (navigator) {\n\t\t\tvar 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\tvar navigator = UA.globals.window.navigator;\n\t\tif (navigator) {\n\t\t\tvar 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 * @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 = (UA.matchUserAgent('Chrome') || UA.matchUserAgent('CriOS')) && !UA.isOpera && !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 = UA.matchUserAgent('Safari') && !(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 */\nUA.globals = {\n\twindow: window\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\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\tbody = new FormData(globals.capturedFormElement);\n\t\t\tthis.maybeAppendSubmitButtonValue_(body);\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.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\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\t * @protected\n\t */\n\tmaybeAppendSubmitButtonValue_(body) {\n\t\tconst button = globals.capturedFormButtonElement;\n\t\tif (button && button.name) {\n\t\t\tbody.append(button.name, button.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 * 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, exitDocument, 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 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\tnode.innerHTML = content;\n\t\tvar placeholder = node.querySelector('senna');\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\tthis.pendingStyles.forEach((style) => exitDocument(style));\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 * 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\ttemporariesInDoc.forEach((resource) => exitDocument(resource));\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(document.documentElement);\n\t\t\tutils.copyNodeAttributes(this.virtualDocument, document.documentElement);\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.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 * 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\tvar 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\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 selectors for tracking resources.\n * @type {object}\n * @protected\n * @static\n */\nHtmlScreen.selectors = {\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]',\n\tstylesPermanent: 'style[data-senna-track=\"permanent\"],link[data-senna-track=\"permanent\"]',\n\tstylesTemporary: 'style[data-senna-track=\"temporary\"],link[data-senna-track=\"temporary\"]'\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;"],"names":["globals","window","document","compatibilityModeData_","uniqueIdCounter_","UID_PROPERTY","Math","random","abstractMethod","Error","disableCompatibilityMode","undefined","enableCompatibilityMode","opt_data","getCompatibilityModeData","__METAL_COMPATIBILITY__","getFirstTruthy_","a","b","getFunctionName","fn","name","str","toString","substring","indexOf","getStaticProperty","ctor","propertyName","opt_mergeFn","mergedName","hasOwnProperty","merged","__proto__","isPrototypeOf","Function","mergeFn","getUid","opt_object","opt_noInheritance","id","identityFunction","opt_returnValue","isBoolean","val","isDef","isDefAndNotNull","isNull","isDocument","nodeType","isDocumentFragment","isElement","isFunction","isNumber","isWindow","isObject","type","isPromise","then","isString","String","isServerSide","process","env","NODE_ENV","browser","nullFunction","array","arr1","arr2","length","i","arr","opt_output","output","Array","isArray","flatten","push","obj","rv","removeAt","prototype","splice","call","start","opt_end","sliced","end","async","throwException","exception","nextTick","run","callback","opt_context","workQueueScheduled_","processWorkQueue","workQueue_","WorkItem_","workItems","workItem","scope","e","cb","bind","wrapCallback_","setImmediate","setImmediate_","getSetImmediateEmulator_","Channel","MessageChannel","postMessage","addEventListener","iframe","createElement","style","display","src","documentElement","appendChild","win","contentWindow","doc","open","write","close","message","origin","location","protocol","host","onmessage","data","port1","port2","channel","head","tail","next","script","onreadystatechange","parentNode","removeChild","Disposable","disposed_","disposeInternal","object","target","key","source","arguments","opt_obj","parts","split","reduce","part","mappedObj","keys","Object","obj1","obj2","keys1","keys2","string","str1","str2","test1","toLowerCase","test2","replace","x","floor","abs","Date","now","hash","len","charCodeAt","value","parseFromAnchor","opt_uri","link","href","test","TypeError","hostname","password","pathname","port","search","username","parse","URL","url","create","MultiMap","values","size","map","names","JSON","stringify","set","TreeNode","value_","parent_","children_","child","setParent","node","current","getParent","ancestors","index","getChildren","EMPTY_ARRAY","depth","root","getChildCount","remove","parent","opt_preorderFn","opt_postorderFn","forEach","traverse","assertChildHasNoParent","parseFn_","Uri","maybeAddProtocolAndHostname_","multimap","getAll","addParameterValue","ensureQueryInitialized_","query","add","param","urlDecode","getHostname","getPort","HOSTNAME_PLACEHOLDER","getHost","getProtocol","get","querystring","getParameterNames","getParameterValues","encodeURIComponent","slice","contains","setParameterValue","RANDOM_PARAM","getRandomString","DEFAULT_PROTOCOL","charAt","removeParameter","getPathname","getSearch","getHash","parseFn","basePath","paths","path","concat","join","decodeURIComponent","isSecure","utils","attributes","attribute","setAttribute","getCurrentBrowserPathWithoutHash","offsetLeft","offsetTop","offsetParent","uri","currentBrowserPath","getUrlPathWithoutHash","getUrlPath","history","pushState","err","error","removeAttribute","substr","METAL_DATA","domData","element","opt_name","opt_initialVal","EventHandle","emitter","event","listener","emitter_","event_","listener_","removeListener","isDisposed","singleArray_","EventEmitter","events_","listenerHandlers_","shouldUseFacade_","holder","handler","opt_default","validateListener_","events","toEventsArray_","addSingleListener_","opt_origin","runListenerHandlers_","addHandler_","getShouldUseFacade","facade","preventedDefault","listeners","getRawListeners_","args","runListeners_","buildFacade_","directListeners","toArray","amount","many_","self","handlerInternal","apply","listenerObj","removeMatchingListenerObjs_","addListener","many","opt_events","listenerObjs","finalListeners","matchesListener_","off","handlers","defaultListeners","default","j","shouldUseFacade","EventEmitterProxy","originEmitter","targetEmitter","opt_blacklist","opt_whitelist","blacklist_","originEmitter_","pendingEvents_","proxiedEvents_","targetEmitter_","whitelist_","startProxy_","on","removeListeners_","emit","shouldProxyEvent_","tryToAddListener_","proxyEvent","onListener","addListener_","emitOnTarget_","EventHandler","eventHandles_","DomDelegatedEventHandle","opt_selector","selector_","delegating","selector","selectors","DomEventHandle","opt_capture","capture_","removeEventListener","elementsByTag_","supportCache_","customEvents","LAST_CONTAINER","USE_CAPTURE","addClasses","elements","classes","addClassesWithNative_","className","classList","addClassesWithoutNative_","elementClassName","classesToAppend","addElementListener_","eventName","addSelectorListener_","delegatingData","addToArr_","attachDelegateEvent_","handleDelegateEvent_","closest","match","append","buildFragment","NodeList","childArr","htmlString","tempDiv","innerHTML","firstChild","fragment","createDocumentFragment","element1","element2","delegate","selectorOrTarget","customConfig","originalEvent","defaultListener_","isAbleToInteractWith_","opt_eventObj","button","matchesSelector","tagName","disabled","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","defaultPrevented","defaultFns","currElement","limit","triggerElementListeners_","triggerSelectorListeners_","lastContainer","triggerListeners_","DomEventEmitterProxy","isDelegateEvent_","babelHelpers.get","isSupportedDomEvent_","features","animationEventName_","checkAnimationEventName_","prefixes","typeTitleCase","replaceInterval","toUpperCase","suffixes","animationElement_","attrOrderChange_","originalContent","globalEval","text","opt_appendFn","opt_callback","runFile","scripts","runScriptsInOrder","runScript","item","globalEvalStyles","rel","runStyle","styles","loadCount","mouseEventMap","related","relatedTarget","customType","animationEventMap","eventType","checkAnimationEventName","Thenable","IMPLEMENTED_BY_PROP","addImplementation","$goog_Thenable","isImplementedBy","partial","newArgs","CancellablePromise","resolver","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","capture","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_","title","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","App","activeScreen","activePath","allowPreventNavigate","browserPathBeforeNavigate","captureScrollPositionFromScrollEvent","defaultTitle","formSelector","ignoreQueryStringFromRoutePath","linkSelector","loadingCssClass","nativeScrollRestorationSupported","isNavigationPending","pendingNavigate","popstateScrollLeft","popstateScrollTop","redirectPath","routes","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","beforeDeactivate","stopPendingNavigate_","nextScreen","createScreenInstance","load","deactivate","prepareNavigateHistory_","prepareNavigateSurfaces_","extractParams","evaluateStyles","flip","evaluateScripts","maybeUpdateScrollPositionState_","syncScrollPositionSyncThenAsync_","finalizeNavigate_","handleNavigateError_","getRoutePath","activate","isCacheable","capturedFormElement","capturedFormButtonElement","matchesPath","getIgnoreQueryStringFromRoutePath","getUrlPathWithoutHashAndSearch","winner","switchScrollPositionRace","scrollTo","scrollLeft","scrollTop","nativeScrollRestoration_","scrollRestoration","canNavigate","navigateFailed","preventDefault","onbeforeunload","_onbeforeunload","_overloaded","anchorElement","getNodeOffset","saveHistoryCurrentPageScrollPosition_","opt_event","isHtml5HistorySupported","form","replaceHistory","func","altKey","ctrlKey","metaKey","shiftKey","maybeNavigate_","method","buttonSelector","activeElement","querySelector","action","maybeRepositionScrollToHashedAnchor","reloadPage","senna","lockHistoryScrollPosition_","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","setHostname","setProtocol","setPort","makeUnique","getRequest","requestPath","responseUrl","maybeExtractResponseUrlFromRequest","removeUnique","getCache","header","FormData","maybeAppendSubmitButtonValue_","POST","formatLoadPath","setRequest","xhr","assertValidResponseStatusCode","addCache","responseText","requestError","requestPrematureTermination","responseURL","getResponseHeader","X_REQUEST_URL_HEADER","HtmlScreen","titleSelector","releaseVirtualDocument","pendingStyles","virtualDocument","copyNodeAttributesFromContent_","newStyle","isTemporaryStyle","stylesTemporary","styleInDoc","insertBefore","nextSibling","bodySurface","placeholder","clearNodeAttributes","copyNodeAttributes","disposePendingStyles","evaluateTrackedScripts","evaluateTrackedResources_","scriptsTemporary","scriptsPermanent","evaluateTrackedStyles","runStylesInElement","stylesPermanent","appendStyleIntoDocument_","evaluatorFn","selectorTemporary","selectorPermanent","opt_appendResourceFn","tracked","virtualQuerySelectorAll_","temporariesInDoc","querySelectorAll_","permanentsInDoc","resource","resourceKey","getResourceKey_","permanentResourcesInDoc","frag","allocateVirtualDocumentForContent","resolveTitleFromVirtualDocument","assertSameBodyIdInVirtualDocument","makeTemporaryStylesHrefsUnique_","replaceStyleAndMakeUnique_","replaceChild","setTitle","textContent","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"],"mappings":"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","preExistingComment":"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL3NyYy9nbG9iYWxzL2dsb2JhbHMuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL2NvcmVOYW1lZC5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvY29yZS5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvYXJyYXkvYXJyYXkuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL2FzeW5jL2FzeW5jLmpzIiwiL1VzZXJzL2JydW5vYmFzdG8vUHJvamVjdHMvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9kaXNwb3NhYmxlL0Rpc3Bvc2FibGUuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL29iamVjdC9vYmplY3QuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL3N0cmluZy9zdHJpbmcuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtdXJpL3NyYy9wYXJzZUZyb21BbmNob3IuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtdXJpL3NyYy9wYXJzZS5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1zdHJ1Y3RzL3NyYy9NdWx0aU1hcC5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1zdHJ1Y3RzL3NyYy9UcmVlTm9kZS5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC11cmkvc3JjL1VyaS5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL3NyYy91dGlscy91dGlscy5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL3NyYy9hcHAvZGF0YUF0dHJpYnV0ZXMuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9kb21EYXRhLmpzIiwiL1VzZXJzL2JydW5vYmFzdG8vUHJvamVjdHMvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWV2ZW50cy9zcmMvRXZlbnRIYW5kbGUuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZXZlbnRzL3NyYy9FdmVudEVtaXR0ZXIuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZXZlbnRzL3NyYy9FdmVudEVtaXR0ZXJQcm94eS5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1ldmVudHMvc3JjL0V2ZW50SGFuZGxlci5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL0RvbURlbGVnYXRlZEV2ZW50SGFuZGxlLmpzIiwiL1VzZXJzL2JydW5vYmFzdG8vUHJvamVjdHMvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvRG9tRXZlbnRIYW5kbGUuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9kb21OYW1lZC5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL2RvbS5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL0RvbUV2ZW50RW1pdHRlclByb3h5LmpzIiwiL1VzZXJzL2JydW5vYmFzdG8vUHJvamVjdHMvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZmVhdHVyZXMuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9nbG9iYWxFdmFsLmpzIiwiL1VzZXJzL2JydW5vYmFzdG8vUHJvamVjdHMvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZ2xvYmFsRXZhbFN0eWxlcy5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL2V2ZW50cy5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1wcm9taXNlL3NyYy9wcm9taXNlL1Byb21pc2UuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZGVib3VuY2Uvc3JjL2RlYm91bmNlLmpzIiwiL1VzZXJzL2JydW5vYmFzdG8vUHJvamVjdHMvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLXBhdGgtcGFyc2VyL3NyYy9wYXRoUGFyc2VyLmpzIiwiL1VzZXJzL2JydW5vYmFzdG8vUHJvamVjdHMvc2VubmEuanMvc3JjL3JvdXRlL1JvdXRlLmpzIiwiL1VzZXJzL2JydW5vYmFzdG8vUHJvamVjdHMvc2VubmEuanMvc3JjL2NhY2hlYWJsZS9DYWNoZWFibGUuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9zcmMvc2NyZWVuL1NjcmVlbi5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL3NyYy9zdXJmYWNlL1N1cmZhY2UuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9zcmMvYXBwL0FwcC5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1hamF4L3NyYy9BamF4LmpzIiwiL1VzZXJzL2JydW5vYmFzdG8vUHJvamVjdHMvc2VubmEuanMvc3JjL2Vycm9ycy9lcnJvcnMuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtdXNlcmFnZW50L3NyYy9VQS5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL3NyYy9zY3JlZW4vUmVxdWVzdFNjcmVlbi5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL3NyYy9zY3JlZW4vSHRtbFNjcmVlbi5qcyIsIi9Vc2Vycy9icnVub2Jhc3RvL1Byb2plY3RzL3Nlbm5hLmpzL3NyYy9hcHAvQXBwRGF0YUF0dHJpYnV0ZUhhbmRsZXIuanMiLCIvVXNlcnMvYnJ1bm9iYXN0by9Qcm9qZWN0cy9zZW5uYS5qcy9zcmMvYXBwL2RhdGFBdHRyaWJ1dGVIYW5kbGVyLmpzIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBnbG9iYWxzID0gZ2xvYmFscyB8fCB7fTtcblxuaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG5cdGdsb2JhbHMud2luZG93ID0gd2luZG93O1xufVxuXG5pZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuXHRnbG9iYWxzLmRvY3VtZW50ID0gZG9jdW1lbnQ7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGdsb2JhbHM7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQSBjb2xsZWN0aW9uIG9mIGNvcmUgdXRpbGl0eSBmdW5jdGlvbnMuXG4gKiBAY29uc3RcbiAqL1xuXG5sZXQgY29tcGF0aWJpbGl0eU1vZGVEYXRhXztcblxuLyoqXG4gKiBDb3VudGVyIGZvciB1bmlxdWUgaWQuXG4gKiBAdHlwZSB7TnVtYmVyfVxuICogQHByaXZhdGVcbiAqL1xubGV0IHVuaXF1ZUlkQ291bnRlcl8gPSAxO1xuXG4vKipcbiAqIFVuaXF1ZSBpZCBwcm9wZXJ0eSBwcmVmaXguXG4gKiBAdHlwZSB7U3RyaW5nfVxuICogQHByb3RlY3RlZFxuICovXG5leHBvcnQgY29uc3QgVUlEX1BST1BFUlRZID0gYGNvcmVfJHsoKE1hdGgucmFuZG9tKCkgKiAxZTkpID4+PiAwKX1gO1xuXG4vKipcbiAqIFdoZW4gZGVmaW5pbmcgYSBjbGFzcyBGb28gd2l0aCBhbiBhYnN0cmFjdCBtZXRob2QgYmFyKCksIHlvdSBjYW4gZG86XG4gKiBGb28ucHJvdG90eXBlLmJhciA9IGFic3RyYWN0TWV0aG9kXG4gKlxuICogTm93IGlmIGEgc3ViY2xhc3Mgb2YgRm9vIGZhaWxzIHRvIG92ZXJyaWRlIGJhcigpLCBhbiBlcnJvciB3aWxsIGJlIHRocm93blxuICogd2hlbiBiYXIoKSBpcyBpbnZva2VkLlxuICpcbiAqIEB0eXBlIHshRnVuY3Rpb259XG4gKiBAdGhyb3dzIHtFcnJvcn0gd2hlbiBpbnZva2VkIHRvIGluZGljYXRlIHRoZSBtZXRob2Qgc2hvdWxkIGJlIG92ZXJyaWRkZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhYnN0cmFjdE1ldGhvZCgpIHtcblx0dGhyb3cgRXJyb3IoJ1VuaW1wbGVtZW50ZWQgYWJzdHJhY3QgbWV0aG9kJyk7XG59XG5cbi8qKlxuICogRGlzYWJsZXMgTWV0YWwuanMncyBjb21wYXRpYmlsaXR5IG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkaXNhYmxlQ29tcGF0aWJpbGl0eU1vZGUoKSB7XG5cdGNvbXBhdGliaWxpdHlNb2RlRGF0YV8gPSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogRW5hYmxlcyBNZXRhbC5qcydzIGNvbXBhdGliaWxpdHkgbW9kZSB3aXRoIHRoZSBmb2xsb3dpbmcgZmVhdHVyZXMgZnJvbSByY1xuICogYW5kIDEueCB2ZXJzaW9uczpcbiAqICAgICAtIFVzaW5nIFwia2V5XCIgdG8gcmVmZXJlbmNlIGNvbXBvbmVudCBpbnN0YW5jZXMuIEluIHRoZSBjdXJyZW50IHZlcnNpb25cbiAqICAgICAgIHRoaXMgc2hvdWxkIGJlIGRvbmUgdmlhIFwicmVmXCIgaW5zdGVhZC4gVGhpcyBhbGxvd3Mgb2xkIGNvZGUgc3RpbGxcbiAqICAgICAgIHVzaW5nIFwia2V5XCIgdG8ga2VlcCB3b3JraW5nIGxpa2UgYmVmb3JlLiBOT1RFOiB0aGlzIG1heSBjYXVzZVxuICogICAgICAgcHJvYmxlbXMsIHNpbmNlIFwia2V5XCIgaXMgbWVhbnQgdG8gYmUgdXNlZCBkaWZmZXJlbnRseS4gT25seSB1c2UgdGhpc1xuICogICAgICAgaWYgaXQncyBub3QgcG9zc2libGUgdG8gdXBncmFkZSB0aGUgY29kZSB0byB1c2UgXCJyZWZcIiBpbnN0ZWFkLlxuICogQHBhcmFtIHtPYmplY3Q9fSBvcHRfZGF0YSBPcHRpb25hbCBvYmplY3Qgd2l0aCBkYXRhIHRvIHNwZWNpZnkgbW9yZVxuICogICAgIGRldGFpbHMsIHN1Y2ggYXM6XG4gKiAgICAgICAgIC0gcmVuZGVyZXJzIHtBcnJheX0gdGhlIHRlbXBsYXRlIHJlbmRlcmVycyB0aGF0IHNob3VsZCBiZSBpblxuICogICAgICAgICAgIGNvbXBhdGliaWxpdHkgbW9kZSwgZWl0aGVyIHRoZWlyIGNvbnN0cnVjdG9ycyBvciBzdHJpbmdzXG4gKiAgICAgICAgICAgcmVwcmVzZW50aW5nIHRoZW0gKGUuZy4gJ3NveScgb3IgJ2pzeCcpLiBCeSBkZWZhdWx0LCBhbGwgdGhlIG9uZXNcbiAqICAgICAgICAgICB0aGF0IGV4dGVuZCBmcm9tIEluY3JlbWVudGFsRG9tUmVuZGVyZXIuXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5leHBvcnQgZnVuY3Rpb24gZW5hYmxlQ29tcGF0aWJpbGl0eU1vZGUob3B0X2RhdGEgPSB7fSkge1xuXHRjb21wYXRpYmlsaXR5TW9kZURhdGFfID0gb3B0X2RhdGE7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZGF0YSB1c2VkIGZvciBjb21wYXRpYmlsaXR5IG1vZGUsIG9yIG5vdGhpbmcgaWYgaXQgaGFzbid0IGJlZW5cbiAqIGVuYWJsZWQuXG4gKiBAcmV0dXJuIHtPYmplY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb21wYXRpYmlsaXR5TW9kZURhdGEoKSB7XG5cdC8vIENvbXBhdGliaWxpdHkgbW9kZSBjYW4gYmUgc2V0IHZpYSB0aGUgX19NRVRBTF9DT01QQVRJQklMSVRZX18gZ2xvYmFsIHZhci5cblx0aWYgKGNvbXBhdGliaWxpdHlNb2RlRGF0YV8gPT09IHVuZGVmaW5lZCkge1xuXHRcdGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuX19NRVRBTF9DT01QQVRJQklMSVRZX18pIHtcblx0XHRcdGVuYWJsZUNvbXBhdGliaWxpdHlNb2RlKHdpbmRvdy5fX01FVEFMX0NPTVBBVElCSUxJVFlfXyk7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBjb21wYXRpYmlsaXR5TW9kZURhdGFfO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGZpcnN0IGFyZ3VtZW50IGlmIGl0J3MgdHJ1dGh5LCBvciB0aGUgc2Vjb25kIG90aGVyd2lzZS5cbiAqIEBwYXJhbSB7Kn0gYVxuICogQHBhcmFtIHsqfSBiXG4gKiBAcmV0dXJuIHsqfVxuICogQHByb3RlY3RlZFxuICovXG5mdW5jdGlvbiBnZXRGaXJzdFRydXRoeV8oYSwgYikge1xuXHRyZXR1cm4gYSB8fCBiO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIG5hbWUgb2YgdGhlIGdpdmVuIGZ1bmN0aW9uLiBJZiB0aGUgY3VycmVudCBicm93c2VyIGRvZXNuJ3RcbiAqIHN1cHBvcnQgdGhlIGBuYW1lYCBwcm9wZXJ0eSwgdGhpcyB3aWxsIGNhbGN1bGF0ZSBpdCBmcm9tIHRoZSBmdW5jdGlvbidzXG4gKiBjb250ZW50IHN0cmluZy5cbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGZuXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRGdW5jdGlvbk5hbWUoZm4pIHtcblx0aWYgKCFmbi5uYW1lKSB7XG5cdFx0Y29uc3Qgc3RyID0gZm4udG9TdHJpbmcoKTtcblx0XHRmbi5uYW1lID0gc3RyLnN1YnN0cmluZyg5LCBzdHIuaW5kZXhPZignKCcpKTtcblx0fVxuXHRyZXR1cm4gZm4ubmFtZTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSB2YWx1ZSBvZiBhIHN0YXRpYyBwcm9wZXJ0eSBpbiB0aGUgZ2l2ZW4gY2xhc3MuIFRoZSB2YWx1ZSB3aWxsIGJlXG4gKiBpbmhlcml0ZWQgZnJvbSBhbmNlc3RvcnMgYXMgZXhwZWN0ZWQsIHVubGVzcyBhIGN1c3RvbSBtZXJnZSBmdW5jdGlvbiBpcyBnaXZlbixcbiAqIHdoaWNoIGNhbiBjaGFuZ2UgaG93IHRoZSBzdXBlciBjbGFzc2VzJyB2YWx1ZSBmb3IgdGhhdCBwcm9wZXJ0eSB3aWxsIGJlIG1lcmdlZFxuICogdG9nZXRoZXIuXG4gKiBUaGUgZmluYWwgbWVyZ2VkIHZhbHVlIHdpbGwgYmUgc3RvcmVkIGluIGFub3RoZXIgcHJvcGVydHksIHNvIHRoYXQgaXQgd29uJ3RcbiAqIGJlIHJlY2FsY3VsYXRlZCBldmVuIGlmIHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIG11bHRpcGxlIHRpbWVzLlxuICogQHBhcmFtIHshZnVuY3Rpb24oKX0gY3RvciBDbGFzcyBjb25zdHJ1Y3Rvci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eU5hbWUgUHJvcGVydHkgbmFtZSB0byBiZSBtZXJnZWQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCosICopOio9fSBvcHRfbWVyZ2VGbiBGdW5jdGlvbiB0aGF0IHJlY2VpdmVzIHRoZSBtZXJnZWRcbiAqICAgICB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgc28gZmFyIGFuZCB0aGUgbmV4dCB2YWx1ZSB0byBiZSBtZXJnZWQgdG8gaXQuXG4gKiAgICAgU2hvdWxkIHJldHVybiB0aGVzZSB0d28gbWVyZ2VkIHRvZ2V0aGVyLiBJZiBub3QgcGFzc2VkIHRoZSBmaW5hbCBwcm9wZXJ0eVxuICogICAgIHdpbGwgYmUgdGhlIGZpcnN0IHRydXRoeSB2YWx1ZSBhbW9uZyBhbmNlc3RvcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGF0aWNQcm9wZXJ0eShjdG9yLCBwcm9wZXJ0eU5hbWUsIG9wdF9tZXJnZUZuKSB7XG5cdGNvbnN0IG1lcmdlZE5hbWUgPSBwcm9wZXJ0eU5hbWUgKyAnX01FUkdFRCc7XG5cdGlmICghY3Rvci5oYXNPd25Qcm9wZXJ0eShtZXJnZWROYW1lKSkge1xuXHRcdGxldCBtZXJnZWQgPSBjdG9yLmhhc093blByb3BlcnR5KHByb3BlcnR5TmFtZSkgPyBjdG9yW3Byb3BlcnR5TmFtZV0gOiBudWxsO1xuXHRcdGlmIChjdG9yLl9fcHJvdG9fXyAmJiAhY3Rvci5fX3Byb3RvX18uaXNQcm90b3R5cGVPZihGdW5jdGlvbikpIHtcblx0XHRcdGNvbnN0IG1lcmdlRm4gPSBvcHRfbWVyZ2VGbiB8fCBnZXRGaXJzdFRydXRoeV87XG5cdFx0XHRtZXJnZWQgPSBtZXJnZUZuKFxuXHRcdFx0XHRtZXJnZWQsXG5cdFx0XHRcdGdldFN0YXRpY1Byb3BlcnR5KGN0b3IuX19wcm90b19fLCBwcm9wZXJ0eU5hbWUsIG1lcmdlRm4pXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRjdG9yW21lcmdlZE5hbWVdID0gbWVyZ2VkO1xuXHR9XG5cdHJldHVybiBjdG9yW21lcmdlZE5hbWVdO1xufVxuXG4vKipcbiAqIEdldHMgYW4gdW5pcXVlIGlkLiBJZiBgb3B0X29iamVjdGAgYXJndW1lbnQgaXMgcGFzc2VkLCB0aGUgb2JqZWN0IGlzXG4gKiBtdXRhdGVkIHdpdGggYW4gdW5pcXVlIGlkLiBDb25zZWN1dGl2ZSBjYWxscyB3aXRoIHRoZSBzYW1lIG9iamVjdFxuICogcmVmZXJlbmNlIHdvbid0IG11dGF0ZSB0aGUgb2JqZWN0IGFnYWluLCBpbnN0ZWFkIHRoZSBjdXJyZW50IG9iamVjdCB1aWRcbiAqIHJldHVybnMuIFNlZSB7QGxpbmsgVUlEX1BST1BFUlRZfS5cbiAqIEBwYXJhbSB7T2JqZWN0PX0gb3B0X29iamVjdCBPcHRpb25hbCBvYmplY3QgdG8gYmUgbXV0YXRlZCB3aXRoIHRoZSB1aWQuIElmXG4gKiAgICAgbm90IHNwZWNpZmllZCB0aGlzIG1ldGhvZCBvbmx5IHJldHVybnMgdGhlIHVpZC5cbiAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9ub0luaGVyaXRhbmNlIE9wdGlvbmFsIGZsYWcgaW5kaWNhdGluZyBpZiB0aGlzXG4gKiAgICAgb2JqZWN0J3MgdWlkIHByb3BlcnR5IGNhbiBiZSBpbmhlcml0ZWQgZnJvbSBwYXJlbnRzIG9yIG5vdC5cbiAqIEB0aHJvd3Mge0Vycm9yfSB3aGVuIGludm9rZWQgdG8gaW5kaWNhdGUgdGhlIG1ldGhvZCBzaG91bGQgYmUgb3ZlcnJpZGRlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFVpZChvcHRfb2JqZWN0LCBvcHRfbm9Jbmhlcml0YW5jZSkge1xuXHRpZiAob3B0X29iamVjdCkge1xuXHRcdGxldCBpZCA9IG9wdF9vYmplY3RbVUlEX1BST1BFUlRZXTtcblx0XHRpZiAob3B0X25vSW5oZXJpdGFuY2UgJiYgIW9wdF9vYmplY3QuaGFzT3duUHJvcGVydHkoVUlEX1BST1BFUlRZKSkge1xuXHRcdFx0aWQgPSBudWxsO1xuXHRcdH1cblx0XHRyZXR1cm4gaWQgfHwgKG9wdF9vYmplY3RbVUlEX1BST1BFUlRZXSA9IHVuaXF1ZUlkQ291bnRlcl8rKyk7XG5cdH1cblx0cmV0dXJuIHVuaXF1ZUlkQ291bnRlcl8rKztcbn1cblxuLyoqXG4gKiBUaGUgaWRlbnRpdHkgZnVuY3Rpb24uIFJldHVybnMgaXRzIGZpcnN0IGFyZ3VtZW50LlxuICogQHBhcmFtIHsqPX0gb3B0X3JldHVyblZhbHVlIFRoZSBzaW5nbGUgdmFsdWUgdGhhdCB3aWxsIGJlIHJldHVybmVkLlxuICogQHJldHVybiB7P30gVGhlIGZpcnN0IGFyZ3VtZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaWRlbnRpdHlGdW5jdGlvbihvcHRfcmV0dXJuVmFsdWUpIHtcblx0cmV0dXJuIG9wdF9yZXR1cm5WYWx1ZTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBhIGJvb2xlYW4uXG4gKiBAcGFyYW0gez99IHZhbCBWYXJpYWJsZSB0byB0ZXN0LlxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB2YXJpYWJsZSBpcyBib29sZWFuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNCb29sZWFuKHZhbCkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ2Jvb2xlYW4nO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIG5vdCB1bmRlZmluZWQuXG4gKiBAcGFyYW0gez99IHZhbCBWYXJpYWJsZSB0byB0ZXN0LlxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB2YXJpYWJsZSBpcyBkZWZpbmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEZWYodmFsKSB7XG5cdHJldHVybiB2YWwgIT09IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgbm90IHVuZGVmaW5lZCBvciBudWxsLlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RlZkFuZE5vdE51bGwodmFsKSB7XG5cdHJldHVybiBpc0RlZih2YWwpICYmICFpc051bGwodmFsKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBkb2N1bWVudC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEb2N1bWVudCh2YWwpIHtcblx0cmV0dXJuIHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB2YWwubm9kZVR5cGUgPT09IDk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgZG9jdW1lbnQtZnJhZ21lbnQuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRG9jdW1lbnRGcmFnbWVudCh2YWwpIHtcblx0cmV0dXJuIHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB2YWwubm9kZVR5cGUgPT09IDExO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIGRvbSBlbGVtZW50LlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0VsZW1lbnQodmFsKSB7XG5cdHJldHVybiB2YWwgJiYgdHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsLm5vZGVUeXBlID09PSAxO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGEgZnVuY3Rpb24uXG4gKiBAcGFyYW0gez99IHZhbCBWYXJpYWJsZSB0byB0ZXN0LlxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB2YXJpYWJsZSBpcyBhIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNGdW5jdGlvbih2YWwpIHtcblx0cmV0dXJuIHR5cGVvZiB2YWwgPT09ICdmdW5jdGlvbic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIG51bGwuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTnVsbCh2YWwpIHtcblx0cmV0dXJuIHZhbCA9PT0gbnVsbDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBhIG51bWJlci5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGEgbnVtYmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNOdW1iZXIodmFsKSB7XG5cdHJldHVybiB0eXBlb2YgdmFsID09PSAnbnVtYmVyJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSB3aW5kb3cuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzV2luZG93KHZhbCkge1xuXHRyZXR1cm4gdmFsICE9PSBudWxsICYmIHZhbCA9PT0gdmFsLndpbmRvdztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBhbiBvYmplY3QuIFRoaXMgaW5jbHVkZXMgYXJyYXlzXG4gKiBhbmQgZnVuY3Rpb25zLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgYW4gb2JqZWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNPYmplY3QodmFsKSB7XG5cdGNvbnN0IHR5cGUgPSB0eXBlb2YgdmFsO1xuXHRyZXR1cm4gdHlwZSA9PT0gJ29iamVjdCcgJiYgdmFsICE9PSBudWxsIHx8IHR5cGUgPT09ICdmdW5jdGlvbic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgUHJvbWlzZS5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQcm9taXNlKHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHR5cGVvZiB2YWwudGhlbiA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBzdHJpbmcuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU3RyaW5nKHZhbCkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ3N0cmluZycgfHwgdmFsIGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG4vKipcbiAqIFNldHMgdG8gdHJ1ZSBpZiBydW5uaW5nIGluc2lkZSBOb2RlLmpzIGVudmlyb25tZW50IHdpdGggZXh0cmEgY2hlY2sgZm9yXG4gKiBgcHJvY2Vzcy5icm93c2VyYCB0byBza2lwIEthcm1hIHJ1bm5lciBlbnZpcm9ubWVudC4gS2FybWEgZW52aXJvbm1lbnQgaGFzXG4gKiBgcHJvY2Vzc2AgZGVmaW5lZCBldmVuIHRob3VnaCBpdCBydW5zIG9uIHRoZSBicm93c2VyLlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2VydmVyU2lkZSgpIHtcblx0cmV0dXJuIHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJlxuXHRcdHR5cGVvZiBwcm9jZXNzLmVudiAhPT0gJ3VuZGVmaW5lZCcgJiZcblx0XHRwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Rlc3QnICYmXG5cdFx0IXByb2Nlc3MuYnJvd3Nlcjtcbn1cblxuLyoqXG4gKiBOdWxsIGZ1bmN0aW9uIHVzZWQgZm9yIGRlZmF1bHQgdmFsdWVzIG9mIGNhbGxiYWNrcywgZXRjLlxuICogQHJldHVybiB7dm9pZH0gTm90aGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG51bGxGdW5jdGlvbigpIHtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxuLy8gVGhpcyBmaWxlIGV4aXN0cyBqdXN0IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgbWFraW5nIHN1cmUgdGhhdCBvbGRcbi8vIGRlZmF1bHQgaW1wb3J0cyBmb3IgdGhpcyBmaWxlIHN0aWxsIHdvcmsuIEl0J3MgYmVzdCB0byB1c2UgdGhlIG5hbWVkIGV4cG9ydHNcbi8vIGZvciBlYWNoIGZ1bmN0aW9uIGluc3RlYWQgdGhvdWdoLCBzaW5jZSB0aGF0IGFsbG93cyBidW5kbGVycyBsaWtlIFJvbGx1cCB0b1xuLy8gcmVkdWNlIHRoZSBidW5kbGUgc2l6ZSBieSByZW1vdmluZyB1bnVzZWQgY29kZS5cbmltcG9ydCAqIGFzIGNvcmUgZnJvbSAnLi9jb3JlTmFtZWQnO1xuXG5leHBvcnQgZGVmYXVsdCBjb3JlO1xuZXhwb3J0IHsgY29yZSB9O1xuZXhwb3J0ICogZnJvbSAnLi9jb3JlTmFtZWQnO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBpc0RlZiB9IGZyb20gJy4uL2NvcmUnO1xuXG5jbGFzcyBhcnJheSB7XG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGFycmF5cyBoYXZlIHRoZSBzYW1lIGNvbnRlbnQuXG5cdCAqIEBwYXJhbSB7IUFycmF5PCo+fSBhcnIxXG5cdCAqIEBwYXJhbSB7IUFycmF5PCo+fSBhcnIyXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRzdGF0aWMgZXF1YWwoYXJyMSwgYXJyMikge1xuXHRcdGlmIChhcnIxID09PSBhcnIyKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0aWYgKGFycjEubGVuZ3RoICE9PSBhcnIyLmxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFycjEubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChhcnIxW2ldICE9PSBhcnIyW2ldKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgZmlyc3QgdmFsdWUgaW4gdGhlIGdpdmVuIGFycmF5IHRoYXQgaXNuJ3QgdW5kZWZpbmVkLlxuXHQgKiBAcGFyYW0geyFBcnJheX0gYXJyXG5cdCAqIEByZXR1cm4geyp9XG5cdCAqL1xuXHRzdGF0aWMgZmlyc3REZWZpbmVkVmFsdWUoYXJyKSB7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChhcnJbaV0gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRyZXR1cm4gYXJyW2ldO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBUcmFuc2Zvcm1zIHRoZSBpbnB1dCBuZXN0ZWQgYXJyYXkgdG8gYmVjb21lIGZsYXQuXG5cdCAqIEBwYXJhbSB7QXJyYXkuPCp8QXJyYXkuPCo+Pn0gYXJyIE5lc3RlZCBhcnJheSB0byBmbGF0dGVuLlxuXHQgKiBAcGFyYW0ge0FycmF5LjwqPn0gb3B0X291dHB1dCBPcHRpb25hbCBvdXRwdXQgYXJyYXkuXG5cdCAqIEByZXR1cm4ge0FycmF5LjwqPn0gRmxhdCBhcnJheS5cblx0ICovXG5cdHN0YXRpYyBmbGF0dGVuKGFyciwgb3B0X291dHB1dCkge1xuXHRcdHZhciBvdXRwdXQgPSBvcHRfb3V0cHV0IHx8IFtdO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAoQXJyYXkuaXNBcnJheShhcnJbaV0pKSB7XG5cdFx0XHRcdGFycmF5LmZsYXR0ZW4oYXJyW2ldLCBvdXRwdXQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0b3V0cHV0LnB1c2goYXJyW2ldKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIG91dHB1dDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGEgcGFydGljdWxhciB2YWx1ZSBmcm9tIGFuIGFycmF5LlxuXHQgKiBAcGFyYW0ge0FycmF5LjxUPn0gYXJyIEFycmF5IGZyb20gd2hpY2ggdG8gcmVtb3ZlIHZhbHVlLlxuXHQgKiBAcGFyYW0ge1R9IG9iaiBPYmplY3QgdG8gcmVtb3ZlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIGFuIGVsZW1lbnQgd2FzIHJlbW92ZWQuXG5cdCAqIEB0ZW1wbGF0ZSBUXG5cdCAqL1xuXHRzdGF0aWMgcmVtb3ZlKGFyciwgb2JqKSB7XG5cdFx0Y29uc3QgaSA9IGFyci5pbmRleE9mKG9iaik7XG5cdFx0bGV0IHJ2O1xuXHRcdGlmICggKHJ2ID0gaSA+PSAwKSApIHtcblx0XHRcdGFycmF5LnJlbW92ZUF0KGFyciwgaSk7XG5cdFx0fVxuXHRcdHJldHVybiBydjtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGZyb20gYW4gYXJyYXkgdGhlIGVsZW1lbnQgYXQgaW5kZXggaVxuXHQgKiBAcGFyYW0ge0FycmF5fSBhcnIgQXJyYXkgb3IgYXJyYXkgbGlrZSBvYmplY3QgZnJvbSB3aGljaCB0byByZW1vdmUgdmFsdWUuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBpIFRoZSBpbmRleCB0byByZW1vdmUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgYW4gZWxlbWVudCB3YXMgcmVtb3ZlZC5cblx0ICovXG5cdHN0YXRpYyByZW1vdmVBdChhcnIsIGkpIHtcblx0XHRyZXR1cm4gQXJyYXkucHJvdG90eXBlLnNwbGljZS5jYWxsKGFyciwgaSwgMSkubGVuZ3RoID09PSAxO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNsaWNlcyB0aGUgZ2l2ZW4gYXJyYXksIGp1c3QgbGlrZSBBcnJheS5wcm90b3R5cGUuc2xpY2UsIGJ1dCB0aGlzXG5cdCAqIGlzIGZhc3RlciBhbmQgd29ya2luZyBvbiBhbGwgYXJyYXktbGlrZSBvYmplY3RzIChsaWtlIGFyZ3VtZW50cykuXG5cdCAqIEBwYXJhbSB7IU9iamVjdH0gYXJyIEFycmF5LWxpa2Ugb2JqZWN0IHRvIHNsaWNlLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIGluZGV4IHRoYXQgc2hvdWxkIHN0YXJ0IHRoZSBzbGljZS5cblx0ICogQHBhcmFtIHtudW1iZXI9fSBvcHRfZW5kIFRoZSBpbmRleCB3aGVyZSB0aGUgc2xpY2Ugc2hvdWxkIGVuZCwgbm90XG5cdCAqICAgaW5jbHVkZWQgaW4gdGhlIGZpbmFsIGFycmF5LiBJZiBub3QgZ2l2ZW4sIGFsbCBlbGVtZW50cyBhZnRlciB0aGVcblx0ICogICBzdGFydCBpbmRleCB3aWxsIGJlIGluY2x1ZGVkLlxuXHQgKiBAcmV0dXJuIHshQXJyYXl9XG5cdCAqL1xuXHRzdGF0aWMgc2xpY2UoYXJyLCBzdGFydCwgb3B0X2VuZCkge1xuXHRcdGNvbnN0IHNsaWNlZCA9IFtdO1xuXHRcdGNvbnN0IGVuZCA9IGlzRGVmKG9wdF9lbmQpID8gb3B0X2VuZCA6IGFyci5sZW5ndGg7XG5cdFx0Zm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcblx0XHRcdHNsaWNlZC5wdXNoKGFycltpXSk7XG5cdFx0fVxuXHRcdHJldHVybiBzbGljZWQ7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgYXJyYXk7XG4iLCIvKiFcbiAqIFBvbHlmaWxsIGZyb20gR29vZ2xlJ3MgQ2xvc3VyZSBMaWJyYXJ5LlxuICogQ29weXJpZ2h0IDIwMTMgVGhlIENsb3N1cmUgTGlicmFyeSBBdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuY29uc3QgYXN5bmMgPSB7fTtcblxuXG4vKipcbiAqIFRocm93IGFuIGl0ZW0gd2l0aG91dCBpbnRlcnJ1cHRpbmcgdGhlIGN1cnJlbnQgZXhlY3V0aW9uIGNvbnRleHQuICBGb3JcbiAqIGV4YW1wbGUsIGlmIHByb2Nlc3NpbmcgYSBncm91cCBvZiBpdGVtcyBpbiBhIGxvb3AsIHNvbWV0aW1lcyBpdCBpcyB1c2VmdWxcbiAqIHRvIHJlcG9ydCBhbiBlcnJvciB3aGlsZSBzdGlsbCBhbGxvd2luZyB0aGUgcmVzdCBvZiB0aGUgYmF0Y2ggdG8gYmVcbiAqIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7Kn0gZXhjZXB0aW9uXG4gKi9cbmFzeW5jLnRocm93RXhjZXB0aW9uID0gZnVuY3Rpb24oZXhjZXB0aW9uKSB7XG5cdC8vIEVhY2ggdGhyb3cgbmVlZHMgdG8gYmUgaW4gaXRzIG93biBjb250ZXh0LlxuXHRhc3luYy5uZXh0VGljayhmdW5jdGlvbigpIHtcblx0XHR0aHJvdyBleGNlcHRpb247XG5cdH0pO1xufTtcblxuXG4vKipcbiAqIEZpcmVzIHRoZSBwcm92aWRlZCBjYWxsYmFjayBqdXN0IGJlZm9yZSB0aGUgY3VycmVudCBjYWxsc3RhY2sgdW53aW5kcywgb3IgYXNcbiAqIHNvb24gYXMgcG9zc2libGUgYWZ0ZXIgdGhlIGN1cnJlbnQgSlMgZXhlY3V0aW9uIGNvbnRleHQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKHRoaXM6VEhJUyl9IGNhbGxiYWNrXG4gKiBAcGFyYW0ge1RISVM9fSBvcHRfY29udGV4dCBPYmplY3QgdG8gdXNlIGFzIHRoZSBcInRoaXMgdmFsdWVcIiB3aGVuIGNhbGxpbmdcbiAqICAgICB0aGUgcHJvdmlkZWQgZnVuY3Rpb24uXG4gKiBAdGVtcGxhdGUgVEhJU1xuICovXG5hc3luYy5ydW4gPSBmdW5jdGlvbihjYWxsYmFjaywgb3B0X2NvbnRleHQpIHtcblx0aWYgKCFhc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXykge1xuXHRcdC8vIE5vdGhpbmcgaXMgY3VycmVudGx5IHNjaGVkdWxlZCwgc2NoZWR1bGUgaXQgbm93LlxuXHRcdGFzeW5jLm5leHRUaWNrKGFzeW5jLnJ1bi5wcm9jZXNzV29ya1F1ZXVlKTtcblx0XHRhc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXyA9IHRydWU7XG5cdH1cblxuXHRhc3luYy5ydW4ud29ya1F1ZXVlXy5wdXNoKFxuXHRcdG5ldyBhc3luYy5ydW4uV29ya0l0ZW1fKGNhbGxiYWNrLCBvcHRfY29udGV4dCkpO1xufTtcblxuXG4vKiogQHByaXZhdGUge2Jvb2xlYW59ICovXG5hc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXyA9IGZhbHNlO1xuXG5cbi8qKiBAcHJpdmF0ZSB7IUFycmF5LjwhYXN5bmMucnVuLldvcmtJdGVtXz59ICovXG5hc3luYy5ydW4ud29ya1F1ZXVlXyA9IFtdO1xuXG4vKipcbiAqIFJ1biBhbnkgcGVuZGluZyBhc3luYy5ydW4gd29yayBpdGVtcy4gVGhpcyBmdW5jdGlvbiBpcyBub3QgaW50ZW5kZWRcbiAqIGZvciBnZW5lcmFsIHVzZSwgYnV0IGZvciB1c2UgYnkgZW50cnkgcG9pbnQgaGFuZGxlcnMgdG8gcnVuIGl0ZW1zIGFoZWFkIG9mXG4gKiBhc3luYy5uZXh0VGljay5cbiAqL1xuYXN5bmMucnVuLnByb2Nlc3NXb3JrUXVldWUgPSBmdW5jdGlvbigpIHtcblx0Ly8gTk9URTogYWRkaXRpb25hbCB3b3JrIHF1ZXVlIGl0ZW1zIG1heSBiZSBwdXNoZWQgd2hpbGUgcHJvY2Vzc2luZy5cblx0d2hpbGUgKGFzeW5jLnJ1bi53b3JrUXVldWVfLmxlbmd0aCkge1xuXHRcdC8vIERvbid0IGxldCB0aGUgd29yayBxdWV1ZSBncm93IGluZGVmaW5pdGVseS5cblx0XHRjb25zdCB3b3JrSXRlbXMgPSBhc3luYy5ydW4ud29ya1F1ZXVlXztcblx0XHRhc3luYy5ydW4ud29ya1F1ZXVlXyA9IFtdO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgd29ya0l0ZW1zLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCB3b3JrSXRlbSA9IHdvcmtJdGVtc1tpXTtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHdvcmtJdGVtLmZuLmNhbGwod29ya0l0ZW0uc2NvcGUpO1xuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRhc3luYy50aHJvd0V4Y2VwdGlvbihlKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBUaGVyZSBhcmUgbm8gbW9yZSB3b3JrIGl0ZW1zLCByZXNldCB0aGUgd29yayBxdWV1ZS5cblx0YXN5bmMucnVuLndvcmtRdWV1ZVNjaGVkdWxlZF8gPSBmYWxzZTtcbn07XG5cblxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqIEBmaW5hbFxuICogQHN0cnVjdFxuICogQHByaXZhdGVcbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGZuXG4gKiBAcGFyYW0ge09iamVjdHxudWxsfHVuZGVmaW5lZH0gc2NvcGVcbiAqL1xuYXN5bmMucnVuLldvcmtJdGVtXyA9IGZ1bmN0aW9uKGZuLCBzY29wZSkge1xuXHQvKiogQGNvbnN0ICovXG5cdHRoaXMuZm4gPSBmbjtcblx0LyoqIEBjb25zdCAqL1xuXHR0aGlzLnNjb3BlID0gc2NvcGU7XG59O1xuXG5cbi8qKlxuICogRmlyZXMgdGhlIHByb3ZpZGVkIGNhbGxiYWNrcyBhcyBzb29uIGFzIHBvc3NpYmxlIGFmdGVyIHRoZSBjdXJyZW50IEpTXG4gKiBleGVjdXRpb24gY29udGV4dC4gc2V0VGltZW91dCjigKYsIDApIGFsd2F5cyB0YWtlcyBhdCBsZWFzdCA1bXMgZm9yIGxlZ2FjeVxuICogcmVhc29ucy5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24odGhpczpTQ09QRSl9IGNhbGxiYWNrIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGZpcmUgYXMgc29vbiBhc1xuICogICAgIHBvc3NpYmxlLlxuICogQHBhcmFtIHtTQ09QRT19IG9wdF9jb250ZXh0IE9iamVjdCBpbiB3aG9zZSBzY29wZSB0byBjYWxsIHRoZSBsaXN0ZW5lci5cbiAqIEB0ZW1wbGF0ZSBTQ09QRVxuICovXG5hc3luYy5uZXh0VGljayA9IGZ1bmN0aW9uKGNhbGxiYWNrLCBvcHRfY29udGV4dCkge1xuXHRsZXQgY2IgPSBjYWxsYmFjaztcblx0aWYgKG9wdF9jb250ZXh0KSB7XG5cdFx0Y2IgPSBjYWxsYmFjay5iaW5kKG9wdF9jb250ZXh0KTtcblx0fVxuXHRjYiA9IGFzeW5jLm5leHRUaWNrLndyYXBDYWxsYmFja18oY2IpO1xuXHQvLyBJbnRyb2R1Y2VkIGFuZCBjdXJyZW50bHkgb25seSBzdXBwb3J0ZWQgYnkgSUUxMC5cblx0Ly8gVmVyaWZ5IGlmIHZhcmlhYmxlIGlzIGRlZmluZWQgb24gdGhlIGN1cnJlbnQgcnVudGltZSAoaS5lLiwgbm9kZSwgYnJvd3NlcikuXG5cdC8vIENhbid0IHVzZSB0eXBlb2YgZW5jbG9zZWQgaW4gYSBmdW5jdGlvbiAoc3VjaCBhcyBjb3JlLmlzRnVuY3Rpb24pIG9yIGFuXG5cdC8vIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93biB3aGVuIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQgb24gYW4gZW52aXJvbm1lbnRcblx0Ly8gd2hlcmUgdGhlIHZhcmlhYmxlIGlzIHVuZGVmaW5lZC5cblx0aWYgKHR5cGVvZiBzZXRJbW1lZGlhdGUgPT09ICdmdW5jdGlvbicpIHtcblx0XHRzZXRJbW1lZGlhdGUoY2IpO1xuXHRcdHJldHVybjtcblx0fVxuXHQvLyBMb29rIGZvciBhbmQgY2FjaGUgdGhlIGN1c3RvbSBmYWxsYmFjayB2ZXJzaW9uIG9mIHNldEltbWVkaWF0ZS5cblx0aWYgKCFhc3luYy5uZXh0VGljay5zZXRJbW1lZGlhdGVfKSB7XG5cdFx0YXN5bmMubmV4dFRpY2suc2V0SW1tZWRpYXRlXyA9IGFzeW5jLm5leHRUaWNrLmdldFNldEltbWVkaWF0ZUVtdWxhdG9yXygpO1xuXHR9XG5cdGFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8oY2IpO1xufTtcblxuXG4vKipcbiAqIENhY2hlIGZvciB0aGUgc2V0SW1tZWRpYXRlIGltcGxlbWVudGF0aW9uLlxuICogQHR5cGUge2Z1bmN0aW9uKGZ1bmN0aW9uKCkpfVxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMubmV4dFRpY2suc2V0SW1tZWRpYXRlXyA9IG51bGw7XG5cblxuLyoqXG4gKiBEZXRlcm1pbmVzIHRoZSBiZXN0IHBvc3NpYmxlIGltcGxlbWVudGF0aW9uIHRvIHJ1biBhIGZ1bmN0aW9uIGFzIHNvb24gYXNcbiAqIHRoZSBKUyBldmVudCBsb29wIGlzIGlkbGUuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbihmdW5jdGlvbigpKX0gVGhlIFwic2V0SW1tZWRpYXRlXCIgaW1wbGVtZW50YXRpb24uXG4gKiBAcHJpdmF0ZVxuICovXG5hc3luYy5uZXh0VGljay5nZXRTZXRJbW1lZGlhdGVFbXVsYXRvcl8gPSBmdW5jdGlvbigpIHtcblx0Ly8gQ3JlYXRlIGEgcHJpdmF0ZSBtZXNzYWdlIGNoYW5uZWwgYW5kIHVzZSBpdCB0byBwb3N0TWVzc2FnZSBlbXB0eSBtZXNzYWdlc1xuXHQvLyB0byBvdXJzZWx2ZXMuXG5cdGxldCBDaGFubmVsO1xuXG5cdC8vIFZlcmlmeSBpZiB2YXJpYWJsZSBpcyBkZWZpbmVkIG9uIHRoZSBjdXJyZW50IHJ1bnRpbWUgKGkuZS4sIG5vZGUsIGJyb3dzZXIpLlxuXHQvLyBDYW4ndCB1c2UgdHlwZW9mIGVuY2xvc2VkIGluIGEgZnVuY3Rpb24gKHN1Y2ggYXMgY29yZS5pc0Z1bmN0aW9uKSBvciBhblxuXHQvLyBleGNlcHRpb24gd2lsbCBiZSB0aHJvd24gd2hlbiB0aGUgZnVuY3Rpb24gaXMgY2FsbGVkIG9uIGFuIGVudmlyb25tZW50XG5cdC8vIHdoZXJlIHRoZSB2YXJpYWJsZSBpcyB1bmRlZmluZWQuXG5cdGlmICh0eXBlb2YgTWVzc2FnZUNoYW5uZWwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRDaGFubmVsID0gTWVzc2FnZUNoYW5uZWw7XG5cdH1cblxuXHQvLyBJZiBNZXNzYWdlQ2hhbm5lbCBpcyBub3QgYXZhaWxhYmxlIGFuZCB3ZSBhcmUgaW4gYSBicm93c2VyLCBpbXBsZW1lbnRcblx0Ly8gYW4gaWZyYW1lIGJhc2VkIHBvbHlmaWxsIGluIGJyb3dzZXJzIHRoYXQgaGF2ZSBwb3N0TWVzc2FnZSBhbmRcblx0Ly8gZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lci4gVGhlIGxhdHRlciBleGNsdWRlcyBJRTggYmVjYXVzZSBpdCBoYXMgYVxuXHQvLyBzeW5jaHJvbm91cyBwb3N0TWVzc2FnZSBpbXBsZW1lbnRhdGlvbi5cblx0aWYgKHR5cGVvZiBDaGFubmVsID09PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJlxuXHRcdHdpbmRvdy5wb3N0TWVzc2FnZSAmJiB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcikge1xuXHRcdC8qKiBAY29uc3RydWN0b3IgKi9cblx0XHRDaGFubmVsID0gZnVuY3Rpb24oKSB7XG5cdFx0XHQvLyBNYWtlIGFuIGVtcHR5LCBpbnZpc2libGUgaWZyYW1lLlxuXHRcdFx0Y29uc3QgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG5cdFx0XHRpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcblx0XHRcdGlmcmFtZS5zcmMgPSAnJztcblx0XHRcdGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZChpZnJhbWUpO1xuXHRcdFx0Y29uc3Qgd2luID0gaWZyYW1lLmNvbnRlbnRXaW5kb3c7XG5cdFx0XHRjb25zdCBkb2MgPSB3aW4uZG9jdW1lbnQ7XG5cdFx0XHRkb2Mub3BlbigpO1xuXHRcdFx0ZG9jLndyaXRlKCcnKTtcblx0XHRcdGRvYy5jbG9zZSgpO1xuXHRcdFx0Y29uc3QgbWVzc2FnZSA9ICdjYWxsSW1tZWRpYXRlJyArIE1hdGgucmFuZG9tKCk7XG5cdFx0XHRjb25zdCBvcmlnaW4gPSB3aW4ubG9jYXRpb24ucHJvdG9jb2wgKyAnLy8nICsgd2luLmxvY2F0aW9uLmhvc3Q7XG5cdFx0XHRjb25zdCBvbm1lc3NhZ2UgPSBmdW5jdGlvbihlKSB7XG5cdFx0XHRcdC8vIFZhbGlkYXRlIG9yaWdpbiBhbmQgbWVzc2FnZSB0byBtYWtlIHN1cmUgdGhhdCB0aGlzIG1lc3NhZ2Ugd2FzXG5cdFx0XHRcdC8vIGludGVuZGVkIGZvciB1cy5cblx0XHRcdFx0aWYgKGUub3JpZ2luICE9PSBvcmlnaW4gJiYgZS5kYXRhICE9PSBtZXNzYWdlKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMucG9ydDEub25tZXNzYWdlKCk7XG5cdFx0XHR9LmJpbmQodGhpcyk7XG5cdFx0XHR3aW4uYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9ubWVzc2FnZSwgZmFsc2UpO1xuXHRcdFx0dGhpcy5wb3J0MSA9IHt9O1xuXHRcdFx0dGhpcy5wb3J0MiA9IHtcblx0XHRcdFx0cG9zdE1lc3NhZ2U6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHdpbi5wb3N0TWVzc2FnZShtZXNzYWdlLCBvcmlnaW4pO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdH07XG5cdH1cblx0aWYgKHR5cGVvZiBDaGFubmVsICE9PSAndW5kZWZpbmVkJykge1xuXHRcdGNvbnN0IGNoYW5uZWwgPSBuZXcgQ2hhbm5lbCgpO1xuXHRcdC8vIFVzZSBhIGZpZm8gbGlua2VkIGxpc3QgdG8gY2FsbCBjYWxsYmFja3MgaW4gdGhlIHJpZ2h0IG9yZGVyLlxuXHRcdGxldCBoZWFkID0ge307XG5cdFx0bGV0IHRhaWwgPSBoZWFkO1xuXHRcdGNoYW5uZWwucG9ydDEub25tZXNzYWdlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRoZWFkID0gaGVhZC5uZXh0O1xuXHRcdFx0Y29uc3QgY2IgPSBoZWFkLmNiO1xuXHRcdFx0aGVhZC5jYiA9IG51bGw7XG5cdFx0XHRjYigpO1xuXHRcdH07XG5cdFx0cmV0dXJuIGZ1bmN0aW9uKGNiKSB7XG5cdFx0XHR0YWlsLm5leHQgPSB7XG5cdFx0XHRcdGNiOiBjYlxuXHRcdFx0fTtcblx0XHRcdHRhaWwgPSB0YWlsLm5leHQ7XG5cdFx0XHRjaGFubmVsLnBvcnQyLnBvc3RNZXNzYWdlKDApO1xuXHRcdH07XG5cdH1cblx0Ly8gSW1wbGVtZW50YXRpb24gZm9yIElFNi04OiBTY3JpcHQgZWxlbWVudHMgZmlyZSBhbiBhc3luY2hyb25vdXNcblx0Ly8gb25yZWFkeXN0YXRlY2hhbmdlIGV2ZW50IHdoZW4gaW5zZXJ0ZWQgaW50byB0aGUgRE9NLlxuXHRpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiAnb25yZWFkeXN0YXRlY2hhbmdlJyBpblxuXHRcdGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpKSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uKGNiKSB7XG5cdFx0XHRsZXQgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG5cdFx0XHRzY3JpcHQub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdC8vIENsZWFuIHVwIGFuZCBjYWxsIHRoZSBjYWxsYmFjay5cblx0XHRcdFx0c2NyaXB0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG5cdFx0XHRcdHNjcmlwdC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHNjcmlwdCk7XG5cdFx0XHRcdHNjcmlwdCA9IG51bGw7XG5cdFx0XHRcdGNiKCk7XG5cdFx0XHRcdGNiID0gbnVsbDtcblx0XHRcdH07XG5cdFx0XHRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcblx0XHR9O1xuXHR9XG5cdC8vIEZhbGwgYmFjayB0byBzZXRUaW1lb3V0IHdpdGggMC4gSW4gYnJvd3NlcnMgdGhpcyBjcmVhdGVzIGEgZGVsYXkgb2YgNW1zXG5cdC8vIG9yIG1vcmUuXG5cdHJldHVybiBmdW5jdGlvbihjYikge1xuXHRcdHNldFRpbWVvdXQoY2IsIDApO1xuXHR9O1xufTtcblxuXG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbiB0aGF0IGlzIG92ZXJyaWRlZCB0byBwcm90ZWN0IGNhbGxiYWNrcyB3aXRoIGVudHJ5IHBvaW50XG4gKiBtb25pdG9yIGlmIHRoZSBhcHBsaWNhdGlvbiBtb25pdG9ycyBlbnRyeSBwb2ludHMuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGNhbGxiYWNrIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGZpcmUgYXMgc29vbiBhcyBwb3NzaWJsZS5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKCl9IFRoZSB3cmFwcGVkIGNhbGxiYWNrLlxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMubmV4dFRpY2sud3JhcENhbGxiYWNrXyA9IGZ1bmN0aW9uKG9wdF9yZXR1cm5WYWx1ZSkge1xuXHRyZXR1cm4gb3B0X3JldHVyblZhbHVlO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmM7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogRGlzcG9zYWJsZSB1dGlsaXR5LiBXaGVuIGluaGVyaXRlZCBwcm92aWRlcyB0aGUgYGRpc3Bvc2VgIGZ1bmN0aW9uIHRvIGl0c1xuICogc3ViY2xhc3MsIHdoaWNoIGlzIHJlc3BvbnNpYmxlIGZvciBkaXNwb3Npbmcgb2YgYW55IG9iamVjdCByZWZlcmVuY2VzXG4gKiB3aGVuIGFuIGluc3RhbmNlIHdvbid0IGJlIHVzZWQgYW55bW9yZS4gU3ViY2xhc3NlcyBzaG91bGQgb3ZlcnJpZGVcbiAqIGBkaXNwb3NlSW50ZXJuYWxgIHRvIGltcGxlbWVudCBhbnkgc3BlY2lmaWMgZGlzcG9zaW5nIGxvZ2ljLlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmNsYXNzIERpc3Bvc2FibGUge1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHQvKipcblx0XHQgKiBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBpbnN0YW5jZSBoYXMgYWxyZWFkeSBiZWVuIGRpc3Bvc2VkLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmRpc3Bvc2VkXyA9IGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy4gQ2FsbHMgYGRpc3Bvc2VJbnRlcm5hbGAuXG5cdCAqL1xuXHRkaXNwb3NlKCkge1xuXHRcdGlmICghdGhpcy5kaXNwb3NlZF8pIHtcblx0XHRcdHRoaXMuZGlzcG9zZUludGVybmFsKCk7XG5cdFx0XHR0aGlzLmRpc3Bvc2VkXyA9IHRydWU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFN1YmNsYXNzZXMgc2hvdWxkIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGltcGxlbWVudCBhbnkgc3BlY2lmaWNcblx0ICogZGlzcG9zaW5nIGxvZ2ljIChsaWtlIGNsZWFyaW5nIHJlZmVyZW5jZXMgYW5kIGNhbGxpbmcgYGRpc3Bvc2VgIG9uIG90aGVyXG5cdCAqIGRpc3Bvc2FibGVzKS5cblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHt9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGlzIGluc3RhbmNlIGhhcyBhbHJlYWR5IGJlZW4gZGlzcG9zZWQuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRpc0Rpc3Bvc2VkKCkge1xuXHRcdHJldHVybiB0aGlzLmRpc3Bvc2VkXztcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBEaXNwb3NhYmxlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5jbGFzcyBvYmplY3Qge1xuXHQvKipcblx0ICogQ29waWVzIGFsbCB0aGUgbWVtYmVycyBvZiBhIHNvdXJjZSBvYmplY3QgdG8gYSB0YXJnZXQgb2JqZWN0LlxuXHQgKiBAcGFyYW0ge09iamVjdH0gdGFyZ2V0IFRhcmdldCBvYmplY3QuXG5cdCAqIEBwYXJhbSB7Li4uT2JqZWN0fSB2YXJfYXJncyBUaGUgb2JqZWN0cyBmcm9tIHdoaWNoIHZhbHVlcyB3aWxsIGJlIGNvcGllZC5cblx0ICogQHJldHVybiB7T2JqZWN0fSBSZXR1cm5zIHRoZSB0YXJnZXQgb2JqZWN0IHJlZmVyZW5jZS5cblx0ICovXG5cdHN0YXRpYyBtaXhpbih0YXJnZXQpIHtcblx0XHRsZXQga2V5LCBzb3VyY2U7XG5cdFx0Zm9yIChsZXQgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHNvdXJjZSA9IGFyZ3VtZW50c1tpXTtcblx0XHRcdGZvciAoa2V5IGluIHNvdXJjZSkge1xuXHRcdFx0XHR0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdGFyZ2V0O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYW4gb2JqZWN0IGJhc2VkIG9uIGl0cyBmdWxseSBxdWFsaWZpZWQgZXh0ZXJuYWwgbmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIGZ1bGx5IHF1YWxpZmllZCBuYW1lLlxuXHQgKiBAcGFyYW0ge29iamVjdD19IG9wdF9vYmogVGhlIG9iamVjdCB3aXRoaW4gd2hpY2ggdG8gbG9vazsgZGVmYXVsdCBpc1xuXHQgKiAgICAgPGNvZGU+d2luZG93PC9jb2RlPi5cblx0ICogQHJldHVybiB7P30gVGhlIHZhbHVlIChvYmplY3Qgb3IgcHJpbWl0aXZlKSBvciwgaWYgbm90IGZvdW5kLCB1bmRlZmluZWQuXG5cdCAqL1xuXHRzdGF0aWMgZ2V0T2JqZWN0QnlOYW1lKG5hbWUsIG9wdF9vYmopIHtcblx0XHRjb25zdCBzY29wZSA9IG9wdF9vYmogfHwgd2luZG93O1xuXHRcdGNvbnN0IHBhcnRzID0gbmFtZS5zcGxpdCgnLicpO1xuXHRcdHJldHVybiBwYXJ0cy5yZWR1Y2UoKHBhcnQsIGtleSkgPT4gcGFydFtrZXldLCBzY29wZSk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIG5ldyBvYmplY3Qgd2l0aCB0aGUgc2FtZSBrZXlzIGFzIHRoZSBnaXZlbiBvbmUsIGJ1dCB3aXRoXG5cdCAqIHRoZWlyIHZhbHVlcyBzZXQgdG8gdGhlIHJldHVybiB2YWx1ZXMgb2YgdGhlIHNwZWNpZmllZCBmdW5jdGlvbi5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBvYmpcblx0ICogQHBhcmFtIHshZnVuY3Rpb24oc3RyaW5nLCAqKX0gZm5cblx0ICogQHJldHVybiB7IU9iamVjdH1cblx0ICovXG5cdHN0YXRpYyBtYXAob2JqLCBmbikge1xuXHRcdGNvbnN0IG1hcHBlZE9iaiA9IHt9O1xuXHRcdGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhvYmopO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0bWFwcGVkT2JqW2tleXNbaV1dID0gZm4oa2V5c1tpXSwgb2JqW2tleXNbaV1dKTtcblx0XHR9XG5cdFx0cmV0dXJuIG1hcHBlZE9iajtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIHR3byBnaXZlbiBvYmplY3RzIGFyZSBlcXVhbC4gVGhpcyBpcyBkb25lIHZpYSBhIHNoYWxsb3dcblx0ICogY2hlY2ssIGluY2x1ZGluZyBvbmx5IHRoZSBrZXlzIGRpcmVjdGx5IGNvbnRhaW5lZCBieSB0aGUgMiBvYmplY3RzLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0c3RhdGljIHNoYWxsb3dFcXVhbChvYmoxLCBvYmoyKSB7XG5cdFx0aWYgKG9iajEgPT09IG9iajIpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdGNvbnN0IGtleXMxID0gT2JqZWN0LmtleXMob2JqMSk7XG5cdFx0Y29uc3Qga2V5czIgPSBPYmplY3Qua2V5cyhvYmoyKTtcblx0XHRpZiAoa2V5czEubGVuZ3RoICE9PSBrZXlzMi5sZW5ndGgpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGtleXMxLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAob2JqMVtrZXlzMVtpXV0gIT09IG9iajJba2V5czFbaV1dKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgb2JqZWN0O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5jbGFzcyBzdHJpbmcge1xuXHQvKipcblx0ICogQ29tcGFyZXMgdGhlIGdpdmVuIHN0cmluZ3Mgd2l0aG91dCB0YWtpbmcgdGhlIGNhc2UgaW50byBhY2NvdW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHN0cjFcblx0ICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBzdHIyXG5cdCAqIEByZXR1cm4ge251bWJlcn0gRWl0aGVyIC0xLCAwIG9yIDEsIGFjY29yZGluZyB0byBpZiB0aGUgZmlyc3Qgc3RyaW5nIGlzXG5cdCAqICAgICBcInNtYWxsZXJcIiwgZXF1YWwgb3IgXCJiaWdnZXJcIiB0aGFuIHRoZSBzZWNvbmQgZ2l2ZW4gc3RyaW5nLlxuXHQgKi9cblx0c3RhdGljIGNhc2VJbnNlbnNpdGl2ZUNvbXBhcmUoc3RyMSwgc3RyMikge1xuXHRcdGNvbnN0IHRlc3QxID0gU3RyaW5nKHN0cjEpLnRvTG93ZXJDYXNlKCk7XG5cdFx0Y29uc3QgdGVzdDIgPSBTdHJpbmcoc3RyMikudG9Mb3dlckNhc2UoKTtcblxuXHRcdGlmICh0ZXN0MSA8IHRlc3QyKSB7XG5cdFx0XHRyZXR1cm4gLTE7XG5cdFx0fSBlbHNlIGlmICh0ZXN0MSA9PT0gdGVzdDIpIHtcblx0XHRcdHJldHVybiAwO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gMTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyB0aGUgYnJlYWtpbmcgc3BhY2VzIGZyb20gdGhlIGxlZnQgYW5kIHJpZ2h0IG9mIHRoZSBzdHJpbmcgYW5kXG5cdCAqIGNvbGxhcHNlcyB0aGUgc2VxdWVuY2VzIG9mIGJyZWFraW5nIHNwYWNlcyBpbiB0aGUgbWlkZGxlIGludG8gc2luZ2xlIHNwYWNlcy5cblx0ICogVGhlIG9yaWdpbmFsIGFuZCB0aGUgcmVzdWx0IHN0cmluZ3MgcmVuZGVyIHRoZSBzYW1lIHdheSBpbiBIVE1MLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyIEEgc3RyaW5nIGluIHdoaWNoIHRvIGNvbGxhcHNlIHNwYWNlcy5cblx0ICogQHJldHVybiB7c3RyaW5nfSBDb3B5IG9mIHRoZSBzdHJpbmcgd2l0aCBub3JtYWxpemVkIGJyZWFraW5nIHNwYWNlcy5cblx0ICovXG5cdHN0YXRpYyBjb2xsYXBzZUJyZWFraW5nU3BhY2VzKHN0cikge1xuXHRcdHJldHVybiBzdHIucmVwbGFjZSgvW1xcdFxcclxcbiBdKy9nLCAnICcpLnJlcGxhY2UoL15bXFx0XFxyXFxuIF0rfFtcXHRcXHJcXG4gXSskL2csICcnKTtcblx0fVxuXG5cdC8qKlxuXHQqIEVzY2FwZXMgY2hhcmFjdGVycyBpbiB0aGUgc3RyaW5nIHRoYXQgYXJlIG5vdCBzYWZlIHRvIHVzZSBpbiBhIFJlZ0V4cC5cblx0KiBAcGFyYW0geyp9IHN0ciBUaGUgc3RyaW5nIHRvIGVzY2FwZS4gSWYgbm90IGEgc3RyaW5nLCBpdCB3aWxsIGJlIGNhc3RlZFxuXHQqICAgICB0byBvbmUuXG5cdCogQHJldHVybiB7c3RyaW5nfSBBIFJlZ0V4cCBzYWZlLCBlc2NhcGVkIGNvcHkgb2Yge0Bjb2RlIHN9LlxuXHQqL1xuXHRzdGF0aWMgZXNjYXBlUmVnZXgoc3RyKSB7XG5cdFx0cmV0dXJuIFN0cmluZyhzdHIpXG5cdFx0XHQucmVwbGFjZSgvKFstKClcXFtcXF17fSs/Ki4kXFxefCw6IzwhXFxcXF0pL2csICdcXFxcJDEnKVxuXHRcdFx0LnJlcGxhY2UoL1xceDA4L2csICdcXFxceDA4Jyk7XG5cdH1cblxuXHQvKipcblx0KiBSZXR1cm5zIGEgc3RyaW5nIHdpdGggYXQgbGVhc3QgNjQtYml0cyBvZiByYW5kb21uZXNzLlxuXHQqIEByZXR1cm4ge3N0cmluZ30gQSByYW5kb20gc3RyaW5nLCBlLmcuIHNuMXM3dmI0Z2NpYy5cblx0Ki9cblx0c3RhdGljIGdldFJhbmRvbVN0cmluZygpIHtcblx0XHRjb25zdCB4ID0gMjE0NzQ4MzY0ODtcblx0XHRyZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogeCkudG9TdHJpbmcoMzYpICtcblx0XHRcdE1hdGguYWJzKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHgpIF4gRGF0ZS5ub3coKSkudG9TdHJpbmcoMzYpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGN1bGF0ZXMgdGhlIGhhc2hjb2RlIGZvciBhIHN0cmluZy4gVGhlIGhhc2hjb2RlIHZhbHVlIGlzIGNvbXB1dGVkIGJ5XG5cdCAqIHRoZSBzdW0gYWxnb3JpdGhtOiBzWzBdKjMxXihuLTEpICsgc1sxXSozMV4obi0yKSArIC4uLiArIHNbbi0xXS4gQSBuaWNlXG5cdCAqIHByb3BlcnR5IG9mIHVzaW5nIDMxIHByaW1lIGlzIHRoYXQgdGhlIG11bHRpcGxpY2F0aW9uIGNhbiBiZSByZXBsYWNlZCBieVxuXHQgKiBhIHNoaWZ0IGFuZCBhIHN1YnRyYWN0aW9uIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2U6IDMxKmkgPT0gKGk8PDUpLWkuXG5cdCAqIE1vZGVybiBWTXMgZG8gdGhpcyBzb3J0IG9mIG9wdGltaXphdGlvbiBhdXRvbWF0aWNhbGx5LlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdmFsIFRhcmdldCBzdHJpbmcuXG5cdCAqIEByZXR1cm4ge051bWJlcn0gUmV0dXJucyB0aGUgc3RyaW5nIGhhc2hjb2RlLlxuXHQgKi9cblx0c3RhdGljIGhhc2hDb2RlKHZhbCkge1xuXHRcdGxldCBoYXNoID0gMDtcblx0XHRmb3IgKGxldCBpID0gMCwgbGVuID0gdmFsLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRoYXNoID0gMzEgKiBoYXNoICsgdmFsLmNoYXJDb2RlQXQoaSk7XG5cdFx0XHRoYXNoICU9IDB4MTAwMDAwMDAwO1xuXHRcdH1cblx0XHRyZXR1cm4gaGFzaDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXBsYWNlcyBpbnRlcnZhbCBpbnRvIHRoZSBzdHJpbmcgd2l0aCBzcGVjaWZpZWQgdmFsdWUsIGUuZy5cblx0ICogYHJlcGxhY2VJbnRlcnZhbChcImFiY2RlXCIsIDEsIDQsIFwiXCIpYCByZXR1cm5zIFwiYWVcIi5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHN0ciBUaGUgaW5wdXQgc3RyaW5nLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gc3RhcnQgU3RhcnQgaW50ZXJ2YWwgcG9zaXRpb24gdG8gYmUgcmVwbGFjZWQuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBlbmQgRW5kIGludGVydmFsIHBvc2l0aW9uIHRvIGJlIHJlcGxhY2VkLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVGhlIHZhbHVlIHRoYXQgcmVwbGFjZXMgdGhlIHNwZWNpZmllZCBpbnRlcnZhbC5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0c3RhdGljIHJlcGxhY2VJbnRlcnZhbChzdHIsIHN0YXJ0LCBlbmQsIHZhbHVlKSB7XG5cdFx0cmV0dXJuIHN0ci5zdWJzdHJpbmcoMCwgc3RhcnQpICsgdmFsdWUgKyBzdHIuc3Vic3RyaW5nKGVuZCk7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgc3RyaW5nO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFBhcnNlcyB0aGUgZ2l2ZW4gdXJpIHN0cmluZyBpbnRvIGFuIG9iamVjdC5cbiAqIEBwYXJhbSB7Kj19IG9wdF91cmkgT3B0aW9uYWwgc3RyaW5nIFVSSSB0byBwYXJzZVxuICovXG5mdW5jdGlvbiBwYXJzZUZyb21BbmNob3Iob3B0X3VyaSkge1xuXHR2YXIgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcblx0bGluay5ocmVmID0gb3B0X3VyaTtcblxuXHRpZihsaW5rLnByb3RvY29sID09PSAnOicgfHwgIS86Ly50ZXN0KGxpbmsuaHJlZikpIHtcblx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKGAke29wdF91cml9IGlzIG5vdCBhIHZhbGlkIFVSTGApO1xuXHR9XG5cblx0cmV0dXJuIHtcblx0XHRoYXNoOiBsaW5rLmhhc2gsXG5cdFx0aG9zdG5hbWU6IGxpbmsuaG9zdG5hbWUsXG5cdFx0cGFzc3dvcmQ6IGxpbmsucGFzc3dvcmQsXG5cdFx0cGF0aG5hbWU6IGxpbmsucGF0aG5hbWVbMF0gPT09ICcvJyA/IGxpbmsucGF0aG5hbWUgOiAnLycgKyBsaW5rLnBhdGhuYW1lLFxuXHRcdHBvcnQ6IGxpbmsucG9ydCxcblx0XHRwcm90b2NvbDogbGluay5wcm90b2NvbCxcblx0XHRzZWFyY2g6IGxpbmsuc2VhcmNoLFxuXHRcdHVzZXJuYW1lOiBsaW5rLnVzZXJuYW1lXG5cdH07XG59XG5cbmV4cG9ydCBkZWZhdWx0IHBhcnNlRnJvbUFuY2hvcjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaXNGdW5jdGlvbiB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBwYXJzZUZyb21BbmNob3IgZnJvbSAnLi9wYXJzZUZyb21BbmNob3InO1xuXG4vKipcbiAqIFBhcnNlcyB0aGUgZ2l2ZW4gdXJpIHN0cmluZyBpbnRvIGFuIG9iamVjdC4gVGhlIFVSTCBmdW5jdGlvbiB3aWxsIGJlIHVzZWRcbiAqIHdoZW4gcHJlc2VudCwgb3RoZXJ3aXNlIHdlJ2xsIGZhbGwgYmFjayB0byB0aGUgYW5jaG9yIG5vZGUgZWxlbWVudC5cbiAqIEBwYXJhbSB7Kj19IG9wdF91cmkgT3B0aW9uYWwgc3RyaW5nIFVSSSB0byBwYXJzZVxuICovXG5mdW5jdGlvbiBwYXJzZShvcHRfdXJpKSB7XG5cdGlmIChpc0Z1bmN0aW9uKFVSTCkgJiYgVVJMLmxlbmd0aCkge1xuXHRcdGNvbnN0IHVybCA9IG5ldyBVUkwob3B0X3VyaSk7XG5cblx0XHQvLyBTYWZhcmkgQnJvd3NlcnMgd2lsbCBjYXAgcG9ydCB0byB0aGUgbWF4IDE2LWJpdCB1bnNpZ25lZCBpbnRlZ2VyICg2NTUzNSkgaW5zdGVhZFxuXHRcdC8vIG9mIHRocm93aW5nIGEgVHlwZUVycm9yIGFzIHBlciBzcGVjLiBJdCB3aWxsIHN0aWxsIGtlZXAgdGhlIHBvcnQgbnVtYmVyIGluIHRoZVxuXHRcdC8vIGhyZWYgYXR0cmlidXRlLCBzbyB3ZSBjYW4gdXNlIHRoaXMgbWlzbWF0Y2ggdG8gcmFpc2UgdGhlIGV4cGVjdGVkIGV4Y2VwdGlvbi5cblx0XHRpZiAodXJsLnBvcnQgJiYgdXJsLmhyZWYuaW5kZXhPZih1cmwucG9ydCkgPT09IC0xKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKGAke29wdF91cml9IGlzIG5vdCBhIHZhbGlkIFVSTGApO1xuXHRcdH1cblxuXHRcdHJldHVybiB1cmw7XG5cdH0gZWxzZSB7XG5cdFx0cmV0dXJuIHBhcnNlRnJvbUFuY2hvcihvcHRfdXJpKTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBwYXJzZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgRGlzcG9zYWJsZSB9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBBIGNhY2hlZCByZWZlcmVuY2UgdG8gdGhlIGNyZWF0ZSBmdW5jdGlvbi5cbiAqL1xudmFyIGNyZWF0ZSA9IE9iamVjdC5jcmVhdGU7XG5cbi8qKlxuICogQ2FzZSBpbnNlbnNpdGl2ZSBzdHJpbmcgTXVsdGltYXAgaW1wbGVtZW50YXRpb24uIEFsbG93cyBtdWx0aXBsZSB2YWx1ZXMgZm9yXG4gKiB0aGUgc2FtZSBrZXkgbmFtZS5cbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBNdWx0aU1hcCBleHRlbmRzIERpc3Bvc2FibGUge1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXHRcdHRoaXMua2V5cyA9IGNyZWF0ZShudWxsKTtcblx0XHR0aGlzLnZhbHVlcyA9IGNyZWF0ZShudWxsKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIHZhbHVlIHRvIGEga2V5IG5hbWUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG5cdCAqIEBwYXJhbSB7Kn0gdmFsdWVcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkKG5hbWUsIHZhbHVlKSB7XG5cdFx0dGhpcy5rZXlzW25hbWUudG9Mb3dlckNhc2UoKV0gPSBuYW1lO1xuXHRcdHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV0gPSB0aGlzLnZhbHVlc1tuYW1lLnRvTG93ZXJDYXNlKCldIHx8IFtdO1xuXHRcdHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV0ucHVzaCh2YWx1ZSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQ2xlYXJzIG1hcCBuYW1lcyBhbmQgdmFsdWVzLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRjbGVhcigpIHtcblx0XHR0aGlzLmtleXMgPSBjcmVhdGUobnVsbCk7XG5cdFx0dGhpcy52YWx1ZXMgPSBjcmVhdGUobnVsbCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIG1hcCBjb250YWlucyBhIHZhbHVlIHRvIHRoZSBrZXkgbmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0Y29udGFpbnMobmFtZSkge1xuXHRcdHJldHVybiBuYW1lLnRvTG93ZXJDYXNlKCkgaW4gdGhpcy52YWx1ZXM7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLnZhbHVlcyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIGBNdWx0aU1hcGAgaW5zdGFuY2UgZnJvbSB0aGUgZ2l2ZW4gb2JqZWN0LlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IG9ialxuXHQgKiBAcmV0dXJuIHshTXVsdGlNYXB9XG5cdCAqL1xuXHRzdGF0aWMgZnJvbU9iamVjdChvYmopIHtcblx0XHR2YXIgbWFwID0gbmV3IE11bHRpTWFwKCk7XG5cdFx0dmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmopO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0bWFwLnNldChrZXlzW2ldLCBvYmpba2V5c1tpXV0pO1xuXHRcdH1cblx0XHRyZXR1cm4gbWFwO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGZpcnN0IGFkZGVkIHZhbHVlIGZyb20gYSBrZXkgbmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHJldHVybiB7Kn1cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0Z2V0KG5hbWUpIHtcblx0XHR2YXIgdmFsdWVzID0gdGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXTtcblx0XHRpZiAodmFsdWVzKSB7XG5cdFx0XHRyZXR1cm4gdmFsdWVzWzBdO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGFsbCB2YWx1ZXMgZnJvbSBhIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAcmV0dXJuIHtBcnJheS48Kj59XG5cdCAqL1xuXHRnZXRBbGwobmFtZSkge1xuXHRcdHJldHVybiB0aGlzLnZhbHVlc1tuYW1lLnRvTG93ZXJDYXNlKCldO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgbWFwIGlzIGVtcHR5LCBmYWxzZSBvdGhlcndpc2UuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRpc0VtcHR5KCkge1xuXHRcdHJldHVybiB0aGlzLnNpemUoKSA9PT0gMDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGFycmF5IG9mIGtleSBuYW1lcy5cblx0ICogQHJldHVybiB7QXJyYXkuPHN0cmluZz59XG5cdCAqL1xuXHRuYW1lcygpIHtcblx0XHRyZXR1cm4gT2JqZWN0LmtleXModGhpcy52YWx1ZXMpLm1hcCgoa2V5KSA9PiB0aGlzLmtleXNba2V5XSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhbGwgdmFsdWVzIGZyb20gYSBrZXkgbmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0cmVtb3ZlKG5hbWUpIHtcblx0XHRkZWxldGUgdGhpcy5rZXlzW25hbWUudG9Mb3dlckNhc2UoKV07XG5cdFx0ZGVsZXRlIHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV07XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgdmFsdWUgb2YgYSBrZXkgbmFtZS4gUmVsZXZhbnQgdG8gcmVwbGFjZSB0aGUgY3VycmVudCB2YWx1ZXMgd2l0aFxuXHQgKiBhIG5ldyBvbmUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG5cdCAqIEBwYXJhbSB7Kn0gdmFsdWVcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0c2V0KG5hbWUsIHZhbHVlKSB7XG5cdFx0dGhpcy5rZXlzW25hbWUudG9Mb3dlckNhc2UoKV0gPSBuYW1lO1xuXHRcdHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV0gPSBbdmFsdWVdO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHNpemUgb2YgdGhlIG1hcCBrZXkgbmFtZXMuXG5cdCAqIEByZXR1cm4ge251bWJlcn1cblx0ICovXG5cdHNpemUoKSB7XG5cdFx0cmV0dXJuIHRoaXMubmFtZXMoKS5sZW5ndGg7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgcGFyc2VkIHZhbHVlcyBhcyBhIHN0cmluZy5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0dG9TdHJpbmcoKSB7XG5cdFx0cmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMudmFsdWVzKTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBNdWx0aU1hcDtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgYXJyYXkgfSBmcm9tICdtZXRhbCc7XG5cbi8qKlxuICogR2VuZXJpYyB0cmVlIG5vZGUgZGF0YSBzdHJ1Y3R1cmUgd2l0aCBhcmJpdHJhcnkgbnVtYmVyIG9mIGNoaWxkIG5vZGVzLlxuICogQHBhcmFtIHtWfSB2YWx1ZSBWYWx1ZS5cbiAqIEBjb25zdHJ1Y3RvclxuICovXG5jbGFzcyBUcmVlTm9kZSB7XG5cblx0Y29uc3RydWN0b3IodmFsdWUpIHtcblx0XHQvKipcblx0XHQgKiBUaGUgdmFsdWUuXG5cdFx0ICogQHByaXZhdGUge1Z9XG5cdFx0ICovXG5cdFx0dGhpcy52YWx1ZV8gPSB2YWx1ZTtcblxuXHRcdC8qKlxuXHRcdCAqIFJlZmVyZW5jZSB0byB0aGUgcGFyZW50IG5vZGUgb3IgbnVsbCBpZiBpdCBoYXMgbm8gcGFyZW50LlxuXHRcdCAqIEBwcml2YXRlIHtUcmVlTm9kZX1cblx0XHQgKi9cblx0XHR0aGlzLnBhcmVudF8gPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogQ2hpbGQgbm9kZXMgb3IgbnVsbCBpbiBjYXNlIG9mIGxlYWYgbm9kZS5cblx0XHQgKiBAcHJpdmF0ZSB7QXJyYXk8IVRyZWVOb2RlPn1cblx0XHQgKi9cblx0XHR0aGlzLmNoaWxkcmVuXyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogQXBwZW5kcyBhIGNoaWxkIG5vZGUgdG8gdGhpcyBub2RlLlxuXHQgKiBAcGFyYW0geyFUcmVlTm9kZX0gY2hpbGQgT3JwaGFuIGNoaWxkIG5vZGUuXG5cdCAqL1xuXHRhZGRDaGlsZChjaGlsZCkge1xuXHRcdGFzc2VydENoaWxkSGFzTm9QYXJlbnQoY2hpbGQpO1xuXHRcdGNoaWxkLnNldFBhcmVudCh0aGlzKTtcblx0XHR0aGlzLmNoaWxkcmVuXyA9IHRoaXMuY2hpbGRyZW5fIHx8IFtdO1xuXHRcdHRoaXMuY2hpbGRyZW5fLnB1c2goY2hpbGQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRlbGxzIHdoZXRoZXIgdGhpcyBub2RlIGlzIHRoZSBhbmNlc3RvciBvZiB0aGUgZ2l2ZW4gbm9kZS5cblx0ICogQHBhcmFtIHshVHJlZU5vZGV9IG5vZGUgQSBub2RlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHRoaXMgbm9kZSBpcyB0aGUgYW5jZXN0b3Igb2Yge0Bjb2RlIG5vZGV9LlxuXHQgKi9cblx0Y29udGFpbnMobm9kZSkge1xuXHRcdGxldCBjdXJyZW50ID0gbm9kZS5nZXRQYXJlbnQoKTtcblx0XHR3aGlsZSAoY3VycmVudCkge1xuXHRcdFx0aWYgKGN1cnJlbnQgPT09IHRoaXMpIHtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0XHRjdXJyZW50ID0gY3VycmVudC5nZXRQYXJlbnQoKTtcblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4geyFBcnJheTxUcmVlTm9kZT59IEFsbCBhbmNlc3RvciBub2RlcyBpbiBib3R0b20tdXAgb3JkZXIuXG5cdCAqL1xuXHRnZXRBbmNlc3RvcnMoKSB7XG5cdFx0bGV0IGFuY2VzdG9ycyA9IFtdO1xuXHRcdGxldCBub2RlID0gdGhpcy5nZXRQYXJlbnQoKTtcblx0XHR3aGlsZSAobm9kZSkge1xuXHRcdFx0YW5jZXN0b3JzLnB1c2gobm9kZSk7XG5cdFx0XHRub2RlID0gbm9kZS5nZXRQYXJlbnQoKTtcblx0XHR9XG5cdFx0cmV0dXJuIGFuY2VzdG9ycztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjaGlsZCBub2RlIG9mIHRoaXMgbm9kZSBhdCB0aGUgZ2l2ZW4gaW5kZXguXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBDaGlsZCBpbmRleC5cblx0ICogQHJldHVybiB7P1RyZWVOb2RlfSBUaGUgbm9kZSBhdCB0aGUgZ2l2ZW4gaW5kZXhcblx0ICogb3IgbnVsbCBpZiBub3QgZm91bmQuXG5cdCAqL1xuXHRnZXRDaGlsZEF0KGluZGV4KSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0Q2hpbGRyZW4oKVtpbmRleF0gfHwgbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHs/QXJyYXk8IVRyZWVOb2RlPn0gQ2hpbGQgbm9kZXMgb3IgbnVsbCBpbiBjYXNlIG9mIGxlYWYgbm9kZS5cblx0ICovXG5cdGdldENoaWxkcmVuKCkge1xuXHRcdHJldHVybiB0aGlzLmNoaWxkcmVuXyB8fCBUcmVlTm9kZS5FTVBUWV9BUlJBWTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgY2hpbGRyZW4uXG5cdCAqL1xuXHRnZXRDaGlsZENvdW50KCkge1xuXHRcdHJldHVybiB0aGlzLmdldENoaWxkcmVuKCkubGVuZ3RoO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBhbmNlc3RvcnMgb2YgdGhlIG5vZGUuXG5cdCAqL1xuXHRnZXREZXB0aCgpIHtcblx0XHRsZXQgZGVwdGggPSAwO1xuXHRcdGxldCBub2RlID0gdGhpcztcblx0XHR3aGlsZSAobm9kZS5nZXRQYXJlbnQoKSkge1xuXHRcdFx0ZGVwdGgrKztcblx0XHRcdG5vZGUgPSBub2RlLmdldFBhcmVudCgpO1xuXHRcdH1cblx0XHRyZXR1cm4gZGVwdGg7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7P1RyZWVOb2RlfSBQYXJlbnQgbm9kZSBvciBudWxsIGlmIGl0IGhhcyBubyBwYXJlbnQuXG5cdCAqL1xuXHRnZXRQYXJlbnQoKSB7XG5cdFx0cmV0dXJuIHRoaXMucGFyZW50Xztcblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHshVHJlZU5vZGV9IFRoZSByb290IG9mIHRoZSB0cmVlIHN0cnVjdHVyZSwgaS5lLiB0aGUgZmFydGhlc3Rcblx0ICogYW5jZXN0b3Igb2YgdGhlIG5vZGUgb3IgdGhlIG5vZGUgaXRzZWxmIGlmIGl0IGhhcyBubyBwYXJlbnRzLlxuXHQgKi9cblx0Z2V0Um9vdCgpIHtcblx0XHRsZXQgcm9vdCA9IHRoaXM7XG5cdFx0d2hpbGUgKHJvb3QuZ2V0UGFyZW50KCkpIHtcblx0XHRcdHJvb3QgPSByb290LmdldFBhcmVudCgpO1xuXHRcdH1cblx0XHRyZXR1cm4gcm9vdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSB2YWx1ZS5cblx0ICogQHJldHVybiB7Vn0gVGhlIHZhbHVlLlxuXHQgKi9cblx0Z2V0VmFsdWUoKSB7XG5cdFx0cmV0dXJuIHRoaXMudmFsdWVfO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdGhlIG5vZGUgaXMgYSBsZWFmIG5vZGUuXG5cdCAqL1xuXHRpc0xlYWYoKSB7XG5cdFx0cmV0dXJuICF0aGlzLmdldENoaWxkQ291bnQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHRoZSBnaXZlbiBjaGlsZCBub2RlIG9mIHRoaXMgbm9kZS5cblx0ICogQHBhcmFtIHtUcmVlTm9kZX0gY2hpbGQgVGhlIG5vZGUgdG8gcmVtb3ZlLlxuXHQgKiBAcmV0dXJuIHtUcmVlTm9kZX0gVGhlIHJlbW92ZWQgbm9kZSBpZiBhbnksIG51bGwgb3RoZXJ3aXNlLlxuXHQgKi9cblx0cmVtb3ZlQ2hpbGQoY2hpbGQpIHtcblx0XHRpZiAoYXJyYXkucmVtb3ZlKHRoaXMuZ2V0Q2hpbGRyZW4oKSwgY2hpbGQpKSB7XG5cdFx0XHRyZXR1cm4gY2hpbGQ7XG5cdFx0fVxuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHBhcmVudCBub2RlIG9mIHRoaXMgbm9kZS4gVGhlIGNhbGxlcnMgbXVzdCBlbnN1cmUgdGhhdCB0aGVcblx0ICogcGFyZW50IG5vZGUgYW5kIG9ubHkgdGhhdCBoYXMgdGhpcyBub2RlIGFtb25nIGl0cyBjaGlsZHJlbi5cblx0ICogQHBhcmFtIHtUcmVlTm9kZX0gcGFyZW50IFRoZSBwYXJlbnQgdG8gc2V0LiBJZiBudWxsLCB0aGUgbm9kZSB3aWxsIGJlXG5cdCAqIGRldGFjaGVkIGZyb20gdGhlIHRyZWUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHNldFBhcmVudChwYXJlbnQpIHtcblx0XHR0aGlzLnBhcmVudF8gPSBwYXJlbnQ7XG5cdH1cblxuXHQvKipcblx0ICogVHJhdmVyc2VzIHRoZSBzdWJ0cmVlLiBUaGUgZmlyc3QgY2FsbGJhY2sgc3RhcnRzIHdpdGggdGhpcyBub2RlLFxuXHQgKiBhbmQgdmlzaXRzIHRoZSBkZXNjZW5kYW50IG5vZGVzIGRlcHRoLWZpcnN0LCBpbiBwcmVvcmRlci5cblx0ICogVGhlIHNlY29uZCBjYWxsYmFjaywgc3RhcnRzIHdpdGggZGVlcGVzdCBjaGlsZCB0aGVuIHZpc2l0c1xuXHQgKiB0aGUgYW5jZXN0b3Igbm9kZXMgZGVwdGgtZmlyc3QsIGluIHBvc3RvcmRlci4gRS5nLlxuXHQgKlxuXHQgKiAgXHQgQVxuXHQgKiAgICAvIFxcXG5cdCAqICAgQiAgIENcblx0ICogIC8gICAvIFxcXG5cdCAqIEQgICBFICAgRlxuXHQgKlxuXHQgKiBwcmVvcmRlciAtPiBbJ0EnLCAnQicsICdEJywgJ0MnLCAnRScsICdGJ11cblx0ICogcG9zdG9yZGVyIC0+IFsnRCcsICdCJywgJ0UnLCAnRicsICdDJywgJ0EnXVxuXHQgKlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uPX0gb3B0X3ByZW9yZGVyRm4gVGhlIGNhbGxiYWNrIHRvIGV4ZWN1dGUgd2hlbiB2aXNpdGluZyBhIG5vZGUuXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb249fSBvcHRfcG9zdG9yZGVyRm4gVGhlIGNhbGxiYWNrIHRvIGV4ZWN1dGUgYmVmb3JlIGxlYXZpbmcgYSBub2RlLlxuXHQgKi9cblx0dHJhdmVyc2Uob3B0X3ByZW9yZGVyRm4sIG9wdF9wb3N0b3JkZXJGbikge1xuXHRcdGlmIChvcHRfcHJlb3JkZXJGbikge1xuXHRcdFx0b3B0X3ByZW9yZGVyRm4odGhpcyk7XG5cdFx0fVxuXHRcdHRoaXMuZ2V0Q2hpbGRyZW4oKS5mb3JFYWNoKChjaGlsZCkgPT4gY2hpbGQudHJhdmVyc2Uob3B0X3ByZW9yZGVyRm4sIG9wdF9wb3N0b3JkZXJGbikpO1xuXHRcdGlmIChvcHRfcG9zdG9yZGVyRm4pIHtcblx0XHRcdG9wdF9wb3N0b3JkZXJGbih0aGlzKTtcblx0XHR9XG5cdH1cblxufVxuXG4vKipcbiAqIENvbnN0YW50IGZvciBlbXB0eSBhcnJheSB0byBhdm9pZCB1bm5lY2Vzc2FyeSBhbGxvY2F0aW9ucy5cbiAqIEBwcml2YXRlXG4gKi9cblRyZWVOb2RlLkVNUFRZX0FSUkFZID0gW107XG5cbi8qKlxuICogQXNzZXJ0cyB0aGF0IGNoaWxkIGhhcyBubyBwYXJlbnQuXG4gKiBAcGFyYW0ge1RyZWVOb2RlfSBjaGlsZCBBIGNoaWxkLlxuICogQHByaXZhdGVcbiAqL1xuY29uc3QgYXNzZXJ0Q2hpbGRIYXNOb1BhcmVudCA9IGZ1bmN0aW9uKGNoaWxkKSB7XG5cdGlmIChjaGlsZC5nZXRQYXJlbnQoKSkge1xuXHRcdHRocm93IG5ldyBFcnJvcignQ2Fubm90IGFkZCBjaGlsZCB3aXRoIHBhcmVudC4nKTtcblx0fVxufTtcblxuZXhwb3J0IGRlZmF1bHQgVHJlZU5vZGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmLCBzdHJpbmcgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgcGFyc2UgZnJvbSAnLi9wYXJzZSc7XG5pbXBvcnQgeyBNdWx0aU1hcCB9IGZyb20gJ21ldGFsLXN0cnVjdHMnO1xuXG52YXIgcGFyc2VGbl8gPSBwYXJzZTtcblxuY2xhc3MgVXJpIHtcblxuXHQvKipcblx0ICogVGhpcyBjbGFzcyBjb250YWlucyBzZXR0ZXJzIGFuZCBnZXR0ZXJzIGZvciB0aGUgcGFydHMgb2YgdGhlIFVSSS5cblx0ICogVGhlIGZvbGxvd2luZyBmaWd1cmUgZGlzcGxheXMgYW4gZXhhbXBsZSBVUklzIGFuZCB0aGVpciBjb21wb25lbnQgcGFydHMuXG5cdCAqXG5cdCAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGhcblx0ICpcdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAg4pSM4pSA4pSA4pSA4pS04pSA4pSA4pSA4pSA4pSQXG5cdCAqXHQgIGFiYzovL2V4YW1wbGUuY29tOjEyMy9wYXRoL2RhdGE/a2V5PXZhbHVlI2ZyYWdpZDFcblx0ICpcdCAg4pSU4pSs4pSYICAg4pSU4pSA4pSA4pSA4pSA4pSs4pSA4pSA4pSA4pSA4pSYIOKUlOKUrOKUmCAgICAgICAgICAg4pSU4pSA4pSA4pSA4pSs4pSA4pSA4pSA4pSYIOKUlOKUgOKUgOKUrOKUgOKUgOKUmFxuXHQgKiBwcm90b2NvbCAgaG9zdG5hbWUgIHBvcnQgICAgICAgICAgICBzZWFyY2ggICAgaGFzaFxuXHQgKiAgICAgICAgICDilJTilIDilIDilIDilIDilIDilIDilKzilIDilIDilIDilIDilIDilIDilIDilJhcblx0ICogICAgICAgICAgICAgICAgaG9zdFxuXHQgKlxuXHQgKiBAcGFyYW0geyo9fSBvcHRfdXJpIE9wdGlvbmFsIHN0cmluZyBVUkkgdG8gcGFyc2Vcblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihvcHRfdXJpID0gJycpIHtcblx0XHR0aGlzLnVybCA9IFVyaS5wYXJzZSh0aGlzLm1heWJlQWRkUHJvdG9jb2xBbmRIb3N0bmFtZV8ob3B0X3VyaSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgcGFyYW1ldGVycyB0byB1cmkgZnJvbSBhIDxjb2RlPk11bHRpTWFwPC9jb2RlPiBhcyBzb3VyY2UuXG5cdCAqIEBwYXJhbSB7TXVsdGlNYXB9IG11bHRpbWFwIFRoZSA8Y29kZT5NdWx0aU1hcDwvY29kZT4gY29udGFpbmluZyB0aGVcblx0ICogICBwYXJhbWV0ZXJzLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZFBhcmFtZXRlcnNGcm9tTXVsdGlNYXAobXVsdGltYXApIHtcblx0XHRtdWx0aW1hcC5uYW1lcygpLmZvckVhY2goKG5hbWUpID0+IHtcblx0XHRcdG11bHRpbWFwLmdldEFsbChuYW1lKS5mb3JFYWNoKCh2YWx1ZSkgPT4ge1xuXHRcdFx0XHR0aGlzLmFkZFBhcmFtZXRlclZhbHVlKG5hbWUsIHZhbHVlKTtcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIHZhbHVlIG9mIHRoZSBuYW1lZCBxdWVyeSBwYXJhbWV0ZXJzLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuIFdpbGwgYmUgZXhwbGljaXRseSBjYXN0ZWQgdG8gU3RyaW5nLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRhZGRQYXJhbWV0ZXJWYWx1ZShuYW1lLCB2YWx1ZSkge1xuXHRcdHRoaXMuZW5zdXJlUXVlcnlJbml0aWFsaXplZF8oKTtcblx0XHRpZiAoaXNEZWYodmFsdWUpKSB7XG5cdFx0XHR2YWx1ZSA9IFN0cmluZyh2YWx1ZSk7XG5cdFx0fVxuXHRcdHRoaXMucXVlcnkuYWRkKG5hbWUsIHZhbHVlKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIHRoZSB2YWx1ZXMgb2YgdGhlIG5hbWVkIHF1ZXJ5IHBhcmFtZXRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgcGFyYW1ldGVyIHRvIHNldC5cblx0ICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbmV3IHZhbHVlLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRhZGRQYXJhbWV0ZXJWYWx1ZXMobmFtZSwgdmFsdWVzKSB7XG5cdFx0dmFsdWVzLmZvckVhY2goKHZhbHVlKSA9PiB0aGlzLmFkZFBhcmFtZXRlclZhbHVlKG5hbWUsIHZhbHVlKSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogRW5zdXJlcyBxdWVyeSBpbnRlcm5hbCBtYXAgaXMgaW5pdGlhbGl6ZWQgYW5kIHN5bmNlZCB3aXRoIGluaXRpYWwgdmFsdWVcblx0ICogZXh0cmFjdGVkIGZyb20gVVJJIHNlYXJjaCBwYXJ0LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRlbnN1cmVRdWVyeUluaXRpYWxpemVkXygpIHtcblx0XHRpZiAodGhpcy5xdWVyeSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLnF1ZXJ5ID0gbmV3IE11bHRpTWFwKCk7XG5cdFx0dmFyIHNlYXJjaCA9IHRoaXMudXJsLnNlYXJjaDtcblx0XHRpZiAoc2VhcmNoKSB7XG5cdFx0XHRzZWFyY2guc3Vic3RyaW5nKDEpLnNwbGl0KCcmJykuZm9yRWFjaCgocGFyYW0pID0+IHtcblx0XHRcdFx0dmFyIFtrZXksIHZhbHVlXSA9IHBhcmFtLnNwbGl0KCc9Jyk7XG5cdFx0XHRcdGlmIChpc0RlZih2YWx1ZSkpIHtcblx0XHRcdFx0XHR2YWx1ZSA9IFVyaS51cmxEZWNvZGUodmFsdWUpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUoa2V5LCB2YWx1ZSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgaGFzaCBwYXJ0IG9mIHVyaS5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0SGFzaCgpIHtcblx0XHRyZXR1cm4gdGhpcy51cmwuaGFzaCB8fCAnJztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBob3N0IHBhcnQgb2YgdXJpLiBFLmcuIDxjb2RlPltob3N0bmFtZV06W3BvcnRdPC9jb2RlPi5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0SG9zdCgpIHtcblx0XHR2YXIgaG9zdCA9IHRoaXMuZ2V0SG9zdG5hbWUoKTtcblx0XHRpZiAoaG9zdCkge1xuXHRcdFx0dmFyIHBvcnQgPSB0aGlzLmdldFBvcnQoKTtcblx0XHRcdGlmIChwb3J0ICYmIHBvcnQgIT09ICc4MCcpIHtcblx0XHRcdFx0aG9zdCArPSAnOicgKyBwb3J0O1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gaG9zdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBob3N0bmFtZSBwYXJ0IG9mIHVyaSB3aXRob3V0IHByb3RvY29sIGFuZCBwb3J0LlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRIb3N0bmFtZSgpIHtcblx0XHR2YXIgaG9zdG5hbWUgPSB0aGlzLnVybC5ob3N0bmFtZTtcblx0XHRpZiAoaG9zdG5hbWUgPT09IFVyaS5IT1NUTkFNRV9QTEFDRUhPTERFUikge1xuXHRcdFx0cmV0dXJuICcnO1xuXHRcdH1cblx0XHRyZXR1cm4gaG9zdG5hbWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgb3JpZ2luIHBhcnQgb2YgdXJpLiBFLmcuIDxjb2RlPmh0dHA6Ly9baG9zdG5hbWVdOltwb3J0XTwvY29kZT4uXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldE9yaWdpbigpIHtcblx0XHR2YXIgaG9zdCA9IHRoaXMuZ2V0SG9zdCgpO1xuXHRcdGlmIChob3N0KSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5nZXRQcm90b2NvbCgpICsgJy8vJyArIGhvc3Q7XG5cdFx0fVxuXHRcdHJldHVybiAnJztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBmaXJzdCB2YWx1ZSBmb3IgYSBnaXZlbiBwYXJhbWV0ZXIgb3IgdW5kZWZpbmVkIGlmIHRoZSBnaXZlblxuXHQgKiBwYXJhbWV0ZXIgbmFtZSBkb2VzIG5vdCBhcHBlYXIgaW4gdGhlIHF1ZXJ5IHN0cmluZy5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhcmFtTmFtZSBVbmVzY2FwZWQgcGFyYW1ldGVyIG5hbWUuXG5cdCAqIEByZXR1cm4ge3N0cmluZ3x1bmRlZmluZWR9IFRoZSBmaXJzdCB2YWx1ZSBmb3IgYSBnaXZlbiBwYXJhbWV0ZXIgb3Jcblx0ICogICB1bmRlZmluZWQgaWYgdGhlIGdpdmVuIHBhcmFtZXRlciBuYW1lIGRvZXMgbm90IGFwcGVhciBpbiB0aGUgcXVlcnlcblx0ICogICBzdHJpbmcuXG5cdCAqL1xuXHRnZXRQYXJhbWV0ZXJWYWx1ZShuYW1lKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdHJldHVybiB0aGlzLnF1ZXJ5LmdldChuYW1lKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSB2YWx1ZTxiPnM8L2I+IGZvciBhIGdpdmVuIHBhcmFtZXRlciBhcyBhIGxpc3Qgb2YgZGVjb2RlZFxuXHQgKiBxdWVyeSBwYXJhbWV0ZXIgdmFsdWVzLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgcGFyYW1ldGVyIHRvIGdldCB2YWx1ZXMgZm9yLlxuXHQgKiBAcmV0dXJuIHshQXJyYXk8Pz59IFRoZSB2YWx1ZXMgZm9yIGEgZ2l2ZW4gcGFyYW1ldGVyIGFzIGEgbGlzdCBvZiBkZWNvZGVkXG5cdCAqICAgcXVlcnkgcGFyYW1ldGVyIHZhbHVlcy5cblx0ICovXG5cdGdldFBhcmFtZXRlclZhbHVlcyhuYW1lKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdHJldHVybiB0aGlzLnF1ZXJ5LmdldEFsbChuYW1lKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBuYW1lPGI+czwvYj4gb2YgdGhlIHBhcmFtZXRlcnMuXG5cdCAqIEByZXR1cm4geyFBcnJheTxzdHJpbmc+fSBUaGUgbmFtZXMgZm9yIHRoZSBwYXJhbWV0ZXJzIGFzIGEgbGlzdCBvZlxuXHQgKiAgIHN0cmluZ3MuXG5cdCAqL1xuXHRnZXRQYXJhbWV0ZXJOYW1lcygpIHtcblx0XHR0aGlzLmVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCk7XG5cdFx0cmV0dXJuIHRoaXMucXVlcnkubmFtZXMoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBmdW5jdGlvbiBjdXJyZW50bHkgYmVpbmcgdXNlZCB0byBwYXJzZSBVUklzLlxuXHQgKiBAcmV0dXJuIHshZnVuY3Rpb24oKX1cblx0ICovXG5cdHN0YXRpYyBnZXRQYXJzZUZuKCkge1xuXHRcdHJldHVybiBwYXJzZUZuXztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBwYXRobmFtZSBwYXJ0IG9mIHVyaS5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0UGF0aG5hbWUoKSB7XG5cdFx0cmV0dXJuIHRoaXMudXJsLnBhdGhuYW1lO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHBvcnQgbnVtYmVyIHBhcnQgb2YgdXJpIGFzIHN0cmluZy5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0UG9ydCgpIHtcblx0XHRyZXR1cm4gdGhpcy51cmwucG9ydDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBwcm90b2NvbCBwYXJ0IG9mIHVyaS4gRS5nLiA8Y29kZT5odHRwOjwvY29kZT4uXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldFByb3RvY29sKCkge1xuXHRcdHJldHVybiB0aGlzLnVybC5wcm90b2NvbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzZWFyY2ggcGFydCBvZiB1cmkuIFNlYXJjaCB2YWx1ZSBpcyByZXRyaWV2ZWQgZnJvbSBxdWVyeVxuXHQgKiBwYXJhbWV0ZXJzLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRTZWFyY2goKSB7XG5cdFx0dmFyIHNlYXJjaCA9ICcnO1xuXHRcdHZhciBxdWVyeXN0cmluZyA9ICcnO1xuXHRcdHRoaXMuZ2V0UGFyYW1ldGVyTmFtZXMoKS5mb3JFYWNoKChuYW1lKSA9PiB7XG5cdFx0XHR0aGlzLmdldFBhcmFtZXRlclZhbHVlcyhuYW1lKS5mb3JFYWNoKCh2YWx1ZSkgPT4ge1xuXHRcdFx0XHRxdWVyeXN0cmluZyArPSBuYW1lO1xuXHRcdFx0XHRpZiAoaXNEZWYodmFsdWUpKSB7XG5cdFx0XHRcdFx0cXVlcnlzdHJpbmcgKz0gJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRxdWVyeXN0cmluZyArPSAnJic7XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0XHRxdWVyeXN0cmluZyA9IHF1ZXJ5c3RyaW5nLnNsaWNlKDAsIC0xKTtcblx0XHRpZiAocXVlcnlzdHJpbmcpIHtcblx0XHRcdHNlYXJjaCArPSAnPycgKyBxdWVyeXN0cmluZztcblx0XHR9XG5cdFx0cmV0dXJuIHNlYXJjaDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdXJpIGNvbnRhaW5zIHRoZSBwYXJhbWV0ZXIuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRoYXNQYXJhbWV0ZXIobmFtZSkge1xuXHRcdHRoaXMuZW5zdXJlUXVlcnlJbml0aWFsaXplZF8oKTtcblx0XHRyZXR1cm4gdGhpcy5xdWVyeS5jb250YWlucyhuYW1lKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYWtlcyB0aGlzIFVSTCB1bmlxdWUgYnkgYWRkaW5nIGEgcmFuZG9tIHBhcmFtIHRvIGl0LiBVc2VmdWwgZm9yIGF2b2lkaW5nXG5cdCAqIGNhY2hlLlxuXHQgKi9cblx0bWFrZVVuaXF1ZSgpIHtcblx0XHR0aGlzLnNldFBhcmFtZXRlclZhbHVlKFVyaS5SQU5ET01fUEFSQU0sIHN0cmluZy5nZXRSYW5kb21TdHJpbmcoKSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogTWF5YmUgYWRkcyBwcm90b2NvbCBhbmQgYSBob3N0bmFtZSBwbGFjZWhvbGRlciBvbiBhIHBhcmlhbCBVUkkgaWYgbmVlZGVkLlxuXHQgKiBSZWxldmVudCBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIDxjb2RlPlVSTDwvY29kZT4gbmF0aXZlIG9iamVjdC5cblx0ICogQHBhcmFtIHtzdHJpbmc9fSBvcHRfdXJpXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gVVJJIHdpdGggcHJvdG9jb2wgYW5kIGhvc3RuYW1lIHBsYWNlaG9sZGVyLlxuXHQgKi9cblx0bWF5YmVBZGRQcm90b2NvbEFuZEhvc3RuYW1lXyhvcHRfdXJpKSB7XG5cdFx0dmFyIHVybCA9IG9wdF91cmk7XG5cdFx0aWYgKG9wdF91cmkuaW5kZXhPZignOi8vJykgPT09IC0xICYmXG5cdFx0XHRvcHRfdXJpLmluZGV4T2YoJ2phdmFzY3JpcHQ6JykgIT09IDApIHsgLy8ganNoaW50IGlnbm9yZTpsaW5lXG5cblx0XHRcdHVybCA9IFVyaS5ERUZBVUxUX1BST1RPQ09MO1xuXHRcdFx0aWYgKG9wdF91cmlbMF0gIT09ICcvJyB8fCBvcHRfdXJpWzFdICE9PSAnLycpIHtcblx0XHRcdFx0dXJsICs9ICcvLyc7XG5cdFx0XHR9XG5cblx0XHRcdHN3aXRjaCAob3B0X3VyaS5jaGFyQXQoMCkpIHtcblx0XHRcdFx0Y2FzZSAnLic6XG5cdFx0XHRcdGNhc2UgJz8nOlxuXHRcdFx0XHRjYXNlICcjJzpcblx0XHRcdFx0XHR1cmwgKz0gVXJpLkhPU1ROQU1FX1BMQUNFSE9MREVSO1xuXHRcdFx0XHRcdHVybCArPSAnLyc7XG5cdFx0XHRcdFx0dXJsICs9IG9wdF91cmk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJyc6XG5cdFx0XHRcdGNhc2UgJy8nOlxuXHRcdFx0XHRcdGlmIChvcHRfdXJpWzFdICE9PSAnLycpIHtcblx0XHRcdFx0XHRcdHVybCArPSBVcmkuSE9TVE5BTUVfUExBQ0VIT0xERVI7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHVybCArPSBvcHRfdXJpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdHVybCArPSBvcHRfdXJpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdXJsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhcnNlcyB0aGUgZ2l2ZW4gdXJpIHN0cmluZyBpbnRvIGFuIG9iamVjdC5cblx0ICogQHBhcmFtIHsqPX0gb3B0X3VyaSBPcHRpb25hbCBzdHJpbmcgVVJJIHRvIHBhcnNlXG5cdCAqL1xuXHRzdGF0aWMgcGFyc2Uob3B0X3VyaSkge1xuXHRcdHJldHVybiBwYXJzZUZuXyhvcHRfdXJpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHRoZSBuYW1lZCBxdWVyeSBwYXJhbWV0ZXIuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBwYXJhbWV0ZXIgdG8gcmVtb3ZlLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRyZW1vdmVQYXJhbWV0ZXIobmFtZSkge1xuXHRcdHRoaXMuZW5zdXJlUXVlcnlJbml0aWFsaXplZF8oKTtcblx0XHR0aGlzLnF1ZXJ5LnJlbW92ZShuYW1lKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHVuaXF1ZW5lc3MgcGFyYW1ldGVyIG9mIHRoZSB1cmkuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHJlbW92ZVVuaXF1ZSgpIHtcblx0XHR0aGlzLnJlbW92ZVBhcmFtZXRlcihVcmkuUkFORE9NX1BBUkFNKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBoYXNoLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaGFzaFxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXRIYXNoKGhhc2gpIHtcblx0XHR0aGlzLnVybC5oYXNoID0gaGFzaDtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBob3N0bmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGhvc3RuYW1lXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldEhvc3RuYW1lKGhvc3RuYW1lKSB7XG5cdFx0dGhpcy51cmwuaG9zdG5hbWUgPSBob3N0bmFtZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB2YWx1ZSBvZiB0aGUgbmFtZWQgcXVlcnkgcGFyYW1ldGVycywgY2xlYXJpbmcgcHJldmlvdXMgdmFsdWVzXG5cdCAqIGZvciB0aGF0IGtleS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgcGFyYW1ldGVyIHRvIHNldC5cblx0ICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbmV3IHZhbHVlLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXRQYXJhbWV0ZXJWYWx1ZShuYW1lLCB2YWx1ZSkge1xuXHRcdHRoaXMucmVtb3ZlUGFyYW1ldGVyKG5hbWUpO1xuXHRcdHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHZhbHVlcyBvZiB0aGUgbmFtZWQgcXVlcnkgcGFyYW1ldGVycywgY2xlYXJpbmcgcHJldmlvdXMgdmFsdWVzXG5cdCAqIGZvciB0aGF0IGtleS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgcGFyYW1ldGVyIHRvIHNldC5cblx0ICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbmV3IHZhbHVlLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXRQYXJhbWV0ZXJWYWx1ZXMobmFtZSwgdmFsdWVzKSB7XG5cdFx0dGhpcy5yZW1vdmVQYXJhbWV0ZXIobmFtZSk7XG5cdFx0dmFsdWVzLmZvckVhY2goKHZhbHVlKSA9PiB0aGlzLmFkZFBhcmFtZXRlclZhbHVlKG5hbWUsIHZhbHVlKSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgcGF0aG5hbWUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwYXRobmFtZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXRQYXRobmFtZShwYXRobmFtZSkge1xuXHRcdHRoaXMudXJsLnBhdGhuYW1lID0gcGF0aG5hbWU7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgcG9ydCBudW1iZXIuXG5cdCAqIEBwYXJhbSB7Kn0gcG9ydCBQb3J0IG51bWJlci5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0c2V0UG9ydChwb3J0KSB7XG5cdFx0dGhpcy51cmwucG9ydCA9IHBvcnQ7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIHVzZWQgZm9yIHBhcnNpbmcgdGhlIG9yaWdpbmFsIHN0cmluZyB1cmlcblx0ICogaW50byBhbiBvYmplY3QuXG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IHBhcnNlRm5cblx0ICovXG5cdHN0YXRpYyBzZXRQYXJzZUZuKHBhcnNlRm4pIHtcblx0XHRwYXJzZUZuXyA9IHBhcnNlRm47XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgcHJvdG9jb2wuIElmIG1pc3NpbmcgPGNvZGU+aHR0cDo8L2NvZGU+IGlzIHVzZWQgYXMgZGVmYXVsdC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHByb3RvY29sXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFByb3RvY29sKHByb3RvY29sKSB7XG5cdFx0dGhpcy51cmwucHJvdG9jb2wgPSBwcm90b2NvbDtcblx0XHRpZiAodGhpcy51cmwucHJvdG9jb2xbdGhpcy51cmwucHJvdG9jb2wubGVuZ3RoIC0gMV0gIT09ICc6Jykge1xuXHRcdFx0dGhpcy51cmwucHJvdG9jb2wgKz0gJzonO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBzdHJpbmcgZm9ybSBvZiB0aGUgdXJsLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdHRvU3RyaW5nKCkge1xuXHRcdHZhciBocmVmID0gJyc7XG5cdFx0dmFyIGhvc3QgPSB0aGlzLmdldEhvc3QoKTtcblx0XHRpZiAoaG9zdCkge1xuXHRcdFx0aHJlZiArPSB0aGlzLmdldFByb3RvY29sKCkgKyAnLy8nO1xuXHRcdH1cblx0XHRocmVmICs9IGhvc3QgKyB0aGlzLmdldFBhdGhuYW1lKCkgKyB0aGlzLmdldFNlYXJjaCgpICsgdGhpcy5nZXRIYXNoKCk7XG5cdFx0cmV0dXJuIGhyZWY7XG5cdH1cblxuXHQvKipcblx0ICogSm9pbnMgdGhlIGdpdmVuIHBhdGhzLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gYmFzZVBhdGhcblx0ICogQHBhcmFtIHsuLi5zdHJpbmd9IC4uLnBhdGhzIEFueSBudW1iZXIgb2YgcGF0aHMgdG8gYmUgam9pbmVkIHdpdGggdGhlIGJhc2UgdXJsLlxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgam9pblBhdGhzKGJhc2VQYXRoLCAuLi5wYXRocykge1xuXHRcdGlmIChiYXNlUGF0aC5jaGFyQXQoYmFzZVBhdGgubGVuZ3RoIC0gMSkgPT09ICcvJykge1xuXHRcdFx0YmFzZVBhdGggPSBiYXNlUGF0aC5zdWJzdHJpbmcoMCwgYmFzZVBhdGgubGVuZ3RoIC0gMSk7XG5cdFx0fVxuXHRcdHBhdGhzID0gcGF0aHMubWFwKHBhdGggPT4gcGF0aC5jaGFyQXQoMCkgPT09ICcvJyA/IHBhdGguc3Vic3RyaW5nKDEpIDogcGF0aCk7XG5cdFx0cmV0dXJuIFtiYXNlUGF0aF0uY29uY2F0KHBhdGhzKS5qb2luKCcvJykucmVwbGFjZSgvXFwvJC8sICcnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBVUkwtZGVjb2RlcyB0aGUgc3RyaW5nLiBXZSBuZWVkIHRvIHNwZWNpYWxseSBoYW5kbGUgJysncyBiZWNhdXNlXG5cdCAqIHRoZSBqYXZhc2NyaXB0IGxpYnJhcnkgZG9lc24ndCBjb252ZXJ0IHRoZW0gdG8gc3BhY2VzLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gdXJsIGRlY29kZS5cblx0ICogQHJldHVybiB7c3RyaW5nfSBUaGUgZGVjb2RlZCB7QGNvZGUgc3RyfS5cblx0ICovXG5cdHN0YXRpYyB1cmxEZWNvZGUoc3RyKSB7XG5cdFx0cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChzdHIucmVwbGFjZSgvXFwrL2csICcgJykpO1xuXHR9XG5cbn1cblxuLyoqXG4gKiBEZWZhdWx0IHByb3RvY29sIHZhbHVlLlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBkZWZhdWx0IGh0dHA6XG4gKiBAc3RhdGljXG4gKi9cbmNvbnN0IGlzU2VjdXJlID0gKCkgPT5cblx0KHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmXG5cdFx0d2luZG93LmxvY2F0aW9uICYmXG5cdFx0d2luZG93LmxvY2F0aW9uLnByb3RvY29sICYmXG5cdFx0d2luZG93LmxvY2F0aW9uLnByb3RvY29sLmluZGV4T2YoJ2h0dHBzJykgPT09IDApO1xuXG5VcmkuREVGQVVMVF9QUk9UT0NPTCA9IGlzU2VjdXJlKCkgPyAnaHR0cHM6JyA6ICdodHRwOic7XG5cbi8qKlxuICogSG9zdG5hbWUgcGxhY2Vob2xkZXIuIFJlbGV2YW50IHRvIGludGVybmFsIHVzYWdlIG9ubHkuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQHN0YXRpY1xuICovXG5VcmkuSE9TVE5BTUVfUExBQ0VIT0xERVIgPSAnaG9zdG5hbWUnICsgRGF0ZS5ub3coKTtcblxuLyoqXG4gKiBOYW1lIHVzZWQgYnkgdGhlIHBhcmFtIGdlbmVyYXRlZCBieSBgbWFrZVVuaXF1ZWAuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQHN0YXRpY1xuICovXG5VcmkuUkFORE9NX1BBUkFNID0gJ3p4JztcblxuZXhwb3J0IGRlZmF1bHQgVXJpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IFVyaSBmcm9tICdtZXRhbC11cmknO1xuXG4vKipcbiAqIEEgY29sbGVjdGlvbiBvZiBzdGF0aWMgdXRpbGl0eSBmdW5jdGlvbnMuXG4gKiBAY29uc3RcbiAqL1xuY2xhc3MgdXRpbHMge1xuXG5cdC8qKlxuXHQgKiBDb3BpZXMgYXR0cmlidXRlcyBmb3JtIHNvdXJjZSBub2RlIHRvIHRhcmdldCBub2RlLlxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgY29weU5vZGVBdHRyaWJ1dGVzKHNvdXJjZSwgdGFyZ2V0KSB7XG5cdFx0QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoc291cmNlLmF0dHJpYnV0ZXMpLmZvckVhY2goKGF0dHJpYnV0ZSkgPT4gdGFyZ2V0LnNldEF0dHJpYnV0ZShhdHRyaWJ1dGUubmFtZSwgYXR0cmlidXRlLnZhbHVlKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgY3VycmVudCBicm93c2VyIHBhdGggaW5jbHVkaW5nIGhhc2hiYW5nLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0Q3VycmVudEJyb3dzZXJQYXRoKCkge1xuXHRcdHJldHVybiB0aGlzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCkgKyBnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5oYXNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGN1cnJlbnQgYnJvd3NlciBwYXRoIGV4Y2x1ZGluZyBoYXNoYmFuZy5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCkge1xuXHRcdHJldHVybiBnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSArIGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnNlYXJjaDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBnaXZlbiBub2RlIG9mZnNldCBjb29yZGluYXRlcy5cblx0ICogQHJldHVybiB7IW9iamVjdH1cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldE5vZGVPZmZzZXQobm9kZSkge1xuXHRcdGxldCBbb2Zmc2V0TGVmdCwgb2Zmc2V0VG9wXSA9IFswLCAwXTtcblx0XHRkbyB7XG5cdFx0XHRvZmZzZXRMZWZ0ICs9IG5vZGUub2Zmc2V0TGVmdDtcblx0XHRcdG9mZnNldFRvcCArPSBub2RlLm9mZnNldFRvcDtcblx0XHRcdG5vZGUgPSBub2RlLm9mZnNldFBhcmVudDtcblx0XHR9IHdoaWxlIChub2RlKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0b2Zmc2V0TGVmdCxcblx0XHRcdG9mZnNldFRvcFxuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogRXh0cmFjdHMgdGhlIHBhdGggcGFydCBvZiBhbiB1cmwuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBnZXRVcmxQYXRoKHVybCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHVybCk7XG5cdFx0cmV0dXJuIHVyaS5nZXRQYXRobmFtZSgpICsgdXJpLmdldFNlYXJjaCgpICsgdXJpLmdldEhhc2goKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFeHRyYWN0cyB0aGUgcGF0aCBwYXJ0IG9mIGFuIHVybCB3aXRob3V0IGhhc2hiYW5nLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0VXJsUGF0aFdpdGhvdXRIYXNoKHVybCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHVybCk7XG5cdFx0cmV0dXJuIHVyaS5nZXRQYXRobmFtZSgpICsgdXJpLmdldFNlYXJjaCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIHRoZSBwYXRoIHBhcnQgb2YgYW4gdXJsIHdpdGhvdXQgaGFzaGJhbmcgYW5kIHF1ZXJ5IHNlYXJjaC5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldFVybFBhdGhXaXRob3V0SGFzaEFuZFNlYXJjaCh1cmwpIHtcblx0XHR2YXIgdXJpID0gbmV3IFVyaSh1cmwpO1xuXHRcdHJldHVybiB1cmkuZ2V0UGF0aG5hbWUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdXJsIGlzIGluIHRoZSBzYW1lIGJyb3dzZXIgY3VycmVudCB1cmwgZXhjbHVkaW5nIHRoZSBoYXNoYmFuZy5cblx0ICogQHBhcmFtICB7IXN0cmluZ30gdXJsXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBpc0N1cnJlbnRCcm93c2VyUGF0aCh1cmwpIHtcblx0XHRpZiAodXJsKSB7XG5cdFx0XHRjb25zdCBjdXJyZW50QnJvd3NlclBhdGggPSB0aGlzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCk7XG5cdFx0XHQvLyB0aGUgZ2V0VXJsUGF0aCB3aWxsIGNyZWF0ZSBhIFVyaSBhbmQgd2lsbCBub3JtYWxpemUgdGhlIHBhdGggYW5kXG5cdFx0XHQvLyByZW1vdmUgdGhlIHRyYWlsbGluZyAnLycgZm9yIHByb3Blcmx5IGNvbXBhcmluZyBwYXRocy5cblx0XHRcdHJldHVybiB1dGlscy5nZXRVcmxQYXRoV2l0aG91dEhhc2godXJsKSA9PT0gdGhpcy5nZXRVcmxQYXRoKGN1cnJlbnRCcm93c2VyUGF0aCk7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgSFRNTDUgSGlzdG9yeSBhcGkgaXMgc3VwcG9ydGVkLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgaXNIdG1sNUhpc3RvcnlTdXBwb3J0ZWQoKSB7XG5cdFx0cmV0dXJuICEhKGdsb2JhbHMud2luZG93Lmhpc3RvcnkgJiYgZ2xvYmFscy53aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBhIGdpdmVuIHVybCBpcyBhIHZhbGlkIGh0dHAocykgdXJpIGFuZCByZXR1cm5zIHRoZSBmb3JtZWQgVXJpXG5cdCAqIG9yIGZhbHNlIGlmIHRoZSBwYXJzaW5nIGZhaWxlZFxuXHQgKiBAcmV0dXJuIHtVcml8Ym9vbGVhbn1cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGlzV2ViVXJpKHVybCkge1xuXHRcdHRyeSB7XG5cdFx0XHRyZXR1cm4gbmV3IFVyaSh1cmwpO1xuXHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0Y29uc29sZS5lcnJvcihgJHtlcnIubWVzc2FnZX0gJHt1cmx9YCk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYWxsIGF0dHJpYnV0ZXMgZm9ybSBub2RlLlxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgY2xlYXJOb2RlQXR0cmlidXRlcyhub2RlKSB7XG5cdFx0QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobm9kZS5hdHRyaWJ1dGVzKS5mb3JFYWNoKChhdHRyaWJ1dGUpID0+IG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJpYnV0ZS5uYW1lKSk7XG5cdH1cblxuXHQvKipcblx0KiBSZW1vdmVzIHRyYWlsaW5nIHNsYXNoIGluIHBhdGguXG5cdCogQHBhcmFtIHshc3RyaW5nfVxuXHQqIEByZXR1cm4ge3N0cmluZ31cblx0Ki9cblx0c3RhdGljIHJlbW92ZVBhdGhUcmFpbGluZ1NsYXNoKHBhdGgpIHtcblx0XHR2YXIgbGVuZ3RoID0gcGF0aCA/IHBhdGgubGVuZ3RoIDogMDtcblx0XHRpZiAobGVuZ3RoID4gMSAmJiBwYXRoW2xlbmd0aCAtIDFdID09PSAnLycpIHtcblx0XHRcdHBhdGggPSBwYXRoLnN1YnN0cigwLCBsZW5ndGggLSAxKTtcblx0XHR9XG5cdFx0cmV0dXJuIHBhdGg7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgdXRpbHM7XG4iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydCBkZWZhdWx0IHtcblx0YmFzZVBhdGg6ICdkYXRhLXNlbm5hLWJhc2UtcGF0aCcsXG5cdGxpbmtTZWxlY3RvcjogJ2RhdGEtc2VubmEtbGluay1zZWxlY3RvcicsXG5cdGxvYWRpbmdDc3NDbGFzczogJ2RhdGEtc2VubmEtbG9hZGluZy1jc3MtY2xhc3MnLFxuXHRzZW5uYTogJ2RhdGEtc2VubmEnLFxuXHRkaXNwYXRjaDogJ2RhdGEtc2VubmEtZGlzcGF0Y2gnLFxuXHRzdXJmYWNlOiAnZGF0YS1zZW5uYS1zdXJmYWNlJyxcblx0dXBkYXRlU2Nyb2xsUG9zaXRpb246ICdkYXRhLXNlbm5hLXVwZGF0ZS1zY3JvbGwtcG9zaXRpb24nXG59OyIsIid1c2Ugc3RyaWN0JztcblxuY29uc3QgTUVUQUxfREFUQSA9ICdfX21ldGFsX2RhdGFfXyc7XG5cbmNsYXNzIGRvbURhdGEge1xuXHQvKipcblx0ICogR2V0cyBNZXRhbC5qcydzIGRhdGEgZm9yIHRoZSBnaXZlbiBlbGVtZW50LlxuXHQgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG5cdCAqIEBwYXJhbSB7c3RyaW5nPX0gb3B0X25hbWUgT3B0aW9uYWwgcHJvcGVydHkgZnJvbSB0aGUgZGF0YSB0byBiZSByZXR1cm5lZC5cblx0ICogQHBhcmFtIHsqfSBvcHRfaW5pdGlhbFZhbCBPcHRpbmFsIHZhbHVlIHRvIHRoZSBzZXQgdGhlIHJlcXVlc3RlZCBwcm9wZXJ0eVxuXHQgKiAgICAgdG8gaWYgaXQgZG9lc24ndCBleGlzdCB5ZXQgaW4gdGhlIGRhdGEuXG5cdCAqIEByZXR1cm4geyFPYmplY3R9XG5cdCAqL1xuXHRzdGF0aWMgZ2V0KGVsZW1lbnQsIG9wdF9uYW1lLCBvcHRfaW5pdGlhbFZhbCkge1xuXHRcdGlmICghZWxlbWVudFtNRVRBTF9EQVRBXSkge1xuXHRcdFx0ZWxlbWVudFtNRVRBTF9EQVRBXSA9IHt9O1xuXHRcdH1cblx0XHRpZiAoIW9wdF9uYW1lKSB7XG5cdFx0XHRyZXR1cm4gZWxlbWVudFtNRVRBTF9EQVRBXTtcblx0XHR9XG5cdFx0aWYgKCFlbGVtZW50W01FVEFMX0RBVEFdW29wdF9uYW1lXSAmJiBvcHRfaW5pdGlhbFZhbCkge1xuXHRcdFx0ZWxlbWVudFtNRVRBTF9EQVRBXVtvcHRfbmFtZV0gPSBvcHRfaW5pdGlhbFZhbDtcblx0XHR9XG5cdFx0cmV0dXJuIGVsZW1lbnRbTUVUQUxfREFUQV1bb3B0X25hbWVdO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZWxlbWVudCBoYXMgZGF0YSBzdG9yZWQgaW4gaXQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdHN0YXRpYyBoYXMoZWxlbWVudCkge1xuXHRcdHJldHVybiAhIWVsZW1lbnRbTUVUQUxfREFUQV07XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgZG9tRGF0YTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgRGlzcG9zYWJsZSB9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBFdmVudEhhbmRsZSB1dGlsaXR5LiBIb2xkcyBpbmZvcm1hdGlvbiBhYm91dCBhbiBldmVudCBzdWJzY3JpcHRpb24sIGFuZFxuICogYWxsb3dzIHJlbW92aW5nIHRoZW0gZWFzaWx5LlxuICogRXZlbnRIYW5kbGUgaXMgYSBEaXNwb3NhYmxlLCBidXQgaXQncyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHRoZVxuICogRXZlbnRFbWl0dGVyIHRoYXQgY3JlYXRlZCBpdCBpcyBub3QgdGhlIG9uZSByZXNwb25zaWJsZSBmb3IgZGlzcG9zaW5nIGl0LlxuICogVGhhdCByZXNwb25zaWJpbGl0eSBpcyBmb3IgdGhlIGNvZGUgdGhhdCBob2xkcyBhIHJlZmVyZW5jZSB0byBpdC5cbiAqIEBwYXJhbSB7IUV2ZW50RW1pdHRlcn0gZW1pdHRlciBFbWl0dGVyIHRoZSBldmVudCB3YXMgc3Vic2NyaWJlZCB0by5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCB3YXMgc3Vic2NyaWJlZCB0by5cbiAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lciBUaGUgbGlzdGVuZXIgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnQuXG4gKiBAY29uc3RydWN0b3JcbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEhhbmRsZSBleHRlbmRzIERpc3Bvc2FibGUge1xuXHRjb25zdHJ1Y3RvcihlbWl0dGVyLCBldmVudCwgbGlzdGVuZXIpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIEV2ZW50RW1pdHRlciBpbnN0YW5jZSB0aGF0IHRoZSBldmVudCB3YXMgc3Vic2NyaWJlZCB0by5cblx0XHQgKiBAdHlwZSB7RXZlbnRFbWl0dGVyfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmVtaXR0ZXJfID0gZW1pdHRlcjtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0aGF0IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHRcdCAqIEB0eXBlIHtzdHJpbmd9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZXZlbnRfID0gZXZlbnQ7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgbGlzdGVuZXIgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnQuXG5cdFx0ICogQHR5cGUge0Z1bmN0aW9ufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmxpc3RlbmVyXyA9IGxpc3RlbmVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy5cblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdHRoaXMuZW1pdHRlcl8gPSBudWxsO1xuXHRcdHRoaXMubGlzdGVuZXJfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHRoZSBsaXN0ZW5lciBzdWJzY3JpcHRpb24gZnJvbSB0aGUgZW1pdHRlci5cblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyKCkge1xuXHRcdGlmICghdGhpcy5lbWl0dGVyXy5pc0Rpc3Bvc2VkKCkpIHtcblx0XHRcdHRoaXMuZW1pdHRlcl8ucmVtb3ZlTGlzdGVuZXIodGhpcy5ldmVudF8sIHRoaXMubGlzdGVuZXJfKTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRXZlbnRIYW5kbGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGFycmF5LCBEaXNwb3NhYmxlLCBpc0Z1bmN0aW9uLCBpc1N0cmluZyB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBFdmVudEhhbmRsZSBmcm9tICcuL0V2ZW50SGFuZGxlJztcblxuY29uc3Qgc2luZ2xlQXJyYXlfID0gWzBdO1xuXG4vKipcbiAqIEV2ZW50RW1pdHRlciB1dGlsaXR5LlxuICogQGNvbnN0cnVjdG9yXG4gKiBAZXh0ZW5kcyB7RGlzcG9zYWJsZX1cbiAqL1xuY2xhc3MgRXZlbnRFbWl0dGVyIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBldmVudCBsaXN0ZW5lcnMgc2NvcGVkIGJ5IGV2ZW50IHR5cGUuXG5cdFx0ICogQHR5cGUge09iamVjdDxzdHJpbmcsICFBcnJheTwhZnVuY3Rpb24oKT4+fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmV2ZW50c18gPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSGFuZGxlcnMgdGhhdCBhcmUgdHJpZ2dlcmVkIHdoZW4gYW4gZXZlbnQgaXMgbGlzdGVuZWQgdG8uXG5cdFx0ICogQHR5cGUge0FycmF5fVxuXHRcdCAqL1xuXHRcdHRoaXMubGlzdGVuZXJIYW5kbGVyc18gPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogQ29uZmlndXJhdGlvbiBvcHRpb24gd2hpY2ggZGV0ZXJtaW5lcyBpZiBhbiBldmVudCBmYWNhZGUgc2hvdWxkIGJlIHNlbnRcblx0XHQgKiBhcyBhIHBhcmFtIG9mIGxpc3RlbmVycyB3aGVuIGVtaXR0aW5nIGV2ZW50cy4gSWYgc2V0IHRvIHRydWUsIHRoZSBmYWNhZGVcblx0XHQgKiB3aWxsIGJlIHBhc3NlZCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgb2YgdGhlIGxpc3RlbmVyLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnNob3VsZFVzZUZhY2FkZV8gPSBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgaGFuZGxlciB0byBnaXZlbiBob2xkZXIgdmFyaWFibGUuIElmIHRoZSBob2xkZXIgZG9lc24ndCBoYXZlIGFcblx0ICogdmFsdWUgeWV0LCBpdCB3aWxsIHJlY2VpdmUgdGhlIGhhbmRsZXIgZGlyZWN0bHkuIElmIHRoZSBob2xkZXIgaXMgYW4gYXJyYXksXG5cdCAqIHRoZSB2YWx1ZSB3aWxsIGp1c3QgYmUgYWRkZWQgdG8gaXQuIE90aGVyd2lzZSwgdGhlIGhvbGRlciB3aWxsIGJlIHNldCB0byBhXG5cdCAqIG5ldyBhcnJheSBjb250YWluaW5nIGl0cyBwcmV2aW91cyB2YWx1ZSBwbHVzIHRoZSBuZXcgaGFuZGxlci5cblx0ICogQHBhcmFtIHsqfSBob2xkZXJcblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKXxPYmplY3R9IGhhbmRsZXJcblx0ICogQHJldHVybiB7Kn0gVGhlIGhvbGRlcidzIG5ldyB2YWx1ZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0YWRkSGFuZGxlcl8oaG9sZGVyLCBoYW5kbGVyKSB7XG5cdFx0aWYgKCFob2xkZXIpIHtcblx0XHRcdGhvbGRlciA9IGhhbmRsZXI7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICghQXJyYXkuaXNBcnJheShob2xkZXIpKSB7XG5cdFx0XHRcdGhvbGRlciA9IFtob2xkZXJdO1xuXHRcdFx0fVxuXHRcdFx0aG9sZGVyLnB1c2goaGFuZGxlcik7XG5cdFx0fVxuXHRcdHJldHVybiBob2xkZXI7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBlbmQgb2YgdGhlIGxpc3RlbmVycyBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudHMuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudFxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHBhcmFtIHtib29sZWFufSBvcHRfZGVmYXVsdCBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBsaXN0ZW5lciBpcyBhIGRlZmF1bHRcblx0ICogICBhY3Rpb24gZm9yIHRoaXMgZXZlbnQuIERlZmF1bHQgYWN0aW9ucyBhcmUgcnVuIGxhc3QsIGFuZCBvbmx5IGlmIG5vIHByZXZpb3VzXG5cdCAqICAgbGlzdGVuZXIgY2FsbCBgcHJldmVudERlZmF1bHQoKWAgb24gdGhlIHJlY2VpdmVkIGV2ZW50IGZhY2FkZS5cblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuXHQgKi9cblx0YWRkTGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyLCBvcHRfZGVmYXVsdCkge1xuXHRcdHRoaXMudmFsaWRhdGVMaXN0ZW5lcl8obGlzdGVuZXIpO1xuXG5cdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuYWRkU2luZ2xlTGlzdGVuZXJfKGV2ZW50c1tpXSwgbGlzdGVuZXIsIG9wdF9kZWZhdWx0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IEV2ZW50SGFuZGxlKHRoaXMsIGV2ZW50LCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBlbmQgb2YgdGhlIGxpc3RlbmVycyBhcnJheSBmb3IgYSBzaW5nbGUgZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHBhcmFtIHtib29sZWFufSBvcHRfZGVmYXVsdCBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBsaXN0ZW5lciBpcyBhIGRlZmF1bHRcblx0ICogICBhY3Rpb24gZm9yIHRoaXMgZXZlbnQuIERlZmF1bHQgYWN0aW9ucyBhcmUgcnVuIGxhc3QsIGFuZCBvbmx5IGlmIG5vIHByZXZpb3VzXG5cdCAqICAgbGlzdGVuZXIgY2FsbCBgcHJldmVudERlZmF1bHQoKWAgb24gdGhlIHJlY2VpdmVkIGV2ZW50IGZhY2FkZS5cblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9uPX0gb3B0X29yaWdpbiBUaGUgb3JpZ2luYWwgZnVuY3Rpb24gdGhhdCB3YXMgYWRkZWQgYXMgYVxuXHQgKiAgIGxpc3RlbmVyLCBpZiB0aGVyZSBpcyBhbnkuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFkZFNpbmdsZUxpc3RlbmVyXyhldmVudCwgbGlzdGVuZXIsIG9wdF9kZWZhdWx0LCBvcHRfb3JpZ2luKSB7XG5cdFx0dGhpcy5ydW5MaXN0ZW5lckhhbmRsZXJzXyhldmVudCk7XG5cdFx0aWYgKG9wdF9kZWZhdWx0IHx8IG9wdF9vcmlnaW4pIHtcblx0XHRcdGxpc3RlbmVyID0ge1xuXHRcdFx0XHRkZWZhdWx0OiBvcHRfZGVmYXVsdCxcblx0XHRcdFx0Zm46IGxpc3RlbmVyLFxuXHRcdFx0XHRvcmlnaW46IG9wdF9vcmlnaW5cblx0XHRcdH07XG5cdFx0fVxuXHRcdHRoaXMuZXZlbnRzXyA9IHRoaXMuZXZlbnRzXyB8fCB7fTtcblx0XHR0aGlzLmV2ZW50c19bZXZlbnRdID0gdGhpcy5hZGRIYW5kbGVyXyh0aGlzLmV2ZW50c19bZXZlbnRdLCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQnVpbGRzIGZhY2FkZSBmb3IgdGhlIGdpdmVuIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7T2JqZWN0fVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRidWlsZEZhY2FkZV8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5nZXRTaG91bGRVc2VGYWNhZGUoKSkge1xuXHRcdFx0Y29uc3QgZmFjYWRlID0ge1xuXHRcdFx0XHRwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0ZmFjYWRlLnByZXZlbnRlZERlZmF1bHQgPSB0cnVlO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR0YXJnZXQ6IHRoaXMsXG5cdFx0XHRcdHR5cGU6IGV2ZW50XG5cdFx0XHR9O1xuXHRcdFx0cmV0dXJuIGZhY2FkZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLmV2ZW50c18gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4ZWN1dGUgZWFjaCBvZiB0aGUgbGlzdGVuZXJzIGluIG9yZGVyIHdpdGggdGhlIHN1cHBsaWVkIGFyZ3VtZW50cy5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwYXJhbSB7Kn0gb3B0X2FyZ3MgW2FyZzFdLCBbYXJnMl0sIFsuLi5dXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiBldmVudCBoYWQgbGlzdGVuZXJzLCBmYWxzZSBvdGhlcndpc2UuXG5cdCAqL1xuXHRlbWl0KGV2ZW50KSB7XG5cdFx0Y29uc3QgbGlzdGVuZXJzID0gdGhpcy5nZXRSYXdMaXN0ZW5lcnNfKGV2ZW50KTtcblx0XHRpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdGNvbnN0IGFyZ3MgPSBhcnJheS5zbGljZShhcmd1bWVudHMsIDEpO1xuXHRcdHRoaXMucnVuTGlzdGVuZXJzXyhsaXN0ZW5lcnMsIGFyZ3MsIHRoaXMuYnVpbGRGYWNhZGVfKGV2ZW50KSk7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgbGlzdGVuZXIgb2JqZWN0cyBmb3IgdGhlIGdpdmVuIGV2ZW50LCBpZiB0aGVyZSBhcmUgYW55LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7IUFycmF5fVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRnZXRSYXdMaXN0ZW5lcnNfKGV2ZW50KSB7XG5cdFx0Y29uc3QgZGlyZWN0TGlzdGVuZXJzID0gdG9BcnJheSh0aGlzLmV2ZW50c18gJiYgdGhpcy5ldmVudHNfW2V2ZW50XSk7XG5cdFx0cmV0dXJuIGRpcmVjdExpc3RlbmVycy5jb25jYXQodG9BcnJheSh0aGlzLmV2ZW50c18gJiYgdGhpcy5ldmVudHNfWycqJ10pKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjb25maWd1cmF0aW9uIG9wdGlvbiB3aGljaCBkZXRlcm1pbmVzIGlmIGFuIGV2ZW50IGZhY2FkZSBzaG91bGRcblx0ICogYmUgc2VudCBhcyBhIHBhcmFtIG9mIGxpc3RlbmVycyB3aGVuIGVtaXR0aW5nIGV2ZW50cy4gSWYgc2V0IHRvIHRydWUsIHRoZVxuXHQgKiBmYWNhZGUgd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIHRoZSBsaXN0ZW5lci5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldFNob3VsZFVzZUZhY2FkZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5zaG91bGRVc2VGYWNhZGVfO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7QXJyYXl9IEFycmF5IG9mIGxpc3RlbmVycy5cblx0ICovXG5cdGxpc3RlbmVycyhldmVudCkge1xuXHRcdHJldHVybiB0aGlzLmdldFJhd0xpc3RlbmVyc18oZXZlbnQpLm1hcChcblx0XHRcdGxpc3RlbmVyID0+IGxpc3RlbmVyLmZuID8gbGlzdGVuZXIuZm4gOiBsaXN0ZW5lclxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGEgZml4ZWQgbnVtYmVyIG9mIHRpbWVzIGZvciB0aGVcblx0ICogZXZlbnRzLiBBZnRlciBlYWNoIGV2ZW50IGlzIHRyaWdnZXJlZCB0aGUgc3BlY2lmaWVkIGFtb3VudCBvZiB0aW1lcywgdGhlXG5cdCAqIGxpc3RlbmVyIGlzIHJlbW92ZWQgZm9yIGl0LlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRcblx0ICogQHBhcmFtIHtudW1iZXJ9IGFtb3VudCBUaGUgYW1vdW50IG9mIHRpbWVzIHRoaXMgZXZlbnQgc2hvdWxkIGJlIGxpc3RlbmVkXG5cdCAqIHRvLlxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuXHQgKi9cblx0bWFueShldmVudCwgYW1vdW50LCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMudG9FdmVudHNBcnJheV8oZXZlbnQpO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLm1hbnlfKGV2ZW50c1tpXSwgYW1vdW50LCBsaXN0ZW5lcik7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBFdmVudEhhbmRsZSh0aGlzLCBldmVudCwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIGZpeGVkIG51bWJlciBvZiB0aW1lcyBmb3IgYSBzaW5nbGVcblx0ICogZXZlbnQuIEFmdGVyIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQgdGhlIHNwZWNpZmllZCBhbW91bnQgb2YgdGltZXMsIHRoZVxuXHQgKiBsaXN0ZW5lciBpcyByZW1vdmVkLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHBhcmFtIHtudW1iZXJ9IGFtb3VudCBUaGUgYW1vdW50IG9mIHRpbWVzIHRoaXMgZXZlbnQgc2hvdWxkIGJlIGxpc3RlbmVkXG5cdCAqIHRvLlxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0bWFueV8oZXZlbnQsIGFtb3VudCwgbGlzdGVuZXIpIHtcblx0XHRjb25zdCBzZWxmID0gdGhpcztcblxuXHRcdGlmIChhbW91bnQgPD0gMCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGhhbmRsZXJJbnRlcm5hbCgpIHtcblx0XHRcdGlmICgtLWFtb3VudCA9PT0gMCkge1xuXHRcdFx0XHRzZWxmLnJlbW92ZUxpc3RlbmVyKGV2ZW50LCBoYW5kbGVySW50ZXJuYWwpO1xuXHRcdFx0fVxuXHRcdFx0bGlzdGVuZXIuYXBwbHkoc2VsZiwgYXJndW1lbnRzKTtcblx0XHR9XG5cblx0XHRzZWxmLmFkZFNpbmdsZUxpc3RlbmVyXyhldmVudCwgaGFuZGxlckludGVybmFsLCBmYWxzZSwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBhIGxpc3RlbmVyIG9iamVjdCBtYXRjaGVzIHRoZSBnaXZlbiBsaXN0ZW5lciBmdW5jdGlvbi4gVG8gbWF0Y2gsXG5cdCAqIGl0IG5lZWRzIHRvIGVpdGhlciBwb2ludCB0byB0aGF0IGxpc3RlbmVyIG9yIGhhdmUgaXQgYXMgaXRzIG9yaWdpbi5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBsaXN0ZW5lck9ialxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0bWF0Y2hlc0xpc3RlbmVyXyhsaXN0ZW5lck9iaiwgbGlzdGVuZXIpIHtcblx0XHRjb25zdCBmbiA9IGxpc3RlbmVyT2JqLmZuIHx8IGxpc3RlbmVyT2JqO1xuXHRcdHJldHVybiBmbiA9PT0gbGlzdGVuZXIgfHxcblx0XHRcdChsaXN0ZW5lck9iai5vcmlnaW4gJiYgbGlzdGVuZXJPYmoub3JpZ2luID09PSBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQ2F1dGlvbjogY2hhbmdlcyBhcnJheSBpbmRpY2VzIGluIHRoZSBsaXN0ZW5lciBhcnJheSBiZWhpbmQgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRzXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fSBSZXR1cm5zIGVtaXR0ZXIsIHNvIGNhbGxzIGNhbiBiZSBjaGFpbmVkLlxuXHQgKi9cblx0b2ZmKGV2ZW50LCBsaXN0ZW5lcikge1xuXHRcdHRoaXMudmFsaWRhdGVMaXN0ZW5lcl8obGlzdGVuZXIpO1xuXHRcdGlmICghdGhpcy5ldmVudHNfKSB7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9XG5cblx0XHRjb25zdCBldmVudHMgPSB0aGlzLnRvRXZlbnRzQXJyYXlfKGV2ZW50KTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dGhpcy5ldmVudHNfW2V2ZW50c1tpXV0gPSB0aGlzLnJlbW92ZU1hdGNoaW5nTGlzdGVuZXJPYmpzXyhcblx0XHRcdFx0dG9BcnJheSh0aGlzLmV2ZW50c19bZXZlbnRzW2ldXSksXG5cdFx0XHRcdGxpc3RlbmVyXG5cdFx0XHQpO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBsaXN0ZW5lciB0byB0aGUgZW5kIG9mIHRoZSBsaXN0ZW5lcnMgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRzLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRzXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG5cdCAqL1xuXHRvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5hZGRMaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgaGFuZGxlciB0aGF0IGdldHMgdHJpZ2dlcmVkIHdoZW4gYW4gZXZlbnQgaXMgbGlzdGVuZWQgdG8gb24gdGhpc1xuXHQgKiBpbnN0YW5jZS5cblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKX1cblx0ICovXG5cdG9uTGlzdGVuZXIoaGFuZGxlcikge1xuXHRcdHRoaXMubGlzdGVuZXJIYW5kbGVyc18gPSB0aGlzLmFkZEhhbmRsZXJfKHRoaXMubGlzdGVuZXJIYW5kbGVyc18sIGhhbmRsZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBvbmUgdGltZSBsaXN0ZW5lciBmb3IgdGhlIGV2ZW50cy4gVGhpcyBsaXN0ZW5lciBpcyBpbnZva2VkIG9ubHkgdGhlXG5cdCAqIG5leHQgdGltZSBlYWNoIGV2ZW50IGlzIGZpcmVkLCBhZnRlciB3aGljaCBpdCBpcyByZW1vdmVkLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRzXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG5cdCAqL1xuXHRvbmNlKGV2ZW50cywgbGlzdGVuZXIpIHtcblx0XHRyZXR1cm4gdGhpcy5tYW55KGV2ZW50cywgMSwgbGlzdGVuZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycywgb3IgdGhvc2Ugb2YgdGhlIHNwZWNpZmllZCBldmVudHMuIEl0J3Mgbm90IGEgZ29vZFxuXHQgKiBpZGVhIHRvIHJlbW92ZSBsaXN0ZW5lcnMgdGhhdCB3ZXJlIGFkZGVkIGVsc2V3aGVyZSBpbiB0aGUgY29kZSxcblx0ICogZXNwZWNpYWxseSB3aGVuIGl0J3Mgb24gYW4gZW1pdHRlciB0aGF0IHlvdSBkaWRuJ3QgY3JlYXRlLlxuXHQgKiBAcGFyYW0geyhBcnJheXxzdHJpbmcpPX0gb3B0X2V2ZW50c1xuXHQgKiBAcmV0dXJuIHshT2JqZWN0fSBSZXR1cm5zIGVtaXR0ZXIsIHNvIGNhbGxzIGNhbiBiZSBjaGFpbmVkLlxuXHQgKi9cblx0cmVtb3ZlQWxsTGlzdGVuZXJzKG9wdF9ldmVudHMpIHtcblx0XHRpZiAodGhpcy5ldmVudHNfKSB7XG5cdFx0XHRpZiAob3B0X2V2ZW50cykge1xuXHRcdFx0XHRjb25zdCBldmVudHMgPSB0aGlzLnRvRXZlbnRzQXJyYXlfKG9wdF9ldmVudHMpO1xuXHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRcdHRoaXMuZXZlbnRzX1tldmVudHNbaV1dID0gbnVsbDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5ldmVudHNfID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhbGwgbGlzdGVuZXIgb2JqZWN0cyBmcm9tIHRoZSBnaXZlbiBhcnJheSB0aGF0IG1hdGNoIHRoZSBnaXZlblxuXHQgKiBsaXN0ZW5lciBmdW5jdGlvbi5cblx0ICogQHBhcmFtIHtBcnJheS48T2JqZWN0Pn0gbGlzdGVuZXJPYmpzXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHtBcnJheS48T2JqZWN0PnxPYmplY3R9IFRoZSBuZXcgbGlzdGVuZXJzIGFycmF5IGZvciB0aGlzIGV2ZW50LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRyZW1vdmVNYXRjaGluZ0xpc3RlbmVyT2Jqc18obGlzdGVuZXJPYmpzLCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IGZpbmFsTGlzdGVuZXJzID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0ZW5lck9ianMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmICghdGhpcy5tYXRjaGVzTGlzdGVuZXJfKGxpc3RlbmVyT2Jqc1tpXSwgbGlzdGVuZXIpKSB7XG5cdFx0XHRcdGZpbmFsTGlzdGVuZXJzLnB1c2gobGlzdGVuZXJPYmpzW2ldKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGZpbmFsTGlzdGVuZXJzLmxlbmd0aCA+IDAgPyBmaW5hbExpc3RlbmVycyA6IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQ2F1dGlvbjogY2hhbmdlcyBhcnJheSBpbmRpY2VzIGluIHRoZSBsaXN0ZW5lciBhcnJheSBiZWhpbmQgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcGFyYW0geyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRzXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fSBSZXR1cm5zIGVtaXR0ZXIsIHNvIGNhbGxzIGNhbiBiZSBjaGFpbmVkLlxuXHQgKi9cblx0cmVtb3ZlTGlzdGVuZXIoKSB7XG5cdFx0cmV0dXJuIHRoaXMub2ZmLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG5cdH1cblxuXHQvKipcblx0ICogUnVucyB0aGUgaGFuZGxlcnMgd2hlbiBhbiBldmVudCBpcyBsaXN0ZW5lZCB0by5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHJ1bkxpc3RlbmVySGFuZGxlcnNfKGV2ZW50KSB7XG5cdFx0bGV0IGhhbmRsZXJzID0gdGhpcy5saXN0ZW5lckhhbmRsZXJzXztcblx0XHRpZiAoaGFuZGxlcnMpIHtcblx0XHRcdGhhbmRsZXJzID0gdG9BcnJheShoYW5kbGVycyk7XG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGhhbmRsZXJzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGhhbmRsZXJzW2ldKGV2ZW50KTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUnVucyB0aGUgZ2l2ZW4gbGlzdGVuZXJzLlxuXHQgKiBAcGFyYW0geyFBcnJheX0gbGlzdGVuZXJzXG5cdCAqIEBwYXJhbSB7IUFycmF5fSBhcmdzXG5cdCAqIEBwYXJhbSAoT2JqZWN0KSBmYWNhZGVcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0cnVuTGlzdGVuZXJzXyhsaXN0ZW5lcnMsIGFyZ3MsIGZhY2FkZSkge1xuXHRcdGlmIChmYWNhZGUpIHtcblx0XHRcdGFyZ3MucHVzaChmYWNhZGUpO1xuXHRcdH1cblxuXHRcdGNvbnN0IGRlZmF1bHRMaXN0ZW5lcnMgPSBbXTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3QgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV0uZm4gfHwgbGlzdGVuZXJzW2ldO1xuXHRcdFx0aWYgKGxpc3RlbmVyc1tpXS5kZWZhdWx0KSB7XG5cdFx0XHRcdGRlZmF1bHRMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRsaXN0ZW5lci5hcHBseSh0aGlzLCBhcmdzKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCFmYWNhZGUgfHwgIWZhY2FkZS5wcmV2ZW50ZWREZWZhdWx0KSB7XG5cdFx0XHRmb3IgKGxldCBqID0gMDsgaiA8IGRlZmF1bHRMaXN0ZW5lcnMubGVuZ3RoOyBqKyspIHtcblx0XHRcdFx0ZGVmYXVsdExpc3RlbmVyc1tqXS5hcHBseSh0aGlzLCBhcmdzKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgY29uZmlndXJhdGlvbiBvcHRpb24gd2hpY2ggZGV0ZXJtaW5lcyBpZiBhbiBldmVudCBmYWNhZGUgc2hvdWxkXG5cdCAqIGJlIHNlbnQgYXMgYSBwYXJhbSBvZiBsaXN0ZW5lcnMgd2hlbiBlbWl0dGluZyBldmVudHMuIElmIHNldCB0byB0cnVlLCB0aGVcblx0ICogZmFjYWRlIHdpbGwgYmUgcGFzc2VkIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBvZiB0aGUgbGlzdGVuZXIuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gc2hvdWxkVXNlRmFjYWRlXG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRzZXRTaG91bGRVc2VGYWNhZGUoc2hvdWxkVXNlRmFjYWRlKSB7XG5cdFx0dGhpcy5zaG91bGRVc2VGYWNhZGVfID0gc2hvdWxkVXNlRmFjYWRlO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIHRoZSBwYXJhbWV0ZXIgdG8gYW4gYXJyYXkgaWYgb25seSBvbmUgZXZlbnQgaXMgZ2l2ZW4uIFJldXNlcyB0aGVcblx0ICogc2FtZSBhcnJheSBlYWNoIHRpbWUgdGhpcyBjb252ZXJzaW9uIGlzIGRvbmUsIHRvIGF2b2lkIHVzaW5nIG1vcmUgbWVtb3J5XG5cdCAqIHRoYW4gbmVjZXNzYXJ5LlxuXHQgKiBAcGFyYW0gIHshKEFycmF5fHN0cmluZyl9IGV2ZW50c1xuXHQgKiBAcmV0dXJuIHshQXJyYXl9XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHRvRXZlbnRzQXJyYXlfKGV2ZW50cykge1xuXHRcdGlmIChpc1N0cmluZyhldmVudHMpKSB7XG5cdFx0XHRzaW5nbGVBcnJheV9bMF0gPSBldmVudHM7XG5cdFx0XHRldmVudHMgPSBzaW5nbGVBcnJheV87XG5cdFx0fVxuXHRcdHJldHVybiBldmVudHM7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBsaXN0ZW5lciBpcyB2YWxpZCwgdGhyb3dpbmcgYW4gZXhjZXB0aW9uIHdoZW4gaXQncyBub3QuXG5cdCAqIEBwYXJhbSAgeyp9IGxpc3RlbmVyXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHZhbGlkYXRlTGlzdGVuZXJfKGxpc3RlbmVyKSB7XG5cdFx0aWYgKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSkge1xuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcignTGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIHRvQXJyYXkodmFsKSB7XG5cdHZhbCA9IHZhbCB8fCBbXTtcblx0cmV0dXJuIEFycmF5LmlzQXJyYXkodmFsKSA/IHZhbCA6IFt2YWxdO1xufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEVtaXR0ZXI7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IERpc3Bvc2FibGUgfSBmcm9tICdtZXRhbCc7XG5cbi8qKlxuICogRXZlbnRFbWl0dGVyUHJveHkgdXRpbGl0eS4gSXQncyByZXNwb25zaWJsZSBmb3IgbGlua2luZyB0d28gRXZlbnRFbWl0dGVyXG4gKiBpbnN0YW5jZXMgdG9nZXRoZXIsIGVtaXR0aW5nIGV2ZW50cyBmcm9tIHRoZSBmaXJzdCBlbWl0dGVyIHRocm91Z2ggdGhlXG4gKiBzZWNvbmQgb25lLiBUaGF0IG1lYW5zIHRoYXQgbGlzdGVuaW5nIHRvIGEgc3VwcG9ydGVkIGV2ZW50IG9uIHRoZSB0YXJnZXRcbiAqIGVtaXR0ZXIgd2lsbCBtZWFuIGxpc3RlbmluZyB0byBpdCBvbiB0aGUgb3JpZ2luIGVtaXR0ZXIgYXMgd2VsbC5cbiAqIEBwYXJhbSB7RXZlbnRFbWl0dGVyfSBvcmlnaW5FbWl0dGVyIEV2ZW50cyBvcmlnaW5hdGVkIG9uIHRoaXMgZW1pdHRlclxuICogICB3aWxsIGJlIGZpcmVkIGZvciB0aGUgdGFyZ2V0IGVtaXR0ZXIncyBsaXN0ZW5lcnMgYXMgd2VsbC5cbiAqIEBwYXJhbSB7RXZlbnRFbWl0dGVyfSB0YXJnZXRFbWl0dGVyIEV2ZW50IGxpc3RlbmVycyBhdHRhY2hlZCB0byB0aGlzIGVtaXR0ZXJcbiAqICAgd2lsbCBhbHNvIGJlIHRyaWdnZXJlZCB3aGVuIHRoZSBldmVudCBpcyBmaXJlZCBieSB0aGUgb3JpZ2luIGVtaXR0ZXIuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0X2JsYWNrbGlzdCBPcHRpb25hbCBibGFja2xpc3Qgb2YgZXZlbnRzIHRoYXQgc2hvdWxkIG5vdCBiZVxuICogICBwcm94aWVkLlxuICogQGNvbnN0cnVjdG9yXG4gKiBAZXh0ZW5kcyB7RGlzcG9zYWJsZX1cbiAqL1xuY2xhc3MgRXZlbnRFbWl0dGVyUHJveHkgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblx0Y29uc3RydWN0b3Iob3JpZ2luRW1pdHRlciwgdGFyZ2V0RW1pdHRlciwgb3B0X2JsYWNrbGlzdCwgb3B0X3doaXRlbGlzdCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBNYXAgb2YgZXZlbnRzIHRoYXQgc2hvdWxkIG5vdCBiZSBwcm94aWVkLlxuXHRcdCAqIEB0eXBlIHtPYmplY3R9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYmxhY2tsaXN0XyA9IG9wdF9ibGFja2xpc3Q7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgb3JpZ2luIGVtaXR0ZXIuIFRoaXMgZW1pdHRlcidzIGV2ZW50cyB3aWxsIGJlIHByb3hpZWQgdGhyb3VnaCB0aGVcblx0XHQgKiB0YXJnZXQgZW1pdHRlci5cblx0XHQgKiBAdHlwZSB7RXZlbnRFbWl0dGVyfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLm9yaWdpbkVtaXR0ZXJfID0gb3JpZ2luRW1pdHRlcjtcblxuXHRcdC8qKlxuXHRcdCAqIEEgbGlzdCBvZiBldmVudHMgdGhhdCBhcmUgcGVuZGluZyB0byBiZSBsaXN0ZW5lZCBieSBhbiBhY3R1YWwgb3JpZ2luXG5cdFx0ICogZW1pdHRlci4gRXZlbnRzIGFyZSBzdG9yZWQgaGVyZSB3aGVuIHRoZSBvcmlnaW4gZG9lc24ndCBleGlzdCwgc28gdGhleVxuXHRcdCAqIGNhbiBiZSBzZXQgb24gYSBuZXcgb3JpZ2luIHdoZW4gb25lIGlzIHNldC5cblx0XHQgKiBAdHlwZSB7QXJyYXl9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucGVuZGluZ0V2ZW50c18gPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgYSBtYXAgb2YgZXZlbnRzIGZyb20gdGhlIG9yaWdpbiBlbWl0dGVyIHRoYXQgYXJlIGFscmVhZHkgYmVpbmcgcHJveGllZC5cblx0XHQgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgIUV2ZW50SGFuZGxlPn1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wcm94aWVkRXZlbnRzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgdGFyZ2V0IGVtaXR0ZXIuIFRoaXMgZW1pdHRlciB3aWxsIGVtaXQgYWxsIGV2ZW50cyB0aGF0IGNvbWUgZnJvbVxuXHRcdCAqIHRoZSBvcmlnaW4gZW1pdHRlci5cblx0XHQgKiBAdHlwZSB7RXZlbnRFbWl0dGVyfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnRhcmdldEVtaXR0ZXJfID0gdGFyZ2V0RW1pdHRlcjtcblxuXHRcdC8qKlxuXHRcdCAqIE1hcCBvZiBldmVudHMgdGhhdCBzaG91bGQgYmUgcHJveGllZC4gSWYgd2hpdGVsaXN0IGlzIHNldCBibGFja2xpc3QgaXMgaWdub3JlZC5cblx0XHQgKiBAdHlwZSB7T2JqZWN0fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLndoaXRlbGlzdF8gPSBvcHRfd2hpdGVsaXN0O1xuXG5cdFx0dGhpcy5zdGFydFByb3h5XygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIGdpdmVuIGxpc3RlbmVyIGZvciB0aGUgZ2l2ZW4gZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbigpfSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IFRoZSBsaXN0ZW5lZCBldmVudCdzIGhhbmRsZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0YWRkTGlzdGVuZXJfKGV2ZW50LCBsaXN0ZW5lcikge1xuXHRcdHJldHVybiB0aGlzLm9yaWdpbkVtaXR0ZXJfLm9uKGV2ZW50LCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLnJlbW92ZUxpc3RlbmVyc18oKTtcblx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gbnVsbDtcblx0XHR0aGlzLm9yaWdpbkVtaXR0ZXJfID0gbnVsbDtcblx0XHR0aGlzLnRhcmdldEVtaXR0ZXJfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBFbWl0cyB0aGUgc3BlY2lmaWVkIGV2ZW50IHR5cGUgb24gdGhlIHRhcmdldCBlbWl0dGVyLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRlbWl0T25UYXJnZXRfKCkge1xuXHRcdHRoaXMudGFyZ2V0RW1pdHRlcl8uZW1pdC5hcHBseSh0aGlzLnRhcmdldEVtaXR0ZXJfLCBhcmd1bWVudHMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByb3hpZXMgdGhlIGdpdmVuIGV2ZW50IGZyb20gdGhlIG9yaWdpbiB0byB0aGUgdGFyZ2V0IGVtaXR0ZXIuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKi9cblx0cHJveHlFdmVudChldmVudCkge1xuXHRcdGlmICh0aGlzLnNob3VsZFByb3h5RXZlbnRfKGV2ZW50KSkge1xuXHRcdFx0dGhpcy50cnlUb0FkZExpc3RlbmVyXyhldmVudCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIHByb3h5IGxpc3RlbmVyIGZvciBhbGwgZXZlbnRzLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRyZW1vdmVMaXN0ZW5lcnNfKCkge1xuXHRcdGlmICh0aGlzLnByb3hpZWRFdmVudHNfKSB7XG5cdFx0XHRjb25zdCBldmVudHMgPSBPYmplY3Qua2V5cyh0aGlzLnByb3hpZWRFdmVudHNfKTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHRoaXMucHJveGllZEV2ZW50c19bZXZlbnRzW2ldXS5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzXyA9IG51bGw7XG5cdFx0fVxuXHRcdHRoaXMucGVuZGluZ0V2ZW50c18gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoYW5nZXMgdGhlIG9yaWdpbiBlbWl0dGVyLiBUaGlzIGF1dG9tYXRpY2FsbHkgZGV0YWNoZXMgYW55IGV2ZW50cyB0aGF0XG5cdCAqIHdlcmUgYWxyZWFkeSBiZWluZyBwcm94aWVkIGZyb20gdGhlIHByZXZpb3VzIGVtaXR0ZXIsIGFuZCBzdGFydHMgcHJveHlpbmdcblx0ICogdGhlbSBvbiB0aGUgbmV3IGVtaXR0ZXIgaW5zdGVhZC5cblx0ICogQHBhcmFtIHshRXZlbnRFbWl0dGVyfSBvcmlnaW5FbWl0dGVyXG5cdCAqL1xuXHRzZXRPcmlnaW5FbWl0dGVyKG9yaWdpbkVtaXR0ZXIpIHtcblx0XHRjb25zdCBldmVudHMgPSB0aGlzLm9yaWdpbkVtaXR0ZXJfICYmIHRoaXMucHJveGllZEV2ZW50c18gP1xuXHRcdFx0T2JqZWN0LmtleXModGhpcy5wcm94aWVkRXZlbnRzXykgOlxuXHRcdFx0dGhpcy5wZW5kaW5nRXZlbnRzXztcblx0XHR0aGlzLm9yaWdpbkVtaXR0ZXJfID0gb3JpZ2luRW1pdHRlcjtcblx0XHRpZiAoZXZlbnRzKSB7XG5cdFx0XHR0aGlzLnJlbW92ZUxpc3RlbmVyc18oKTtcblx0XHRcdGV2ZW50cy5mb3JFYWNoKGV2ZW50ID0+IHRoaXMucHJveHlFdmVudChldmVudCkpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGV2ZW50IHNob3VsZCBiZSBwcm94aWVkLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0c2hvdWxkUHJveHlFdmVudF8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy53aGl0ZWxpc3RfICYmICF0aGlzLndoaXRlbGlzdF9bZXZlbnRdKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGlmICh0aGlzLmJsYWNrbGlzdF8gJiYgdGhpcy5ibGFja2xpc3RfW2V2ZW50XSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gIXRoaXMucHJveGllZEV2ZW50c18gfHwgIXRoaXMucHJveGllZEV2ZW50c19bZXZlbnRdO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0cyBwcm94eWluZyBhbGwgZXZlbnRzIGZyb20gdGhlIG9yaWdpbiB0byB0aGUgdGFyZ2V0IGVtaXR0ZXIuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHN0YXJ0UHJveHlfKCkge1xuXHRcdHRoaXMudGFyZ2V0RW1pdHRlcl8ub25MaXN0ZW5lcih0aGlzLnByb3h5RXZlbnQuYmluZCh0aGlzKSk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBvcmlnaW4gZW1pdHRlciwgaWYgaXQgZXhpc3RzLiBPdGhlcndpc2UsIHN0b3Jlc1xuXHQgKiB0aGUgcGVuZGluZyBsaXN0ZW5lciBzbyBpdCBjYW4gYmUgdXNlZCBvbiBhIGZ1dHVyZSBvcmlnaW4gZW1pdHRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHRyeVRvQWRkTGlzdGVuZXJfKGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMub3JpZ2luRW1pdHRlcl8pIHtcblx0XHRcdHRoaXMucHJveGllZEV2ZW50c18gPSB0aGlzLnByb3hpZWRFdmVudHNfIHx8IHt9O1xuXHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzX1tldmVudF0gPSB0aGlzLmFkZExpc3RlbmVyXyhcblx0XHRcdFx0ZXZlbnQsXG5cdFx0XHRcdHRoaXMuZW1pdE9uVGFyZ2V0Xy5iaW5kKHRoaXMsIGV2ZW50KVxuXHRcdFx0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5wZW5kaW5nRXZlbnRzXyA9IHRoaXMucGVuZGluZ0V2ZW50c18gfHwgW107XG5cdFx0XHR0aGlzLnBlbmRpbmdFdmVudHNfLnB1c2goZXZlbnQpO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEVtaXR0ZXJQcm94eTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgRGlzcG9zYWJsZSB9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBFdmVudEhhbmRsZXIgdXRpbGl0eS4gSXQncyB1c2VmdWwgZm9yIGVhc2lseSByZW1vdmluZyBhIGdyb3VwIG9mXG4gKiBsaXN0ZW5lcnMgZnJvbSBkaWZmZXJlbnQgRXZlbnRFbWl0dGVyIGluc3RhbmNlcy5cbiAqIEBjb25zdHJ1Y3RvclxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIEV2ZW50SGFuZGxlciBleHRlbmRzIERpc3Bvc2FibGUge1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogQW4gYXJyYXkgdGhhdCBob2xkcyB0aGUgYWRkZWQgZXZlbnQgaGFuZGxlcywgc28gdGhlIGxpc3RlbmVycyBjYW4gYmVcblx0XHQgKiByZW1vdmVkIGxhdGVyLlxuXHRcdCAqIEB0eXBlIHtBcnJheS48RXZlbnRIYW5kbGU+fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmV2ZW50SGFuZGxlc18gPSBbXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGV2ZW50IGhhbmRsZXMgdG8gYmUgcmVtb3ZlZCBsYXRlciB0aHJvdWdoIHRoZSBgcmVtb3ZlQWxsTGlzdGVuZXJzYFxuXHQgKiBtZXRob2QuXG5cdCAqIEBwYXJhbSB7Li4uKCFFdmVudEhhbmRsZSl9IHZhcl9hcmdzXG5cdCAqL1xuXHRhZGQoKSB7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuZXZlbnRIYW5kbGVzXy5wdXNoKGFyZ3VtZW50c1tpXSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy5cblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5ldmVudEhhbmRsZXNfID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgdGhhdCBoYXZlIGJlZW4gYWRkZWQgdGhyb3VnaCB0aGUgYGFkZGAgbWV0aG9kLlxuXHQgKi9cblx0cmVtb3ZlQWxsTGlzdGVuZXJzKCkge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5ldmVudEhhbmRsZXNfLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmV2ZW50SGFuZGxlc19baV0ucmVtb3ZlTGlzdGVuZXIoKTtcblx0XHR9XG5cblx0XHR0aGlzLmV2ZW50SGFuZGxlc18gPSBbXTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEhhbmRsZXI7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGFycmF5LCBpc1N0cmluZyB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBkb21EYXRhIGZyb20gJy4vZG9tRGF0YSc7XG5pbXBvcnQgeyBFdmVudEhhbmRsZSB9IGZyb20gJ21ldGFsLWV2ZW50cyc7XG5cbi8qKlxuICogVGhpcyBpcyBhIHNwZWNpYWwgRXZlbnRIYW5kbGUsIHRoYXQgaXMgcmVzcG9uc2libGUgZm9yIGRvbSBkZWxlZ2F0ZWQgZXZlbnRzXG4gKiAob25seSB0aGUgb25lcyB0aGF0IHJlY2VpdmUgYSB0YXJnZXQgZWxlbWVudCwgbm90IGEgc2VsZWN0b3Igc3RyaW5nKS5cbiAqIEBleHRlbmRzIHtFdmVudEhhbmRsZX1cbiAqL1xuY2xhc3MgRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGUgZXh0ZW5kcyBFdmVudEhhbmRsZSB7XG5cdC8qKlxuXHQgKiBUaGUgY29uc3RydWN0b3IgZm9yIGBEb21EZWxlZ2F0ZWRFdmVudEhhbmRsZWAuXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBlbWl0dGVyIEVsZW1lbnQgdGhlIGV2ZW50IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnQgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRoYXQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lciBUaGUgbGlzdGVuZXIgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nPX0gb3B0X3NlbGVjdG9yIEFuIG9wdGlvbmFsIHNlbGVjdG9yIHVzZWQgd2hlbiBkZWxlZ2F0aW5nXG5cdCAqICAgICB0aGUgZXZlbnQuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoZW1pdHRlciwgZXZlbnQsIGxpc3RlbmVyLCBvcHRfc2VsZWN0b3IpIHtcblx0XHRzdXBlcihlbWl0dGVyLCBldmVudCwgbGlzdGVuZXIpO1xuXHRcdHRoaXMuc2VsZWN0b3JfID0gb3B0X3NlbGVjdG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRyZW1vdmVMaXN0ZW5lcigpIHtcblx0XHRjb25zdCBkZWxlZ2F0aW5nID0gZG9tRGF0YS5nZXQodGhpcy5lbWl0dGVyXywgJ2RlbGVnYXRpbmcnLCB7fSk7XG5cdFx0Y29uc3QgbGlzdGVuZXJzID0gZG9tRGF0YS5nZXQodGhpcy5lbWl0dGVyXywgJ2xpc3RlbmVycycsIHt9KTtcblx0XHRjb25zdCBzZWxlY3RvciA9IHRoaXMuc2VsZWN0b3JfO1xuXHRcdGNvbnN0IGFyciA9IGlzU3RyaW5nKHNlbGVjdG9yKSA/IGRlbGVnYXRpbmdbdGhpcy5ldmVudF9dLnNlbGVjdG9ycyA6IGxpc3RlbmVycztcblx0XHRjb25zdCBrZXkgPSBpc1N0cmluZyhzZWxlY3RvcikgPyBzZWxlY3RvciA6IHRoaXMuZXZlbnRfO1xuXG5cdFx0YXJyYXkucmVtb3ZlKGFycltrZXldIHx8IFtdLCB0aGlzLmxpc3RlbmVyXyk7XG5cdFx0aWYgKGFycltrZXldICYmIGFycltrZXldLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0ZGVsZXRlIGFycltrZXldO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBEb21EZWxlZ2F0ZWRFdmVudEhhbmRsZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgRXZlbnRIYW5kbGUgfSBmcm9tICdtZXRhbC1ldmVudHMnO1xuXG4vKipcbiAqIFRoaXMgaXMgYSBzcGVjaWFsIEV2ZW50SGFuZGxlLCB0aGF0IGlzIHJlc3BvbnNpYmxlIGZvciBkb20gZXZlbnRzLCBpbnN0ZWFkXG4gKiBvZiBFdmVudEVtaXR0ZXIgZXZlbnRzLlxuICogQGV4dGVuZHMge0V2ZW50SGFuZGxlfVxuICovXG5jbGFzcyBEb21FdmVudEhhbmRsZSBleHRlbmRzIEV2ZW50SGFuZGxlIHtcblx0LyoqXG5cdCAqIFRoZSBjb25zdHJ1Y3RvciBmb3IgYERvbUV2ZW50SGFuZGxlYC5cblx0ICogQHBhcmFtIHshRXZlbnRFbWl0dGVyfSBlbWl0dGVyIEVtaXR0ZXIgdGhlIGV2ZW50IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnQgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRoYXQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lciBUaGUgbGlzdGVuZXIgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnQuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0X2NhcHR1cmUgRmxhZyBpbmRpY2F0aW5nIGlmIGxpc3RlbmVyIHNob3VsZCBiZSB0cmlnZ2VyZWRcblx0ICogICBkdXJpbmcgY2FwdHVyZSBwaGFzZSwgaW5zdGVhZCBvZiBkdXJpbmcgdGhlIGJ1YmJsaW5nIHBoYXNlLiBEZWZhdWx0cyB0byBmYWxzZS5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihlbWl0dGVyLCBldmVudCwgbGlzdGVuZXIsIG9wdF9jYXB0dXJlKSB7XG5cdFx0c3VwZXIoZW1pdHRlciwgZXZlbnQsIGxpc3RlbmVyKTtcblx0XHR0aGlzLmNhcHR1cmVfID0gb3B0X2NhcHR1cmU7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyKCkge1xuXHRcdHRoaXMuZW1pdHRlcl8ucmVtb3ZlRXZlbnRMaXN0ZW5lcih0aGlzLmV2ZW50XywgdGhpcy5saXN0ZW5lcl8sIHRoaXMuY2FwdHVyZV8pO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERvbUV2ZW50SGFuZGxlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBpc0RlZiwgaXNEb2N1bWVudCwgaXNEb2N1bWVudEZyYWdtZW50LCBpc0VsZW1lbnQsIGlzT2JqZWN0LCBpc1N0cmluZywgb2JqZWN0IH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IGRvbURhdGEgZnJvbSAnLi9kb21EYXRhJztcbmltcG9ydCBEb21EZWxlZ2F0ZWRFdmVudEhhbmRsZSBmcm9tICcuL0RvbURlbGVnYXRlZEV2ZW50SGFuZGxlJztcbmltcG9ydCBEb21FdmVudEhhbmRsZSBmcm9tICcuL0RvbUV2ZW50SGFuZGxlJztcblxuY29uc3QgZWxlbWVudHNCeVRhZ18gPSB7fTtcbmNvbnN0IHN1cHBvcnRDYWNoZV8gPSB7fTtcbmV4cG9ydCBjb25zdCBjdXN0b21FdmVudHMgPSB7fTtcblxuY29uc3QgTEFTVF9DT05UQUlORVIgPSAnX19tZXRhbF9sYXN0X2NvbnRhaW5lcl9fJztcbmNvbnN0IFVTRV9DQVBUVVJFID0ge1xuXHRibHVyOiB0cnVlLFxuXHRlcnJvcjogdHJ1ZSxcblx0Zm9jdXM6IHRydWUsXG5cdGludmFsaWQ6IHRydWUsXG5cdGxvYWQ6IHRydWUsXG5cdHNjcm9sbDogdHJ1ZVxufTtcblxuLyoqXG4gKiBBZGRzIHRoZSByZXF1ZXN0ZWQgQ1NTIGNsYXNzZXMgdG8gYW4gZWxlbWVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR8IU5vZGVsaXN0fSBlbGVtZW50cyBUaGUgZWxlbWVudCBvciBlbGVtZW50cyB0byBhZGQgQ1NTIGNsYXNzZXMgdG8uXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NlcyBDU1MgY2xhc3NlcyB0byBhZGQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRDbGFzc2VzKGVsZW1lbnRzLCBjbGFzc2VzKSB7XG5cdGlmICghaXNPYmplY3QoZWxlbWVudHMpIHx8ICFpc1N0cmluZyhjbGFzc2VzKSkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdGlmICghZWxlbWVudHMubGVuZ3RoKSB7XG5cdFx0ZWxlbWVudHMgPSBbZWxlbWVudHNdO1xuXHR9XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdGlmICgnY2xhc3NMaXN0JyBpbiBlbGVtZW50c1tpXSkge1xuXHRcdFx0YWRkQ2xhc3Nlc1dpdGhOYXRpdmVfKGVsZW1lbnRzW2ldLCBjbGFzc2VzKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0YWRkQ2xhc3Nlc1dpdGhvdXROYXRpdmVfKGVsZW1lbnRzW2ldLCBjbGFzc2VzKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBBZGRzIHRoZSByZXF1ZXN0ZWQgQ1NTIGNsYXNzZXMgdG8gYW4gZWxlbWVudCB1c2luZyBjbGFzc0xpc3QuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHRvIGFkZCBDU1MgY2xhc3NlcyB0by5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIGFkZC5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGFkZENsYXNzZXNXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGNsYXNzZXMuc3BsaXQoJyAnKS5mb3JFYWNoKGZ1bmN0aW9uKGNsYXNzTmFtZSkge1xuXHRcdGlmIChjbGFzc05hbWUpIHtcblx0XHRcdGVsZW1lbnQuY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpO1xuXHRcdH1cblx0fSk7XG59XG5cbi8qKlxuICogQWRkcyB0aGUgcmVxdWVzdGVkIENTUyBjbGFzc2VzIHRvIGFuIGVsZW1lbnQgd2l0aG91dCB1c2luZyBjbGFzc0xpc3QuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHRvIGFkZCBDU1MgY2xhc3NlcyB0by5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIGFkZC5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGFkZENsYXNzZXNXaXRob3V0TmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGNvbnN0IGVsZW1lbnRDbGFzc05hbWUgPSBgICR7ZWxlbWVudC5jbGFzc05hbWV9IGA7XG5cdGxldCBjbGFzc2VzVG9BcHBlbmQgPSAnJztcblxuXHRjbGFzc2VzID0gY2xhc3Nlcy5zcGxpdCgnICcpO1xuXG5cdGZvciAobGV0IGkgPSAwOyBpIDwgY2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuXHRcdGNvbnN0IGNsYXNzTmFtZSA9IGNsYXNzZXNbaV07XG5cblx0XHRpZiAoZWxlbWVudENsYXNzTmFtZS5pbmRleE9mKGAgJHtjbGFzc05hbWV9IGApID09PSAtMSkge1xuXHRcdFx0Y2xhc3Nlc1RvQXBwZW5kICs9IGAgJHtjbGFzc05hbWV9YDtcblx0XHR9XG5cdH1cblxuXHRpZiAoY2xhc3Nlc1RvQXBwZW5kKSB7XG5cdFx0ZWxlbWVudC5jbGFzc05hbWUgPSBlbGVtZW50LmNsYXNzTmFtZSArIGNsYXNzZXNUb0FwcGVuZDtcblx0fVxufVxuXG4vKipcbiAqIEFkZHMgYW4gZXZlbnQgbGlzdGVuZXIgdG8gdGhlIGdpdmVuIGVsZW1lbnQsIHRvIGJlIHRyaWdnZXJlZCB2aWEgZGVsZWdhdGUuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKiBAcGFyYW0geyFmdW5jdGlvbigpfSBsaXN0ZW5lclxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkRWxlbWVudExpc3RlbmVyXyhlbGVtZW50LCBldmVudE5hbWUsIGxpc3RlbmVyKSB7XG5cdGFkZFRvQXJyXyhkb21EYXRhLmdldChlbGVtZW50LCAnbGlzdGVuZXJzJywge30pLCBldmVudE5hbWUsIGxpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBBZGRzIGFuIGV2ZW50IGxpc3RlbmVyIHRvIHRoZSBnaXZlbiBlbGVtZW50LCB0byBiZSB0cmlnZ2VyZWQgdmlhIGRlbGVnYXRlXG4gKiBzZWxlY3RvcnMuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JcbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGxpc3RlbmVyXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBhZGRTZWxlY3Rvckxpc3RlbmVyXyhlbGVtZW50LCBldmVudE5hbWUsIHNlbGVjdG9yLCBsaXN0ZW5lcikge1xuXHRjb25zdCBkZWxlZ2F0aW5nRGF0YSA9IGRvbURhdGEuZ2V0KGVsZW1lbnQsICdkZWxlZ2F0aW5nJywge30pO1xuXHRhZGRUb0Fycl8oZGVsZWdhdGluZ0RhdGFbZXZlbnROYW1lXS5zZWxlY3RvcnMsIHNlbGVjdG9yLCBsaXN0ZW5lcik7XG59XG5cbi8qKlxuICogQWRkcyBhIHZhbHVlIHRvIGFuIGFycmF5IGluc2lkZSBhbiBvYmplY3QsIGNyZWF0aW5nIGl0IGZpcnN0IGlmIGl0IGRvZXNuJ3RcbiAqIHlldCBleGlzdC5cbiAqIEBwYXJhbSB7IUFycmF5fSBhcnJcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGFkZFRvQXJyXyhhcnIsIGtleSwgdmFsdWUpIHtcblx0aWYgKCFhcnJba2V5XSkge1xuXHRcdGFycltrZXldID0gW107XG5cdH1cblx0YXJyW2tleV0ucHVzaCh2YWx1ZSk7XG59XG5cbi8qKlxuICogQXR0YWNoZXMgYSBkZWxlZ2F0ZSBsaXN0ZW5lciwgdW5sZXNzIHRoZXJlJ3MgYWxyZWFkeSBvbmUgYXR0YWNoZWQuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBhdHRhY2hEZWxlZ2F0ZUV2ZW50XyhlbGVtZW50LCBldmVudE5hbWUpIHtcblx0bGV0IGRlbGVnYXRpbmdEYXRhID0gZG9tRGF0YS5nZXQoZWxlbWVudCwgJ2RlbGVnYXRpbmcnLCB7fSk7XG5cdGlmICghZGVsZWdhdGluZ0RhdGFbZXZlbnROYW1lXSkge1xuXHRcdGRlbGVnYXRpbmdEYXRhW2V2ZW50TmFtZV0gPSB7XG5cdFx0XHRoYW5kbGU6IG9uKFxuXHRcdFx0XHRlbGVtZW50LFxuXHRcdFx0XHRldmVudE5hbWUsXG5cdFx0XHRcdGhhbmRsZURlbGVnYXRlRXZlbnRfLFxuXHRcdFx0XHQhIVVTRV9DQVBUVVJFW2V2ZW50TmFtZV1cblx0XHRcdCksXG5cdFx0XHRzZWxlY3RvcnM6IHt9XG5cdFx0fTtcblx0fVxufVxuXG4vKipcbiAqIEdldHMgdGhlIGNsb3Nlc3QgZWxlbWVudCB1cCB0aGUgdHJlZSBmcm9tIHRoZSBnaXZlbiBlbGVtZW50IChpbmNsdWRpbmdcbiAqIGl0c2VsZikgdGhhdCBtYXRjaGVzIHRoZSBzcGVjaWZpZWQgc2VsZWN0b3IsIG9yIG51bGwgaWYgbm9uZSBtYXRjaC5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcmV0dXJuIHtFbGVtZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xvc2VzdChlbGVtZW50LCBzZWxlY3Rvcikge1xuXHR3aGlsZSAoZWxlbWVudCAmJiAhbWF0Y2goZWxlbWVudCwgc2VsZWN0b3IpKSB7XG5cdFx0ZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcblx0fVxuXHRyZXR1cm4gZWxlbWVudDtcbn1cblxuLyoqXG4gKiBBcHBlbmRzIGEgY2hpbGQgbm9kZSB3aXRoIHRleHQgb3Igb3RoZXIgbm9kZXMgdG8gYSBwYXJlbnQgbm9kZS4gSWZcbiAqIGNoaWxkIGlzIGEgSFRNTCBzdHJpbmcgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNvbnZlcnRlZCB0byBhIGRvY3VtZW50XG4gKiBmcmFnbWVudCBiZWZvcmUgYXBwZW5kaW5nIGl0IHRvIHRoZSBwYXJlbnQuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBwYXJlbnQgVGhlIG5vZGUgdG8gYXBwZW5kIG5vZGVzIHRvLlxuICogQHBhcmFtIHshKEVsZW1lbnR8Tm9kZUxpc3R8c3RyaW5nKX0gY2hpbGQgVGhlIHRoaW5nIHRvIGFwcGVuZCB0byB0aGUgcGFyZW50LlxuICogQHJldHVybiB7IUVsZW1lbnR9IFRoZSBhcHBlbmRlZCBjaGlsZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGVuZChwYXJlbnQsIGNoaWxkKSB7XG5cdGlmIChpc1N0cmluZyhjaGlsZCkpIHtcblx0XHRjaGlsZCA9IGJ1aWxkRnJhZ21lbnQoY2hpbGQpO1xuXHR9XG5cdGlmIChjaGlsZCBpbnN0YW5jZW9mIE5vZGVMaXN0KSB7XG5cdFx0Y29uc3QgY2hpbGRBcnIgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChjaGlsZCk7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZEFyci5sZW5ndGg7IGkrKykge1xuXHRcdFx0cGFyZW50LmFwcGVuZENoaWxkKGNoaWxkQXJyW2ldKTtcblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0cGFyZW50LmFwcGVuZENoaWxkKGNoaWxkKTtcblx0fVxuXHRyZXR1cm4gY2hpbGQ7XG59XG5cbi8qKlxuICogSGVscGVyIGZvciBjb252ZXJ0aW5nIGEgSFRNTCBzdHJpbmcgaW50byBhIGRvY3VtZW50IGZyYWdtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGh0bWxTdHJpbmcgVGhlIEhUTUwgc3RyaW5nIHRvIGNvbnZlcnQuXG4gKiBAcmV0dXJuIHshRWxlbWVudH0gVGhlIHJlc3VsdGluZyBkb2N1bWVudCBmcmFnbWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkRnJhZ21lbnQoaHRtbFN0cmluZykge1xuXHRjb25zdCB0ZW1wRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cdHRlbXBEaXYuaW5uZXJIVE1MID0gYDxicj4ke2h0bWxTdHJpbmd9YDtcblx0dGVtcERpdi5yZW1vdmVDaGlsZCh0ZW1wRGl2LmZpcnN0Q2hpbGQpO1xuXG5cdGNvbnN0IGZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuXHR3aGlsZSAodGVtcERpdi5maXJzdENoaWxkKSB7XG5cdFx0ZnJhZ21lbnQuYXBwZW5kQ2hpbGQodGVtcERpdi5maXJzdENoaWxkKTtcblx0fVxuXHRyZXR1cm4gZnJhZ21lbnQ7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBmaXJzdCBlbGVtZW50IGNvbnRhaW5zIHRoZSBzZWNvbmQgb25lLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudDFcbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQyXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnMoZWxlbWVudDEsIGVsZW1lbnQyKSB7XG5cdGlmIChpc0RvY3VtZW50KGVsZW1lbnQxKSkge1xuXHRcdC8vIGRvY3VtZW50LmNvbnRhaW5zIGlzIG5vdCBkZWZpbmVkIG9uIElFOSwgc28gY2FsbCBpdCBvbiBkb2N1bWVudEVsZW1lbnQgaW5zdGVhZC5cblx0XHRyZXR1cm4gZWxlbWVudDEuZG9jdW1lbnRFbGVtZW50LmNvbnRhaW5zKGVsZW1lbnQyKTtcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gZWxlbWVudDEuY29udGFpbnMoZWxlbWVudDIpO1xuXHR9XG59XG5cbi8qKlxuICogTGlzdGVucyB0byB0aGUgc3BlY2lmaWVkIGV2ZW50IG9uIHRoZSBnaXZlbiBET00gZWxlbWVudCwgYnV0IG9ubHkgY2FsbHMgdGhlXG4gKiBnaXZlbiBjYWxsYmFjayBsaXN0ZW5lciB3aGVuIGl0J3MgdHJpZ2dlcmVkIGJ5IGVsZW1lbnRzIHRoYXQgbWF0Y2ggdGhlXG4gKiBnaXZlbiBzZWxlY3RvciBvciB0YXJnZXQgZWxlbWVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIERPTSBlbGVtZW50IHRoZSBldmVudCBzaG91bGQgYmUgbGlzdGVuZWQgb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBsaXN0ZW4gdG8uXG4gKiBAcGFyYW0geyFFbGVtZW50fHN0cmluZ30gc2VsZWN0b3JPclRhcmdldCBFaXRoZXIgYW4gZWxlbWVudCBvciBjc3Mgc2VsZWN0b3JcbiAqICAgICB0aGF0IHNob3VsZCBtYXRjaCB0aGUgZXZlbnQgZm9yIHRoZSBsaXN0ZW5lciB0byBiZSB0cmlnZ2VyZWQuXG4gKiBAcGFyYW0geyFmdW5jdGlvbighT2JqZWN0KX0gY2FsbGJhY2sgRnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50XG4gKiAgICAgaXMgdHJpZ2dlcmVkLiBJdCB3aWxsIHJlY2VpdmUgdGhlIG5vcm1hbGl6ZWQgZXZlbnQgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFuPX0gb3B0X2RlZmF1bHQgT3B0aW9uYWwgZmxhZyBpbmRpY2F0aW5nIGlmIHRoaXMgaXMgYSBkZWZhdWx0XG4gKiAgICAgbGlzdGVuZXIuIFRoYXQgbWVhbnMgdGhhdCBpdCB3b3VsZCBvbmx5IGJlIGV4ZWN1dGVkIGFmdGVyIGFsbCBub25cbiAqICAgICBkZWZhdWx0IGxpc3RlbmVycywgYW5kIG9ubHkgaWYgdGhlIGV2ZW50IGlzbid0IHByZXZlbnRlZCB2aWFcbiAqICAgICBgcHJldmVudERlZmF1bHRgLlxuICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVsZWdhdGUoZWxlbWVudCwgZXZlbnROYW1lLCBzZWxlY3Rvck9yVGFyZ2V0LCBjYWxsYmFjaywgb3B0X2RlZmF1bHQpIHtcblx0Y29uc3QgY3VzdG9tQ29uZmlnID0gY3VzdG9tRXZlbnRzW2V2ZW50TmFtZV07XG5cdGlmIChjdXN0b21Db25maWcgJiYgY3VzdG9tQ29uZmlnLmRlbGVnYXRlKSB7XG5cdFx0ZXZlbnROYW1lID0gY3VzdG9tQ29uZmlnLm9yaWdpbmFsRXZlbnQ7XG5cdFx0Y2FsbGJhY2sgPSBjdXN0b21Db25maWcuaGFuZGxlci5iaW5kKGN1c3RvbUNvbmZpZywgY2FsbGJhY2spO1xuXHR9XG5cblx0aWYgKG9wdF9kZWZhdWx0KSB7XG5cdFx0Ly8gV3JhcCBjYWxsYmFjayBzbyB3ZSBkb24ndCBzZXQgcHJvcGVydHkgZGlyZWN0bHkgb24gaXQuXG5cdFx0Y2FsbGJhY2sgPSBjYWxsYmFjay5iaW5kKCk7XG5cdFx0Y2FsbGJhY2suZGVmYXVsdExpc3RlbmVyXyA9IHRydWU7XG5cdH1cblxuXHRhdHRhY2hEZWxlZ2F0ZUV2ZW50XyhlbGVtZW50LCBldmVudE5hbWUpO1xuXHRpZiAoaXNTdHJpbmcoc2VsZWN0b3JPclRhcmdldCkpIHtcblx0XHRhZGRTZWxlY3Rvckxpc3RlbmVyXyhlbGVtZW50LCBldmVudE5hbWUsIHNlbGVjdG9yT3JUYXJnZXQsIGNhbGxiYWNrKTtcblx0fSBlbHNlIHtcblx0XHRhZGRFbGVtZW50TGlzdGVuZXJfKHNlbGVjdG9yT3JUYXJnZXQsIGV2ZW50TmFtZSwgY2FsbGJhY2spO1xuXHR9XG5cblx0cmV0dXJuIG5ldyBEb21EZWxlZ2F0ZWRFdmVudEhhbmRsZShcblx0XHRpc1N0cmluZyhzZWxlY3Rvck9yVGFyZ2V0KSA/IGVsZW1lbnQgOiBzZWxlY3Rvck9yVGFyZ2V0LFxuXHRcdGV2ZW50TmFtZSxcblx0XHRjYWxsYmFjayxcblx0XHRpc1N0cmluZyhzZWxlY3Rvck9yVGFyZ2V0KSA/IHNlbGVjdG9yT3JUYXJnZXQgOiBudWxsXG5cdCk7XG59XG5cbi8qKlxuICogVmVyaWZpZXMgaWYgdGhlIGVsZW1lbnQgaXMgYWJsZSB0byB0cmlnZ2VyIHRoZSBDbGljayBldmVudCxcbiAqIHNpbXVsYXRpbmcgYnJvd3NlcnMgYmVoYXZpb3VyLCBhdm9pZGluZyBldmVudCBsaXN0ZW5lcnMgdG8gYmUgY2FsbGVkIGJ5IHRyaWdnZXJFdmVudCBtZXRob2QuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGUgRWxlbWVudCB0byBiZSBjaGVja2VkLlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgZXZlbnQgbmFtZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGlzQWJsZVRvSW50ZXJhY3RXaXRoXyhub2RlLCBldmVudE5hbWUsIG9wdF9ldmVudE9iaikge1xuXHRpZiAob3B0X2V2ZW50T2JqICYmIGV2ZW50TmFtZSA9PT0gJ2NsaWNrJyAmJiBvcHRfZXZlbnRPYmouYnV0dG9uID09PSAyKSB7XG5cdFx0Ly8gRmlyZWZveCB0cmlnZ2VycyBcImNsaWNrXCIgZXZlbnRzIG9uIHRoZSBkb2N1bWVudCBmb3IgcmlnaHQgY2xpY2tzLiBUaGlzXG5cdFx0Ly8gY2F1c2VzIG91ciBkZWxlZ2F0ZSBsb2dpYyB0byB0cmlnZ2VyIGl0IGZvciByZWd1bGFyIGVsZW1lbnRzIHRvbywgd2hpY2hcblx0XHQvLyBzaG91bGRuJ3QgaGFwcGVuLiBJZ25vcmluZyB0aGVtIGhlcmUuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Y29uc3QgbWF0Y2hlc1NlbGVjdG9yID0gWydCVVRUT04nLCAnSU5QVVQnLCAnU0VMRUNUJywgJ1RFWFRBUkVBJywgJ0ZJRUxEU0VUJ107XG5cdGlmIChldmVudE5hbWUgPT09ICdjbGljaycgJiYgbWF0Y2hlc1NlbGVjdG9yLmluZGV4T2Yobm9kZS50YWdOYW1lKSA+IC0xKSB7XG5cdFx0cmV0dXJuICEobm9kZS5kaXNhYmxlZCB8fCBwYXJlbnQobm9kZSwgJ2ZpZWxkc2V0W2Rpc2FibGVkXScpKTtcblx0fVxuXHRyZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBJbnNlcnRzIG5vZGUgaW4gZG9jdW1lbnQgYXMgbGFzdCBlbGVtZW50LlxuICogQHBhcmFtIHtFbGVtZW50fSBub2RlIEVsZW1lbnQgdG8gcmVtb3ZlIGNoaWxkcmVuIGZyb20uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnRlckRvY3VtZW50KG5vZGUpIHtcblx0bm9kZSAmJiBhcHBlbmQoZG9jdW1lbnQuYm9keSwgbm9kZSk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBub2RlIGZyb20gZG9jdW1lbnQuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGUgRWxlbWVudCB0byByZW1vdmUgY2hpbGRyZW4gZnJvbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4aXREb2N1bWVudChub2RlKSB7XG5cdGlmIChub2RlICYmIG5vZGUucGFyZW50Tm9kZSkge1xuXHRcdG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcblx0fVxufVxuXG4vKipcbiAqIFRoaXMgaXMgY2FsbGVkIHdoZW4gYW4gZXZlbnQgaXMgdHJpZ2dlcmVkIGJ5IGEgZGVsZWdhdGUgbGlzdGVuZXIuIEFsbFxuICogbWF0Y2hpbmcgbGlzdGVuZXJzIG9mIHRoaXMgZXZlbnQgdHlwZSBmcm9tIGB0YXJnZXRgIHRvIGBjdXJyZW50VGFyZ2V0YCB3aWxsXG4gKiBiZSB0cmlnZ2VyZWQuXG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgVGhlIGV2ZW50IHBheWxvYWQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBGYWxzZSBpZiBhdCBsZWFzdCBvbmUgb2YgdGhlIHRyaWdnZXJlZCBjYWxsYmFja3MgcmV0dXJuc1xuICogICAgIGZhbHNlLCBvciB0cnVlIG90aGVyd2lzZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZURlbGVnYXRlRXZlbnRfKGV2ZW50KSB7XG5cdG5vcm1hbGl6ZURlbGVnYXRlRXZlbnRfKGV2ZW50KTtcblx0bGV0IHJldCA9IHRydWU7XG5cdGNvbnN0IGNvbnRhaW5lciA9IGV2ZW50LmN1cnJlbnRUYXJnZXQ7XG5cdGNvbnN0IGRlZkZucyA9IFtdO1xuXG5cdHJldCAmPSB0cmlnZ2VyRGVsZWdhdGVkTGlzdGVuZXJzXyhjb250YWluZXIsIGV2ZW50LCBkZWZGbnMpO1xuXHRyZXQgJj0gdHJpZ2dlckRlZmF1bHREZWxlZ2F0ZWRMaXN0ZW5lcnNfKGRlZkZucywgZXZlbnQpO1xuXG5cdGV2ZW50LmRlbGVnYXRlVGFyZ2V0ID0gbnVsbDtcblx0ZXZlbnRbTEFTVF9DT05UQUlORVJdID0gY29udGFpbmVyO1xuXHRyZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZWxlbWVudCBoYXMgdGhlIHJlcXVlc3RlZCBjc3MgY2xhc3MuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzQ2xhc3MoZWxlbWVudCwgY2xhc3NOYW1lKSB7XG5cdGlmICgnY2xhc3NMaXN0JyBpbiBlbGVtZW50KSB7XG5cdFx0cmV0dXJuIGhhc0NsYXNzV2l0aE5hdGl2ZV8oZWxlbWVudCwgY2xhc3NOYW1lKTtcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gaGFzQ2xhc3NXaXRob3V0TmF0aXZlXyhlbGVtZW50LCBjbGFzc05hbWUpO1xuXHR9XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IGhhcyB0aGUgcmVxdWVzdGVkIGNzcyBjbGFzcyB1c2luZyBjbGFzc0xpc3QuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gaGFzQ2xhc3NXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc05hbWUpIHtcblx0cmV0dXJuIGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKGNsYXNzTmFtZSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IGhhcyB0aGUgcmVxdWVzdGVkIGNzcyBjbGFzcyB3aXRob3V0IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc05hbWVcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBoYXNDbGFzc1dpdGhvdXROYXRpdmVfKGVsZW1lbnQsIGNsYXNzTmFtZSkge1xuXHRyZXR1cm4gKGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYCkuaW5kZXhPZihgICR7Y2xhc3NOYW1lfSBgKSA+PSAwO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZWxlbWVudCBpcyBlbXB0eSBvciBub3QuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eShlbGVtZW50KSB7XG5cdHJldHVybiBlbGVtZW50LmNoaWxkTm9kZXMubGVuZ3RoID09PSAwO1xufVxuXG4vKipcbiAqIENoZWNrIGlmIGFuIGVsZW1lbnQgbWF0Y2hlcyBhIGdpdmVuIHNlbGVjdG9yLlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaChlbGVtZW50LCBzZWxlY3Rvcikge1xuXHRpZiAoIWVsZW1lbnQgfHwgZWxlbWVudC5ub2RlVHlwZSAhPT0gMSkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGNvbnN0IHAgPSBFbGVtZW50LnByb3RvdHlwZTtcblx0Y29uc3QgbSA9IHAubWF0Y2hlcyB8fCBwLndlYmtpdE1hdGNoZXNTZWxlY3RvciB8fCBwLm1vek1hdGNoZXNTZWxlY3RvciB8fCBwLm1zTWF0Y2hlc1NlbGVjdG9yIHx8IHAub01hdGNoZXNTZWxlY3Rvcjtcblx0aWYgKG0pIHtcblx0XHRyZXR1cm4gbS5jYWxsKGVsZW1lbnQsIHNlbGVjdG9yKTtcblx0fVxuXG5cdHJldHVybiBtYXRjaEZhbGxiYWNrXyhlbGVtZW50LCBzZWxlY3Rvcik7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgYW4gZWxlbWVudCBtYXRjaGVzIGEgZ2l2ZW4gc2VsZWN0b3IsIHVzaW5nIGFuIGludGVybmFsIGltcGxlbWVudGF0aW9uXG4gKiBpbnN0ZWFkIG9mIGNhbGxpbmcgZXhpc3RpbmcgamF2YXNjcmlwdCBmdW5jdGlvbnMuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIG1hdGNoRmFsbGJhY2tfKGVsZW1lbnQsIHNlbGVjdG9yKSB7XG5cdGNvbnN0IG5vZGVzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvciwgZWxlbWVudC5wYXJlbnROb2RlKTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7ICsraSkge1xuXHRcdGlmIChub2Rlc1tpXSA9PT0gZWxlbWVudCkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBuZXh0IHNpYmxpbmcgb2YgdGhlIGdpdmVuIGVsZW1lbnQgdGhhdCBtYXRjaGVzIHRoZSBzcGVjaWZpZWRcbiAqIHNlbGVjdG9yLCBvciBudWxsIGlmIHRoZXJlIGlzIG5vbmUuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0gez9zdHJpbmd9IHNlbGVjdG9yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXh0KGVsZW1lbnQsIHNlbGVjdG9yKSB7XG5cdGRvIHtcblx0XHRlbGVtZW50ID0gZWxlbWVudC5uZXh0U2libGluZztcblx0XHRpZiAoZWxlbWVudCAmJiBtYXRjaChlbGVtZW50LCBzZWxlY3RvcikpIHtcblx0XHRcdHJldHVybiBlbGVtZW50O1xuXHRcdH1cblx0fSB3aGlsZSAoZWxlbWVudCk7XG5cdHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIE5vcm1hbGl6ZXMgdGhlIGV2ZW50IHBheWxvYWQgZm9yIGRlbGVnYXRlIGxpc3RlbmVycy5cbiAqIEBwYXJhbSB7IUV2ZW50fSBldmVudFxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplRGVsZWdhdGVFdmVudF8oZXZlbnQpIHtcblx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uID0gc3RvcFByb3BhZ2F0aW9uXztcblx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uID0gc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uXztcbn1cblxuLyoqXG4gKiBMaXN0ZW5zIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQgb24gdGhlIGdpdmVuIERPTSBlbGVtZW50LiBUaGlzIGZ1bmN0aW9uIG5vcm1hbGl6ZXNcbiAqIERPTSBldmVudCBwYXlsb2FkcyBhbmQgZnVuY3Rpb25zIHNvIHRoZXknbGwgd29yayB0aGUgc2FtZSB3YXkgb24gYWxsIHN1cHBvcnRlZFxuICogYnJvd3NlcnMuXG4gKiBAcGFyYW0geyFFbGVtZW50fHN0cmluZ30gZWxlbWVudCBUaGUgRE9NIGVsZW1lbnQgdG8gbGlzdGVuIHRvIHRoZSBldmVudCBvbiwgb3JcbiAqICAgYSBzZWxlY3RvciB0aGF0IHNob3VsZCBiZSBkZWxlZ2F0ZWQgb24gdGhlIGVudGlyZSBkb2N1bWVudC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGxpc3RlbiB0by5cbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCFPYmplY3QpfSBjYWxsYmFjayBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXNcbiAqICAgdHJpZ2dlcmVkLiBJdCB3aWxsIHJlY2VpdmUgdGhlIG5vcm1hbGl6ZWQgZXZlbnQgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFufSBvcHRfY2FwdHVyZSBGbGFnIGluZGljYXRpbmcgaWYgbGlzdGVuZXIgc2hvdWxkIGJlIHRyaWdnZXJlZFxuICogICBkdXJpbmcgY2FwdHVyZSBwaGFzZSwgaW5zdGVhZCBvZiBkdXJpbmcgdGhlIGJ1YmJsaW5nIHBoYXNlLiBEZWZhdWx0cyB0byBmYWxzZS5cbiAqIEByZXR1cm4geyFEb21FdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uKGVsZW1lbnQsIGV2ZW50TmFtZSwgY2FsbGJhY2ssIG9wdF9jYXB0dXJlKSB7XG5cdGlmIChpc1N0cmluZyhlbGVtZW50KSkge1xuXHRcdHJldHVybiBkZWxlZ2F0ZShkb2N1bWVudCwgZXZlbnROYW1lLCBlbGVtZW50LCBjYWxsYmFjayk7XG5cdH1cblx0Y29uc3QgY3VzdG9tQ29uZmlnID0gY3VzdG9tRXZlbnRzW2V2ZW50TmFtZV07XG5cdGlmIChjdXN0b21Db25maWcgJiYgY3VzdG9tQ29uZmlnLmV2ZW50KSB7XG5cdFx0ZXZlbnROYW1lID0gY3VzdG9tQ29uZmlnLm9yaWdpbmFsRXZlbnQ7XG5cdFx0Y2FsbGJhY2sgPSBjdXN0b21Db25maWcuaGFuZGxlci5iaW5kKGN1c3RvbUNvbmZpZywgY2FsbGJhY2spO1xuXHR9XG5cdGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRfY2FwdHVyZSk7XG5cdHJldHVybiBuZXcgRG9tRXZlbnRIYW5kbGUoZWxlbWVudCwgZXZlbnROYW1lLCBjYWxsYmFjaywgb3B0X2NhcHR1cmUpO1xufVxuXG4vKipcbiAqIExpc3RlbnMgdG8gdGhlIHNwZWNpZmllZCBldmVudCBvbiB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgb25jZS4gVGhpc1xuICogZnVuY3Rpb24gbm9ybWFsaXplcyBET00gZXZlbnQgcGF5bG9hZHMgYW5kIGZ1bmN0aW9ucyBzbyB0aGV5J2xsIHdvcmsgdGhlXG4gKiBzYW1lIHdheSBvbiBhbGwgc3VwcG9ydGVkIGJyb3dzZXJzLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgRE9NIGVsZW1lbnQgdG8gbGlzdGVuIHRvIHRoZSBldmVudCBvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGxpc3RlbiB0by5cbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCFPYmplY3QpfSBjYWxsYmFjayBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnRcbiAqICAgaXMgdHJpZ2dlcmVkLiBJdCB3aWxsIHJlY2VpdmUgdGhlIG5vcm1hbGl6ZWQgZXZlbnQgb2JqZWN0LlxuICogQHJldHVybiB7IURvbUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gb25jZShlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrKSB7XG5cdGNvbnN0IGRvbUV2ZW50SGFuZGxlID0gb24oZWxlbWVudCwgZXZlbnROYW1lLCBmdW5jdGlvbigpIHtcblx0XHRkb21FdmVudEhhbmRsZS5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdHJldHVybiBjYWxsYmFjay5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXHR9KTtcblx0cmV0dXJuIGRvbUV2ZW50SGFuZGxlO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGZpcnN0IHBhcmVudCBmcm9tIHRoZSBnaXZlbiBlbGVtZW50IHRoYXQgbWF0Y2hlcyB0aGUgc3BlY2lmaWVkXG4gKiBzZWxlY3Rvciwgb3IgbnVsbCBpZiBub25lIG1hdGNoLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcmV0dXJuIHtFbGVtZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyZW50KGVsZW1lbnQsIHNlbGVjdG9yKSB7XG5cdHJldHVybiBjbG9zZXN0KGVsZW1lbnQucGFyZW50Tm9kZSwgc2VsZWN0b3IpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhIGN1c3RvbSBldmVudC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGN1c3RvbSBldmVudC5cbiAqIEBwYXJhbSB7IU9iamVjdH0gY3VzdG9tQ29uZmlnIEFuIG9iamVjdCB3aXRoIGluZm9ybWF0aW9uIGFib3V0IGhvdyB0aGUgZXZlbnRcbiAqICAgc2hvdWxkIGJlIGhhbmRsZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckN1c3RvbUV2ZW50KGV2ZW50TmFtZSwgY3VzdG9tQ29uZmlnKSB7XG5cdGN1c3RvbUV2ZW50c1tldmVudE5hbWVdID0gY3VzdG9tQ29uZmlnO1xufVxuXG4vKipcbiAqIFJlbW92ZXMgYWxsIHRoZSBjaGlsZCBub2RlcyBvbiBhIERPTSBub2RlLlxuICogQHBhcmFtIHtFbGVtZW50fSBub2RlIEVsZW1lbnQgdG8gcmVtb3ZlIGNoaWxkcmVuIGZyb20uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVDaGlsZHJlbihub2RlKSB7XG5cdGxldCBjaGlsZDtcblx0d2hpbGUgKChjaGlsZCA9IG5vZGUuZmlyc3RDaGlsZCkpIHtcblx0XHRub2RlLnJlbW92ZUNoaWxkKGNoaWxkKTtcblx0fVxufVxuXG4vKipcbiAqIFJlbW92ZXMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQuXG4gKiBAcGFyYW0geyFFbGVtZW50fCFOb2RlTGlzdH0gZWxlbWVudHMgVGhlIGVsZW1lbnQgb3IgZWxlbWVudHMgdG8gcmVtb3ZlIENTUyBjbGFzc2VzIGZyb20uXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NlcyBDU1MgY2xhc3NlcyB0byByZW1vdmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVDbGFzc2VzKGVsZW1lbnRzLCBjbGFzc2VzKSB7XG5cdGlmICghaXNPYmplY3QoZWxlbWVudHMpIHx8ICFpc1N0cmluZyhjbGFzc2VzKSkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdGlmICghZWxlbWVudHMubGVuZ3RoKSB7XG5cdFx0ZWxlbWVudHMgPSBbZWxlbWVudHNdO1xuXHR9XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdGlmICgnY2xhc3NMaXN0JyBpbiBlbGVtZW50c1tpXSkge1xuXHRcdFx0cmVtb3ZlQ2xhc3Nlc1dpdGhOYXRpdmVfKGVsZW1lbnRzW2ldLCBjbGFzc2VzKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVtb3ZlQ2xhc3Nlc1dpdGhvdXROYXRpdmVfKGVsZW1lbnRzW2ldLCBjbGFzc2VzKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBSZW1vdmVzIHRoZSByZXF1ZXN0ZWQgQ1NTIGNsYXNzZXMgZnJvbSBhbiBlbGVtZW50IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gcmVtb3ZlIENTUyBjbGFzc2VzIGZyb20uXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NlcyBDU1MgY2xhc3NlcyB0byByZW1vdmUuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiByZW1vdmVDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudCwgY2xhc3Nlcykge1xuXHRjbGFzc2VzLnNwbGl0KCcgJykuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcblx0XHRpZiAoY2xhc3NOYW1lKSB7XG5cdFx0XHRlbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoY2xhc3NOYW1lKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vKipcbiAqIFJlbW92ZXMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQgd2l0aG91dCB1c2luZyBjbGFzc0xpc3QuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHRvIHJlbW92ZSBDU1MgY2xhc3NlcyBmcm9tLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgQ1NTIGNsYXNzZXMgdG8gcmVtb3ZlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gcmVtb3ZlQ2xhc3Nlc1dpdGhvdXROYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpIHtcblx0bGV0IGVsZW1lbnRDbGFzc05hbWUgPSBgICR7ZWxlbWVudC5jbGFzc05hbWV9IGA7XG5cblx0Y2xhc3NlcyA9IGNsYXNzZXMuc3BsaXQoJyAnKTtcblxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGNsYXNzZXMubGVuZ3RoOyBpKyspIHtcblx0XHRlbGVtZW50Q2xhc3NOYW1lID0gZWxlbWVudENsYXNzTmFtZS5yZXBsYWNlKGAgJHtjbGFzc2VzW2ldfSBgLCAnICcpO1xuXHR9XG5cblx0ZWxlbWVudC5jbGFzc05hbWUgPSBlbGVtZW50Q2xhc3NOYW1lLnRyaW0oKTtcbn1cblxuLyoqXG4gKiBSZXBsYWNlcyB0aGUgZmlyc3QgZWxlbWVudCB3aXRoIHRoZSBzZWNvbmQuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQxXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXBsYWNlKGVsZW1lbnQxLCBlbGVtZW50Mikge1xuXHRpZiAoZWxlbWVudDEgJiYgZWxlbWVudDIgJiYgZWxlbWVudDEgIT09IGVsZW1lbnQyICYmIGVsZW1lbnQxLnBhcmVudE5vZGUpIHtcblx0XHRlbGVtZW50MS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShlbGVtZW50MiwgZWxlbWVudDEpO1xuXHRcdGVsZW1lbnQxLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZWxlbWVudDEpO1xuXHR9XG59XG5cbi8qKlxuICogVGhlIGZ1bmN0aW9uIHRoYXQgcmVwbGFjZXMgYHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbl9gIGZvciBldmVudHMuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb25fKCkge1xuXHRjb25zdCBldmVudCA9IHRoaXM7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0ZXZlbnQuc3RvcHBlZCA9IHRydWU7XG5cdGV2ZW50LnN0b3BwZWRJbW1lZGlhdGUgPSB0cnVlO1xuXHRFdmVudC5wcm90b3R5cGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uLmNhbGwoZXZlbnQpO1xufVxuXG4vKipcbiAqIFRoZSBmdW5jdGlvbiB0aGF0IHJlcGxhY2VzIGBzdG9wUHJvcGFnYXRpb25gIGZvciBldmVudHMuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBzdG9wUHJvcGFnYXRpb25fKCkge1xuXHRjb25zdCBldmVudCA9IHRoaXM7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0ZXZlbnQuc3RvcHBlZCA9IHRydWU7XG5cdEV2ZW50LnByb3RvdHlwZS5zdG9wUHJvcGFnYXRpb24uY2FsbChldmVudCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IHN1cHBvcnRzIHRoZSBnaXZlbiBldmVudCB0eXBlLlxuICogQHBhcmFtIHshRWxlbWVudHxzdHJpbmd9IGVsZW1lbnQgVGhlIERPTSBlbGVtZW50IG9yIGVsZW1lbnQgdGFnIG5hbWUgdG8gY2hlY2suXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBjaGVjay5cbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdXBwb3J0c0V2ZW50KGVsZW1lbnQsIGV2ZW50TmFtZSkge1xuXHRpZiAoY3VzdG9tRXZlbnRzW2V2ZW50TmFtZV0pIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdGlmIChpc1N0cmluZyhlbGVtZW50KSkge1xuXHRcdGlmICghZWxlbWVudHNCeVRhZ19bZWxlbWVudF0pIHtcblx0XHRcdGVsZW1lbnRzQnlUYWdfW2VsZW1lbnRdID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChlbGVtZW50KTtcblx0XHR9XG5cdFx0ZWxlbWVudCA9IGVsZW1lbnRzQnlUYWdfW2VsZW1lbnRdO1xuXHR9XG5cblx0Y29uc3QgdGFnID0gZWxlbWVudC50YWdOYW1lO1xuXHRpZiAoIXN1cHBvcnRDYWNoZV9bdGFnXSB8fCAhc3VwcG9ydENhY2hlX1t0YWddLmhhc093blByb3BlcnR5KGV2ZW50TmFtZSkpIHtcblx0XHRzdXBwb3J0Q2FjaGVfW3RhZ10gPSBzdXBwb3J0Q2FjaGVfW3RhZ10gfHwge307XG5cdFx0c3VwcG9ydENhY2hlX1t0YWddW2V2ZW50TmFtZV0gPSAnb24nICsgZXZlbnROYW1lIGluIGVsZW1lbnQ7XG5cdH1cblx0cmV0dXJuIHN1cHBvcnRDYWNoZV9bdGFnXVtldmVudE5hbWVdO1xufVxuXG4vKipcbiAqIFRoaXMgdHJpZ2dlcnMgYWxsIGRlZmF1bHQgbWF0Y2hlZCBkZWxlZ2F0ZWQgbGlzdGVuZXJzIG9mIGEgZ2l2ZW4gZXZlbnQgdHlwZS5cbiAqIEBwYXJhbSB7IUFycmF5fSBkZWZhdWx0Rm5zIEFycmF5IHRvIGNvbGxlY3QgZGVmYXVsdCBsaXN0ZW5lcnMgaW4sIGluc3RlYWRcbiAqIEBwYXJhbSB7IUV2ZW50fSBldmVudFxuICogQHJldHVybiB7Ym9vbGVhbn0gRmFsc2UgaWYgYXQgbGVhc3Qgb25lIG9mIHRoZSB0cmlnZ2VyZWQgY2FsbGJhY2tzIHJldHVybnNcbiAqICAgICBmYWxzZSwgb3IgdHJ1ZSBvdGhlcndpc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0cmlnZ2VyRGVmYXVsdERlbGVnYXRlZExpc3RlbmVyc18oZGVmRm5zLCBldmVudCkge1xuXHRsZXQgcmV0ID0gdHJ1ZTtcblxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGRlZkZucy5sZW5ndGggJiYgIWV2ZW50LmRlZmF1bHRQcmV2ZW50ZWQ7IGkrKykge1xuXHRcdGV2ZW50LmRlbGVnYXRlVGFyZ2V0ID0gZGVmRm5zW2ldLmVsZW1lbnQ7XG5cdFx0cmV0ICY9IGRlZkZuc1tpXS5mbihldmVudCk7XG5cdH1cblxuXHRyZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIFRoaXMgdHJpZ2dlcnMgYWxsIG1hdGNoZWQgZGVsZWdhdGVkIGxpc3RlbmVycyBvZiBhIGdpdmVuIGV2ZW50IHR5cGUgd2hlbiBpdHNcbiAqIGRlbGVnYXRlZCB0YXJnZXQgaXMgYWJsZSB0byBpbnRlcmFjdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGNvbnRhaW5lclxuICogQHBhcmFtIHshRXZlbnR9IGV2ZW50XG4gKiBAcGFyYW0geyFBcnJheX0gZGVmYXVsdEZucyBBcnJheSB0byBjb2xsZWN0IGRlZmF1bHQgbGlzdGVuZXJzIGluLCBpbnN0ZWFkXG4gKiAgICAgb2YgcnVubmluZyB0aGVtLlxuICogQHJldHVybiB7Ym9vbGVhbn0gRmFsc2UgaWYgYXQgbGVhc3Qgb25lIG9mIHRoZSB0cmlnZ2VyZWQgY2FsbGJhY2tzIHJldHVybnNcbiAqICAgICBmYWxzZSwgb3IgdHJ1ZSBvdGhlcndpc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0cmlnZ2VyRGVsZWdhdGVkTGlzdGVuZXJzXyhjb250YWluZXIsIGV2ZW50LCBkZWZhdWx0Rm5zKSB7XG5cdGxldCByZXQgPSB0cnVlO1xuXHRsZXQgY3VyckVsZW1lbnQgPSBldmVudC50YXJnZXQ7XG5cdGNvbnN0IGxpbWl0ID0gY29udGFpbmVyLnBhcmVudE5vZGU7XG5cblx0d2hpbGUgKGN1cnJFbGVtZW50ICYmIGN1cnJFbGVtZW50ICE9PSBsaW1pdCAmJiAhZXZlbnQuc3RvcHBlZCkge1xuXHRcdGlmIChpc0FibGVUb0ludGVyYWN0V2l0aF8oY3VyckVsZW1lbnQsIGV2ZW50LnR5cGUsIGV2ZW50KSkge1xuXHRcdFx0ZXZlbnQuZGVsZWdhdGVUYXJnZXQgPSBjdXJyRWxlbWVudDtcblx0XHRcdHJldCAmPSB0cmlnZ2VyRWxlbWVudExpc3RlbmVyc18oY3VyckVsZW1lbnQsIGV2ZW50LCBkZWZhdWx0Rm5zKTtcblx0XHRcdHJldCAmPSB0cmlnZ2VyU2VsZWN0b3JMaXN0ZW5lcnNfKGNvbnRhaW5lciwgY3VyckVsZW1lbnQsIGV2ZW50LCBkZWZhdWx0Rm5zKTtcblx0XHR9XG5cdFx0Y3VyckVsZW1lbnQgPSBjdXJyRWxlbWVudC5wYXJlbnROb2RlO1xuXHR9XG5cblx0cmV0dXJuIHJldDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gYXJndW1lbnQgdG8gYSBET00gZWxlbWVudC4gU3RyaW5ncyBhcmUgYXNzdW1lZCB0b1xuICogYmUgc2VsZWN0b3JzLCBhbmQgc28gYSBtYXRjaGVkIGVsZW1lbnQgd2lsbCBiZSByZXR1cm5lZC4gSWYgdGhlIGFyZ1xuICogaXMgYWxyZWFkeSBhIERPTSBlbGVtZW50IGl0IHdpbGwgYmUgdGhlIHJldHVybiB2YWx1ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfEVsZW1lbnR8RG9jdW1lbnR9IHNlbGVjdG9yT3JFbGVtZW50XG4gKiBAcmV0dXJuIHtFbGVtZW50fSBUaGUgY29udmVydGVkIGVsZW1lbnQsIG9yIG51bGwgaWYgbm9uZSB3YXMgZm91bmQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0VsZW1lbnQoc2VsZWN0b3JPckVsZW1lbnQpIHtcblx0aWYgKGlzRWxlbWVudChzZWxlY3Rvck9yRWxlbWVudCkgfHwgaXNEb2N1bWVudChzZWxlY3Rvck9yRWxlbWVudCkgfHwgaXNEb2N1bWVudEZyYWdtZW50KHNlbGVjdG9yT3JFbGVtZW50KSkge1xuXHRcdHJldHVybiBzZWxlY3Rvck9yRWxlbWVudDtcblx0fSBlbHNlIGlmIChpc1N0cmluZyhzZWxlY3Rvck9yRWxlbWVudCkpIHtcblx0XHRpZiAoc2VsZWN0b3JPckVsZW1lbnRbMF0gPT09ICcjJyAmJiBzZWxlY3Rvck9yRWxlbWVudC5pbmRleE9mKCcgJykgPT09IC0xKSB7XG5cdFx0XHRyZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoc2VsZWN0b3JPckVsZW1lbnQuc3Vic3RyKDEpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3JPckVsZW1lbnQpO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gbnVsbDtcblx0fVxufVxuXG4vKipcbiAqIEFkZHMgb3IgcmVtb3ZlcyBvbmUgb3IgbW9yZSBjbGFzc2VzIGZyb20gYW4gZWxlbWVudC4gSWYgYW55IG9mIHRoZSBjbGFzc2VzXG4gKiBpcyBwcmVzZW50LCBpdCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZWxlbWVudCwgb3IgYWRkZWQgb3RoZXJ3aXNlLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB3aGljaCBjbGFzc2VzIHdpbGwgYmUgdG9nZ2xlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIFRoZSBjbGFzc2VzIHdoaWNoIGhhdmUgdG8gYWRkZWQgb3IgcmVtb3ZlZCBmcm9tIHRoZSBlbGVtZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9nZ2xlQ2xhc3NlcyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGlmICghaXNPYmplY3QoZWxlbWVudCkgfHwgIWlzU3RyaW5nKGNsYXNzZXMpKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0aWYgKCdjbGFzc0xpc3QnIGluIGVsZW1lbnQpIHtcblx0XHR0b2dnbGVDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudCwgY2xhc3Nlcyk7XG5cdH0gZWxzZSB7XG5cdFx0dG9nZ2xlQ2xhc3Nlc1dpdGhvdXROYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpO1xuXHR9XG59XG5cbi8qKlxuICogQWRkcyBvciByZW1vdmVzIG9uZSBvciBtb3JlIGNsYXNzZXMgZnJvbSBhbiBlbGVtZW50IHVzaW5nIGNsYXNzTGlzdC5cbiAqIElmIGFueSBvZiB0aGUgY2xhc3NlcyBpcyBwcmVzZW50LCBpdCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZWxlbWVudCxcbiAqIG9yIGFkZGVkIG90aGVyd2lzZS5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgd2hpY2ggY2xhc3NlcyB3aWxsIGJlIHRvZ2dsZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NlcyBUaGUgY2xhc3NlcyB3aGljaCBoYXZlIHRvIGFkZGVkIG9yIHJlbW92ZWQgZnJvbSB0aGUgZWxlbWVudC5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHRvZ2dsZUNsYXNzZXNXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGNsYXNzZXMuc3BsaXQoJyAnKS5mb3JFYWNoKGZ1bmN0aW9uKGNsYXNzTmFtZSkge1xuXHRcdGVsZW1lbnQuY2xhc3NMaXN0LnRvZ2dsZShjbGFzc05hbWUpO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBBZGRzIG9yIHJlbW92ZXMgb25lIG9yIG1vcmUgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQgd2l0aG91dCB1c2luZyBjbGFzc0xpc3QuXG4gKiBJZiBhbnkgb2YgdGhlIGNsYXNzZXMgaXMgcHJlc2VudCwgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQsXG4gKiBvciBhZGRlZCBvdGhlcndpc2UuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHdoaWNoIGNsYXNzZXMgd2lsbCBiZSB0b2dnbGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgVGhlIGNsYXNzZXMgd2hpY2ggaGF2ZSB0byBhZGRlZCBvciByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0b2dnbGVDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudCwgY2xhc3Nlcykge1xuXHRsZXQgZWxlbWVudENsYXNzTmFtZSA9IGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYDtcblxuXHRjbGFzc2VzID0gY2xhc3Nlcy5zcGxpdCgnICcpO1xuXG5cdGZvciAobGV0IGkgPSAwOyBpIDwgY2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuXHRcdGNvbnN0IGNsYXNzTmFtZSA9IGAgJHtjbGFzc2VzW2ldfSBgO1xuXHRcdGNvbnN0IGNsYXNzSW5kZXggPSBlbGVtZW50Q2xhc3NOYW1lLmluZGV4T2YoY2xhc3NOYW1lKTtcblxuXHRcdGlmIChjbGFzc0luZGV4ID09PSAtMSkge1xuXHRcdFx0ZWxlbWVudENsYXNzTmFtZSA9IGAke2VsZW1lbnRDbGFzc05hbWV9JHtjbGFzc2VzW2ldfSBgO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zdCBiZWZvcmUgPSBlbGVtZW50Q2xhc3NOYW1lLnN1YnN0cmluZygwLCBjbGFzc0luZGV4KTtcblx0XHRcdGNvbnN0IGFmdGVyID0gZWxlbWVudENsYXNzTmFtZS5zdWJzdHJpbmcoY2xhc3NJbmRleCArIGNsYXNzTmFtZS5sZW5ndGgpO1xuXHRcdFx0ZWxlbWVudENsYXNzTmFtZSA9IGAke2JlZm9yZX0gJHthZnRlcn1gO1xuXHRcdH1cblx0fVxuXG5cdGVsZW1lbnQuY2xhc3NOYW1lID0gZWxlbWVudENsYXNzTmFtZS50cmltKCk7XG59XG5cbi8qKlxuICogVHJpZ2dlcnMgYWxsIGxpc3RlbmVycyBmb3IgdGhlIGdpdmVuIGV2ZW50IHR5cGUgdGhhdCBhcmUgc3RvcmVkIGluIHRoZVxuICogc3BlY2lmaWVkIGVsZW1lbnQuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnRcbiAqIEBwYXJhbSB7IUFycmF5fSBkZWZhdWx0Rm5zIEFycmF5IHRvIGNvbGxlY3QgZGVmYXVsdCBsaXN0ZW5lcnMgaW4sIGluc3RlYWRcbiAqICAgICBvZiBydW5uaW5nIHRoZW0uXG4gKiBAcmV0dXJuIHtib29sZWFufSBGYWxzZSBpZiBhdCBsZWFzdCBvbmUgb2YgdGhlIHRyaWdnZXJlZCBjYWxsYmFja3MgcmV0dXJuc1xuICogICAgIGZhbHNlLCBvciB0cnVlIG90aGVyd2lzZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHRyaWdnZXJFbGVtZW50TGlzdGVuZXJzXyhlbGVtZW50LCBldmVudCwgZGVmYXVsdEZucykge1xuXHRjb25zdCBsYXN0Q29udGFpbmVyID0gZXZlbnRbTEFTVF9DT05UQUlORVJdO1xuXHRpZiAoIWlzRGVmKGxhc3RDb250YWluZXIpIHx8ICFjb250YWlucyhsYXN0Q29udGFpbmVyLCBlbGVtZW50KSkge1xuXHRcdGNvbnN0IGxpc3RlbmVycyA9IGRvbURhdGEuZ2V0KGVsZW1lbnQsICdsaXN0ZW5lcnMnLCB7fSlbZXZlbnQudHlwZV07XG5cdFx0cmV0dXJuIHRyaWdnZXJMaXN0ZW5lcnNfKGxpc3RlbmVycywgZXZlbnQsIGVsZW1lbnQsIGRlZmF1bHRGbnMpO1xuXHR9XG5cdHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIFRyaWdnZXJzIHRoZSBzcGVjaWZpZWQgZXZlbnQgb24gdGhlIGdpdmVuIGVsZW1lbnQuXG4gKiBOT1RFOiBUaGlzIHNob3VsZCBtb3N0bHkgYmUgdXNlZCBmb3IgdGVzdGluZywgbm90IG9uIHJlYWwgY29kZS5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIG5vZGUgdGhhdCBzaG91bGQgdHJpZ2dlciB0aGUgZXZlbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBiZSB0cmlnZ3JlZC5cbiAqIEBwYXJhbSB7T2JqZWN0PX0gb3B0X2V2ZW50T2JqIEFuIG9iamVjdCB3aXRoIGRhdGEgdGhhdCBzaG91bGQgYmUgb24gdGhlXG4gKiAgIHRyaWdnZXJlZCBldmVudCdzIHBheWxvYWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmlnZ2VyRXZlbnQoZWxlbWVudCwgZXZlbnROYW1lLCBvcHRfZXZlbnRPYmopIHtcblx0aWYgKGlzQWJsZVRvSW50ZXJhY3RXaXRoXyhlbGVtZW50LCBldmVudE5hbWUsIG9wdF9ldmVudE9iaikpIHtcblx0XHRjb25zdCBldmVudE9iaiA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdIVE1MRXZlbnRzJyk7XG5cdFx0ZXZlbnRPYmouaW5pdEV2ZW50KGV2ZW50TmFtZSwgdHJ1ZSwgdHJ1ZSk7XG5cdFx0b2JqZWN0Lm1peGluKGV2ZW50T2JqLCBvcHRfZXZlbnRPYmopO1xuXHRcdGVsZW1lbnQuZGlzcGF0Y2hFdmVudChldmVudE9iaik7XG5cdH1cbn1cblxuLyoqXG4gKiBUcmlnZ2VycyB0aGUgZ2l2ZW4gbGlzdGVuZXJzIGFycmF5LlxuICogQHBhcmFtIHtBcnJheTwhZnVuY3Rpb24oKT59IGxpc3RlbmVyc1xuICogQHBhcmFtIHshRXZlbnR9IGV2ZW50XG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0geyFBcnJheX0gZGVmYXVsdEZucyBBcnJheSB0byBjb2xsZWN0IGRlZmF1bHQgbGlzdGVuZXJzIGluLCBpbnN0ZWFkXG4gKiAgICAgb2YgcnVubmluZyB0aGVtLlxuICogQHJldHVybiB7Ym9vbGVhbn0gRmFsc2UgaWYgYXQgbGVhc3Qgb25lIG9mIHRoZSB0cmlnZ2VyZWQgY2FsbGJhY2tzIHJldHVybnNcbiAqICAgICBmYWxzZSwgb3IgdHJ1ZSBvdGhlcndpc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiB0cmlnZ2VyTGlzdGVuZXJzXyhsaXN0ZW5lcnMsIGV2ZW50LCBlbGVtZW50LCBkZWZhdWx0Rm5zKSB7XG5cdGxldCByZXQgPSB0cnVlO1xuXHRsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMgfHwgW107XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aCAmJiAhZXZlbnQuc3RvcHBlZEltbWVkaWF0ZTsgaSsrKSB7XG5cdFx0aWYgKGxpc3RlbmVyc1tpXS5kZWZhdWx0TGlzdGVuZXJfKSB7XG5cdFx0XHRkZWZhdWx0Rm5zLnB1c2goe1xuXHRcdFx0XHRlbGVtZW50LFxuXHRcdFx0XHRmbjogbGlzdGVuZXJzW2ldXG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0ICY9IGxpc3RlbmVyc1tpXShldmVudCk7XG5cdFx0fVxuXHR9XG5cdHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogVHJpZ2dlcnMgYWxsIHNlbGVjdG9yIGxpc3RlbmVycyBmb3IgdGhlIGdpdmVuIGV2ZW50LlxuICogQHBhcmFtIHshRWxlbWVudH0gY29udGFpbmVyXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnRcbiAqIEBwYXJhbSB7IUFycmF5fSBkZWZhdWx0Rm5zIEFycmF5IHRvIGNvbGxlY3QgZGVmYXVsdCBsaXN0ZW5lcnMgaW4sIGluc3RlYWRcbiAqICAgICBvZiBydW5uaW5nIHRoZW0uXG4gKiBAcmV0dXJuIHtib29sZWFufSBGYWxzZSBpZiBhdCBsZWFzdCBvbmUgb2YgdGhlIHRyaWdnZXJlZCBjYWxsYmFja3MgcmV0dXJuc1xuICogICAgIGZhbHNlLCBvciB0cnVlIG90aGVyd2lzZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHRyaWdnZXJTZWxlY3Rvckxpc3RlbmVyc18oY29udGFpbmVyLCBlbGVtZW50LCBldmVudCwgZGVmYXVsdEZucykge1xuXHRsZXQgcmV0ID0gdHJ1ZTtcblx0Y29uc3QgZGF0YSA9IGRvbURhdGEuZ2V0KGNvbnRhaW5lciwgJ2RlbGVnYXRpbmcnLCB7fSk7XG5cdGNvbnN0IG1hcCA9IGRhdGFbZXZlbnQudHlwZV0uc2VsZWN0b3JzO1xuXHRjb25zdCBzZWxlY3RvcnMgPSBPYmplY3Qua2V5cyhtYXApO1xuXHRmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdG9ycy5sZW5ndGggJiYgIWV2ZW50LnN0b3BwZWRJbW1lZGlhdGU7IGkrKykge1xuXHRcdGlmIChtYXRjaChlbGVtZW50LCBzZWxlY3RvcnNbaV0pKSB7XG5cdFx0XHRjb25zdCBsaXN0ZW5lcnMgPSBtYXBbc2VsZWN0b3JzW2ldXTtcblx0XHRcdHJldCAmPSB0cmlnZ2VyTGlzdGVuZXJzXyhsaXN0ZW5lcnMsIGV2ZW50LCBlbGVtZW50LCBkZWZhdWx0Rm5zKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHJldDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxuLy8gVGhpcyBmaWxlIGV4aXN0cyBqdXN0IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgbWFraW5nIHN1cmUgdGhhdCBvbGRcbi8vIGRlZmF1bHQgaW1wb3J0cyBmb3IgdGhpcyBmaWxlIHN0aWxsIHdvcmsuIEl0J3MgYmVzdCB0byB1c2UgdGhlIG5hbWVkIGV4cG9ydHNcbi8vIGZvciBlYWNoIGZ1bmN0aW9uIGluc3RlYWQgdGhvdWdoLCBzaW5jZSB0aGF0IGFsbG93cyBidW5kbGVycyBsaWtlIFJvbGx1cCB0b1xuLy8gcmVkdWNlIHRoZSBidW5kbGUgc2l6ZSBieSByZW1vdmluZyB1bnVzZWQgY29kZS5cbmltcG9ydCAqIGFzIGRvbSBmcm9tICcuL2RvbU5hbWVkJztcblxuZXhwb3J0IGRlZmF1bHQgZG9tO1xuZXhwb3J0IHsgZG9tIH07XG5leHBvcnQgKiBmcm9tICcuL2RvbU5hbWVkJztcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgZGVsZWdhdGUsIG9uLCBzdXBwb3J0c0V2ZW50IH0gZnJvbSAnLi9kb20nO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyUHJveHkgfSBmcm9tICdtZXRhbC1ldmVudHMnO1xuXG4vKipcbiAqIERvbUV2ZW50RW1pdHRlclByb3h5IHV0aWxpdHkuIEl0IGV4dGVuZHMgYEV2ZW50RW1pdHRlclByb3h5YCB0byBhbHNvIGFjY2VwdFxuICogZG9tIGVsZW1lbnRzIGFzIG9yaWdpbiBlbWl0dGVycy5cbiAqIEBleHRlbmRzIHtFdmVudEVtaXR0ZXJQcm94eX1cbiAqL1xuY2xhc3MgRG9tRXZlbnRFbWl0dGVyUHJveHkgZXh0ZW5kcyBFdmVudEVtaXR0ZXJQcm94eSB7XG5cdC8qKlxuXHQgKiBBZGRzIHRoZSBnaXZlbiBsaXN0ZW5lciBmb3IgdGhlIGdpdmVuIGV2ZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKX0gbGlzdGVuZXJcblx0ICogQHJldHVybiB7IUV2ZW50SGFuZGxlfSBUaGUgbGlzdGVuZWQgZXZlbnQncyBoYW5kbGUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRhZGRMaXN0ZW5lcl8oZXZlbnQsIGxpc3RlbmVyKSB7XG5cdFx0aWYgKHRoaXMub3JpZ2luRW1pdHRlcl8uYWRkRXZlbnRMaXN0ZW5lcikge1xuXHRcdFx0aWYgKHRoaXMuaXNEZWxlZ2F0ZUV2ZW50XyhldmVudCkpIHtcblx0XHRcdFx0Y29uc3QgaW5kZXggPSBldmVudC5pbmRleE9mKCc6JywgOSk7XG5cdFx0XHRcdGNvbnN0IGV2ZW50TmFtZSA9IGV2ZW50LnN1YnN0cmluZyg5LCBpbmRleCk7XG5cdFx0XHRcdGNvbnN0IHNlbGVjdG9yID0gZXZlbnQuc3Vic3RyaW5nKGluZGV4ICsgMSk7XG5cdFx0XHRcdHJldHVybiBkZWxlZ2F0ZSh0aGlzLm9yaWdpbkVtaXR0ZXJfLCBldmVudE5hbWUsIHNlbGVjdG9yLCBsaXN0ZW5lcik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gb24odGhpcy5vcmlnaW5FbWl0dGVyXywgZXZlbnQsIGxpc3RlbmVyKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIHN1cGVyLmFkZExpc3RlbmVyXyhldmVudCwgbGlzdGVuZXIpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGV2ZW50IGlzIG9mIHRoZSBkZWxlZ2F0ZSB0eXBlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0aXNEZWxlZ2F0ZUV2ZW50XyhldmVudCkge1xuXHRcdHJldHVybiBldmVudC5zdWJzdHIoMCwgOSkgPT09ICdkZWxlZ2F0ZTonO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZXZlbnQgaXMgc3VwcG9ydGVkIGJ5IHRoZSBvcmlnaW4gZWxlbWVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGlzU3VwcG9ydGVkRG9tRXZlbnRfKGV2ZW50KSB7XG5cdFx0aWYgKCF0aGlzLm9yaWdpbkVtaXR0ZXJfIHx8ICF0aGlzLm9yaWdpbkVtaXR0ZXJfLmFkZEV2ZW50TGlzdGVuZXIpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gKHRoaXMuaXNEZWxlZ2F0ZUV2ZW50XyhldmVudCkgJiYgZXZlbnQuaW5kZXhPZignOicsIDkpICE9PSAtMSkgfHxcblx0XHRcdHN1cHBvcnRzRXZlbnQodGhpcy5vcmlnaW5FbWl0dGVyXywgZXZlbnQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZXZlbnQgc2hvdWxkIGJlIHByb3hpZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0c2hvdWxkUHJveHlFdmVudF8oZXZlbnQpIHtcblx0XHRyZXR1cm4gc3VwZXIuc2hvdWxkUHJveHlFdmVudF8oZXZlbnQpICYmIHRoaXMuaXNTdXBwb3J0ZWREb21FdmVudF8oZXZlbnQpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERvbUV2ZW50RW1pdHRlclByb3h5O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBhcHBlbmQgfSBmcm9tICcuL2RvbSc7XG5pbXBvcnQgeyBzdHJpbmcgfSBmcm9tICdtZXRhbCc7XG5cbi8qKlxuICogQ2xhc3Mgd2l0aCBzdGF0aWMgbWV0aG9kcyByZXNwb25zaWJsZSBmb3IgZG9pbmcgYnJvd3NlciBmZWF0dXJlIGNoZWNrcy5cbiAqL1xuY2xhc3MgZmVhdHVyZXMge1xuXHQvKipcblx0ICogU29tZSBicm93c2VycyBzdGlsbCBzdXBwb3J0cyBwcmVmaXhlZCBhbmltYXRpb24gZXZlbnRzLiBUaGlzIG1ldGhvZCBjYW5cblx0ICogYmUgdXNlZCB0byByZXRyaWV2ZSB0aGUgY3VycmVudCBicm93c2VyIGV2ZW50IG5hbWUgZm9yIGJvdGgsIGFuaW1hdGlvblxuXHQgKiBhbmQgdHJhbnNpdGlvbi5cblx0ICogQHJldHVybiB7b2JqZWN0fVxuXHQgKi9cblx0c3RhdGljIGNoZWNrQW5pbWF0aW9uRXZlbnROYW1lKCkge1xuXHRcdGlmIChmZWF0dXJlcy5hbmltYXRpb25FdmVudE5hbWVfID09PSB1bmRlZmluZWQpIHtcblx0XHRcdGZlYXR1cmVzLmFuaW1hdGlvbkV2ZW50TmFtZV8gPSB7XG5cdFx0XHRcdGFuaW1hdGlvbjogZmVhdHVyZXMuY2hlY2tBbmltYXRpb25FdmVudE5hbWVfKCdhbmltYXRpb24nKSxcblx0XHRcdFx0dHJhbnNpdGlvbjogZmVhdHVyZXMuY2hlY2tBbmltYXRpb25FdmVudE5hbWVfKCd0cmFuc2l0aW9uJylcblx0XHRcdH07XG5cdFx0fVxuXHRcdHJldHVybiBmZWF0dXJlcy5hbmltYXRpb25FdmVudE5hbWVfO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgVHlwZSB0byB0ZXN0OiBhbmltYXRpb24sIHRyYW5zaXRpb24uXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gQnJvd3NlciBldmVudCBuYW1lLlxuXHQgKi9cblx0c3RhdGljIGNoZWNrQW5pbWF0aW9uRXZlbnROYW1lXyh0eXBlKSB7XG5cdFx0Y29uc3QgcHJlZml4ZXMgPSBbJ1dlYmtpdCcsICdNUycsICdPJywgJyddO1xuXHRcdGNvbnN0IHR5cGVUaXRsZUNhc2UgPSBzdHJpbmcucmVwbGFjZUludGVydmFsKHR5cGUsIDAsIDEsIHR5cGUuc3Vic3RyaW5nKDAsIDEpLnRvVXBwZXJDYXNlKCkpO1xuXHRcdGNvbnN0IHN1ZmZpeGVzID0gW2Ake3R5cGVUaXRsZUNhc2V9RW5kYCwgYCR7dHlwZVRpdGxlQ2FzZX1FbmRgLCBgJHt0eXBlVGl0bGVDYXNlfUVuZGAsIGAke3R5cGV9ZW5kYF07XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBwcmVmaXhlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGZlYXR1cmVzLmFuaW1hdGlvbkVsZW1lbnRfLnN0eWxlW3ByZWZpeGVzW2ldICsgdHlwZVRpdGxlQ2FzZV0gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRyZXR1cm4gcHJlZml4ZXNbaV0udG9Mb3dlckNhc2UoKSArIHN1ZmZpeGVzW2ldO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gYCR7dHlwZX1lbmRgO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNvbWUgYnJvd3NlcnMgKGxpa2UgSUU5KSBjaGFuZ2UgdGhlIG9yZGVyIG9mIGVsZW1lbnQgYXR0cmlidXRlcywgd2hlbiBodG1sXG5cdCAqIGlzIHJlbmRlcmVkLiBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiB0aGlzIGJlaGF2aW9yIGhhcHBlbnMgb25cblx0ICogdGhlIGN1cnJlbnQgYnJvd3Nlci5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdHN0YXRpYyBjaGVja0F0dHJPcmRlckNoYW5nZSgpIHtcblx0XHRpZiAoZmVhdHVyZXMuYXR0ck9yZGVyQ2hhbmdlXyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRjb25zdCBvcmlnaW5hbENvbnRlbnQgPSAnPGRpdiBkYXRhLWNvbXBvbmVudD1cIlwiIGRhdGEtcmVmPVwiXCI+PC9kaXY+Jztcblx0XHRcdGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblx0XHRcdGFwcGVuZChlbGVtZW50LCBvcmlnaW5hbENvbnRlbnQpO1xuXHRcdFx0ZmVhdHVyZXMuYXR0ck9yZGVyQ2hhbmdlXyA9IG9yaWdpbmFsQ29udGVudCAhPT0gZWxlbWVudC5pbm5lckhUTUw7XG5cdFx0fVxuXHRcdHJldHVybiBmZWF0dXJlcy5hdHRyT3JkZXJDaGFuZ2VfO1xuXHR9XG59XG5cbmZlYXR1cmVzLmFuaW1hdGlvbkVsZW1lbnRfID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5mZWF0dXJlcy5hbmltYXRpb25FdmVudE5hbWVfID0gdW5kZWZpbmVkO1xuZmVhdHVyZXMuYXR0ck9yZGVyQ2hhbmdlXyA9IHVuZGVmaW5lZDtcblxuZXhwb3J0IGRlZmF1bHQgZmVhdHVyZXM7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGFzeW5jIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgZXhpdERvY3VtZW50LCBvbmNlIH0gZnJvbSAnLi9kb20nO1xuXG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb25zIGZvciBydW5uaW5nIGphdmFzY3JpcHQgY29kZSBpbiB0aGUgZ2xvYmFsIHNjb3BlLlxuICovXG5jbGFzcyBnbG9iYWxFdmFsIHtcblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0aGUgZ2l2ZW4gc3RyaW5nIGluIHRoZSBnbG9iYWwgc2NvcGUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9hcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKiBAcmV0dXJuIHtFbGVtZW50fSBzY3JpcHRcblx0ICovXG5cdHN0YXRpYyBydW4odGV4dCwgb3B0X2FwcGVuZEZuKSB7XG5cdFx0Y29uc3Qgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG5cdFx0c2NyaXB0LnRleHQgPSB0ZXh0O1xuXHRcdGlmIChvcHRfYXBwZW5kRm4pIHtcblx0XHRcdG9wdF9hcHBlbmRGbihzY3JpcHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG5cdFx0fVxuXHRcdGV4aXREb2N1bWVudChzY3JpcHQpO1xuXHRcdHJldHVybiBzY3JpcHQ7XG5cdH1cblxuXHQvKipcblx0ICogRXZhbHVhdGVzIHRoZSBnaXZlbiBqYXZhc2NyaXB0IGZpbGUgaW4gdGhlIGdsb2JhbCBzY29wZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHNyYyBUaGUgZmlsZSdzIHBhdGguXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9jYWxsYmFjayBPcHRpb25hbCBmdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICogICB3aGVuIHRoZSBzY3JpcHQgaGFzIGJlZW4gcnVuLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBvcHRfYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc2NyaXB0XG5cdCAqL1xuXHRzdGF0aWMgcnVuRmlsZShzcmMsIG9wdF9jYWxsYmFjaywgb3B0X2FwcGVuZEZuKSB7XG5cdFx0Y29uc3Qgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG5cdFx0c2NyaXB0LnNyYyA9IHNyYztcblxuXHRcdGNvbnN0IGNhbGxiYWNrID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRleGl0RG9jdW1lbnQoc2NyaXB0KTtcblx0XHRcdG9wdF9jYWxsYmFjayAmJiBvcHRfY2FsbGJhY2soKTtcblx0XHR9O1xuXHRcdG9uY2Uoc2NyaXB0LCAnbG9hZCcsIGNhbGxiYWNrKTtcblx0XHRvbmNlKHNjcmlwdCwgJ2Vycm9yJywgY2FsbGJhY2spO1xuXG5cdFx0aWYgKG9wdF9hcHBlbmRGbikge1xuXHRcdFx0b3B0X2FwcGVuZEZuKHNjcmlwdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gc2NyaXB0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0aGUgY29kZSByZWZlcmVuY2VkIGJ5IHRoZSBnaXZlbiBzY3JpcHQgZWxlbWVudC5cblx0ICogQHBhcmFtIHshRWxlbWVudH0gc2NyaXB0XG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9jYWxsYmFjayBPcHRpb25hbCBmdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICogICB3aGVuIHRoZSBzY3JpcHQgaGFzIGJlZW4gcnVuLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBvcHRfYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc2NyaXB0XG5cdCAqL1xuXHRzdGF0aWMgcnVuU2NyaXB0KHNjcmlwdCwgb3B0X2NhbGxiYWNrLCBvcHRfYXBwZW5kRm4pIHtcblx0XHRjb25zdCBjYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0b3B0X2NhbGxiYWNrICYmIG9wdF9jYWxsYmFjaygpO1xuXHRcdH07XG5cdFx0aWYgKHNjcmlwdC50eXBlICYmIHNjcmlwdC50eXBlICE9PSAndGV4dC9qYXZhc2NyaXB0Jykge1xuXHRcdFx0YXN5bmMubmV4dFRpY2soY2FsbGJhY2spO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRleGl0RG9jdW1lbnQoc2NyaXB0KTtcblx0XHRpZiAoc2NyaXB0LnNyYykge1xuXHRcdFx0cmV0dXJuIGdsb2JhbEV2YWwucnVuRmlsZShzY3JpcHQuc3JjLCBvcHRfY2FsbGJhY2ssIG9wdF9hcHBlbmRGbik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFzeW5jLm5leHRUaWNrKGNhbGxiYWNrKTtcblx0XHRcdHJldHVybiBnbG9iYWxFdmFsLnJ1bihzY3JpcHQudGV4dCwgb3B0X2FwcGVuZEZuKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogRXZhbHVhdGVzIGFueSBzY3JpcHQgdGFncyBwcmVzZW50IGluIHRoZSBnaXZlbiBlbGVtZW50LlxuXHQgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9jYWxsYmFjayBPcHRpb25hbCBmdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICogICB3aGVuIHRoZSBzY3JpcHQgaGFzIGJlZW4gcnVuLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBvcHRfYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICovXG5cdHN0YXRpYyBydW5TY3JpcHRzSW5FbGVtZW50KGVsZW1lbnQsIG9wdF9jYWxsYmFjaywgb3B0X2FwcGVuZEZuKSB7XG5cdFx0Y29uc3Qgc2NyaXB0cyA9IGVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnc2NyaXB0Jyk7XG5cdFx0aWYgKHNjcmlwdHMubGVuZ3RoKSB7XG5cdFx0XHRnbG9iYWxFdmFsLnJ1blNjcmlwdHNJbk9yZGVyKHNjcmlwdHMsIDAsIG9wdF9jYWxsYmFjaywgb3B0X2FwcGVuZEZuKTtcblx0XHR9IGVsc2UgaWYgKG9wdF9jYWxsYmFjaykge1xuXHRcdFx0YXN5bmMubmV4dFRpY2sob3B0X2NhbGxiYWNrKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUnVucyB0aGUgZ2l2ZW4gc2NyaXB0cyBlbGVtZW50cyBpbiB0aGUgb3JkZXIgdGhhdCB0aGV5IGFwcGVhci5cblx0ICogQHBhcmFtIHshTm9kZUxpc3R9IHNjcmlwdHNcblx0ICogQHBhcmFtIHtudW1iZXJ9IGluZGV4XG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9jYWxsYmFjayBPcHRpb25hbCBmdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICogICB3aGVuIHRoZSBzY3JpcHQgaGFzIGJlZW4gcnVuLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBvcHRfYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICovXG5cdHN0YXRpYyBydW5TY3JpcHRzSW5PcmRlcihzY3JpcHRzLCBpbmRleCwgb3B0X2NhbGxiYWNrLCBvcHRfYXBwZW5kRm4pIHtcblx0XHRnbG9iYWxFdmFsLnJ1blNjcmlwdChzY3JpcHRzLml0ZW0oaW5kZXgpLCBmdW5jdGlvbigpIHtcblx0XHRcdGlmIChpbmRleCA8IHNjcmlwdHMubGVuZ3RoIC0gMSkge1xuXHRcdFx0XHRnbG9iYWxFdmFsLnJ1blNjcmlwdHNJbk9yZGVyKHNjcmlwdHMsIGluZGV4ICsgMSwgb3B0X2NhbGxiYWNrLCBvcHRfYXBwZW5kRm4pO1xuXHRcdFx0fSBlbHNlIGlmIChvcHRfY2FsbGJhY2spIHtcblx0XHRcdFx0YXN5bmMubmV4dFRpY2sob3B0X2NhbGxiYWNrKTtcblx0XHRcdH1cblx0XHR9LCBvcHRfYXBwZW5kRm4pO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGdsb2JhbEV2YWw7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGFzeW5jIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgb25jZSB9IGZyb20gJy4vZG9tJztcblxuLyoqXG4gKiBVdGlsaXR5IGZ1bmN0aW9ucyBmb3IgcnVubmluZyBzdHlsZXMuXG4gKi9cbmNsYXNzIGdsb2JhbEV2YWxTdHlsZXMge1xuXHQvKipcblx0ICogRXZhbHVhdGVzIHRoZSBnaXZlbiBzdHlsZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHRleHRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2FwcGVuZEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGFwcGVuZCB0aGUgbm9kZVxuXHQgKiAgIGludG8gZG9jdW1lbnQuXG5cdCAqIEByZXR1cm4ge0VsZW1lbnR9IHN0eWxlXG5cdCAqL1xuXHRzdGF0aWMgcnVuKHRleHQsIG9wdF9hcHBlbmRGbikge1xuXHRcdGNvbnN0IHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcblx0XHRzdHlsZS5pbm5lckhUTUwgPSB0ZXh0O1xuXHRcdGlmIChvcHRfYXBwZW5kRm4pIHtcblx0XHRcdG9wdF9hcHBlbmRGbihzdHlsZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGUpO1xuXHRcdH1cblx0XHRyZXR1cm4gc3R5bGU7XG5cdH1cblxuXHQvKipcblx0ICogRXZhbHVhdGVzIHRoZSBnaXZlbiBzdHlsZSBmaWxlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaHJlZiBUaGUgZmlsZSdzIHBhdGguXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9jYWxsYmFjayBPcHRpb25hbCBmdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICogICB3aGVuIHRoZSBzdHlsZXMgaGFzIGJlZW4gcnVuLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBvcHRfYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc3R5bGVcblx0ICovXG5cdHN0YXRpYyBydW5GaWxlKGhyZWYsIG9wdF9jYWxsYmFjaywgb3B0X2FwcGVuZEZuKSB7XG5cdFx0Y29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKTtcblx0XHRsaW5rLnJlbCA9ICdzdHlsZXNoZWV0Jztcblx0XHRsaW5rLmhyZWYgPSBocmVmO1xuXHRcdGdsb2JhbEV2YWxTdHlsZXMucnVuU3R5bGUobGluaywgb3B0X2NhbGxiYWNrLCBvcHRfYXBwZW5kRm4pO1xuXHRcdHJldHVybiBsaW5rO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0aGUgY29kZSByZWZlcmVuY2VkIGJ5IHRoZSBnaXZlbiBzdHlsZS9saW5rIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IHN0eWxlXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9jYWxsYmFjayBPcHRpb25hbCBmdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICogICB3aGVuIHRoZSBzY3JpcHQgaGFzIGJlZW4gcnVuLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBvcHRfYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogIEByZXR1cm4ge0VsZW1lbnR9IHN0eWxlXG5cdCAqL1xuXHRzdGF0aWMgcnVuU3R5bGUoc3R5bGUsIG9wdF9jYWxsYmFjaywgb3B0X2FwcGVuZEZuKSB7XG5cdFx0Y29uc3QgY2FsbGJhY2sgPSBmdW5jdGlvbigpIHtcblx0XHRcdG9wdF9jYWxsYmFjayAmJiBvcHRfY2FsbGJhY2soKTtcblx0XHR9O1xuXHRcdGlmIChzdHlsZS5yZWwgJiYgc3R5bGUucmVsICE9PSAnc3R5bGVzaGVldCcpIHtcblx0XHRcdGFzeW5jLm5leHRUaWNrKGNhbGxiYWNrKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoc3R5bGUudGFnTmFtZSA9PT0gJ1NUWUxFJykge1xuXHRcdFx0YXN5bmMubmV4dFRpY2soY2FsbGJhY2spO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRvbmNlKHN0eWxlLCAnbG9hZCcsIGNhbGxiYWNrKTtcblx0XHRcdG9uY2Uoc3R5bGUsICdlcnJvcicsIGNhbGxiYWNrKTtcblx0XHR9XG5cblx0XHRpZiAob3B0X2FwcGVuZEZuKSB7XG5cdFx0XHRvcHRfYXBwZW5kRm4oc3R5bGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHN0eWxlKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gc3R5bGU7XG5cdH1cblxuXHQvKipcblx0ICogRXZhbHVhdGVzIGFueSBzdHlsZSBwcmVzZW50IGluIHRoZSBnaXZlbiBlbGVtZW50LlxuXHQgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9jYWxsYmFjayBPcHRpb25hbCBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGVcblx0ICogICBzdHlsZSBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9hcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKi9cblx0c3RhdGljIHJ1blN0eWxlc0luRWxlbWVudChlbGVtZW50LCBvcHRfY2FsbGJhY2ssIG9wdF9hcHBlbmRGbikge1xuXHRcdGNvbnN0IHN0eWxlcyA9IGVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnc3R5bGUsbGluaycpO1xuXHRcdGlmIChzdHlsZXMubGVuZ3RoID09PSAwICYmIG9wdF9jYWxsYmFjaykge1xuXHRcdFx0YXN5bmMubmV4dFRpY2sob3B0X2NhbGxiYWNrKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRsZXQgbG9hZENvdW50ID0gMDtcblx0XHRjb25zdCBjYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKG9wdF9jYWxsYmFjayAmJiArK2xvYWRDb3VudCA9PT0gc3R5bGVzLmxlbmd0aCkge1xuXHRcdFx0XHRhc3luYy5uZXh0VGljayhvcHRfY2FsbGJhY2spO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzdHlsZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGdsb2JhbEV2YWxTdHlsZXMucnVuU3R5bGUoc3R5bGVzW2ldLCBjYWxsYmFjaywgb3B0X2FwcGVuZEZuKTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgZ2xvYmFsRXZhbFN0eWxlcztcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgcmVnaXN0ZXJDdXN0b21FdmVudCwgY29udGFpbnMgfSBmcm9tICcuL2RvbSc7XG5pbXBvcnQgZmVhdHVyZXMgZnJvbSAnLi9mZWF0dXJlcyc7XG5cbmNvbnN0IG1vdXNlRXZlbnRNYXAgPSB7XG5cdG1vdXNlZW50ZXI6ICdtb3VzZW92ZXInLFxuXHRtb3VzZWxlYXZlOiAnbW91c2VvdXQnLFxuXHRwb2ludGVyZW50ZXI6ICdwb2ludGVyb3ZlcicsXG5cdHBvaW50ZXJsZWF2ZTogJ3BvaW50ZXJvdXQnXG59O1xuT2JqZWN0LmtleXMobW91c2VFdmVudE1hcCkuZm9yRWFjaChmdW5jdGlvbihldmVudE5hbWUpIHtcblx0cmVnaXN0ZXJDdXN0b21FdmVudChldmVudE5hbWUsIHtcblx0XHRkZWxlZ2F0ZTogdHJ1ZSxcblx0XHRoYW5kbGVyOiBmdW5jdGlvbihjYWxsYmFjaywgZXZlbnQpIHtcblx0XHRcdGNvbnN0IHJlbGF0ZWQgPSBldmVudC5yZWxhdGVkVGFyZ2V0O1xuXHRcdFx0Y29uc3QgdGFyZ2V0ID0gZXZlbnQuZGVsZWdhdGVUYXJnZXQ7XG5cdFx0XHRpZiAoIXJlbGF0ZWQgfHwgKHJlbGF0ZWQgIT09IHRhcmdldCAmJiAhY29udGFpbnModGFyZ2V0LCByZWxhdGVkKSkpIHtcblx0XHRcdFx0ZXZlbnQuY3VzdG9tVHlwZSA9IGV2ZW50TmFtZTtcblx0XHRcdFx0cmV0dXJuIGNhbGxiYWNrKGV2ZW50KTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdG9yaWdpbmFsRXZlbnQ6IG1vdXNlRXZlbnRNYXBbZXZlbnROYW1lXVxuXHR9KTtcbn0pO1xuXG5jb25zdCBhbmltYXRpb25FdmVudE1hcCA9IHtcblx0YW5pbWF0aW9uOiAnYW5pbWF0aW9uZW5kJyxcblx0dHJhbnNpdGlvbjogJ3RyYW5zaXRpb25lbmQnXG59O1xuT2JqZWN0LmtleXMoYW5pbWF0aW9uRXZlbnRNYXApLmZvckVhY2goZnVuY3Rpb24oZXZlbnRUeXBlKSB7XG5cdGNvbnN0IGV2ZW50TmFtZSA9IGFuaW1hdGlvbkV2ZW50TWFwW2V2ZW50VHlwZV07XG5cdHJlZ2lzdGVyQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCB7XG5cdFx0ZXZlbnQ6IHRydWUsXG5cdFx0ZGVsZWdhdGU6IHRydWUsXG5cdFx0aGFuZGxlcjogZnVuY3Rpb24oY2FsbGJhY2ssIGV2ZW50KSB7XG5cdFx0XHRldmVudC5jdXN0b21UeXBlID0gZXZlbnROYW1lO1xuXHRcdFx0cmV0dXJuIGNhbGxiYWNrKGV2ZW50KTtcblx0XHR9LFxuXHRcdG9yaWdpbmFsRXZlbnQ6IGZlYXR1cmVzLmNoZWNrQW5pbWF0aW9uRXZlbnROYW1lKClbZXZlbnRUeXBlXVxuXHR9KTtcbn0pO1xuIiwiLyohXG4gKiBQcm9taXNlcyBwb2x5ZmlsbCBmcm9tIEdvb2dsZSdzIENsb3N1cmUgTGlicmFyeS5cbiAqXG4gKiAgICAgIENvcHlyaWdodCAyMDEzIFRoZSBDbG9zdXJlIExpYnJhcnkgQXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBOT1RFKGVkdWFyZG8pOiBQcm9taXNlIHN1cHBvcnQgaXMgbm90IHJlYWR5IG9uIGFsbCBzdXBwb3J0ZWQgYnJvd3NlcnMsXG4gKiB0aGVyZWZvcmUgbWV0YWwtcHJvbWlzZSBpcyB0ZW1wb3JhcmlseSB1c2luZyBHb29nbGUncyBwcm9taXNlcyBhcyBwb2x5ZmlsbC5cbiAqIEl0IHN1cHBvcnRzIGNhbmNlbGxhYmxlIHByb21pc2VzIGFuZCBoYXMgY2xlYW4gYW5kIGZhc3QgaW1wbGVtZW50YXRpb24uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBpc0RlZiwgaXNGdW5jdGlvbiwgaXNPYmplY3QgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBhc3luYyB9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBQcm92aWRlcyBhIG1vcmUgc3RyaWN0IGludGVyZmFjZSBmb3IgVGhlbmFibGVzIGluIHRlcm1zIG9mXG4gKiBodHRwOi8vcHJvbWlzZXNhcGx1cy5jb20gZm9yIGludGVyb3Agd2l0aCB7QHNlZSBDYW5jZWxsYWJsZVByb21pc2V9LlxuICpcbiAqIEBpbnRlcmZhY2VcbiAqIEBleHRlbmRzIHtJVGhlbmFibGUuPFRZUEU+fVxuICogQHRlbXBsYXRlIFRZUEVcbiAqL1xudmFyIFRoZW5hYmxlID0gZnVuY3Rpb24oKSB7fTtcblxuLyoqXG4gKiBBZGRzIGNhbGxiYWNrcyB0aGF0IHdpbGwgb3BlcmF0ZSBvbiB0aGUgcmVzdWx0IG9mIHRoZSBUaGVuYWJsZSwgcmV0dXJuaW5nIGFcbiAqIG5ldyBjaGlsZCBQcm9taXNlLlxuICpcbiAqIElmIHRoZSBUaGVuYWJsZSBpcyBmdWxmaWxsZWQsIHRoZSB7QGNvZGUgb25GdWxmaWxsZWR9IGNhbGxiYWNrIHdpbGwgYmVcbiAqIGludm9rZWQgd2l0aCB0aGUgZnVsZmlsbG1lbnQgdmFsdWUgYXMgYXJndW1lbnQsIGFuZCB0aGUgY2hpbGQgUHJvbWlzZSB3aWxsXG4gKiBiZSBmdWxmaWxsZWQgd2l0aCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBjYWxsYmFjay4gSWYgdGhlIGNhbGxiYWNrIHRocm93c1xuICogYW4gZXhjZXB0aW9uLCB0aGUgY2hpbGQgUHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkIHdpdGggdGhlIHRocm93biB2YWx1ZVxuICogaW5zdGVhZC5cbiAqXG4gKiBJZiB0aGUgVGhlbmFibGUgaXMgcmVqZWN0ZWQsIHRoZSB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2sgd2lsbCBiZSBpbnZva2VkXG4gKiB3aXRoIHRoZSByZWplY3Rpb24gcmVhc29uIGFzIGFyZ3VtZW50LCBhbmQgdGhlIGNoaWxkIFByb21pc2Ugd2lsbCBiZSByZWplY3RlZFxuICogd2l0aCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBjYWxsYmFjayBvciB0aHJvd24gdmFsdWUuXG4gKlxuICogQHBhcmFtIHs/KGZ1bmN0aW9uKHRoaXM6VEhJUywgVFlQRSk6XG4gKiAgICAgICAgICAgICAoUkVTVUxUfElUaGVuYWJsZS48UkVTVUxUPnxUaGVuYWJsZSkpPX0gb3B0X29uRnVsZmlsbGVkIEFcbiAqICAgICBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgaW52b2tlZCB3aXRoIHRoZSBmdWxmaWxsbWVudCB2YWx1ZSBpZiB0aGUgUHJvbWlzZVxuICogICAgIGlzIGZ1bGxmaWxsZWQuXG4gKiBAcGFyYW0gez8oZnVuY3Rpb24oKik6ICopPX0gb3B0X29uUmVqZWN0ZWQgQSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgaW52b2tlZFxuICogICAgIHdpdGggdGhlIHJlamVjdGlvbiByZWFzb24gaWYgdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQuXG4gKiBAcGFyYW0ge1RISVM9fSBvcHRfY29udGV4dCBBbiBvcHRpb25hbCBjb250ZXh0IG9iamVjdCB0aGF0IHdpbGwgYmUgdGhlXG4gKiAgICAgZXhlY3V0aW9uIGNvbnRleHQgZm9yIHRoZSBjYWxsYmFja3MuIEJ5IGRlZmF1bHQsIGZ1bmN0aW9ucyBhcmUgZXhlY3V0ZWRcbiAqICAgICB3aXRoIHRoZSBkZWZhdWx0IHRoaXMuXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlLjxSRVNVTFQ+fSBBIG5ldyBQcm9taXNlIHRoYXQgd2lsbCByZWNlaXZlIHRoZVxuICogICAgIHJlc3VsdCBvZiB0aGUgZnVsZmlsbG1lbnQgb3IgcmVqZWN0aW9uIGNhbGxiYWNrLlxuICogQHRlbXBsYXRlIFJFU1VMVCxUSElTXG4gKi9cblRoZW5hYmxlLnByb3RvdHlwZS50aGVuID0gZnVuY3Rpb24oKSB7fTtcblxuXG4vKipcbiAqIEFuIGV4cGFuZG8gcHJvcGVydHkgdG8gaW5kaWNhdGUgdGhhdCBhbiBvYmplY3QgaW1wbGVtZW50c1xuICoge0Bjb2RlIFRoZW5hYmxlfS5cbiAqXG4gKiB7QHNlZSBhZGRJbXBsZW1lbnRhdGlvbn0uXG4gKlxuICogQGNvbnN0XG4gKi9cblRoZW5hYmxlLklNUExFTUVOVEVEX0JZX1BST1AgPSAnJGdvb2dfVGhlbmFibGUnO1xuXG5cbi8qKlxuICogTWFya3MgYSBnaXZlbiBjbGFzcyAoY29uc3RydWN0b3IpIGFzIGFuIGltcGxlbWVudGF0aW9uIG9mIFRoZW5hYmxlLCBzb1xuICogdGhhdCB3ZSBjYW4gcXVlcnkgdGhhdCBmYWN0IGF0IHJ1bnRpbWUuIFRoZSBjbGFzcyBtdXN0IGhhdmUgYWxyZWFkeVxuICogaW1wbGVtZW50ZWQgdGhlIGludGVyZmFjZS5cbiAqIEV4cG9ydHMgYSAndGhlbicgbWV0aG9kIG9uIHRoZSBjb25zdHJ1Y3RvciBwcm90b3R5cGUsIHNvIHRoYXQgdGhlIG9iamVjdHNcbiAqIGFsc28gaW1wbGVtZW50IHRoZSBleHRlcm4ge0BzZWUgVGhlbmFibGV9IGludGVyZmFjZSBmb3IgaW50ZXJvcCB3aXRoXG4gKiBvdGhlciBQcm9taXNlIGltcGxlbWVudGF0aW9ucy5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24obmV3OlRoZW5hYmxlLC4uLls/XSl9IGN0b3IgVGhlIGNsYXNzIGNvbnN0cnVjdG9yLiBUaGVcbiAqICAgICBjb3JyZXNwb25kaW5nIGNsYXNzIG11c3QgaGF2ZSBhbHJlYWR5IGltcGxlbWVudGVkIHRoZSBpbnRlcmZhY2UuXG4gKi9cblRoZW5hYmxlLmFkZEltcGxlbWVudGF0aW9uID0gZnVuY3Rpb24oY3Rvcikge1xuICBjdG9yLnByb3RvdHlwZS50aGVuID0gY3Rvci5wcm90b3R5cGUudGhlbjtcbiAgY3Rvci5wcm90b3R5cGUuJGdvb2dfVGhlbmFibGUgPSB0cnVlO1xufTtcblxuXG4vKipcbiAqIEBwYXJhbSB7Kn0gb2JqZWN0XG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIGEgZ2l2ZW4gaW5zdGFuY2UgaW1wbGVtZW50cyB7QGNvZGUgVGhlbmFibGV9LlxuICogICAgIFRoZSBjbGFzcy9zdXBlcmNsYXNzIG9mIHRoZSBpbnN0YW5jZSBtdXN0IGNhbGwge0Bjb2RlIGFkZEltcGxlbWVudGF0aW9ufS5cbiAqL1xuVGhlbmFibGUuaXNJbXBsZW1lbnRlZEJ5ID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gIGlmICghb2JqZWN0KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHRyeSB7XG4gICAgcmV0dXJuICEhb2JqZWN0LiRnb29nX1RoZW5hYmxlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgLy8gUHJvcGVydHkgYWNjZXNzIHNlZW1zIHRvIGJlIGZvcmJpZGRlbi5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBMaWtlIGJpbmQoKSwgZXhjZXB0IHRoYXQgYSAndGhpcyBvYmplY3QnIGlzIG5vdCByZXF1aXJlZC4gVXNlZnVsIHdoZW4gdGhlXG4gKiB0YXJnZXQgZnVuY3Rpb24gaXMgYWxyZWFkeSBib3VuZC5cbiAqXG4gKiBVc2FnZTpcbiAqIHZhciBnID0gcGFydGlhbChmLCBhcmcxLCBhcmcyKTtcbiAqIGcoYXJnMywgYXJnNCk7XG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gQSBmdW5jdGlvbiB0byBwYXJ0aWFsbHkgYXBwbHkuXG4gKiBAcGFyYW0gey4uLip9IHZhcl9hcmdzIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRoYXQgYXJlIHBhcnRpYWxseSBhcHBsaWVkIHRvIGZuLlxuICogQHJldHVybiB7IUZ1bmN0aW9ufSBBIHBhcnRpYWxseS1hcHBsaWVkIGZvcm0gb2YgdGhlIGZ1bmN0aW9uIGJpbmQoKSB3YXNcbiAqICAgICBpbnZva2VkIGFzIGEgbWV0aG9kIG9mLlxuICovXG52YXIgcGFydGlhbCA9IGZ1bmN0aW9uKGZuKSB7XG4gIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIC8vIENsb25lIHRoZSBhcnJheSAod2l0aCBzbGljZSgpKSBhbmQgYXBwZW5kIGFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAgLy8gdG8gdGhlIGV4aXN0aW5nIGFyZ3VtZW50cy5cbiAgICB2YXIgbmV3QXJncyA9IGFyZ3Muc2xpY2UoKTtcbiAgICBuZXdBcmdzLnB1c2guYXBwbHkobmV3QXJncywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgbmV3QXJncyk7XG4gIH07XG59O1xuXG4vKipcbiAqIFByb21pc2VzIHByb3ZpZGUgYSByZXN1bHQgdGhhdCBtYXkgYmUgcmVzb2x2ZWQgYXN5bmNocm9ub3VzbHkuIEEgUHJvbWlzZSBtYXlcbiAqIGJlIHJlc29sdmVkIGJ5IGJlaW5nIGZ1bGZpbGxlZCBvciByZWplY3RlZCB3aXRoIGEgdmFsdWUsIHdoaWNoIHdpbGwgYmUga25vd25cbiAqIGFzIHRoZSBmdWxmaWxsbWVudCB2YWx1ZSBvciB0aGUgcmVqZWN0aW9uIHJlYXNvbi4gV2hldGhlciBmdWxmaWxsZWQgb3JcbiAqIHJlamVjdGVkLCB0aGUgUHJvbWlzZSByZXN1bHQgaXMgaW1tdXRhYmxlIG9uY2UgaXQgaXMgc2V0LlxuICpcbiAqIFByb21pc2VzIG1heSByZXByZXNlbnQgcmVzdWx0cyBvZiBhbnkgdHlwZSwgaW5jbHVkaW5nIHVuZGVmaW5lZC4gUmVqZWN0aW9uXG4gKiByZWFzb25zIGFyZSB0eXBpY2FsbHkgRXJyb3JzLCBidXQgbWF5IGFsc28gYmUgb2YgYW55IHR5cGUuIENsb3N1cmUgUHJvbWlzZXNcbiAqIGFsbG93IGZvciBvcHRpb25hbCB0eXBlIGFubm90YXRpb25zIHRoYXQgZW5mb3JjZSB0aGF0IGZ1bGZpbGxtZW50IHZhbHVlcyBhcmVcbiAqIG9mIHRoZSBhcHByb3ByaWF0ZSB0eXBlcyBhdCBjb21waWxlIHRpbWUuXG4gKlxuICogVGhlIHJlc3VsdCBvZiBhIFByb21pc2UgaXMgYWNjZXNzaWJsZSBieSBjYWxsaW5nIHtAY29kZSB0aGVufSBhbmQgcmVnaXN0ZXJpbmdcbiAqIHtAY29kZSBvbkZ1bGZpbGxlZH0gYW5kIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFja3MuIE9uY2UgdGhlIFByb21pc2VcbiAqIHJlc29sdmVzLCB0aGUgcmVsZXZhbnQgY2FsbGJhY2tzIGFyZSBpbnZva2VkIHdpdGggdGhlIGZ1bGZpbGxtZW50IHZhbHVlIG9yXG4gKiByZWplY3Rpb24gcmVhc29uIGFzIGFyZ3VtZW50LiBDYWxsYmFja3MgYXJlIGFsd2F5cyBpbnZva2VkIGluIHRoZSBvcmRlciB0aGV5XG4gKiB3ZXJlIHJlZ2lzdGVyZWQsIGV2ZW4gd2hlbiBhZGRpdGlvbmFsIHtAY29kZSB0aGVufSBjYWxscyBhcmUgbWFkZSBmcm9tIGluc2lkZVxuICogYW5vdGhlciBjYWxsYmFjay4gQSBjYWxsYmFjayBpcyBhbHdheXMgcnVuIGFzeW5jaHJvbm91c2x5IHNvbWV0aW1lIGFmdGVyIHRoZVxuICogc2NvcGUgY29udGFpbmluZyB0aGUgcmVnaXN0ZXJpbmcge0Bjb2RlIHRoZW59IGludm9jYXRpb24gaGFzIHJldHVybmVkLlxuICpcbiAqIElmIGEgUHJvbWlzZSBpcyByZXNvbHZlZCB3aXRoIGFub3RoZXIgUHJvbWlzZSwgdGhlIGZpcnN0IFByb21pc2Ugd2lsbCBibG9ja1xuICogdW50aWwgdGhlIHNlY29uZCBpcyByZXNvbHZlZCwgYW5kIHRoZW4gYXNzdW1lcyB0aGUgc2FtZSByZXN1bHQgYXMgdGhlIHNlY29uZFxuICogUHJvbWlzZS4gVGhpcyBhbGxvd3MgUHJvbWlzZXMgdG8gZGVwZW5kIG9uIHRoZSByZXN1bHRzIG9mIG90aGVyIFByb21pc2VzLFxuICogbGlua2luZyB0b2dldGhlciBtdWx0aXBsZSBhc3luY2hyb25vdXMgb3BlcmF0aW9ucy5cbiAqXG4gKiBUaGlzIGltcGxlbWVudGF0aW9uIGlzIGNvbXBhdGlibGUgd2l0aCB0aGUgUHJvbWlzZXMvQSsgc3BlY2lmaWNhdGlvbiBhbmRcbiAqIHBhc3NlcyB0aGF0IHNwZWNpZmljYXRpb24ncyBjb25mb3JtYW5jZSB0ZXN0IHN1aXRlLiBBIENsb3N1cmUgUHJvbWlzZSBtYXkgYmVcbiAqIHJlc29sdmVkIHdpdGggYSBQcm9taXNlIGluc3RhbmNlIChvciBzdWZmaWNpZW50bHkgY29tcGF0aWJsZSBQcm9taXNlLWxpa2VcbiAqIG9iamVjdCkgY3JlYXRlZCBieSBvdGhlciBQcm9taXNlIGltcGxlbWVudGF0aW9ucy4gRnJvbSB0aGUgc3BlY2lmaWNhdGlvbixcbiAqIFByb21pc2UtbGlrZSBvYmplY3RzIGFyZSBrbm93biBhcyBcIlRoZW5hYmxlc1wiLlxuICpcbiAqIEBzZWUgaHR0cDovL3Byb21pc2VzYXBsdXMuY29tL1xuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb24oXG4gKiAgICAgICAgICAgICB0aGlzOlJFU09MVkVSX0NPTlRFWFQsXG4gKiAgICAgICAgICAgICBmdW5jdGlvbigoVFlQRXxJVGhlbmFibGUuPFRZUEU+fFRoZW5hYmxlKSksXG4gKiAgICAgICAgICAgICBmdW5jdGlvbigqKSk6IHZvaWR9IHJlc29sdmVyXG4gKiAgICAgSW5pdGlhbGl6YXRpb24gZnVuY3Rpb24gdGhhdCBpcyBpbnZva2VkIGltbWVkaWF0ZWx5IHdpdGgge0Bjb2RlIHJlc29sdmV9XG4gKiAgICAgYW5kIHtAY29kZSByZWplY3R9IGZ1bmN0aW9ucyBhcyBhcmd1bWVudHMuIFRoZSBQcm9taXNlIGlzIHJlc29sdmVkIG9yXG4gKiAgICAgcmVqZWN0ZWQgd2l0aCB0aGUgZmlyc3QgYXJndW1lbnQgcGFzc2VkIHRvIGVpdGhlciBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7UkVTT0xWRVJfQ09OVEVYVD19IG9wdF9jb250ZXh0IEFuIG9wdGlvbmFsIGNvbnRleHQgZm9yIGV4ZWN1dGluZyB0aGVcbiAqICAgICByZXNvbHZlciBmdW5jdGlvbi4gSWYgdW5zcGVjaWZpZWQsIHRoZSByZXNvbHZlciBmdW5jdGlvbiB3aWxsIGJlIGV4ZWN1dGVkXG4gKiAgICAgaW4gdGhlIGRlZmF1bHQgc2NvcGUuXG4gKiBAY29uc3RydWN0b3JcbiAqIEBzdHJ1Y3RcbiAqIEBmaW5hbFxuICogQGltcGxlbWVudHMge1RoZW5hYmxlLjxUWVBFPn1cbiAqIEB0ZW1wbGF0ZSBUWVBFLFJFU09MVkVSX0NPTlRFWFRcbiAqL1xudmFyIENhbmNlbGxhYmxlUHJvbWlzZSA9IGZ1bmN0aW9uKHJlc29sdmVyLCBvcHRfY29udGV4dCkge1xuICAvKipcbiAgICogVGhlIGludGVybmFsIHN0YXRlIG9mIHRoaXMgUHJvbWlzZS4gRWl0aGVyIFBFTkRJTkcsIEZVTEZJTExFRCwgUkVKRUNURUQsIG9yXG4gICAqIEJMT0NLRUQuXG4gICAqIEBwcml2YXRlIHtDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVffVxuICAgKi9cbiAgdGhpcy5zdGF0ZV8gPSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkc7XG5cbiAgLyoqXG4gICAqIFRoZSByZXNvbHZlZCByZXN1bHQgb2YgdGhlIFByb21pc2UuIEltbXV0YWJsZSBvbmNlIHNldCB3aXRoIGVpdGhlciBhXG4gICAqIGZ1bGZpbGxtZW50IHZhbHVlIG9yIHJlamVjdGlvbiByZWFzb24uXG4gICAqIEBwcml2YXRlIHsqfVxuICAgKi9cbiAgdGhpcy5yZXN1bHRfID0gdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBGb3IgUHJvbWlzZXMgY3JlYXRlZCBieSBjYWxsaW5nIHtAY29kZSB0aGVuKCl9LCB0aGUgb3JpZ2luYXRpbmcgcGFyZW50LlxuICAgKiBAcHJpdmF0ZSB7Q2FuY2VsbGFibGVQcm9taXNlfVxuICAgKi9cbiAgdGhpcy5wYXJlbnRfID0gbnVsbDtcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2Yge0Bjb2RlIG9uRnVsZmlsbGVkfSBhbmQge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrcyBhZGRlZCB0b1xuICAgKiB0aGlzIFByb21pc2UgYnkgY2FsbHMgdG8ge0Bjb2RlIHRoZW4oKX0uXG4gICAqIEBwcml2YXRlIHtBcnJheS48Q2FuY2VsbGFibGVQcm9taXNlLkNhbGxiYWNrRW50cnlfPn1cbiAgICovXG4gIHRoaXMuY2FsbGJhY2tFbnRyaWVzXyA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIFByb21pc2UgaXMgaW4gdGhlIHF1ZXVlIG9mIFByb21pc2VzIHRvIGV4ZWN1dGUuXG4gICAqIEBwcml2YXRlIHtib29sZWFufVxuICAgKi9cbiAgdGhpcy5leGVjdXRpbmdfID0gZmFsc2U7XG5cbiAgaWYgKENhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZID4gMCkge1xuICAgIC8qKlxuICAgICAqIEEgdGltZW91dCBJRCB1c2VkIHdoZW4gdGhlIHtAY29kZSBVTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZfSBpcyBncmVhdGVyXG4gICAgICogdGhhbiAwIG1pbGxpc2Vjb25kcy4gVGhlIElEIGlzIHNldCB3aGVuIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLCBhbmRcbiAgICAgKiBjbGVhcmVkIG9ubHkgaWYgYW4ge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrIGlzIGludm9rZWQgZm9yIHRoZVxuICAgICAqIFByb21pc2UgKG9yIG9uZSBvZiBpdHMgZGVzY2VuZGFudHMpIGJlZm9yZSB0aGUgZGVsYXkgaXMgZXhjZWVkZWQuXG4gICAgICpcbiAgICAgKiBJZiB0aGUgcmVqZWN0aW9uIGlzIG5vdCBoYW5kbGVkIGJlZm9yZSB0aGUgdGltZW91dCBjb21wbGV0ZXMsIHRoZVxuICAgICAqIHJlamVjdGlvbiByZWFzb24gaXMgcGFzc2VkIHRvIHRoZSB1bmhhbmRsZWQgcmVqZWN0aW9uIGhhbmRsZXIuXG4gICAgICogQHByaXZhdGUge251bWJlcn1cbiAgICAgKi9cbiAgICB0aGlzLnVuaGFuZGxlZFJlamVjdGlvbklkXyA9IDA7XG4gIH0gZWxzZSBpZiAoQ2FuY2VsbGFibGVQcm9taXNlLlVOSEFORExFRF9SRUpFQ1RJT05fREVMQVkgPT09IDApIHtcbiAgICAvKipcbiAgICAgKiBXaGVuIHRoZSB7QGNvZGUgVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWX0gaXMgc2V0IHRvIDAgbWlsbGlzZWNvbmRzLCBhXG4gICAgICogYm9vbGVhbiB0aGF0IGlzIHNldCBpZiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZCwgYW5kIHJlc2V0IHRvIGZhbHNlIGlmIGFuXG4gICAgICoge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrIGlzIGludm9rZWQgZm9yIHRoZSBQcm9taXNlIChvciBvbmUgb2YgaXRzXG4gICAgICogZGVzY2VuZGFudHMpLiBJZiB0aGUgcmVqZWN0aW9uIGlzIG5vdCBoYW5kbGVkIGJlZm9yZSB0aGUgbmV4dCB0aW1lc3RlcCxcbiAgICAgKiB0aGUgcmVqZWN0aW9uIHJlYXNvbiBpcyBwYXNzZWQgdG8gdGhlIHVuaGFuZGxlZCByZWplY3Rpb24gaGFuZGxlci5cbiAgICAgKiBAcHJpdmF0ZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICB0aGlzLmhhZFVuaGFuZGxlZFJlamVjdGlvbl8gPSBmYWxzZTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHJlc29sdmVyLmNhbGwoXG4gICAgICBvcHRfY29udGV4dCwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgc2VsZi5yZXNvbHZlXyhDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkZVTEZJTExFRCwgdmFsdWUpO1xuICAgICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7XG4gICAgICAgIHNlbGYucmVzb2x2ZV8oQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCwgcmVhc29uKTtcbiAgICAgIH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhpcy5yZXNvbHZlXyhDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVELCBlKTtcbiAgfVxufTtcblxuLyoqXG4gKiBUaGUgZGVsYXkgaW4gbWlsbGlzZWNvbmRzIGJlZm9yZSBhIHJlamVjdGVkIFByb21pc2UncyByZWFzb24gaXMgcGFzc2VkIHRvXG4gKiB0aGUgcmVqZWN0aW9uIGhhbmRsZXIuIEJ5IGRlZmF1bHQsIHRoZSByZWplY3Rpb24gaGFuZGxlciByZXRocm93cyB0aGVcbiAqIHJlamVjdGlvbiByZWFzb24gc28gdGhhdCBpdCBhcHBlYXJzIGluIHRoZSBkZXZlbG9wZXIgY29uc29sZSBvclxuICoge0Bjb2RlIHdpbmRvdy5vbmVycm9yfSBoYW5kbGVyLlxuICogUmVqZWN0aW9ucyBhcmUgcmV0aHJvd24gYXMgcXVpY2tseSBhcyBwb3NzaWJsZSBieSBkZWZhdWx0LiBBIG5lZ2F0aXZlIHZhbHVlXG4gKiBkaXNhYmxlcyByZWplY3Rpb24gaGFuZGxpbmcgZW50aXJlbHkuXG4gKiBAdHlwZSB7bnVtYmVyfVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA9IDA7XG5cblxuLyoqXG4gKiBUaGUgcG9zc2libGUgaW50ZXJuYWwgc3RhdGVzIGZvciBhIFByb21pc2UuIFRoZXNlIHN0YXRlcyBhcmUgbm90IGRpcmVjdGx5XG4gKiBvYnNlcnZhYmxlIHRvIGV4dGVybmFsIGNhbGxlcnMuXG4gKiBAZW51bSB7bnVtYmVyfVxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXyA9IHtcbiAgLyoqIFRoZSBQcm9taXNlIGlzIHdhaXRpbmcgZm9yIHJlc29sdXRpb24uICovXG4gIFBFTkRJTkc6IDAsXG5cbiAgLyoqIFRoZSBQcm9taXNlIGlzIGJsb2NrZWQgd2FpdGluZyBmb3IgdGhlIHJlc3VsdCBvZiBhbm90aGVyIFRoZW5hYmxlLiAqL1xuICBCTE9DS0VEOiAxLFxuXG4gIC8qKiBUaGUgUHJvbWlzZSBoYXMgYmVlbiByZXNvbHZlZCB3aXRoIGEgZnVsZmlsbG1lbnQgdmFsdWUuICovXG4gIEZVTEZJTExFRDogMixcblxuICAvKiogVGhlIFByb21pc2UgaGFzIGJlZW4gcmVzb2x2ZWQgd2l0aCBhIHJlamVjdGlvbiByZWFzb24uICovXG4gIFJFSkVDVEVEOiAzXG59O1xuXG5cbi8qKlxuICogVHlwZWRlZiBmb3IgZW50cmllcyBpbiB0aGUgY2FsbGJhY2sgY2hhaW4uIEVhY2ggY2FsbCB0byB7QGNvZGUgdGhlbn0sXG4gKiB7QGNvZGUgdGhlbkNhdGNofSwgb3Ige0Bjb2RlIHRoZW5BbHdheXN9IGNyZWF0ZXMgYW4gZW50cnkgY29udGFpbmluZyB0aGVcbiAqIGZ1bmN0aW9ucyB0aGF0IG1heSBiZSBpbnZva2VkIG9uY2UgdGhlIFByb21pc2UgaXMgcmVzb2x2ZWQuXG4gKlxuICogQHR5cGVkZWYge3tcbiAqICAgY2hpbGQ6IENhbmNlbGxhYmxlUHJvbWlzZSxcbiAqICAgb25GdWxmaWxsZWQ6IGZ1bmN0aW9uKCopLFxuICogICBvblJlamVjdGVkOiBmdW5jdGlvbigqKVxuICogfX1cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5DYWxsYmFja0VudHJ5XyA9IG51bGw7XG5cblxuLyoqXG4gKiBAcGFyYW0geyhUWVBFfFRoZW5hYmxlLjxUWVBFPnxUaGVuYWJsZSk9fSBvcHRfdmFsdWVcbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2UuPFRZUEU+fSBBIG5ldyBQcm9taXNlIHRoYXQgaXMgaW1tZWRpYXRlbHkgcmVzb2x2ZWRcbiAqICAgICB3aXRoIHRoZSBnaXZlbiB2YWx1ZS5cbiAqIEB0ZW1wbGF0ZSBUWVBFXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5yZXNvbHZlID0gZnVuY3Rpb24ob3B0X3ZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUpIHtcbiAgICAgIHJlc29sdmUob3B0X3ZhbHVlKTtcbiAgICB9KTtcbn07XG5cblxuLyoqXG4gKiBAcGFyYW0geyo9fSBvcHRfcmVhc29uXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlfSBBIG5ldyBQcm9taXNlIHRoYXQgaXMgaW1tZWRpYXRlbHkgcmVqZWN0ZWQgd2l0aCB0aGVcbiAqICAgICBnaXZlbiByZWFzb24uXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QgPSBmdW5jdGlvbihvcHRfcmVhc29uKSB7XG4gIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgcmVqZWN0KG9wdF9yZWFzb24pO1xuICAgIH0pO1xufTtcblxuXG4vKipcbiAqIEBwYXJhbSB7IUFycmF5LjwhKFRoZW5hYmxlLjxUWVBFPnxUaGVuYWJsZSk+fSBwcm9taXNlc1xuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZS48VFlQRT59IEEgUHJvbWlzZSB0aGF0IHJlY2VpdmVzIHRoZSByZXN1bHQgb2YgdGhlXG4gKiAgICAgZmlyc3QgUHJvbWlzZSAob3IgUHJvbWlzZS1saWtlKSBpbnB1dCB0byBjb21wbGV0ZS5cbiAqIEB0ZW1wbGF0ZSBUWVBFXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5yYWNlID0gZnVuY3Rpb24ocHJvbWlzZXMpIHtcbiAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICBpZiAoIXByb21pc2VzLmxlbmd0aCkge1xuICAgICAgICByZXNvbHZlKHVuZGVmaW5lZCk7XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBpID0gMCwgcHJvbWlzZTsgKHByb21pc2UgPSBwcm9taXNlc1tpXSk7IGkrKykge1xuICAgICAgICBwcm9taXNlLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgIH1cbiAgICB9KTtcbn07XG5cblxuLyoqXG4gKiBAcGFyYW0geyFBcnJheS48IShUaGVuYWJsZS48VFlQRT58VGhlbmFibGUpPn0gcHJvbWlzZXNcbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2UuPCFBcnJheS48VFlQRT4+fSBBIFByb21pc2UgdGhhdCByZWNlaXZlcyBhIGxpc3Qgb2ZcbiAqICAgICBldmVyeSBmdWxmaWxsZWQgdmFsdWUgb25jZSBldmVyeSBpbnB1dCBQcm9taXNlIChvciBQcm9taXNlLWxpa2UpIGlzXG4gKiAgICAgc3VjY2Vzc2Z1bGx5IGZ1bGZpbGxlZCwgb3IgaXMgcmVqZWN0ZWQgYnkgdGhlIGZpcnN0IHJlamVjdGlvbiByZXN1bHQuXG4gKiBAdGVtcGxhdGUgVFlQRVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuYWxsID0gZnVuY3Rpb24ocHJvbWlzZXMpIHtcbiAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICB2YXIgdG9GdWxmaWxsID0gcHJvbWlzZXMubGVuZ3RoO1xuICAgICAgdmFyIHZhbHVlcyA9IFtdO1xuXG4gICAgICBpZiAoIXRvRnVsZmlsbCkge1xuICAgICAgICByZXNvbHZlKHZhbHVlcyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIG9uRnVsZmlsbCA9IGZ1bmN0aW9uKGluZGV4LCB2YWx1ZSkge1xuICAgICAgICB0b0Z1bGZpbGwtLTtcbiAgICAgICAgdmFsdWVzW2luZGV4XSA9IHZhbHVlO1xuICAgICAgICBpZiAodG9GdWxmaWxsID09PSAwKSB7XG4gICAgICAgICAgcmVzb2x2ZSh2YWx1ZXMpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICB2YXIgb25SZWplY3QgPSBmdW5jdGlvbihyZWFzb24pIHtcbiAgICAgICAgcmVqZWN0KHJlYXNvbik7XG4gICAgICB9O1xuXG4gICAgICBmb3IgKHZhciBpID0gMCwgcHJvbWlzZTsgKHByb21pc2UgPSBwcm9taXNlc1tpXSk7IGkrKykge1xuICAgICAgICBwcm9taXNlLnRoZW4ocGFydGlhbChvbkZ1bGZpbGwsIGkpLCBvblJlamVjdCk7XG4gICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQHBhcmFtIHshQXJyYXkuPCEoVGhlbmFibGUuPFRZUEU+fFRoZW5hYmxlKT59IHByb21pc2VzXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlLjxUWVBFPn0gQSBQcm9taXNlIHRoYXQgcmVjZWl2ZXMgdGhlIHZhbHVlIG9mXG4gKiAgICAgdGhlIGZpcnN0IGlucHV0IHRvIGJlIGZ1bGZpbGxlZCwgb3IgaXMgcmVqZWN0ZWQgd2l0aCBhIGxpc3Qgb2YgZXZlcnlcbiAqICAgICByZWplY3Rpb24gcmVhc29uIGlmIGFsbCBpbnB1dHMgYXJlIHJlamVjdGVkLlxuICogQHRlbXBsYXRlIFRZUEVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLmZpcnN0RnVsZmlsbGVkID0gZnVuY3Rpb24ocHJvbWlzZXMpIHtcbiAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICB2YXIgdG9SZWplY3QgPSBwcm9taXNlcy5sZW5ndGg7XG4gICAgICB2YXIgcmVhc29ucyA9IFtdO1xuXG4gICAgICBpZiAoIXRvUmVqZWN0KSB7XG4gICAgICAgIHJlc29sdmUodW5kZWZpbmVkKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgb25GdWxmaWxsID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmVzb2x2ZSh2YWx1ZSk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgb25SZWplY3QgPSBmdW5jdGlvbihpbmRleCwgcmVhc29uKSB7XG4gICAgICAgIHRvUmVqZWN0LS07XG4gICAgICAgIHJlYXNvbnNbaW5kZXhdID0gcmVhc29uO1xuICAgICAgICBpZiAodG9SZWplY3QgPT09IDApIHtcbiAgICAgICAgICByZWplY3QocmVhc29ucyk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBwcm9taXNlOyAocHJvbWlzZSA9IHByb21pc2VzW2ldKTsgaSsrKSB7XG4gICAgICAgIHByb21pc2UudGhlbihvbkZ1bGZpbGwsIHBhcnRpYWwob25SZWplY3QsIGkpKTtcbiAgICAgIH1cbiAgICB9KTtcbn07XG5cblxuLyoqXG4gKiBBZGRzIGNhbGxiYWNrcyB0aGF0IHdpbGwgb3BlcmF0ZSBvbiB0aGUgcmVzdWx0IG9mIHRoZSBQcm9taXNlLCByZXR1cm5pbmcgYVxuICogbmV3IGNoaWxkIFByb21pc2UuXG4gKlxuICogSWYgdGhlIFByb21pc2UgaXMgZnVsZmlsbGVkLCB0aGUge0Bjb2RlIG9uRnVsZmlsbGVkfSBjYWxsYmFjayB3aWxsIGJlIGludm9rZWRcbiAqIHdpdGggdGhlIGZ1bGZpbGxtZW50IHZhbHVlIGFzIGFyZ3VtZW50LCBhbmQgdGhlIGNoaWxkIFByb21pc2Ugd2lsbCBiZVxuICogZnVsZmlsbGVkIHdpdGggdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgY2FsbGJhY2suIElmIHRoZSBjYWxsYmFjayB0aHJvd3MgYW5cbiAqIGV4Y2VwdGlvbiwgdGhlIGNoaWxkIFByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSB0aHJvd24gdmFsdWUgaW5zdGVhZC5cbiAqXG4gKiBJZiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZCwgdGhlIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFjayB3aWxsIGJlIGludm9rZWRcbiAqIHdpdGggdGhlIHJlamVjdGlvbiByZWFzb24gYXMgYXJndW1lbnQsIGFuZCB0aGUgY2hpbGQgUHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkXG4gKiB3aXRoIHRoZSByZXR1cm4gdmFsdWUgKG9yIHRocm93biB2YWx1ZSkgb2YgdGhlIGNhbGxiYWNrLlxuICpcbiAqIEBvdmVycmlkZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnRoZW4gPSBmdW5jdGlvbihvcHRfb25GdWxmaWxsZWQsIG9wdF9vblJlamVjdGVkLCBvcHRfY29udGV4dCkge1xuICByZXR1cm4gdGhpcy5hZGRDaGlsZFByb21pc2VfKFxuICAgIGlzRnVuY3Rpb24ob3B0X29uRnVsZmlsbGVkKSA/IG9wdF9vbkZ1bGZpbGxlZCA6IG51bGwsXG4gICAgaXNGdW5jdGlvbihvcHRfb25SZWplY3RlZCkgPyBvcHRfb25SZWplY3RlZCA6IG51bGwsXG4gICAgb3B0X2NvbnRleHQpO1xufTtcblRoZW5hYmxlLmFkZEltcGxlbWVudGF0aW9uKENhbmNlbGxhYmxlUHJvbWlzZSk7XG5cblxuLyoqXG4gKiBBZGRzIGEgY2FsbGJhY2sgdGhhdCB3aWxsIGJlIGludm9rZWQgd2hldGhlciB0aGUgUHJvbWlzZSBpcyBmdWxmaWxsZWQgb3JcbiAqIHJlamVjdGVkLiBUaGUgY2FsbGJhY2sgcmVjZWl2ZXMgbm8gYXJndW1lbnQsIGFuZCBubyBuZXcgY2hpbGQgUHJvbWlzZSBpc1xuICogY3JlYXRlZC4gVGhpcyBpcyB1c2VmdWwgZm9yIGVuc3VyaW5nIHRoYXQgY2xlYW51cCB0YWtlcyBwbGFjZSBhZnRlciBjZXJ0YWluXG4gKiBhc3luY2hyb25vdXMgb3BlcmF0aW9ucy4gQ2FsbGJhY2tzIGFkZGVkIHdpdGgge0Bjb2RlIHRoZW5BbHdheXN9IHdpbGwgYmVcbiAqIGV4ZWN1dGVkIGluIHRoZSBzYW1lIG9yZGVyIHdpdGggb3RoZXIgY2FsbHMgdG8ge0Bjb2RlIHRoZW59LFxuICoge0Bjb2RlIHRoZW5BbHdheXN9LCBvciB7QGNvZGUgdGhlbkNhdGNofS5cbiAqXG4gKiBTaW5jZSBpdCBkb2VzIG5vdCBwcm9kdWNlIGEgbmV3IGNoaWxkIFByb21pc2UsIGNhbmNlbGxhdGlvbiBwcm9wYWdhdGlvbiBpc1xuICogbm90IHByZXZlbnRlZCBieSBhZGRpbmcgY2FsbGJhY2tzIHdpdGgge0Bjb2RlIHRoZW5BbHdheXN9LiBBIFByb21pc2UgdGhhdCBoYXNcbiAqIGEgY2xlYW51cCBoYW5kbGVyIGFkZGVkIHdpdGgge0Bjb2RlIHRoZW5BbHdheXN9IHdpbGwgYmUgY2FuY2VsZWQgaWYgYWxsIG9mXG4gKiBpdHMgY2hpbGRyZW4gY3JlYXRlZCBieSB7QGNvZGUgdGhlbn0gKG9yIHtAY29kZSB0aGVuQ2F0Y2h9KSBhcmUgY2FuY2VsZWQuXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbih0aGlzOlRISVMpOiB2b2lkfSBvblJlc29sdmVkIEEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGludm9rZWRcbiAqICAgICB3aGVuIHRoZSBQcm9taXNlIGlzIHJlc29sdmVkLlxuICogQHBhcmFtIHtUSElTPX0gb3B0X2NvbnRleHQgQW4gb3B0aW9uYWwgY29udGV4dCBvYmplY3QgdGhhdCB3aWxsIGJlIHRoZVxuICogICAgIGV4ZWN1dGlvbiBjb250ZXh0IGZvciB0aGUgY2FsbGJhY2tzLiBCeSBkZWZhdWx0LCBmdW5jdGlvbnMgYXJlIGV4ZWN1dGVkXG4gKiAgICAgaW4gdGhlIGdsb2JhbCBzY29wZS5cbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2UuPFRZUEU+fSBUaGlzIFByb21pc2UsIGZvciBjaGFpbmluZyBhZGRpdGlvbmFsIGNhbGxzLlxuICogQHRlbXBsYXRlIFRISVNcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS50aGVuQWx3YXlzID0gZnVuY3Rpb24ob25SZXNvbHZlZCwgb3B0X2NvbnRleHQpIHtcbiAgdmFyIGNhbGxiYWNrID0gZnVuY3Rpb24oKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIEVuc3VyZSB0aGF0IG5vIGFyZ3VtZW50cyBhcmUgcGFzc2VkIHRvIG9uUmVzb2x2ZWQuXG4gICAgICBvblJlc29sdmVkLmNhbGwob3B0X2NvbnRleHQpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgQ2FuY2VsbGFibGVQcm9taXNlLmhhbmRsZVJlamVjdGlvbl8uY2FsbChudWxsLCBlcnIpO1xuICAgIH1cbiAgfTtcblxuICB0aGlzLmFkZENhbGxiYWNrRW50cnlfKHtcbiAgICBjaGlsZDogbnVsbCxcbiAgICBvblJlamVjdGVkOiBjYWxsYmFjayxcbiAgICBvbkZ1bGZpbGxlZDogY2FsbGJhY2tcbiAgfSk7XG4gIHJldHVybiB0aGlzO1xufTtcblxuXG4vKipcbiAqIEFkZHMgYSBjYWxsYmFjayB0aGF0IHdpbGwgYmUgaW52b2tlZCBvbmx5IGlmIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLiBUaGlzXG4gKiBpcyBlcXVpdmFsZW50IHRvIHtAY29kZSB0aGVuKG51bGwsIG9uUmVqZWN0ZWQpfS5cbiAqXG4gKiBAcGFyYW0geyFmdW5jdGlvbih0aGlzOlRISVMsICopOiAqfSBvblJlamVjdGVkIEEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlXG4gKiAgICAgaW52b2tlZCB3aXRoIHRoZSByZWplY3Rpb24gcmVhc29uIGlmIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLlxuICogQHBhcmFtIHtUSElTPX0gb3B0X2NvbnRleHQgQW4gb3B0aW9uYWwgY29udGV4dCBvYmplY3QgdGhhdCB3aWxsIGJlIHRoZVxuICogICAgIGV4ZWN1dGlvbiBjb250ZXh0IGZvciB0aGUgY2FsbGJhY2tzLiBCeSBkZWZhdWx0LCBmdW5jdGlvbnMgYXJlIGV4ZWN1dGVkXG4gKiAgICAgaW4gdGhlIGdsb2JhbCBzY29wZS5cbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2V9IEEgbmV3IFByb21pc2UgdGhhdCB3aWxsIHJlY2VpdmUgdGhlIHJlc3VsdCBvZiB0aGVcbiAqICAgICBjYWxsYmFjay5cbiAqIEB0ZW1wbGF0ZSBUSElTXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudGhlbkNhdGNoID0gZnVuY3Rpb24ob25SZWplY3RlZCwgb3B0X2NvbnRleHQpIHtcbiAgcmV0dXJuIHRoaXMuYWRkQ2hpbGRQcm9taXNlXyhudWxsLCBvblJlamVjdGVkLCBvcHRfY29udGV4dCk7XG59O1xuXG4vKipcbiAqIEFsaWFzIG9mIHtAbGluayBDYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnRoZW5DYXRjaH1cbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5jYXRjaCA9IENhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudGhlbkNhdGNoO1xuXG5cbi8qKlxuICogQ2FuY2VscyB0aGUgUHJvbWlzZSBpZiBpdCBpcyBzdGlsbCBwZW5kaW5nIGJ5IHJlamVjdGluZyBpdCB3aXRoIGEgY2FuY2VsXG4gKiBFcnJvci4gTm8gYWN0aW9uIGlzIHBlcmZvcm1lZCBpZiB0aGUgUHJvbWlzZSBpcyBhbHJlYWR5IHJlc29sdmVkLlxuICpcbiAqIEFsbCBjaGlsZCBQcm9taXNlcyBvZiB0aGUgY2FuY2VsZWQgUHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkIHdpdGggdGhlIHNhbWVcbiAqIGNhbmNlbCBlcnJvciwgYXMgd2l0aCBub3JtYWwgUHJvbWlzZSByZWplY3Rpb24uIElmIHRoZSBQcm9taXNlIHRvIGJlIGNhbmNlbGVkXG4gKiBpcyB0aGUgb25seSBjaGlsZCBvZiBhIHBlbmRpbmcgUHJvbWlzZSwgdGhlIHBhcmVudCBQcm9taXNlIHdpbGwgYWxzbyBiZVxuICogY2FuY2VsZWQuIENhbmNlbGxhdGlvbiBtYXkgcHJvcGFnYXRlIHVwd2FyZCB0aHJvdWdoIG11bHRpcGxlIGdlbmVyYXRpb25zLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nPX0gb3B0X21lc3NhZ2UgQW4gb3B0aW9uYWwgZGVidWdnaW5nIG1lc3NhZ2UgZm9yIGRlc2NyaWJpbmcgdGhlXG4gKiAgICAgY2FuY2VsbGF0aW9uIHJlYXNvbi5cbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5jYW5jZWwgPSBmdW5jdGlvbihvcHRfbWVzc2FnZSkge1xuICBpZiAodGhpcy5zdGF0ZV8gPT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORykge1xuICAgIGFzeW5jLnJ1bihmdW5jdGlvbigpIHtcbiAgICAgIHZhciBlcnIgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlLkNhbmNlbGxhdGlvbkVycm9yKG9wdF9tZXNzYWdlKTtcbiAgICAgIGVyci5JU19DQU5DRUxMQVRJT05fRVJST1IgPSB0cnVlO1xuICAgICAgdGhpcy5jYW5jZWxJbnRlcm5hbF8oZXJyKTtcbiAgICB9LCB0aGlzKTtcbiAgfVxufTtcblxuXG4vKipcbiAqIENhbmNlbHMgdGhpcyBQcm9taXNlIHdpdGggdGhlIGdpdmVuIGVycm9yLlxuICpcbiAqIEBwYXJhbSB7IUVycm9yfSBlcnIgVGhlIGNhbmNlbGxhdGlvbiBlcnJvci5cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuY2FuY2VsSW50ZXJuYWxfID0gZnVuY3Rpb24oZXJyKSB7XG4gIGlmICh0aGlzLnN0YXRlXyA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5QRU5ESU5HKSB7XG4gICAgaWYgKHRoaXMucGFyZW50Xykge1xuICAgICAgLy8gQ2FuY2VsIHRoZSBQcm9taXNlIGFuZCByZW1vdmUgaXQgZnJvbSB0aGUgcGFyZW50J3MgY2hpbGQgbGlzdC5cbiAgICAgIHRoaXMucGFyZW50Xy5jYW5jZWxDaGlsZF8odGhpcywgZXJyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZXNvbHZlXyhDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVELCBlcnIpO1xuICAgIH1cbiAgfVxufTtcblxuXG4vKipcbiAqIENhbmNlbHMgYSBjaGlsZCBQcm9taXNlIGZyb20gdGhlIGxpc3Qgb2YgY2FsbGJhY2sgZW50cmllcy4gSWYgdGhlIFByb21pc2UgaGFzXG4gKiBub3QgYWxyZWFkeSBiZWVuIHJlc29sdmVkLCByZWplY3QgaXQgd2l0aCBhIGNhbmNlbCBlcnJvci4gSWYgdGhlcmUgYXJlIG5vXG4gKiBvdGhlciBjaGlsZHJlbiBpbiB0aGUgbGlzdCBvZiBjYWxsYmFjayBlbnRyaWVzLCBwcm9wYWdhdGUgdGhlIGNhbmNlbGxhdGlvblxuICogYnkgY2FuY2VsaW5nIHRoaXMgUHJvbWlzZSBhcyB3ZWxsLlxuICpcbiAqIEBwYXJhbSB7IUNhbmNlbGxhYmxlUHJvbWlzZX0gY2hpbGRQcm9taXNlIFRoZSBQcm9taXNlIHRvIGNhbmNlbC5cbiAqIEBwYXJhbSB7IUVycm9yfSBlcnIgVGhlIGNhbmNlbCBlcnJvciB0byB1c2UgZm9yIHJlamVjdGluZyB0aGUgUHJvbWlzZS5cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuY2FuY2VsQ2hpbGRfID0gZnVuY3Rpb24oY2hpbGRQcm9taXNlLCBlcnIpIHtcbiAgaWYgKCF0aGlzLmNhbGxiYWNrRW50cmllc18pIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIGNoaWxkQ291bnQgPSAwO1xuICB2YXIgY2hpbGRJbmRleCA9IC0xO1xuXG4gIC8vIEZpbmQgdGhlIGNhbGxiYWNrIGVudHJ5IGZvciB0aGUgY2hpbGRQcm9taXNlLCBhbmQgY291bnQgd2hldGhlciB0aGVyZSBhcmVcbiAgLy8gYWRkaXRpb25hbCBjaGlsZCBQcm9taXNlcy5cbiAgZm9yICh2YXIgaSA9IDAsIGVudHJ5OyAoZW50cnkgPSB0aGlzLmNhbGxiYWNrRW50cmllc19baV0pOyBpKyspIHtcbiAgICB2YXIgY2hpbGQgPSBlbnRyeS5jaGlsZDtcbiAgICBpZiAoY2hpbGQpIHtcbiAgICAgIGNoaWxkQ291bnQrKztcbiAgICAgIGlmIChjaGlsZCA9PT0gY2hpbGRQcm9taXNlKSB7XG4gICAgICAgIGNoaWxkSW5kZXggPSBpO1xuICAgICAgfVxuICAgICAgaWYgKGNoaWxkSW5kZXggPj0gMCAmJiBjaGlsZENvdW50ID4gMSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBJZiB0aGUgY2hpbGQgUHJvbWlzZSB3YXMgdGhlIG9ubHkgY2hpbGQsIGNhbmNlbCB0aGlzIFByb21pc2UgYXMgd2VsbC5cbiAgLy8gT3RoZXJ3aXNlLCByZWplY3Qgb25seSB0aGUgY2hpbGQgUHJvbWlzZSB3aXRoIHRoZSBjYW5jZWwgZXJyb3IuXG4gIGlmIChjaGlsZEluZGV4ID49IDApIHtcbiAgICBpZiAodGhpcy5zdGF0ZV8gPT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORyAmJiBjaGlsZENvdW50ID09PSAxKSB7XG4gICAgICB0aGlzLmNhbmNlbEludGVybmFsXyhlcnIpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgY2FsbGJhY2tFbnRyeSA9IHRoaXMuY2FsbGJhY2tFbnRyaWVzXy5zcGxpY2UoY2hpbGRJbmRleCwgMSlbMF07XG4gICAgICB0aGlzLmV4ZWN1dGVDYWxsYmFja18oXG4gICAgICAgIGNhbGxiYWNrRW50cnksIENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQsIGVycik7XG4gICAgfVxuICB9XG59O1xuXG5cbi8qKlxuICogQWRkcyBhIGNhbGxiYWNrIGVudHJ5IHRvIHRoZSBjdXJyZW50IFByb21pc2UsIGFuZCBzY2hlZHVsZXMgY2FsbGJhY2tcbiAqIGV4ZWN1dGlvbiBpZiB0aGUgUHJvbWlzZSBoYXMgYWxyZWFkeSBiZWVuIHJlc29sdmVkLlxuICpcbiAqIEBwYXJhbSB7Q2FuY2VsbGFibGVQcm9taXNlLkNhbGxiYWNrRW50cnlffSBjYWxsYmFja0VudHJ5IFJlY29yZCBjb250YWluaW5nXG4gKiAgICAge0Bjb2RlIG9uRnVsZmlsbGVkfSBhbmQge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrcyB0byBleGVjdXRlIGFmdGVyXG4gKiAgICAgdGhlIFByb21pc2UgaXMgcmVzb2x2ZWQuXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmFkZENhbGxiYWNrRW50cnlfID0gZnVuY3Rpb24oY2FsbGJhY2tFbnRyeSkge1xuICBpZiAoKCF0aGlzLmNhbGxiYWNrRW50cmllc18gfHwgIXRoaXMuY2FsbGJhY2tFbnRyaWVzXy5sZW5ndGgpICYmXG4gICAgKHRoaXMuc3RhdGVfID09PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkZVTEZJTExFRCB8fFxuICAgIHRoaXMuc3RhdGVfID09PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVEKSkge1xuICAgIHRoaXMuc2NoZWR1bGVDYWxsYmFja3NfKCk7XG4gIH1cbiAgaWYgKCF0aGlzLmNhbGxiYWNrRW50cmllc18pIHtcbiAgICB0aGlzLmNhbGxiYWNrRW50cmllc18gPSBbXTtcbiAgfVxuICB0aGlzLmNhbGxiYWNrRW50cmllc18ucHVzaChjYWxsYmFja0VudHJ5KTtcbn07XG5cblxuLyoqXG4gKiBDcmVhdGVzIGEgY2hpbGQgUHJvbWlzZSBhbmQgYWRkcyBpdCB0byB0aGUgY2FsbGJhY2sgZW50cnkgbGlzdC4gVGhlIHJlc3VsdCBvZlxuICogdGhlIGNoaWxkIFByb21pc2UgaXMgZGV0ZXJtaW5lZCBieSB0aGUgc3RhdGUgb2YgdGhlIHBhcmVudCBQcm9taXNlIGFuZCB0aGVcbiAqIHJlc3VsdCBvZiB0aGUge0Bjb2RlIG9uRnVsZmlsbGVkfSBvciB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2tzIGFzXG4gKiBzcGVjaWZpZWQgaW4gdGhlIFByb21pc2UgcmVzb2x1dGlvbiBwcm9jZWR1cmUuXG4gKlxuICogQHNlZSBodHRwOi8vcHJvbWlzZXNhcGx1cy5jb20vI3RoZV9fbWV0aG9kXG4gKlxuICogQHBhcmFtIHs/ZnVuY3Rpb24odGhpczpUSElTLCBUWVBFKTpcbiAqICAgICAgICAgIChSRVNVTFR8Q2FuY2VsbGFibGVQcm9taXNlLjxSRVNVTFQ+fFRoZW5hYmxlKX0gb25GdWxmaWxsZWQgQSBjYWxsYmFjayB0aGF0XG4gKiAgICAgd2lsbCBiZSBpbnZva2VkIGlmIHRoZSBQcm9taXNlIGlzIGZ1bGxmaWxsZWQsIG9yIG51bGwuXG4gKiBAcGFyYW0gez9mdW5jdGlvbih0aGlzOlRISVMsICopOiAqfSBvblJlamVjdGVkIEEgY2FsbGJhY2sgdGhhdCB3aWxsIGJlXG4gKiAgICAgaW52b2tlZCBpZiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZCwgb3IgbnVsbC5cbiAqIEBwYXJhbSB7VEhJUz19IG9wdF9jb250ZXh0IEFuIG9wdGlvbmFsIGV4ZWN1dGlvbiBjb250ZXh0IGZvciB0aGUgY2FsbGJhY2tzLlxuICogICAgIGluIHRoZSBkZWZhdWx0IGNhbGxpbmcgY29udGV4dC5cbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2V9IFRoZSBjaGlsZCBQcm9taXNlLlxuICogQHRlbXBsYXRlIFJFU1VMVCxUSElTXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmFkZENoaWxkUHJvbWlzZV8gPSBmdW5jdGlvbihcbm9uRnVsZmlsbGVkLCBvblJlamVjdGVkLCBvcHRfY29udGV4dCkge1xuXG4gIHZhciBjYWxsYmFja0VudHJ5ID0ge1xuICAgIGNoaWxkOiBudWxsLFxuICAgIG9uRnVsZmlsbGVkOiBudWxsLFxuICAgIG9uUmVqZWN0ZWQ6IG51bGxcbiAgfTtcblxuICBjYWxsYmFja0VudHJ5LmNoaWxkID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAvLyBJbnZva2Ugb25GdWxmaWxsZWQsIG9yIHJlc29sdmUgd2l0aCB0aGUgcGFyZW50J3MgdmFsdWUgaWYgYWJzZW50LlxuICAgIGNhbGxiYWNrRW50cnkub25GdWxmaWxsZWQgPSBvbkZ1bGZpbGxlZCA/IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICB0cnkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gb25GdWxmaWxsZWQuY2FsbChvcHRfY29udGV4dCwgdmFsdWUpO1xuICAgICAgICByZXNvbHZlKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9XG4gICAgfSA6IHJlc29sdmU7XG5cbiAgICAvLyBJbnZva2Ugb25SZWplY3RlZCwgb3IgcmVqZWN0IHdpdGggdGhlIHBhcmVudCdzIHJlYXNvbiBpZiBhYnNlbnQuXG4gICAgY2FsbGJhY2tFbnRyeS5vblJlamVjdGVkID0gb25SZWplY3RlZCA/IGZ1bmN0aW9uKHJlYXNvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG9uUmVqZWN0ZWQuY2FsbChvcHRfY29udGV4dCwgcmVhc29uKTtcbiAgICAgICAgaWYgKCFpc0RlZihyZXN1bHQpICYmIHJlYXNvbi5JU19DQU5DRUxMQVRJT05fRVJST1IpIHtcbiAgICAgICAgICAvLyBQcm9wYWdhdGUgY2FuY2VsbGF0aW9uIHRvIGNoaWxkcmVuIGlmIG5vIG90aGVyIHJlc3VsdCBpcyByZXR1cm5lZC5cbiAgICAgICAgICByZWplY3QocmVhc29uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgIH1cbiAgICB9IDogcmVqZWN0O1xuICB9KTtcblxuICBjYWxsYmFja0VudHJ5LmNoaWxkLnBhcmVudF8gPSB0aGlzO1xuICB0aGlzLmFkZENhbGxiYWNrRW50cnlfKFxuICAgIC8qKiBAdHlwZSB7Q2FuY2VsbGFibGVQcm9taXNlLkNhbGxiYWNrRW50cnlffSAqLyAoY2FsbGJhY2tFbnRyeSkpO1xuICByZXR1cm4gY2FsbGJhY2tFbnRyeS5jaGlsZDtcbn07XG5cblxuLyoqXG4gKiBVbmJsb2NrcyB0aGUgUHJvbWlzZSBhbmQgZnVsZmlsbHMgaXQgd2l0aCB0aGUgZ2l2ZW4gdmFsdWUuXG4gKlxuICogQHBhcmFtIHtUWVBFfSB2YWx1ZVxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS51bmJsb2NrQW5kRnVsZmlsbF8gPSBmdW5jdGlvbih2YWx1ZSkge1xuICBpZiAodGhpcy5zdGF0ZV8gIT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uQkxPQ0tFRCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FuY2VsbGFibGVQcm9taXNlIGlzIG5vdCBibG9ja2VkLicpO1xuICB9XG4gIHRoaXMuc3RhdGVfID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5QRU5ESU5HO1xuICB0aGlzLnJlc29sdmVfKENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uRlVMRklMTEVELCB2YWx1ZSk7XG59O1xuXG5cbi8qKlxuICogVW5ibG9ja3MgdGhlIFByb21pc2UgYW5kIHJlamVjdHMgaXQgd2l0aCB0aGUgZ2l2ZW4gcmVqZWN0aW9uIHJlYXNvbi5cbiAqXG4gKiBAcGFyYW0geyp9IHJlYXNvblxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS51bmJsb2NrQW5kUmVqZWN0XyA9IGZ1bmN0aW9uKHJlYXNvbikge1xuICBpZiAodGhpcy5zdGF0ZV8gIT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uQkxPQ0tFRCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FuY2VsbGFibGVQcm9taXNlIGlzIG5vdCBibG9ja2VkLicpO1xuICB9XG4gIHRoaXMuc3RhdGVfID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5QRU5ESU5HO1xuICB0aGlzLnJlc29sdmVfKENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQsIHJlYXNvbik7XG59O1xuXG5cbi8qKlxuICogQXR0ZW1wdHMgdG8gcmVzb2x2ZSBhIFByb21pc2Ugd2l0aCBhIGdpdmVuIHJlc29sdXRpb24gc3RhdGUgYW5kIHZhbHVlLiBUaGlzXG4gKiBpcyBhIG5vLW9wIGlmIHRoZSBnaXZlbiBQcm9taXNlIGhhcyBhbHJlYWR5IGJlZW4gcmVzb2x2ZWQuXG4gKlxuICogSWYgdGhlIGdpdmVuIHJlc3VsdCBpcyBhIFRoZW5hYmxlIChzdWNoIGFzIGFub3RoZXIgUHJvbWlzZSksIHRoZSBQcm9taXNlIHdpbGxcbiAqIGJlIHJlc29sdmVkIHdpdGggdGhlIHNhbWUgc3RhdGUgYW5kIHJlc3VsdCBhcyB0aGUgVGhlbmFibGUgb25jZSBpdCBpcyBpdHNlbGZcbiAqIHJlc29sdmVkLlxuICpcbiAqIElmIHRoZSBnaXZlbiByZXN1bHQgaXMgbm90IGEgVGhlbmFibGUsIHRoZSBQcm9taXNlIHdpbGwgYmUgZnVsZmlsbGVkIG9yXG4gKiByZWplY3RlZCB3aXRoIHRoYXQgcmVzdWx0IGJhc2VkIG9uIHRoZSBnaXZlbiBzdGF0ZS5cbiAqXG4gKiBAc2VlIGh0dHA6Ly9wcm9taXNlc2FwbHVzLmNvbS8jdGhlX3Byb21pc2VfcmVzb2x1dGlvbl9wcm9jZWR1cmVcbiAqXG4gKiBAcGFyYW0ge0NhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV99IHN0YXRlXG4gKiBAcGFyYW0geyp9IHggVGhlIHJlc3VsdCB0byBhcHBseSB0byB0aGUgUHJvbWlzZS5cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUucmVzb2x2ZV8gPSBmdW5jdGlvbihzdGF0ZSwgeCkge1xuICBpZiAodGhpcy5zdGF0ZV8gIT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICh0aGlzID09PSB4KSB7XG4gICAgc3RhdGUgPSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVEO1xuICAgIHggPSBuZXcgVHlwZUVycm9yKCdDYW5jZWxsYWJsZVByb21pc2UgY2Fubm90IHJlc29sdmUgdG8gaXRzZWxmJyk7XG5cbiAgfSBlbHNlIGlmIChUaGVuYWJsZS5pc0ltcGxlbWVudGVkQnkoeCkpIHtcbiAgICB4ID0gLyoqIEB0eXBlIHshVGhlbmFibGV9ICovICh4KTtcbiAgICB0aGlzLnN0YXRlXyA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uQkxPQ0tFRDtcbiAgICB4LnRoZW4odGhpcy51bmJsb2NrQW5kRnVsZmlsbF8sIHRoaXMudW5ibG9ja0FuZFJlamVjdF8sIHRoaXMpO1xuICAgIHJldHVybjtcblxuICB9IGVsc2UgaWYgKGlzT2JqZWN0KHgpKSB7XG4gICAgdHJ5IHtcbiAgICAgIHZhciB0aGVuID0geC50aGVuO1xuICAgICAgaWYgKGlzRnVuY3Rpb24odGhlbikpIHtcbiAgICAgICAgdGhpcy50cnlUaGVuXyh4LCB0aGVuKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHN0YXRlID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRDtcbiAgICAgIHggPSBlO1xuICAgIH1cbiAgfVxuXG4gIHRoaXMucmVzdWx0XyA9IHg7XG4gIHRoaXMuc3RhdGVfID0gc3RhdGU7XG4gIHRoaXMuc2NoZWR1bGVDYWxsYmFja3NfKCk7XG5cbiAgaWYgKHN0YXRlID09PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVEICYmICF4LklTX0NBTkNFTExBVElPTl9FUlJPUikge1xuICAgIENhbmNlbGxhYmxlUHJvbWlzZS5hZGRVbmhhbmRsZWRSZWplY3Rpb25fKHRoaXMsIHgpO1xuICB9XG59O1xuXG5cbi8qKlxuICogQXR0ZW1wdHMgdG8gY2FsbCB0aGUge0Bjb2RlIHRoZW59IG1ldGhvZCBvbiBhbiBvYmplY3QgaW4gdGhlIGhvcGVzIHRoYXQgaXQgaXNcbiAqIGEgUHJvbWlzZS1jb21wYXRpYmxlIGluc3RhbmNlLiBUaGlzIGFsbG93cyBpbnRlcm9wZXJhdGlvbiBiZXR3ZWVuIGRpZmZlcmVudFxuICogUHJvbWlzZSBpbXBsZW1lbnRhdGlvbnMsIGhvd2V2ZXIgYSBub24tY29tcGxpYW50IG9iamVjdCBtYXkgY2F1c2UgYSBQcm9taXNlXG4gKiB0byBoYW5nIGluZGVmaW5pdGVseS4gSWYgdGhlIHtAY29kZSB0aGVufSBtZXRob2QgdGhyb3dzIGFuIGV4Y2VwdGlvbiwgdGhlXG4gKiBkZXBlbmRlbnQgUHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkIHdpdGggdGhlIHRocm93biB2YWx1ZS5cbiAqXG4gKiBAc2VlIGh0dHA6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNzBcbiAqXG4gKiBAcGFyYW0ge1RoZW5hYmxlfSB0aGVuYWJsZSBBbiBvYmplY3Qgd2l0aCBhIHtAY29kZSB0aGVufSBtZXRob2QgdGhhdCBtYXkgYmVcbiAqICAgICBjb21wYXRpYmxlIHdpdGggdGhlIFByb21pc2UvQSsgc3BlY2lmaWNhdGlvbi5cbiAqIEBwYXJhbSB7IUZ1bmN0aW9ufSB0aGVuIFRoZSB7QGNvZGUgdGhlbn0gbWV0aG9kIG9mIHRoZSBUaGVuYWJsZSBvYmplY3QuXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnRyeVRoZW5fID0gZnVuY3Rpb24odGhlbmFibGUsIHRoZW4pIHtcbiAgdGhpcy5zdGF0ZV8gPSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkJMT0NLRUQ7XG4gIHZhciBwcm9taXNlID0gdGhpcztcbiAgdmFyIGNhbGxlZCA9IGZhbHNlO1xuXG4gIHZhciByZXNvbHZlID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgIHByb21pc2UudW5ibG9ja0FuZEZ1bGZpbGxfKHZhbHVlKTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIHJlamVjdCA9IGZ1bmN0aW9uKHJlYXNvbikge1xuICAgIGlmICghY2FsbGVkKSB7XG4gICAgICBjYWxsZWQgPSB0cnVlO1xuICAgICAgcHJvbWlzZS51bmJsb2NrQW5kUmVqZWN0XyhyZWFzb24pO1xuICAgIH1cbiAgfTtcblxuICB0cnkge1xuICAgIHRoZW4uY2FsbCh0aGVuYWJsZSwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJlamVjdChlKTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEV4ZWN1dGVzIHRoZSBwZW5kaW5nIGNhbGxiYWNrcyBvZiBhIHJlc29sdmVkIFByb21pc2UgYWZ0ZXIgYSB0aW1lb3V0LlxuICpcbiAqIFNlY3Rpb24gMi4yLjQgb2YgdGhlIFByb21pc2VzL0ErIHNwZWNpZmljYXRpb24gcmVxdWlyZXMgdGhhdCBQcm9taXNlXG4gKiBjYWxsYmFja3MgbXVzdCBvbmx5IGJlIGludm9rZWQgZnJvbSBhIGNhbGwgc3RhY2sgdGhhdCBvbmx5IGNvbnRhaW5zIFByb21pc2VcbiAqIGltcGxlbWVudGF0aW9uIGNvZGUsIHdoaWNoIHdlIGFjY29tcGxpc2ggYnkgaW52b2tpbmcgY2FsbGJhY2sgZXhlY3V0aW9uIGFmdGVyXG4gKiBhIHRpbWVvdXQuIElmIHtAY29kZSBzdGFydEV4ZWN1dGlvbl99IGlzIGNhbGxlZCBtdWx0aXBsZSB0aW1lcyBmb3IgdGhlIHNhbWVcbiAqIFByb21pc2UsIHRoZSBjYWxsYmFjayBjaGFpbiB3aWxsIGJlIGV2YWx1YXRlZCBvbmx5IG9uY2UuIEFkZGl0aW9uYWwgY2FsbGJhY2tzXG4gKiBtYXkgYmUgYWRkZWQgZHVyaW5nIHRoZSBldmFsdWF0aW9uIHBoYXNlLCBhbmQgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgc2FtZVxuICogZXZlbnQgbG9vcC5cbiAqXG4gKiBBbGwgUHJvbWlzZXMgYWRkZWQgdG8gdGhlIHdhaXRpbmcgbGlzdCBkdXJpbmcgdGhlIHNhbWUgYnJvd3NlciBldmVudCBsb29wXG4gKiB3aWxsIGJlIGV4ZWN1dGVkIGluIG9uZSBiYXRjaCB0byBhdm9pZCB1c2luZyBhIHNlcGFyYXRlIHRpbWVvdXQgcGVyIFByb21pc2UuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5zY2hlZHVsZUNhbGxiYWNrc18gPSBmdW5jdGlvbigpIHtcbiAgaWYgKCF0aGlzLmV4ZWN1dGluZ18pIHtcbiAgICB0aGlzLmV4ZWN1dGluZ18gPSB0cnVlO1xuICAgIGFzeW5jLnJ1bih0aGlzLmV4ZWN1dGVDYWxsYmFja3NfLCB0aGlzKTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEV4ZWN1dGVzIGFsbCBwZW5kaW5nIGNhbGxiYWNrcyBmb3IgdGhpcyBQcm9taXNlLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuZXhlY3V0ZUNhbGxiYWNrc18gPSBmdW5jdGlvbigpIHtcbiAgd2hpbGUgKHRoaXMuY2FsbGJhY2tFbnRyaWVzXyAmJiB0aGlzLmNhbGxiYWNrRW50cmllc18ubGVuZ3RoKSB7XG4gICAgdmFyIGVudHJpZXMgPSB0aGlzLmNhbGxiYWNrRW50cmllc187XG4gICAgdGhpcy5jYWxsYmFja0VudHJpZXNfID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuZXhlY3V0ZUNhbGxiYWNrXyhlbnRyaWVzW2ldLCB0aGlzLnN0YXRlXywgdGhpcy5yZXN1bHRfKTtcbiAgICB9XG4gIH1cbiAgdGhpcy5leGVjdXRpbmdfID0gZmFsc2U7XG59O1xuXG5cbi8qKlxuICogRXhlY3V0ZXMgYSBwZW5kaW5nIGNhbGxiYWNrIGZvciB0aGlzIFByb21pc2UuIEludm9rZXMgYW4ge0Bjb2RlIG9uRnVsZmlsbGVkfVxuICogb3Ige0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrIGJhc2VkIG9uIHRoZSByZXNvbHZlZCBzdGF0ZSBvZiB0aGUgUHJvbWlzZS5cbiAqXG4gKiBAcGFyYW0geyFDYW5jZWxsYWJsZVByb21pc2UuQ2FsbGJhY2tFbnRyeV99IGNhbGxiYWNrRW50cnkgQW4gZW50cnkgY29udGFpbmluZyB0aGVcbiAqICAgICBvbkZ1bGZpbGxlZCBhbmQvb3Igb25SZWplY3RlZCBjYWxsYmFja3MgZm9yIHRoaXMgc3RlcC5cbiAqIEBwYXJhbSB7Q2FuY2VsbGFibGVQcm9taXNlLlN0YXRlX30gc3RhdGUgVGhlIHJlc29sdXRpb24gc3RhdHVzIG9mIHRoZSBQcm9taXNlLFxuICogICAgIGVpdGhlciBGVUxGSUxMRUQgb3IgUkVKRUNURUQuXG4gKiBAcGFyYW0geyp9IHJlc3VsdCBUaGUgcmVzb2x2ZWQgcmVzdWx0IG9mIHRoZSBQcm9taXNlLlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5leGVjdXRlQ2FsbGJhY2tfID0gZnVuY3Rpb24oXG5jYWxsYmFja0VudHJ5LCBzdGF0ZSwgcmVzdWx0KSB7XG4gIGlmIChzdGF0ZSA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5GVUxGSUxMRUQpIHtcbiAgICBjYWxsYmFja0VudHJ5Lm9uRnVsZmlsbGVkKHJlc3VsdCk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5yZW1vdmVVbmhhbmRsZWRSZWplY3Rpb25fKCk7XG4gICAgY2FsbGJhY2tFbnRyeS5vblJlamVjdGVkKHJlc3VsdCk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBNYXJrcyB0aGlzIHJlamVjdGVkIFByb21pc2UgYXMgaGF2aW5nIGJlaW5nIGhhbmRsZWQuIEFsc28gbWFya3MgYW55IHBhcmVudFxuICogUHJvbWlzZXMgaW4gdGhlIHJlamVjdGVkIHN0YXRlIGFzIGhhbmRsZWQuIFRoZSByZWplY3Rpb24gaGFuZGxlciB3aWxsIG5vXG4gKiBsb25nZXIgYmUgaW52b2tlZCBmb3IgdGhpcyBQcm9taXNlIChpZiBpdCBoYXMgbm90IGJlZW4gY2FsbGVkIGFscmVhZHkpLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUucmVtb3ZlVW5oYW5kbGVkUmVqZWN0aW9uXyA9IGZ1bmN0aW9uKCkge1xuICB2YXIgcDtcbiAgaWYgKENhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZID4gMCkge1xuICAgIGZvciAocCA9IHRoaXM7IHAgJiYgcC51bmhhbmRsZWRSZWplY3Rpb25JZF87IHAgPSBwLnBhcmVudF8pIHtcbiAgICAgIGNsZWFyVGltZW91dChwLnVuaGFuZGxlZFJlamVjdGlvbklkXyk7XG4gICAgICBwLnVuaGFuZGxlZFJlamVjdGlvbklkXyA9IDA7XG4gICAgfVxuICB9IGVsc2UgaWYgKENhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZID09PSAwKSB7XG4gICAgZm9yIChwID0gdGhpczsgcCAmJiBwLmhhZFVuaGFuZGxlZFJlamVjdGlvbl87IHAgPSBwLnBhcmVudF8pIHtcbiAgICAgIHAuaGFkVW5oYW5kbGVkUmVqZWN0aW9uXyA9IGZhbHNlO1xuICAgIH1cbiAgfVxufTtcblxuXG4vKipcbiAqIE1hcmtzIHRoaXMgcmVqZWN0ZWQgUHJvbWlzZSBhcyB1bmhhbmRsZWQuIElmIG5vIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFja1xuICogaXMgY2FsbGVkIGZvciB0aGlzIFByb21pc2UgYmVmb3JlIHRoZSB7QGNvZGUgVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWX1cbiAqIGV4cGlyZXMsIHRoZSByZWFzb24gd2lsbCBiZSBwYXNzZWQgdG8gdGhlIHVuaGFuZGxlZCByZWplY3Rpb24gaGFuZGxlci4gVGhlXG4gKiBoYW5kbGVyIHR5cGljYWxseSByZXRocm93cyB0aGUgcmVqZWN0aW9uIHJlYXNvbiBzbyB0aGF0IGl0IGJlY29tZXMgdmlzaWJsZSBpblxuICogdGhlIGRldmVsb3BlciBjb25zb2xlLlxuICpcbiAqIEBwYXJhbSB7IUNhbmNlbGxhYmxlUHJvbWlzZX0gcHJvbWlzZSBUaGUgcmVqZWN0ZWQgUHJvbWlzZS5cbiAqIEBwYXJhbSB7Kn0gcmVhc29uIFRoZSBQcm9taXNlIHJlamVjdGlvbiByZWFzb24uXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuYWRkVW5oYW5kbGVkUmVqZWN0aW9uXyA9IGZ1bmN0aW9uKHByb21pc2UsIHJlYXNvbikge1xuICBpZiAoQ2FuY2VsbGFibGVQcm9taXNlLlVOSEFORExFRF9SRUpFQ1RJT05fREVMQVkgPiAwKSB7XG4gICAgcHJvbWlzZS51bmhhbmRsZWRSZWplY3Rpb25JZF8gPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgQ2FuY2VsbGFibGVQcm9taXNlLmhhbmRsZVJlamVjdGlvbl8uY2FsbChudWxsLCByZWFzb24pO1xuICAgIH0sIENhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZKTtcblxuICB9IGVsc2UgaWYgKENhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZID09PSAwKSB7XG4gICAgcHJvbWlzZS5oYWRVbmhhbmRsZWRSZWplY3Rpb25fID0gdHJ1ZTtcbiAgICBhc3luYy5ydW4oZnVuY3Rpb24oKSB7XG4gICAgICBpZiAocHJvbWlzZS5oYWRVbmhhbmRsZWRSZWplY3Rpb25fKSB7XG4gICAgICAgIENhbmNlbGxhYmxlUHJvbWlzZS5oYW5kbGVSZWplY3Rpb25fLmNhbGwobnVsbCwgcmVhc29uKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEEgbWV0aG9kIHRoYXQgaXMgaW52b2tlZCB3aXRoIHRoZSByZWplY3Rpb24gcmVhc29ucyBmb3IgUHJvbWlzZXMgdGhhdCBhcmVcbiAqIHJlamVjdGVkIGJ1dCBoYXZlIG5vIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFja3MgcmVnaXN0ZXJlZCB5ZXQuXG4gKiBAdHlwZSB7ZnVuY3Rpb24oKil9XG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuaGFuZGxlUmVqZWN0aW9uXyA9IGFzeW5jLnRocm93RXhjZXB0aW9uO1xuXG5cbi8qKlxuICogU2V0cyBhIGhhbmRsZXIgdGhhdCB3aWxsIGJlIGNhbGxlZCB3aXRoIHJlYXNvbnMgZnJvbSB1bmhhbmRsZWQgcmVqZWN0ZWRcbiAqIFByb21pc2VzLiBJZiB0aGUgcmVqZWN0ZWQgUHJvbWlzZSAob3Igb25lIG9mIGl0cyBkZXNjZW5kYW50cykgaGFzIGFuXG4gKiB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2sgcmVnaXN0ZXJlZCwgdGhlIHJlamVjdGlvbiB3aWxsIGJlIGNvbnNpZGVyZWRcbiAqIGhhbmRsZWQsIGFuZCB0aGUgcmVqZWN0aW9uIGhhbmRsZXIgd2lsbCBub3QgYmUgY2FsbGVkLlxuICpcbiAqIEJ5IGRlZmF1bHQsIHVuaGFuZGxlZCByZWplY3Rpb25zIGFyZSByZXRocm93biBzbyB0aGF0IHRoZSBlcnJvciBtYXkgYmVcbiAqIGNhcHR1cmVkIGJ5IHRoZSBkZXZlbG9wZXIgY29uc29sZSBvciBhIHtAY29kZSB3aW5kb3cub25lcnJvcn0gaGFuZGxlci5cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCopfSBoYW5kbGVyIEEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCB3aXRoIHJlYXNvbnMgZnJvbVxuICogICAgIHJlamVjdGVkIFByb21pc2VzLiBEZWZhdWx0cyB0byB7QGNvZGUgYXN5bmMudGhyb3dFeGNlcHRpb259LlxuICovXG5DYW5jZWxsYWJsZVByb21pc2Uuc2V0VW5oYW5kbGVkUmVqZWN0aW9uSGFuZGxlciA9IGZ1bmN0aW9uKGhhbmRsZXIpIHtcbiAgQ2FuY2VsbGFibGVQcm9taXNlLmhhbmRsZVJlamVjdGlvbl8gPSBoYW5kbGVyO1xufTtcblxuXG5cbi8qKlxuICogRXJyb3IgdXNlZCBhcyBhIHJlamVjdGlvbiByZWFzb24gZm9yIGNhbmNlbGVkIFByb21pc2VzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nPX0gb3B0X21lc3NhZ2VcbiAqIEBjb25zdHJ1Y3RvclxuICogQGV4dGVuZHMge0Vycm9yfVxuICogQGZpbmFsXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvciA9IGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihvcHRfbWVzc2FnZSkge1xuICAgICBzdXBlcihvcHRfbWVzc2FnZSk7XG5cbiAgICAgaWYgKG9wdF9tZXNzYWdlKSB7XG4gICAgICAgdGhpcy5tZXNzYWdlID0gb3B0X21lc3NhZ2U7XG4gICAgIH1cbiAgIH1cbn07XG5cbi8qKiBAb3ZlcnJpZGUgKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvci5wcm90b3R5cGUubmFtZSA9ICdjYW5jZWwnO1xuXG5leHBvcnQge0NhbmNlbGxhYmxlUHJvbWlzZX07XG5leHBvcnQgZGVmYXVsdCBDYW5jZWxsYWJsZVByb21pc2U7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICAqIERlYm91bmNlcyBmdW5jdGlvbiBleGVjdXRpb24uXG4gICogQHBhcmFtIHshZnVuY3Rpb24oKX0gZm5cbiAgKiBAcGFyYW0ge251bWJlcn0gZGVsYXlcbiAgKiBAcmV0dXJuIHshZnVuY3Rpb24oKX1cbiAgKi9cbmZ1bmN0aW9uIGRlYm91bmNlKGZuLCBkZWxheSkge1xuXHRyZXR1cm4gZnVuY3Rpb24gZGVib3VuY2VkKCkge1xuXHRcdHZhciBhcmdzID0gYXJndW1lbnRzO1xuXHRcdGNhbmNlbERlYm91bmNlKGRlYm91bmNlZCk7XG5cdFx0ZGVib3VuY2VkLmlkID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHRcdGZuLmFwcGx5KG51bGwsIGFyZ3MpO1xuXHRcdH0sIGRlbGF5KTtcblx0fTtcbn1cblxuLyoqXG4gKiBDYW5jZWxzIHRoZSBzY2hlZHVsZWQgZGVib3VuY2VkIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBjYW5jZWxEZWJvdW5jZShkZWJvdW5jZWQpIHtcblx0Y2xlYXJUaW1lb3V0KGRlYm91bmNlZC5pZCk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGRlYm91bmNlO1xuZXhwb3J0IHsgY2FuY2VsRGVib3VuY2UsIGRlYm91bmNlIH07XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBjb3JlIGZyb20gJ21ldGFsJztcblxuY29uc3QgUkVHRVggPSAvKFtcXC9dKT8oPzooPzpcXDooXFx3KykoPzpcXCgoKD86XFxcXC58W15cXFxcKCldKSopXFwpKT98XFwoKCg/OlxcXFwufFteXFxcXCgpXSkrKVxcKSkoWysqP10pPykvZztcblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gYXJyYXkgb2YgcmVnZXggbWF0Y2hlcyB0byBhIG1vcmUgcmVhZGFibGUgb2JqZWN0IGZvcm1hdC5cbiAqIEBwYXJhbSB7IUFycmF5PHN0cmluZz59IG1hdGNoZXNcbiAqIEByZXR1cm4geyFPYmplY3R9XG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRNYXRjaGVzVG9PYmoobWF0Y2hlcykge1xuXHRyZXR1cm4ge1xuXHRcdG1hdGNoOiBtYXRjaGVzWzBdLFxuXHRcdHByZWZpeDogbWF0Y2hlc1sxXSxcblx0XHRuYW1lOiBtYXRjaGVzWzJdLFxuXHRcdHBhcmFtUGF0dGVybjogbWF0Y2hlc1szXSxcblx0XHR1bm5hbWVkUGF0dGVybjogbWF0Y2hlc1s0XSxcblx0XHRtb2RpZmllcjogbWF0Y2hlc1s1XVxuXHR9O1xufVxuXG4vKipcbiAqIENvbnZlcnRzIHRoZSBnaXZlbiB0b2tlbnMgcGFyc2VkIGZyb20gYSByb3V0ZSBmb3JtYXQgc3RyaW5nIHRvIGEgcmVnZXguXG4gKiBAcGFyYW0geyFBcnJheTxzdHJpbmd8IU9iamVjdD59IHRva2Vuc1xuICogQHJldHVybiB7IVJlZ0V4cH1cbiAqL1xuZnVuY3Rpb24gY29udmVydFRva2Vuc1RvUmVnZXgodG9rZW5zKSB7XG5cdGxldCByZWdleCA9ICcnO1xuXHRmb3IgKGxldCBpID0gMDsgaSA8IHRva2Vucy5sZW5ndGg7IGkrKykge1xuXHRcdGlmIChjb3JlLmlzU3RyaW5nKHRva2Vuc1tpXSkpIHtcblx0XHRcdHJlZ2V4ICs9IGVzY2FwZSh0b2tlbnNbaV0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsZXQgY2FwdHVyZSA9IGVuY2xvc2VOb25DYXB0dXJpbmdHcm91cCh0b2tlbnNbaV0ucGF0dGVybik7XG5cdFx0XHRpZiAodG9rZW5zW2ldLnJlcGVhdCkge1xuXHRcdFx0XHRjYXB0dXJlICs9IGVuY2xvc2VOb25DYXB0dXJpbmdHcm91cCgnXFxcXC8nICsgY2FwdHVyZSkgKyAnKic7XG5cdFx0XHR9XG5cdFx0XHRjYXB0dXJlID0gZXNjYXBlKHRva2Vuc1tpXS5wcmVmaXgpICsgYCgke2NhcHR1cmV9KWA7XG5cdFx0XHRpZiAodG9rZW5zW2ldLm9wdGlvbmFsKSB7XG5cdFx0XHRcdGlmICghdG9rZW5zW2ldLnBhcnRpYWwpIHtcblx0XHRcdFx0XHRjYXB0dXJlID0gZW5jbG9zZU5vbkNhcHR1cmluZ0dyb3VwKGNhcHR1cmUpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNhcHR1cmUgKz0gJz8nO1xuXHRcdFx0fVxuXHRcdFx0cmVnZXggKz0gY2FwdHVyZTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIG5ldyBSZWdFeHAoJ14nICsgbWFrZVRyYWlsaW5nU2xhc2hPcHRpb25hbChyZWdleCkgKyAnJCcpO1xufVxuXG4vKipcbiAqIEVuY2xvc2VzIHRoZSBnaXZlbiByZWdleCBwYXR0ZXJuIGludG8gYSBub24gY2FwdHVyaW5nIGdyb3VwLlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdHRlcm5cbiAqIEByZXR1cm4ge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gZW5jbG9zZU5vbkNhcHR1cmluZ0dyb3VwKHBhdHRlcm4pIHtcblx0cmV0dXJuIGAoPzoke3BhdHRlcm59KWA7XG59XG5cbi8qKlxuICogRXNjYXBlcyB0aGUgZ2l2ZW4gc3RyaW5nIHRvIHNob3cgdXAgaW4gdGhlIHBhdGggcmVnZXguXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIGVzY2FwZShzdHIpIHtcblx0cmV0dXJuIHN0ci5yZXBsYWNlKC8oWy4rKj89XiE6JHt9KClbXFxdfFxcL1xcXFxdKS9nLCAnXFxcXCQxJyk7XG59XG5cbi8qKlxuICogTWFrZXMgdHJhaWxpbmcgc2xhc2ggb3B0aW9uYWwgb24gcGF0aHMuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVnZXhcbiAqIEBwYXJhbSB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiBtYWtlVHJhaWxpbmdTbGFzaE9wdGlvbmFsKHJlZ2V4KSB7XG5cdGlmICgvXFwvJC8udGVzdChyZWdleCkpIHtcblx0XHRyZWdleCArPSAnPyc7XG5cdH0gZWxzZSB7XG5cdFx0cmVnZXggKz0gJ1xcXFwvPyc7XG5cdH1cblx0cmV0dXJuIHJlZ2V4O1xufVxuXG4vKipcbiAqIFBhcnNlcyB0aGUgZ2l2ZW4gcm91dGUgZm9ybWF0IHN0cmluZyBpbnRvIHRva2VucyByZXByZXNlbnRpbmcgaXRzIGNvbnRlbnRzLlxuICogQHBhcmFtIHshQXJyYXl8c3RyaW5nfSByb3V0ZU9yVG9rZW5zIEVpdGhlciBhIHJvdXRlIGZvcm1hdCBzdHJpbmcgb3IgdG9rZW5zXG4gKiAgICAgcHJldmlvdXNseSBwYXJzZWQgdmlhIHRoZSBgcGFyc2VgIGZ1bmN0aW9uLlxuICogQHJldHVybiB7IUFycmF5PHN0cmluZ3whT2JqZWN0Pn0gQW4gYXJyYXkgb2YgdG9rZW5zIHRoYXQgY2FuIGJlIGVpdGhlciBwbGFpblxuICogICAgIHN0cmluZ3MgKHBhcnQgb2YgdGhlIHJvdXRlKSBvciBvYmplY3RzIGNvbnRhaW5pbmcgaW5mb3JtYXRpb25zIG9uIHBhcmFtcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlKHJvdXRlT3JUb2tlbnMpIHtcblx0aWYgKCFjb3JlLmlzU3RyaW5nKHJvdXRlT3JUb2tlbnMpKSB7XG5cdFx0cmV0dXJuIHJvdXRlT3JUb2tlbnM7XG5cdH1cblxuXHRjb25zdCByb3V0ZSA9IHJvdXRlT3JUb2tlbnM7XG5cdGxldCB1bm5hbWVkQ291bnQgPSAwO1xuXHRjb25zdCB0b2tlbnMgPSBbXTtcblx0bGV0IGN1cnJQYXRoID0gJyc7XG5cdGxldCBpbmRleCA9IDA7XG5cblx0bGV0IG1hdGNoZXMgPSBSRUdFWC5leGVjKHJvdXRlKTtcblx0d2hpbGUgKG1hdGNoZXMpIHtcblx0XHRjb25zdCBkYXRhID0gY29udmVydE1hdGNoZXNUb09iaihtYXRjaGVzKTtcblxuXHRcdGN1cnJQYXRoID0gcm91dGUuc2xpY2UoaW5kZXgsIG1hdGNoZXMuaW5kZXgpO1xuXHRcdGluZGV4ID0gbWF0Y2hlcy5pbmRleCArIGRhdGEubWF0Y2gubGVuZ3RoO1xuXHRcdHRva2Vucy5wdXNoKGN1cnJQYXRoKTtcblxuXHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdG5hbWU6IGRhdGEubmFtZSA/IGRhdGEubmFtZSA6ICcnICsgdW5uYW1lZENvdW50KyssXG5cdFx0XHRwYXJ0aWFsOiByb3V0ZVtpbmRleF0gJiYgcm91dGVbaW5kZXhdICE9PSBkYXRhLnByZWZpeCxcblx0XHRcdHByZWZpeDogZGF0YS5wcmVmaXggfHwgJycsXG5cdFx0XHRwYXR0ZXJuOiBkYXRhLnBhcmFtUGF0dGVybiB8fCBkYXRhLnVubmFtZWRQYXR0ZXJuIHx8ICdbXlxcXFwvXSsnLFxuXHRcdFx0cmVwZWF0OiBkYXRhLm1vZGlmaWVyID09PSAnKicgfHwgZGF0YS5tb2RpZmllciA9PT0gJysnLFxuXHRcdFx0b3B0aW9uYWw6IGRhdGEubW9kaWZpZXIgPT09ICcqJyB8fCBkYXRhLm1vZGlmaWVyID09PSAnPydcblx0XHR9KTtcblxuXHRcdG1hdGNoZXMgPSBSRUdFWC5leGVjKHJvdXRlKTtcblx0fVxuXG5cdGlmIChpbmRleCA8IHJvdXRlLmxlbmd0aCkge1xuXHRcdHRva2Vucy5wdXNoKHJvdXRlLnN1YnN0cihpbmRleCkpO1xuXHR9XG5cdHJldHVybiB0b2tlbnM7XG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIHJvdXRlIGZvcm1hdCBzdHJpbmcgdG8gYSByZWdleCB0aGF0IGNhbiBleHRyYWN0IHBhcmFtXG4gKiBkYXRhIGZyb20gcGF0aHMgbWF0Y2hpbmcgaXQuXG4gKiBAcGFyYW0geyFBcnJheXxzdHJpbmd9IHJvdXRlT3JUb2tlbnMgRWl0aGVyIGEgcm91dGUgZm9ybWF0IHN0cmluZyBvciB0b2tlbnNcbiAqICAgICBwcmV2aW91c2x5IHBhcnNlZCB2aWEgdGhlIGBwYXJzZWAgZnVuY3Rpb24uXG4gKiBAcmV0dXJuIHshUmVnRXhwfVxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9SZWdleChyb3V0ZU9yVG9rZW5zKSB7XG5cdHJldHVybiBjb252ZXJ0VG9rZW5zVG9SZWdleChwYXJzZShyb3V0ZU9yVG9rZW5zKSk7XG59XG5cbi8qKlxuICogRXh0cmFjdHMgZGF0YSBmcm9tIHRoZSBnaXZlbiBwYXRoIGFjY29yZGluZyB0byB0aGUgc3BlY2lmaWVkIHJvdXRlIGZvcm1hdC5cbiAqIEBwYXJhbSB7IUFycmF5fHN0cmluZ30gcm91dGVPclRva2VucyBFaXRoZXIgYSByb3V0ZSBmb3JtYXQgc3RyaW5nIG9yIHRva2Vuc1xuICogICAgIHByZXZpb3VzbHkgcGFyc2VkIHZpYSB0aGUgYHBhcnNlYCBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBUaGUgcGF0aCB0byBleHRyYWN0IHBhcmFtIGRhdGEgZnJvbS5cbiAqIEByZXR1cm4ge09iamVjdDxzdHJpbmcsIHN0cmluZz59IFRoZSBkYXRhIG9iamVjdCwgb3IgbnVsbCBpZiB0aGUgcGF0aCBkb2Vzbid0XG4gKiAgICAgbWF0Y2ggdGhlIGdpdmVuIGZvcm1hdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3REYXRhKHJvdXRlT3JUb2tlbnMsIHBhdGgpIHtcblx0Y29uc3QgZGF0YSA9IHt9O1xuXHRjb25zdCB0b2tlbnMgPSBwYXJzZShyb3V0ZU9yVG9rZW5zKTtcblx0Y29uc3QgbWF0Y2ggPSBwYXRoLm1hdGNoKGNvbnZlcnRUb2tlbnNUb1JlZ2V4KHRva2VucykpO1xuXG5cdGlmICghbWF0Y2gpIHtcblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdGxldCBwYXJhbUluZGV4ID0gMTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcblx0XHRpZiAoIWNvcmUuaXNTdHJpbmcodG9rZW5zW2ldKSkge1xuXHRcdFx0bGV0IHZhbHVlID0gbWF0Y2hbcGFyYW1JbmRleCsrXTtcblx0XHRcdGlmIChjb3JlLmlzRGVmKHZhbHVlKSkge1xuXHRcdFx0XHRpZiAodG9rZW5zW2ldLnJlcGVhdCkge1xuXHRcdFx0XHRcdHZhbHVlID0gdmFsdWUuc3BsaXQoJy8nKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRkYXRhW3Rva2Vuc1tpXS5uYW1lXSA9IHZhbHVlO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXHRyZXR1cm4gZGF0YTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaXNEZWZBbmROb3ROdWxsLCBpc0Z1bmN0aW9uLCBpc1N0cmluZyB9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7IGV4dHJhY3REYXRhLCBwYXJzZSwgdG9SZWdleCB9IGZyb20gJ21ldGFsLXBhdGgtcGFyc2VyJztcblxuY2xhc3MgUm91dGUge1xuXG5cdC8qKlxuXHQgKiBSb3V0ZSBjbGFzcy5cblx0ICogQHBhcmFtIHshc3RyaW5nfFJlZ0V4cHxGdW5jdGlvbn0gcGF0aFxuXHQgKiBAcGFyYW0geyFGdW5jdGlvbn0gaGFuZGxlclxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKHBhdGgsIGhhbmRsZXIpIHtcblx0XHRpZiAoIWlzRGVmQW5kTm90TnVsbChwYXRoKSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdSb3V0ZSBwYXRoIG5vdCBzcGVjaWZpZWQuJyk7XG5cdFx0fVxuXHRcdGlmICghaXNGdW5jdGlvbihoYW5kbGVyKSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdSb3V0ZSBoYW5kbGVyIGlzIG5vdCBhIGZ1bmN0aW9uLicpO1xuXHRcdH1cblxuXHRcdC8qKlxuXHRcdCAqIERlZmluZXMgdGhlIGhhbmRsZXIgd2hpY2ggd2lsbCBleGVjdXRlIG9uY2UgYSBVUkwgaW4gdGhlIGFwcGxpY2F0aW9uXG5cdFx0ICogbWF0Y2hlcyB0aGUgcGF0aC5cblx0XHQgKiBAdHlwZSB7IUZ1bmN0aW9ufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmhhbmRsZXIgPSBoYW5kbGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogRGVmaW5lcyB0aGUgcGF0aCB3aGljaCB3aWxsIHRyaWdnZXIgdGhlIHJvdXRlIGhhbmRsZXIuXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd8UmVnRXhwfEZ1bmN0aW9ufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnBhdGggPSBwYXRoO1xuXHR9XG5cblx0LyoqXG5cdCogQnVpbGRzIHBhcnNlZCBkYXRhIChyZWdleCBhbmQgdG9rZW5zKSBmb3IgdGhpcyByb3V0ZS5cblx0KiBAcmV0dXJuIHshT2JqZWN0fVxuXHQqIEBwcm90ZWN0ZWRcblx0Ki9cblx0YnVpbGRQYXJzZWREYXRhXygpIHtcblx0XHRpZiAoIXRoaXMucGFyc2VkRGF0YV8pIHtcblx0XHRcdHZhciB0b2tlbnMgPSBwYXJzZSh0aGlzLnBhdGgpO1xuXHRcdFx0dmFyIHJlZ2V4ID0gdG9SZWdleCh0b2tlbnMpO1xuXHRcdFx0dGhpcy5wYXJzZWREYXRhXyA9IHtcblx0XHRcdFx0cmVnZXgsXG5cdFx0XHRcdHRva2Vuc1xuXHRcdFx0fTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMucGFyc2VkRGF0YV87XG5cdH1cblxuXHQvKipcblx0ICogRXh0cmFjdHMgcGFyYW0gZGF0YSBmcm9tIHRoZSBnaXZlbiBwYXRoLCBhY2NvcmRpbmcgdG8gdGhpcyByb3V0ZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGggVGhlIHVybCBwYXRoIHRvIGV4dHJhY3QgcGFyYW1zIGZyb20uXG5cdCAqIEByZXR1cm4ge09iamVjdH0gVGhlIGV4dHJhY3RlZCBkYXRhLCBpZiB0aGUgcGF0aCBtYXRjaGVzIHRoaXMgcm91dGUsIG9yXG5cdCAqICAgICBudWxsIG90aGVyd2lzZS5cblx0ICovXG5cdGV4dHJhY3RQYXJhbXMocGF0aCkge1xuXHRcdGlmIChpc1N0cmluZyh0aGlzLnBhdGgpKSB7XG5cdFx0XHRyZXR1cm4gZXh0cmFjdERhdGEodGhpcy5idWlsZFBhcnNlZERhdGFfKCkudG9rZW5zLCBwYXRoKTtcblx0XHR9XG5cdFx0cmV0dXJuIHt9O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHJvdXRlIGhhbmRsZXIuXG5cdCAqIEByZXR1cm4geyFGdW5jdGlvbn1cblx0ICovXG5cdGdldEhhbmRsZXIoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaGFuZGxlcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByb3V0ZSBwYXRoLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfFJlZ0V4cHxGdW5jdGlvbn1cblx0ICovXG5cdGdldFBhdGgoKSB7XG5cdFx0cmV0dXJuIHRoaXMucGF0aDtcblx0fVxuXG5cdC8qKlxuIFx0ICogTWF0Y2hlcyBpZiB0aGUgcm91dGVyIGNhbiBoYW5kbGUgdGhlIHRlc3RlZCBwYXRoLlxuIFx0ICogQHBhcmFtIHshc3RyaW5nfSB2YWx1ZSBQYXRoIHRvIHRlc3QgKG1heSBjb250YWluIHRoZSBxdWVyeXN0cmluZyBwYXJ0KS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIG1hdGNoZXMgYW55IHJvdXRlLlxuXHQgKi9cblx0bWF0Y2hlc1BhdGgodmFsdWUpIHtcblx0XHR2YXIgcGF0aCA9IHRoaXMucGF0aDtcblxuXHRcdGlmIChpc0Z1bmN0aW9uKHBhdGgpKSB7XG5cdFx0XHRyZXR1cm4gcGF0aCh2YWx1ZSk7XG5cdFx0fVxuXHRcdGlmIChpc1N0cmluZyhwYXRoKSkge1xuXHRcdFx0cGF0aCA9IHRoaXMuYnVpbGRQYXJzZWREYXRhXygpLnJlZ2V4O1xuXHRcdH1cblx0XHRpZiAocGF0aCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuXHRcdFx0cmV0dXJuIHZhbHVlLnNlYXJjaChwYXRoKSA+IC0xO1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IFJvdXRlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlIH0gZnJvbSAnbWV0YWwnO1xuXG5jbGFzcyBDYWNoZWFibGUgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblxuXHQvKipcblx0ICogQWJzdHJhY3QgY2xhc3MgZm9yIGRlZmluaW5nIGNhY2hlYWJsZSBiZWhhdmlvci5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGNhY2hlZCBkYXRhLlxuXHRcdCAqIEB0eXBlIHshT2JqZWN0fVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5jYWNoZSA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB3aGV0aGVyIGNsYXNzIGlzIGNhY2hlYWJsZS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmNhY2hlYWJsZSA9IGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgY29udGVudCB0byB0aGUgY2FjaGUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBjb250ZW50IENvbnRlbnQgdG8gYmUgY2FjaGVkLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRhZGRDYWNoZShjb250ZW50KSB7XG5cdFx0aWYgKHRoaXMuY2FjaGVhYmxlKSB7XG5cdFx0XHR0aGlzLmNhY2hlID0gY29udGVudDtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQ2xlYXJzIHRoZSBjYWNoZS5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0Y2xlYXJDYWNoZSgpIHtcblx0XHR0aGlzLmNhY2hlID0gbnVsbDtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwb3NlcyBvZiB0aGlzIGluc3RhbmNlJ3Mgb2JqZWN0IHJlZmVyZW5jZXMuXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHRoaXMuY2xlYXJDYWNoZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGNhY2hlZCBjb250ZW50LlxuXHQgKiBAcmV0dXJuIHtPYmplY3R9IENhY2hlZCBjb250ZW50LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRnZXRDYWNoZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5jYWNoZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoZSBjbGFzcyBpcyBjYWNoZWFibGUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSB3aGVuIGNsYXNzIGlzIGNhY2hlYWJsZSwgZmFsc2Ugb3RoZXJ3aXNlLlxuXHQgKi9cblx0aXNDYWNoZWFibGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY2FjaGVhYmxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgd2hldGhlciB0aGUgY2xhc3MgaXMgY2FjaGVhYmxlLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IGNhY2hlYWJsZVxuXHQgKi9cblx0c2V0Q2FjaGVhYmxlKGNhY2hlYWJsZSkge1xuXHRcdGlmICghY2FjaGVhYmxlKSB7XG5cdFx0XHR0aGlzLmNsZWFyQ2FjaGUoKTtcblx0XHR9XG5cdFx0dGhpcy5jYWNoZWFibGUgPSBjYWNoZWFibGU7XG5cdH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBDYWNoZWFibGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGdldFVpZCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7IGdsb2JhbEV2YWwgfSBmcm9tICdtZXRhbC1kb20nO1xuaW1wb3J0IENhY2hlYWJsZSBmcm9tICcuLi9jYWNoZWFibGUvQ2FjaGVhYmxlJztcbmltcG9ydCBDYW5jZWxsYWJsZVByb21pc2UgZnJvbSAnbWV0YWwtcHJvbWlzZSc7XG5cbmNsYXNzIFNjcmVlbiBleHRlbmRzIENhY2hlYWJsZSB7XG5cblx0LyoqXG5cdCAqIFNjcmVlbiBjbGFzcyBpcyBhIHNwZWNpYWwgdHlwZSBvZiByb3V0ZSBoYW5kbGVyIHRoYXQgcHJvdmlkZXMgaGVscGVyXG5cdCAqIHV0aWxpdGllcyB0aGF0IGFkZHMgbGlmZWN5Y2xlIGFuZCBtZXRob2RzIHRvIHByb3ZpZGUgY29udGVudCB0byBlYWNoXG5cdCAqIHJlZ2lzdGVyZWQgc3VyZmFjZS5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqIEBleHRlbmRzIHtDYWNoZWFibGV9XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHNjcmVlbiBpZC5cblx0XHQgKiBAdHlwZSB7c3RyaW5nfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmlkID0gdGhpcy5tYWtlSWRfKGdldFVpZCgpKTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBzY3JlZW4gdGl0bGUuIFJlbGV2YW50IHdoZW4gdGhlIHBhZ2UgdGl0bGUgc2hvdWxkIGJlXG5cdFx0ICogdXBhZGF0ZWQgd2hlbiBzY3JlZW4gaXMgcmVuZGVyZWQuXG5cdFx0ICogQHR5cGUgez9zdHJpbmc9fVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy50aXRsZSA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogRmlyZXMgd2hlbiB0aGUgc2NyZWVuIGlzIGFjdGl2ZS4gQWxsb3dzIGEgc2NyZWVuIHRvIHBlcmZvcm0gYW55IHNldHVwXG5cdCAqIHRoYXQgcmVxdWlyZXMgaXRzIERPTSB0byBiZSB2aXNpYmxlLiBMaWZlY3ljbGUuXG5cdCAqL1xuXHRhY3RpdmF0ZSgpIHtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGFjdGl2YXRlJyk7XG5cdH1cblxuXHQvKipcblx0ICogR2l2ZXMgdGhlIFNjcmVlbiBhIGNoYW5jZSB0byBjYW5jZWwgdGhlIG5hdmlnYXRpb24gYW5kIHN0b3AgaXRzZWxmIGZyb21cblx0ICogYmVpbmcgZGVhY3RpdmF0ZWQuIENhbiBiZSB1c2VkLCBmb3IgZXhhbXBsZSwgaWYgdGhlIHNjcmVlbiBoYXMgdW5zYXZlZFxuXHQgKiBzdGF0ZS4gTGlmZWN5Y2xlLiBDbGVhbi11cCBzaG91bGQgbm90IGJlIHByZWZvcm1lZCBoZXJlLCBzaW5jZSB0aGVcblx0ICogbmF2aWdhdGlvbiBtYXkgc3RpbGwgYmUgY2FuY2VsbGVkLiBEbyBjbGVhbi11cCBpbiBkZWFjdGl2YXRlLlxuXHQgKiBAcmV0dXJuIHtib29sZWFuPX0gSWYgcmV0dXJucyB0cnVlLCB0aGUgY3VycmVudCBzY3JlZW4gaXMgbG9ja2VkIGFuZCB0aGVcblx0ICogICAgIG5leHQgbmFnaXZhdGlvbiBpbnRlcnJ1cHRlZC5cblx0ICovXG5cdGJlZm9yZURlYWN0aXZhdGUoKSB7XG5cdFx0Y29uc29sZS5sb2coJ1NjcmVlbiBbJyArIHRoaXMgKyAnXSBiZWZvcmVEZWFjdGl2YXRlJyk7XG5cdH1cblxuXHQvKipcblx0ICogR2l2ZXMgdGhlIFNjcmVlbiBhIGNoYW5jZSBmb3JtYXQgdGhlIHBhdGggYmVmb3JlIGhpc3RvcnkgdXBkYXRlLlxuXHQgKiBAcGF0aCB7IXN0cmluZ30gcGF0aCBOYXZpZ2F0aW9uIHBhdGguXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9IE5hdmlnYXRpb24gcGF0aCB0byB1c2Ugb24gaGlzdG9yeS5cblx0ICovXG5cdGJlZm9yZVVwZGF0ZUhpc3RvcnlQYXRoKHBhdGgpIHtcblx0XHRyZXR1cm4gcGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHaXZlcyB0aGUgU2NyZWVuIGEgY2hhbmNlIGZvcm1hdCB0aGUgc3RhdGUgYmVmb3JlIGhpc3RvcnkgdXBkYXRlLlxuXHQgKiBAcGF0aCB7IW9iamVjdH0gc3RhdGUgSGlzdG9yeSBzdGF0ZS5cblx0ICogQHJldHVybiB7IW9iamVjdH0gSGlzdG9yeSBzdGF0ZSB0byB1c2Ugb24gaGlzdG9yeS5cblx0ICovXG5cdGJlZm9yZVVwZGF0ZUhpc3RvcnlTdGF0ZShzdGF0ZSkge1xuXHRcdHJldHVybiBzdGF0ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGxvd3MgYSBzY3JlZW4gdG8gZG8gYW55IGNsZWFudXAgbmVjZXNzYXJ5IGFmdGVyIGl0IGhhcyBiZWVuXG5cdCAqIGRlYWN0aXZhdGVkLCBmb3IgZXhhbXBsZSBjYW5jZWxsaW5nIG91dHN0YW5kaW5nIHJlcXVlc3RzIG9yIHN0b3BwaW5nXG5cdCAqIHRpbWVycy4gTGlmZWN5Y2xlLlxuXHQgKi9cblx0ZGVhY3RpdmF0ZSgpIHtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGRlYWN0aXZhdGUnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwb3NlIGEgc2NyZWVuLCBlaXRoZXIgYWZ0ZXIgaXQgaXMgZGVhY3RpdmF0ZWQgKGluIHRoZSBjYXNlIG9mIGFcblx0ICogbm9uLWNhY2hlYWJsZSB2aWV3KSBvciB3aGVuIHRoZSBBcHAgaXMgaXRzZWxmIGRpc3Bvc2VkIGZvciB3aGF0ZXZlclxuXHQgKiByZWFzb24uIExpZmVjeWNsZS5cblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHRzdXBlci5kaXNwb3NlSW50ZXJuYWwoKTtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGRpc3Bvc2UnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGxvd3MgYSBzY3JlZW4gdG8gZXZhbHVhdGUgc2NyaXB0cyBiZWZvcmUgdGhlIGVsZW1lbnQgaXMgbWFkZSB2aXNpYmxlLlxuXHQgKiBMaWZlY3ljbGUuXG5cdCAqIEBwYXJhbSB7IW9iamVjdH0gc3VyZmFjZXMgTWFwIG9mIHN1cmZhY2VzIHRvIGZsaXAga2V5ZWQgYnkgc3VyZmFjZSBpZC5cblx0ICogQHJldHVybiB7P0NhbmNlbGxhYmxlUHJvbWlzZT19IFRoaXMgY2FuIHJldHVybiBhIHByb21pc2UsIHdoaWNoIHdpbGxcblx0ICogICAgIHBhdXNlIHRoZSBuYXZpZ2F0aW9uIHVudGlsIGl0IGlzIHJlc29sdmVkLlxuXHQgKi9cblx0ZXZhbHVhdGVTY3JpcHRzKHN1cmZhY2VzKSB7XG5cdFx0T2JqZWN0LmtleXMoc3VyZmFjZXMpLmZvckVhY2goc0lkID0+IHtcblx0XHRcdGlmIChzdXJmYWNlc1tzSWRdLmFjdGl2ZUNoaWxkKSB7XG5cdFx0XHRcdGdsb2JhbEV2YWwucnVuU2NyaXB0c0luRWxlbWVudChzdXJmYWNlc1tzSWRdLmFjdGl2ZUNoaWxkKTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGxvd3MgYSBzY3JlZW4gdG8gZXZhbHVhdGUgc3R5bGVzIGJlZm9yZSB0aGUgZWxlbWVudCBpcyBtYWRlIHZpc2libGUuXG5cdCAqIExpZmVjeWNsZS5cblx0ICogQHBhcmFtIHshb2JqZWN0fSBzdXJmYWNlcyBNYXAgb2Ygc3VyZmFjZXMgdG8gZmxpcCBrZXllZCBieSBzdXJmYWNlIGlkLlxuXHQgKiBAcmV0dXJuIHs/Q2FuY2VsbGFibGVQcm9taXNlPX0gVGhpcyBjYW4gcmV0dXJuIGEgcHJvbWlzZSwgd2hpY2ggd2lsbFxuXHQgKiAgICAgcGF1c2UgdGhlIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHRldmFsdWF0ZVN0eWxlcygpIHtcblx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGxvd3MgYSBzY3JlZW4gdG8gcGVyZm9ybSBhbnkgc2V0dXAgaW1tZWRpYXRlbHkgYmVmb3JlIHRoZSBlbGVtZW50IGlzXG5cdCAqIG1hZGUgdmlzaWJsZS4gTGlmZWN5Y2xlLlxuXHQgKiBAcGFyYW0geyFvYmplY3R9IHN1cmZhY2VzIE1hcCBvZiBzdXJmYWNlcyB0byBmbGlwIGtleWVkIGJ5IHN1cmZhY2UgaWQuXG5cdCAqIEByZXR1cm4gez9DYW5jZWxsYWJsZVByb21pc2U9fSBUaGlzIGNhbiByZXR1cm4gYSBwcm9taXNlLCB3aGljaCB3aWxsIHBhdXNlIHRoZVxuXHQgKiAgICAgbmF2aWdhdGlvbiB1bnRpbCBpdCBpcyByZXNvbHZlZC5cblx0ICovXG5cdGZsaXAoc3VyZmFjZXMpIHtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGZsaXAnKTtcblxuXHRcdHZhciB0cmFuc2l0aW9ucyA9IFtdO1xuXG5cdFx0T2JqZWN0LmtleXMoc3VyZmFjZXMpLmZvckVhY2goc0lkID0+IHtcblx0XHRcdHZhciBzdXJmYWNlID0gc3VyZmFjZXNbc0lkXTtcblx0XHRcdHZhciBkZWZlcnJlZCA9IHN1cmZhY2Uuc2hvdyh0aGlzLmlkKTtcblx0XHRcdHRyYW5zaXRpb25zLnB1c2goZGVmZXJyZWQpO1xuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIENhbmNlbGxhYmxlUHJvbWlzZS5hbGwodHJhbnNpdGlvbnMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHNjcmVlbiBpZC5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0SWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaWQ7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgY29udGVudCBmb3IgdGhlIGdpdmVuIHN1cmZhY2UsIG9yIG51bGwgaWYgdGhlIHN1cmZhY2UgaXNuJ3Rcblx0ICogdXNlZCBieSB0aGlzIHNjcmVlbi4gVGhpcyB3aWxsIGJlIGNhbGxlZCB3aGVuIGEgc2NyZWVuIGlzIGluaXRpYWxseVxuXHQgKiBjb25zdHJ1Y3RlZCBvciwgaWYgYSBzY3JlZW4gaXMgbm9uLWNhY2hlYWJsZSwgd2hlbiBuYXZpZ2F0ZWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc3VyZmFjZUlkIFRoZSBpZCBvZiB0aGUgc3VyZmFjZSBET00gZWxlbWVudC5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBwYXJhbXMgUGFyYW1zIGV4dHJhY3RlZCBmcm9tIHRoZSBjdXJyZW50IHBhdGguXG5cdCAqIEByZXR1cm4gez9zdHJpbmd8RWxlbWVudD19IFRoaXMgY2FuIHJldHVybiBhIHN0cmluZyBvciBub2RlIHJlcHJlc2VudGluZ1xuXHQgKiAgICAgdGhlIGNvbnRlbnQgb2YgdGhlIHN1cmZhY2UuIElmIHJldHVybnMgZmFsc3kgdmFsdWVzIHN1cmZhY2UgZGVmYXVsdFxuXHQgKiAgICAgY29udGVudCBpcyByZXN0b3JlZC5cblx0ICovXG5cdGdldFN1cmZhY2VDb250ZW50KCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZ2V0U3VyZmFjZUNvbnRlbnQnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzY3JlZW4gdGl0bGUuXG5cdCAqIEByZXR1cm4gez9zdHJpbmc9fVxuXHQgKi9cblx0Z2V0VGl0bGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMudGl0bGU7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbGwgY29udGVudHMgZm9yIHRoZSBzdXJmYWNlcy4gVGhpcyB3aWxsIHBhc3MgdGhlIGxvYWRlZCBjb250ZW50XG5cdCAqIHRvIDxjb2RlPlNjcmVlbi5sb2FkPC9jb2RlPiB3aXRoIGFsbCBpbmZvcm1hdGlvbiB5b3Vcblx0ICogbmVlZCB0byBmdWxmaWxsIHRoZSBzdXJmYWNlcy4gTGlmZWN5Y2xlLlxuXHQgKiBAcGFyYW0geyFzdHJpbmc9fSBwYXRoIFRoZSByZXF1ZXN0ZWQgcGF0aC5cblx0ICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZX0gVGhpcyBjYW4gcmV0dXJuIGEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGVcblx0ICogICAgIGNvbnRlbnRzIG9mIHRoZSBzdXJmYWNlcyBvciBhIHByb21pc2UsIHdoaWNoIHdpbGwgcGF1c2UgdGhlIG5hdmlnYXRpb25cblx0ICogICAgIHVudGlsIGl0IGlzIHJlc29sdmVkLiBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9hZGluZyBhc3luYyBjb250ZW50LlxuXHQgKi9cblx0bG9hZCgpIHtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGxvYWQnKTtcblx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYWtlcyB0aGUgaWQgZm9yIHRoZSBzY3JlZW4uXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaWQgVGhlIHNjcmVlbiBpZCB0aGUgY29udGVudCBiZWxvbmdzIHRvby5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0bWFrZUlkXyhpZCkge1xuXHRcdHJldHVybiAnc2NyZWVuXycgKyBpZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBzY3JlZW4gaWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaWRcblx0ICovXG5cdHNldElkKGlkKSB7XG5cdFx0dGhpcy5pZCA9IGlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHNjcmVlbiB0aXRsZS5cblx0ICogQHBhcmFtIHs/c3RyaW5nPX0gdGl0bGVcblx0ICovXG5cdHNldFRpdGxlKHRpdGxlKSB7XG5cdFx0dGhpcy50aXRsZSA9IHRpdGxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdHRvU3RyaW5nKCkge1xuXHRcdHJldHVybiB0aGlzLmlkO1xuXHR9XG5cbn1cblxuLyoqXG4gKiBAcGFyYW0geyp9IG9iamVjdFxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciBhIGdpdmVuIGluc3RhbmNlIGltcGxlbWVudHNcbiAqIDxjb2RlPlNjcmVlbjwvY29kZT4uXG4gKi9cblNjcmVlbi5pc0ltcGxlbWVudGVkQnkgPSBmdW5jdGlvbihvYmplY3QpIHtcblx0cmV0dXJuIG9iamVjdCBpbnN0YW5jZW9mIFNjcmVlbjtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IFNjcmVlbjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IGdsb2JhbHMgZnJvbSAnLi4vZ2xvYmFscy9nbG9iYWxzJztcbmltcG9ydCB7IERpc3Bvc2FibGUsIGlzRGVmQW5kTm90TnVsbCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7IGFwcGVuZCwgcmVtb3ZlQ2hpbGRyZW4sIGV4aXREb2N1bWVudCB9IGZyb20gJ21ldGFsLWRvbSc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuXG5jbGFzcyBTdXJmYWNlIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cblx0LyoqXG5cdCAqIFN1cmZhY2UgY2xhc3MgcmVwcmVzZW50aW5nIHRoZSByZWZlcmVuY2VzIHRvIGVsZW1lbnRzIG9uIHRoZSBwYWdlIHRoYXRcblx0ICogY2FuIHBvdGVudGlhbGx5IGJlIHVwZGF0ZWQgYnkgPGNvZGU+QXBwPC9jb2RlPi5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGlkXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoaWQpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0aWYgKCFpZCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTdXJmYWNlIGVsZW1lbnQgaWQgbm90IHNwZWNpZmllZC4gQSBzdXJmYWNlIGVsZW1lbnQgcmVxdWlyZXMgYSB2YWxpZCBpZC4nKTtcblx0XHR9XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgYWN0aXZlIGNoaWxkIGVsZW1lbnQuXG5cdFx0ICogQHR5cGUge0VsZW1lbnR9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmFjdGl2ZUNoaWxkID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBkZWZhdWx0IGNoaWxkIGVsZW1lbnQuXG5cdFx0ICogQHR5cGUge0VsZW1lbnR9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmRlZmF1bHRDaGlsZCA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgZWxlbWVudCB3aXRoIHRoZSBzcGVjaWZpZWQgc3VyZmFjZSBpZCwgaWYgbm90IGZvdW5kIGNyZWF0ZXMgYVxuXHRcdCAqIG5ldyBlbGVtZW50IHdpdGggdGhlIHNwZWNpZmllZCBpZC5cblx0XHQgKiBAdHlwZSB7RWxlbWVudH1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZWxlbWVudCA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgc3VyZmFjZSBpZC5cblx0XHQgKiBAdHlwZSB7U3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5pZCA9IGlkO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGRlZmF1bHQgdHJhbnNpdGlvbkZuIGZvciB0aGUgc3VyZmFjZXMuXG5cdFx0ICogQHBhcmFtIHs/RWxlbWVudD19IGZyb20gVGhlIHZpc2libGUgc3VyZmFjZSBlbGVtZW50LlxuXHRcdCAqIEBwYXJhbSB7P0VsZW1lbnQ9fSB0byBUaGUgc3VyZmFjZSBlbGVtZW50IHRvIGJlIGZsaXBwZWQuXG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdHRoaXMudHJhbnNpdGlvbkZuID0gbnVsbDtcblxuXHRcdHRoaXMuZGVmYXVsdENoaWxkID0gdGhpcy5nZXRDaGlsZChTdXJmYWNlLkRFRkFVTFQpO1xuXHRcdHRoaXMubWF5YmVXcmFwQ29udGVudEFzRGVmYXVsdF8oKTtcblx0XHR0aGlzLmFjdGl2ZUNoaWxkID0gdGhpcy5kZWZhdWx0Q2hpbGQ7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBzY3JlZW4gY29udGVudCB0byBhIHN1cmZhY2UuIElmIGNvbnRlbnQgaGFzbid0IGJlZW4gcGFzc2VkLCBzZWUgaWZcblx0ICogYW4gZWxlbWVudCBleGlzdHMgaW4gdGhlIERPTSB0aGF0IG1hdGNoZXMgdGhlIGlkLiBCeSBjb252ZW50aW9uLCB0aGVcblx0ICogZWxlbWVudCBzaG91bGQgYWxyZWFkeSBiZSBuZXN0ZWQgaW4gdGhlIHJpZ2h0IGVsZW1lbnQgYW5kIHNob3VsZCBoYXZlIGFuXG5cdCAqIGlkIHRoYXQgaXMgYSBjb25jYXRlbnRhdGlvbiBvZiB0aGUgc3VyZmFjZSBpZCArICctJyArIHRoZSBzY3JlZW4gaWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2NyZWVuSWQgVGhlIHNjcmVlbiBpZCB0aGUgY29udGVudCBiZWxvbmdzIHRvby5cblx0ICogQHBhcmFtIHs/c3RyaW5nfEVsZW1lbnQ9fSBvcHRfY29udGVudCBUaGUgc3RyaW5nIGNvbnRlbnQgb3IgZWxlbWVudCB0b1xuXHQgKiAgICAgYWRkIGJlIGFkZGVkIGFzIHN1cmZhY2UgY29udGVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH1cblx0ICovXG5cdGFkZENvbnRlbnQoc2NyZWVuSWQsIG9wdF9jb250ZW50KSB7XG5cdFx0dmFyIGNoaWxkID0gdGhpcy5kZWZhdWx0Q2hpbGQ7XG5cblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKG9wdF9jb250ZW50KSkge1xuXHRcdFx0Y2hpbGQgPSB0aGlzLmdldENoaWxkKHNjcmVlbklkKTtcblx0XHRcdGlmIChjaGlsZCkge1xuXHRcdFx0XHRyZW1vdmVDaGlsZHJlbihjaGlsZCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjaGlsZCA9IHRoaXMuY3JlYXRlQ2hpbGQoc2NyZWVuSWQpO1xuXHRcdFx0XHR0aGlzLnRyYW5zaXRpb24oY2hpbGQsIG51bGwpO1xuXHRcdFx0fVxuXHRcdFx0YXBwZW5kKGNoaWxkLCBvcHRfY29udGVudCk7XG5cdFx0fVxuXG5cdFx0dmFyIGVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnQoKTtcblxuXHRcdGlmIChlbGVtZW50ICYmIGNoaWxkKSB7XG5cdFx0XHRhcHBlbmQoZWxlbWVudCwgY2hpbGQpO1xuXHRcdH1cblxuXHRcdHJldHVybiBjaGlsZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGNoaWxkIG5vZGUgZm9yIHRoZSBzdXJmYWNlLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQuXG5cdCAqIEByZXR1cm4ge0VsZW1lbnR9XG5cdCAqL1xuXHRjcmVhdGVDaGlsZChzY3JlZW5JZCkge1xuXHRcdHZhciBjaGlsZCA9IGdsb2JhbHMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cdFx0Y2hpbGQuc2V0QXR0cmlidXRlKCdpZCcsIHRoaXMubWFrZUlkXyhzY3JlZW5JZCkpO1xuXHRcdHJldHVybiBjaGlsZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGNoaWxkIG5vZGUgb2YgdGhlIHN1cmZhY2UuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2NyZWVuSWQgVGhlIHNjcmVlbiBpZC5cblx0ICogQHJldHVybiB7P0VsZW1lbnR9XG5cdCAqL1xuXHRnZXRDaGlsZChzY3JlZW5JZCkge1xuXHRcdHJldHVybiBnbG9iYWxzLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMubWFrZUlkXyhzY3JlZW5JZCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHN1cmZhY2UgZWxlbWVudCBmcm9tIGVsZW1lbnQsIGFuZCBzZXRzIGl0IHRvIHRoZSBlbCBwcm9wZXJ0eSBvZlxuXHQgKiB0aGUgY3VycmVudCBpbnN0YW5jZS5cblx0ICogPGNvZGU+dGhpcy5lbGVtZW50PC9jb2RlPiB3aWxsIGJlIHVzZWQuXG5cdCAqIEByZXR1cm4gez9FbGVtZW50fSBUaGUgY3VycmVudCBzdXJmYWNlIGVsZW1lbnQuXG5cdCAqL1xuXHRnZXRFbGVtZW50KCkge1xuXHRcdGlmICh0aGlzLmVsZW1lbnQpIHtcblx0XHRcdHJldHVybiB0aGlzLmVsZW1lbnQ7XG5cdFx0fVxuXHRcdHRoaXMuZWxlbWVudCA9IGdsb2JhbHMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5pZCk7XG5cdFx0cmV0dXJuIHRoaXMuZWxlbWVudDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzdXJmYWNlIGlkLlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqL1xuXHRnZXRJZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBzdXJmYWNlIHRyYW5zaXRpb24gZnVuY3Rpb24uXG5cdCAqIFNlZSA8Y29kZT5TdXJmYWNlLmRlZmF1bHRUcmFuc2l0aW9uPC9jb2RlPi5cblx0ICogQHJldHVybiB7P0Z1bmN0aW9uPX0gVGhlIHRyYW5zaXRpb24gZnVuY3Rpb24uXG5cdCAqL1xuXHRnZXRUcmFuc2l0aW9uRm4oKSB7XG5cdFx0cmV0dXJuIHRoaXMudHJhbnNpdGlvbkZuO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIHRoZSBpZCBmb3IgdGhlIGVsZW1lbnQgdGhhdCBob2xkcyBjb250ZW50IGZvciBhIHNjcmVlbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzY3JlZW5JZCBUaGUgc2NyZWVuIGlkIHRoZSBjb250ZW50IGJlbG9uZ3MgdG9vLlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRtYWtlSWRfKHNjcmVlbklkKSB7XG5cdFx0cmV0dXJuIHRoaXMuaWQgKyAnLScgKyBzY3JlZW5JZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZiBkZWZhdWx0IGNoaWxkIGlzIG1pc3NpbmcsIHdyYXBzIHN1cmZhY2UgY29udGVudCBhcyBkZWZhdWx0IGNoaWxkLiBJZlxuXHQgKiBzdXJmYWNlIGhhdmUgc3RhdGljIGNvbnRlbnQsIG1ha2Ugc3VyZSB0byBwbGFjZSBhXG5cdCAqIDxjb2RlPnN1cmZhY2VJZC1kZWZhdWx0PC9jb2RlPiBlbGVtZW50IGluc2lkZSBzdXJmYWNlLCBvbmx5IGNvbnRlbnRzXG5cdCAqIGluc2lkZSB0aGUgZGVmYXVsdCBjaGlsZCB3aWxsIGJlIHJlcGxhY2VkIGJ5IG5hdmlnYXRpb24uXG5cdCAqL1xuXHRtYXliZVdyYXBDb250ZW50QXNEZWZhdWx0XygpIHtcblx0XHR2YXIgZWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudCgpO1xuXHRcdGlmIChlbGVtZW50ICYmICF0aGlzLmRlZmF1bHRDaGlsZCkge1xuXHRcdFx0dmFyIGZyYWdtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cdFx0XHR3aGlsZSAoZWxlbWVudC5maXJzdENoaWxkKSB7XG5cdFx0XHRcdGZyYWdtZW50LmFwcGVuZENoaWxkKGVsZW1lbnQuZmlyc3RDaGlsZCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmRlZmF1bHRDaGlsZCA9IHRoaXMuYWRkQ29udGVudChTdXJmYWNlLkRFRkFVTFQsIGZyYWdtZW50KTtcblx0XHRcdHRoaXMudHJhbnNpdGlvbihudWxsLCB0aGlzLmRlZmF1bHRDaGlsZCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHN1cmZhY2UgaWQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaWRcblx0ICovXG5cdHNldElkKGlkKSB7XG5cdFx0dGhpcy5pZCA9IGlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHN1cmZhY2UgdHJhbnNpdGlvbiBmdW5jdGlvbi5cblx0ICogU2VlIDxjb2RlPlN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb248L2NvZGU+LlxuXHQgKiBAcGFyYW0gez9GdW5jdGlvbj19IHRyYW5zaXRpb25GbiBUaGUgdHJhbnNpdGlvbiBmdW5jdGlvbi5cblx0ICovXG5cdHNldFRyYW5zaXRpb25Gbih0cmFuc2l0aW9uRm4pIHtcblx0XHR0aGlzLnRyYW5zaXRpb25GbiA9IHRyYW5zaXRpb25Gbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBTaG93cyBzY3JlZW4gY29udGVudCBmcm9tIGEgc3VyZmFjZS5cblx0ICogQHBhcmFtIHtTdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQgdG8gc2hvdy5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBQYXVzZXMgdGhlIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHRzaG93KHNjcmVlbklkKSB7XG5cdFx0dmFyIGZyb20gPSB0aGlzLmFjdGl2ZUNoaWxkO1xuXHRcdHZhciB0byA9IHRoaXMuZ2V0Q2hpbGQoc2NyZWVuSWQpO1xuXHRcdGlmICghdG8pIHtcblx0XHRcdHRvID0gdGhpcy5kZWZhdWx0Q2hpbGQ7XG5cdFx0fVxuXHRcdHRoaXMuYWN0aXZlQ2hpbGQgPSB0bztcblx0XHRyZXR1cm4gdGhpcy50cmFuc2l0aW9uKGZyb20sIHRvKS50aGVuQWx3YXlzKCgpID0+IHtcblx0XHRcdGlmIChmcm9tICYmIGZyb20gIT09IHRvKSB7XG5cdFx0XHRcdGV4aXREb2N1bWVudChmcm9tKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHNjcmVlbiBjb250ZW50IGZyb20gYSBzdXJmYWNlLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQgdG8gcmVtb3ZlLlxuXHQgKi9cblx0cmVtb3ZlKHNjcmVlbklkKSB7XG5cdFx0dmFyIGNoaWxkID0gdGhpcy5nZXRDaGlsZChzY3JlZW5JZCk7XG5cdFx0aWYgKGNoaWxkKSB7XG5cdFx0XHRleGl0RG9jdW1lbnQoY2hpbGQpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9XG5cdCAqL1xuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbnZva2VzIHRoZSB0cmFuc2l0aW9uIGZ1bmN0aW9uIHNwZWNpZmllZCBvbiA8Y29kZT50cmFuc2l0aW9uPC9jb2RlPiBhdHRyaWJ1dGUuXG5cdCAqIEBwYXJhbSB7P0VsZW1lbnQ9fSBmcm9tXG5cdCAqIEBwYXJhbSB7P0VsZW1lbnQ9fSB0b1xuXHQgKiBAcmV0dXJuIHs/Q2FuY2VsbGFibGVQcm9taXNlPX0gVGhpcyBjYW4gcmV0dXJuIGEgcHJvbWlzZSwgd2hpY2ggd2lsbCBwYXVzZSB0aGVcblx0ICogICAgIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHR0cmFuc2l0aW9uKGZyb20sIHRvKSB7XG5cdFx0dmFyIHRyYW5zaXRpb25GbiA9IHRoaXMudHJhbnNpdGlvbkZuIHx8IFN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb247XG5cdFx0cmV0dXJuIENhbmNlbGxhYmxlUHJvbWlzZS5yZXNvbHZlKHRyYW5zaXRpb25Gbi5jYWxsKHRoaXMsIGZyb20sIHRvKSk7XG5cdH1cblxufVxuXG4vKipcbiAgICogSG9sZHMgdGhlIGRlZmF1bHQgc3VyZmFjZSBuYW1lLiBFbGVtZW50cyBvbiB0aGUgcGFnZSBtdXN0IGNvbnRhaW4gYSBjaGlsZFxuICAgKiBlbGVtZW50IGNvbnRhaW5pbmcgdGhlIGRlZmF1bHQgY29udGVudCwgdGhpcyBlbGVtZW50IG11c3QgYmUgYXMgZm9sbG93aW5nOlxuICAgKlxuICAgKiBFeGFtcGxlOlxuICAgKiA8Y29kZT5cbiAgICogICA8ZGl2IGlkPVwibXlzdXJmYWNlXCI+XG4gICAqICAgICA8ZGl2IGlkPVwibXlzdXJmYWNlLWRlZmF1bHRcIj5EZWZhdWx0IHN1cmZhY2UgY29udGVudC48L2Rpdj5cbiAgICogICA8L2Rpdj5cbiAgICogPC9jb2RlPlxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCBjb250ZW50IGlzIHJlbGV2YW50IGZvciB0aGUgaW5pdGlhbCBwYWdlIGNvbnRlbnQuIFdoZW4gYVxuICAgKiBzY3JlZW4gZG9lc24ndCBwcm92aWRlIGNvbnRlbnQgZm9yIHRoZSBzdXJmYWNlIHRoZSBkZWZhdWx0IGNvbnRlbnQgaXNcbiAgICogcmVzdG9yZWQgaW50byB0aGUgcGFnZS5cbiAgICpcbiAgICogQHR5cGUgeyFTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQHN0YXRpY1xuICAgKi9cblN1cmZhY2UuREVGQVVMVCA9ICdkZWZhdWx0JztcblxuLyoqXG4gKiBIb2xkcyB0aGUgZGVmYXVsdCB0cmFuc2l0aW9uIGZvciBhbGwgc3VyZmFjZXMuIEVhY2ggc3VyZmFjZSBjb3VsZCBoYXZlIGl0c1xuICogb3duIHRyYW5zaXRpb24uXG4gKlxuICogRXhhbXBsZTpcbiAqXG4gKiA8Y29kZT5cbiAqIHN1cmZhY2Uuc2V0VHJhbnNpdGlvbkZuKGZ1bmN0aW9uKGZyb20sIHRvKSB7XG4gKiAgIGlmIChmcm9tKSB7XG4gKiAgICAgZnJvbS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICogICAgIGZyb20uY2xhc3NMaXN0LnJlbW92ZSgnZmxpcHBlZCcpO1xuICogICB9XG4gKiAgIGlmICh0bykge1xuICogICAgIHRvLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICogICAgIHRvLmNsYXNzTGlzdC5hZGQoJ2ZsaXBwZWQnKTtcbiAqICAgfVxuICogICByZXR1cm4gbnVsbDtcbiAqIH0pO1xuICogPC9jb2RlPlxuICpcbiAqIEBwYXJhbSB7P0VsZW1lbnQ9fSBmcm9tIFRoZSB2aXNpYmxlIHN1cmZhY2UgZWxlbWVudC5cbiAqIEBwYXJhbSB7P0VsZW1lbnQ9fSB0byBUaGUgc3VyZmFjZSBlbGVtZW50IHRvIGJlIGZsaXBwZWQuXG4gKiBAc3RhdGljXG4gKi9cblN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb24gPSBmdW5jdGlvbihmcm9tLCB0bykge1xuXHRpZiAoZnJvbSkge1xuXHRcdGZyb20uc3R5bGUuZGlzcGxheSA9ICdub25lJztcblx0XHRmcm9tLmNsYXNzTGlzdC5yZW1vdmUoJ2ZsaXBwZWQnKTtcblx0fVxuXHRpZiAodG8pIHtcblx0XHR0by5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblx0XHR0by5jbGFzc0xpc3QuYWRkKCdmbGlwcGVkJyk7XG5cdH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IFN1cmZhY2U7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGFkZENsYXNzZXMsIGRlbGVnYXRlLCBtYXRjaCwgb24sIHJlbW92ZUNsYXNzZXMgfSBmcm9tICdtZXRhbC1kb20nO1xuaW1wb3J0IHsgYXJyYXksIGFzeW5jLCBpc0RlZkFuZE5vdE51bGwsIGlzU3RyaW5nIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyLCBFdmVudEhhbmRsZXIgfSBmcm9tICdtZXRhbC1ldmVudHMnO1xuaW1wb3J0IENhbmNlbGxhYmxlUHJvbWlzZSBmcm9tICdtZXRhbC1wcm9taXNlJztcbmltcG9ydCBkZWJvdW5jZSBmcm9tICdtZXRhbC1kZWJvdW5jZSc7XG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IFJvdXRlIGZyb20gJy4uL3JvdXRlL1JvdXRlJztcbmltcG9ydCBTY3JlZW4gZnJvbSAnLi4vc2NyZWVuL1NjcmVlbic7XG5pbXBvcnQgU3VyZmFjZSBmcm9tICcuLi9zdXJmYWNlL1N1cmZhY2UnO1xuaW1wb3J0IFVyaSBmcm9tICdtZXRhbC11cmknO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4uL3V0aWxzL3V0aWxzJztcblxuY2xhc3MgQXBwIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcblxuXHQvKipcblx0ICogQXBwIGNsYXNzIHRoYXQgaGFuZGxlIHJvdXRlcyBhbmQgc2NyZWVucyBsaWZlY3ljbGUuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKiBAZXh0ZW5kcyB7RXZlbnRFbWl0dGVyfVxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBhY3RpdmUgc2NyZWVuLlxuXHRcdCAqIEB0eXBlIHs/U2NyZWVufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmFjdGl2ZVNjcmVlbiA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgYWN0aXZlIHBhdGggY29udGFpbmluZyB0aGUgcXVlcnkgcGFyYW1ldGVycy5cblx0XHQgKiBAdHlwZSB7P3N0cmluZ31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5hY3RpdmVQYXRoID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEFsbG93cyBwcmV2ZW50IG5hdmlnYXRlIGZyb20gZG9tIHByZXZlbnRlZCBldmVudC5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCB0cnVlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYWxsb3dQcmV2ZW50TmF2aWdhdGUgPSB0cnVlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgbGluayBiYXNlIHBhdGguXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgJydcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5iYXNlUGF0aCA9ICcnO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHZhbHVlIG9mIHRoZSBicm93c2VyIHBhdGggYmVmb3JlIGEgbmF2aWdhdGlvbiBpcyBwZXJmb3JtZWQuXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgdGhlIGN1cnJlbnQgYnJvd3NlciBwYXRoLlxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmJyb3dzZXJQYXRoQmVmb3JlTmF2aWdhdGUgPSB1dGlscy5nZXRDdXJyZW50QnJvd3NlclBhdGhXaXRob3V0SGFzaCgpO1xuXG5cdFx0LyoqXG5cdFx0ICogQ2FwdHVyZXMgc2Nyb2xsIHBvc2l0aW9uIGZyb20gc2Nyb2xsIGV2ZW50LlxuXHRcdCAqIEB0eXBlIHshYm9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCB0cnVlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuY2FwdHVyZVNjcm9sbFBvc2l0aW9uRnJvbVNjcm9sbEV2ZW50ID0gdHJ1ZTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBkZWZhdWx0IHBhZ2UgdGl0bGUuXG5cdFx0ICogQHR5cGUge3N0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZGVmYXVsdFRpdGxlID0gZ2xvYmFscy5kb2N1bWVudC50aXRsZTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBmb3JtIHNlbGVjdG9yIHRvIGRlZmluZSBmb3JtcyB0aGF0IGFyZSByb3V0ZWQuXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgZm9ybVtlbmN0eXBlPVwibXVsdGlwYXJ0L2Zvcm0tZGF0YVwiXTpub3QoW2RhdGEtc2VubmEtb2ZmXSlcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5mb3JtU2VsZWN0b3IgPSAnZm9ybVtlbmN0eXBlPVwibXVsdGlwYXJ0L2Zvcm0tZGF0YVwiXTpub3QoW2RhdGEtc2VubmEtb2ZmXSknO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hlbiBlbmFibGVkLCB0aGUgcm91dGUgbWF0Y2hpbmcgaWdub3JlcyBxdWVyeSBzdHJpbmcgZnJvbSB0aGUgcGF0aC5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmlnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aCA9IGZhbHNlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGxpbmsgc2VsZWN0b3IgdG8gZGVmaW5lIGxpbmtzIHRoYXQgYXJlIHJvdXRlZC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBhOm5vdChbZGF0YS1zZW5uYS1vZmZdKVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmxpbmtTZWxlY3RvciA9ICdhOm5vdChbZGF0YS1zZW5uYS1vZmZdKTpub3QoW3RhcmdldD1cIl9ibGFua1wiXSknO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGxvYWRpbmcgY3NzIGNsYXNzLlxuXHRcdCAqIEB0eXBlIHshc3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IHNlbm5hLWxvYWRpbmdcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5sb2FkaW5nQ3NzQ2xhc3MgPSAnc2VubmEtbG9hZGluZyc7XG5cblx0XHQvKipcblx0XHQgKiBVc2luZyB0aGUgSGlzdG9yeSBBUEkgdG8gbWFuYWdlIHlvdXIgVVJMcyBpcyBhd2Vzb21lIGFuZCwgYXMgaXQgaGFwcGVucyxcblx0XHQgKiBhIGNydWNpYWwgZmVhdHVyZSBvZiBnb29kIHdlYiBhcHBzLiBPbmUgb2YgaXRzIGRvd25zaWRlcywgaG93ZXZlciwgaXNcblx0XHQgKiB0aGF0IHNjcm9sbCBwb3NpdGlvbnMgYXJlIHN0b3JlZCBhbmQgdGhlbiwgbW9yZSBpbXBvcnRhbnRseSwgcmVzdG9yZWRcblx0XHQgKiB3aGVuZXZlciB5b3UgdHJhdmVyc2UgdGhlIGhpc3RvcnkuIFRoaXMgb2Z0ZW4gbWVhbnMgdW5zaWdodGx5IGp1bXBzIGFzXG5cdFx0ICogdGhlIHNjcm9sbCBwb3NpdGlvbiBjaGFuZ2VzIGF1dG9tYXRpY2FsbHksIGFuZCBlc3BlY2lhbGx5IHNvIGlmIHlvdXIgYXBwXG5cdFx0ICogZG9lcyB0cmFuc2l0aW9ucywgb3IgY2hhbmdlcyB0aGUgY29udGVudHMgb2YgdGhlIHBhZ2UgaW4gYW55IHdheS5cblx0XHQgKiBVbHRpbWF0ZWx5IHRoaXMgbGVhZHMgdG8gYW4gaG9ycmlibGUgdXNlciBleHBlcmllbmNlLiBUaGUgZ29vZCBuZXdzIGlzLFxuXHRcdCAqIGhvd2V2ZXIsIHRoYXQgdGhlcmXigJlzIGEgcG90ZW50aWFsIGZpeDogaGlzdG9yeS5zY3JvbGxSZXN0b3JhdGlvbi5cblx0XHQgKiBodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS93ZWIvdXBkYXRlcy8yMDE1LzA5L2hpc3RvcnktYXBpLXNjcm9sbC1yZXN0b3JhdGlvblxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uU3VwcG9ydGVkID0gKCdzY3JvbGxSZXN0b3JhdGlvbicgaW4gZ2xvYmFscy53aW5kb3cuaGlzdG9yeSk7XG5cblx0XHQvKipcblx0XHQgKiBXaGVuIHNldCB0byB0cnVlIHRoZXJlIGlzIGEgcGVuZGluZ05hdmlnYXRlIHRoYXQgaGFzIG5vdCB5ZXQgYmVlblxuXHRcdCAqIHJlc29sdmVkIG9yIHJlamVjdGVkLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuaXNOYXZpZ2F0aW9uUGVuZGluZyA9IGZhbHNlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgYSBkZWZlcnJlZCB3aXRoIHRoZSBjdXJyZW50IG5hdmlnYXRpb24uXG5cdFx0ICogQHR5cGUgez9DYW5jZWxsYWJsZVByb21pc2V9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZSA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgd2luZG93IGhvcml6b250YWwgc2Nyb2xsIHBvc2l0aW9uIHdoZW4gdGhlIG5hdmlnYXRpb24gdXNpbmdcblx0XHQgKiBiYWNrIG9yIGZvcndhcmQgaGFwcGVucyB0byBiZSByZXN0b3JlZCBhZnRlciB0aGUgc3VyZmFjZXMgYXJlIHVwZGF0ZWQuXG5cdFx0ICogQHR5cGUgeyFOdW1iZXJ9XG5cdFx0ICogQGRlZmF1bHQgMFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnBvcHN0YXRlU2Nyb2xsTGVmdCA9IDA7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgd2luZG93IHZlcnRpY2FsIHNjcm9sbCBwb3NpdGlvbiB3aGVuIHRoZSBuYXZpZ2F0aW9uIHVzaW5nXG5cdFx0ICogYmFjayBvciBmb3J3YXJkIGhhcHBlbnMgdG8gYmUgcmVzdG9yZWQgYWZ0ZXIgdGhlIHN1cmZhY2VzIGFyZSB1cGRhdGVkLlxuXHRcdCAqIEB0eXBlIHshTnVtYmVyfVxuXHRcdCAqIEBkZWZhdWx0IDBcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wb3BzdGF0ZVNjcm9sbFRvcCA9IDA7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgcmVkaXJlY3QgcGF0aCBjb250YWluaW5nIHRoZSBxdWVyeSBwYXJhbWV0ZXJzLlxuXHRcdCAqIEB0eXBlIHs/c3RyaW5nfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnJlZGlyZWN0UGF0aCA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgc2NyZWVuIHJvdXRlcyBjb25maWd1cmF0aW9uLlxuXHRcdCAqIEB0eXBlIHs/QXJyYXl9XG5cdFx0ICogQGRlZmF1bHQgW11cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5yb3V0ZXMgPSBbXTtcblxuXHRcdC8qKlxuXHRcdCAqIE1hcHMgdGhlIHNjcmVlbiBpbnN0YW5jZXMgYnkgdGhlIHVybCBjb250YWluaW5nIHRoZSBwYXJhbWV0ZXJzLlxuXHRcdCAqIEB0eXBlIHs/T2JqZWN0fVxuXHRcdCAqIEBkZWZhdWx0IHt9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuc2NyZWVucyA9IHt9O1xuXG5cdFx0LyoqXG5cdFx0ICogV2hlbiBzZXQgdG8gdHJ1ZSB0aGUgZmlyc3QgZXJyb25lb3VzIHBvcHN0YXRlIGZpcmVkIG9uIHBhZ2UgbG9hZCB3aWxsIGJlXG5cdFx0ICogaWdub3JlZCwgb25seSBpZiA8Y29kZT5nbG9iYWxzLndpbmRvdy5oaXN0b3J5LnN0YXRlPC9jb2RlPiBpcyBhbHNvXG5cdFx0ICogPGNvZGU+bnVsbDwvY29kZT4uXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQGRlZmF1bHQgZmFsc2Vcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5za2lwTG9hZFBvcHN0YXRlID0gZmFsc2U7XG5cblx0XHQvKipcblx0XHQgKiBNYXBzIHRoYXQgaW5kZXggdGhlIHN1cmZhY2VzIGluc3RhbmNlcyBieSB0aGUgc3VyZmFjZSBpZC5cblx0XHQgKiBAdHlwZSB7P09iamVjdH1cblx0XHQgKiBAZGVmYXVsdCB7fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnN1cmZhY2VzID0ge307XG5cblx0XHQvKipcblx0XHQgKiBXaGVuIHNldCB0byB0cnVlLCBtb3ZlcyB0aGUgc2Nyb2xsIHBvc2l0aW9uIGFmdGVyIHBvcHN0YXRlLCBvciB0byB0aGVcblx0XHQgKiB0b3Agb2YgdGhlIHZpZXdwb3J0IGZvciBuZXcgbmF2aWdhdGlvbi4gSWYgZmFsc2UsIHRoZSBicm93c2VyIHdpbGxcblx0XHQgKiB0YWtlIGNhcmUgb2Ygc2Nyb2xsIHJlc3RvcmF0aW9uLlxuXHRcdCAqIEB0eXBlIHshYm9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCB0cnVlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudXBkYXRlU2Nyb2xsUG9zaXRpb24gPSB0cnVlO1xuXG5cdFx0dGhpcy5hcHBFdmVudEhhbmRsZXJzXyA9IG5ldyBFdmVudEhhbmRsZXIoKTtcblxuXHRcdHRoaXMuYXBwRXZlbnRIYW5kbGVyc18uYWRkKFxuXHRcdFx0b24oZ2xvYmFscy53aW5kb3csICdzY3JvbGwnLCBkZWJvdW5jZSh0aGlzLm9uU2Nyb2xsXy5iaW5kKHRoaXMpLCAxMDApKSxcblx0XHRcdG9uKGdsb2JhbHMud2luZG93LCAnbG9hZCcsIHRoaXMub25Mb2FkXy5iaW5kKHRoaXMpKSxcblx0XHRcdG9uKGdsb2JhbHMud2luZG93LCAncG9wc3RhdGUnLCB0aGlzLm9uUG9wc3RhdGVfLmJpbmQodGhpcykpXG5cdFx0KTtcblxuXHRcdHRoaXMub24oJ3N0YXJ0TmF2aWdhdGUnLCB0aGlzLm9uU3RhcnROYXZpZ2F0ZV8pO1xuXHRcdHRoaXMub24oJ2JlZm9yZU5hdmlnYXRlJywgdGhpcy5vbkJlZm9yZU5hdmlnYXRlXyk7XG5cdFx0dGhpcy5vbignYmVmb3JlTmF2aWdhdGUnLCB0aGlzLm9uQmVmb3JlTmF2aWdhdGVEZWZhdWx0XywgdHJ1ZSk7XG5cdFx0dGhpcy5vbignYmVmb3JlVW5sb2FkJywgdGhpcy5vbkJlZm9yZVVubG9hZERlZmF1bHRfKTtcblxuXHRcdHRoaXMuc2V0TGlua1NlbGVjdG9yKHRoaXMubGlua1NlbGVjdG9yKTtcblx0XHR0aGlzLnNldEZvcm1TZWxlY3Rvcih0aGlzLmZvcm1TZWxlY3Rvcik7XG5cblx0XHR0aGlzLm1heWJlT3ZlcmxvYWRCZWZvcmVVbmxvYWRfKCk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBvbmUgb3IgbW9yZSBzY3JlZW5zIHRvIHRoZSBhcHBsaWNhdGlvbi5cblx0ICpcblx0ICogRXhhbXBsZTpcblx0ICpcblx0ICogPGNvZGU+XG5cdCAqICAgYXBwLmFkZFJvdXRlcyh7IHBhdGg6ICcvZm9vJywgaGFuZGxlcjogRm9vU2NyZWVuIH0pO1xuXHQgKiAgIG9yXG5cdCAqICAgYXBwLmFkZFJvdXRlcyhbeyBwYXRoOiAnL2ZvbycsIGhhbmRsZXI6IGZ1bmN0aW9uKHJvdXRlKSB7IHJldHVybiBuZXcgRm9vU2NyZWVuKCk7IH0gfV0pO1xuXHQgKiA8L2NvZGU+XG5cdCAqXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBvciB7QXJyYXl9IHJvdXRlcyBTaW5nbGUgb2JqZWN0IG9yIGFuIGFycmF5IG9mIG9iamVjdC5cblx0ICogICAgIEVhY2ggb2JqZWN0IHNob3VsZCBjb250YWluIDxjb2RlPnBhdGg8L2NvZGU+IGFuZCA8Y29kZT5zY3JlZW48L2NvZGU+LlxuXHQgKiAgICAgVGhlIDxjb2RlPnBhdGg8L2NvZGU+IHNob3VsZCBiZSBhIHN0cmluZyBvciBhIHJlZ2V4IHRoYXQgbWFwcyB0aGVcblx0ICogICAgIG5hdmlnYXRpb24gcm91dGUgdG8gYSBzY3JlZW4gY2xhc3MgZGVmaW5pdGlvbiAobm90IGFuIGluc3RhbmNlKSwgZS5nOlxuXHQgKiAgICAgICAgIDxjb2RlPnsgcGF0aDogXCIvaG9tZTpwYXJhbTFcIiwgaGFuZGxlcjogTXlTY3JlZW4gfTwvY29kZT5cblx0ICogICAgICAgICA8Y29kZT57IHBhdGg6IC9mb28uKy8sIGhhbmRsZXI6IE15U2NyZWVuIH08L2NvZGU+XG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZFJvdXRlcyhyb3V0ZXMpIHtcblx0XHRpZiAoIUFycmF5LmlzQXJyYXkocm91dGVzKSkge1xuXHRcdFx0cm91dGVzID0gW3JvdXRlc107XG5cdFx0fVxuXHRcdHJvdXRlcy5mb3JFYWNoKChyb3V0ZSkgPT4ge1xuXHRcdFx0aWYgKCEocm91dGUgaW5zdGFuY2VvZiBSb3V0ZSkpIHtcblx0XHRcdFx0cm91dGUgPSBuZXcgUm91dGUocm91dGUucGF0aCwgcm91dGUuaGFuZGxlcik7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnJvdXRlcy5wdXNoKHJvdXRlKTtcblx0XHR9KTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIG9uZSBvciBtb3JlIHN1cmZhY2VzIHRvIHRoZSBhcHBsaWNhdGlvbi5cblx0ICogQHBhcmFtIHtTdXJmYWNlfFN0cmluZ3xBcnJheS48U3VyZmFjZXxTdHJpbmc+fSBzdXJmYWNlc1xuXHQgKiAgICAgU3VyZmFjZSBlbGVtZW50IGlkIG9yIHN1cmZhY2UgaW5zdGFuY2UuIFlvdSBjYW4gYWxzbyBwYXNzIGFuIEFycmF5XG5cdCAqICAgICB3aGljaGNvbnRhaW5zIHN1cmZhY2UgaW5zdGFuY2VzIG9yIGlkLiBJbiBjYXNlIG9mIElELCB0aGVzZSBzaG91bGQgYmVcblx0ICogICAgIHRoZSBpZCBvZiBzdXJmYWNlIGVsZW1lbnQuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZFN1cmZhY2VzKHN1cmZhY2VzKSB7XG5cdFx0aWYgKCFBcnJheS5pc0FycmF5KHN1cmZhY2VzKSkge1xuXHRcdFx0c3VyZmFjZXMgPSBbc3VyZmFjZXNdO1xuXHRcdH1cblx0XHRzdXJmYWNlcy5mb3JFYWNoKChzdXJmYWNlKSA9PiB7XG5cdFx0XHRpZiAoaXNTdHJpbmcoc3VyZmFjZSkpIHtcblx0XHRcdFx0c3VyZmFjZSA9IG5ldyBTdXJmYWNlKHN1cmZhY2UpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5zdXJmYWNlc1tzdXJmYWNlLmdldElkKCldID0gc3VyZmFjZTtcblx0XHR9KTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGlmIGNhbiBuYXZpZ2F0ZSB0byBwYXRoLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHVybFxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0Y2FuTmF2aWdhdGUodXJsKSB7XG5cdFx0Y29uc3QgdXJpID0gdXRpbHMuaXNXZWJVcmkodXJsKTtcblxuXHRcdGlmICghdXJpKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Y29uc3QgcGF0aCA9IHV0aWxzLmdldFVybFBhdGgodXJsKTtcblxuXHRcdGlmICghdGhpcy5pc0xpbmtTYW1lT3JpZ2luXyh1cmkuZ2V0SG9zdG5hbWUoKSkpIHtcblx0XHRcdGNvbnNvbGUubG9nKCdPZmZzaXRlIGxpbmsgY2xpY2tlZCcpO1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRpZiAoIXRoaXMuaXNTYW1lQmFzZVBhdGhfKHBhdGgpKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnTGluayBjbGlja2VkIG91dHNpZGUgYXBwXFwncyBiYXNlIHBhdGgnKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0Ly8gUHJldmVudHMgbmF2aWdhdGlvbiBpZiBpdCdzIGEgaGFzaCBjaGFuZ2Ugb24gdGhlIHNhbWUgdXJsLlxuXHRcdGlmICh1cmkuZ2V0SGFzaCgpICYmIHV0aWxzLmlzQ3VycmVudEJyb3dzZXJQYXRoKHBhdGgpKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGlmICghdGhpcy5maW5kUm91dGUocGF0aCkpIHtcblx0XHRcdGNvbnNvbGUubG9nKCdObyByb3V0ZSBmb3IgJyArIHBhdGgpO1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIENsZWFyIHNjcmVlbnMgY2FjaGUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGNsZWFyU2NyZWVuc0NhY2hlKCkge1xuXHRcdE9iamVjdC5rZXlzKHRoaXMuc2NyZWVucykuZm9yRWFjaCgocGF0aCkgPT4ge1xuXHRcdFx0aWYgKHBhdGggPT09IHRoaXMuYWN0aXZlUGF0aCkge1xuXHRcdFx0XHR0aGlzLmFjdGl2ZVNjcmVlbi5jbGVhckNhY2hlKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnJlbW92ZVNjcmVlbihwYXRoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXRyaWV2ZXMgb3IgY3JlYXRlIGEgc2NyZWVuIGluc3RhbmNlIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHJldHVybiB7U2NyZWVufVxuXHQgKi9cblx0Y3JlYXRlU2NyZWVuSW5zdGFuY2UocGF0aCwgcm91dGUpIHtcblx0XHRpZiAoIXRoaXMucGVuZGluZ05hdmlnYXRlICYmIHBhdGggPT09IHRoaXMuYWN0aXZlUGF0aCkge1xuXHRcdFx0Y29uc29sZS5sb2coJ0FscmVhZHkgYXQgZGVzdGluYXRpb24sIHJlZnJlc2ggbmF2aWdhdGlvbicpO1xuXHRcdFx0cmV0dXJuIHRoaXMuYWN0aXZlU2NyZWVuO1xuXHRcdH1cblx0XHQvKiBqc2hpbnQgbmV3Y2FwOiBmYWxzZSAqL1xuXHRcdHZhciBzY3JlZW4gPSB0aGlzLnNjcmVlbnNbcGF0aF07XG5cdFx0aWYgKCFzY3JlZW4pIHtcblx0XHRcdHZhciBoYW5kbGVyID0gcm91dGUuZ2V0SGFuZGxlcigpO1xuXHRcdFx0aWYgKGhhbmRsZXIgPT09IFNjcmVlbiB8fCBTY3JlZW4uaXNJbXBsZW1lbnRlZEJ5KGhhbmRsZXIucHJvdG90eXBlKSkge1xuXHRcdFx0XHRzY3JlZW4gPSBuZXcgaGFuZGxlcigpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2NyZWVuID0gaGFuZGxlcihyb3V0ZSkgfHwgbmV3IFNjcmVlbigpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc29sZS5sb2coJ0NyZWF0ZSBzY3JlZW4gZm9yIFsnICsgcGF0aCArICddIFsnICsgc2NyZWVuICsgJ10nKTtcblx0XHR9XG5cdFx0cmV0dXJuIHNjcmVlbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbikge1xuXHRcdFx0dGhpcy5yZW1vdmVTY3JlZW4odGhpcy5hY3RpdmVQYXRoKTtcblx0XHR9XG5cdFx0dGhpcy5jbGVhclNjcmVlbnNDYWNoZSgpO1xuXHRcdHRoaXMuZm9ybUV2ZW50SGFuZGxlcl8ucmVtb3ZlTGlzdGVuZXIoKTtcblx0XHR0aGlzLmxpbmtFdmVudEhhbmRsZXJfLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0dGhpcy5hcHBFdmVudEhhbmRsZXJzXy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcblx0XHRzdXBlci5kaXNwb3NlSW50ZXJuYWwoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwYXRjaGVzIHRvIHRoZSBmaXJzdCByb3V0ZSBoYW5kbGVyIHRoYXQgbWF0Y2hlcyB0aGUgY3VycmVudCBwYXRoLCBpZlxuXHQgKiBhbnkuXG5cdCAqIEByZXR1cm4ge0NhbmNlbGxhYmxlUHJvbWlzZX0gUmV0dXJucyBhIHBlbmRpbmcgcmVxdWVzdCBjYW5jZWxsYWJsZSBwcm9taXNlLlxuXHQgKi9cblx0ZGlzcGF0Y2goKSB7XG5cdFx0cmV0dXJuIHRoaXMubmF2aWdhdGUodXRpbHMuZ2V0Q3VycmVudEJyb3dzZXJQYXRoKCksIHRydWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0cyBuYXZpZ2F0aW9uIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3JlcGxhY2VIaXN0b3J5IFJlcGxhY2VzIGJyb3dzZXIgaGlzdG9yeS5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBSZXR1cm5zIGEgcGVuZGluZyByZXF1ZXN0IGNhbmNlbGxhYmxlIHByb21pc2UuXG5cdCAqL1xuXHRkb05hdmlnYXRlXyhwYXRoLCBvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHRpZiAodGhpcy5hY3RpdmVTY3JlZW4gJiYgdGhpcy5hY3RpdmVTY3JlZW4uYmVmb3JlRGVhY3RpdmF0ZSgpKSB7XG5cdFx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZSA9IENhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcignQ2FuY2VsbGVkIGJ5IGFjdGl2ZSBzY3JlZW4nKSk7XG5cdFx0XHRyZXR1cm4gdGhpcy5wZW5kaW5nTmF2aWdhdGU7XG5cdFx0fVxuXG5cdFx0dmFyIHJvdXRlID0gdGhpcy5maW5kUm91dGUocGF0aCk7XG5cdFx0aWYgKCFyb3V0ZSkge1xuXHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUgPSBDYW5jZWxsYWJsZVByb21pc2UucmVqZWN0KG5ldyBDYW5jZWxsYWJsZVByb21pc2UuQ2FuY2VsbGF0aW9uRXJyb3IoJ05vIHJvdXRlIGZvciAnICsgcGF0aCkpO1xuXHRcdFx0cmV0dXJuIHRoaXMucGVuZGluZ05hdmlnYXRlO1xuXHRcdH1cblxuXHRcdGNvbnNvbGUubG9nKCdOYXZpZ2F0ZSB0byBbJyArIHBhdGggKyAnXScpO1xuXG5cdFx0dGhpcy5zdG9wUGVuZGluZ05hdmlnYXRlXygpO1xuXHRcdHRoaXMuaXNOYXZpZ2F0aW9uUGVuZGluZyA9IHRydWU7XG5cblx0XHR2YXIgbmV4dFNjcmVlbiA9IHRoaXMuY3JlYXRlU2NyZWVuSW5zdGFuY2UocGF0aCwgcm91dGUpO1xuXG5cdFx0cmV0dXJuIG5leHRTY3JlZW4ubG9hZChwYXRoKVxuXHRcdFx0LnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRpZiAodGhpcy5hY3RpdmVTY3JlZW4pIHtcblx0XHRcdFx0XHR0aGlzLmFjdGl2ZVNjcmVlbi5kZWFjdGl2YXRlKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5wcmVwYXJlTmF2aWdhdGVIaXN0b3J5XyhwYXRoLCBuZXh0U2NyZWVuLCBvcHRfcmVwbGFjZUhpc3RvcnkpO1xuXHRcdFx0XHR0aGlzLnByZXBhcmVOYXZpZ2F0ZVN1cmZhY2VzXyhcblx0XHRcdFx0XHRuZXh0U2NyZWVuLFxuXHRcdFx0XHRcdHRoaXMuc3VyZmFjZXMsXG5cdFx0XHRcdFx0dGhpcy5leHRyYWN0UGFyYW1zKHJvdXRlLCBwYXRoKVxuXHRcdFx0XHQpO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuKCgpID0+IG5leHRTY3JlZW4uZXZhbHVhdGVTdHlsZXModGhpcy5zdXJmYWNlcykpXG5cdFx0XHQudGhlbigoKSA9PiBuZXh0U2NyZWVuLmZsaXAodGhpcy5zdXJmYWNlcykpXG5cdFx0XHQudGhlbigoKSA9PiBuZXh0U2NyZWVuLmV2YWx1YXRlU2NyaXB0cyh0aGlzLnN1cmZhY2VzKSlcblx0XHRcdC50aGVuKCgpID0+IHRoaXMubWF5YmVVcGRhdGVTY3JvbGxQb3NpdGlvblN0YXRlXygpKVxuXHRcdFx0LnRoZW4oKCkgPT4gdGhpcy5zeW5jU2Nyb2xsUG9zaXRpb25TeW5jVGhlbkFzeW5jXygpKVxuXHRcdFx0LnRoZW4oKCkgPT4gdGhpcy5maW5hbGl6ZU5hdmlnYXRlXyhwYXRoLCBuZXh0U2NyZWVuKSlcblx0XHRcdC50aGVuKCgpID0+IHRoaXMubWF5YmVPdmVybG9hZEJlZm9yZVVubG9hZF8oKSlcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdHRoaXMuaXNOYXZpZ2F0aW9uUGVuZGluZyA9IGZhbHNlO1xuXHRcdFx0XHR0aGlzLmhhbmRsZU5hdmlnYXRlRXJyb3JfKHBhdGgsIG5leHRTY3JlZW4sIHJlYXNvbik7XG5cdFx0XHRcdHRocm93IHJlYXNvbjtcblx0XHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIHBhcmFtcyBhY2NvcmRpbmcgdG8gdGhlIGdpdmVuIHBhdGggYW5kIHJvdXRlLlxuXHQgKiBAcGFyYW0geyFSb3V0ZX0gcm91dGVcblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGhcblx0ICogQHBhcmFtIHshT2JqZWN0fVxuXHQgKi9cblx0ZXh0cmFjdFBhcmFtcyhyb3V0ZSwgcGF0aCkge1xuXHRcdHJldHVybiByb3V0ZS5leHRyYWN0UGFyYW1zKHRoaXMuZ2V0Um91dGVQYXRoKHBhdGgpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBGaW5hbGl6ZXMgYSBzY3JlZW4gbmF2aWdhdGlvbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHBhcmFtIHshU2NyZWVufSBuZXh0U2NyZWVuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGZpbmFsaXplTmF2aWdhdGVfKHBhdGgsIG5leHRTY3JlZW4pIHtcblx0XHRuZXh0U2NyZWVuLmFjdGl2YXRlKCk7XG5cblx0XHRpZiAodGhpcy5hY3RpdmVTY3JlZW4gJiYgIXRoaXMuYWN0aXZlU2NyZWVuLmlzQ2FjaGVhYmxlKCkpIHtcblx0XHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbiAhPT0gbmV4dFNjcmVlbikge1xuXHRcdFx0XHR0aGlzLnJlbW92ZVNjcmVlbih0aGlzLmFjdGl2ZVBhdGgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuYWN0aXZlUGF0aCA9IHBhdGg7XG5cdFx0dGhpcy5hY3RpdmVTY3JlZW4gPSBuZXh0U2NyZWVuO1xuXHRcdHRoaXMuYnJvd3NlclBhdGhCZWZvcmVOYXZpZ2F0ZSA9IHV0aWxzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCk7XG5cdFx0dGhpcy5zY3JlZW5zW3BhdGhdID0gbmV4dFNjcmVlbjtcblx0XHR0aGlzLmlzTmF2aWdhdGlvblBlbmRpbmcgPSBmYWxzZTtcblx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZSA9IG51bGw7XG5cdFx0Z2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50ID0gbnVsbDtcblx0XHRnbG9iYWxzLmNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQgPSBudWxsO1xuXHRcdGNvbnNvbGUubG9nKCdOYXZpZ2F0aW9uIGRvbmUnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBGaW5kcyBhIHJvdXRlIGZvciB0aGUgdGVzdCBwYXRoLiBSZXR1cm5zIHRydWUgaWYgbWF0Y2hlcyBoYXMgYSByb3V0ZSxcblx0ICogb3RoZXJ3aXNlIHJldHVybnMgbnVsbC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHJldHVybiB7P09iamVjdH0gUm91dGUgaGFuZGxlciBpZiBtYXRjaCBhbnkgb3IgPGNvZGU+bnVsbDwvY29kZT4gaWYgdGhlXG5cdCAqICAgICBwYXRoIGlzIHRoZSBzYW1lIGFzIHRoZSBjdXJyZW50IHVybCBhbmQgdGhlIHBhdGggY29udGFpbnMgYSBmcmFnbWVudC5cblx0ICovXG5cdGZpbmRSb3V0ZShwYXRoKSB7XG5cdFx0cGF0aCA9IHRoaXMuZ2V0Um91dGVQYXRoKHBhdGgpO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5yb3V0ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHZhciByb3V0ZSA9IHRoaXMucm91dGVzW2ldO1xuXHRcdFx0aWYgKHJvdXRlLm1hdGNoZXNQYXRoKHBhdGgpKSB7XG5cdFx0XHRcdHJldHVybiByb3V0ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGFsbG93IHByZXZlbnQgbmF2aWdhdGUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRnZXRBbGxvd1ByZXZlbnROYXZpZ2F0ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5hbGxvd1ByZXZlbnROYXZpZ2F0ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGxpbmsgYmFzZSBwYXRoLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKi9cblx0Z2V0QmFzZVBhdGgoKSB7XG5cdFx0cmV0dXJuIHRoaXMuYmFzZVBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgZGVmYXVsdCBwYWdlIHRpdGxlLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IGRlZmF1bHRUaXRsZVxuXHQgKi9cblx0Z2V0RGVmYXVsdFRpdGxlKCkge1xuXHRcdHJldHVybiB0aGlzLmRlZmF1bHRUaXRsZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBmb3JtIHNlbGVjdG9yLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKi9cblx0Z2V0Rm9ybVNlbGVjdG9yKCkge1xuXHRcdHJldHVybiB0aGlzLmZvcm1TZWxlY3Rvcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVjayBpZiByb3V0ZSBtYXRjaGluZyBpcyBpZ25vcmluZyBxdWVyeSBzdHJpbmcgZnJvbSB0aGUgcm91dGUgcGF0aC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldElnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aCgpIHtcblx0XHRyZXR1cm4gdGhpcy5pZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgbGluayBzZWxlY3Rvci5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICovXG5cdGdldExpbmtTZWxlY3RvcigpIHtcblx0XHRyZXR1cm4gdGhpcy5saW5rU2VsZWN0b3I7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgbG9hZGluZyBjc3MgY2xhc3MuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqL1xuXHRnZXRMb2FkaW5nQ3NzQ2xhc3MoKSB7XG5cdFx0cmV0dXJuIHRoaXMubG9hZGluZ0Nzc0NsYXNzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGdpdmVuIHBhdGggZm9ybWF0dGVkIHRvIGJlIG1hdGNoZWQgYnkgYSByb3V0ZS4gVGhpcyB3aWxsLFxuXHQgKiBmb3IgZXhhbXBsZSwgcmVtb3ZlIHRoZSBiYXNlIHBhdGggZnJvbSBpdCwgYnV0IG1ha2Ugc3VyZSBpdCB3aWxsIGVuZFxuXHQgKiB3aXRoIGEgJy8nLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGF0aFxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRSb3V0ZVBhdGgocGF0aCkge1xuXHRcdGlmICh0aGlzLmdldElnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aCgpKSB7XG5cdFx0XHRwYXRoID0gdXRpbHMuZ2V0VXJsUGF0aFdpdGhvdXRIYXNoQW5kU2VhcmNoKHBhdGgpO1xuXHRcdFx0cmV0dXJuIHV0aWxzLmdldFVybFBhdGhXaXRob3V0SGFzaEFuZFNlYXJjaChwYXRoLnN1YnN0cih0aGlzLmJhc2VQYXRoLmxlbmd0aCkpO1xuXHRcdH1cblxuXHRcdHBhdGggPSB1dGlscy5nZXRVcmxQYXRoV2l0aG91dEhhc2gocGF0aCk7XG5cdFx0cmV0dXJuIHV0aWxzLmdldFVybFBhdGhXaXRob3V0SGFzaChwYXRoLnN1YnN0cih0aGlzLmJhc2VQYXRoLmxlbmd0aCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHVwZGF0ZSBzY3JvbGwgcG9zaXRpb24gdmFsdWUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRnZXRVcGRhdGVTY3JvbGxQb3NpdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy51cGRhdGVTY3JvbGxQb3NpdGlvbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBIYW5kbGUgbmF2aWdhdGlvbiBlcnJvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHBhcmFtIHshU2NyZWVufSBuZXh0U2NyZWVuXG5cdCAqIEBwYXJhbSB7IUVycm9yfSBlcnJvclxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRoYW5kbGVOYXZpZ2F0ZUVycm9yXyhwYXRoLCBuZXh0U2NyZWVuLCBlcnJvcikge1xuXHRcdGNvbnNvbGUubG9nKCdOYXZpZ2F0aW9uIGVycm9yIGZvciBbJyArIG5leHRTY3JlZW4gKyAnXSAoJyArIGVycm9yICsgJyknKTtcblx0XHR0aGlzLmVtaXQoJ25hdmlnYXRpb25FcnJvcicsIHtcblx0XHRcdGVycm9yLFxuXHRcdFx0bmV4dFNjcmVlbixcblx0XHRcdHBhdGhcblx0XHR9KTtcblx0XHRpZiAoIXV0aWxzLmlzQ3VycmVudEJyb3dzZXJQYXRoKHBhdGgpKSB7XG5cdFx0XHRpZiAodGhpcy5pc05hdmlnYXRpb25QZW5kaW5nICYmIHRoaXMucGVuZGluZ05hdmlnYXRlKSB7XG5cdFx0XHRcdHRoaXMucGVuZGluZ05hdmlnYXRlLnRoZW5BbHdheXMoKCkgPT4gdGhpcy5yZW1vdmVTY3JlZW4ocGF0aCksIHRoaXMpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5yZW1vdmVTY3JlZW4ocGF0aCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBhcHAgaGFzIHJvdXRlcy5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGhhc1JvdXRlcygpIHtcblx0XHRyZXR1cm4gdGhpcy5yb3V0ZXMubGVuZ3RoID4gMDtcblx0fVxuXG5cdC8qKlxuXHQgKiBUZXN0cyBpZiBob3N0bmFtZSBpcyBhbiBvZmZzaXRlIGxpbmsuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaG9zdG5hbWUgTGluayBob3N0bmFtZSB0byBjb21wYXJlIHdpdGhcblx0ICogICAgIDxjb2RlPmdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhvc3RuYW1lPC9jb2RlPi5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0aXNMaW5rU2FtZU9yaWdpbl8oaG9zdG5hbWUpIHtcblx0XHRyZXR1cm4gaG9zdG5hbWUgPT09IGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhvc3RuYW1lO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRlc3RzIGlmIGxpbmsgZWxlbWVudCBoYXMgdGhlIHNhbWUgYXBwJ3MgYmFzZSBwYXRoLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggTGluayBwYXRoIGNvbnRhaW5pbmcgdGhlIHF1ZXJ5c3RyaW5nIHBhcnQuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGlzU2FtZUJhc2VQYXRoXyhwYXRoKSB7XG5cdFx0cmV0dXJuIHBhdGguaW5kZXhPZih0aGlzLmJhc2VQYXRoKSA9PT0gMDtcblx0fVxuXG5cdC8qKlxuXHQgKiBMb2NrIHRoZSBkb2N1bWVudCBzY3JvbGwgaW4gb3JkZXIgdG8gYXZvaWQgdGhlIGJyb3dzZXIgbmF0aXZlIGJhY2sgYW5kXG5cdCAqIGZvcndhcmQgbmF2aWdhdGlvbiB0byBjaGFuZ2UgdGhlIHNjcm9sbCBwb3NpdGlvbi4gSW4gdGhlIGVuZCBvZlxuXHQgKiBuYXZpZ2F0aW9uIGxpZmVjeWNsZSBzY3JvbGwgaXMgcmVwb3NpdGlvbmVkLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRsb2NrSGlzdG9yeVNjcm9sbFBvc2l0aW9uXygpIHtcblx0XHR2YXIgc3RhdGUgPSBnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnN0YXRlO1xuXHRcdGlmICghc3RhdGUpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Ly8gQnJvd3NlcnMgYXJlIGluY29uc2lzdGVudCB3aGVuIHJlLXBvc2l0aW9uaW5nIHRoZSBzY3JvbGwgaGlzdG9yeSBvblxuXHRcdC8vIHBvcHN0YXRlLiBBdCBzb21lIGJyb3dzZXJzLCBoaXN0b3J5IHNjcm9sbCBoYXBwZW5zIGJlZm9yZSBwb3BzdGF0ZSwgdGhlblxuXHRcdC8vIGxvY2sgdGhlIHNjcm9sbCBvbiB0aGUgbGFzdCBrbm93biBwb3NpdGlvbiBhcyBzb29uIGFzIHBvc3NpYmxlIGFmdGVyIHRoZVxuXHRcdC8vIGN1cnJlbnQgSlMgZXhlY3V0aW9uIGNvbnRleHQgYW5kIGNhcHR1cmUgdGhlIGN1cnJlbnQgdmFsdWUuIFNvbWUgb3RoZXJzLFxuXHRcdC8vIGhpc3Rvcnkgc2Nyb2xsIGhhcHBlbnMgYWZ0ZXIgcG9wc3RhdGUsIGluIHRoaXMgY2FzZSwgd2UgYmluZCBhbiBvbmNlXG5cdFx0Ly8gc2Nyb2xsIGV2ZW50IHRvIGxvY2sgdGhlIGxhcyBrbm93biBwb3NpdGlvbi4gTGFzdGx5LCB0aGUgcHJldmlvdXMgdHdvXG5cdFx0Ly8gYmVoYXZpb3JzIGNhbiBoYXBwZW4gZXZlbiBvbiB0aGUgc2FtZSBicm93c2VyLCBoZW5jZSB0aGUgcmFjZSB3aWxsIGRlY2lkZVxuXHRcdC8vIHRoZSB3aW5uZXIuXG5cdFx0dmFyIHdpbm5lciA9IGZhbHNlO1xuXHRcdHZhciBzd2l0Y2hTY3JvbGxQb3NpdGlvblJhY2UgPSBmdW5jdGlvbigpIHtcblx0XHRcdGdsb2JhbHMuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgc3dpdGNoU2Nyb2xsUG9zaXRpb25SYWNlLCBmYWxzZSk7XG5cdFx0XHRpZiAoIXdpbm5lcikge1xuXHRcdFx0XHRnbG9iYWxzLndpbmRvdy5zY3JvbGxUbyhzdGF0ZS5zY3JvbGxMZWZ0LCBzdGF0ZS5zY3JvbGxUb3ApO1xuXHRcdFx0XHR3aW5uZXIgPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0YXN5bmMubmV4dFRpY2soc3dpdGNoU2Nyb2xsUG9zaXRpb25SYWNlKTtcblx0XHRnbG9iYWxzLmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHN3aXRjaFNjcm9sbFBvc2l0aW9uUmFjZSwgZmFsc2UpO1xuXHR9XG5cblx0LyoqXG5cdCAqIElmIHN1cHBvcnRlZCBieSB0aGUgYnJvd3NlciwgZGlzYWJsZXMgbmF0aXZlIHNjcm9sbCByZXN0b3JhdGlvbiBhbmRcblx0ICogc3RvcmVzIGN1cnJlbnQgdmFsdWUuXG5cdCAqL1xuXHRtYXliZURpc2FibGVOYXRpdmVTY3JvbGxSZXN0b3JhdGlvbigpIHtcblx0XHRpZiAodGhpcy5uYXRpdmVTY3JvbGxSZXN0b3JhdGlvblN1cHBvcnRlZCkge1xuXHRcdFx0dGhpcy5uYXRpdmVTY3JvbGxSZXN0b3JhdGlvbl8gPSBnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uO1xuXHRcdFx0Z2xvYmFscy53aW5kb3cuaGlzdG9yeS5zY3JvbGxSZXN0b3JhdGlvbiA9ICdtYW51YWwnO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBuYXZpZ2F0ZSB0byBhIHBhdGguXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBocmVmIEluZm9ybWF0aW9uIGFib3V0IHRoZSBsaW5rJ3MgaHJlZi5cblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnQgRG9tIGV2ZW50IHRoYXQgaW5pdGlhdGVkIHRoZSBuYXZpZ2F0aW9uLlxuXHQgKi9cblx0bWF5YmVOYXZpZ2F0ZV8oaHJlZiwgZXZlbnQpIHtcblx0XHRpZiAoIXRoaXMuY2FuTmF2aWdhdGUoaHJlZikpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQgPSBldmVudC5jYXB0dXJlZEZvcm1FbGVtZW50O1xuXHRcdGdsb2JhbHMuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCA9IGV2ZW50LmNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQ7XG5cblx0XHR2YXIgbmF2aWdhdGVGYWlsZWQgPSBmYWxzZTtcblx0XHR0cnkge1xuXHRcdFx0dGhpcy5uYXZpZ2F0ZSh1dGlscy5nZXRVcmxQYXRoKGhyZWYpLCBmYWxzZSwgZXZlbnQpO1xuXHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0Ly8gRG8gbm90IHByZXZlbnQgbGluayBuYXZpZ2F0aW9uIGluIGNhc2Ugc29tZSBzeW5jaHJvbm91cyBlcnJvciBvY2N1cnNcblx0XHRcdG5hdmlnYXRlRmFpbGVkID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIW5hdmlnYXRlRmFpbGVkKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3Mgd2hldGhlciB0aGUgb25iZWZvcmV1bmxvYWQgZ2xvYmFsIGV2ZW50IGhhbmRsZXIgaXMgb3ZlcmxvYWRlZFxuXHQgKiBieSBjbGllbnQgY29kZS4gSWYgc28sIGl0IHJlcGxhY2VzIHdpdGggYSBmdW5jdGlvbiB0aGF0IGhhbHRzIHRoZSBub3JtYWxcblx0ICogZXZlbnQgZmxvdyBpbiByZWxhdGlvbiB3aXRoIHRoZSBjbGllbnQgb25iZWZvcmV1bmxvYWQgZnVuY3Rpb24uXG5cdCAqIFRoaXMgY2FuIGJlIGluIG1vc3QgcGFydCB1c2VkIHRvIHByZW1hdHVyZWx5IHRlcm1pbmF0ZSBuYXZpZ2F0aW9uIHRvIG90aGVyIHBhZ2VzXG5cdCAqIGFjY29yZGluZyB0byB0aGUgZ2l2ZW4gY29uc3RyYWl0KHMpLiBcblx0ICogQHByb3RlY3RlZCBcblx0ICovXG5cdG1heWJlT3ZlcmxvYWRCZWZvcmVVbmxvYWRfKCkge1xuXHRcdGlmICgnZnVuY3Rpb24nID09PSB0eXBlb2Ygd2luZG93Lm9uYmVmb3JldW5sb2FkKSB7XG5cdFx0XHR3aW5kb3cuX29uYmVmb3JldW5sb2FkID0gd2luZG93Lm9uYmVmb3JldW5sb2FkO1xuXG5cdFx0XHR3aW5kb3cub25iZWZvcmV1bmxvYWQgPSBldmVudCA9PiB7XG5cdFx0XHRcdHRoaXMuZW1pdCgnYmVmb3JlVW5sb2FkJywgZXZlbnQpO1xuXHRcdFx0XHRpZiAoZXZlbnQgJiYgZXZlbnQuZGVmYXVsdFByZXZlbnRlZCkge1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXG5cdFx0XHQvLyBtYXJrIHRoZSB1cGRhdGVkIGhhbmRsZXIgZHVlIHVud2FudGVkIHJlY3Vyc2lvbiBcblx0XHRcdHdpbmRvdy5vbmJlZm9yZXVubG9hZC5fb3ZlcmxvYWRlZCA9IHRydWU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHJlcG9zaXRpb24gc2Nyb2xsIHRvIGhhc2hlZCBhbmNob3IuXG5cdCAqL1xuXHRtYXliZVJlcG9zaXRpb25TY3JvbGxUb0hhc2hlZEFuY2hvcigpIHtcblx0XHRjb25zdCBoYXNoID0gZ2xvYmFscy53aW5kb3cubG9jYXRpb24uaGFzaDtcblx0XHRpZiAoaGFzaCkge1xuXHRcdFx0bGV0IGFuY2hvckVsZW1lbnQgPSBnbG9iYWxzLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGhhc2guc3Vic3RyaW5nKDEpKTtcblx0XHRcdGlmIChhbmNob3JFbGVtZW50KSB7XG5cdFx0XHRcdGNvbnN0IHtvZmZzZXRMZWZ0LCBvZmZzZXRUb3B9ID0gdXRpbHMuZ2V0Tm9kZU9mZnNldChhbmNob3JFbGVtZW50KTtcblx0XHRcdFx0Z2xvYmFscy53aW5kb3cuc2Nyb2xsVG8ob2Zmc2V0TGVmdCwgb2Zmc2V0VG9wKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogSWYgc3VwcG9ydGVkIGJ5IHRoZSBicm93c2VyLCByZXN0b3JlcyBuYXRpdmUgc2Nyb2xsIHJlc3RvcmF0aW9uIHRvIHRoZVxuXHQgKiB2YWx1ZSBjYXB0dXJlZCBieSBgbWF5YmVEaXNhYmxlTmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25gLlxuXHQgKi9cblx0bWF5YmVSZXN0b3JlTmF0aXZlU2Nyb2xsUmVzdG9yYXRpb24oKSB7XG5cdFx0aWYgKHRoaXMubmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25TdXBwb3J0ZWQgJiYgdGhpcy5uYXRpdmVTY3JvbGxSZXN0b3JhdGlvbl8pIHtcblx0XHRcdGdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc2Nyb2xsUmVzdG9yYXRpb24gPSB0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uXztcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogTWF5YmUgcmVzdG9yZSByZWRpcmVjdGVkIHBhdGggaGFzaCBpbiBjYXNlIGJvdGggdGhlIGN1cnJlbnQgcGF0aCBhbmRcblx0ICogdGhlIGdpdmVuIHBhdGggYXJlIHRoZSBzYW1lLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBiZWZvcmUgbmF2aWdhdGlvbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSByZWRpcmVjdFBhdGggUGF0aCBhZnRlciBuYXZpZ2F0aW9uLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IGhhc2ggSGFzaCB0byBiZSBhZGRlZCB0byB0aGUgcGF0aC5cblx0ICogQHJldHVybiB7IXN0cmluZ30gUmV0dXJucyB0aGUgcGF0aCB3aXRoIHRoZSBoYXNoIHJlc3RvcmVkLlxuXHQgKi9cblx0bWF5YmVSZXN0b3JlUmVkaXJlY3RQYXRoSGFzaF8ocGF0aCwgcmVkaXJlY3RQYXRoLCBoYXNoKSB7XG5cdFx0aWYgKHJlZGlyZWN0UGF0aCA9PT0gdXRpbHMuZ2V0VXJsUGF0aFdpdGhvdXRIYXNoKHBhdGgpKSB7XG5cdFx0XHRyZXR1cm4gcmVkaXJlY3RQYXRoICsgaGFzaDtcblx0XHR9XG5cdFx0cmV0dXJuIHJlZGlyZWN0UGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSB1cGRhdGUgc2Nyb2xsIHBvc2l0aW9uIGluIGhpc3Rvcnkgc3RhdGUgdG8gYW5jaG9yIG9uIHBhdGguXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIGNvbnRhaW5pbmcgYW5jaG9yXG5cdCAqL1xuXHRtYXliZVVwZGF0ZVNjcm9sbFBvc2l0aW9uU3RhdGVfKCkge1xuXHRcdHZhciBoYXNoID0gZ2xvYmFscy53aW5kb3cubG9jYXRpb24uaGFzaDtcblx0XHR2YXIgYW5jaG9yRWxlbWVudCA9IGdsb2JhbHMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaGFzaC5zdWJzdHJpbmcoMSkpO1xuXHRcdGlmIChhbmNob3JFbGVtZW50KSB7XG5cdFx0XHRjb25zdCB7b2Zmc2V0TGVmdCwgb2Zmc2V0VG9wfSA9IHV0aWxzLmdldE5vZGVPZmZzZXQoYW5jaG9yRWxlbWVudCk7XG5cdFx0XHR0aGlzLnNhdmVIaXN0b3J5Q3VycmVudFBhZ2VTY3JvbGxQb3NpdGlvbl8ob2Zmc2V0VG9wLCBvZmZzZXRMZWZ0KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogTmF2aWdhdGVzIHRvIHRoZSBzcGVjaWZpZWQgcGF0aCBpZiB0aGVyZSBpcyBhIHJvdXRlIGhhbmRsZXIgdGhhdCBtYXRjaGVzLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCB0byBuYXZpZ2F0ZSBjb250YWluaW5nIHRoZSBiYXNlIHBhdGguXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9yZXBsYWNlSGlzdG9yeSBSZXBsYWNlcyBicm93c2VyIGhpc3RvcnkuXG5cdCAqIEBwYXJhbSB7RXZlbnQ9fSBldmVudCBPcHRpb25hbCBldmVudCBvYmplY3QgdGhhdCB0cmlnZ2VyZWQgdGhlIG5hdmlnYXRpb24uXG5cdCAqIEByZXR1cm4ge0NhbmNlbGxhYmxlUHJvbWlzZX0gUmV0dXJucyBhIHBlbmRpbmcgcmVxdWVzdCBjYW5jZWxsYWJsZSBwcm9taXNlLlxuXHQgKi9cblx0bmF2aWdhdGUocGF0aCwgb3B0X3JlcGxhY2VIaXN0b3J5LCBvcHRfZXZlbnQpIHtcblx0XHRpZiAoIXV0aWxzLmlzSHRtbDVIaXN0b3J5U3VwcG9ydGVkKCkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignSFRNTDUgSGlzdG9yeSBpcyBub3Qgc3VwcG9ydGVkLiBTZW5uYSB3aWxsIG5vdCBpbnRlcmNlcHQgbmF2aWdhdGlvbi4nKTtcblx0XHR9XG5cblx0XHQvLyBXaGVuIHJlbG9hZGluZyB0aGUgc2FtZSBwYXRoIGRvIHJlcGxhY2VTdGF0ZSBpbnN0ZWFkIG9mIHB1c2hTdGF0ZSB0b1xuXHRcdC8vIGF2b2lkIHBvbGx1dGluZyBoaXN0b3J5IHdpdGggc3RhdGVzIHdpdGggdGhlIHNhbWUgcGF0aC5cblx0XHRpZiAocGF0aCA9PT0gdGhpcy5hY3RpdmVQYXRoKSB7XG5cdFx0XHRvcHRfcmVwbGFjZUhpc3RvcnkgPSB0cnVlO1xuXHRcdH1cblxuXHRcdHRoaXMuZW1pdCgnYmVmb3JlTmF2aWdhdGUnLCB7XG5cdFx0XHRldmVudDogb3B0X2V2ZW50LFxuXHRcdFx0cGF0aDogcGF0aCxcblx0XHRcdHJlcGxhY2VIaXN0b3J5OiAhIW9wdF9yZXBsYWNlSGlzdG9yeVxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIHRoaXMucGVuZGluZ05hdmlnYXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEJlZm9yZXMgbmF2aWdhdGlvbiB0byBhIHBhdGguXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBFdmVudCBmYWNhZGUgY29udGFpbmluZyA8Y29kZT5wYXRoPC9jb2RlPiBhbmRcblx0ICogICAgIDxjb2RlPnJlcGxhY2VIaXN0b3J5PC9jb2RlPi5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25CZWZvcmVOYXZpZ2F0ZV8oZXZlbnQpIHtcblx0XHRpZiAoZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50KSB7XG5cdFx0XHRldmVudC5mb3JtID0gZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50O1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBCZWZvcmVzIG5hdmlnYXRpb24gdG8gYSBwYXRoLiBSdW5zIGFmdGVyIGV4dGVybmFsIGxpc3RlbmVycy5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZSBjb250YWluaW5nIDxjb2RlPnBhdGg8L2NvZGU+IGFuZFxuXHQgKiAgICAgPGNvZGU+cmVwbGFjZUhpc3Rvcnk8L2NvZGU+LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvbkJlZm9yZU5hdmlnYXRlRGVmYXVsdF8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5wZW5kaW5nTmF2aWdhdGUpIHtcblx0XHRcdGlmICh0aGlzLnBlbmRpbmdOYXZpZ2F0ZS5wYXRoID09PSBldmVudC5wYXRoKSB7XG5cdFx0XHRcdGNvbnNvbGUubG9nKCdXYWl0aW5nLi4uJyk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLmVtaXQoJ2JlZm9yZVVubG9hZCcsIGV2ZW50KTtcblxuXHRcdHRoaXMuZW1pdCgnc3RhcnROYXZpZ2F0ZScsIHtcblx0XHRcdGZvcm06IGV2ZW50LmZvcm0sXG5cdFx0XHRwYXRoOiBldmVudC5wYXRoLFxuXHRcdFx0cmVwbGFjZUhpc3Rvcnk6IGV2ZW50LnJlcGxhY2VIaXN0b3J5XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogQ3VzdG9tIGV2ZW50IGhhbmRsZXIgdGhhdCBleGVjdXRlcyB0aGUgb3JpZ2luYWwgbGlzdGVuZXIgdGhhdCBoYXMgYmVlblxuXHQgKiBhZGRlZCBieSB0aGUgY2xpZW50IGNvZGUgYW5kIHRlcm1pbmF0ZXMgdGhlIG5hdmlnYXRpb24gYWNjb3JkaW5nbHkuXG5cdCAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBvcmlnaW5hbCBFdmVudCBmYWNhZGUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG9uQmVmb3JlVW5sb2FkRGVmYXVsdF8oZXZlbnQpIHtcblx0XHR2YXIgZnVuYyA9IHdpbmRvdy5fb25iZWZvcmV1bmxvYWQ7XG5cdFx0aWYgKGZ1bmMgJiYgIWZ1bmMuX292ZXJsb2FkZWQgJiYgZnVuYygpKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBJbnRlcmNlcHRzIGRvY3VtZW50IGNsaWNrcyBhbmQgdGVzdCBsaW5rIGVsZW1lbnRzIGluIG9yZGVyIHRvIGRlY2lkZVxuXHQgKiB3aGV0aGVyIFN1cmZhY2UgYXBwIGNhbiBuYXZpZ2F0ZS5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvbkRvY0NsaWNrRGVsZWdhdGVfKGV2ZW50KSB7XG5cdFx0aWYgKGV2ZW50LmFsdEtleSB8fCBldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXkgfHwgZXZlbnQuc2hpZnRLZXkgfHwgZXZlbnQuYnV0dG9uKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnTmF2aWdhdGUgYWJvcnRlZCwgaW52YWxpZCBtb3VzZSBidXR0b24gb3IgbW9kaWZpZXIga2V5IHByZXNzZWQuJyk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMubWF5YmVOYXZpZ2F0ZV8oZXZlbnQuZGVsZWdhdGVUYXJnZXQuaHJlZiwgZXZlbnQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEludGVyY2VwdHMgZG9jdW1lbnQgZm9ybSBzdWJtaXRzIGFuZCB0ZXN0IGFjdGlvbiBwYXRoIGluIG9yZGVyIHRvIGRlY2lkZVxuXHQgKiB3aGV0aGVyIFN1cmZhY2UgYXBwIGNhbiBuYXZpZ2F0ZS5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvbkRvY1N1Ym1pdERlbGVnYXRlXyhldmVudCkge1xuXHRcdHZhciBmb3JtID0gZXZlbnQuZGVsZWdhdGVUYXJnZXQ7XG5cdFx0aWYgKGZvcm0ubWV0aG9kID09PSAnZ2V0Jykge1xuXHRcdFx0Y29uc29sZS5sb2coJ0dFVCBtZXRob2Qgbm90IHN1cHBvcnRlZCcpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRldmVudC5jYXB0dXJlZEZvcm1FbGVtZW50ID0gZm9ybTtcblx0XHRjb25zdCBidXR0b25TZWxlY3RvciA9ICdidXR0b246bm90KFt0eXBlXSksYnV0dG9uW3R5cGU9c3VibWl0XSxpbnB1dFt0eXBlPXN1Ym1pdF0nO1xuXHRcdGlmIChtYXRjaChnbG9iYWxzLmRvY3VtZW50LmFjdGl2ZUVsZW1lbnQsIGJ1dHRvblNlbGVjdG9yKSkge1xuXHRcdFx0ZXZlbnQuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCA9IGdsb2JhbHMuZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZXZlbnQuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCA9IGZvcm0ucXVlcnlTZWxlY3RvcihidXR0b25TZWxlY3Rvcik7XG5cdFx0fVxuXHRcdHRoaXMubWF5YmVOYXZpZ2F0ZV8oZm9ybS5hY3Rpb24sIGV2ZW50KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBMaXN0ZW5zIHRvIHRoZSB3aW5kb3cncyBsb2FkIGV2ZW50IGluIG9yZGVyIHRvIGF2b2lkIGlzc3VlcyB3aXRoIHNvbWUgYnJvd3NlcnNcblx0ICogdGhhdCB0cmlnZ2VyIHBvcHN0YXRlIGNhbGxzIG9uIHRoZSBmaXJzdCBsb2FkLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBzZWVcblx0ICogaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NDIxNzY5L3BvcHN0YXRlLW9uLXBhZ2VzLWxvYWQtaW4tY2hyb21lLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvbkxvYWRfKCkge1xuXHRcdHRoaXMuc2tpcExvYWRQb3BzdGF0ZSA9IHRydWU7XG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHQvLyBUaGUgdGltZW91dCBlbnN1cmVzIHRoYXQgcG9wc3RhdGUgZXZlbnRzIHdpbGwgYmUgdW5ibG9ja2VkIHJpZ2h0XG5cdFx0XHQvLyBhZnRlciB0aGUgbG9hZCBldmVudCBvY2N1cmVkLCBidXQgbm90IGluIHRoZSBzYW1lIGV2ZW50LWxvb3AgY3ljbGUuXG5cdFx0XHR0aGlzLnNraXBMb2FkUG9wc3RhdGUgPSBmYWxzZTtcblx0XHR9LCAwKTtcblx0XHQvLyBUcnkgdG8gcmVwb3NpdGlvbiBzY3JvbGwgdG8gdGhlIGhhc2hlZCBhbmNob3Igd2hlbiBwYWdlIGxvYWRzLlxuXHRcdHRoaXMubWF5YmVSZXBvc2l0aW9uU2Nyb2xsVG9IYXNoZWRBbmNob3IoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBIYW5kbGVzIGJyb3dzZXIgaGlzdG9yeSBjaGFuZ2VzIGFuZCBmaXJlcyBhcHAncyBuYXZpZ2F0aW9uIGlmIHRoZSBzdGF0ZVxuXHQgKiBiZWxvd3MgdG8gdXMuIElmIHdlIGRldGVjdCBhIHBvcHN0YXRlIGFuZCB0aGUgc3RhdGUgaXMgPGNvZGU+bnVsbDwvY29kZT4sXG5cdCAqIGFzc3VtZSBpdCBpcyBuYXZpZ2F0aW5nIHRvIGFuIGV4dGVybmFsIHBhZ2Ugb3IgdG8gYSBwYWdlIHdlIGRvbid0IGhhdmVcblx0ICogcm91dGUsIHRoZW4gPGNvZGU+Z2xvYmFscy53aW5kb3cubG9jYXRpb24ucmVsb2FkKCk8L2NvZGU+IGlzIGludm9rZWQgaW4gb3JkZXIgdG9cblx0ICogcmVsb2FkIHRoZSBjb250ZW50IHRvIHRoZSBjdXJyZW50IHVybC5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvblBvcHN0YXRlXyhldmVudCkge1xuXHRcdGlmICh0aGlzLnNraXBMb2FkUG9wc3RhdGUpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBEbyBub3QgbmF2aWdhdGUgaWYgdGhlIHBvcHN0YXRlIHdhcyB0cmlnZ2VyZWQgYnkgYSBoYXNoIGNoYW5nZS5cblx0XHRpZiAodXRpbHMuaXNDdXJyZW50QnJvd3NlclBhdGgodGhpcy5icm93c2VyUGF0aEJlZm9yZU5hdmlnYXRlKSkge1xuXHRcdFx0dGhpcy5tYXliZVJlcG9zaXRpb25TY3JvbGxUb0hhc2hlZEFuY2hvcigpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBzdGF0ZSA9IGV2ZW50LnN0YXRlO1xuXG5cdFx0aWYgKCFzdGF0ZSkge1xuXHRcdFx0aWYgKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhhc2gpIHtcblx0XHRcdFx0Ly8gSWYgc2VubmEgaXMgb24gYW4gcmVkaXJlY3QgcGF0aCBhbmQgYSBoYXNoIHBvcHN0YXRlIGhhcHBlbnNcblx0XHRcdFx0Ly8gdG8gYSBkaWZmZXJlbnQgdXJsLCByZWxvYWQgdGhlIGJyb3dzZXIuIFRoaXMgYmVoYXZpb3IgZG9lc24ndFxuXHRcdFx0XHQvLyByZXF1aXJlIHNlbm5hIHRvIHJvdXRlIGhhc2hlZCBsaW5rcyBhbmQgaXMgY2xvc2VyIHRvIG5hdGl2ZVxuXHRcdFx0XHQvLyBicm93c2VyIGJlaGF2aW9yLlxuXHRcdFx0XHRpZiAodGhpcy5yZWRpcmVjdFBhdGggJiYgIXV0aWxzLmlzQ3VycmVudEJyb3dzZXJQYXRoKHRoaXMucmVkaXJlY3RQYXRoKSkge1xuXHRcdFx0XHRcdHRoaXMucmVsb2FkUGFnZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdC8vIEFsd2F5cyB0cnkgdG8gcmVwb3NpdGlvbiBzY3JvbGwgdG8gdGhlIGhhc2hlZCBhbmNob3Igd2hlblxuXHRcdFx0XHQvLyBoYXNoIHBvcHN0YXRlIGhhcHBlbnMuXG5cdFx0XHRcdHRoaXMubWF5YmVSZXBvc2l0aW9uU2Nyb2xsVG9IYXNoZWRBbmNob3IoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMucmVsb2FkUGFnZSgpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChzdGF0ZS5zZW5uYSkge1xuXHRcdFx0Y29uc29sZS5sb2coJ0hpc3RvcnkgbmF2aWdhdGlvbiB0byBbJyArIHN0YXRlLnBhdGggKyAnXScpO1xuXHRcdFx0dGhpcy5wb3BzdGF0ZVNjcm9sbFRvcCA9IHN0YXRlLnNjcm9sbFRvcDtcblx0XHRcdHRoaXMucG9wc3RhdGVTY3JvbGxMZWZ0ID0gc3RhdGUuc2Nyb2xsTGVmdDtcblx0XHRcdGlmICghdGhpcy5uYXRpdmVTY3JvbGxSZXN0b3JhdGlvblN1cHBvcnRlZCkge1xuXHRcdFx0XHR0aGlzLmxvY2tIaXN0b3J5U2Nyb2xsUG9zaXRpb25fKCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLm5hdmlnYXRlKHN0YXRlLnBhdGgsIHRydWUpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBMaXN0ZW5zIGRvY3VtZW50IHNjcm9sbCBjaGFuZ2VzIGluIG9yZGVyIHRvIGNhcHR1cmUgdGhlIHBvc3NpYmxlIGxvY2tcblx0ICogc2Nyb2xsIHBvc2l0aW9uIGZvciBoaXN0b3J5IHNjcm9sbGluZy5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25TY3JvbGxfKCkge1xuXHRcdGlmICh0aGlzLmNhcHR1cmVTY3JvbGxQb3NpdGlvbkZyb21TY3JvbGxFdmVudCkge1xuXHRcdFx0dGhpcy5zYXZlSGlzdG9yeUN1cnJlbnRQYWdlU2Nyb2xsUG9zaXRpb25fKGdsb2JhbHMud2luZG93LnBhZ2VZT2Zmc2V0LCBnbG9iYWxzLndpbmRvdy5wYWdlWE9mZnNldCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0cyBuYXZpZ2F0aW9uIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZSBjb250YWluaW5nIDxjb2RlPnBhdGg8L2NvZGU+IGFuZFxuXHQgKiAgICAgPGNvZGU+cmVwbGFjZUhpc3Rvcnk8L2NvZGU+LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvblN0YXJ0TmF2aWdhdGVfKGV2ZW50KSB7XG5cdFx0dGhpcy5tYXliZURpc2FibGVOYXRpdmVTY3JvbGxSZXN0b3JhdGlvbigpO1xuXHRcdHRoaXMuY2FwdHVyZVNjcm9sbFBvc2l0aW9uRnJvbVNjcm9sbEV2ZW50ID0gZmFsc2U7XG5cdFx0YWRkQ2xhc3NlcyhnbG9iYWxzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgdGhpcy5sb2FkaW5nQ3NzQ2xhc3MpO1xuXG5cdFx0dmFyIGVuZE5hdmlnYXRlUGF5bG9hZCA9IHtcblx0XHRcdGZvcm06IGV2ZW50LmZvcm0sXG5cdFx0XHRwYXRoOiBldmVudC5wYXRoXG5cdFx0fTtcblxuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gdGhpcy5kb05hdmlnYXRlXyhldmVudC5wYXRoLCBldmVudC5yZXBsYWNlSGlzdG9yeSlcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdGVuZE5hdmlnYXRlUGF5bG9hZC5lcnJvciA9IHJlYXNvbjtcblx0XHRcdFx0dGhyb3cgcmVhc29uO1xuXHRcdFx0fSlcblx0XHRcdC50aGVuQWx3YXlzKCgpID0+IHtcblx0XHRcdFx0aWYgKCF0aGlzLnBlbmRpbmdOYXZpZ2F0ZSkge1xuXHRcdFx0XHRcdHJlbW92ZUNsYXNzZXMoZ2xvYmFscy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsIHRoaXMubG9hZGluZ0Nzc0NsYXNzKTtcblx0XHRcdFx0XHR0aGlzLm1heWJlUmVzdG9yZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uKCk7XG5cdFx0XHRcdFx0dGhpcy5jYXB0dXJlU2Nyb2xsUG9zaXRpb25Gcm9tU2Nyb2xsRXZlbnQgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMuZW1pdCgnZW5kTmF2aWdhdGUnLCBlbmROYXZpZ2F0ZVBheWxvYWQpO1xuXHRcdFx0fSk7XG5cblx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZS5wYXRoID0gZXZlbnQucGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBQcmVmZXRjaGVzIHRoZSBzcGVjaWZpZWQgcGF0aCBpZiB0aGVyZSBpcyBhIHJvdXRlIGhhbmRsZXIgdGhhdCBtYXRjaGVzLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCB0byBuYXZpZ2F0ZSBjb250YWluaW5nIHRoZSBiYXNlIHBhdGguXG5cdCAqIEByZXR1cm4ge0NhbmNlbGxhYmxlUHJvbWlzZX0gUmV0dXJucyBhIHBlbmRpbmcgcmVxdWVzdCBjYW5jZWxsYWJsZSBwcm9taXNlLlxuXHQgKi9cblx0cHJlZmV0Y2gocGF0aCkge1xuXHRcdHZhciByb3V0ZSA9IHRoaXMuZmluZFJvdXRlKHBhdGgpO1xuXHRcdGlmICghcm91dGUpIHtcblx0XHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVqZWN0KG5ldyBDYW5jZWxsYWJsZVByb21pc2UuQ2FuY2VsbGF0aW9uRXJyb3IoJ05vIHJvdXRlIGZvciAnICsgcGF0aCkpO1xuXHRcdH1cblxuXHRcdGNvbnNvbGUubG9nKCdQcmVmZXRjaGluZyBbJyArIHBhdGggKyAnXScpO1xuXG5cdFx0dmFyIG5leHRTY3JlZW4gPSB0aGlzLmNyZWF0ZVNjcmVlbkluc3RhbmNlKHBhdGgsIHJvdXRlKTtcblxuXHRcdHJldHVybiBuZXh0U2NyZWVuLmxvYWQocGF0aClcblx0XHRcdC50aGVuKCgpID0+IHRoaXMuc2NyZWVuc1twYXRoXSA9IG5leHRTY3JlZW4pXG5cdFx0XHQuY2F0Y2goKHJlYXNvbikgPT4ge1xuXHRcdFx0XHR0aGlzLmhhbmRsZU5hdmlnYXRlRXJyb3JfKHBhdGgsIG5leHRTY3JlZW4sIHJlYXNvbik7XG5cdFx0XHRcdHRocm93IHJlYXNvbjtcblx0XHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByZXBhcmVzIHNjcmVlbiBmbGlwLiBVcGRhdGVzIGhpc3Rvcnkgc3RhdGUgYW5kIHN1cmZhY2VzIGNvbnRlbnQuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIGNvbnRhaW5pbmcgdGhlIHF1ZXJ5c3RyaW5nIHBhcnQuXG5cdCAqIEBwYXJhbSB7IVNjcmVlbn0gbmV4dFNjcmVlblxuXHQgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfcmVwbGFjZUhpc3RvcnkgUmVwbGFjZXMgYnJvd3NlciBoaXN0b3J5LlxuXHQgKi9cblx0cHJlcGFyZU5hdmlnYXRlSGlzdG9yeV8ocGF0aCwgbmV4dFNjcmVlbiwgb3B0X3JlcGxhY2VIaXN0b3J5KSB7XG5cdFx0bGV0IHRpdGxlID0gbmV4dFNjcmVlbi5nZXRUaXRsZSgpO1xuXHRcdGlmICghaXNTdHJpbmcodGl0bGUpKSB7XG5cdFx0XHR0aXRsZSA9IHRoaXMuZ2V0RGVmYXVsdFRpdGxlKCk7XG5cdFx0fVxuXHRcdGxldCByZWRpcmVjdFBhdGggPSBuZXh0U2NyZWVuLmJlZm9yZVVwZGF0ZUhpc3RvcnlQYXRoKHBhdGgpO1xuXHRcdGNvbnN0IGhpc3RvcnlTdGF0ZSA9IHtcblx0XHRcdGZvcm06IGlzRGVmQW5kTm90TnVsbChnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQpLFxuXHRcdFx0cGF0aCxcblx0XHRcdHJlZGlyZWN0UGF0aCxcblx0XHRcdHNjcm9sbExlZnQ6IDAsXG5cdFx0XHRzY3JvbGxUb3A6IDAsXG5cdFx0XHRzZW5uYTogdHJ1ZVxuXHRcdH07XG5cdFx0aWYgKG9wdF9yZXBsYWNlSGlzdG9yeSkge1xuXHRcdFx0aGlzdG9yeVN0YXRlLnNjcm9sbFRvcCA9IHRoaXMucG9wc3RhdGVTY3JvbGxUb3A7XG5cdFx0XHRoaXN0b3J5U3RhdGUuc2Nyb2xsTGVmdCA9IHRoaXMucG9wc3RhdGVTY3JvbGxMZWZ0O1xuXHRcdH1cblx0XHRjb25zdCBoYXNoID0gbmV3IFVyaShwYXRoKS5nZXRIYXNoKCk7XG5cdFx0cmVkaXJlY3RQYXRoID0gdGhpcy5tYXliZVJlc3RvcmVSZWRpcmVjdFBhdGhIYXNoXyhwYXRoLCByZWRpcmVjdFBhdGgsIGhhc2gpO1xuXHRcdHRoaXMudXBkYXRlSGlzdG9yeV8odGl0bGUsIHJlZGlyZWN0UGF0aCwgbmV4dFNjcmVlbi5iZWZvcmVVcGRhdGVIaXN0b3J5U3RhdGUoaGlzdG9yeVN0YXRlKSwgb3B0X3JlcGxhY2VIaXN0b3J5KTtcblx0XHR0aGlzLnJlZGlyZWN0UGF0aCA9IHJlZGlyZWN0UGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBQcmVwYXJlcyBzY3JlZW4gZmxpcC4gVXBkYXRlcyBoaXN0b3J5IHN0YXRlIGFuZCBzdXJmYWNlcyBjb250ZW50LlxuXHQgKiBAcGFyYW0geyFTY3JlZW59IG5leHRTY3JlZW5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBzdXJmYWNlcyBNYXAgb2Ygc3VyZmFjZXMgdG8gZmxpcCBrZXllZCBieSBzdXJmYWNlIGlkLlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IHBhcmFtcyBQYXJhbXMgZXh0cmFjdGVkIGZyb20gdGhlIGN1cnJlbnQgcGF0aC5cblx0ICovXG5cdHByZXBhcmVOYXZpZ2F0ZVN1cmZhY2VzXyhuZXh0U2NyZWVuLCBzdXJmYWNlcywgcGFyYW1zKSB7XG5cdFx0T2JqZWN0LmtleXMoc3VyZmFjZXMpLmZvckVhY2goKGlkKSA9PiB7XG5cdFx0XHR2YXIgc3VyZmFjZUNvbnRlbnQgPSBuZXh0U2NyZWVuLmdldFN1cmZhY2VDb250ZW50KGlkLCBwYXJhbXMpO1xuXHRcdFx0c3VyZmFjZXNbaWRdLmFkZENvbnRlbnQobmV4dFNjcmVlbi5nZXRJZCgpLCBzdXJmYWNlQ29udGVudCk7XG5cdFx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgbmV4dFNjcmVlbi5nZXRJZCgpICsgJ10gYWRkIGNvbnRlbnQgdG8gc3VyZmFjZSAnICtcblx0XHRcdFx0J1snICsgc3VyZmFjZXNbaWRdICsgJ10gWycgKyAoaXNEZWZBbmROb3ROdWxsKHN1cmZhY2VDb250ZW50KSA/ICcuLi4nIDogJ2VtcHR5JykgKyAnXScpO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbG9hZHMgdGhlIHBhZ2UgYnkgcGVyZm9ybWluZyBgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpYC5cblx0ICovXG5cdHJlbG9hZFBhZ2UoKSB7XG5cdFx0Z2xvYmFscy53aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyByb3V0ZSBpbnN0YW5jZSBmcm9tIGFwcCByb3V0ZXMuXG5cdCAqIEBwYXJhbSB7Um91dGV9IHJvdXRlXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgYW4gZWxlbWVudCB3YXMgcmVtb3ZlZC5cblx0ICovXG5cdHJlbW92ZVJvdXRlKHJvdXRlKSB7XG5cdFx0cmV0dXJuIGFycmF5LnJlbW92ZSh0aGlzLnJvdXRlcywgcm91dGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYSBzY3JlZW4uXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIGNvbnRhaW5pbmcgdGhlIHF1ZXJ5c3RyaW5nIHBhcnQuXG5cdCAqL1xuXHRyZW1vdmVTY3JlZW4ocGF0aCkge1xuXHRcdHZhciBzY3JlZW4gPSB0aGlzLnNjcmVlbnNbcGF0aF07XG5cdFx0aWYgKHNjcmVlbikge1xuXHRcdFx0T2JqZWN0LmtleXModGhpcy5zdXJmYWNlcykuZm9yRWFjaCgoc3VyZmFjZUlkKSA9PiB0aGlzLnN1cmZhY2VzW3N1cmZhY2VJZF0ucmVtb3ZlKHNjcmVlbi5nZXRJZCgpKSk7XG5cdFx0XHRzY3JlZW4uZGlzcG9zZSgpO1xuXHRcdFx0ZGVsZXRlIHRoaXMuc2NyZWVuc1twYXRoXTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU2F2ZXMgZ2l2ZW4gc2Nyb2xsIHBvc2l0aW9uIGludG8gaGlzdG9yeSBzdGF0ZS5cblx0ICogQHBhcmFtIHshbnVtYmVyfSBzY3JvbGxUb3AgTnVtYmVyIGNvbnRhaW5pbmcgdGhlIHRvcCBzY3JvbGwgcG9zaXRpb24gdG8gYmUgc2F2ZWQuXG5cdCAqIEBwYXJhbSB7IW51bWJlcn0gc2Nyb2xsTGVmdCBOdW1iZXIgY29udGFpbmluZyB0aGUgbGVmdCBzY3JvbGwgcG9zaXRpb24gdG8gYmUgc2F2ZWQuXG5cdCAqL1xuXHRzYXZlSGlzdG9yeUN1cnJlbnRQYWdlU2Nyb2xsUG9zaXRpb25fKHNjcm9sbFRvcCwgc2Nyb2xsTGVmdCkge1xuXHRcdHZhciBzdGF0ZSA9IGdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc3RhdGU7XG5cdFx0aWYgKHN0YXRlICYmIHN0YXRlLnNlbm5hKSB7XG5cdFx0XHRbc3RhdGUuc2Nyb2xsVG9wLCBzdGF0ZS5zY3JvbGxMZWZ0XSA9IFtzY3JvbGxUb3AsIHNjcm9sbExlZnRdO1xuXHRcdFx0Z2xvYmFscy53aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGUoc3RhdGUsIG51bGwsIG51bGwpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIGFsbG93IHByZXZlbnQgbmF2aWdhdGUuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gYWxsb3dQcmV2ZW50TmF2aWdhdGVcblx0ICovXG5cdHNldEFsbG93UHJldmVudE5hdmlnYXRlKGFsbG93UHJldmVudE5hdmlnYXRlKSB7XG5cdFx0dGhpcy5hbGxvd1ByZXZlbnROYXZpZ2F0ZSA9IGFsbG93UHJldmVudE5hdmlnYXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgbGluayBiYXNlIHBhdGguXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aFxuXHQgKi9cblx0c2V0QmFzZVBhdGgoYmFzZVBhdGgpIHtcblx0XHR0aGlzLmJhc2VQYXRoID0gdXRpbHMucmVtb3ZlUGF0aFRyYWlsaW5nU2xhc2goYmFzZVBhdGgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGRlZmF1bHQgcGFnZSB0aXRsZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGRlZmF1bHRUaXRsZVxuXHQgKi9cblx0c2V0RGVmYXVsdFRpdGxlKGRlZmF1bHRUaXRsZSkge1xuXHRcdHRoaXMuZGVmYXVsdFRpdGxlID0gZGVmYXVsdFRpdGxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGZvcm0gc2VsZWN0b3IuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gZm9ybVNlbGVjdG9yXG5cdCAqL1xuXHRzZXRGb3JtU2VsZWN0b3IoZm9ybVNlbGVjdG9yKSB7XG5cdFx0dGhpcy5mb3JtU2VsZWN0b3IgPSBmb3JtU2VsZWN0b3I7XG5cdFx0aWYgKHRoaXMuZm9ybUV2ZW50SGFuZGxlcl8pIHtcblx0XHRcdHRoaXMuZm9ybUV2ZW50SGFuZGxlcl8ucmVtb3ZlTGlzdGVuZXIoKTtcblx0XHR9XG5cdFx0dGhpcy5mb3JtRXZlbnRIYW5kbGVyXyA9IGRlbGVnYXRlKGRvY3VtZW50LCAnc3VibWl0JywgdGhpcy5mb3JtU2VsZWN0b3IsIHRoaXMub25Eb2NTdWJtaXREZWxlZ2F0ZV8uYmluZCh0aGlzKSwgdGhpcy5hbGxvd1ByZXZlbnROYXZpZ2F0ZSk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyBpZiByb3V0ZSBtYXRjaGluZyBzaG91bGQgaWdub3JlIHF1ZXJ5IHN0cmluZyBmcm9tIHRoZSByb3V0ZSBwYXRoLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IGlnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aFxuXHQgKi9cblx0c2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKGlnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aCkge1xuXHRcdHRoaXMuaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoID0gaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGxpbmsgc2VsZWN0b3IuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gbGlua1NlbGVjdG9yXG5cdCAqL1xuXHRzZXRMaW5rU2VsZWN0b3IobGlua1NlbGVjdG9yKSB7XG5cdFx0dGhpcy5saW5rU2VsZWN0b3IgPSBsaW5rU2VsZWN0b3I7XG5cdFx0aWYgKHRoaXMubGlua0V2ZW50SGFuZGxlcl8pIHtcblx0XHRcdHRoaXMubGlua0V2ZW50SGFuZGxlcl8ucmVtb3ZlTGlzdGVuZXIoKTtcblx0XHR9XG5cdFx0dGhpcy5saW5rRXZlbnRIYW5kbGVyXyA9IGRlbGVnYXRlKGRvY3VtZW50LCAnY2xpY2snLCB0aGlzLmxpbmtTZWxlY3RvciwgdGhpcy5vbkRvY0NsaWNrRGVsZWdhdGVfLmJpbmQodGhpcyksIHRoaXMuYWxsb3dQcmV2ZW50TmF2aWdhdGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGxvYWRpbmcgY3NzIGNsYXNzLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IGxvYWRpbmdDc3NDbGFzc1xuXHQgKi9cblx0c2V0TG9hZGluZ0Nzc0NsYXNzKGxvYWRpbmdDc3NDbGFzcykge1xuXHRcdHRoaXMubG9hZGluZ0Nzc0NsYXNzID0gbG9hZGluZ0Nzc0NsYXNzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHVwZGF0ZSBzY3JvbGwgcG9zaXRpb24gdmFsdWUuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gdXBkYXRlU2Nyb2xsUG9zaXRpb25cblx0ICovXG5cdHNldFVwZGF0ZVNjcm9sbFBvc2l0aW9uKHVwZGF0ZVNjcm9sbFBvc2l0aW9uKSB7XG5cdFx0dGhpcy51cGRhdGVTY3JvbGxQb3NpdGlvbiA9IHVwZGF0ZVNjcm9sbFBvc2l0aW9uO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbmNlbHMgcGVuZGluZyBuYXZpZ2F0ZSB3aXRoIDxjb2RlPkNhbmNlbCBwZW5kaW5nIG5hdmlnYXRpb248L2NvZGU+IGVycm9yLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRzdG9wUGVuZGluZ05hdmlnYXRlXygpIHtcblx0XHRpZiAodGhpcy5wZW5kaW5nTmF2aWdhdGUpIHtcblx0XHRcdHRoaXMucGVuZGluZ05hdmlnYXRlLmNhbmNlbCgnQ2FuY2VsIHBlbmRpbmcgbmF2aWdhdGlvbicpO1xuXHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUgPSBudWxsO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTeW5jIGRvY3VtZW50IHNjcm9sbCBwb3NpdGlvbiB0d2ljZSwgdGhlIGZpcnN0IG9uZSBzeW5jaHJvbm91cyBhbmQgdGhlblxuXHQgKiBvbmUgaW5zaWRlIDxjb2RlPmFzeW5jLm5leHRUaWNrPC9jb2RlPi4gUmVsZXZhbnQgdG8gYnJvd3NlcnMgdGhhdCBmaXJlc1xuXHQgKiBzY3JvbGwgcmVzdG9yYXRpb24gYXN5bmNocm9ub3VzbHkgYWZ0ZXIgcG9wc3RhdGUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQHJldHVybiB7P0NhbmNlbGxhYmxlUHJvbWlzZT19XG5cdCAqL1xuXHRzeW5jU2Nyb2xsUG9zaXRpb25TeW5jVGhlbkFzeW5jXygpIHtcblx0XHR2YXIgc3RhdGUgPSBnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnN0YXRlO1xuXHRcdGlmICghc3RhdGUpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgc2Nyb2xsVG9wID0gc3RhdGUuc2Nyb2xsVG9wO1xuXHRcdHZhciBzY3JvbGxMZWZ0ID0gc3RhdGUuc2Nyb2xsTGVmdDtcblxuXHRcdHZhciBzeW5jID0gKCkgPT4ge1xuXHRcdFx0aWYgKHRoaXMudXBkYXRlU2Nyb2xsUG9zaXRpb24pIHtcblx0XHRcdFx0Z2xvYmFscy53aW5kb3cuc2Nyb2xsVG8oc2Nyb2xsTGVmdCwgc2Nyb2xsVG9wKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0cmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUpID0+IHN5bmMoKSAmIGFzeW5jLm5leHRUaWNrKCgpID0+IHN5bmMoKSAmIHJlc29sdmUoKSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZXMgb3IgcmVwbGFjZSBicm93c2VyIGhpc3RvcnkuXG5cdCAqIEBwYXJhbSB7P3N0cmluZ30gdGl0bGUgRG9jdW1lbnQgdGl0bGUuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIGNvbnRhaW5pbmcgdGhlIHF1ZXJ5c3RyaW5nIHBhcnQuXG5cdCAqIEBwYXJhbSB7IW9iamVjdH0gc3RhdGVcblx0ICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3JlcGxhY2VIaXN0b3J5IFJlcGxhY2VzIGJyb3dzZXIgaGlzdG9yeS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dXBkYXRlSGlzdG9yeV8odGl0bGUsIHBhdGgsIHN0YXRlLCBvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHRpZiAob3B0X3JlcGxhY2VIaXN0b3J5KSB7XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShzdGF0ZSwgdGl0bGUsIHBhdGgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnB1c2hTdGF0ZShzdGF0ZSwgdGl0bGUsIHBhdGgpO1xuXHRcdH1cblxuXHRcdGxldCB0aXRsZU5vZGUgPSBnbG9iYWxzLmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3RpdGxlJyk7XG5cdFx0aWYgKHRpdGxlTm9kZSkge1xuXHRcdFx0dGl0bGVOb2RlLmlubmVySFRNTCA9IHRpdGxlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRnbG9iYWxzLmRvY3VtZW50LnRpdGxlID0gdGl0bGU7XG5cdFx0fVxuXHR9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgQXBwO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBpc0RlZiwgaXNEZWZBbmROb3ROdWxsIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IFVyaSBmcm9tICdtZXRhbC11cmknO1xuaW1wb3J0IHsgQ2FuY2VsbGFibGVQcm9taXNlIGFzIFByb21pc2UgfSBmcm9tICdtZXRhbC1wcm9taXNlJztcblxuY2xhc3MgQWpheCB7XG5cblx0LyoqXG5cdCAqIFhtbEh0dHBSZXF1ZXN0J3MgZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkgbWV0aG9kIHJldHVybnMgYSBzdHJpbmcgb2Zcblx0ICogcmVzcG9uc2UgaGVhZGVycyBhY2NvcmRpbmcgdG8gdGhlIGZvcm1hdCBkZXNjcmliZWQgb24gdGhlIHNwZWM6XG5cdCAqIHtAbGluayBodHRwOi8vd3d3LnczLm9yZy9UUi9YTUxIdHRwUmVxdWVzdC8jdGhlLWdldGFsbHJlc3BvbnNlaGVhZGVycy1tZXRob2R9LlxuXHQgKiBUaGlzIG1ldGhvZCBwYXJzZXMgdGhhdCBzdHJpbmcgaW50byBhIHVzZXItZnJpZW5kbHkgbmFtZS92YWx1ZSBwYWlyXG5cdCAqIG9iamVjdC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGFsbEhlYWRlcnMgQWxsIGhlYWRlcnMgYXMgc3RyaW5nLlxuXHQgKiBAcmV0dXJuIHshQXJyYXkuPE9iamVjdDxzdHJpbmcsIHN0cmluZz4+fVxuXHQgKi9cblx0c3RhdGljIHBhcnNlUmVzcG9uc2VIZWFkZXJzKGFsbEhlYWRlcnMpIHtcblx0XHR2YXIgaGVhZGVycyA9IFtdO1xuXHRcdGlmICghYWxsSGVhZGVycykge1xuXHRcdFx0cmV0dXJuIGhlYWRlcnM7XG5cdFx0fVxuXHRcdHZhciBwYWlycyA9IGFsbEhlYWRlcnMuc3BsaXQoJ1xcdTAwMGRcXHUwMDBhJyk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwYWlycy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIGluZGV4ID0gcGFpcnNbaV0uaW5kZXhPZignXFx1MDAzYVxcdTAwMjAnKTtcblx0XHRcdGlmIChpbmRleCA+IDApIHtcblx0XHRcdFx0dmFyIG5hbWUgPSBwYWlyc1tpXS5zdWJzdHJpbmcoMCwgaW5kZXgpO1xuXHRcdFx0XHR2YXIgdmFsdWUgPSBwYWlyc1tpXS5zdWJzdHJpbmcoaW5kZXggKyAyKTtcblx0XHRcdFx0aGVhZGVycy5wdXNoKHtcblx0XHRcdFx0XHRuYW1lOiBuYW1lLFxuXHRcdFx0XHRcdHZhbHVlOiB2YWx1ZVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGhlYWRlcnM7XG5cdH1cblxuXHQvKipcblx0ICogUmVxdWVzdHMgdGhlIHVybCB1c2luZyBYTUxIdHRwUmVxdWVzdC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSB1cmxcblx0ICogQHBhcmFtIHshc3RyaW5nfSBtZXRob2Rcblx0ICogQHBhcmFtIHs/c3RyaW5nfSBib2R5XG5cdCAqIEBwYXJhbSB7TXVsdGlNYXA9fSBvcHRfaGVhZGVyc1xuXHQgKiBAcGFyYW0ge011bHRpTWFwPX0gb3B0X3BhcmFtc1xuXHQgKiBAcGFyYW0ge251bWJlcj19IG9wdF90aW1lb3V0XG5cdCAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9zeW5jXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF93aXRoQ3JlZGVudGlhbHNcblx0ICogQHJldHVybiB7UHJvbWlzZX0gRGVmZXJyZWQgYWpheCByZXF1ZXN0LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRzdGF0aWMgcmVxdWVzdCh1cmwsIG1ldGhvZCwgYm9keSwgb3B0X2hlYWRlcnMsIG9wdF9wYXJhbXMsIG9wdF90aW1lb3V0LCBvcHRfc3luYywgb3B0X3dpdGhDcmVkZW50aWFscykge1xuXHRcdHVybCA9IHVybCB8fCAnJztcblx0XHRtZXRob2QgPSBtZXRob2QgfHwgJ0dFVCc7XG5cblx0XHR2YXIgcmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuXHRcdHZhciBwcmV2aW91c1JlYWR5U3RhdGUgPSAwO1xuXG5cdFx0dmFyIHByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcblx0XHRcdHJlcXVlc3Qub25sb2FkID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmIChyZXF1ZXN0LmFib3J0ZWQpIHtcblx0XHRcdFx0XHRyZXF1ZXN0Lm9uZXJyb3IoKTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0cmVzb2x2ZShyZXF1ZXN0KTtcblx0XHRcdH07XG5cdFx0XHRyZXF1ZXN0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAocHJldmlvdXNSZWFkeVN0YXRlICYmIHByZXZpb3VzUmVhZHlTdGF0ZSA8IDMgJiYgNCA9PT0gcmVxdWVzdC5yZWFkeVN0YXRlKSB7XG5cdFx0XHRcdFx0cmVxdWVzdC50ZXJtaW5hdGVkUHJlbWF0dXJlbHkgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHByZXZpb3VzUmVhZHlTdGF0ZSA9IHJlcXVlc3QucmVhZHlTdGF0ZTtcblx0XHRcdH07XG5cdFx0XHRyZXF1ZXN0Lm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIG1lc3NhZ2UgPSAnUmVxdWVzdCBlcnJvcic7XG5cdFx0XHRcdGlmIChyZXF1ZXN0LnRlcm1pbmF0ZWRQcmVtYXR1cmVseSkge1xuXHRcdFx0XHRcdG1lc3NhZ2UgPSAnUmVxdWVzdCB0ZXJtaW5hdGVkIHByZW1hdHVyZWx5Jztcblx0XHRcdFx0fSBcblx0XHRcdFx0dmFyIGVycm9yID0gbmV3IEVycm9yKG1lc3NhZ2UpO1xuXHRcdFx0XHRlcnJvci5yZXF1ZXN0ID0gcmVxdWVzdDtcblx0XHRcdFx0cmVqZWN0KGVycm9yKTtcblx0XHRcdH07XG5cdFx0fSkudGhlbkNhdGNoKGZ1bmN0aW9uKHJlYXNvbikge1xuXHRcdFx0cmVxdWVzdC5hYm9ydCgpO1xuXHRcdFx0dGhyb3cgcmVhc29uO1xuXHRcdH0pLnRoZW5BbHdheXMoZnVuY3Rpb24oKSB7XG5cdFx0XHRjbGVhclRpbWVvdXQodGltZW91dCk7XG5cdFx0fSk7XG5cblx0XHR1cmwgPSBuZXcgVXJpKHVybCk7XG5cblx0XHRpZiAob3B0X3BhcmFtcykge1xuXHRcdFx0dXJsLmFkZFBhcmFtZXRlcnNGcm9tTXVsdGlNYXAob3B0X3BhcmFtcykudG9TdHJpbmcoKTtcblx0XHR9XG5cblx0XHR1cmwgPSB1cmwudG9TdHJpbmcoKTtcblxuXHRcdHJlcXVlc3Qub3BlbihtZXRob2QsIHVybCwgIW9wdF9zeW5jKTtcblxuXHRcdGlmIChvcHRfd2l0aENyZWRlbnRpYWxzKSB7XG5cdFx0XHRyZXF1ZXN0LndpdGhDcmVkZW50aWFscyA9IHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdF9oZWFkZXJzKSB7XG5cdFx0XHRvcHRfaGVhZGVycy5uYW1lcygpLmZvckVhY2goZnVuY3Rpb24obmFtZSkge1xuXHRcdFx0XHRyZXF1ZXN0LnNldFJlcXVlc3RIZWFkZXIobmFtZSwgb3B0X2hlYWRlcnMuZ2V0QWxsKG5hbWUpLmpvaW4oJywgJykpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0cmVxdWVzdC5zZW5kKGlzRGVmKGJvZHkpID8gYm9keSA6IG51bGwpO1xuXG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChvcHRfdGltZW91dCkpIHtcblx0XHRcdHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHRcdFx0cHJvbWlzZS5jYW5jZWwoJ1JlcXVlc3QgdGltZW91dCcpO1xuXHRcdFx0fSwgb3B0X3RpbWVvdXQpO1xuXHRcdH1cblxuXHRcdHJldHVybiBwcm9taXNlO1xuXHR9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgQWpheDtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBIb2xkcyB2YWx1ZSBlcnJvciBtZXNzYWdlcy5cbiAqIEBjb25zdFxuICovXG5jbGFzcyBlcnJvcnMge1xufVxuXG4vKipcbiAqIEludmFsaWQgc3RhdHVzIGVycm9yIG1lc3NhZ2UuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQHN0YXRpY1xuICovXG5lcnJvcnMuSU5WQUxJRF9TVEFUVVMgPSAnSW52YWxpZCBzdGF0dXMgY29kZSc7XG5cbi8qKlxuICogUmVxdWVzdCBlcnJvciBtZXNzYWdlLlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBzdGF0aWNcbiAqL1xuZXJyb3JzLlJFUVVFU1RfRVJST1IgPSAnUmVxdWVzdCBlcnJvcic7XG5cbi8qKlxuICogUmVxdWVzdCB0aW1lb3V0IGVycm9yIG1lc3NhZ2UuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQHN0YXRpY1xuICovXG5lcnJvcnMuUkVRVUVTVF9USU1FT1VUID0gJ1JlcXVlc3QgdGltZW91dCc7XG5cbi8qKlxuICogUmVxdWVzdCBpcyBibG9ja2VkIGJ5IENPUlMgaXNzdWUgbWVzc2FnZS5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cbmVycm9ycy5SRVFVRVNUX1BSRU1BVFVSRV9URVJNSU5BVElPTiA9ICdSZXF1ZXN0IHRlcm1pbmF0ZWQgcHJlbWF0dXJlbHknO1xuXG5leHBvcnQgZGVmYXVsdCBlcnJvcnM7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogTWV0YWwuanMgYnJvd3NlciB1c2VyIGFnZW50IGRldGVjdGlvbi4gSXQncyBleHRyZW1lbHkgcmVjb21tZW5kZWQgdGhlIHVzYWdlXG4gKiBvZiBmZWF0dXJlIGNoZWNraW5nIG92ZXIgYnJvd3NlciB1c2VyIGFnZW50IHNuaWZmaW5nLiBVbmZvcnR1bmF0ZWx5LCBpbiBzb21lXG4gKiBzaXR1YXRpb25zIGZlYXR1cmUgY2hlY2tpbmcgY2FuIGJlIHNsb3cgb3IgZXZlbiBpbXBvc3NpYmxlLCB0aGVyZWZvcmUgdXNlXG4gKiB0aGlzIHV0aWxpdHkgd2l0aCBjYXV0aW9uLlxuICogQHNlZSA8YSBocmVmPVwiaHR0cDovL3d3dy51c2VyYWdlbnRzdHJpbmcuY29tL1wiPlVzZXIgYWdlbnQgc3RyaW5nczwvYT4uXG4gKi9cbmNsYXNzIFVBIHtcblx0LyoqXG5cdCAqIEdldHMgdGhlIG5hdGl2ZSB1c2VyQWdlbnQgc3RyaW5nIGZyb20gbmF2aWdhdG9yIGlmIGl0IGV4aXN0cy4gSWZcblx0ICogbmF2aWdhdG9yIG9yIG5hdmlnYXRvci51c2VyQWdlbnQgc3RyaW5nIGlzIG1pc3NpbmcsIHJldHVybnMgYW4gZW1wdHlcblx0ICogc3RyaW5nLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqIEBwcml2YXRlXG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBnZXROYXRpdmVVc2VyQWdlbnQoKSB7XG5cdFx0dmFyIG5hdmlnYXRvciA9IFVBLmdsb2JhbHMud2luZG93Lm5hdmlnYXRvcjtcblx0XHRpZiAobmF2aWdhdG9yKSB7XG5cdFx0XHR2YXIgdXNlckFnZW50ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcblx0XHRcdGlmICh1c2VyQWdlbnQpIHtcblx0XHRcdFx0cmV0dXJuIHVzZXJBZ2VudDtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuICcnO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIG5hdGl2ZSBwbGF0Zm9ybSBzdHJpbmcgZnJvbSBuYXZpZ2F0b3IgaWYgaXQgZXhpc3RzLiBJZlxuXHQgKiBuYXZpZ2F0b3Igb3IgbmF2aWdhdG9yLnBsYXRmb3JtIHN0cmluZyBpcyBtaXNzaW5nLCByZXR1cm5zIGFuIGVtcHR5XG5cdCAqIHN0cmluZy5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0TmF0aXZlUGxhdGZvcm0oKSB7XG5cdFx0dmFyIG5hdmlnYXRvciA9IFVBLmdsb2JhbHMud2luZG93Lm5hdmlnYXRvcjtcblx0XHRpZiAobmF2aWdhdG9yKSB7XG5cdFx0XHR2YXIgcGxhdGZvcm0gPSBuYXZpZ2F0b3IucGxhdGZvcm07XG5cdFx0XHRpZiAocGxhdGZvcm0pIHtcblx0XHRcdFx0cmV0dXJuIHBsYXRmb3JtO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gJyc7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgcGxhdGZvcm0gY29udGFpbnMgdGhlIGdpdmVuIHN0cmluZywgaWdub3JpbmcgY2FzZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHN0clxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAc3RhdGljXG5cdCovXG5cdHN0YXRpYyBtYXRjaFBsYXRmb3JtKHN0cikge1xuXHRcdHJldHVybiBVQS5wbGF0Zm9ybS5pbmRleE9mKHN0cikgIT09IC0xO1xuXHR9XG5cblx0LyoqXG5cdCAqIFdoZXRoZXIgdGhlIHVzZXIgYWdlbnQgY29udGFpbnMgdGhlIGdpdmVuIHN0cmluZywgaWdub3JpbmcgY2FzZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHN0clxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAc3RhdGljXG5cdCovXG5cdHN0YXRpYyBtYXRjaFVzZXJBZ2VudChzdHIpIHtcblx0XHRyZXR1cm4gVUEudXNlckFnZW50LmluZGV4T2Yoc3RyKSAhPT0gLTE7XG5cdH1cblxuXHQvKipcblx0ICogVGVzdHMgdGhlIHVzZXIgYWdlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyQWdlbnQgVGhlIHVzZXIgYWdlbnQgc3RyaW5nLlxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgdGVzdFVzZXJBZ2VudCh1c2VyQWdlbnQgPSAnJywgcGxhdGZvcm0gPSAnJykge1xuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSB1c2VyIGFnZW50IHZhbHVlIGV4dHJhY3RlZCBmcm9tIGJyb3dzZXIgbmF0aXZlIHVzZXIgYWdlbnQuXG5cdFx0ICogQHR5cGUge3N0cmluZ31cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEudXNlckFnZW50ID0gdXNlckFnZW50O1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHBsYXRmb3JtIHZhbHVlIGV4dHJhY3RlZCBmcm9tIGJyb3dzZXIgbmF0aXZlIHBsYXRmb3JtLlxuXHRcdCAqIEB0eXBlIHtzdHJpbmd9XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLnBsYXRmb3JtID0gcGxhdGZvcm07XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgT1MgaXMgTWFjLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc01hYyA9IFVBLm1hdGNoUGxhdGZvcm0oJ01hYycpO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIE9TIGlzIFdpbi5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNXaW4gPSBVQS5tYXRjaFBsYXRmb3JtKCdXaW4nKTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBicm93c2VyIGlzIE9wZXJhLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc09wZXJhID0gVUEubWF0Y2hVc2VyQWdlbnQoJ09wZXJhJykgfHwgVUEubWF0Y2hVc2VyQWdlbnQoJ09QUicpO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgSUUuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzSWUgPSBVQS5tYXRjaFVzZXJBZ2VudCgnVHJpZGVudCcpIHx8IFVBLm1hdGNoVXNlckFnZW50KCdNU0lFJyk7XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgYnJvd3NlciBpcyBFZGdlLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc0VkZ2UgPSBVQS5tYXRjaFVzZXJBZ2VudCgnRWRnZScpO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgSUUgb3IgRWRnZS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNJZU9yRWRnZSA9IFVBLmlzSWUgfHwgVUEuaXNFZGdlO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgQ2hyb21lLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc0Nocm9tZSA9IChVQS5tYXRjaFVzZXJBZ2VudCgnQ2hyb21lJykgfHwgVUEubWF0Y2hVc2VyQWdlbnQoJ0NyaU9TJykpICYmICFVQS5pc09wZXJhICYmICFVQS5pc0VkZ2U7XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgYnJvd3NlciBpcyBTYWZhcmkuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzU2FmYXJpID0gVUEubWF0Y2hVc2VyQWdlbnQoJ1NhZmFyaScpICYmICEoVUEuaXNDaHJvbWUgfHwgVUEuaXNPcGVyYSB8fCBVQS5pc0VkZ2UpO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgRmlyZWZveC5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNGaXJlZm94ID0gVUEubWF0Y2hVc2VyQWdlbnQoJ0ZpcmVmb3gnKTtcblx0fVxufVxuXG4vKipcbiAqIEV4cG9zZXMgZ2xvYmFsIHJlZmVyZW5jZXMuXG4gKiBAdHlwZSB7b2JqZWN0fVxuICogQHN0YXRpY1xuICovXG5VQS5nbG9iYWxzID0ge1xuXHR3aW5kb3c6IHdpbmRvd1xufTtcblxuVUEudGVzdFVzZXJBZ2VudChVQS5nZXROYXRpdmVVc2VyQWdlbnQoKSwgVUEuZ2V0TmF0aXZlUGxhdGZvcm0oKSk7XG5cbmV4cG9ydCBkZWZhdWx0IFVBO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBpc0RlZkFuZE5vdE51bGwgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgQWpheCBmcm9tICdtZXRhbC1hamF4JztcbmltcG9ydCB7IE11bHRpTWFwIH0gZnJvbSAnbWV0YWwtc3RydWN0cyc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuaW1wb3J0IGVycm9ycyBmcm9tICcuLi9lcnJvcnMvZXJyb3JzJztcbmltcG9ydCB1dGlscyBmcm9tICcuLi91dGlscy91dGlscyc7XG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IFNjcmVlbiBmcm9tICcuL1NjcmVlbic7XG5pbXBvcnQgVXJpIGZyb20gJ21ldGFsLXVyaSc7XG5pbXBvcnQgVUEgZnJvbSAnbWV0YWwtdXNlcmFnZW50JztcblxuY2xhc3MgUmVxdWVzdFNjcmVlbiBleHRlbmRzIFNjcmVlbiB7XG5cblx0LyoqXG5cdCAqIFJlcXVlc3Qgc2NyZWVuIGFic3RyYWN0IGNsYXNzIHRvIHBlcmZvcm0gaW8gb3BlcmF0aW9ucyBvbiBkZXNjZW5kYW50XG5cdCAqIHNjcmVlbnMuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKiBAZXh0ZW5kcyB7U2NyZWVufVxuXHQgKi9cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEBpbmhlcml0RG9jXG5cdFx0ICogQGRlZmF1bHQgdHJ1ZVxuXHRcdCAqL1xuXHRcdHRoaXMuY2FjaGVhYmxlID0gdHJ1ZTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGRlZmF1bHQgaHR0cCBoZWFkZXJzIHRvIHNldCBvbiByZXF1ZXN0LlxuXHRcdCAqIEB0eXBlIHs/T2JqZWN0PX1cblx0XHQgKiBAZGVmYXVsdCB7XG5cdFx0ICogICAnWC1QSkFYJzogJ3RydWUnLFxuXHRcdCAqICAgJ1gtUmVxdWVzdGVkLVdpdGgnOiAnWE1MSHR0cFJlcXVlc3QnXG5cdFx0ICogfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmh0dHBIZWFkZXJzID0ge1xuXHRcdFx0J1gtUEpBWCc6ICd0cnVlJyxcblx0XHRcdCdYLVJlcXVlc3RlZC1XaXRoJzogJ1hNTEh0dHBSZXF1ZXN0J1xuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBkZWZhdWx0IGh0dHAgbWV0aG9kIHRvIHBlcmZvcm0gdGhlIHJlcXVlc3QuXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgUmVxdWVzdFNjcmVlbi5HRVRcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5odHRwTWV0aG9kID0gUmVxdWVzdFNjcmVlbi5HRVQ7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgWEhSIG9iamVjdCByZXNwb25zaWJsZSBmb3IgdGhlIHJlcXVlc3QuXG5cdFx0ICogQHR5cGUge1hNTEh0dHBSZXF1ZXN0fVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5yZXF1ZXN0ID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSByZXF1ZXN0IHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzLlxuXHRcdCAqIEB0eXBlIHshbnVtYmVyfVxuXHRcdCAqIEBkZWZhdWx0IDMwMDAwXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudGltZW91dCA9IDMwMDAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFzc2VydHMgdGhhdCByZXNwb25zZSBzdGF0dXMgY29kZSBpcyB2YWxpZC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHN0YXR1c1xuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRhc3NlcnRWYWxpZFJlc3BvbnNlU3RhdHVzQ29kZShzdGF0dXMpIHtcblx0XHRpZiAoIXRoaXMuaXNWYWxpZFJlc3BvbnNlU3RhdHVzQ29kZShzdGF0dXMpKSB7XG5cdFx0XHR2YXIgZXJyb3IgPSBuZXcgRXJyb3IoZXJyb3JzLklOVkFMSURfU1RBVFVTKTtcblx0XHRcdGVycm9yLmludmFsaWRTdGF0dXMgPSB0cnVlO1xuXHRcdFx0ZXJyb3Iuc3RhdHVzQ29kZSA9IHN0YXR1cztcblx0XHRcdHRocm93IGVycm9yO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0YmVmb3JlVXBkYXRlSGlzdG9yeVBhdGgocGF0aCkge1xuXHRcdHZhciByZWRpcmVjdFBhdGggPSB0aGlzLmdldFJlcXVlc3RQYXRoKCk7XG5cdFx0aWYgKHJlZGlyZWN0UGF0aCAmJiByZWRpcmVjdFBhdGggIT09IHBhdGgpIHtcblx0XHRcdHJldHVybiByZWRpcmVjdFBhdGg7XG5cdFx0fVxuXHRcdHJldHVybiBwYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRiZWZvcmVVcGRhdGVIaXN0b3J5U3RhdGUoc3RhdGUpIHtcblx0XHQvLyBJZiBzdGF0ZSBpcyBvdXJzIGFuZCBuYXZpZ2F0ZSB0byBwb3N0LXdpdGhvdXQtcmVkaXJlY3QtZ2V0IHNldFxuXHRcdC8vIGhpc3Rvcnkgc3RhdGUgdG8gbnVsbCwgdGhhdCB3YXkgU2VubmEgd2lsbCByZWxvYWQgdGhlIHBhZ2Ugb25cblx0XHQvLyBwb3BzdGF0ZSBzaW5jZSBpdCBjYW5ub3QgcHJlZGljdCBwb3N0IGRhdGEuXG5cdFx0aWYgKHN0YXRlLnNlbm5hICYmIHN0YXRlLmZvcm0gJiYgc3RhdGUucmVkaXJlY3RQYXRoID09PSBzdGF0ZS5wYXRoKSB7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cdFx0cmV0dXJuIHN0YXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZvcm1hdHMgbG9hZCBwYXRoIGJlZm9yZSBpbnZva2luZyBhamF4IGNhbGwuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gRm9ybWF0dGVkIHBhdGg7XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGZvcm1hdExvYWRQYXRoKHBhdGgpIHtcblx0XHR2YXIgdXJpID0gbmV3IFVyaShwYXRoKTtcblxuXHRcdHVyaS5zZXRIb3N0bmFtZShnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5ob3N0bmFtZSk7XG5cdFx0dXJpLnNldFByb3RvY29sKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnByb3RvY29sKTtcblxuXHRcdGlmIChnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5wb3J0KSB7XG5cdFx0XHR1cmkuc2V0UG9ydChnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5wb3J0KTtcblx0XHR9XG5cblx0XHRpZiAoVUEuaXNJZU9yRWRnZSAmJiB0aGlzLmh0dHBNZXRob2QgPT09IFJlcXVlc3RTY3JlZW4uR0VUKSB7XG5cdFx0XHRyZXR1cm4gdXJpLm1ha2VVbmlxdWUoKS50b1N0cmluZygpO1xuXHRcdH1cblxuXHRcdHJldHVybiB1cmkudG9TdHJpbmcoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBodHRwIGhlYWRlcnMuXG5cdCAqIEByZXR1cm4gez9PYmplY3Q9fVxuXHQgKi9cblx0Z2V0SHR0cEhlYWRlcnMoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaHR0cEhlYWRlcnM7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgaHR0cCBtZXRob2QuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqL1xuXHRnZXRIdHRwTWV0aG9kKCkge1xuXHRcdHJldHVybiB0aGlzLmh0dHBNZXRob2Q7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyByZXF1ZXN0IHBhdGguXG5cdCAqIEByZXR1cm4ge3N0cmluZz19XG5cdCAqL1xuXHRnZXRSZXF1ZXN0UGF0aCgpIHtcblx0XHR2YXIgcmVxdWVzdCA9IHRoaXMuZ2V0UmVxdWVzdCgpO1xuXHRcdGlmIChyZXF1ZXN0KSB7XG5cdFx0XHR2YXIgcmVxdWVzdFBhdGggPSByZXF1ZXN0LnJlcXVlc3RQYXRoO1xuXHRcdFx0dmFyIHJlc3BvbnNlVXJsID0gdGhpcy5tYXliZUV4dHJhY3RSZXNwb25zZVVybEZyb21SZXF1ZXN0KHJlcXVlc3QpO1xuXHRcdFx0aWYgKHJlc3BvbnNlVXJsKSB7XG5cdFx0XHRcdHJlcXVlc3RQYXRoID0gcmVzcG9uc2VVcmw7XG5cdFx0XHR9XG5cdFx0XHRpZiAoVUEuaXNJZU9yRWRnZSAmJiB0aGlzLmh0dHBNZXRob2QgPT09IFJlcXVlc3RTY3JlZW4uR0VUKSB7XG5cdFx0XHRcdHJlcXVlc3RQYXRoID0gbmV3IFVyaShyZXF1ZXN0UGF0aCkucmVtb3ZlVW5pcXVlKCkudG9TdHJpbmcoKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB1dGlscy5nZXRVcmxQYXRoKHJlcXVlc3RQYXRoKTtcblx0XHR9XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcmVxdWVzdCBvYmplY3QuXG5cdCAqIEByZXR1cm4gez9PYmplY3R9XG5cdCAqL1xuXHRnZXRSZXF1ZXN0KCkge1xuXHRcdHJldHVybiB0aGlzLnJlcXVlc3Q7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcmVxdWVzdCB0aW1lb3V0LlxuXHQgKiBAcmV0dXJuIHshbnVtYmVyfVxuXHQgKi9cblx0Z2V0VGltZW91dCgpIHtcblx0XHRyZXR1cm4gdGhpcy50aW1lb3V0O1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiByZXNwb25zZSBzdWNjZWVkZWQuIEFueSBzdGF0dXMgY29kZSAyeHggb3IgM3h4IGlzIGNvbnNpZGVyZWRcblx0ICogdmFsaWQuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBzdGF0dXNDb2RlXG5cdCAqL1xuXHRpc1ZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlKHN0YXR1c0NvZGUpIHtcblx0XHRyZXR1cm4gc3RhdHVzQ29kZSA+PSAyMDAgJiYgc3RhdHVzQ29kZSA8PSAzOTk7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGxvYWQocGF0aCkge1xuXHRcdGNvbnN0IGNhY2hlID0gdGhpcy5nZXRDYWNoZSgpO1xuXHRcdGlmIChpc0RlZkFuZE5vdE51bGwoY2FjaGUpKSB7XG5cdFx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUoY2FjaGUpO1xuXHRcdH1cblx0XHRsZXQgYm9keSA9IG51bGw7XG5cdFx0bGV0IGh0dHBNZXRob2QgPSB0aGlzLmh0dHBNZXRob2Q7XG5cdFx0Y29uc3QgaGVhZGVycyA9IG5ldyBNdWx0aU1hcCgpO1xuXHRcdE9iamVjdC5rZXlzKHRoaXMuaHR0cEhlYWRlcnMpLmZvckVhY2goaGVhZGVyID0+IGhlYWRlcnMuYWRkKGhlYWRlciwgdGhpcy5odHRwSGVhZGVyc1toZWFkZXJdKSk7XG5cdFx0aWYgKGdsb2JhbHMuY2FwdHVyZWRGb3JtRWxlbWVudCkge1xuXHRcdFx0Ym9keSA9IG5ldyBGb3JtRGF0YShnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQpO1xuXHRcdFx0dGhpcy5tYXliZUFwcGVuZFN1Ym1pdEJ1dHRvblZhbHVlXyhib2R5KTtcblx0XHRcdGh0dHBNZXRob2QgPSBSZXF1ZXN0U2NyZWVuLlBPU1Q7XG5cdFx0XHRpZiAoVUEuaXNJZU9yRWRnZSkge1xuXHRcdFx0XHRoZWFkZXJzLmFkZCgnSWYtTm9uZS1NYXRjaCcsICdcIjBcIicpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRjb25zdCByZXF1ZXN0UGF0aCA9IHRoaXMuZm9ybWF0TG9hZFBhdGgocGF0aCk7XG5cdFx0cmV0dXJuIEFqYXhcblx0XHRcdC5yZXF1ZXN0KHJlcXVlc3RQYXRoLCBodHRwTWV0aG9kLCBib2R5LCBoZWFkZXJzLCBudWxsLCB0aGlzLnRpbWVvdXQpXG5cdFx0XHQudGhlbih4aHIgPT4ge1xuXHRcdFx0XHR0aGlzLnNldFJlcXVlc3QoeGhyKTtcblx0XHRcdFx0dGhpcy5hc3NlcnRWYWxpZFJlc3BvbnNlU3RhdHVzQ29kZSh4aHIuc3RhdHVzKTtcblx0XHRcdFx0aWYgKGh0dHBNZXRob2QgPT09IFJlcXVlc3RTY3JlZW4uR0VUICYmIHRoaXMuaXNDYWNoZWFibGUoKSkge1xuXHRcdFx0XHRcdHRoaXMuYWRkQ2FjaGUoeGhyLnJlc3BvbnNlVGV4dCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0eGhyLnJlcXVlc3RQYXRoID0gcmVxdWVzdFBhdGg7XG5cdFx0XHRcdHJldHVybiB4aHIucmVzcG9uc2VUZXh0O1xuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdHN3aXRjaCAocmVhc29uLm1lc3NhZ2UpIHtcblx0XHRcdFx0XHRjYXNlIGVycm9ycy5SRVFVRVNUX1RJTUVPVVQ6XG5cdFx0XHRcdFx0XHRyZWFzb24udGltZW91dCA9IHRydWU7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIGVycm9ycy5SRVFVRVNUX0VSUk9SOlxuXHRcdFx0XHRcdFx0cmVhc29uLnJlcXVlc3RFcnJvciA9IHRydWU7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIGVycm9ycy5SRVFVRVNUX1BSRU1BVFVSRV9URVJNSU5BVElPTjpcblx0XHRcdFx0XHRcdHJlYXNvbi5yZXF1ZXN0RXJyb3IgPSB0cnVlO1xuXHRcdFx0XHRcdFx0cmVhc29uLnJlcXVlc3RQcmVtYXR1cmVUZXJtaW5hdGlvbiA9IHRydWU7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0XHR0aHJvdyByZWFzb247XG5cdFx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGFkaXRpb25hbCBkYXRhIHRvIHRoZSBib2R5IG9mIHRoZSByZXF1ZXN0IGluIGNhc2UgYSBzdWJtaXQgYnV0dG9uXG5cdCAqIGlzIGNhcHR1cmVkIGR1cmluZyBmb3JtIHN1Ym1pc3Npb24uXG5cdCAqIEBwYXJhbSB7IUZvcm1EYXRhfSBib2R5IFRoZSBGb3JtRGF0YSBjb250YWluaW5nIHRoZSByZXF1ZXN0IGJvZHkuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG1heWJlQXBwZW5kU3VibWl0QnV0dG9uVmFsdWVfKGJvZHkpIHtcblx0XHRjb25zdCBidXR0b24gPSBnbG9iYWxzLmNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQ7XG5cdFx0aWYgKGJ1dHRvbiAmJiBidXR0b24ubmFtZSkge1xuXHRcdFx0Ym9keS5hcHBlbmQoYnV0dG9uLm5hbWUsIGJ1dHRvbi52YWx1ZSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBmb2xsb3dpbmcgbWV0aG9kIHRyaWVzIHRvIGV4dHJhY3QgdGhlIHJlc3BvbnNlIHVybCB2YWx1ZSBieSBjaGVja2luZ1xuXHQgKiB0aGUgY3VzdG9tIHJlc3BvbnNlIGhlYWRlciAnWC1SZXF1ZXN0LVVSTCcgaWYgcHJvcGVyIHZhbHVlIGlzIG5vdCBwcmVzZW50XG5cdCAqIGluIFhNTEh0dHBSZXF1ZXN0LiBUaGUgdmFsdWUgb2YgcmVzcG9uc2VVUkwgd2lsbCBiZSB0aGUgZmluYWwgVVJMXG5cdCAqIG9idGFpbmVkIGFmdGVyIGFueSByZWRpcmVjdHMuIEludGVybmV0IEV4cGxvcmVyLCBFZGdlIGFuZCBTYWZhcmkgPD0gN1xuXHQgKiBkb2VzIG5vdCB5ZXQgc3VwcG9ydCB0aGUgZmVhdHVyZS4gRm9yIG1vcmUgaW5mb3JtYXRpb24gc2VlOlxuXHQgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvWE1MSHR0cFJlcXVlc3QvcmVzcG9uc2VVUkxcblx0ICogaHR0cHM6Ly94aHIuc3BlYy53aGF0d2cub3JnLyN0aGUtcmVzcG9uc2V1cmwtYXR0cmlidXRlXG5cdCAqIEBwYXJhbSB7WE1MSHR0cFJlcXVlc3R9IHJlcXVlc3Rcblx0ICogQHJldHVybiB7P3N0cmluZ30gUmVzcG9uc2UgdXJsIGJlc3QgbWF0Y2guXG5cdCAqL1xuXHRtYXliZUV4dHJhY3RSZXNwb25zZVVybEZyb21SZXF1ZXN0KHJlcXVlc3QpIHtcblx0XHR2YXIgcmVzcG9uc2VVcmwgPSByZXF1ZXN0LnJlc3BvbnNlVVJMO1xuXHRcdGlmIChyZXNwb25zZVVybCkge1xuXHRcdFx0cmV0dXJuIHJlc3BvbnNlVXJsO1xuXHRcdH1cblx0XHRyZXR1cm4gcmVxdWVzdC5nZXRSZXNwb25zZUhlYWRlcihSZXF1ZXN0U2NyZWVuLlhfUkVRVUVTVF9VUkxfSEVBREVSKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBodHRwIGhlYWRlcnMuXG5cdCAqIEBwYXJhbSB7P09iamVjdD19IGh0dHBIZWFkZXJzXG5cdCAqL1xuXHRzZXRIdHRwSGVhZGVycyhodHRwSGVhZGVycykge1xuXHRcdHRoaXMuaHR0cEhlYWRlcnMgPSBodHRwSGVhZGVycztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBodHRwIG1ldGhvZC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBodHRwTWV0aG9kXG5cdCAqL1xuXHRzZXRIdHRwTWV0aG9kKGh0dHBNZXRob2QpIHtcblx0XHR0aGlzLmh0dHBNZXRob2QgPSBodHRwTWV0aG9kLnRvTG93ZXJDYXNlKCk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgcmVxdWVzdCBvYmplY3QuXG5cdCAqIEBwYXJhbSB7P09iamVjdH0gcmVxdWVzdFxuXHQgKi9cblx0c2V0UmVxdWVzdChyZXF1ZXN0KSB7XG5cdFx0dGhpcy5yZXF1ZXN0ID0gcmVxdWVzdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSByZXF1ZXN0IHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzLlxuXHQgKiBAcGFyYW0geyFudW1iZXJ9IHRpbWVvdXRcblx0ICovXG5cdHNldFRpbWVvdXQodGltZW91dCkge1xuXHRcdHRoaXMudGltZW91dCA9IHRpbWVvdXQ7XG5cdH1cblxufVxuXG4vKipcbiAqIEhvbGRzIHZhbHVlIGZvciBtZXRob2QgZ2V0LlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBkZWZhdWx0ICdnZXQnXG4gKiBAc3RhdGljXG4gKi9cblJlcXVlc3RTY3JlZW4uR0VUID0gJ2dldCc7XG5cbi8qKlxuICogSG9sZHMgdmFsdWUgZm9yIG1ldGhvZCBwb3N0LlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBkZWZhdWx0ICdwb3N0J1xuICogQHN0YXRpY1xuICovXG5SZXF1ZXN0U2NyZWVuLlBPU1QgPSAncG9zdCc7XG5cbi8qKlxuICogRmFsbGJhY2sgaHR0cCBoZWFkZXIgdG8gcmV0cmlldmUgcmVzcG9uc2UgcmVxdWVzdCB1cmwuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgJ1gtUmVxdWVzdC1VUkwnXG4gKiBAc3RhdGljXG4gKi9cblJlcXVlc3RTY3JlZW4uWF9SRVFVRVNUX1VSTF9IRUFERVIgPSAnWC1SZXF1ZXN0LVVSTCc7XG5cbmV4cG9ydCBkZWZhdWx0IFJlcXVlc3RTY3JlZW47XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGdldFVpZCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7IGJ1aWxkRnJhZ21lbnQsIGV4aXREb2N1bWVudCwgZ2xvYmFsRXZhbCwgZ2xvYmFsRXZhbFN0eWxlcywgbWF0Y2ggfSBmcm9tICdtZXRhbC1kb20nO1xuaW1wb3J0IENhbmNlbGxhYmxlUHJvbWlzZSBmcm9tICdtZXRhbC1wcm9taXNlJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgUmVxdWVzdFNjcmVlbiBmcm9tICcuL1JlcXVlc3RTY3JlZW4nO1xuaW1wb3J0IFN1cmZhY2UgZnJvbSAnLi4vc3VyZmFjZS9TdXJmYWNlJztcbmltcG9ydCBVQSBmcm9tICdtZXRhbC11c2VyYWdlbnQnO1xuaW1wb3J0IFVyaSBmcm9tICdtZXRhbC11cmknO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4uL3V0aWxzL3V0aWxzJztcblxuY2xhc3MgSHRtbFNjcmVlbiBleHRlbmRzIFJlcXVlc3RTY3JlZW4ge1xuXG5cdC8qKlxuXHQgKiBTY3JlZW4gY2xhc3MgdGhhdCBwZXJmb3JtIGEgcmVxdWVzdCBhbmQgZXh0cmFjdHMgc3VyZmFjZSBjb250ZW50cyBmcm9tXG5cdCAqIHRoZSByZXNwb25zZSBjb250ZW50LlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICogQGV4dGVuZHMge1JlcXVlc3RTY3JlZW59XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHRpdGxlIHNlbGVjdG9yLiBSZWxldmFudCB0byBleHRyYWN0IHRoZSA8Y29kZT48dGl0bGU+PC9jb2RlPlxuXHRcdCAqIGVsZW1lbnQgZnJvbSByZXF1ZXN0IGZyYWdtZW50cyB0byB1c2UgYXMgdGhlIHNjcmVlbiB0aXRsZS5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCB0aXRsZVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnRpdGxlU2VsZWN0b3IgPSAndGl0bGUnO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRhY3RpdmF0ZSgpIHtcblx0XHRzdXBlci5hY3RpdmF0ZSgpO1xuXHRcdHRoaXMucmVsZWFzZVZpcnR1YWxEb2N1bWVudCgpO1xuXHRcdHRoaXMucGVuZGluZ1N0eWxlcyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogQWxsb2NhdGVzIHZpcnR1YWwgZG9jdW1lbnQgZm9yIGNvbnRlbnQuIEFmdGVyIGFsbG9jYXRlZCB2aXJ0dWFsIGRvY3VtZW50XG5cdCAqIGNhbiBiZSBhY2Nlc3NlZCBieSA8Y29kZT50aGlzLnZpcnR1YWxEb2N1bWVudDwvY29kZT4uXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaHRtbFN0cmluZ1xuXHQgKi9cblx0YWxsb2NhdGVWaXJ0dWFsRG9jdW1lbnRGb3JDb250ZW50KGh0bWxTdHJpbmcpIHtcblx0XHRpZiAoIXRoaXMudmlydHVhbERvY3VtZW50KSB7XG5cdFx0XHR0aGlzLnZpcnR1YWxEb2N1bWVudCA9IGdsb2JhbHMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaHRtbCcpO1xuXHRcdH1cblxuXHRcdHRoaXMuY29weU5vZGVBdHRyaWJ1dGVzRnJvbUNvbnRlbnRfKGh0bWxTdHJpbmcsIHRoaXMudmlydHVhbERvY3VtZW50KTtcblxuXHRcdHRoaXMudmlydHVhbERvY3VtZW50LmlubmVySFRNTCA9IGh0bWxTdHJpbmc7XG5cdH1cblxuXHQvKipcblx0ICogQ3VzdG9taXplcyBsb2dpYyB0byBhcHBlbmQgc3R5bGVzIGludG8gZG9jdW1lbnQuIFJlbGV2YW50IHRvIHdoZW5cblx0ICogdHJhY2tpbmcgYSBzdHlsZSBieSBpZCBtYWtlIHN1cmUgdG8gcmUtcG9zaXRpb25zIHRoZSBuZXcgc3R5bGUgaW4gdGhlXG5cdCAqIHNhbWUgZG9tIG9yZGVyLlxuXHQgKiBAcGFyYW0ge0VsZW1lbnR9IG5ld1N0eWxlXG5cdCAqL1xuXHRhcHBlbmRTdHlsZUludG9Eb2N1bWVudF8obmV3U3R5bGUpIHtcblx0XHR2YXIgaXNUZW1wb3JhcnlTdHlsZSA9IG1hdGNoKG5ld1N0eWxlLCBIdG1sU2NyZWVuLnNlbGVjdG9ycy5zdHlsZXNUZW1wb3JhcnkpO1xuXHRcdGlmIChpc1RlbXBvcmFyeVN0eWxlKSB7XG5cdFx0XHR0aGlzLnBlbmRpbmdTdHlsZXMucHVzaChuZXdTdHlsZSk7XG5cdFx0fVxuXHRcdGlmIChuZXdTdHlsZS5pZCkge1xuXHRcdFx0dmFyIHN0eWxlSW5Eb2MgPSBnbG9iYWxzLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKG5ld1N0eWxlLmlkKTtcblx0XHRcdGlmIChzdHlsZUluRG9jKSB7XG5cdFx0XHRcdHN0eWxlSW5Eb2MucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobmV3U3R5bGUsIHN0eWxlSW5Eb2MubmV4dFNpYmxpbmcpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGdsb2JhbHMuZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChuZXdTdHlsZSk7XG5cdH1cblxuXHQvKipcblx0ICogSWYgYm9keSBpcyB1c2VkIGFzIHN1cmZhY2UgZm9yY2VzIHRoZSByZXF1ZXN0ZWQgZG9jdW1lbnRzIHRvIGhhdmUgc2FtZSBpZFxuXHQgKiBvZiB0aGUgaW5pdGlhbCBwYWdlLlxuXHQgKi9cblx0YXNzZXJ0U2FtZUJvZHlJZEluVmlydHVhbERvY3VtZW50KCkge1xuXHRcdHZhciBib2R5U3VyZmFjZSA9IHRoaXMudmlydHVhbERvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2JvZHknKTtcblx0XHRpZiAoIWdsb2JhbHMuZG9jdW1lbnQuYm9keS5pZCkge1xuXHRcdFx0Z2xvYmFscy5kb2N1bWVudC5ib2R5LmlkID0gJ3Nlbm5hX3N1cmZhY2VfJyArIGdldFVpZCgpO1xuXHRcdH1cblx0XHRpZiAoYm9keVN1cmZhY2UpIHtcblx0XHRcdGJvZHlTdXJmYWNlLmlkID0gZ2xvYmFscy5kb2N1bWVudC5ib2R5LmlkO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDb3BpZXMgYXR0cmlidXRlcyBmcm9tIHRoZSA8aHRtbD4gdGFnIG9mIGNvbnRlbnQgdG8gdGhlIGdpdmVuIG5vZGUuXG5cdCAqL1xuXHRjb3B5Tm9kZUF0dHJpYnV0ZXNGcm9tQ29udGVudF8oY29udGVudCwgbm9kZSkge1xuXHRcdGNvbnRlbnQgPSBjb250ZW50LnJlcGxhY2UoL1s8XVxccypodG1sL2lnLCAnPHNlbm5hJyk7XG5cdFx0Y29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvXFwvaHRtbFxccypcXD4vaWcsICcvc2VubmE+Jyk7XG5cdFx0bm9kZS5pbm5lckhUTUwgPSBjb250ZW50O1xuXHRcdHZhciBwbGFjZWhvbGRlciA9IG5vZGUucXVlcnlTZWxlY3Rvcignc2VubmEnKTtcblx0XHRpZiAocGxhY2Vob2xkZXIpIHtcblx0XHRcdHV0aWxzLmNsZWFyTm9kZUF0dHJpYnV0ZXMobm9kZSk7XG5cdFx0XHR1dGlscy5jb3B5Tm9kZUF0dHJpYnV0ZXMocGxhY2Vob2xkZXIsIG5vZGUpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAT3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLmRpc3Bvc2VQZW5kaW5nU3R5bGVzKCk7XG5cdFx0c3VwZXIuZGlzcG9zZUludGVybmFsKCk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgcGVuZGluZyBzdHlsZXMgaWYgc2NyZWVuIGdldCBkaXNwb3NlZCBwcmlvciB0byBpdHMgbG9hZGluZy5cblx0ICovXG5cdGRpc3Bvc2VQZW5kaW5nU3R5bGVzKCkge1xuXHRcdGlmICh0aGlzLnBlbmRpbmdTdHlsZXMpIHtcblx0XHRcdHRoaXMucGVuZGluZ1N0eWxlcy5mb3JFYWNoKChzdHlsZSkgPT4gZXhpdERvY3VtZW50KHN0eWxlKSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEBPdmVycmlkZVxuXHQgKi9cblx0ZXZhbHVhdGVTY3JpcHRzKHN1cmZhY2VzKSB7XG5cdFx0dmFyIGV2YWx1YXRlVHJhY2tlZFNjcmlwdHMgPSB0aGlzLmV2YWx1YXRlVHJhY2tlZFJlc291cmNlc18oXG5cdFx0XHRnbG9iYWxFdmFsLnJ1blNjcmlwdHNJbkVsZW1lbnQsIEh0bWxTY3JlZW4uc2VsZWN0b3JzLnNjcmlwdHMsXG5cdFx0XHRIdG1sU2NyZWVuLnNlbGVjdG9ycy5zY3JpcHRzVGVtcG9yYXJ5LCBIdG1sU2NyZWVuLnNlbGVjdG9ycy5zY3JpcHRzUGVybWFuZW50KTtcblxuXHRcdHJldHVybiBldmFsdWF0ZVRyYWNrZWRTY3JpcHRzLnRoZW4oKCkgPT4gc3VwZXIuZXZhbHVhdGVTY3JpcHRzKHN1cmZhY2VzKSk7XG5cdH1cblxuXHQvKipcblx0ICogQE92ZXJyaWRlXG5cdCAqL1xuXHRldmFsdWF0ZVN0eWxlcyhzdXJmYWNlcykge1xuXHRcdHRoaXMucGVuZGluZ1N0eWxlcyA9IFtdO1xuXHRcdHZhciBldmFsdWF0ZVRyYWNrZWRTdHlsZXMgPSB0aGlzLmV2YWx1YXRlVHJhY2tlZFJlc291cmNlc18oXG5cdFx0XHRnbG9iYWxFdmFsU3R5bGVzLnJ1blN0eWxlc0luRWxlbWVudCwgSHRtbFNjcmVlbi5zZWxlY3RvcnMuc3R5bGVzLFxuXHRcdFx0SHRtbFNjcmVlbi5zZWxlY3RvcnMuc3R5bGVzVGVtcG9yYXJ5LCBIdG1sU2NyZWVuLnNlbGVjdG9ycy5zdHlsZXNQZXJtYW5lbnQsXG5cdFx0XHR0aGlzLmFwcGVuZFN0eWxlSW50b0RvY3VtZW50Xy5iaW5kKHRoaXMpKTtcblxuXHRcdHJldHVybiBldmFsdWF0ZVRyYWNrZWRTdHlsZXMudGhlbigoKSA9PiBzdXBlci5ldmFsdWF0ZVN0eWxlcyhzdXJmYWNlcykpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlcyB0cmFja2VkIHJlc291cmNlcyBpbnNpZGUgaW5jb21pbmcgZnJhZ21lbnQgYW5kIHJlbW92ZSBleGlzdGluZ1xuXHQgKiB0ZW1wb3JhcnkgcmVzb3VyY2VzLlxuXHQgKiBAcGFyYW0gez9mdW5jdGlvbigpfSBhcHBlbmRGbiBGdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGUgaW50byBkb2N1bWVudC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzZWxlY3RvciBTZWxlY3RvciB1c2VkIHRvIGZpbmQgcmVzb3VyY2VzIHRvIHRyYWNrLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNlbGVjdG9yVGVtcG9yYXJ5IFNlbGVjdG9yIHVzZWQgdG8gZmluZCB0ZW1wb3Jhcnlcblx0ICogICAgIHJlc291cmNlcyB0byB0cmFjay5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzZWxlY3RvclBlcm1hbmVudCBTZWxlY3RvciB1c2VkIHRvIGZpbmQgcGVybWFuZW50XG5cdCAqICAgICByZXNvdXJjZXMgdG8gdHJhY2suXG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9ufSBvcHRfYXBwZW5kUmVzb3VyY2VGbiBPcHRpb25hbCBmdW5jdGlvbiB1c2VkIHRvXG5cdCAqICAgICBldmFsdWF0ZSBmcmFnbWVudCBjb250YWluaW5nIHJlc291cmNlcy5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBEZWZlcnJlZCB0aGF0IHdhaXRzIHJlc291cmNlcyBldmFsdWF0aW9uIHRvXG5cdCAqICAgICBjb21wbGV0ZS5cblx0ICogQHByaXZhdGVcblx0ICovXG5cdGV2YWx1YXRlVHJhY2tlZFJlc291cmNlc18oZXZhbHVhdG9yRm4sIHNlbGVjdG9yLCBzZWxlY3RvclRlbXBvcmFyeSwgc2VsZWN0b3JQZXJtYW5lbnQsIG9wdF9hcHBlbmRSZXNvdXJjZUZuKSB7XG5cdFx0dmFyIHRyYWNrZWQgPSB0aGlzLnZpcnR1YWxRdWVyeVNlbGVjdG9yQWxsXyhzZWxlY3Rvcik7XG5cdFx0dmFyIHRlbXBvcmFyaWVzSW5Eb2MgPSB0aGlzLnF1ZXJ5U2VsZWN0b3JBbGxfKHNlbGVjdG9yVGVtcG9yYXJ5KTtcblx0XHR2YXIgcGVybWFuZW50c0luRG9jID0gdGhpcy5xdWVyeVNlbGVjdG9yQWxsXyhzZWxlY3RvclBlcm1hbmVudCk7XG5cblx0XHQvLyBBZGRzIHBlcm1hbmVudCByZXNvdXJjZXMgaW4gZG9jdW1lbnQgdG8gY2FjaGUuXG5cdFx0cGVybWFuZW50c0luRG9jLmZvckVhY2goKHJlc291cmNlKSA9PiB7XG5cdFx0XHR2YXIgcmVzb3VyY2VLZXkgPSB0aGlzLmdldFJlc291cmNlS2V5XyhyZXNvdXJjZSk7XG5cdFx0XHRpZiAocmVzb3VyY2VLZXkpIHtcblx0XHRcdFx0SHRtbFNjcmVlbi5wZXJtYW5lbnRSZXNvdXJjZXNJbkRvY1tyZXNvdXJjZUtleV0gPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0dmFyIGZyYWcgPSBidWlsZEZyYWdtZW50KCk7XG5cdFx0dHJhY2tlZC5mb3JFYWNoKChyZXNvdXJjZSkgPT4ge1xuXHRcdFx0dmFyIHJlc291cmNlS2V5ID0gdGhpcy5nZXRSZXNvdXJjZUtleV8ocmVzb3VyY2UpO1xuXHRcdFx0Ly8gRG8gbm90IGxvYWQgcGVybWFuZW50IHJlc291cmNlcyBpZiBhbHJlYWR5IGluIGRvY3VtZW50LlxuXHRcdFx0aWYgKCFIdG1sU2NyZWVuLnBlcm1hbmVudFJlc291cmNlc0luRG9jW3Jlc291cmNlS2V5XSkge1xuXHRcdFx0XHRmcmFnLmFwcGVuZENoaWxkKHJlc291cmNlKTtcblx0XHRcdH1cblx0XHRcdC8vIElmIHJlc291cmNlIGhhcyBrZXkgYW5kIGlzIHBlcm1hbmVudCBhZGQgdG8gY2FjaGUuXG5cdFx0XHRpZiAocmVzb3VyY2VLZXkgJiYgbWF0Y2gocmVzb3VyY2UsIHNlbGVjdG9yUGVybWFuZW50KSkge1xuXHRcdFx0XHRIdG1sU2NyZWVuLnBlcm1hbmVudFJlc291cmNlc0luRG9jW3Jlc291cmNlS2V5XSA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuXHRcdFx0ZXZhbHVhdG9yRm4oZnJhZywgKCkgPT4ge1xuXHRcdFx0XHR0ZW1wb3Jhcmllc0luRG9jLmZvckVhY2goKHJlc291cmNlKSA9PiBleGl0RG9jdW1lbnQocmVzb3VyY2UpKTtcblx0XHRcdFx0cmVzb2x2ZSgpO1xuXHRcdFx0fSwgb3B0X2FwcGVuZFJlc291cmNlRm4pO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBPdmVycmlkZVxuXHQgKi9cblx0ZmxpcChzdXJmYWNlcykge1xuXHRcdHJldHVybiBzdXBlci5mbGlwKHN1cmZhY2VzKS50aGVuKCgpID0+IHtcblx0XHRcdHV0aWxzLmNsZWFyTm9kZUF0dHJpYnV0ZXMoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KTtcblx0XHRcdHV0aWxzLmNvcHlOb2RlQXR0cmlidXRlcyh0aGlzLnZpcnR1YWxEb2N1bWVudCwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KTtcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFeHRyYWN0cyBhIGtleSB0byBpZGVudGlmeSB0aGUgcmVzb3VyY2UgYmFzZWQgb24gaXRzIGF0dHJpYnV0ZXMuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gcmVzb3VyY2Vcblx0ICogQHJldHVybiB7c3RyaW5nfSBFeHRyYWN0ZWQga2V5IGJhc2VkIG9uIHJlc291cmNlIGF0dHJpYnV0ZXMgaW4gb3JkZXIgb2Zcblx0ICogICAgIHByZWZlcmVuY2U6IGlkLCBocmVmLCBzcmMuXG5cdCAqL1xuXHRnZXRSZXNvdXJjZUtleV8ocmVzb3VyY2UpIHtcblx0XHRyZXR1cm4gcmVzb3VyY2UuaWQgfHwgcmVzb3VyY2UuaHJlZiB8fCByZXNvdXJjZS5zcmMgfHwgJyc7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGdldFN1cmZhY2VDb250ZW50KHN1cmZhY2VJZCkge1xuXHRcdHZhciBzdXJmYWNlID0gdGhpcy52aXJ0dWFsRG9jdW1lbnQucXVlcnlTZWxlY3RvcignIycgKyBzdXJmYWNlSWQpO1xuXHRcdGlmIChzdXJmYWNlKSB7XG5cdFx0XHR2YXIgZGVmYXVsdENoaWxkID0gc3VyZmFjZS5xdWVyeVNlbGVjdG9yKCcjJyArIHN1cmZhY2VJZCArICctJyArIFN1cmZhY2UuREVGQVVMVCk7XG5cdFx0XHRpZiAoZGVmYXVsdENoaWxkKSB7XG5cdFx0XHRcdHJldHVybiBkZWZhdWx0Q2hpbGQuaW5uZXJIVE1MO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHN1cmZhY2UuaW5uZXJIVE1MOyAvLyBJZiBkZWZhdWx0IGNvbnRlbnQgbm90IGZvdW5kLCB1c2Ugc3VyZmFjZSBjb250ZW50XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHRpdGxlIHNlbGVjdG9yLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKi9cblx0Z2V0VGl0bGVTZWxlY3RvcigpIHtcblx0XHRyZXR1cm4gdGhpcy50aXRsZVNlbGVjdG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRsb2FkKHBhdGgpIHtcblx0XHRyZXR1cm4gc3VwZXIubG9hZChwYXRoKVxuXHRcdFx0LnRoZW4oY29udGVudCA9PiB7XG5cdFx0XHRcdHRoaXMuYWxsb2NhdGVWaXJ0dWFsRG9jdW1lbnRGb3JDb250ZW50KGNvbnRlbnQpO1xuXHRcdFx0XHR0aGlzLnJlc29sdmVUaXRsZUZyb21WaXJ0dWFsRG9jdW1lbnQoKTtcblx0XHRcdFx0dGhpcy5hc3NlcnRTYW1lQm9keUlkSW5WaXJ0dWFsRG9jdW1lbnQoKTtcblx0XHRcdFx0aWYgKFVBLmlzSWUpIHtcblx0XHRcdFx0XHR0aGlzLm1ha2VUZW1wb3JhcnlTdHlsZXNIcmVmc1VuaXF1ZV8oKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gY29udGVudDtcblx0XHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFF1ZXJpZXMgdGVtcG9yYXJ5IHN0eWxlcyBmcm9tIHZpcnR1YWwgZG9jdW1lbnQsIGFuZCBtYWtlcyB0aGVtIHVuaXF1ZS5cblx0ICogVGhpcyBpcyBuZWNlc3NhcnkgZm9yIGNhY2hpbmcgYW5kIGxvYWQgZXZlbnQgZmlyaW5nIGlzc3VlcyBzcGVjaWZpYyB0b1xuXHQgKiBJRTExLiBodHRwczovL2RldmVsb3Blci5taWNyb3NvZnQuY29tL2VuLXVzL21pY3Jvc29mdC1lZGdlL3BsYXRmb3JtL2lzc3Vlcy83OTQwMTcxL1xuXHQgKi9cblx0bWFrZVRlbXBvcmFyeVN0eWxlc0hyZWZzVW5pcXVlXygpIHtcblx0XHR2YXIgdGVtcG9yYXJpZXNJbkRvYyA9IHRoaXMudmlydHVhbFF1ZXJ5U2VsZWN0b3JBbGxfKEh0bWxTY3JlZW4uc2VsZWN0b3JzLnN0eWxlc1RlbXBvcmFyeSk7XG5cdFx0dGVtcG9yYXJpZXNJbkRvYy5mb3JFYWNoKChzdHlsZSkgPT4gdGhpcy5yZXBsYWNlU3R5bGVBbmRNYWtlVW5pcXVlXyhzdHlsZSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgZWxlbWVudCBmcm9tIGdpdmVuLCBjb3BpZXMgYXR0cmlidXRlcywgbXV0YXRlcyBocmVmIHRvIGJlXG5cdCAqIHVuaXF1ZSB0byBwcmV2ZW50IGNhY2hpbmcgYW5kIG1vcmUgdGhhbiBvbmUgbG9hZC9lcnJvciBldmVudCBmcm9tIGZpcmluZy5cblx0ICovXG5cdHJlcGxhY2VTdHlsZUFuZE1ha2VVbmlxdWVfKHN0eWxlKSB7XG5cdFx0aWYgKHN0eWxlLmhyZWYpIHtcblx0XHRcdHZhciBuZXdTdHlsZSA9IGdsb2JhbHMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudChzdHlsZS50YWdOYW1lKTtcblx0XHRcdHN0eWxlLmhyZWYgPSBuZXcgVXJpKHN0eWxlLmhyZWYpLm1ha2VVbmlxdWUoKS50b1N0cmluZygpO1xuXHRcdFx0dXRpbHMuY29weU5vZGVBdHRyaWJ1dGVzKHN0eWxlLCBuZXdTdHlsZSk7XG5cdFx0XHRzdHlsZS5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdTdHlsZSwgc3R5bGUpO1xuXHRcdFx0c3R5bGUuZGlzYWJsZWQgPSB0cnVlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBRdWVyaWVzIGVsZW1lbnRzIGZyb20gdmlydHVhbCBkb2N1bWVudCBhbmQgcmV0dXJucyBhbiBhcnJheSBvZiBlbGVtZW50cy5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzZWxlY3RvclxuXHQgKiBAcmV0dXJuIHthcnJheS48RWxlbWVudD59XG5cdCAqL1xuXHR2aXJ0dWFsUXVlcnlTZWxlY3RvckFsbF8oc2VsZWN0b3IpIHtcblx0XHRyZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy52aXJ0dWFsRG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFF1ZXJpZXMgZWxlbWVudHMgZnJvbSBkb2N1bWVudCBhbmQgcmV0dXJucyBhbiBhcnJheSBvZiBlbGVtZW50cy5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzZWxlY3RvclxuXHQgKiBAcmV0dXJuIHthcnJheS48RWxlbWVudD59XG5cdCAqL1xuXHRxdWVyeVNlbGVjdG9yQWxsXyhzZWxlY3Rvcikge1xuXHRcdHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChnbG9iYWxzLmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZWxlYXNlcyB2aXJ0dWFsIGRvY3VtZW50IGFsbG9jYXRlZCBmb3IgY29udGVudC5cblx0ICovXG5cdHJlbGVhc2VWaXJ0dWFsRG9jdW1lbnQoKSB7XG5cdFx0dGhpcy52aXJ0dWFsRG9jdW1lbnQgPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlc29sdmVzIHRpdGxlIGZyb20gYWxsb2NhdGVkIHZpcnR1YWwgZG9jdW1lbnQuXG5cdCAqL1xuXHRyZXNvbHZlVGl0bGVGcm9tVmlydHVhbERvY3VtZW50KCkge1xuXHRcdHZhciB0aXRsZSA9IHRoaXMudmlydHVhbERvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy50aXRsZVNlbGVjdG9yKTtcblx0XHRpZiAodGl0bGUpIHtcblx0XHRcdHRoaXMuc2V0VGl0bGUodGl0bGUudGV4dENvbnRlbnQudHJpbSgpKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgdGl0bGUgc2VsZWN0b3IuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gdGl0bGVTZWxlY3RvclxuXHQgKi9cblx0c2V0VGl0bGVTZWxlY3Rvcih0aXRsZVNlbGVjdG9yKSB7XG5cdFx0dGhpcy50aXRsZVNlbGVjdG9yID0gdGl0bGVTZWxlY3Rvcjtcblx0fVxuXG59XG5cbi8qKlxuICogSGVscGVyIHNlbGVjdG9ycyBmb3IgdHJhY2tpbmcgcmVzb3VyY2VzLlxuICogQHR5cGUge29iamVjdH1cbiAqIEBwcm90ZWN0ZWRcbiAqIEBzdGF0aWNcbiAqL1xuSHRtbFNjcmVlbi5zZWxlY3RvcnMgPSB7XG5cdHNjcmlwdHM6ICdzY3JpcHRbZGF0YS1zZW5uYS10cmFja10nLFxuXHRzY3JpcHRzUGVybWFuZW50OiAnc2NyaXB0W2RhdGEtc2VubmEtdHJhY2s9XCJwZXJtYW5lbnRcIl0nLFxuXHRzY3JpcHRzVGVtcG9yYXJ5OiAnc2NyaXB0W2RhdGEtc2VubmEtdHJhY2s9XCJ0ZW1wb3JhcnlcIl0nLFxuXHRzdHlsZXM6ICdzdHlsZVtkYXRhLXNlbm5hLXRyYWNrXSxsaW5rW2RhdGEtc2VubmEtdHJhY2tdJyxcblx0c3R5bGVzUGVybWFuZW50OiAnc3R5bGVbZGF0YS1zZW5uYS10cmFjaz1cInBlcm1hbmVudFwiXSxsaW5rW2RhdGEtc2VubmEtdHJhY2s9XCJwZXJtYW5lbnRcIl0nLFxuXHRzdHlsZXNUZW1wb3Jhcnk6ICdzdHlsZVtkYXRhLXNlbm5hLXRyYWNrPVwidGVtcG9yYXJ5XCJdLGxpbmtbZGF0YS1zZW5uYS10cmFjaz1cInRlbXBvcmFyeVwiXSdcbn07XG5cbi8qKlxuICogQ2FjaGVzIHBlcm1hbmVudCByZXNvdXJjZSBrZXlzLlxuICogQHR5cGUge29iamVjdH1cbiAqIEBwcm90ZWN0ZWRcbiAqIEBzdGF0aWNcbiAqL1xuSHRtbFNjcmVlbi5wZXJtYW5lbnRSZXNvdXJjZXNJbkRvYyA9IHt9O1xuXG5leHBvcnQgZGVmYXVsdCBIdG1sU2NyZWVuO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlLCBnZXRVaWQsIGlzRGVmQW5kTm90TnVsbCwgaXNFbGVtZW50LCBvYmplY3QgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgZGF0YUF0dHJpYnV0ZXMgZnJvbSAnLi9kYXRhQXR0cmlidXRlcyc7XG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IEFwcCBmcm9tICcuL0FwcCc7XG5pbXBvcnQgSHRtbFNjcmVlbiBmcm9tICcuLi9zY3JlZW4vSHRtbFNjcmVlbic7XG5pbXBvcnQgUm91dGUgZnJvbSAnLi4vcm91dGUvUm91dGUnO1xuXG5jbGFzcyBBcHBEYXRhQXR0cmlidXRlSGFuZGxlciBleHRlbmRzIERpc3Bvc2FibGUge1xuXG5cdC8qKlxuXHQgKiBJbml0aWxpemVzIEFwcCwgcmVnaXN0ZXIgc3VyZmFjZXMgYW5kIHJvdXRlcyBmcm9tIGRhdGEgYXR0cmlidXRlcy5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGFwcCByZWZlcmVuY2UgaW5pdGlhbGl6ZWQgYnkgZGF0YSBhdHRyaWJ1dGVzLlxuXHRcdCAqIEB0eXBlIHtBcHB9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdHRoaXMuYXBwID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBiYXNlIGVsZW1lbnQgdG8gc2VhcmNoIGluaXRpYWxpemF0aW9uIGRhdGEgYXR0cmlidXRlcy4gVGhpc1xuXHRcdCAqIGVsZW1lbnQgaXMgdGhlIGNvbnRhaW5lciB1c2VkIHRvIGVuYWJsZSBpbml0aWFsaXphdGlvbiBiYXNlZCBvbiB0aGVcblx0XHQgKiBwcmVzZW5jZSBvZiBgZGF0YS1zZW5uYWAgYXR0cmlidXRlLlxuXHRcdCAqIEB0eXBlIHtFbGVtZW50fVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHR0aGlzLmJhc2VFbGVtZW50ID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbml0cyBhcHBsaWNhdGlvbiBiYXNlZCBvbiBpbmZvcm1hdGlvbiBzY2FubmVkIGZyb20gZG9jdW1lbnQuXG5cdCAqL1xuXHRoYW5kbGUoKSB7XG5cdFx0aWYgKCFpc0VsZW1lbnQodGhpcy5iYXNlRWxlbWVudCkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignU2VubmEgZGF0YSBhdHRyaWJ1dGUgaGFuZGxlciBiYXNlIGVsZW1lbnQgJyArXG5cdFx0XHRcdCdub3Qgc2V0IG9yIGludmFsaWQsIHRyeSBzZXR0aW5nIGEgdmFsaWQgZWxlbWVudCB0aGF0ICcgK1xuXHRcdFx0XHQnY29udGFpbnMgYSBgZGF0YS1zZW5uYWAgYXR0cmlidXRlLicpO1xuXHRcdH1cblxuXHRcdGlmICghdGhpcy5iYXNlRWxlbWVudC5oYXNBdHRyaWJ1dGUoZGF0YUF0dHJpYnV0ZXMuc2VubmEpKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnU2VubmEgd2FzIG5vdCBpbml0aWFsaXplZCBmcm9tIGRhdGEgYXR0cmlidXRlcy4gJyArXG5cdFx0XHRcdCdJbiBvcmRlciB0byBlbmFibGUgaXRzIHVzYWdlIGZyb20gZGF0YSBhdHRyaWJ1dGVzIHRyeSBzZXR0aW5nICcgK1xuXHRcdFx0XHQnaW4gdGhlIGJhc2UgZWxlbWVudCwgZS5nLiBgPGJvZHkgZGF0YS1zZW5uYT5gLicpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLmFwcCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTZW5uYSBhcHAgd2FzIGFscmVhZHkgaW5pdGlhbGl6ZWQuJyk7XG5cdFx0fVxuXG5cdFx0Y29uc29sZS5sb2coJ1Nlbm5hIGluaXRpYWxpemVkIGZyb20gZGF0YSBhdHRyaWJ1dGUuJyk7XG5cblx0XHR0aGlzLmFwcCA9IG5ldyBBcHAoKTtcblx0XHR0aGlzLm1heWJlQWRkUm91dGVzXygpO1xuXHRcdHRoaXMubWF5YmVBZGRTdXJmYWNlc18oKTtcblx0XHR0aGlzLm1heWJlU2V0QmFzZVBhdGhfKCk7XG5cdFx0dGhpcy5tYXliZVNldExpbmtTZWxlY3Rvcl8oKTtcblx0XHR0aGlzLm1heWJlU2V0TG9hZGluZ0Nzc0NsYXNzXygpO1xuXHRcdHRoaXMubWF5YmVTZXRVcGRhdGVTY3JvbGxQb3NpdGlvbl8oKTtcblx0XHR0aGlzLm1heWJlRGlzcGF0Y2hfKCk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHRpZiAodGhpcy5hcHApIHtcblx0XHRcdHRoaXMuYXBwLmRpc3Bvc2UoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgYXBwIHJlZmVyZW5jZS5cblx0ICogQHJldHVybiB7QXBwfVxuXHQgKi9cblx0Z2V0QXBwKCkge1xuXHRcdHJldHVybiB0aGlzLmFwcDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBiYXNlIGVsZW1lbnQuXG5cdCAqIEByZXR1cm4ge0VsZW1lbnR9IGJhc2VFbGVtZW50XG5cdCAqL1xuXHRnZXRCYXNlRWxlbWVudCgpIHtcblx0XHRyZXR1cm4gdGhpcy5iYXNlRWxlbWVudDtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBhZGRzIGFwcCByb3V0ZXMgZnJvbSBsaW5rIGVsZW1lbnRzIHRoYXQgYXJlIGBzZW5uYS1yb3V0ZWAuXG5cdCAqL1xuXHRtYXliZUFkZFJvdXRlc18oKSB7XG5cdFx0dmFyIHJvdXRlc1NlbGVjdG9yID0gJ2xpbmtbcmVsPVwic2VubmEtcm91dGVcIl0nO1xuXHRcdHRoaXMucXVlcnlTZWxlY3RvckFsbEFzQXJyYXlfKHJvdXRlc1NlbGVjdG9yKS5mb3JFYWNoKChsaW5rKSA9PiB0aGlzLm1heWJlUGFyc2VMaW5rUm91dGVfKGxpbmspKTtcblx0XHRpZiAoIXRoaXMuYXBwLmhhc1JvdXRlcygpKSB7XG5cdFx0XHR0aGlzLmFwcC5hZGRSb3V0ZXMobmV3IFJvdXRlKC8uKi8sIEh0bWxTY3JlZW4pKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBjYW5cXCd0IGZpbmQgcm91dGUgZWxlbWVudHMsIGFkZGluZyBkZWZhdWx0LicpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBhZGRzIGFwcCBzdXJmYWNlcyBieSBzY2FubmluZyBgZGF0YS1zZW5uYS1zdXJmYWNlYCBkYXRhIGF0dHJpYnV0ZS5cblx0ICovXG5cdG1heWJlQWRkU3VyZmFjZXNfKCkge1xuXHRcdHZhciBzdXJmYWNlc1NlbGVjdG9yID0gJ1snICsgZGF0YUF0dHJpYnV0ZXMuc3VyZmFjZSArICddJztcblx0XHR0aGlzLnF1ZXJ5U2VsZWN0b3JBbGxBc0FycmF5XyhzdXJmYWNlc1NlbGVjdG9yKS5mb3JFYWNoKChzdXJmYWNlRWxlbWVudCkgPT4ge1xuXHRcdFx0dGhpcy51cGRhdGVFbGVtZW50SWRJZlNwZWNpYWxTdXJmYWNlXyhzdXJmYWNlRWxlbWVudCk7XG5cdFx0XHR0aGlzLmFwcC5hZGRTdXJmYWNlcyhzdXJmYWNlRWxlbWVudC5pZCk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcGF0Y2hlcyBhcHAgbmF2aWdhdGlvbiB0byB0aGUgY3VycmVudCBwYXRoIHdoZW4gaW5pdGlhbGl6ZXMuXG5cdCAqL1xuXHRtYXliZURpc3BhdGNoXygpIHtcblx0XHRpZiAodGhpcy5iYXNlRWxlbWVudC5oYXNBdHRyaWJ1dGUoZGF0YUF0dHJpYnV0ZXMuZGlzcGF0Y2gpKSB7XG5cdFx0XHR0aGlzLmFwcC5kaXNwYXRjaCgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGFwcCByb3V0ZSBieSBwYXJzaW5nIHZhbGlkIGxpbmsgZWxlbWVudHMuIEEgdmFsaWQgbGluayBlbGVtZW50IGlzIG9mXG5cdCAqIHRoZSBraW5kIGByZWw9XCJzZW5uYS1yb3V0ZVwiYC5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBsaW5rXG5cdCAqL1xuXHRtYXliZVBhcnNlTGlua1JvdXRlXyhsaW5rKSB7XG5cdFx0dmFyIHJvdXRlID0gbmV3IFJvdXRlKHRoaXMubWF5YmVQYXJzZUxpbmtSb3V0ZVBhdGhfKGxpbmspLCB0aGlzLm1heWJlUGFyc2VMaW5rUm91dGVIYW5kbGVyXyhsaW5rKSk7XG5cdFx0dGhpcy5hcHAuYWRkUm91dGVzKHJvdXRlKTtcblx0XHRjb25zb2xlLmxvZygnU2VubmEgc2Nhbm5lZCByb3V0ZSAnICsgcm91dGUuZ2V0UGF0aCgpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBwYXJzZSBsaW5rIHJvdXRlIGhhbmRsZXIuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbGlua1xuXHQgKiBAcmV0dXJuIHs/c3RyaW5nfVxuXHQgKi9cblx0bWF5YmVQYXJzZUxpbmtSb3V0ZUhhbmRsZXJfKGxpbmspIHtcblx0XHR2YXIgaGFuZGxlciA9IGxpbmsuZ2V0QXR0cmlidXRlKCd0eXBlJyk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChoYW5kbGVyKSkge1xuXHRcdFx0aGFuZGxlciA9IG9iamVjdC5nZXRPYmplY3RCeU5hbWUoaGFuZGxlcik7XG5cdFx0fVxuXHRcdHJldHVybiBoYW5kbGVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHBhcnNlIGxpbmsgcm91dGUgcGF0aC5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBsaW5rXG5cdCAqIEByZXR1cm4gez9zdHJpbmd9XG5cdCAqL1xuXHRtYXliZVBhcnNlTGlua1JvdXRlUGF0aF8obGluaykge1xuXHRcdHZhciBwYXRoID0gbGluay5nZXRBdHRyaWJ1dGUoJ2hyZWYnKTtcblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKHBhdGgpKSB7XG5cdFx0XHRpZiAocGF0aC5pbmRleE9mKCdyZWdleDonKSA9PT0gMCkge1xuXHRcdFx0XHRwYXRoID0gbmV3IFJlZ0V4cChwYXRoLnN1YnN0cmluZyg2KSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBwYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHNldHMgYXBwIGJhc2UgcGF0aCBmcm9tIGBkYXRhLXNlbm5hLWJhc2UtcGF0aGAgZGF0YSBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldEJhc2VQYXRoXygpIHtcblx0XHR2YXIgYmFzZVBhdGggPSB0aGlzLmJhc2VFbGVtZW50LmdldEF0dHJpYnV0ZShkYXRhQXR0cmlidXRlcy5iYXNlUGF0aCk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChiYXNlUGF0aCkpIHtcblx0XHRcdHRoaXMuYXBwLnNldEJhc2VQYXRoKGJhc2VQYXRoKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIGJhc2UgcGF0aCAnICsgYmFzZVBhdGgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBzZXRzIGFwcCBsaW5rIHNlbGVjdG9yIGZyb20gYGRhdGEtc2VubmEtbGluay1zZWxlY3RvcmAgZGF0YVxuXHQgKiBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldExpbmtTZWxlY3Rvcl8oKSB7XG5cdFx0dmFyIGxpbmtTZWxlY3RvciA9IHRoaXMuYmFzZUVsZW1lbnQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGVzLmxpbmtTZWxlY3Rvcik7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChsaW5rU2VsZWN0b3IpKSB7XG5cdFx0XHR0aGlzLmFwcC5zZXRMaW5rU2VsZWN0b3IobGlua1NlbGVjdG9yKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIGxpbmsgc2VsZWN0b3IgJyArIGxpbmtTZWxlY3Rvcik7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHNldHMgYXBwIGxpbmsgbG9hZGluZyBjc3MgY2xhc3MgZnJvbSBgZGF0YS1zZW5uYS1sb2FkaW5nLWNzcy1jbGFzc2Bcblx0ICogZGF0YSBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldExvYWRpbmdDc3NDbGFzc18oKSB7XG5cdFx0dmFyIGxvYWRpbmdDc3NDbGFzcyA9IHRoaXMuYmFzZUVsZW1lbnQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGVzLmxvYWRpbmdDc3NDbGFzcyk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChsb2FkaW5nQ3NzQ2xhc3MpKSB7XG5cdFx0XHR0aGlzLmFwcC5zZXRMb2FkaW5nQ3NzQ2xhc3MobG9hZGluZ0Nzc0NsYXNzKTtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIGxvYWRpbmcgY3NzIGNsYXNzICcgKyBsb2FkaW5nQ3NzQ2xhc3MpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBzZXRzIGFwcCB1cGRhdGUgc2Nyb2xsIHBvc2l0aW9uIGZyb21cblx0ICogYGRhdGEtc2VubmEtdXBkYXRlLXNjcm9sbC1wb3NpdGlvbmAgZGF0YSBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRtYXliZVNldFVwZGF0ZVNjcm9sbFBvc2l0aW9uXygpIHtcblx0XHR2YXIgdXBkYXRlU2Nyb2xsUG9zaXRpb24gPSB0aGlzLmJhc2VFbGVtZW50LmdldEF0dHJpYnV0ZShkYXRhQXR0cmlidXRlcy51cGRhdGVTY3JvbGxQb3NpdGlvbik7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbCh1cGRhdGVTY3JvbGxQb3NpdGlvbikpIHtcblx0XHRcdGlmICh1cGRhdGVTY3JvbGxQb3NpdGlvbiA9PT0gJ2ZhbHNlJykge1xuXHRcdFx0XHR0aGlzLmFwcC5zZXRVcGRhdGVTY3JvbGxQb3NpdGlvbihmYWxzZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmFwcC5zZXRVcGRhdGVTY3JvbGxQb3NpdGlvbih0cnVlKTtcblx0XHRcdH1cblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIHVwZGF0ZSBzY3JvbGwgcG9zaXRpb24gJyArIHVwZGF0ZVNjcm9sbFBvc2l0aW9uKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUXVlcmllcyBlbGVtZW50cyBmcm9tIGRvY3VtZW50IGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIGVsZW1lbnRzLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNlbGVjdG9yXG5cdCAqIEByZXR1cm4ge2FycmF5LjxFbGVtZW50Pn1cblx0ICovXG5cdHF1ZXJ5U2VsZWN0b3JBbGxBc0FycmF5XyhzZWxlY3Rvcikge1xuXHRcdHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChnbG9iYWxzLmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIGVsZW1lbnQgaWQgaWYgaGFuZGxlZCBhcyBzcGVjaWFsIHN1cmZhY2UgZWxlbWVudC4gU29tZSBzdXJmYWNlc1xuXHQgKiBhcmUgc2xpZ2h0bHkgZGlmZmVyZW50IGZyb20gb3RoZXJzLCBsaWtlIHdoZW4gdGhyZWF0aW5nIDxjb2RlPmJvZHk8L2NvZGU+XG5cdCAqIGFzIHN1cmZhY2UuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuXHQgKi9cblx0dXBkYXRlRWxlbWVudElkSWZTcGVjaWFsU3VyZmFjZV8oZWxlbWVudCkge1xuXHRcdGlmICghZWxlbWVudC5pZCAmJiBlbGVtZW50ID09PSBnbG9iYWxzLmRvY3VtZW50LmJvZHkpIHtcblx0XHRcdGVsZW1lbnQuaWQgPSAnc2VubmFfc3VyZmFjZV8nICsgZ2V0VWlkKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGJhc2UgZWxlbWVudC5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBiYXNlRWxlbWVudFxuXHQgKi9cblx0c2V0QmFzZUVsZW1lbnQoYmFzZUVsZW1lbnQpIHtcblx0XHR0aGlzLmJhc2VFbGVtZW50ID0gYmFzZUVsZW1lbnQ7XG5cdH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBBcHBEYXRhQXR0cmlidXRlSGFuZGxlcjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IGdsb2JhbHMgZnJvbSAnLi4vZ2xvYmFscy9nbG9iYWxzJztcbmltcG9ydCBBcHBEYXRhQXR0cmlidXRlSGFuZGxlciBmcm9tICcuL0FwcERhdGFBdHRyaWJ1dGVIYW5kbGVyJztcblxuLyoqXG4gKiBEYXRhIGF0dHJpYnV0ZSBoYW5kbGVyLlxuICogQHR5cGUge0FwcERhdGFBdHRyaWJ1dGVIYW5kbGVyfVxuICovXG52YXIgZGF0YUF0dHJpYnV0ZUhhbmRsZXIgPSBuZXcgQXBwRGF0YUF0dHJpYnV0ZUhhbmRsZXIoKTtcblxuZ2xvYmFscy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZnVuY3Rpb24oKSB7XG5cdGRhdGFBdHRyaWJ1dGVIYW5kbGVyLnNldEJhc2VFbGVtZW50KGdsb2JhbHMuZG9jdW1lbnQuYm9keSk7XG5cdGRhdGFBdHRyaWJ1dGVIYW5kbGVyLmhhbmRsZSgpO1xufSk7XG5cbmV4cG9ydCBkZWZhdWx0IGRhdGFBdHRyaWJ1dGVIYW5kbGVyOyJdLCJuYW1lcyI6WyJnbG9iYWxzIiwid2luZG93IiwiZG9jdW1lbnQiLCJjb21wYXRpYmlsaXR5TW9kZURhdGFfIiwidW5pcXVlSWRDb3VudGVyXyIsIlVJRF9QUk9QRVJUWSIsIk1hdGgiLCJyYW5kb20iLCJhYnN0cmFjdE1ldGhvZCIsIkVycm9yIiwiZGlzYWJsZUNvbXBhdGliaWxpdHlNb2RlIiwidW5kZWZpbmVkIiwiZW5hYmxlQ29tcGF0aWJpbGl0eU1vZGUiLCJvcHRfZGF0YSIsImdldENvbXBhdGliaWxpdHlNb2RlRGF0YSIsIl9fTUVUQUxfQ09NUEFUSUJJTElUWV9fIiwiZ2V0Rmlyc3RUcnV0aHlfIiwiYSIsImIiLCJnZXRGdW5jdGlvbk5hbWUiLCJmbiIsIm5hbWUiLCJzdHIiLCJ0b1N0cmluZyIsInN1YnN0cmluZyIsImluZGV4T2YiLCJnZXRTdGF0aWNQcm9wZXJ0eSIsImN0b3IiLCJwcm9wZXJ0eU5hbWUiLCJvcHRfbWVyZ2VGbiIsIm1lcmdlZE5hbWUiLCJoYXNPd25Qcm9wZXJ0eSIsIm1lcmdlZCIsIl9fcHJvdG9fXyIsImlzUHJvdG90eXBlT2YiLCJGdW5jdGlvbiIsIm1lcmdlRm4iLCJnZXRVaWQiLCJvcHRfb2JqZWN0Iiwib3B0X25vSW5oZXJpdGFuY2UiLCJpZCIsImlkZW50aXR5RnVuY3Rpb24iLCJvcHRfcmV0dXJuVmFsdWUiLCJpc0Jvb2xlYW4iLCJ2YWwiLCJpc0RlZiIsImlzRGVmQW5kTm90TnVsbCIsImlzTnVsbCIsImlzRG9jdW1lbnQiLCJub2RlVHlwZSIsImlzRG9jdW1lbnRGcmFnbWVudCIsImlzRWxlbWVudCIsImlzRnVuY3Rpb24iLCJpc051bWJlciIsImlzV2luZG93IiwiaXNPYmplY3QiLCJ0eXBlIiwiaXNQcm9taXNlIiwidGhlbiIsImlzU3RyaW5nIiwiU3RyaW5nIiwiaXNTZXJ2ZXJTaWRlIiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwiYnJvd3NlciIsIm51bGxGdW5jdGlvbiIsImFycmF5IiwiYXJyMSIsImFycjIiLCJsZW5ndGgiLCJpIiwiYXJyIiwib3B0X291dHB1dCIsIm91dHB1dCIsIkFycmF5IiwiaXNBcnJheSIsImZsYXR0ZW4iLCJwdXNoIiwib2JqIiwicnYiLCJyZW1vdmVBdCIsInByb3RvdHlwZSIsInNwbGljZSIsImNhbGwiLCJzdGFydCIsIm9wdF9lbmQiLCJzbGljZWQiLCJlbmQiLCJhc3luYyIsInRocm93RXhjZXB0aW9uIiwiZXhjZXB0aW9uIiwibmV4dFRpY2siLCJydW4iLCJjYWxsYmFjayIsIm9wdF9jb250ZXh0Iiwid29ya1F1ZXVlU2NoZWR1bGVkXyIsInByb2Nlc3NXb3JrUXVldWUiLCJ3b3JrUXVldWVfIiwiV29ya0l0ZW1fIiwid29ya0l0ZW1zIiwid29ya0l0ZW0iLCJzY29wZSIsImUiLCJjYiIsImJpbmQiLCJ3cmFwQ2FsbGJhY2tfIiwic2V0SW1tZWRpYXRlIiwic2V0SW1tZWRpYXRlXyIsImdldFNldEltbWVkaWF0ZUVtdWxhdG9yXyIsIkNoYW5uZWwiLCJNZXNzYWdlQ2hhbm5lbCIsInBvc3RNZXNzYWdlIiwiYWRkRXZlbnRMaXN0ZW5lciIsImlmcmFtZSIsImNyZWF0ZUVsZW1lbnQiLCJzdHlsZSIsImRpc3BsYXkiLCJzcmMiLCJkb2N1bWVudEVsZW1lbnQiLCJhcHBlbmRDaGlsZCIsIndpbiIsImNvbnRlbnRXaW5kb3ciLCJkb2MiLCJvcGVuIiwid3JpdGUiLCJjbG9zZSIsIm1lc3NhZ2UiLCJvcmlnaW4iLCJsb2NhdGlvbiIsInByb3RvY29sIiwiaG9zdCIsIm9ubWVzc2FnZSIsImRhdGEiLCJwb3J0MSIsInBvcnQyIiwiY2hhbm5lbCIsImhlYWQiLCJ0YWlsIiwibmV4dCIsInNjcmlwdCIsIm9ucmVhZHlzdGF0ZWNoYW5nZSIsInBhcmVudE5vZGUiLCJyZW1vdmVDaGlsZCIsIkRpc3Bvc2FibGUiLCJkaXNwb3NlZF8iLCJkaXNwb3NlSW50ZXJuYWwiLCJvYmplY3QiLCJ0YXJnZXQiLCJrZXkiLCJzb3VyY2UiLCJhcmd1bWVudHMiLCJvcHRfb2JqIiwicGFydHMiLCJzcGxpdCIsInJlZHVjZSIsInBhcnQiLCJtYXBwZWRPYmoiLCJrZXlzIiwiT2JqZWN0Iiwib2JqMSIsIm9iajIiLCJrZXlzMSIsImtleXMyIiwic3RyaW5nIiwic3RyMSIsInN0cjIiLCJ0ZXN0MSIsInRvTG93ZXJDYXNlIiwidGVzdDIiLCJyZXBsYWNlIiwieCIsImZsb29yIiwiYWJzIiwiRGF0ZSIsIm5vdyIsImhhc2giLCJsZW4iLCJjaGFyQ29kZUF0IiwidmFsdWUiLCJwYXJzZUZyb21BbmNob3IiLCJvcHRfdXJpIiwibGluayIsImhyZWYiLCJ0ZXN0IiwiVHlwZUVycm9yIiwiaG9zdG5hbWUiLCJwYXNzd29yZCIsInBhdGhuYW1lIiwicG9ydCIsInNlYXJjaCIsInVzZXJuYW1lIiwicGFyc2UiLCJVUkwiLCJ1cmwiLCJjcmVhdGUiLCJNdWx0aU1hcCIsInZhbHVlcyIsInNpemUiLCJtYXAiLCJuYW1lcyIsIkpTT04iLCJzdHJpbmdpZnkiLCJzZXQiLCJUcmVlTm9kZSIsInZhbHVlXyIsInBhcmVudF8iLCJjaGlsZHJlbl8iLCJjaGlsZCIsInNldFBhcmVudCIsIm5vZGUiLCJjdXJyZW50IiwiZ2V0UGFyZW50IiwiYW5jZXN0b3JzIiwiaW5kZXgiLCJnZXRDaGlsZHJlbiIsIkVNUFRZX0FSUkFZIiwiZGVwdGgiLCJyb290IiwiZ2V0Q2hpbGRDb3VudCIsInJlbW92ZSIsInBhcmVudCIsIm9wdF9wcmVvcmRlckZuIiwib3B0X3Bvc3RvcmRlckZuIiwiZm9yRWFjaCIsInRyYXZlcnNlIiwiYXNzZXJ0Q2hpbGRIYXNOb1BhcmVudCIsInBhcnNlRm5fIiwiVXJpIiwibWF5YmVBZGRQcm90b2NvbEFuZEhvc3RuYW1lXyIsIm11bHRpbWFwIiwiZ2V0QWxsIiwiYWRkUGFyYW1ldGVyVmFsdWUiLCJlbnN1cmVRdWVyeUluaXRpYWxpemVkXyIsInF1ZXJ5IiwiYWRkIiwicGFyYW0iLCJ1cmxEZWNvZGUiLCJnZXRIb3N0bmFtZSIsImdldFBvcnQiLCJIT1NUTkFNRV9QTEFDRUhPTERFUiIsImdldEhvc3QiLCJnZXRQcm90b2NvbCIsImdldCIsInF1ZXJ5c3RyaW5nIiwiZ2V0UGFyYW1ldGVyTmFtZXMiLCJnZXRQYXJhbWV0ZXJWYWx1ZXMiLCJlbmNvZGVVUklDb21wb25lbnQiLCJzbGljZSIsImNvbnRhaW5zIiwic2V0UGFyYW1ldGVyVmFsdWUiLCJSQU5ET01fUEFSQU0iLCJnZXRSYW5kb21TdHJpbmciLCJERUZBVUxUX1BST1RPQ09MIiwiY2hhckF0IiwicmVtb3ZlUGFyYW1ldGVyIiwiZ2V0UGF0aG5hbWUiLCJnZXRTZWFyY2giLCJnZXRIYXNoIiwicGFyc2VGbiIsImJhc2VQYXRoIiwicGF0aHMiLCJwYXRoIiwiY29uY2F0Iiwiam9pbiIsImRlY29kZVVSSUNvbXBvbmVudCIsImlzU2VjdXJlIiwidXRpbHMiLCJhdHRyaWJ1dGVzIiwiYXR0cmlidXRlIiwic2V0QXR0cmlidXRlIiwiZ2V0Q3VycmVudEJyb3dzZXJQYXRoV2l0aG91dEhhc2giLCJvZmZzZXRMZWZ0Iiwib2Zmc2V0VG9wIiwib2Zmc2V0UGFyZW50IiwidXJpIiwiY3VycmVudEJyb3dzZXJQYXRoIiwiZ2V0VXJsUGF0aFdpdGhvdXRIYXNoIiwiZ2V0VXJsUGF0aCIsImhpc3RvcnkiLCJwdXNoU3RhdGUiLCJlcnIiLCJlcnJvciIsInJlbW92ZUF0dHJpYnV0ZSIsInN1YnN0ciIsIk1FVEFMX0RBVEEiLCJkb21EYXRhIiwiZWxlbWVudCIsIm9wdF9uYW1lIiwib3B0X2luaXRpYWxWYWwiLCJFdmVudEhhbmRsZSIsImVtaXR0ZXIiLCJldmVudCIsImxpc3RlbmVyIiwiZW1pdHRlcl8iLCJldmVudF8iLCJsaXN0ZW5lcl8iLCJyZW1vdmVMaXN0ZW5lciIsImlzRGlzcG9zZWQiLCJzaW5nbGVBcnJheV8iLCJFdmVudEVtaXR0ZXIiLCJldmVudHNfIiwibGlzdGVuZXJIYW5kbGVyc18iLCJzaG91bGRVc2VGYWNhZGVfIiwiaG9sZGVyIiwiaGFuZGxlciIsIm9wdF9kZWZhdWx0IiwidmFsaWRhdGVMaXN0ZW5lcl8iLCJldmVudHMiLCJ0b0V2ZW50c0FycmF5XyIsImFkZFNpbmdsZUxpc3RlbmVyXyIsIm9wdF9vcmlnaW4iLCJydW5MaXN0ZW5lckhhbmRsZXJzXyIsImFkZEhhbmRsZXJfIiwiZ2V0U2hvdWxkVXNlRmFjYWRlIiwiZmFjYWRlIiwicHJldmVudGVkRGVmYXVsdCIsImxpc3RlbmVycyIsImdldFJhd0xpc3RlbmVyc18iLCJhcmdzIiwicnVuTGlzdGVuZXJzXyIsImJ1aWxkRmFjYWRlXyIsImRpcmVjdExpc3RlbmVycyIsInRvQXJyYXkiLCJhbW91bnQiLCJtYW55XyIsInNlbGYiLCJoYW5kbGVySW50ZXJuYWwiLCJhcHBseSIsImxpc3RlbmVyT2JqIiwicmVtb3ZlTWF0Y2hpbmdMaXN0ZW5lck9ianNfIiwiYWRkTGlzdGVuZXIiLCJtYW55Iiwib3B0X2V2ZW50cyIsImxpc3RlbmVyT2JqcyIsImZpbmFsTGlzdGVuZXJzIiwibWF0Y2hlc0xpc3RlbmVyXyIsIm9mZiIsImhhbmRsZXJzIiwiZGVmYXVsdExpc3RlbmVycyIsImRlZmF1bHQiLCJqIiwic2hvdWxkVXNlRmFjYWRlIiwiRXZlbnRFbWl0dGVyUHJveHkiLCJvcmlnaW5FbWl0dGVyIiwidGFyZ2V0RW1pdHRlciIsIm9wdF9ibGFja2xpc3QiLCJvcHRfd2hpdGVsaXN0IiwiYmxhY2tsaXN0XyIsIm9yaWdpbkVtaXR0ZXJfIiwicGVuZGluZ0V2ZW50c18iLCJwcm94aWVkRXZlbnRzXyIsInRhcmdldEVtaXR0ZXJfIiwid2hpdGVsaXN0XyIsInN0YXJ0UHJveHlfIiwib24iLCJyZW1vdmVMaXN0ZW5lcnNfIiwiZW1pdCIsInNob3VsZFByb3h5RXZlbnRfIiwidHJ5VG9BZGRMaXN0ZW5lcl8iLCJwcm94eUV2ZW50Iiwib25MaXN0ZW5lciIsImFkZExpc3RlbmVyXyIsImVtaXRPblRhcmdldF8iLCJFdmVudEhhbmRsZXIiLCJldmVudEhhbmRsZXNfIiwiRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGUiLCJvcHRfc2VsZWN0b3IiLCJzZWxlY3Rvcl8iLCJkZWxlZ2F0aW5nIiwic2VsZWN0b3IiLCJzZWxlY3RvcnMiLCJEb21FdmVudEhhbmRsZSIsIm9wdF9jYXB0dXJlIiwiY2FwdHVyZV8iLCJyZW1vdmVFdmVudExpc3RlbmVyIiwiZWxlbWVudHNCeVRhZ18iLCJzdXBwb3J0Q2FjaGVfIiwiY3VzdG9tRXZlbnRzIiwiTEFTVF9DT05UQUlORVIiLCJVU0VfQ0FQVFVSRSIsImFkZENsYXNzZXMiLCJlbGVtZW50cyIsImNsYXNzZXMiLCJhZGRDbGFzc2VzV2l0aE5hdGl2ZV8iLCJjbGFzc05hbWUiLCJjbGFzc0xpc3QiLCJhZGRDbGFzc2VzV2l0aG91dE5hdGl2ZV8iLCJlbGVtZW50Q2xhc3NOYW1lIiwiY2xhc3Nlc1RvQXBwZW5kIiwiYWRkRWxlbWVudExpc3RlbmVyXyIsImV2ZW50TmFtZSIsImFkZFNlbGVjdG9yTGlzdGVuZXJfIiwiZGVsZWdhdGluZ0RhdGEiLCJhZGRUb0Fycl8iLCJhdHRhY2hEZWxlZ2F0ZUV2ZW50XyIsImhhbmRsZURlbGVnYXRlRXZlbnRfIiwiY2xvc2VzdCIsIm1hdGNoIiwiYXBwZW5kIiwiYnVpbGRGcmFnbWVudCIsIk5vZGVMaXN0IiwiY2hpbGRBcnIiLCJodG1sU3RyaW5nIiwidGVtcERpdiIsImlubmVySFRNTCIsImZpcnN0Q2hpbGQiLCJmcmFnbWVudCIsImNyZWF0ZURvY3VtZW50RnJhZ21lbnQiLCJlbGVtZW50MSIsImVsZW1lbnQyIiwiZGVsZWdhdGUiLCJzZWxlY3Rvck9yVGFyZ2V0IiwiY3VzdG9tQ29uZmlnIiwib3JpZ2luYWxFdmVudCIsImRlZmF1bHRMaXN0ZW5lcl8iLCJpc0FibGVUb0ludGVyYWN0V2l0aF8iLCJvcHRfZXZlbnRPYmoiLCJidXR0b24iLCJtYXRjaGVzU2VsZWN0b3IiLCJ0YWdOYW1lIiwiZGlzYWJsZWQiLCJleGl0RG9jdW1lbnQiLCJyZXQiLCJjb250YWluZXIiLCJjdXJyZW50VGFyZ2V0IiwiZGVmRm5zIiwidHJpZ2dlckRlbGVnYXRlZExpc3RlbmVyc18iLCJ0cmlnZ2VyRGVmYXVsdERlbGVnYXRlZExpc3RlbmVyc18iLCJkZWxlZ2F0ZVRhcmdldCIsInAiLCJFbGVtZW50IiwibSIsIm1hdGNoZXMiLCJ3ZWJraXRNYXRjaGVzU2VsZWN0b3IiLCJtb3pNYXRjaGVzU2VsZWN0b3IiLCJtc01hdGNoZXNTZWxlY3RvciIsIm9NYXRjaGVzU2VsZWN0b3IiLCJtYXRjaEZhbGxiYWNrXyIsIm5vZGVzIiwicXVlcnlTZWxlY3RvckFsbCIsIm5vcm1hbGl6ZURlbGVnYXRlRXZlbnRfIiwic3RvcFByb3BhZ2F0aW9uIiwic3RvcFByb3BhZ2F0aW9uXyIsInN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbiIsInN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbl8iLCJvbmNlIiwiZG9tRXZlbnRIYW5kbGUiLCJyZWdpc3RlckN1c3RvbUV2ZW50IiwicmVtb3ZlQ2hpbGRyZW4iLCJyZW1vdmVDbGFzc2VzIiwicmVtb3ZlQ2xhc3Nlc1dpdGhOYXRpdmVfIiwicmVtb3ZlQ2xhc3Nlc1dpdGhvdXROYXRpdmVfIiwidHJpbSIsInN0b3BwZWQiLCJzdG9wcGVkSW1tZWRpYXRlIiwic3VwcG9ydHNFdmVudCIsInRhZyIsImRlZmF1bHRQcmV2ZW50ZWQiLCJkZWZhdWx0Rm5zIiwiY3VyckVsZW1lbnQiLCJsaW1pdCIsInRyaWdnZXJFbGVtZW50TGlzdGVuZXJzXyIsInRyaWdnZXJTZWxlY3Rvckxpc3RlbmVyc18iLCJsYXN0Q29udGFpbmVyIiwidHJpZ2dlckxpc3RlbmVyc18iLCJEb21FdmVudEVtaXR0ZXJQcm94eSIsImlzRGVsZWdhdGVFdmVudF8iLCJiYWJlbEhlbHBlcnMuZ2V0IiwiaXNTdXBwb3J0ZWREb21FdmVudF8iLCJmZWF0dXJlcyIsImFuaW1hdGlvbkV2ZW50TmFtZV8iLCJjaGVja0FuaW1hdGlvbkV2ZW50TmFtZV8iLCJwcmVmaXhlcyIsInR5cGVUaXRsZUNhc2UiLCJyZXBsYWNlSW50ZXJ2YWwiLCJ0b1VwcGVyQ2FzZSIsInN1ZmZpeGVzIiwiYW5pbWF0aW9uRWxlbWVudF8iLCJhdHRyT3JkZXJDaGFuZ2VfIiwib3JpZ2luYWxDb250ZW50IiwiZ2xvYmFsRXZhbCIsInRleHQiLCJvcHRfYXBwZW5kRm4iLCJvcHRfY2FsbGJhY2siLCJydW5GaWxlIiwic2NyaXB0cyIsInJ1blNjcmlwdHNJbk9yZGVyIiwicnVuU2NyaXB0IiwiaXRlbSIsImdsb2JhbEV2YWxTdHlsZXMiLCJyZWwiLCJydW5TdHlsZSIsInN0eWxlcyIsImxvYWRDb3VudCIsIm1vdXNlRXZlbnRNYXAiLCJyZWxhdGVkIiwicmVsYXRlZFRhcmdldCIsImN1c3RvbVR5cGUiLCJhbmltYXRpb25FdmVudE1hcCIsImV2ZW50VHlwZSIsImNoZWNrQW5pbWF0aW9uRXZlbnROYW1lIiwiVGhlbmFibGUiLCJJTVBMRU1FTlRFRF9CWV9QUk9QIiwiYWRkSW1wbGVtZW50YXRpb24iLCIkZ29vZ19UaGVuYWJsZSIsImlzSW1wbGVtZW50ZWRCeSIsInBhcnRpYWwiLCJuZXdBcmdzIiwiQ2FuY2VsbGFibGVQcm9taXNlIiwicmVzb2x2ZXIiLCJzdGF0ZV8iLCJTdGF0ZV8iLCJQRU5ESU5HIiwicmVzdWx0XyIsImNhbGxiYWNrRW50cmllc18iLCJleGVjdXRpbmdfIiwiVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSIsInVuaGFuZGxlZFJlamVjdGlvbklkXyIsImhhZFVuaGFuZGxlZFJlamVjdGlvbl8iLCJyZXNvbHZlXyIsIkZVTEZJTExFRCIsInJlYXNvbiIsIlJFSkVDVEVEIiwiQ2FsbGJhY2tFbnRyeV8iLCJyZXNvbHZlIiwib3B0X3ZhbHVlIiwicmVqZWN0Iiwib3B0X3JlYXNvbiIsInJhY2UiLCJwcm9taXNlcyIsInByb21pc2UiLCJhbGwiLCJ0b0Z1bGZpbGwiLCJvbkZ1bGZpbGwiLCJvblJlamVjdCIsImZpcnN0RnVsZmlsbGVkIiwidG9SZWplY3QiLCJyZWFzb25zIiwib3B0X29uRnVsZmlsbGVkIiwib3B0X29uUmVqZWN0ZWQiLCJhZGRDaGlsZFByb21pc2VfIiwidGhlbkFsd2F5cyIsIm9uUmVzb2x2ZWQiLCJoYW5kbGVSZWplY3Rpb25fIiwiYWRkQ2FsbGJhY2tFbnRyeV8iLCJ0aGVuQ2F0Y2giLCJvblJlamVjdGVkIiwiY2F0Y2giLCJjYW5jZWwiLCJvcHRfbWVzc2FnZSIsIkNhbmNlbGxhdGlvbkVycm9yIiwiSVNfQ0FOQ0VMTEFUSU9OX0VSUk9SIiwiY2FuY2VsSW50ZXJuYWxfIiwiY2FuY2VsQ2hpbGRfIiwiY2hpbGRQcm9taXNlIiwiY2hpbGRDb3VudCIsImNoaWxkSW5kZXgiLCJlbnRyeSIsImNhbGxiYWNrRW50cnkiLCJleGVjdXRlQ2FsbGJhY2tfIiwic2NoZWR1bGVDYWxsYmFja3NfIiwib25GdWxmaWxsZWQiLCJyZXN1bHQiLCJ1bmJsb2NrQW5kRnVsZmlsbF8iLCJCTE9DS0VEIiwidW5ibG9ja0FuZFJlamVjdF8iLCJzdGF0ZSIsInRyeVRoZW5fIiwiYWRkVW5oYW5kbGVkUmVqZWN0aW9uXyIsInRoZW5hYmxlIiwiY2FsbGVkIiwiZXhlY3V0ZUNhbGxiYWNrc18iLCJlbnRyaWVzIiwicmVtb3ZlVW5oYW5kbGVkUmVqZWN0aW9uXyIsInNldFRpbWVvdXQiLCJzZXRVbmhhbmRsZWRSZWplY3Rpb25IYW5kbGVyIiwiZGVib3VuY2UiLCJkZWxheSIsImRlYm91bmNlZCIsImNhbmNlbERlYm91bmNlIiwiUkVHRVgiLCJjb252ZXJ0TWF0Y2hlc1RvT2JqIiwiY29udmVydFRva2Vuc1RvUmVnZXgiLCJ0b2tlbnMiLCJyZWdleCIsImNvcmUiLCJlc2NhcGUiLCJjYXB0dXJlIiwiZW5jbG9zZU5vbkNhcHR1cmluZ0dyb3VwIiwicGF0dGVybiIsInJlcGVhdCIsInByZWZpeCIsIm9wdGlvbmFsIiwiUmVnRXhwIiwibWFrZVRyYWlsaW5nU2xhc2hPcHRpb25hbCIsInJvdXRlT3JUb2tlbnMiLCJyb3V0ZSIsInVubmFtZWRDb3VudCIsImN1cnJQYXRoIiwiZXhlYyIsInBhcmFtUGF0dGVybiIsInVubmFtZWRQYXR0ZXJuIiwibW9kaWZpZXIiLCJ0b1JlZ2V4IiwiZXh0cmFjdERhdGEiLCJwYXJhbUluZGV4IiwiUm91dGUiLCJwYXJzZWREYXRhXyIsImJ1aWxkUGFyc2VkRGF0YV8iLCJDYWNoZWFibGUiLCJjYWNoZSIsImNhY2hlYWJsZSIsImNvbnRlbnQiLCJjbGVhckNhY2hlIiwiU2NyZWVuIiwibWFrZUlkXyIsInRpdGxlIiwibG9nIiwic3VyZmFjZXMiLCJzSWQiLCJhY3RpdmVDaGlsZCIsInJ1blNjcmlwdHNJbkVsZW1lbnQiLCJ0cmFuc2l0aW9ucyIsInN1cmZhY2UiLCJkZWZlcnJlZCIsInNob3ciLCJTdXJmYWNlIiwiZGVmYXVsdENoaWxkIiwidHJhbnNpdGlvbkZuIiwiZ2V0Q2hpbGQiLCJERUZBVUxUIiwibWF5YmVXcmFwQ29udGVudEFzRGVmYXVsdF8iLCJzY3JlZW5JZCIsIm9wdF9jb250ZW50IiwiY3JlYXRlQ2hpbGQiLCJ0cmFuc2l0aW9uIiwiZ2V0RWxlbWVudCIsImdldEVsZW1lbnRCeUlkIiwiYWRkQ29udGVudCIsImZyb20iLCJ0byIsImRlZmF1bHRUcmFuc2l0aW9uIiwiQXBwIiwiYWN0aXZlU2NyZWVuIiwiYWN0aXZlUGF0aCIsImFsbG93UHJldmVudE5hdmlnYXRlIiwiYnJvd3NlclBhdGhCZWZvcmVOYXZpZ2F0ZSIsImNhcHR1cmVTY3JvbGxQb3NpdGlvbkZyb21TY3JvbGxFdmVudCIsImRlZmF1bHRUaXRsZSIsImZvcm1TZWxlY3RvciIsImlnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aCIsImxpbmtTZWxlY3RvciIsImxvYWRpbmdDc3NDbGFzcyIsIm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uU3VwcG9ydGVkIiwiaXNOYXZpZ2F0aW9uUGVuZGluZyIsInBlbmRpbmdOYXZpZ2F0ZSIsInBvcHN0YXRlU2Nyb2xsTGVmdCIsInBvcHN0YXRlU2Nyb2xsVG9wIiwicmVkaXJlY3RQYXRoIiwicm91dGVzIiwic2NyZWVucyIsInNraXBMb2FkUG9wc3RhdGUiLCJ1cGRhdGVTY3JvbGxQb3NpdGlvbiIsImFwcEV2ZW50SGFuZGxlcnNfIiwib25TY3JvbGxfIiwib25Mb2FkXyIsIm9uUG9wc3RhdGVfIiwib25TdGFydE5hdmlnYXRlXyIsIm9uQmVmb3JlTmF2aWdhdGVfIiwib25CZWZvcmVOYXZpZ2F0ZURlZmF1bHRfIiwib25CZWZvcmVVbmxvYWREZWZhdWx0XyIsInNldExpbmtTZWxlY3RvciIsInNldEZvcm1TZWxlY3RvciIsIm1heWJlT3ZlcmxvYWRCZWZvcmVVbmxvYWRfIiwiZ2V0SWQiLCJpc1dlYlVyaSIsImlzTGlua1NhbWVPcmlnaW5fIiwiaXNTYW1lQmFzZVBhdGhfIiwiaXNDdXJyZW50QnJvd3NlclBhdGgiLCJmaW5kUm91dGUiLCJyZW1vdmVTY3JlZW4iLCJzY3JlZW4iLCJnZXRIYW5kbGVyIiwiY2xlYXJTY3JlZW5zQ2FjaGUiLCJmb3JtRXZlbnRIYW5kbGVyXyIsImxpbmtFdmVudEhhbmRsZXJfIiwicmVtb3ZlQWxsTGlzdGVuZXJzIiwibmF2aWdhdGUiLCJnZXRDdXJyZW50QnJvd3NlclBhdGgiLCJvcHRfcmVwbGFjZUhpc3RvcnkiLCJiZWZvcmVEZWFjdGl2YXRlIiwic3RvcFBlbmRpbmdOYXZpZ2F0ZV8iLCJuZXh0U2NyZWVuIiwiY3JlYXRlU2NyZWVuSW5zdGFuY2UiLCJsb2FkIiwiZGVhY3RpdmF0ZSIsInByZXBhcmVOYXZpZ2F0ZUhpc3RvcnlfIiwicHJlcGFyZU5hdmlnYXRlU3VyZmFjZXNfIiwiZXh0cmFjdFBhcmFtcyIsImV2YWx1YXRlU3R5bGVzIiwiZmxpcCIsImV2YWx1YXRlU2NyaXB0cyIsIm1heWJlVXBkYXRlU2Nyb2xsUG9zaXRpb25TdGF0ZV8iLCJzeW5jU2Nyb2xsUG9zaXRpb25TeW5jVGhlbkFzeW5jXyIsImZpbmFsaXplTmF2aWdhdGVfIiwiaGFuZGxlTmF2aWdhdGVFcnJvcl8iLCJnZXRSb3V0ZVBhdGgiLCJhY3RpdmF0ZSIsImlzQ2FjaGVhYmxlIiwiY2FwdHVyZWRGb3JtRWxlbWVudCIsImNhcHR1cmVkRm9ybUJ1dHRvbkVsZW1lbnQiLCJtYXRjaGVzUGF0aCIsImdldElnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aCIsImdldFVybFBhdGhXaXRob3V0SGFzaEFuZFNlYXJjaCIsIndpbm5lciIsInN3aXRjaFNjcm9sbFBvc2l0aW9uUmFjZSIsInNjcm9sbFRvIiwic2Nyb2xsTGVmdCIsInNjcm9sbFRvcCIsIm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uXyIsInNjcm9sbFJlc3RvcmF0aW9uIiwiY2FuTmF2aWdhdGUiLCJuYXZpZ2F0ZUZhaWxlZCIsInByZXZlbnREZWZhdWx0Iiwib25iZWZvcmV1bmxvYWQiLCJfb25iZWZvcmV1bmxvYWQiLCJfb3ZlcmxvYWRlZCIsImFuY2hvckVsZW1lbnQiLCJnZXROb2RlT2Zmc2V0Iiwic2F2ZUhpc3RvcnlDdXJyZW50UGFnZVNjcm9sbFBvc2l0aW9uXyIsIm9wdF9ldmVudCIsImlzSHRtbDVIaXN0b3J5U3VwcG9ydGVkIiwiZm9ybSIsInJlcGxhY2VIaXN0b3J5IiwiZnVuYyIsImFsdEtleSIsImN0cmxLZXkiLCJtZXRhS2V5Iiwic2hpZnRLZXkiLCJtYXliZU5hdmlnYXRlXyIsIm1ldGhvZCIsImJ1dHRvblNlbGVjdG9yIiwiYWN0aXZlRWxlbWVudCIsInF1ZXJ5U2VsZWN0b3IiLCJhY3Rpb24iLCJtYXliZVJlcG9zaXRpb25TY3JvbGxUb0hhc2hlZEFuY2hvciIsInJlbG9hZFBhZ2UiLCJzZW5uYSIsImxvY2tIaXN0b3J5U2Nyb2xsUG9zaXRpb25fIiwicGFnZVlPZmZzZXQiLCJwYWdlWE9mZnNldCIsIm1heWJlRGlzYWJsZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uIiwiZW5kTmF2aWdhdGVQYXlsb2FkIiwiZG9OYXZpZ2F0ZV8iLCJtYXliZVJlc3RvcmVOYXRpdmVTY3JvbGxSZXN0b3JhdGlvbiIsImdldFRpdGxlIiwiZ2V0RGVmYXVsdFRpdGxlIiwiYmVmb3JlVXBkYXRlSGlzdG9yeVBhdGgiLCJoaXN0b3J5U3RhdGUiLCJtYXliZVJlc3RvcmVSZWRpcmVjdFBhdGhIYXNoXyIsInVwZGF0ZUhpc3RvcnlfIiwiYmVmb3JlVXBkYXRlSGlzdG9yeVN0YXRlIiwicGFyYW1zIiwic3VyZmFjZUNvbnRlbnQiLCJnZXRTdXJmYWNlQ29udGVudCIsInJlbG9hZCIsInN1cmZhY2VJZCIsImRpc3Bvc2UiLCJyZXBsYWNlU3RhdGUiLCJyZW1vdmVQYXRoVHJhaWxpbmdTbGFzaCIsIm9uRG9jU3VibWl0RGVsZWdhdGVfIiwib25Eb2NDbGlja0RlbGVnYXRlXyIsInN5bmMiLCJ0aXRsZU5vZGUiLCJBamF4IiwiYWxsSGVhZGVycyIsImhlYWRlcnMiLCJwYWlycyIsImJvZHkiLCJvcHRfaGVhZGVycyIsIm9wdF9wYXJhbXMiLCJvcHRfdGltZW91dCIsIm9wdF9zeW5jIiwib3B0X3dpdGhDcmVkZW50aWFscyIsInJlcXVlc3QiLCJYTUxIdHRwUmVxdWVzdCIsInByZXZpb3VzUmVhZHlTdGF0ZSIsIlByb21pc2UiLCJvbmxvYWQiLCJhYm9ydGVkIiwib25lcnJvciIsInJlYWR5U3RhdGUiLCJ0ZXJtaW5hdGVkUHJlbWF0dXJlbHkiLCJhYm9ydCIsInRpbWVvdXQiLCJhZGRQYXJhbWV0ZXJzRnJvbU11bHRpTWFwIiwid2l0aENyZWRlbnRpYWxzIiwic2V0UmVxdWVzdEhlYWRlciIsInNlbmQiLCJlcnJvcnMiLCJJTlZBTElEX1NUQVRVUyIsIlJFUVVFU1RfRVJST1IiLCJSRVFVRVNUX1RJTUVPVVQiLCJSRVFVRVNUX1BSRU1BVFVSRV9URVJNSU5BVElPTiIsIlVBIiwibmF2aWdhdG9yIiwidXNlckFnZW50IiwicGxhdGZvcm0iLCJpc01hYyIsIm1hdGNoUGxhdGZvcm0iLCJpc1dpbiIsImlzT3BlcmEiLCJtYXRjaFVzZXJBZ2VudCIsImlzSWUiLCJpc0VkZ2UiLCJpc0llT3JFZGdlIiwiaXNDaHJvbWUiLCJpc1NhZmFyaSIsImlzRmlyZWZveCIsInRlc3RVc2VyQWdlbnQiLCJnZXROYXRpdmVVc2VyQWdlbnQiLCJnZXROYXRpdmVQbGF0Zm9ybSIsIlJlcXVlc3RTY3JlZW4iLCJodHRwSGVhZGVycyIsImh0dHBNZXRob2QiLCJHRVQiLCJzdGF0dXMiLCJpc1ZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlIiwiaW52YWxpZFN0YXR1cyIsInN0YXR1c0NvZGUiLCJnZXRSZXF1ZXN0UGF0aCIsInNldEhvc3RuYW1lIiwic2V0UHJvdG9jb2wiLCJzZXRQb3J0IiwibWFrZVVuaXF1ZSIsImdldFJlcXVlc3QiLCJyZXF1ZXN0UGF0aCIsInJlc3BvbnNlVXJsIiwibWF5YmVFeHRyYWN0UmVzcG9uc2VVcmxGcm9tUmVxdWVzdCIsInJlbW92ZVVuaXF1ZSIsImdldENhY2hlIiwiaGVhZGVyIiwiRm9ybURhdGEiLCJtYXliZUFwcGVuZFN1Ym1pdEJ1dHRvblZhbHVlXyIsIlBPU1QiLCJmb3JtYXRMb2FkUGF0aCIsInNldFJlcXVlc3QiLCJ4aHIiLCJhc3NlcnRWYWxpZFJlc3BvbnNlU3RhdHVzQ29kZSIsImFkZENhY2hlIiwicmVzcG9uc2VUZXh0IiwicmVxdWVzdEVycm9yIiwicmVxdWVzdFByZW1hdHVyZVRlcm1pbmF0aW9uIiwicmVzcG9uc2VVUkwiLCJnZXRSZXNwb25zZUhlYWRlciIsIlhfUkVRVUVTVF9VUkxfSEVBREVSIiwiSHRtbFNjcmVlbiIsInRpdGxlU2VsZWN0b3IiLCJyZWxlYXNlVmlydHVhbERvY3VtZW50IiwicGVuZGluZ1N0eWxlcyIsInZpcnR1YWxEb2N1bWVudCIsImNvcHlOb2RlQXR0cmlidXRlc0Zyb21Db250ZW50XyIsIm5ld1N0eWxlIiwiaXNUZW1wb3JhcnlTdHlsZSIsInN0eWxlc1RlbXBvcmFyeSIsInN0eWxlSW5Eb2MiLCJpbnNlcnRCZWZvcmUiLCJuZXh0U2libGluZyIsImJvZHlTdXJmYWNlIiwicGxhY2Vob2xkZXIiLCJjbGVhck5vZGVBdHRyaWJ1dGVzIiwiY29weU5vZGVBdHRyaWJ1dGVzIiwiZGlzcG9zZVBlbmRpbmdTdHlsZXMiLCJldmFsdWF0ZVRyYWNrZWRTY3JpcHRzIiwiZXZhbHVhdGVUcmFja2VkUmVzb3VyY2VzXyIsInNjcmlwdHNUZW1wb3JhcnkiLCJzY3JpcHRzUGVybWFuZW50IiwiZXZhbHVhdGVUcmFja2VkU3R5bGVzIiwicnVuU3R5bGVzSW5FbGVtZW50Iiwic3R5bGVzUGVybWFuZW50IiwiYXBwZW5kU3R5bGVJbnRvRG9jdW1lbnRfIiwiZXZhbHVhdG9yRm4iLCJzZWxlY3RvclRlbXBvcmFyeSIsInNlbGVjdG9yUGVybWFuZW50Iiwib3B0X2FwcGVuZFJlc291cmNlRm4iLCJ0cmFja2VkIiwidmlydHVhbFF1ZXJ5U2VsZWN0b3JBbGxfIiwidGVtcG9yYXJpZXNJbkRvYyIsInF1ZXJ5U2VsZWN0b3JBbGxfIiwicGVybWFuZW50c0luRG9jIiwicmVzb3VyY2UiLCJyZXNvdXJjZUtleSIsImdldFJlc291cmNlS2V5XyIsInBlcm1hbmVudFJlc291cmNlc0luRG9jIiwiZnJhZyIsImFsbG9jYXRlVmlydHVhbERvY3VtZW50Rm9yQ29udGVudCIsInJlc29sdmVUaXRsZUZyb21WaXJ0dWFsRG9jdW1lbnQiLCJhc3NlcnRTYW1lQm9keUlkSW5WaXJ0dWFsRG9jdW1lbnQiLCJtYWtlVGVtcG9yYXJ5U3R5bGVzSHJlZnNVbmlxdWVfIiwicmVwbGFjZVN0eWxlQW5kTWFrZVVuaXF1ZV8iLCJyZXBsYWNlQ2hpbGQiLCJzZXRUaXRsZSIsInRleHRDb250ZW50IiwiQXBwRGF0YUF0dHJpYnV0ZUhhbmRsZXIiLCJhcHAiLCJiYXNlRWxlbWVudCIsImhhc0F0dHJpYnV0ZSIsImRhdGFBdHRyaWJ1dGVzIiwibWF5YmVBZGRSb3V0ZXNfIiwibWF5YmVBZGRTdXJmYWNlc18iLCJtYXliZVNldEJhc2VQYXRoXyIsIm1heWJlU2V0TGlua1NlbGVjdG9yXyIsIm1heWJlU2V0TG9hZGluZ0Nzc0NsYXNzXyIsIm1heWJlU2V0VXBkYXRlU2Nyb2xsUG9zaXRpb25fIiwibWF5YmVEaXNwYXRjaF8iLCJyb3V0ZXNTZWxlY3RvciIsInF1ZXJ5U2VsZWN0b3JBbGxBc0FycmF5XyIsIm1heWJlUGFyc2VMaW5rUm91dGVfIiwiaGFzUm91dGVzIiwiYWRkUm91dGVzIiwic3VyZmFjZXNTZWxlY3RvciIsInN1cmZhY2VFbGVtZW50IiwidXBkYXRlRWxlbWVudElkSWZTcGVjaWFsU3VyZmFjZV8iLCJhZGRTdXJmYWNlcyIsImRpc3BhdGNoIiwibWF5YmVQYXJzZUxpbmtSb3V0ZVBhdGhfIiwibWF5YmVQYXJzZUxpbmtSb3V0ZUhhbmRsZXJfIiwiZ2V0UGF0aCIsImdldEF0dHJpYnV0ZSIsImdldE9iamVjdEJ5TmFtZSIsInNldEJhc2VQYXRoIiwic2V0TG9hZGluZ0Nzc0NsYXNzIiwic2V0VXBkYXRlU2Nyb2xsUG9zaXRpb24iLCJkYXRhQXR0cmlidXRlSGFuZGxlciIsInNldEJhc2VFbGVtZW50IiwiaGFuZGxlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxJQUFJQSxVQUFVQSxXQUFXLEVBQXpCOztBQUVBLElBQUksT0FBT0MsTUFBUCxLQUFrQixXQUF0QixFQUFtQztTQUMxQkEsTUFBUixHQUFpQkEsTUFBakI7OztBQUdELElBQUksT0FBT0Ms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"} \ No newline at end of file +{"version":3,"file":"senna.js","sources":["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-dom/src/domData.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-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","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/version.js"],"sourcesContent":["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=} opt_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(opt_data = {}) {\n\tcompatibilityModeData_ = opt_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(*, *):*=} opt_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 */\nexport function getStaticProperty(ctor, propertyName, opt_mergeFn) {\n\tconst mergedName = propertyName + '_MERGED';\n\tif (!ctor.hasOwnProperty(mergedName)) {\n\t\tlet merged = ctor.hasOwnProperty(propertyName) ? ctor[propertyName] : null;\n\t\tif (ctor.__proto__ && !ctor.__proto__.isPrototypeOf(Function)) {\n\t\t\tconst mergeFn = opt_mergeFn || getFirstTruthy_;\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 `opt_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=} opt_object Optional object to be mutated with the uid. If\n * not specified this method only returns the uid.\n * @param {boolean=} opt_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 */\nexport function getUid(opt_object, opt_noInheritance) {\n\tif (opt_object) {\n\t\tlet id = opt_object[UID_PROPERTY];\n\t\tif (opt_noInheritance && !opt_object.hasOwnProperty(UID_PROPERTY)) {\n\t\t\tid = null;\n\t\t}\n\t\treturn id || (opt_object[UID_PROPERTY] = uniqueIdCounter_++);\n\t}\n\treturn uniqueIdCounter_++;\n}\n\n/**\n * The identity function. Returns its first argument.\n * @param {*=} opt_returnValue The single value that will be returned.\n * @return {?} The first argument.\n */\nexport function identityFunction(opt_returnValue) {\n\treturn opt_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 * @return {boolean}\n */\nexport function isServerSide() {\n\treturn typeof process !== 'undefined' &&\n\t\ttypeof process.env !== 'undefined' &&\n\t\tprocess.env.NODE_ENV !== 'test' &&\n\t\t!process.browser;\n}\n\n/**\n * Null function used for default values of callbacks, etc.\n * @return {void} Nothing.\n */\nexport function nullFunction() {\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 core from './coreNamed';\n\nexport default core;\nexport { core };\nexport * from './coreNamed';\n","'use strict';\n\nimport { isDef } from '../core';\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.<*>} opt_output Optional output array.\n\t * @return {Array.<*>} Flat array.\n\t */\n\tstatic flatten(arr, opt_output) {\n\t\tvar output = opt_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=} opt_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, opt_end) {\n\t\tconst sliced = [];\n\t\tconst end = isDef(opt_end) ? opt_end : arr.length;\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\nconst async = {};\n\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/**\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=} opt_context Object to use as the \"this value\" when calling\n * the provided function.\n * @template THIS\n */\nasync.run = function(callback, opt_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(\n\t\tnew async.run.WorkItem_(callback, opt_context));\n};\n\n\n/** @private {boolean} */\nasync.run.workQueueScheduled_ = false;\n\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/**\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/**\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=} opt_context Object in whose scope to call the listener.\n * @template SCOPE\n */\nasync.nextTick = function(callback, opt_context) {\n\tlet cb = callback;\n\tif (opt_context) {\n\t\tcb = callback.bind(opt_context);\n\t}\n\tcb = async.nextTick.wrapCallback_(cb);\n\t// Introduced and currently only supported by IE10.\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 setImmediate === 'function') {\n\t\tsetImmediate(cb);\n\t\treturn;\n\t}\n\t// Look for and cache the custom fallback version of setImmediate.\n\tif (!async.nextTick.setImmediate_) {\n\t\tasync.nextTick.setImmediate_ = async.nextTick.getSetImmediateEmulator_();\n\t}\n\tasync.nextTick.setImmediate_(cb);\n};\n\n\n/**\n * Cache for the setImmediate implementation.\n * @type {function(function())}\n * @private\n */\nasync.nextTick.setImmediate_ = null;\n\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 (typeof Channel === 'undefined' && typeof window !== 'undefined' &&\n\t\twindow.postMessage && window.addEventListener) {\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\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 (typeof document !== 'undefined' && 'onreadystatechange' in\n\t\tdocument.createElement('script')) {\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/**\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(opt_returnValue) {\n\treturn opt_returnValue;\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\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\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) {\n\t\tlet key, source;\n\t\tfor (let i = 1; i < arguments.length; i++) {\n\t\t\tsource = arguments[i];\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=} opt_obj 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, opt_obj) {\n\t\tconst scope = opt_obj || 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 * @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\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.replace(/[\\t\\r\\n ]+/g, ' ').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');\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 Math.floor(Math.random() * x).toString(36) +\n\t\t\tMath.abs(Math.floor(Math.random() * x) ^ Date.now()).toString(36);\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 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* 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\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\nconst METAL_DATA = '__metal_data__';\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=} opt_name Optional property from the data to be returned.\n\t * @param {*} opt_initialVal Optinal 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, opt_name, opt_initialVal) {\n\t\tif (!element[METAL_DATA]) {\n\t\t\telement[METAL_DATA] = {};\n\t\t}\n\t\tif (!opt_name) {\n\t\t\treturn element[METAL_DATA];\n\t\t}\n\t\tif (!element[METAL_DATA][opt_name] && opt_initialVal) {\n\t\t\telement[METAL_DATA][opt_name] = opt_initialVal;\n\t\t}\n\t\treturn element[METAL_DATA][opt_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\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 * @param {!EventEmitter} emitter Emitter the event was subscribed to.\n * @param {string} event The name of the event that was subscribed to.\n * @param {!Function} listener The listener subscribed to the event.\n * @constructor\n * @extends {Disposable}\n */\nclass EventHandle extends Disposable {\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 * @constructor\n * @extends {Disposable}\n */\nclass EventEmitter extends Disposable {\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} opt_default 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, opt_default) {\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, opt_default);\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} opt_default 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 * @param {Function=} opt_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, opt_default, opt_origin) {\n\t\tthis.runListenerHandlers_(event);\n\t\tif (opt_default || opt_origin) {\n\t\t\tlistener = {\n\t\t\t\tdefault: opt_default,\n\t\t\t\tfn: listener,\n\t\t\t\torigin: opt_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);\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(toArray(this.events_ && this.events_['*']));\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\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);\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 fn === listener ||\n\t\t\t(listenerObj.origin && listenerObj.origin === listener);\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\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);\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()}\n\t */\n\tonListener(handler) {\n\t\tthis.listenerHandlers_ = this.addHandler_(this.listenerHandlers_, handler);\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)=} opt_events\n\t * @return {!Object} Returns emitter, so calls can be chained.\n\t */\n\tremoveAllListeners(opt_events) {\n\t\tif (this.events_) {\n\t\t\tif (opt_events) {\n\t\t\t\tconst events = this.toEventsArray_(opt_events);\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);\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\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 * @param {EventEmitter} originEmitter Events originated on this emitter\n * will be fired for the target emitter's listeners as well.\n * @param {EventEmitter} targetEmitter Event listeners attached to this emitter\n * will also be triggered when the event is fired by the origin emitter.\n * @param {Object} opt_blacklist Optional blacklist of events that should not be\n * proxied.\n * @constructor\n * @extends {Disposable}\n */\nclass EventEmitterProxy extends Disposable {\n\tconstructor(originEmitter, targetEmitter, opt_blacklist, opt_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_ = opt_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_ = opt_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_() {\n\t\tthis.targetEmitter_.emit.apply(this.targetEmitter_, arguments);\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 = this.originEmitter_ && this.proxiedEvents_ ?\n\t\t\tObject.keys(this.proxiedEvents_) :\n\t\t\tthis.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 * @constructor\n * @extends {Disposable}\n */\nclass EventHandler extends Disposable {\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() {\n\t\tfor (let i = 0; i < arguments.length; i++) {\n\t\t\tthis.eventHandles_.push(arguments[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=} opt_selector An optional selector used when delegating\n\t * the event.\n\t * @constructor\n\t */\n\tconstructor(emitter, event, listener, opt_selector) {\n\t\tsuper(emitter, event, listener);\n\t\tthis.selector_ = opt_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) ? delegating[this.event_].selectors : 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} opt_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, opt_capture) {\n\t\tsuper(emitter, event, listener);\n\t\tthis.capture_ = opt_capture;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tremoveListener() {\n\t\tthis.emitter_.removeEventListener(this.event_, this.listener_, this.capture_);\n\t}\n}\n\nexport default DomEventHandle;\n","'use strict';\n\nimport { isDef, isDocument, isDocumentFragment, isElement, isObject, isString, object } 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 * 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 * 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 * 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 (child instanceof NodeList) {\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 * @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=} opt_default 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(element, eventName, selectorOrTarget, callback, opt_default) {\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 (opt_default) {\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 * @private\n */\nfunction isAbleToInteractWith_(node, eventName, opt_eventObj) {\n\tif (opt_eventObj && eventName === 'click' && opt_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 = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'FIELDSET'];\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 * 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 element.classList.contains(className);\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 (` ${element.className} `).indexOf(` ${className} `) >= 0;\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 * 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 = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.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 nodes = document.querySelectorAll(selector, element.parentNode);\n\tfor (let i = 0; i < nodes.length; ++i) {\n\t\tif (nodes[i] === element) {\n\t\t\treturn true;\n\t\t}\n\t}\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 */\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} opt_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, opt_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, opt_capture);\n\treturn new DomEventHandle(element, eventName, callback, opt_capture);\n}\n\n/**\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);\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 * 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 * 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 * @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.insertBefore(element2, element1);\n\t\telement1.parentNode.removeChild(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} defaultFns 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_(container, currElement, event, defaultFns);\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 (isElement(selectorOrElement) || isDocument(selectorOrElement) || isDocumentFragment(selectorOrElement)) {\n\t\treturn selectorOrElement;\n\t} else if (isString(selectorOrElement)) {\n\t\tif (selectorOrElement[0] === '#' && selectorOrElement.indexOf(' ') === -1) {\n\t\t\treturn document.getElementById(selectorOrElement.substr(1));\n\t\t} else {\n\t\t\treturn document.querySelector(selectorOrElement);\n\t\t}\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 * 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(classIndex + className.length);\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=} opt_eventObj An object with data that should be on the\n * triggered event's payload.\n */\nexport function triggerEvent(element, eventName, opt_eventObj) {\n\tif (isAbleToInteractWith_(element, eventName, opt_eventObj)) {\n\t\tconst eventObj = document.createEvent('HTMLEvents');\n\t\teventObj.initEvent(eventName, true, true);\n\t\tobject.mixin(eventObj, opt_eventObj);\n\t\telement.dispatchEvent(eventObj);\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(this.originEmitter_, eventName, selector, listener);\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 */\n\tisSupportedDomEvent_(event) {\n\t\tif (!this.originEmitter_ || !this.originEmitter_.addEventListener) {\n\t\t\treturn true;\n\t\t}\n\t\treturn (this.isDelegateEvent_(event) && event.indexOf(':', 9) !== -1) ||\n\t\t\tsupportsEvent(this.originEmitter_, event);\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 super.shouldProxyEvent_(event) && this.isSupportedDomEvent_(event);\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(type, 0, 1, type.substring(0, 1).toUpperCase());\n\t\tconst suffixes = [`${typeTitleCase}End`, `${typeTitleCase}End`, `${typeTitleCase}End`, `${type}end`];\n\t\tfor (let i = 0; i < prefixes.length; i++) {\n\t\t\tif (features.animationElement_.style[prefixes[i] + typeTitleCase] !== undefined) {\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 IE9) 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_ = document.createElement('div');\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()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic run(text, opt_appendFn) {\n\t\tconst script = document.createElement('script');\n\t\tscript.text = text;\n\t\tif (opt_appendFn) {\n\t\t\topt_appendFn(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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic runFile(src, opt_callback, opt_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\topt_callback && opt_callback();\n\t\t};\n\t\tonce(script, 'load', callback);\n\t\tonce(script, 'error', callback);\n\n\t\tif (opt_appendFn) {\n\t\t\topt_appendFn(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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} script\n\t */\n\tstatic runScript(script, opt_callback, opt_appendFn) {\n\t\tconst callback = function() {\n\t\t\topt_callback && opt_callback();\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, opt_callback, opt_appendFn);\n\t\t} else {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn globalEval.run(script.text, opt_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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runScriptsInElement(element, opt_callback, opt_appendFn) {\n\t\tconst scripts = element.querySelectorAll('script');\n\t\tif (scripts.length) {\n\t\t\tglobalEval.runScriptsInOrder(scripts, 0, opt_callback, opt_appendFn);\n\t\t} else if (opt_callback) {\n\t\t\tasync.nextTick(opt_callback);\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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runScriptsInOrder(scripts, index, opt_callback, opt_appendFn) {\n\t\tglobalEval.runScript(scripts.item(index), function() {\n\t\t\tif (index < scripts.length - 1) {\n\t\t\t\tglobalEval.runScriptsInOrder(scripts, index + 1, opt_callback, opt_appendFn);\n\t\t\t} else if (opt_callback) {\n\t\t\t\tasync.nextTick(opt_callback);\n\t\t\t}\n\t\t}, opt_appendFn);\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()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic run(text, opt_appendFn) {\n\t\tconst style = document.createElement('style');\n\t\tstyle.innerHTML = text;\n\t\tif (opt_appendFn) {\n\t\t\topt_appendFn(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()=} opt_callback Optional function to be called\n\t * when the styles has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic runFile(href, opt_callback, opt_appendFn) {\n\t\tconst link = document.createElement('link');\n\t\tlink.rel = 'stylesheet';\n\t\tlink.href = href;\n\t\tglobalEvalStyles.runStyle(link, opt_callback, opt_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()=} opt_callback Optional function to be called\n\t * when the script has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t * @return {Element} style\n\t */\n\tstatic runStyle(style, opt_callback, opt_appendFn) {\n\t\tconst callback = function() {\n\t\t\topt_callback && opt_callback();\n\t\t};\n\t\tif (style.rel && style.rel !== 'stylesheet') {\n\t\t\tasync.nextTick(callback);\n\t\t\treturn;\n\t\t}\n\n\t\tif (style.tagName === 'STYLE') {\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 (opt_appendFn) {\n\t\t\topt_appendFn(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()=} opt_callback Optional function to be called when the\n\t * style has been run.\n\t * @param {function()=} opt_appendFn Optional function to append the node\n\t * into document.\n\t */\n\tstatic runStylesInElement(element, opt_callback, opt_appendFn) {\n\t\tconst styles = element.querySelectorAll('style,link');\n\t\tif (styles.length === 0 && opt_callback) {\n\t\t\tasync.nextTick(opt_callback);\n\t\t\treturn;\n\t\t}\n\n\t\tlet loadCount = 0;\n\t\tconst callback = function() {\n\t\t\tif (opt_callback && ++loadCount === styles.length) {\n\t\t\t\tasync.nextTick(opt_callback);\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, opt_appendFn);\n\t\t}\n\t}\n}\n\nexport default globalEvalStyles;\n","'use strict';\n\nimport { registerCustomEvent, contains } from './dom';\nimport features from './features';\n\nconst mouseEventMap = {\n\tmouseenter: 'mouseover',\n\tmouseleave: 'mouseout',\n\tpointerenter: 'pointerover',\n\tpointerleave: 'pointerout'\n};\nObject.keys(mouseEventMap).forEach(function(eventName) {\n\tregisterCustomEvent(eventName, {\n\t\tdelegate: true,\n\t\thandler: function(callback, event) {\n\t\t\tconst related = event.relatedTarget;\n\t\t\tconst target = event.delegateTarget;\n\t\t\tif (!related || (related !== target && !contains(target, related))) {\n\t\t\t\tevent.customType = eventName;\n\t\t\t\treturn callback(event);\n\t\t\t}\n\t\t},\n\t\toriginalEvent: mouseEventMap[eventName]\n\t});\n});\n\nconst animationEventMap = {\n\tanimation: 'animationend',\n\ttransition: 'transitionend'\n};\nObject.keys(animationEventMap).forEach(function(eventType) {\n\tconst eventName = animationEventMap[eventType];\n\tregisterCustomEvent(eventName, {\n\t\tevent: true,\n\t\tdelegate: true,\n\t\thandler: function(callback, event) {\n\t\t\tevent.customType = eventName;\n\t\t\treturn callback(event);\n\t\t},\n\t\toriginalEvent: features.checkAnimationEventName()[eventType]\n\t});\n});\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 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 * 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=} If returns true, the current screen is locked and the\n\t * 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 * 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 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 } 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\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 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 * 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.getHostname())) {\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 {\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\tif (this.activeScreen && this.activeScreen.beforeDeactivate()) {\n\t\t\tthis.pendingNavigate = CancellablePromise.reject(new CancellablePromise.CancellationError('Cancelled by active screen'));\n\t\t\treturn this.pendingNavigate;\n\t\t}\n\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 nextScreen.load(path)\n\t\t\t.then(() => {\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}\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 + ')');\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 hostname is an offsite link.\n\t * @param {!string} hostname Link hostname to compare with\n\t * <code>globals.window.location.hostname</code>.\n\t * @return {boolean}\n\t * @protected\n\t */\n\tisLinkSameOrigin_(hostname) {\n\t\treturn hostname === globals.window.location.hostname;\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 * 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\tglobals.capturedFormElement = event.capturedFormElement;\n\t\tglobals.capturedFormButtonElement = event.capturedFormButtonElement;\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) {\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 * 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\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) {\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.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) {\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 <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\tthis.pendingNavigate = null;\n\t\t}\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\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\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\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\tvar navigator = UA.globals.window.navigator;\n\t\tif (navigator) {\n\t\t\tvar 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\tvar navigator = UA.globals.window.navigator;\n\t\tif (navigator) {\n\t\t\tvar 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 * @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 = (UA.matchUserAgent('Chrome') || UA.matchUserAgent('CriOS')) && !UA.isOpera && !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 = UA.matchUserAgent('Safari') && !(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 */\nUA.globals = {\n\twindow: window\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\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\tbody = new FormData(globals.capturedFormElement);\n\t\t\tthis.maybeAppendSubmitButtonValue_(body);\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.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\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\t * @protected\n\t */\n\tmaybeAppendSubmitButtonValue_(body) {\n\t\tconst button = globals.capturedFormButtonElement;\n\t\tif (button && button.name) {\n\t\t\tbody.append(button.name, button.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 * 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, exitDocument, 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 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\tnode.innerHTML = content;\n\t\tvar placeholder = node.querySelector('senna');\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\tthis.pendingStyles.forEach((style) => exitDocument(style));\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 * 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\ttemporariesInDoc.forEach((resource) => exitDocument(resource));\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(document.documentElement);\n\t\t\tutils.copyNodeAttributes(this.virtualDocument, document.documentElement);\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.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 * 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\tvar 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\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 selectors for tracking resources.\n * @type {object}\n * @protected\n * @static\n */\nHtmlScreen.selectors = {\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]',\n\tstylesPermanent: 'style[data-senna-track=\"permanent\"],link[data-senna-track=\"permanent\"]',\n\tstylesTemporary: 'style[data-senna-track=\"temporary\"],link[data-senna-track=\"temporary\"]'\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 current senna version\n */\nexport default '<%= version %>';"],"names":["globals","window","document","compatibilityModeData_","uniqueIdCounter_","UID_PROPERTY","Math","random","abstractMethod","Error","disableCompatibilityMode","undefined","enableCompatibilityMode","opt_data","getCompatibilityModeData","__METAL_COMPATIBILITY__","getFirstTruthy_","a","b","getFunctionName","fn","name","str","toString","substring","indexOf","getStaticProperty","ctor","propertyName","opt_mergeFn","mergedName","hasOwnProperty","merged","__proto__","isPrototypeOf","Function","mergeFn","getUid","opt_object","opt_noInheritance","id","identityFunction","opt_returnValue","isBoolean","val","isDef","isDefAndNotNull","isNull","isDocument","nodeType","isDocumentFragment","isElement","isFunction","isNumber","isWindow","isObject","type","isPromise","then","isString","String","isServerSide","process","env","NODE_ENV","browser","nullFunction","array","arr1","arr2","length","i","arr","opt_output","output","Array","isArray","flatten","push","obj","rv","removeAt","prototype","splice","call","start","opt_end","sliced","end","async","throwException","exception","nextTick","run","callback","opt_context","workQueueScheduled_","processWorkQueue","workQueue_","WorkItem_","workItems","workItem","scope","e","cb","bind","wrapCallback_","setImmediate","setImmediate_","getSetImmediateEmulator_","Channel","MessageChannel","postMessage","addEventListener","iframe","createElement","style","display","src","documentElement","appendChild","win","contentWindow","doc","open","write","close","message","origin","location","protocol","host","onmessage","data","port1","port2","channel","head","tail","next","script","onreadystatechange","parentNode","removeChild","Disposable","disposed_","disposeInternal","object","target","key","source","arguments","opt_obj","parts","split","reduce","part","mappedObj","keys","Object","obj1","obj2","keys1","keys2","string","str1","str2","test1","toLowerCase","test2","replace","x","floor","abs","Date","now","hash","len","charCodeAt","value","parseFromAnchor","opt_uri","link","href","test","TypeError","hostname","password","pathname","port","search","username","parse","URL","url","create","MultiMap","values","size","map","names","JSON","stringify","set","TreeNode","value_","parent_","children_","child","setParent","node","current","getParent","ancestors","index","getChildren","EMPTY_ARRAY","depth","root","getChildCount","remove","parent","opt_preorderFn","opt_postorderFn","forEach","traverse","assertChildHasNoParent","parseFn_","Uri","maybeAddProtocolAndHostname_","multimap","getAll","addParameterValue","ensureQueryInitialized_","query","add","param","urlDecode","getHostname","getPort","HOSTNAME_PLACEHOLDER","getHost","getProtocol","get","querystring","getParameterNames","getParameterValues","encodeURIComponent","slice","contains","setParameterValue","RANDOM_PARAM","getRandomString","DEFAULT_PROTOCOL","charAt","removeParameter","getPathname","getSearch","getHash","parseFn","basePath","paths","path","concat","join","decodeURIComponent","isSecure","utils","attributes","attribute","setAttribute","getCurrentBrowserPathWithoutHash","offsetLeft","offsetTop","offsetParent","uri","currentBrowserPath","getUrlPathWithoutHash","getUrlPath","history","pushState","err","error","removeAttribute","substr","METAL_DATA","domData","element","opt_name","opt_initialVal","EventHandle","emitter","event","listener","emitter_","event_","listener_","removeListener","isDisposed","singleArray_","EventEmitter","events_","listenerHandlers_","shouldUseFacade_","holder","handler","opt_default","validateListener_","events","toEventsArray_","addSingleListener_","opt_origin","runListenerHandlers_","addHandler_","getShouldUseFacade","facade","preventedDefault","listeners","getRawListeners_","args","runListeners_","buildFacade_","directListeners","toArray","amount","many_","self","handlerInternal","apply","listenerObj","removeMatchingListenerObjs_","addListener","many","opt_events","listenerObjs","finalListeners","matchesListener_","off","handlers","defaultListeners","default","j","shouldUseFacade","EventEmitterProxy","originEmitter","targetEmitter","opt_blacklist","opt_whitelist","blacklist_","originEmitter_","pendingEvents_","proxiedEvents_","targetEmitter_","whitelist_","startProxy_","on","removeListeners_","emit","shouldProxyEvent_","tryToAddListener_","proxyEvent","onListener","addListener_","emitOnTarget_","EventHandler","eventHandles_","DomDelegatedEventHandle","opt_selector","selector_","delegating","selector","selectors","DomEventHandle","opt_capture","capture_","removeEventListener","elementsByTag_","supportCache_","customEvents","LAST_CONTAINER","USE_CAPTURE","addClasses","elements","classes","addClassesWithNative_","className","classList","addClassesWithoutNative_","elementClassName","classesToAppend","addElementListener_","eventName","addSelectorListener_","delegatingData","addToArr_","attachDelegateEvent_","handleDelegateEvent_","closest","match","append","buildFragment","NodeList","childArr","htmlString","tempDiv","innerHTML","firstChild","fragment","createDocumentFragment","element1","element2","delegate","selectorOrTarget","customConfig","originalEvent","defaultListener_","isAbleToInteractWith_","opt_eventObj","button","matchesSelector","tagName","disabled","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","defaultPrevented","defaultFns","currElement","limit","triggerElementListeners_","triggerSelectorListeners_","lastContainer","triggerListeners_","DomEventEmitterProxy","isDelegateEvent_","babelHelpers.get","isSupportedDomEvent_","features","animationEventName_","checkAnimationEventName_","prefixes","typeTitleCase","replaceInterval","toUpperCase","suffixes","animationElement_","attrOrderChange_","originalContent","globalEval","text","opt_appendFn","opt_callback","runFile","scripts","runScriptsInOrder","runScript","item","globalEvalStyles","rel","runStyle","styles","loadCount","mouseEventMap","related","relatedTarget","customType","animationEventMap","eventType","checkAnimationEventName","Thenable","IMPLEMENTED_BY_PROP","addImplementation","$goog_Thenable","isImplementedBy","partial","newArgs","CancellablePromise","resolver","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","capture","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_","title","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","App","activeScreen","activePath","allowPreventNavigate","browserPathBeforeNavigate","captureScrollPositionFromScrollEvent","defaultTitle","formSelector","ignoreQueryStringFromRoutePath","linkSelector","loadingCssClass","nativeScrollRestorationSupported","isNavigationPending","pendingNavigate","popstateScrollLeft","popstateScrollTop","redirectPath","routes","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","beforeDeactivate","stopPendingNavigate_","nextScreen","createScreenInstance","load","deactivate","prepareNavigateHistory_","prepareNavigateSurfaces_","extractParams","evaluateStyles","flip","evaluateScripts","maybeUpdateScrollPositionState_","syncScrollPositionSyncThenAsync_","finalizeNavigate_","handleNavigateError_","getRoutePath","activate","isCacheable","capturedFormElement","capturedFormButtonElement","matchesPath","getIgnoreQueryStringFromRoutePath","getUrlPathWithoutHashAndSearch","winner","switchScrollPositionRace","scrollTo","scrollLeft","scrollTop","nativeScrollRestoration_","scrollRestoration","canNavigate","navigateFailed","preventDefault","onbeforeunload","_onbeforeunload","_overloaded","anchorElement","getNodeOffset","saveHistoryCurrentPageScrollPosition_","opt_event","isHtml5HistorySupported","form","replaceHistory","func","altKey","ctrlKey","metaKey","shiftKey","maybeNavigate_","method","buttonSelector","activeElement","querySelector","action","maybeRepositionScrollToHashedAnchor","reloadPage","senna","lockHistoryScrollPosition_","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","setHostname","setProtocol","setPort","makeUnique","getRequest","requestPath","responseUrl","maybeExtractResponseUrlFromRequest","removeUnique","getCache","header","FormData","maybeAppendSubmitButtonValue_","POST","formatLoadPath","setRequest","xhr","assertValidResponseStatusCode","addCache","responseText","requestError","requestPrematureTermination","responseURL","getResponseHeader","X_REQUEST_URL_HEADER","HtmlScreen","titleSelector","releaseVirtualDocument","pendingStyles","virtualDocument","copyNodeAttributesFromContent_","newStyle","isTemporaryStyle","stylesTemporary","styleInDoc","insertBefore","nextSibling","bodySurface","placeholder","clearNodeAttributes","copyNodeAttributes","disposePendingStyles","evaluateTrackedScripts","evaluateTrackedResources_","scriptsTemporary","scriptsPermanent","evaluateTrackedStyles","runStylesInElement","stylesPermanent","appendStyleIntoDocument_","evaluatorFn","selectorTemporary","selectorPermanent","opt_appendResourceFn","tracked","virtualQuerySelectorAll_","temporariesInDoc","querySelectorAll_","permanentsInDoc","resource","resourceKey","getResourceKey_","permanentResourcesInDoc","frag","allocateVirtualDocumentForContent","resolveTitleFromVirtualDocument","assertSameBodyIdInVirtualDocument","makeTemporaryStylesHrefsUnique_","replaceStyleAndMakeUnique_","replaceChild","setTitle","textContent","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"],"mappings":"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","preExistingComment":"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9zcmMvZ2xvYmFscy9nbG9iYWxzLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvY29yZU5hbWVkLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvY29yZS5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwvc3JjL2FycmF5L2FycmF5LmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvYXN5bmMvYXN5bmMuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9kaXNwb3NhYmxlL0Rpc3Bvc2FibGUuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsL3NyYy9vYmplY3Qvb2JqZWN0LmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC9zcmMvc3RyaW5nL3N0cmluZy5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtdXJpL3NyYy9wYXJzZUZyb21BbmNob3IuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLXVyaS9zcmMvcGFyc2UuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLXN0cnVjdHMvc3JjL011bHRpTWFwLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1zdHJ1Y3RzL3NyYy9UcmVlTm9kZS5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtdXJpL3NyYy9VcmkuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvc3JjL3V0aWxzL3V0aWxzLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL3NyYy9hcHAvZGF0YUF0dHJpYnV0ZXMuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZG9tRGF0YS5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZXZlbnRzL3NyYy9FdmVudEhhbmRsZS5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZXZlbnRzL3NyYy9FdmVudEVtaXR0ZXIuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWV2ZW50cy9zcmMvRXZlbnRFbWl0dGVyUHJveHkuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWV2ZW50cy9zcmMvRXZlbnRIYW5kbGVyLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL0RvbURlbGVnYXRlZEV2ZW50SGFuZGxlLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL0RvbUV2ZW50SGFuZGxlLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL2RvbU5hbWVkLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL2RvbS5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9Eb21FdmVudEVtaXR0ZXJQcm94eS5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9mZWF0dXJlcy5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtZG9tL3NyYy9nbG9iYWxFdmFsLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1kb20vc3JjL2dsb2JhbEV2YWxTdHlsZXMuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRvbS9zcmMvZXZlbnRzLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL25vZGVfbW9kdWxlcy9tZXRhbC1wcm9taXNlL3NyYy9wcm9taXNlL1Byb21pc2UuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWRlYm91bmNlL3NyYy9kZWJvdW5jZS5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9ub2RlX21vZHVsZXMvbWV0YWwtcGF0aC1wYXJzZXIvc3JjL3BhdGhQYXJzZXIuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvc3JjL3JvdXRlL1JvdXRlLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL3NyYy9jYWNoZWFibGUvQ2FjaGVhYmxlLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL3NyYy9zY3JlZW4vU2NyZWVuLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL3NyYy9zdXJmYWNlL1N1cmZhY2UuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvc3JjL2FwcC9BcHAuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLWFqYXgvc3JjL0FqYXguanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvc3JjL2Vycm9ycy9lcnJvcnMuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvbm9kZV9tb2R1bGVzL21ldGFsLXVzZXJhZ2VudC9zcmMvVUEuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvc3JjL3NjcmVlbi9SZXF1ZXN0U2NyZWVuLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL3NyYy9zY3JlZW4vSHRtbFNjcmVlbi5qcyIsIi9Vc2Vycy9MaWZlcmF5L3dvcmtzcGFjZS9wci9zZW5uYS5qcy9zcmMvYXBwL0FwcERhdGFBdHRyaWJ1dGVIYW5kbGVyLmpzIiwiL1VzZXJzL0xpZmVyYXkvd29ya3NwYWNlL3ByL3Nlbm5hLmpzL3NyYy9hcHAvZGF0YUF0dHJpYnV0ZUhhbmRsZXIuanMiLCIvVXNlcnMvTGlmZXJheS93b3Jrc3BhY2UvcHIvc2VubmEuanMvc3JjL3ZlcnNpb24uanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIGdsb2JhbHMgPSBnbG9iYWxzIHx8IHt9O1xuXG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0Z2xvYmFscy53aW5kb3cgPSB3aW5kb3c7XG59XG5cbmlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG5cdGdsb2JhbHMuZG9jdW1lbnQgPSBkb2N1bWVudDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZ2xvYmFscztcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBBIGNvbGxlY3Rpb24gb2YgY29yZSB1dGlsaXR5IGZ1bmN0aW9ucy5cbiAqIEBjb25zdFxuICovXG5cbmxldCBjb21wYXRpYmlsaXR5TW9kZURhdGFfO1xuXG4vKipcbiAqIENvdW50ZXIgZm9yIHVuaXF1ZSBpZC5cbiAqIEB0eXBlIHtOdW1iZXJ9XG4gKiBAcHJpdmF0ZVxuICovXG5sZXQgdW5pcXVlSWRDb3VudGVyXyA9IDE7XG5cbi8qKlxuICogVW5pcXVlIGlkIHByb3BlcnR5IHByZWZpeC5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAcHJvdGVjdGVkXG4gKi9cbmV4cG9ydCBjb25zdCBVSURfUFJPUEVSVFkgPSBgY29yZV8keygoTWF0aC5yYW5kb20oKSAqIDFlOSkgPj4+IDApfWA7XG5cbi8qKlxuICogV2hlbiBkZWZpbmluZyBhIGNsYXNzIEZvbyB3aXRoIGFuIGFic3RyYWN0IG1ldGhvZCBiYXIoKSwgeW91IGNhbiBkbzpcbiAqIEZvby5wcm90b3R5cGUuYmFyID0gYWJzdHJhY3RNZXRob2RcbiAqXG4gKiBOb3cgaWYgYSBzdWJjbGFzcyBvZiBGb28gZmFpbHMgdG8gb3ZlcnJpZGUgYmFyKCksIGFuIGVycm9yIHdpbGwgYmUgdGhyb3duXG4gKiB3aGVuIGJhcigpIGlzIGludm9rZWQuXG4gKlxuICogQHR5cGUgeyFGdW5jdGlvbn1cbiAqIEB0aHJvd3Mge0Vycm9yfSB3aGVuIGludm9rZWQgdG8gaW5kaWNhdGUgdGhlIG1ldGhvZCBzaG91bGQgYmUgb3ZlcnJpZGRlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFic3RyYWN0TWV0aG9kKCkge1xuXHR0aHJvdyBFcnJvcignVW5pbXBsZW1lbnRlZCBhYnN0cmFjdCBtZXRob2QnKTtcbn1cblxuLyoqXG4gKiBEaXNhYmxlcyBNZXRhbC5qcydzIGNvbXBhdGliaWxpdHkgbW9kZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRpc2FibGVDb21wYXRpYmlsaXR5TW9kZSgpIHtcblx0Y29tcGF0aWJpbGl0eU1vZGVEYXRhXyA9IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBFbmFibGVzIE1ldGFsLmpzJ3MgY29tcGF0aWJpbGl0eSBtb2RlIHdpdGggdGhlIGZvbGxvd2luZyBmZWF0dXJlcyBmcm9tIHJjXG4gKiBhbmQgMS54IHZlcnNpb25zOlxuICogICAgIC0gVXNpbmcgXCJrZXlcIiB0byByZWZlcmVuY2UgY29tcG9uZW50IGluc3RhbmNlcy4gSW4gdGhlIGN1cnJlbnQgdmVyc2lvblxuICogICAgICAgdGhpcyBzaG91bGQgYmUgZG9uZSB2aWEgXCJyZWZcIiBpbnN0ZWFkLiBUaGlzIGFsbG93cyBvbGQgY29kZSBzdGlsbFxuICogICAgICAgdXNpbmcgXCJrZXlcIiB0byBrZWVwIHdvcmtpbmcgbGlrZSBiZWZvcmUuIE5PVEU6IHRoaXMgbWF5IGNhdXNlXG4gKiAgICAgICBwcm9ibGVtcywgc2luY2UgXCJrZXlcIiBpcyBtZWFudCB0byBiZSB1c2VkIGRpZmZlcmVudGx5LiBPbmx5IHVzZSB0aGlzXG4gKiAgICAgICBpZiBpdCdzIG5vdCBwb3NzaWJsZSB0byB1cGdyYWRlIHRoZSBjb2RlIHRvIHVzZSBcInJlZlwiIGluc3RlYWQuXG4gKiBAcGFyYW0ge09iamVjdD19IG9wdF9kYXRhIE9wdGlvbmFsIG9iamVjdCB3aXRoIGRhdGEgdG8gc3BlY2lmeSBtb3JlXG4gKiAgICAgZGV0YWlscywgc3VjaCBhczpcbiAqICAgICAgICAgLSByZW5kZXJlcnMge0FycmF5fSB0aGUgdGVtcGxhdGUgcmVuZGVyZXJzIHRoYXQgc2hvdWxkIGJlIGluXG4gKiAgICAgICAgICAgY29tcGF0aWJpbGl0eSBtb2RlLCBlaXRoZXIgdGhlaXIgY29uc3RydWN0b3JzIG9yIHN0cmluZ3NcbiAqICAgICAgICAgICByZXByZXNlbnRpbmcgdGhlbSAoZS5nLiAnc295JyBvciAnanN4JykuIEJ5IGRlZmF1bHQsIGFsbCB0aGUgb25lc1xuICogICAgICAgICAgIHRoYXQgZXh0ZW5kIGZyb20gSW5jcmVtZW50YWxEb21SZW5kZXJlci5cbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmFibGVDb21wYXRpYmlsaXR5TW9kZShvcHRfZGF0YSA9IHt9KSB7XG5cdGNvbXBhdGliaWxpdHlNb2RlRGF0YV8gPSBvcHRfZGF0YTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBkYXRhIHVzZWQgZm9yIGNvbXBhdGliaWxpdHkgbW9kZSwgb3Igbm90aGluZyBpZiBpdCBoYXNuJ3QgYmVlblxuICogZW5hYmxlZC5cbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbXBhdGliaWxpdHlNb2RlRGF0YSgpIHtcblx0Ly8gQ29tcGF0aWJpbGl0eSBtb2RlIGNhbiBiZSBzZXQgdmlhIHRoZSBfX01FVEFMX0NPTVBBVElCSUxJVFlfXyBnbG9iYWwgdmFyLlxuXHRpZiAoY29tcGF0aWJpbGl0eU1vZGVEYXRhXyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0aWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5fX01FVEFMX0NPTVBBVElCSUxJVFlfXykge1xuXHRcdFx0ZW5hYmxlQ29tcGF0aWJpbGl0eU1vZGUod2luZG93Ll9fTUVUQUxfQ09NUEFUSUJJTElUWV9fKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGNvbXBhdGliaWxpdHlNb2RlRGF0YV87XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZmlyc3QgYXJndW1lbnQgaWYgaXQncyB0cnV0aHksIG9yIHRoZSBzZWNvbmQgb3RoZXJ3aXNlLlxuICogQHBhcmFtIHsqfSBhXG4gKiBAcGFyYW0geyp9IGJcbiAqIEByZXR1cm4geyp9XG4gKiBAcHJvdGVjdGVkXG4gKi9cbmZ1bmN0aW9uIGdldEZpcnN0VHJ1dGh5XyhhLCBiKSB7XG5cdHJldHVybiBhIHx8IGI7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgbmFtZSBvZiB0aGUgZ2l2ZW4gZnVuY3Rpb24uIElmIHRoZSBjdXJyZW50IGJyb3dzZXIgZG9lc24ndFxuICogc3VwcG9ydCB0aGUgYG5hbWVgIHByb3BlcnR5LCB0aGlzIHdpbGwgY2FsY3VsYXRlIGl0IGZyb20gdGhlIGZ1bmN0aW9uJ3NcbiAqIGNvbnRlbnQgc3RyaW5nLlxuICogQHBhcmFtIHshZnVuY3Rpb24oKX0gZm5cbiAqIEByZXR1cm4ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEZ1bmN0aW9uTmFtZShmbikge1xuXHRpZiAoIWZuLm5hbWUpIHtcblx0XHRjb25zdCBzdHIgPSBmbi50b1N0cmluZygpO1xuXHRcdGZuLm5hbWUgPSBzdHIuc3Vic3RyaW5nKDksIHN0ci5pbmRleE9mKCcoJykpO1xuXHR9XG5cdHJldHVybiBmbi5uYW1lO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHZhbHVlIG9mIGEgc3RhdGljIHByb3BlcnR5IGluIHRoZSBnaXZlbiBjbGFzcy4gVGhlIHZhbHVlIHdpbGwgYmVcbiAqIGluaGVyaXRlZCBmcm9tIGFuY2VzdG9ycyBhcyBleHBlY3RlZCwgdW5sZXNzIGEgY3VzdG9tIG1lcmdlIGZ1bmN0aW9uIGlzIGdpdmVuLFxuICogd2hpY2ggY2FuIGNoYW5nZSBob3cgdGhlIHN1cGVyIGNsYXNzZXMnIHZhbHVlIGZvciB0aGF0IHByb3BlcnR5IHdpbGwgYmUgbWVyZ2VkXG4gKiB0b2dldGhlci5cbiAqIFRoZSBmaW5hbCBtZXJnZWQgdmFsdWUgd2lsbCBiZSBzdG9yZWQgaW4gYW5vdGhlciBwcm9wZXJ0eSwgc28gdGhhdCBpdCB3b24ndFxuICogYmUgcmVjYWxjdWxhdGVkIGV2ZW4gaWYgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgbXVsdGlwbGUgdGltZXMuXG4gKiBAcGFyYW0geyFmdW5jdGlvbigpfSBjdG9yIENsYXNzIGNvbnN0cnVjdG9yLlxuICogQHBhcmFtIHtzdHJpbmd9IHByb3BlcnR5TmFtZSBQcm9wZXJ0eSBuYW1lIHRvIGJlIG1lcmdlZC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oKiwgKik6Kj19IG9wdF9tZXJnZUZuIEZ1bmN0aW9uIHRoYXQgcmVjZWl2ZXMgdGhlIG1lcmdlZFxuICogICAgIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSBzbyBmYXIgYW5kIHRoZSBuZXh0IHZhbHVlIHRvIGJlIG1lcmdlZCB0byBpdC5cbiAqICAgICBTaG91bGQgcmV0dXJuIHRoZXNlIHR3byBtZXJnZWQgdG9nZXRoZXIuIElmIG5vdCBwYXNzZWQgdGhlIGZpbmFsIHByb3BlcnR5XG4gKiAgICAgd2lsbCBiZSB0aGUgZmlyc3QgdHJ1dGh5IHZhbHVlIGFtb25nIGFuY2VzdG9ycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0YXRpY1Byb3BlcnR5KGN0b3IsIHByb3BlcnR5TmFtZSwgb3B0X21lcmdlRm4pIHtcblx0Y29uc3QgbWVyZ2VkTmFtZSA9IHByb3BlcnR5TmFtZSArICdfTUVSR0VEJztcblx0aWYgKCFjdG9yLmhhc093blByb3BlcnR5KG1lcmdlZE5hbWUpKSB7XG5cdFx0bGV0IG1lcmdlZCA9IGN0b3IuaGFzT3duUHJvcGVydHkocHJvcGVydHlOYW1lKSA/IGN0b3JbcHJvcGVydHlOYW1lXSA6IG51bGw7XG5cdFx0aWYgKGN0b3IuX19wcm90b19fICYmICFjdG9yLl9fcHJvdG9fXy5pc1Byb3RvdHlwZU9mKEZ1bmN0aW9uKSkge1xuXHRcdFx0Y29uc3QgbWVyZ2VGbiA9IG9wdF9tZXJnZUZuIHx8IGdldEZpcnN0VHJ1dGh5Xztcblx0XHRcdG1lcmdlZCA9IG1lcmdlRm4oXG5cdFx0XHRcdG1lcmdlZCxcblx0XHRcdFx0Z2V0U3RhdGljUHJvcGVydHkoY3Rvci5fX3Byb3RvX18sIHByb3BlcnR5TmFtZSwgbWVyZ2VGbilcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGN0b3JbbWVyZ2VkTmFtZV0gPSBtZXJnZWQ7XG5cdH1cblx0cmV0dXJuIGN0b3JbbWVyZ2VkTmFtZV07XG59XG5cbi8qKlxuICogR2V0cyBhbiB1bmlxdWUgaWQuIElmIGBvcHRfb2JqZWN0YCBhcmd1bWVudCBpcyBwYXNzZWQsIHRoZSBvYmplY3QgaXNcbiAqIG11dGF0ZWQgd2l0aCBhbiB1bmlxdWUgaWQuIENvbnNlY3V0aXZlIGNhbGxzIHdpdGggdGhlIHNhbWUgb2JqZWN0XG4gKiByZWZlcmVuY2Ugd29uJ3QgbXV0YXRlIHRoZSBvYmplY3QgYWdhaW4sIGluc3RlYWQgdGhlIGN1cnJlbnQgb2JqZWN0IHVpZFxuICogcmV0dXJucy4gU2VlIHtAbGluayBVSURfUFJPUEVSVFl9LlxuICogQHBhcmFtIHtPYmplY3Q9fSBvcHRfb2JqZWN0IE9wdGlvbmFsIG9iamVjdCB0byBiZSBtdXRhdGVkIHdpdGggdGhlIHVpZC4gSWZcbiAqICAgICBub3Qgc3BlY2lmaWVkIHRoaXMgbWV0aG9kIG9ubHkgcmV0dXJucyB0aGUgdWlkLlxuICogQHBhcmFtIHtib29sZWFuPX0gb3B0X25vSW5oZXJpdGFuY2UgT3B0aW9uYWwgZmxhZyBpbmRpY2F0aW5nIGlmIHRoaXNcbiAqICAgICBvYmplY3QncyB1aWQgcHJvcGVydHkgY2FuIGJlIGluaGVyaXRlZCBmcm9tIHBhcmVudHMgb3Igbm90LlxuICogQHRocm93cyB7RXJyb3J9IHdoZW4gaW52b2tlZCB0byBpbmRpY2F0ZSB0aGUgbWV0aG9kIHNob3VsZCBiZSBvdmVycmlkZGVuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VWlkKG9wdF9vYmplY3QsIG9wdF9ub0luaGVyaXRhbmNlKSB7XG5cdGlmIChvcHRfb2JqZWN0KSB7XG5cdFx0bGV0IGlkID0gb3B0X29iamVjdFtVSURfUFJPUEVSVFldO1xuXHRcdGlmIChvcHRfbm9Jbmhlcml0YW5jZSAmJiAhb3B0X29iamVjdC5oYXNPd25Qcm9wZXJ0eShVSURfUFJPUEVSVFkpKSB7XG5cdFx0XHRpZCA9IG51bGw7XG5cdFx0fVxuXHRcdHJldHVybiBpZCB8fCAob3B0X29iamVjdFtVSURfUFJPUEVSVFldID0gdW5pcXVlSWRDb3VudGVyXysrKTtcblx0fVxuXHRyZXR1cm4gdW5pcXVlSWRDb3VudGVyXysrO1xufVxuXG4vKipcbiAqIFRoZSBpZGVudGl0eSBmdW5jdGlvbi4gUmV0dXJucyBpdHMgZmlyc3QgYXJndW1lbnQuXG4gKiBAcGFyYW0geyo9fSBvcHRfcmV0dXJuVmFsdWUgVGhlIHNpbmdsZSB2YWx1ZSB0aGF0IHdpbGwgYmUgcmV0dXJuZWQuXG4gKiBAcmV0dXJuIHs/fSBUaGUgZmlyc3QgYXJndW1lbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpZGVudGl0eUZ1bmN0aW9uKG9wdF9yZXR1cm5WYWx1ZSkge1xuXHRyZXR1cm4gb3B0X3JldHVyblZhbHVlO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGEgYm9vbGVhbi5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGJvb2xlYW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Jvb2xlYW4odmFsKSB7XG5cdHJldHVybiB0eXBlb2YgdmFsID09PSAnYm9vbGVhbic7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgbm90IHVuZGVmaW5lZC5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGRlZmluZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RlZih2YWwpIHtcblx0cmV0dXJuIHZhbCAhPT0gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBub3QgdW5kZWZpbmVkIG9yIG51bGwuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGVmQW5kTm90TnVsbCh2YWwpIHtcblx0cmV0dXJuIGlzRGVmKHZhbCkgJiYgIWlzTnVsbCh2YWwpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIGRvY3VtZW50LlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RvY3VtZW50KHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbC5ub2RlVHlwZSA9PT0gOTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBkb2N1bWVudC1mcmFnbWVudC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEb2N1bWVudEZyYWdtZW50KHZhbCkge1xuXHRyZXR1cm4gdmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbC5ub2RlVHlwZSA9PT0gMTE7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHZhbHVlIGlzIGEgZG9tIGVsZW1lbnQuXG4gKiBAcGFyYW0geyp9IHZhbFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRWxlbWVudCh2YWwpIHtcblx0cmV0dXJuIHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB2YWwubm9kZVR5cGUgPT09IDE7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYSBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7P30gdmFsIFZhcmlhYmxlIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHZhcmlhYmxlIGlzIGEgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbCkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgbnVsbC5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNOdWxsKHZhbCkge1xuXHRyZXR1cm4gdmFsID09PSBudWxsO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGEgbnVtYmVyLlxuICogQHBhcmFtIHs/fSB2YWwgVmFyaWFibGUgdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdmFyaWFibGUgaXMgYSBudW1iZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc051bWJlcih2YWwpIHtcblx0cmV0dXJuIHR5cGVvZiB2YWwgPT09ICdudW1iZXInO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIHdpbmRvdy5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNXaW5kb3codmFsKSB7XG5cdHJldHVybiB2YWwgIT09IG51bGwgJiYgdmFsID09PSB2YWwud2luZG93O1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGFuIG9iamVjdC4gVGhpcyBpbmNsdWRlcyBhcnJheXNcbiAqIGFuZCBmdW5jdGlvbnMuXG4gKiBAcGFyYW0gez99IHZhbCBWYXJpYWJsZSB0byB0ZXN0LlxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB2YXJpYWJsZSBpcyBhbiBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc09iamVjdCh2YWwpIHtcblx0Y29uc3QgdHlwZSA9IHR5cGVvZiB2YWw7XG5cdHJldHVybiB0eXBlID09PSAnb2JqZWN0JyAmJiB2YWwgIT09IG51bGwgfHwgdHlwZSA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdmFsdWUgaXMgYSBQcm9taXNlLlxuICogQHBhcmFtIHsqfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1Byb21pc2UodmFsKSB7XG5cdHJldHVybiB2YWwgJiYgdHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIHZhbC50aGVuID09PSAnZnVuY3Rpb24nO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB2YWx1ZSBpcyBhIHN0cmluZy5cbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTdHJpbmcodmFsKSB7XG5cdHJldHVybiB0eXBlb2YgdmFsID09PSAnc3RyaW5nJyB8fCB2YWwgaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbi8qKlxuICogU2V0cyB0byB0cnVlIGlmIHJ1bm5pbmcgaW5zaWRlIE5vZGUuanMgZW52aXJvbm1lbnQgd2l0aCBleHRyYSBjaGVjayBmb3JcbiAqIGBwcm9jZXNzLmJyb3dzZXJgIHRvIHNraXAgS2FybWEgcnVubmVyIGVudmlyb25tZW50LiBLYXJtYSBlbnZpcm9ubWVudCBoYXNcbiAqIGBwcm9jZXNzYCBkZWZpbmVkIGV2ZW4gdGhvdWdoIGl0IHJ1bnMgb24gdGhlIGJyb3dzZXIuXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTZXJ2ZXJTaWRlKCkge1xuXHRyZXR1cm4gdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmXG5cdFx0dHlwZW9mIHByb2Nlc3MuZW52ICE9PSAndW5kZWZpbmVkJyAmJlxuXHRcdHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAndGVzdCcgJiZcblx0XHQhcHJvY2Vzcy5icm93c2VyO1xufVxuXG4vKipcbiAqIE51bGwgZnVuY3Rpb24gdXNlZCBmb3IgZGVmYXVsdCB2YWx1ZXMgb2YgY2FsbGJhY2tzLCBldGMuXG4gKiBAcmV0dXJuIHt2b2lkfSBOb3RoaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbnVsbEZ1bmN0aW9uKCkge1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBUaGlzIGZpbGUgZXhpc3RzIGp1c3QgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LCBtYWtpbmcgc3VyZSB0aGF0IG9sZFxuLy8gZGVmYXVsdCBpbXBvcnRzIGZvciB0aGlzIGZpbGUgc3RpbGwgd29yay4gSXQncyBiZXN0IHRvIHVzZSB0aGUgbmFtZWQgZXhwb3J0c1xuLy8gZm9yIGVhY2ggZnVuY3Rpb24gaW5zdGVhZCB0aG91Z2gsIHNpbmNlIHRoYXQgYWxsb3dzIGJ1bmRsZXJzIGxpa2UgUm9sbHVwIHRvXG4vLyByZWR1Y2UgdGhlIGJ1bmRsZSBzaXplIGJ5IHJlbW92aW5nIHVudXNlZCBjb2RlLlxuaW1wb3J0ICogYXMgY29yZSBmcm9tICcuL2NvcmVOYW1lZCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNvcmU7XG5leHBvcnQgeyBjb3JlIH07XG5leHBvcnQgKiBmcm9tICcuL2NvcmVOYW1lZCc7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmIH0gZnJvbSAnLi4vY29yZSc7XG5cbmNsYXNzIGFycmF5IHtcblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gYXJyYXlzIGhhdmUgdGhlIHNhbWUgY29udGVudC5cblx0ICogQHBhcmFtIHshQXJyYXk8Kj59IGFycjFcblx0ICogQHBhcmFtIHshQXJyYXk8Kj59IGFycjJcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdHN0YXRpYyBlcXVhbChhcnIxLCBhcnIyKSB7XG5cdFx0aWYgKGFycjEgPT09IGFycjIpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRpZiAoYXJyMS5sZW5ndGggIT09IGFycjIubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXJyMS5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGFycjFbaV0gIT09IGFycjJbaV0pIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBmaXJzdCB2YWx1ZSBpbiB0aGUgZ2l2ZW4gYXJyYXkgdGhhdCBpc24ndCB1bmRlZmluZWQuXG5cdCAqIEBwYXJhbSB7IUFycmF5fSBhcnJcblx0ICogQHJldHVybiB7Kn1cblx0ICovXG5cdHN0YXRpYyBmaXJzdERlZmluZWRWYWx1ZShhcnIpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGFycltpXSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHJldHVybiBhcnJbaV07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRyYW5zZm9ybXMgdGhlIGlucHV0IG5lc3RlZCBhcnJheSB0byBiZWNvbWUgZmxhdC5cblx0ICogQHBhcmFtIHtBcnJheS48KnxBcnJheS48Kj4+fSBhcnIgTmVzdGVkIGFycmF5IHRvIGZsYXR0ZW4uXG5cdCAqIEBwYXJhbSB7QXJyYXkuPCo+fSBvcHRfb3V0cHV0IE9wdGlvbmFsIG91dHB1dCBhcnJheS5cblx0ICogQHJldHVybiB7QXJyYXkuPCo+fSBGbGF0IGFycmF5LlxuXHQgKi9cblx0c3RhdGljIGZsYXR0ZW4oYXJyLCBvcHRfb3V0cHV0KSB7XG5cdFx0dmFyIG91dHB1dCA9IG9wdF9vdXRwdXQgfHwgW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChBcnJheS5pc0FycmF5KGFycltpXSkpIHtcblx0XHRcdFx0YXJyYXkuZmxhdHRlbihhcnJbaV0sIG91dHB1dCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvdXRwdXQucHVzaChhcnJbaV0pO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gb3V0cHV0O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgYSBwYXJ0aWN1bGFyIHZhbHVlIGZyb20gYW4gYXJyYXkuXG5cdCAqIEBwYXJhbSB7QXJyYXkuPFQ+fSBhcnIgQXJyYXkgZnJvbSB3aGljaCB0byByZW1vdmUgdmFsdWUuXG5cdCAqIEBwYXJhbSB7VH0gb2JqIE9iamVjdCB0byByZW1vdmUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgYW4gZWxlbWVudCB3YXMgcmVtb3ZlZC5cblx0ICogQHRlbXBsYXRlIFRcblx0ICovXG5cdHN0YXRpYyByZW1vdmUoYXJyLCBvYmopIHtcblx0XHRjb25zdCBpID0gYXJyLmluZGV4T2Yob2JqKTtcblx0XHRsZXQgcnY7XG5cdFx0aWYgKCAocnYgPSBpID49IDApICkge1xuXHRcdFx0YXJyYXkucmVtb3ZlQXQoYXJyLCBpKTtcblx0XHR9XG5cdFx0cmV0dXJuIHJ2O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgZnJvbSBhbiBhcnJheSB0aGUgZWxlbWVudCBhdCBpbmRleCBpXG5cdCAqIEBwYXJhbSB7QXJyYXl9IGFyciBBcnJheSBvciBhcnJheSBsaWtlIG9iamVjdCBmcm9tIHdoaWNoIHRvIHJlbW92ZSB2YWx1ZS5cblx0ICogQHBhcmFtIHtudW1iZXJ9IGkgVGhlIGluZGV4IHRvIHJlbW92ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhbiBlbGVtZW50IHdhcyByZW1vdmVkLlxuXHQgKi9cblx0c3RhdGljIHJlbW92ZUF0KGFyciwgaSkge1xuXHRcdHJldHVybiBBcnJheS5wcm90b3R5cGUuc3BsaWNlLmNhbGwoYXJyLCBpLCAxKS5sZW5ndGggPT09IDE7XG5cdH1cblxuXHQvKipcblx0ICogU2xpY2VzIHRoZSBnaXZlbiBhcnJheSwganVzdCBsaWtlIEFycmF5LnByb3RvdHlwZS5zbGljZSwgYnV0IHRoaXNcblx0ICogaXMgZmFzdGVyIGFuZCB3b3JraW5nIG9uIGFsbCBhcnJheS1saWtlIG9iamVjdHMgKGxpa2UgYXJndW1lbnRzKS5cblx0ICogQHBhcmFtIHshT2JqZWN0fSBhcnIgQXJyYXktbGlrZSBvYmplY3QgdG8gc2xpY2UuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydCBUaGUgaW5kZXggdGhhdCBzaG91bGQgc3RhcnQgdGhlIHNsaWNlLlxuXHQgKiBAcGFyYW0ge251bWJlcj19IG9wdF9lbmQgVGhlIGluZGV4IHdoZXJlIHRoZSBzbGljZSBzaG91bGQgZW5kLCBub3Rcblx0ICogICBpbmNsdWRlZCBpbiB0aGUgZmluYWwgYXJyYXkuIElmIG5vdCBnaXZlbiwgYWxsIGVsZW1lbnRzIGFmdGVyIHRoZVxuXHQgKiAgIHN0YXJ0IGluZGV4IHdpbGwgYmUgaW5jbHVkZWQuXG5cdCAqIEByZXR1cm4geyFBcnJheX1cblx0ICovXG5cdHN0YXRpYyBzbGljZShhcnIsIHN0YXJ0LCBvcHRfZW5kKSB7XG5cdFx0Y29uc3Qgc2xpY2VkID0gW107XG5cdFx0Y29uc3QgZW5kID0gaXNEZWYob3B0X2VuZCkgPyBvcHRfZW5kIDogYXJyLmxlbmd0aDtcblx0XHRmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuXHRcdFx0c2xpY2VkLnB1c2goYXJyW2ldKTtcblx0XHR9XG5cdFx0cmV0dXJuIHNsaWNlZDtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBhcnJheTtcbiIsIi8qIVxuICogUG9seWZpbGwgZnJvbSBHb29nbGUncyBDbG9zdXJlIExpYnJhcnkuXG4gKiBDb3B5cmlnaHQgMjAxMyBUaGUgQ2xvc3VyZSBMaWJyYXJ5IEF1dGhvcnMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5jb25zdCBhc3luYyA9IHt9O1xuXG5cbi8qKlxuICogVGhyb3cgYW4gaXRlbSB3aXRob3V0IGludGVycnVwdGluZyB0aGUgY3VycmVudCBleGVjdXRpb24gY29udGV4dC4gIEZvclxuICogZXhhbXBsZSwgaWYgcHJvY2Vzc2luZyBhIGdyb3VwIG9mIGl0ZW1zIGluIGEgbG9vcCwgc29tZXRpbWVzIGl0IGlzIHVzZWZ1bFxuICogdG8gcmVwb3J0IGFuIGVycm9yIHdoaWxlIHN0aWxsIGFsbG93aW5nIHRoZSByZXN0IG9mIHRoZSBiYXRjaCB0byBiZVxuICogcHJvY2Vzc2VkLlxuICogQHBhcmFtIHsqfSBleGNlcHRpb25cbiAqL1xuYXN5bmMudGhyb3dFeGNlcHRpb24gPSBmdW5jdGlvbihleGNlcHRpb24pIHtcblx0Ly8gRWFjaCB0aHJvdyBuZWVkcyB0byBiZSBpbiBpdHMgb3duIGNvbnRleHQuXG5cdGFzeW5jLm5leHRUaWNrKGZ1bmN0aW9uKCkge1xuXHRcdHRocm93IGV4Y2VwdGlvbjtcblx0fSk7XG59O1xuXG5cbi8qKlxuICogRmlyZXMgdGhlIHByb3ZpZGVkIGNhbGxiYWNrIGp1c3QgYmVmb3JlIHRoZSBjdXJyZW50IGNhbGxzdGFjayB1bndpbmRzLCBvciBhc1xuICogc29vbiBhcyBwb3NzaWJsZSBhZnRlciB0aGUgY3VycmVudCBKUyBleGVjdXRpb24gY29udGV4dC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24odGhpczpUSElTKX0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7VEhJUz19IG9wdF9jb250ZXh0IE9iamVjdCB0byB1c2UgYXMgdGhlIFwidGhpcyB2YWx1ZVwiIHdoZW4gY2FsbGluZ1xuICogICAgIHRoZSBwcm92aWRlZCBmdW5jdGlvbi5cbiAqIEB0ZW1wbGF0ZSBUSElTXG4gKi9cbmFzeW5jLnJ1biA9IGZ1bmN0aW9uKGNhbGxiYWNrLCBvcHRfY29udGV4dCkge1xuXHRpZiAoIWFzeW5jLnJ1bi53b3JrUXVldWVTY2hlZHVsZWRfKSB7XG5cdFx0Ly8gTm90aGluZyBpcyBjdXJyZW50bHkgc2NoZWR1bGVkLCBzY2hlZHVsZSBpdCBub3cuXG5cdFx0YXN5bmMubmV4dFRpY2soYXN5bmMucnVuLnByb2Nlc3NXb3JrUXVldWUpO1xuXHRcdGFzeW5jLnJ1bi53b3JrUXVldWVTY2hlZHVsZWRfID0gdHJ1ZTtcblx0fVxuXG5cdGFzeW5jLnJ1bi53b3JrUXVldWVfLnB1c2goXG5cdFx0bmV3IGFzeW5jLnJ1bi5Xb3JrSXRlbV8oY2FsbGJhY2ssIG9wdF9jb250ZXh0KSk7XG59O1xuXG5cbi8qKiBAcHJpdmF0ZSB7Ym9vbGVhbn0gKi9cbmFzeW5jLnJ1bi53b3JrUXVldWVTY2hlZHVsZWRfID0gZmFsc2U7XG5cblxuLyoqIEBwcml2YXRlIHshQXJyYXkuPCFhc3luYy5ydW4uV29ya0l0ZW1fPn0gKi9cbmFzeW5jLnJ1bi53b3JrUXVldWVfID0gW107XG5cbi8qKlxuICogUnVuIGFueSBwZW5kaW5nIGFzeW5jLnJ1biB3b3JrIGl0ZW1zLiBUaGlzIGZ1bmN0aW9uIGlzIG5vdCBpbnRlbmRlZFxuICogZm9yIGdlbmVyYWwgdXNlLCBidXQgZm9yIHVzZSBieSBlbnRyeSBwb2ludCBoYW5kbGVycyB0byBydW4gaXRlbXMgYWhlYWQgb2ZcbiAqIGFzeW5jLm5leHRUaWNrLlxuICovXG5hc3luYy5ydW4ucHJvY2Vzc1dvcmtRdWV1ZSA9IGZ1bmN0aW9uKCkge1xuXHQvLyBOT1RFOiBhZGRpdGlvbmFsIHdvcmsgcXVldWUgaXRlbXMgbWF5IGJlIHB1c2hlZCB3aGlsZSBwcm9jZXNzaW5nLlxuXHR3aGlsZSAoYXN5bmMucnVuLndvcmtRdWV1ZV8ubGVuZ3RoKSB7XG5cdFx0Ly8gRG9uJ3QgbGV0IHRoZSB3b3JrIHF1ZXVlIGdyb3cgaW5kZWZpbml0ZWx5LlxuXHRcdGNvbnN0IHdvcmtJdGVtcyA9IGFzeW5jLnJ1bi53b3JrUXVldWVfO1xuXHRcdGFzeW5jLnJ1bi53b3JrUXVldWVfID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB3b3JrSXRlbXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IHdvcmtJdGVtID0gd29ya0l0ZW1zW2ldO1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0d29ya0l0ZW0uZm4uY2FsbCh3b3JrSXRlbS5zY29wZSk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdGFzeW5jLnRocm93RXhjZXB0aW9uKGUpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIFRoZXJlIGFyZSBubyBtb3JlIHdvcmsgaXRlbXMsIHJlc2V0IHRoZSB3b3JrIHF1ZXVlLlxuXHRhc3luYy5ydW4ud29ya1F1ZXVlU2NoZWR1bGVkXyA9IGZhbHNlO1xufTtcblxuXG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICogQGZpbmFsXG4gKiBAc3RydWN0XG4gKiBAcHJpdmF0ZVxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb24oKX0gZm5cbiAqIEBwYXJhbSB7T2JqZWN0fG51bGx8dW5kZWZpbmVkfSBzY29wZVxuICovXG5hc3luYy5ydW4uV29ya0l0ZW1fID0gZnVuY3Rpb24oZm4sIHNjb3BlKSB7XG5cdC8qKiBAY29uc3QgKi9cblx0dGhpcy5mbiA9IGZuO1xuXHQvKiogQGNvbnN0ICovXG5cdHRoaXMuc2NvcGUgPSBzY29wZTtcbn07XG5cblxuLyoqXG4gKiBGaXJlcyB0aGUgcHJvdmlkZWQgY2FsbGJhY2tzIGFzIHNvb24gYXMgcG9zc2libGUgYWZ0ZXIgdGhlIGN1cnJlbnQgSlNcbiAqIGV4ZWN1dGlvbiBjb250ZXh0LiBzZXRUaW1lb3V0KOKApiwgMCkgYWx3YXlzIHRha2VzIGF0IGxlYXN0IDVtcyBmb3IgbGVnYWN5XG4gKiByZWFzb25zLlxuICogQHBhcmFtIHtmdW5jdGlvbih0aGlzOlNDT1BFKX0gY2FsbGJhY2sgQ2FsbGJhY2sgZnVuY3Rpb24gdG8gZmlyZSBhcyBzb29uIGFzXG4gKiAgICAgcG9zc2libGUuXG4gKiBAcGFyYW0ge1NDT1BFPX0gb3B0X2NvbnRleHQgT2JqZWN0IGluIHdob3NlIHNjb3BlIHRvIGNhbGwgdGhlIGxpc3RlbmVyLlxuICogQHRlbXBsYXRlIFNDT1BFXG4gKi9cbmFzeW5jLm5leHRUaWNrID0gZnVuY3Rpb24oY2FsbGJhY2ssIG9wdF9jb250ZXh0KSB7XG5cdGxldCBjYiA9IGNhbGxiYWNrO1xuXHRpZiAob3B0X2NvbnRleHQpIHtcblx0XHRjYiA9IGNhbGxiYWNrLmJpbmQob3B0X2NvbnRleHQpO1xuXHR9XG5cdGNiID0gYXN5bmMubmV4dFRpY2sud3JhcENhbGxiYWNrXyhjYik7XG5cdC8vIEludHJvZHVjZWQgYW5kIGN1cnJlbnRseSBvbmx5IHN1cHBvcnRlZCBieSBJRTEwLlxuXHQvLyBWZXJpZnkgaWYgdmFyaWFibGUgaXMgZGVmaW5lZCBvbiB0aGUgY3VycmVudCBydW50aW1lIChpLmUuLCBub2RlLCBicm93c2VyKS5cblx0Ly8gQ2FuJ3QgdXNlIHR5cGVvZiBlbmNsb3NlZCBpbiBhIGZ1bmN0aW9uIChzdWNoIGFzIGNvcmUuaXNGdW5jdGlvbikgb3IgYW5cblx0Ly8gZXhjZXB0aW9uIHdpbGwgYmUgdGhyb3duIHdoZW4gdGhlIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBhbiBlbnZpcm9ubWVudFxuXHQvLyB3aGVyZSB0aGUgdmFyaWFibGUgaXMgdW5kZWZpbmVkLlxuXHRpZiAodHlwZW9mIHNldEltbWVkaWF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdHNldEltbWVkaWF0ZShjYik7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdC8vIExvb2sgZm9yIGFuZCBjYWNoZSB0aGUgY3VzdG9tIGZhbGxiYWNrIHZlcnNpb24gb2Ygc2V0SW1tZWRpYXRlLlxuXHRpZiAoIWFzeW5jLm5leHRUaWNrLnNldEltbWVkaWF0ZV8pIHtcblx0XHRhc3luYy5uZXh0VGljay5zZXRJbW1lZGlhdGVfID0gYXN5bmMubmV4dFRpY2suZ2V0U2V0SW1tZWRpYXRlRW11bGF0b3JfKCk7XG5cdH1cblx0YXN5bmMubmV4dFRpY2suc2V0SW1tZWRpYXRlXyhjYik7XG59O1xuXG5cbi8qKlxuICogQ2FjaGUgZm9yIHRoZSBzZXRJbW1lZGlhdGUgaW1wbGVtZW50YXRpb24uXG4gKiBAdHlwZSB7ZnVuY3Rpb24oZnVuY3Rpb24oKSl9XG4gKiBAcHJpdmF0ZVxuICovXG5hc3luYy5uZXh0VGljay5zZXRJbW1lZGlhdGVfID0gbnVsbDtcblxuXG4vKipcbiAqIERldGVybWluZXMgdGhlIGJlc3QgcG9zc2libGUgaW1wbGVtZW50YXRpb24gdG8gcnVuIGEgZnVuY3Rpb24gYXMgc29vbiBhc1xuICogdGhlIEpTIGV2ZW50IGxvb3AgaXMgaWRsZS5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGZ1bmN0aW9uKCkpfSBUaGUgXCJzZXRJbW1lZGlhdGVcIiBpbXBsZW1lbnRhdGlvbi5cbiAqIEBwcml2YXRlXG4gKi9cbmFzeW5jLm5leHRUaWNrLmdldFNldEltbWVkaWF0ZUVtdWxhdG9yXyA9IGZ1bmN0aW9uKCkge1xuXHQvLyBDcmVhdGUgYSBwcml2YXRlIG1lc3NhZ2UgY2hhbm5lbCBhbmQgdXNlIGl0IHRvIHBvc3RNZXNzYWdlIGVtcHR5IG1lc3NhZ2VzXG5cdC8vIHRvIG91cnNlbHZlcy5cblx0bGV0IENoYW5uZWw7XG5cblx0Ly8gVmVyaWZ5IGlmIHZhcmlhYmxlIGlzIGRlZmluZWQgb24gdGhlIGN1cnJlbnQgcnVudGltZSAoaS5lLiwgbm9kZSwgYnJvd3NlcikuXG5cdC8vIENhbid0IHVzZSB0eXBlb2YgZW5jbG9zZWQgaW4gYSBmdW5jdGlvbiAoc3VjaCBhcyBjb3JlLmlzRnVuY3Rpb24pIG9yIGFuXG5cdC8vIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93biB3aGVuIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQgb24gYW4gZW52aXJvbm1lbnRcblx0Ly8gd2hlcmUgdGhlIHZhcmlhYmxlIGlzIHVuZGVmaW5lZC5cblx0aWYgKHR5cGVvZiBNZXNzYWdlQ2hhbm5lbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdENoYW5uZWwgPSBNZXNzYWdlQ2hhbm5lbDtcblx0fVxuXG5cdC8vIElmIE1lc3NhZ2VDaGFubmVsIGlzIG5vdCBhdmFpbGFibGUgYW5kIHdlIGFyZSBpbiBhIGJyb3dzZXIsIGltcGxlbWVudFxuXHQvLyBhbiBpZnJhbWUgYmFzZWQgcG9seWZpbGwgaW4gYnJvd3NlcnMgdGhhdCBoYXZlIHBvc3RNZXNzYWdlIGFuZFxuXHQvLyBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyLiBUaGUgbGF0dGVyIGV4Y2x1ZGVzIElFOCBiZWNhdXNlIGl0IGhhcyBhXG5cdC8vIHN5bmNocm9ub3VzIHBvc3RNZXNzYWdlIGltcGxlbWVudGF0aW9uLlxuXHRpZiAodHlwZW9mIENoYW5uZWwgPT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmXG5cdFx0d2luZG93LnBvc3RNZXNzYWdlICYmIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKSB7XG5cdFx0LyoqIEBjb25zdHJ1Y3RvciAqL1xuXHRcdENoYW5uZWwgPSBmdW5jdGlvbigpIHtcblx0XHRcdC8vIE1ha2UgYW4gZW1wdHksIGludmlzaWJsZSBpZnJhbWUuXG5cdFx0XHRjb25zdCBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcblx0XHRcdGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXHRcdFx0aWZyYW1lLnNyYyA9ICcnO1xuXHRcdFx0ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmFwcGVuZENoaWxkKGlmcmFtZSk7XG5cdFx0XHRjb25zdCB3aW4gPSBpZnJhbWUuY29udGVudFdpbmRvdztcblx0XHRcdGNvbnN0IGRvYyA9IHdpbi5kb2N1bWVudDtcblx0XHRcdGRvYy5vcGVuKCk7XG5cdFx0XHRkb2Mud3JpdGUoJycpO1xuXHRcdFx0ZG9jLmNsb3NlKCk7XG5cdFx0XHRjb25zdCBtZXNzYWdlID0gJ2NhbGxJbW1lZGlhdGUnICsgTWF0aC5yYW5kb20oKTtcblx0XHRcdGNvbnN0IG9yaWdpbiA9IHdpbi5sb2NhdGlvbi5wcm90b2NvbCArICcvLycgKyB3aW4ubG9jYXRpb24uaG9zdDtcblx0XHRcdGNvbnN0IG9ubWVzc2FnZSA9IGZ1bmN0aW9uKGUpIHtcblx0XHRcdFx0Ly8gVmFsaWRhdGUgb3JpZ2luIGFuZCBtZXNzYWdlIHRvIG1ha2Ugc3VyZSB0aGF0IHRoaXMgbWVzc2FnZSB3YXNcblx0XHRcdFx0Ly8gaW50ZW5kZWQgZm9yIHVzLlxuXHRcdFx0XHRpZiAoZS5vcmlnaW4gIT09IG9yaWdpbiAmJiBlLmRhdGEgIT09IG1lc3NhZ2UpIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5wb3J0MS5vbm1lc3NhZ2UoKTtcblx0XHRcdH0uYmluZCh0aGlzKTtcblx0XHRcdHdpbi5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25tZXNzYWdlLCBmYWxzZSk7XG5cdFx0XHR0aGlzLnBvcnQxID0ge307XG5cdFx0XHR0aGlzLnBvcnQyID0ge1xuXHRcdFx0XHRwb3N0TWVzc2FnZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0d2luLnBvc3RNZXNzYWdlKG1lc3NhZ2UsIG9yaWdpbik7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fTtcblx0fVxuXHRpZiAodHlwZW9mIENoYW5uZWwgIT09ICd1bmRlZmluZWQnKSB7XG5cdFx0Y29uc3QgY2hhbm5lbCA9IG5ldyBDaGFubmVsKCk7XG5cdFx0Ly8gVXNlIGEgZmlmbyBsaW5rZWQgbGlzdCB0byBjYWxsIGNhbGxiYWNrcyBpbiB0aGUgcmlnaHQgb3JkZXIuXG5cdFx0bGV0IGhlYWQgPSB7fTtcblx0XHRsZXQgdGFpbCA9IGhlYWQ7XG5cdFx0Y2hhbm5lbC5wb3J0MS5vbm1lc3NhZ2UgPSBmdW5jdGlvbigpIHtcblx0XHRcdGhlYWQgPSBoZWFkLm5leHQ7XG5cdFx0XHRjb25zdCBjYiA9IGhlYWQuY2I7XG5cdFx0XHRoZWFkLmNiID0gbnVsbDtcblx0XHRcdGNiKCk7XG5cdFx0fTtcblx0XHRyZXR1cm4gZnVuY3Rpb24oY2IpIHtcblx0XHRcdHRhaWwubmV4dCA9IHtcblx0XHRcdFx0Y2I6IGNiXG5cdFx0XHR9O1xuXHRcdFx0dGFpbCA9IHRhaWwubmV4dDtcblx0XHRcdGNoYW5uZWwucG9ydDIucG9zdE1lc3NhZ2UoMCk7XG5cdFx0fTtcblx0fVxuXHQvLyBJbXBsZW1lbnRhdGlvbiBmb3IgSUU2LTg6IFNjcmlwdCBlbGVtZW50cyBmaXJlIGFuIGFzeW5jaHJvbm91c1xuXHQvLyBvbnJlYWR5c3RhdGVjaGFuZ2UgZXZlbnQgd2hlbiBpbnNlcnRlZCBpbnRvIHRoZSBET00uXG5cdGlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnICYmICdvbnJlYWR5c3RhdGVjaGFuZ2UnIGluXG5cdFx0ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0JykpIHtcblx0XHRyZXR1cm4gZnVuY3Rpb24oY2IpIHtcblx0XHRcdGxldCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcblx0XHRcdHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0Ly8gQ2xlYW4gdXAgYW5kIGNhbGwgdGhlIGNhbGxiYWNrLlxuXHRcdFx0XHRzY3JpcHQub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbDtcblx0XHRcdFx0c2NyaXB0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc2NyaXB0KTtcblx0XHRcdFx0c2NyaXB0ID0gbnVsbDtcblx0XHRcdFx0Y2IoKTtcblx0XHRcdFx0Y2IgPSBudWxsO1xuXHRcdFx0fTtcblx0XHRcdGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuXHRcdH07XG5cdH1cblx0Ly8gRmFsbCBiYWNrIHRvIHNldFRpbWVvdXQgd2l0aCAwLiBJbiBicm93c2VycyB0aGlzIGNyZWF0ZXMgYSBkZWxheSBvZiA1bXNcblx0Ly8gb3IgbW9yZS5cblx0cmV0dXJuIGZ1bmN0aW9uKGNiKSB7XG5cdFx0c2V0VGltZW91dChjYiwgMCk7XG5cdH07XG59O1xuXG5cbi8qKlxuICogSGVscGVyIGZ1bmN0aW9uIHRoYXQgaXMgb3ZlcnJpZGVkIHRvIHByb3RlY3QgY2FsbGJhY2tzIHdpdGggZW50cnkgcG9pbnRcbiAqIG1vbml0b3IgaWYgdGhlIGFwcGxpY2F0aW9uIG1vbml0b3JzIGVudHJ5IHBvaW50cy5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oKX0gY2FsbGJhY2sgQ2FsbGJhY2sgZnVuY3Rpb24gdG8gZmlyZSBhcyBzb29uIGFzIHBvc3NpYmxlLlxuICogQHJldHVybiB7ZnVuY3Rpb24oKX0gVGhlIHdyYXBwZWQgY2FsbGJhY2suXG4gKiBAcHJpdmF0ZVxuICovXG5hc3luYy5uZXh0VGljay53cmFwQ2FsbGJhY2tfID0gZnVuY3Rpb24ob3B0X3JldHVyblZhbHVlKSB7XG5cdHJldHVybiBvcHRfcmV0dXJuVmFsdWU7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYztcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBEaXNwb3NhYmxlIHV0aWxpdHkuIFdoZW4gaW5oZXJpdGVkIHByb3ZpZGVzIHRoZSBgZGlzcG9zZWAgZnVuY3Rpb24gdG8gaXRzXG4gKiBzdWJjbGFzcywgd2hpY2ggaXMgcmVzcG9uc2libGUgZm9yIGRpc3Bvc2luZyBvZiBhbnkgb2JqZWN0IHJlZmVyZW5jZXNcbiAqIHdoZW4gYW4gaW5zdGFuY2Ugd29uJ3QgYmUgdXNlZCBhbnltb3JlLiBTdWJjbGFzc2VzIHNob3VsZCBvdmVycmlkZVxuICogYGRpc3Bvc2VJbnRlcm5hbGAgdG8gaW1wbGVtZW50IGFueSBzcGVjaWZpYyBkaXNwb3NpbmcgbG9naWMuXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuY2xhc3MgRGlzcG9zYWJsZSB7XG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdC8qKlxuXHRcdCAqIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGluc3RhbmNlIGhhcyBhbHJlYWR5IGJlZW4gZGlzcG9zZWQuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZGlzcG9zZWRfID0gZmFsc2U7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLiBDYWxscyBgZGlzcG9zZUludGVybmFsYC5cblx0ICovXG5cdGRpc3Bvc2UoKSB7XG5cdFx0aWYgKCF0aGlzLmRpc3Bvc2VkXykge1xuXHRcdFx0dGhpcy5kaXNwb3NlSW50ZXJuYWwoKTtcblx0XHRcdHRoaXMuZGlzcG9zZWRfID0gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU3ViY2xhc3NlcyBzaG91bGQgb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gaW1wbGVtZW50IGFueSBzcGVjaWZpY1xuXHQgKiBkaXNwb3NpbmcgbG9naWMgKGxpa2UgY2xlYXJpbmcgcmVmZXJlbmNlcyBhbmQgY2FsbGluZyBgZGlzcG9zZWAgb24gb3RoZXJcblx0ICogZGlzcG9zYWJsZXMpLlxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge31cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoaXMgaW5zdGFuY2UgaGFzIGFscmVhZHkgYmVlbiBkaXNwb3NlZC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGlzRGlzcG9zZWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZGlzcG9zZWRfO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERpc3Bvc2FibGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmNsYXNzIG9iamVjdCB7XG5cdC8qKlxuXHQgKiBDb3BpZXMgYWxsIHRoZSBtZW1iZXJzIG9mIGEgc291cmNlIG9iamVjdCB0byBhIHRhcmdldCBvYmplY3QuXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSB0YXJnZXQgVGFyZ2V0IG9iamVjdC5cblx0ICogQHBhcmFtIHsuLi5PYmplY3R9IHZhcl9hcmdzIFRoZSBvYmplY3RzIGZyb20gd2hpY2ggdmFsdWVzIHdpbGwgYmUgY29waWVkLlxuXHQgKiBAcmV0dXJuIHtPYmplY3R9IFJldHVybnMgdGhlIHRhcmdldCBvYmplY3QgcmVmZXJlbmNlLlxuXHQgKi9cblx0c3RhdGljIG1peGluKHRhcmdldCkge1xuXHRcdGxldCBrZXksIHNvdXJjZTtcblx0XHRmb3IgKGxldCBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0c291cmNlID0gYXJndW1lbnRzW2ldO1xuXHRcdFx0Zm9yIChrZXkgaW4gc291cmNlKSB7XG5cdFx0XHRcdHRhcmdldFtrZXldID0gc291cmNlW2tleV07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0YXJnZXQ7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbiBvYmplY3QgYmFzZWQgb24gaXRzIGZ1bGx5IHF1YWxpZmllZCBleHRlcm5hbCBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUuXG5cdCAqIEBwYXJhbSB7b2JqZWN0PX0gb3B0X29iaiBUaGUgb2JqZWN0IHdpdGhpbiB3aGljaCB0byBsb29rOyBkZWZhdWx0IGlzXG5cdCAqICAgICA8Y29kZT53aW5kb3c8L2NvZGU+LlxuXHQgKiBAcmV0dXJuIHs/fSBUaGUgdmFsdWUgKG9iamVjdCBvciBwcmltaXRpdmUpIG9yLCBpZiBub3QgZm91bmQsIHVuZGVmaW5lZC5cblx0ICovXG5cdHN0YXRpYyBnZXRPYmplY3RCeU5hbWUobmFtZSwgb3B0X29iaikge1xuXHRcdGNvbnN0IHNjb3BlID0gb3B0X29iaiB8fCB3aW5kb3c7XG5cdFx0Y29uc3QgcGFydHMgPSBuYW1lLnNwbGl0KCcuJyk7XG5cdFx0cmV0dXJuIHBhcnRzLnJlZHVjZSgocGFydCwga2V5KSA9PiBwYXJ0W2tleV0sIHNjb3BlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgbmV3IG9iamVjdCB3aXRoIHRoZSBzYW1lIGtleXMgYXMgdGhlIGdpdmVuIG9uZSwgYnV0IHdpdGhcblx0ICogdGhlaXIgdmFsdWVzIHNldCB0byB0aGUgcmV0dXJuIHZhbHVlcyBvZiB0aGUgc3BlY2lmaWVkIGZ1bmN0aW9uLlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IG9ialxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbihzdHJpbmcsICopfSBmblxuXHQgKiBAcmV0dXJuIHshT2JqZWN0fVxuXHQgKi9cblx0c3RhdGljIG1hcChvYmosIGZuKSB7XG5cdFx0Y29uc3QgbWFwcGVkT2JqID0ge307XG5cdFx0Y29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRtYXBwZWRPYmpba2V5c1tpXV0gPSBmbihrZXlzW2ldLCBvYmpba2V5c1tpXV0pO1xuXHRcdH1cblx0XHRyZXR1cm4gbWFwcGVkT2JqO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgdHdvIGdpdmVuIG9iamVjdHMgYXJlIGVxdWFsLiBUaGlzIGlzIGRvbmUgdmlhIGEgc2hhbGxvd1xuXHQgKiBjaGVjaywgaW5jbHVkaW5nIG9ubHkgdGhlIGtleXMgZGlyZWN0bHkgY29udGFpbmVkIGJ5IHRoZSAyIG9iamVjdHMuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRzdGF0aWMgc2hhbGxvd0VxdWFsKG9iajEsIG9iajIpIHtcblx0XHRpZiAob2JqMSA9PT0gb2JqMikge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Y29uc3Qga2V5czEgPSBPYmplY3Qua2V5cyhvYmoxKTtcblx0XHRjb25zdCBrZXlzMiA9IE9iamVjdC5rZXlzKG9iajIpO1xuXHRcdGlmIChrZXlzMS5sZW5ndGggIT09IGtleXMyLmxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwga2V5czEubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChvYmoxW2tleXMxW2ldXSAhPT0gb2JqMltrZXlzMVtpXV0pIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBvYmplY3Q7XG4iLCIndXNlIHN0cmljdCc7XG5cbmNsYXNzIHN0cmluZyB7XG5cdC8qKlxuXHQgKiBDb21wYXJlcyB0aGUgZ2l2ZW4gc3RyaW5ncyB3aXRob3V0IHRha2luZyB0aGUgY2FzZSBpbnRvIGFjY291bnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gc3RyMVxuXHQgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHN0cjJcblx0ICogQHJldHVybiB7bnVtYmVyfSBFaXRoZXIgLTEsIDAgb3IgMSwgYWNjb3JkaW5nIHRvIGlmIHRoZSBmaXJzdCBzdHJpbmcgaXNcblx0ICogICAgIFwic21hbGxlclwiLCBlcXVhbCBvciBcImJpZ2dlclwiIHRoYW4gdGhlIHNlY29uZCBnaXZlbiBzdHJpbmcuXG5cdCAqL1xuXHRzdGF0aWMgY2FzZUluc2Vuc2l0aXZlQ29tcGFyZShzdHIxLCBzdHIyKSB7XG5cdFx0Y29uc3QgdGVzdDEgPSBTdHJpbmcoc3RyMSkudG9Mb3dlckNhc2UoKTtcblx0XHRjb25zdCB0ZXN0MiA9IFN0cmluZyhzdHIyKS50b0xvd2VyQ2FzZSgpO1xuXG5cdFx0aWYgKHRlc3QxIDwgdGVzdDIpIHtcblx0XHRcdHJldHVybiAtMTtcblx0XHR9IGVsc2UgaWYgKHRlc3QxID09PSB0ZXN0Mikge1xuXHRcdFx0cmV0dXJuIDA7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiAxO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHRoZSBicmVha2luZyBzcGFjZXMgZnJvbSB0aGUgbGVmdCBhbmQgcmlnaHQgb2YgdGhlIHN0cmluZyBhbmRcblx0ICogY29sbGFwc2VzIHRoZSBzZXF1ZW5jZXMgb2YgYnJlYWtpbmcgc3BhY2VzIGluIHRoZSBtaWRkbGUgaW50byBzaW5nbGUgc3BhY2VzLlxuXHQgKiBUaGUgb3JpZ2luYWwgYW5kIHRoZSByZXN1bHQgc3RyaW5ncyByZW5kZXIgdGhlIHNhbWUgd2F5IGluIEhUTUwuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgQSBzdHJpbmcgaW4gd2hpY2ggdG8gY29sbGFwc2Ugc3BhY2VzLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IENvcHkgb2YgdGhlIHN0cmluZyB3aXRoIG5vcm1hbGl6ZWQgYnJlYWtpbmcgc3BhY2VzLlxuXHQgKi9cblx0c3RhdGljIGNvbGxhcHNlQnJlYWtpbmdTcGFjZXMoc3RyKSB7XG5cdFx0cmV0dXJuIHN0ci5yZXBsYWNlKC9bXFx0XFxyXFxuIF0rL2csICcgJykucmVwbGFjZSgvXltcXHRcXHJcXG4gXSt8W1xcdFxcclxcbiBdKyQvZywgJycpO1xuXHR9XG5cblx0LyoqXG5cdCogRXNjYXBlcyBjaGFyYWN0ZXJzIGluIHRoZSBzdHJpbmcgdGhhdCBhcmUgbm90IHNhZmUgdG8gdXNlIGluIGEgUmVnRXhwLlxuXHQqIEBwYXJhbSB7Kn0gc3RyIFRoZSBzdHJpbmcgdG8gZXNjYXBlLiBJZiBub3QgYSBzdHJpbmcsIGl0IHdpbGwgYmUgY2FzdGVkXG5cdCogICAgIHRvIG9uZS5cblx0KiBAcmV0dXJuIHtzdHJpbmd9IEEgUmVnRXhwIHNhZmUsIGVzY2FwZWQgY29weSBvZiB7QGNvZGUgc30uXG5cdCovXG5cdHN0YXRpYyBlc2NhcGVSZWdleChzdHIpIHtcblx0XHRyZXR1cm4gU3RyaW5nKHN0cilcblx0XHRcdC5yZXBsYWNlKC8oWy0oKVxcW1xcXXt9Kz8qLiRcXF58LDojPCFcXFxcXSkvZywgJ1xcXFwkMScpXG5cdFx0XHQucmVwbGFjZSgvXFx4MDgvZywgJ1xcXFx4MDgnKTtcblx0fVxuXG5cdC8qKlxuXHQqIFJldHVybnMgYSBzdHJpbmcgd2l0aCBhdCBsZWFzdCA2NC1iaXRzIG9mIHJhbmRvbW5lc3MuXG5cdCogQHJldHVybiB7c3RyaW5nfSBBIHJhbmRvbSBzdHJpbmcsIGUuZy4gc24xczd2YjRnY2ljLlxuXHQqL1xuXHRzdGF0aWMgZ2V0UmFuZG9tU3RyaW5nKCkge1xuXHRcdGNvbnN0IHggPSAyMTQ3NDgzNjQ4O1xuXHRcdHJldHVybiBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB4KS50b1N0cmluZygzNikgK1xuXHRcdFx0TWF0aC5hYnMoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogeCkgXiBEYXRlLm5vdygpKS50b1N0cmluZygzNik7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsY3VsYXRlcyB0aGUgaGFzaGNvZGUgZm9yIGEgc3RyaW5nLiBUaGUgaGFzaGNvZGUgdmFsdWUgaXMgY29tcHV0ZWQgYnlcblx0ICogdGhlIHN1bSBhbGdvcml0aG06IHNbMF0qMzFeKG4tMSkgKyBzWzFdKjMxXihuLTIpICsgLi4uICsgc1tuLTFdLiBBIG5pY2Vcblx0ICogcHJvcGVydHkgb2YgdXNpbmcgMzEgcHJpbWUgaXMgdGhhdCB0aGUgbXVsdGlwbGljYXRpb24gY2FuIGJlIHJlcGxhY2VkIGJ5XG5cdCAqIGEgc2hpZnQgYW5kIGEgc3VidHJhY3Rpb24gZm9yIGJldHRlciBwZXJmb3JtYW5jZTogMzEqaSA9PSAoaTw8NSktaS5cblx0ICogTW9kZXJuIFZNcyBkbyB0aGlzIHNvcnQgb2Ygb3B0aW1pemF0aW9uIGF1dG9tYXRpY2FsbHkuXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSB2YWwgVGFyZ2V0IHN0cmluZy5cblx0ICogQHJldHVybiB7TnVtYmVyfSBSZXR1cm5zIHRoZSBzdHJpbmcgaGFzaGNvZGUuXG5cdCAqL1xuXHRzdGF0aWMgaGFzaENvZGUodmFsKSB7XG5cdFx0bGV0IGhhc2ggPSAwO1xuXHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSB2YWwubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGhhc2ggPSAzMSAqIGhhc2ggKyB2YWwuY2hhckNvZGVBdChpKTtcblx0XHRcdGhhc2ggJT0gMHgxMDAwMDAwMDA7XG5cdFx0fVxuXHRcdHJldHVybiBoYXNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlcGxhY2VzIGludGVydmFsIGludG8gdGhlIHN0cmluZyB3aXRoIHNwZWNpZmllZCB2YWx1ZSwgZS5nLlxuXHQgKiBgcmVwbGFjZUludGVydmFsKFwiYWJjZGVcIiwgMSwgNCwgXCJcIilgIHJldHVybnMgXCJhZVwiLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyIFRoZSBpbnB1dCBzdHJpbmcuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBzdGFydCBTdGFydCBpbnRlcnZhbCBwb3NpdGlvbiB0byBiZSByZXBsYWNlZC5cblx0ICogQHBhcmFtIHtOdW1iZXJ9IGVuZCBFbmQgaW50ZXJ2YWwgcG9zaXRpb24gdG8gYmUgcmVwbGFjZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdGhhdCByZXBsYWNlcyB0aGUgc3BlY2lmaWVkIGludGVydmFsLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRzdGF0aWMgcmVwbGFjZUludGVydmFsKHN0ciwgc3RhcnQsIGVuZCwgdmFsdWUpIHtcblx0XHRyZXR1cm4gc3RyLnN1YnN0cmluZygwLCBzdGFydCkgKyB2YWx1ZSArIHN0ci5zdWJzdHJpbmcoZW5kKTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBzdHJpbmc7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogUGFyc2VzIHRoZSBnaXZlbiB1cmkgc3RyaW5nIGludG8gYW4gb2JqZWN0LlxuICogQHBhcmFtIHsqPX0gb3B0X3VyaSBPcHRpb25hbCBzdHJpbmcgVVJJIHRvIHBhcnNlXG4gKi9cbmZ1bmN0aW9uIHBhcnNlRnJvbUFuY2hvcihvcHRfdXJpKSB7XG5cdHZhciBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuXHRsaW5rLmhyZWYgPSBvcHRfdXJpO1xuXG5cdGlmKGxpbmsucHJvdG9jb2wgPT09ICc6JyB8fCAhLzovLnRlc3QobGluay5ocmVmKSkge1xuXHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYCR7b3B0X3VyaX0gaXMgbm90IGEgdmFsaWQgVVJMYCk7XG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdGhhc2g6IGxpbmsuaGFzaCxcblx0XHRob3N0bmFtZTogbGluay5ob3N0bmFtZSxcblx0XHRwYXNzd29yZDogbGluay5wYXNzd29yZCxcblx0XHRwYXRobmFtZTogbGluay5wYXRobmFtZVswXSA9PT0gJy8nID8gbGluay5wYXRobmFtZSA6ICcvJyArIGxpbmsucGF0aG5hbWUsXG5cdFx0cG9ydDogbGluay5wb3J0LFxuXHRcdHByb3RvY29sOiBsaW5rLnByb3RvY29sLFxuXHRcdHNlYXJjaDogbGluay5zZWFyY2gsXG5cdFx0dXNlcm5hbWU6IGxpbmsudXNlcm5hbWVcblx0fTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgcGFyc2VGcm9tQW5jaG9yO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBpc0Z1bmN0aW9uIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHBhcnNlRnJvbUFuY2hvciBmcm9tICcuL3BhcnNlRnJvbUFuY2hvcic7XG5cbi8qKlxuICogUGFyc2VzIHRoZSBnaXZlbiB1cmkgc3RyaW5nIGludG8gYW4gb2JqZWN0LiBUaGUgVVJMIGZ1bmN0aW9uIHdpbGwgYmUgdXNlZFxuICogd2hlbiBwcmVzZW50LCBvdGhlcndpc2Ugd2UnbGwgZmFsbCBiYWNrIHRvIHRoZSBhbmNob3Igbm9kZSBlbGVtZW50LlxuICogQHBhcmFtIHsqPX0gb3B0X3VyaSBPcHRpb25hbCBzdHJpbmcgVVJJIHRvIHBhcnNlXG4gKi9cbmZ1bmN0aW9uIHBhcnNlKG9wdF91cmkpIHtcblx0aWYgKGlzRnVuY3Rpb24oVVJMKSAmJiBVUkwubGVuZ3RoKSB7XG5cdFx0Y29uc3QgdXJsID0gbmV3IFVSTChvcHRfdXJpKTtcblxuXHRcdC8vIFNhZmFyaSBCcm93c2VycyB3aWxsIGNhcCBwb3J0IHRvIHRoZSBtYXggMTYtYml0IHVuc2lnbmVkIGludGVnZXIgKDY1NTM1KSBpbnN0ZWFkXG5cdFx0Ly8gb2YgdGhyb3dpbmcgYSBUeXBlRXJyb3IgYXMgcGVyIHNwZWMuIEl0IHdpbGwgc3RpbGwga2VlcCB0aGUgcG9ydCBudW1iZXIgaW4gdGhlXG5cdFx0Ly8gaHJlZiBhdHRyaWJ1dGUsIHNvIHdlIGNhbiB1c2UgdGhpcyBtaXNtYXRjaCB0byByYWlzZSB0aGUgZXhwZWN0ZWQgZXhjZXB0aW9uLlxuXHRcdGlmICh1cmwucG9ydCAmJiB1cmwuaHJlZi5pbmRleE9mKHVybC5wb3J0KSA9PT0gLTEpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYCR7b3B0X3VyaX0gaXMgbm90IGEgdmFsaWQgVVJMYCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVybDtcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gcGFyc2VGcm9tQW5jaG9yKG9wdF91cmkpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IHBhcnNlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlIH0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEEgY2FjaGVkIHJlZmVyZW5jZSB0byB0aGUgY3JlYXRlIGZ1bmN0aW9uLlxuICovXG52YXIgY3JlYXRlID0gT2JqZWN0LmNyZWF0ZTtcblxuLyoqXG4gKiBDYXNlIGluc2Vuc2l0aXZlIHN0cmluZyBNdWx0aW1hcCBpbXBsZW1lbnRhdGlvbi4gQWxsb3dzIG11bHRpcGxlIHZhbHVlcyBmb3JcbiAqIHRoZSBzYW1lIGtleSBuYW1lLlxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIE11bHRpTWFwIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cdFx0dGhpcy5rZXlzID0gY3JlYXRlKG51bGwpO1xuXHRcdHRoaXMudmFsdWVzID0gY3JlYXRlKG51bGwpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdmFsdWUgdG8gYSBrZXkgbmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHBhcmFtIHsqfSB2YWx1ZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRhZGQobmFtZSwgdmFsdWUpIHtcblx0XHR0aGlzLmtleXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IG5hbWU7XG5cdFx0dGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV0gfHwgW107XG5cdFx0dGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXS5wdXNoKHZhbHVlKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhcnMgbWFwIG5hbWVzIGFuZCB2YWx1ZXMuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGNsZWFyKCkge1xuXHRcdHRoaXMua2V5cyA9IGNyZWF0ZShudWxsKTtcblx0XHR0aGlzLnZhbHVlcyA9IGNyZWF0ZShudWxsKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgbWFwIGNvbnRhaW5zIGEgdmFsdWUgdG8gdGhlIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRjb250YWlucyhuYW1lKSB7XG5cdFx0cmV0dXJuIG5hbWUudG9Mb3dlckNhc2UoKSBpbiB0aGlzLnZhbHVlcztcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHRoaXMudmFsdWVzID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgYE11bHRpTWFwYCBpbnN0YW5jZSBmcm9tIHRoZSBnaXZlbiBvYmplY3QuXG5cdCAqIEBwYXJhbSB7IU9iamVjdH0gb2JqXG5cdCAqIEByZXR1cm4geyFNdWx0aU1hcH1cblx0ICovXG5cdHN0YXRpYyBmcm9tT2JqZWN0KG9iaikge1xuXHRcdHZhciBtYXAgPSBuZXcgTXVsdGlNYXAoKTtcblx0XHR2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRtYXAuc2V0KGtleXNbaV0sIG9ialtrZXlzW2ldXSk7XG5cdFx0fVxuXHRcdHJldHVybiBtYXA7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgZmlyc3QgYWRkZWQgdmFsdWUgZnJvbSBhIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAcmV0dXJuIHsqfVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRnZXQobmFtZSkge1xuXHRcdHZhciB2YWx1ZXMgPSB0aGlzLnZhbHVlc1tuYW1lLnRvTG93ZXJDYXNlKCldO1xuXHRcdGlmICh2YWx1ZXMpIHtcblx0XHRcdHJldHVybiB2YWx1ZXNbMF07XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYWxsIHZhbHVlcyBmcm9tIGEga2V5IG5hbWUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG5cdCAqIEByZXR1cm4ge0FycmF5LjwqPn1cblx0ICovXG5cdGdldEFsbChuYW1lKSB7XG5cdFx0cmV0dXJuIHRoaXMudmFsdWVzW25hbWUudG9Mb3dlckNhc2UoKV07XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0cnVlIGlmIHRoZSBtYXAgaXMgZW1wdHksIGZhbHNlIG90aGVyd2lzZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGlzRW1wdHkoKSB7XG5cdFx0cmV0dXJuIHRoaXMuc2l6ZSgpID09PSAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYXJyYXkgb2Yga2V5IG5hbWVzLlxuXHQgKiBAcmV0dXJuIHtBcnJheS48c3RyaW5nPn1cblx0ICovXG5cdG5hbWVzKCkge1xuXHRcdHJldHVybiBPYmplY3Qua2V5cyh0aGlzLnZhbHVlcykubWFwKChrZXkpID0+IHRoaXMua2V5c1trZXldKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCB2YWx1ZXMgZnJvbSBhIGtleSBuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRyZW1vdmUobmFtZSkge1xuXHRcdGRlbGV0ZSB0aGlzLmtleXNbbmFtZS50b0xvd2VyQ2FzZSgpXTtcblx0XHRkZWxldGUgdGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB2YWx1ZSBvZiBhIGtleSBuYW1lLiBSZWxldmFudCB0byByZXBsYWNlIHRoZSBjdXJyZW50IHZhbHVlcyB3aXRoXG5cdCAqIGEgbmV3IG9uZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHBhcmFtIHsqfSB2YWx1ZVxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXQobmFtZSwgdmFsdWUpIHtcblx0XHR0aGlzLmtleXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IG5hbWU7XG5cdFx0dGhpcy52YWx1ZXNbbmFtZS50b0xvd2VyQ2FzZSgpXSA9IFt2YWx1ZV07XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc2l6ZSBvZiB0aGUgbWFwIGtleSBuYW1lcy5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0c2l6ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5uYW1lcygpLmxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBwYXJzZWQgdmFsdWVzIGFzIGEgc3RyaW5nLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy52YWx1ZXMpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE11bHRpTWFwO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBhcnJheSB9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBHZW5lcmljIHRyZWUgbm9kZSBkYXRhIHN0cnVjdHVyZSB3aXRoIGFyYml0cmFyeSBudW1iZXIgb2YgY2hpbGQgbm9kZXMuXG4gKiBAcGFyYW0ge1Z9IHZhbHVlIFZhbHVlLlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmNsYXNzIFRyZWVOb2RlIHtcblxuXHRjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuXHRcdC8qKlxuXHRcdCAqIFRoZSB2YWx1ZS5cblx0XHQgKiBAcHJpdmF0ZSB7Vn1cblx0XHQgKi9cblx0XHR0aGlzLnZhbHVlXyA9IHZhbHVlO1xuXG5cdFx0LyoqXG5cdFx0ICogUmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgbm9kZSBvciBudWxsIGlmIGl0IGhhcyBubyBwYXJlbnQuXG5cdFx0ICogQHByaXZhdGUge1RyZWVOb2RlfVxuXHRcdCAqL1xuXHRcdHRoaXMucGFyZW50XyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBDaGlsZCBub2RlcyBvciBudWxsIGluIGNhc2Ugb2YgbGVhZiBub2RlLlxuXHRcdCAqIEBwcml2YXRlIHtBcnJheTwhVHJlZU5vZGU+fVxuXHRcdCAqL1xuXHRcdHRoaXMuY2hpbGRyZW5fID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBcHBlbmRzIGEgY2hpbGQgbm9kZSB0byB0aGlzIG5vZGUuXG5cdCAqIEBwYXJhbSB7IVRyZWVOb2RlfSBjaGlsZCBPcnBoYW4gY2hpbGQgbm9kZS5cblx0ICovXG5cdGFkZENoaWxkKGNoaWxkKSB7XG5cdFx0YXNzZXJ0Q2hpbGRIYXNOb1BhcmVudChjaGlsZCk7XG5cdFx0Y2hpbGQuc2V0UGFyZW50KHRoaXMpO1xuXHRcdHRoaXMuY2hpbGRyZW5fID0gdGhpcy5jaGlsZHJlbl8gfHwgW107XG5cdFx0dGhpcy5jaGlsZHJlbl8ucHVzaChjaGlsZCk7XG5cdH1cblxuXHQvKipcblx0ICogVGVsbHMgd2hldGhlciB0aGlzIG5vZGUgaXMgdGhlIGFuY2VzdG9yIG9mIHRoZSBnaXZlbiBub2RlLlxuXHQgKiBAcGFyYW0geyFUcmVlTm9kZX0gbm9kZSBBIG5vZGUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdGhpcyBub2RlIGlzIHRoZSBhbmNlc3RvciBvZiB7QGNvZGUgbm9kZX0uXG5cdCAqL1xuXHRjb250YWlucyhub2RlKSB7XG5cdFx0bGV0IGN1cnJlbnQgPSBub2RlLmdldFBhcmVudCgpO1xuXHRcdHdoaWxlIChjdXJyZW50KSB7XG5cdFx0XHRpZiAoY3VycmVudCA9PT0gdGhpcykge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdGN1cnJlbnQgPSBjdXJyZW50LmdldFBhcmVudCgpO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7IUFycmF5PFRyZWVOb2RlPn0gQWxsIGFuY2VzdG9yIG5vZGVzIGluIGJvdHRvbS11cCBvcmRlci5cblx0ICovXG5cdGdldEFuY2VzdG9ycygpIHtcblx0XHRsZXQgYW5jZXN0b3JzID0gW107XG5cdFx0bGV0IG5vZGUgPSB0aGlzLmdldFBhcmVudCgpO1xuXHRcdHdoaWxlIChub2RlKSB7XG5cdFx0XHRhbmNlc3RvcnMucHVzaChub2RlKTtcblx0XHRcdG5vZGUgPSBub2RlLmdldFBhcmVudCgpO1xuXHRcdH1cblx0XHRyZXR1cm4gYW5jZXN0b3JzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGNoaWxkIG5vZGUgb2YgdGhpcyBub2RlIGF0IHRoZSBnaXZlbiBpbmRleC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IENoaWxkIGluZGV4LlxuXHQgKiBAcmV0dXJuIHs/VHJlZU5vZGV9IFRoZSBub2RlIGF0IHRoZSBnaXZlbiBpbmRleFxuXHQgKiBvciBudWxsIGlmIG5vdCBmb3VuZC5cblx0ICovXG5cdGdldENoaWxkQXQoaW5kZXgpIHtcblx0XHRyZXR1cm4gdGhpcy5nZXRDaGlsZHJlbigpW2luZGV4XSB8fCBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4gez9BcnJheTwhVHJlZU5vZGU+fSBDaGlsZCBub2RlcyBvciBudWxsIGluIGNhc2Ugb2YgbGVhZiBub2RlLlxuXHQgKi9cblx0Z2V0Q2hpbGRyZW4oKSB7XG5cdFx0cmV0dXJuIHRoaXMuY2hpbGRyZW5fIHx8IFRyZWVOb2RlLkVNUFRZX0FSUkFZO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBjaGlsZHJlbi5cblx0ICovXG5cdGdldENoaWxkQ291bnQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0Q2hpbGRyZW4oKS5sZW5ndGg7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGFuY2VzdG9ycyBvZiB0aGUgbm9kZS5cblx0ICovXG5cdGdldERlcHRoKCkge1xuXHRcdGxldCBkZXB0aCA9IDA7XG5cdFx0bGV0IG5vZGUgPSB0aGlzO1xuXHRcdHdoaWxlIChub2RlLmdldFBhcmVudCgpKSB7XG5cdFx0XHRkZXB0aCsrO1xuXHRcdFx0bm9kZSA9IG5vZGUuZ2V0UGFyZW50KCk7XG5cdFx0fVxuXHRcdHJldHVybiBkZXB0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJuIHs/VHJlZU5vZGV9IFBhcmVudCBub2RlIG9yIG51bGwgaWYgaXQgaGFzIG5vIHBhcmVudC5cblx0ICovXG5cdGdldFBhcmVudCgpIHtcblx0XHRyZXR1cm4gdGhpcy5wYXJlbnRfO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4geyFUcmVlTm9kZX0gVGhlIHJvb3Qgb2YgdGhlIHRyZWUgc3RydWN0dXJlLCBpLmUuIHRoZSBmYXJ0aGVzdFxuXHQgKiBhbmNlc3RvciBvZiB0aGUgbm9kZSBvciB0aGUgbm9kZSBpdHNlbGYgaWYgaXQgaGFzIG5vIHBhcmVudHMuXG5cdCAqL1xuXHRnZXRSb290KCkge1xuXHRcdGxldCByb290ID0gdGhpcztcblx0XHR3aGlsZSAocm9vdC5nZXRQYXJlbnQoKSkge1xuXHRcdFx0cm9vdCA9IHJvb3QuZ2V0UGFyZW50KCk7XG5cdFx0fVxuXHRcdHJldHVybiByb290O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHZhbHVlLlxuXHQgKiBAcmV0dXJuIHtWfSBUaGUgdmFsdWUuXG5cdCAqL1xuXHRnZXRWYWx1ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy52YWx1ZV87XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB0aGUgbm9kZSBpcyBhIGxlYWYgbm9kZS5cblx0ICovXG5cdGlzTGVhZigpIHtcblx0XHRyZXR1cm4gIXRoaXMuZ2V0Q2hpbGRDb3VudCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGdpdmVuIGNoaWxkIG5vZGUgb2YgdGhpcyBub2RlLlxuXHQgKiBAcGFyYW0ge1RyZWVOb2RlfSBjaGlsZCBUaGUgbm9kZSB0byByZW1vdmUuXG5cdCAqIEByZXR1cm4ge1RyZWVOb2RlfSBUaGUgcmVtb3ZlZCBub2RlIGlmIGFueSwgbnVsbCBvdGhlcndpc2UuXG5cdCAqL1xuXHRyZW1vdmVDaGlsZChjaGlsZCkge1xuXHRcdGlmIChhcnJheS5yZW1vdmUodGhpcy5nZXRDaGlsZHJlbigpLCBjaGlsZCkpIHtcblx0XHRcdHJldHVybiBjaGlsZDtcblx0XHR9XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgcGFyZW50IG5vZGUgb2YgdGhpcyBub2RlLiBUaGUgY2FsbGVycyBtdXN0IGVuc3VyZSB0aGF0IHRoZVxuXHQgKiBwYXJlbnQgbm9kZSBhbmQgb25seSB0aGF0IGhhcyB0aGlzIG5vZGUgYW1vbmcgaXRzIGNoaWxkcmVuLlxuXHQgKiBAcGFyYW0ge1RyZWVOb2RlfSBwYXJlbnQgVGhlIHBhcmVudCB0byBzZXQuIElmIG51bGwsIHRoZSBub2RlIHdpbGwgYmVcblx0ICogZGV0YWNoZWQgZnJvbSB0aGUgdHJlZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0c2V0UGFyZW50KHBhcmVudCkge1xuXHRcdHRoaXMucGFyZW50XyA9IHBhcmVudDtcblx0fVxuXG5cdC8qKlxuXHQgKiBUcmF2ZXJzZXMgdGhlIHN1YnRyZWUuIFRoZSBmaXJzdCBjYWxsYmFjayBzdGFydHMgd2l0aCB0aGlzIG5vZGUsXG5cdCAqIGFuZCB2aXNpdHMgdGhlIGRlc2NlbmRhbnQgbm9kZXMgZGVwdGgtZmlyc3QsIGluIHByZW9yZGVyLlxuXHQgKiBUaGUgc2Vjb25kIGNhbGxiYWNrLCBzdGFydHMgd2l0aCBkZWVwZXN0IGNoaWxkIHRoZW4gdmlzaXRzXG5cdCAqIHRoZSBhbmNlc3RvciBub2RlcyBkZXB0aC1maXJzdCwgaW4gcG9zdG9yZGVyLiBFLmcuXG5cdCAqXG5cdCAqICBcdCBBXG5cdCAqICAgIC8gXFxcblx0ICogICBCICAgQ1xuXHQgKiAgLyAgIC8gXFxcblx0ICogRCAgIEUgICBGXG5cdCAqXG5cdCAqIHByZW9yZGVyIC0+IFsnQScsICdCJywgJ0QnLCAnQycsICdFJywgJ0YnXVxuXHQgKiBwb3N0b3JkZXIgLT4gWydEJywgJ0InLCAnRScsICdGJywgJ0MnLCAnQSddXG5cdCAqXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb249fSBvcHRfcHJlb3JkZXJGbiBUaGUgY2FsbGJhY2sgdG8gZXhlY3V0ZSB3aGVuIHZpc2l0aW5nIGEgbm9kZS5cblx0ICogQHBhcmFtIHtmdW5jdGlvbj19IG9wdF9wb3N0b3JkZXJGbiBUaGUgY2FsbGJhY2sgdG8gZXhlY3V0ZSBiZWZvcmUgbGVhdmluZyBhIG5vZGUuXG5cdCAqL1xuXHR0cmF2ZXJzZShvcHRfcHJlb3JkZXJGbiwgb3B0X3Bvc3RvcmRlckZuKSB7XG5cdFx0aWYgKG9wdF9wcmVvcmRlckZuKSB7XG5cdFx0XHRvcHRfcHJlb3JkZXJGbih0aGlzKTtcblx0XHR9XG5cdFx0dGhpcy5nZXRDaGlsZHJlbigpLmZvckVhY2goKGNoaWxkKSA9PiBjaGlsZC50cmF2ZXJzZShvcHRfcHJlb3JkZXJGbiwgb3B0X3Bvc3RvcmRlckZuKSk7XG5cdFx0aWYgKG9wdF9wb3N0b3JkZXJGbikge1xuXHRcdFx0b3B0X3Bvc3RvcmRlckZuKHRoaXMpO1xuXHRcdH1cblx0fVxuXG59XG5cbi8qKlxuICogQ29uc3RhbnQgZm9yIGVtcHR5IGFycmF5IHRvIGF2b2lkIHVubmVjZXNzYXJ5IGFsbG9jYXRpb25zLlxuICogQHByaXZhdGVcbiAqL1xuVHJlZU5vZGUuRU1QVFlfQVJSQVkgPSBbXTtcblxuLyoqXG4gKiBBc3NlcnRzIHRoYXQgY2hpbGQgaGFzIG5vIHBhcmVudC5cbiAqIEBwYXJhbSB7VHJlZU5vZGV9IGNoaWxkIEEgY2hpbGQuXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBhc3NlcnRDaGlsZEhhc05vUGFyZW50ID0gZnVuY3Rpb24oY2hpbGQpIHtcblx0aWYgKGNoaWxkLmdldFBhcmVudCgpKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYWRkIGNoaWxkIHdpdGggcGFyZW50LicpO1xuXHR9XG59O1xuXG5leHBvcnQgZGVmYXVsdCBUcmVlTm9kZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaXNEZWYsIHN0cmluZyB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBwYXJzZSBmcm9tICcuL3BhcnNlJztcbmltcG9ydCB7IE11bHRpTWFwIH0gZnJvbSAnbWV0YWwtc3RydWN0cyc7XG5cbnZhciBwYXJzZUZuXyA9IHBhcnNlO1xuXG5jbGFzcyBVcmkge1xuXG5cdC8qKlxuXHQgKiBUaGlzIGNsYXNzIGNvbnRhaW5zIHNldHRlcnMgYW5kIGdldHRlcnMgZm9yIHRoZSBwYXJ0cyBvZiB0aGUgVVJJLlxuXHQgKiBUaGUgZm9sbG93aW5nIGZpZ3VyZSBkaXNwbGF5cyBhbiBleGFtcGxlIFVSSXMgYW5kIHRoZWlyIGNvbXBvbmVudCBwYXJ0cy5cblx0ICpcblx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aFxuXHQgKlx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilIzilIDilIDilIDilLTilIDilIDilIDilIDilJBcblx0ICpcdCAgYWJjOi8vZXhhbXBsZS5jb206MTIzL3BhdGgvZGF0YT9rZXk9dmFsdWUjZnJhZ2lkMVxuXHQgKlx0ICDilJTilKzilJggICDilJTilIDilIDilIDilIDilKzilIDilIDilIDilIDilJgg4pSU4pSs4pSYICAgICAgICAgICDilJTilIDilIDilIDilKzilIDilIDilIDilJgg4pSU4pSA4pSA4pSs4pSA4pSA4pSYXG5cdCAqIHByb3RvY29sICBob3N0bmFtZSAgcG9ydCAgICAgICAgICAgIHNlYXJjaCAgICBoYXNoXG5cdCAqICAgICAgICAgIOKUlOKUgOKUgOKUgOKUgOKUgOKUgOKUrOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUmFxuXHQgKiAgICAgICAgICAgICAgICBob3N0XG5cdCAqXG5cdCAqIEBwYXJhbSB7Kj19IG9wdF91cmkgT3B0aW9uYWwgc3RyaW5nIFVSSSB0byBwYXJzZVxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKG9wdF91cmkgPSAnJykge1xuXHRcdHRoaXMudXJsID0gVXJpLnBhcnNlKHRoaXMubWF5YmVBZGRQcm90b2NvbEFuZEhvc3RuYW1lXyhvcHRfdXJpKSk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBwYXJhbWV0ZXJzIHRvIHVyaSBmcm9tIGEgPGNvZGU+TXVsdGlNYXA8L2NvZGU+IGFzIHNvdXJjZS5cblx0ICogQHBhcmFtIHtNdWx0aU1hcH0gbXVsdGltYXAgVGhlIDxjb2RlPk11bHRpTWFwPC9jb2RlPiBjb250YWluaW5nIHRoZVxuXHQgKiAgIHBhcmFtZXRlcnMuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkUGFyYW1ldGVyc0Zyb21NdWx0aU1hcChtdWx0aW1hcCkge1xuXHRcdG11bHRpbWFwLm5hbWVzKCkuZm9yRWFjaCgobmFtZSkgPT4ge1xuXHRcdFx0bXVsdGltYXAuZ2V0QWxsKG5hbWUpLmZvckVhY2goKHZhbHVlKSA9PiB7XG5cdFx0XHRcdHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyB0aGUgdmFsdWUgb2YgdGhlIG5hbWVkIHF1ZXJ5IHBhcmFtZXRlcnMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIHBhcmFtZXRlciB0byBzZXQuXG5cdCAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG5ldyB2YWx1ZS4gV2lsbCBiZSBleHBsaWNpdGx5IGNhc3RlZCB0byBTdHJpbmcuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZFBhcmFtZXRlclZhbHVlKG5hbWUsIHZhbHVlKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdGlmIChpc0RlZih2YWx1ZSkpIHtcblx0XHRcdHZhbHVlID0gU3RyaW5nKHZhbHVlKTtcblx0XHR9XG5cdFx0dGhpcy5xdWVyeS5hZGQobmFtZSwgdmFsdWUpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIHZhbHVlcyBvZiB0aGUgbmFtZWQgcXVlcnkgcGFyYW1ldGVyLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZFBhcmFtZXRlclZhbHVlcyhuYW1lLCB2YWx1ZXMpIHtcblx0XHR2YWx1ZXMuZm9yRWFjaCgodmFsdWUpID0+IHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBFbnN1cmVzIHF1ZXJ5IGludGVybmFsIG1hcCBpcyBpbml0aWFsaXplZCBhbmQgc3luY2VkIHdpdGggaW5pdGlhbCB2YWx1ZVxuXHQgKiBleHRyYWN0ZWQgZnJvbSBVUkkgc2VhcmNoIHBhcnQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCkge1xuXHRcdGlmICh0aGlzLnF1ZXJ5KSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMucXVlcnkgPSBuZXcgTXVsdGlNYXAoKTtcblx0XHR2YXIgc2VhcmNoID0gdGhpcy51cmwuc2VhcmNoO1xuXHRcdGlmIChzZWFyY2gpIHtcblx0XHRcdHNlYXJjaC5zdWJzdHJpbmcoMSkuc3BsaXQoJyYnKS5mb3JFYWNoKChwYXJhbSkgPT4ge1xuXHRcdFx0XHR2YXIgW2tleSwgdmFsdWVdID0gcGFyYW0uc3BsaXQoJz0nKTtcblx0XHRcdFx0aWYgKGlzRGVmKHZhbHVlKSkge1xuXHRcdFx0XHRcdHZhbHVlID0gVXJpLnVybERlY29kZSh2YWx1ZSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5hZGRQYXJhbWV0ZXJWYWx1ZShrZXksIHZhbHVlKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBoYXNoIHBhcnQgb2YgdXJpLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRIYXNoKCkge1xuXHRcdHJldHVybiB0aGlzLnVybC5oYXNoIHx8ICcnO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGhvc3QgcGFydCBvZiB1cmkuIEUuZy4gPGNvZGU+W2hvc3RuYW1lXTpbcG9ydF08L2NvZGU+LlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRIb3N0KCkge1xuXHRcdHZhciBob3N0ID0gdGhpcy5nZXRIb3N0bmFtZSgpO1xuXHRcdGlmIChob3N0KSB7XG5cdFx0XHR2YXIgcG9ydCA9IHRoaXMuZ2V0UG9ydCgpO1xuXHRcdFx0aWYgKHBvcnQgJiYgcG9ydCAhPT0gJzgwJykge1xuXHRcdFx0XHRob3N0ICs9ICc6JyArIHBvcnQ7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBob3N0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGhvc3RuYW1lIHBhcnQgb2YgdXJpIHdpdGhvdXQgcHJvdG9jb2wgYW5kIHBvcnQuXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldEhvc3RuYW1lKCkge1xuXHRcdHZhciBob3N0bmFtZSA9IHRoaXMudXJsLmhvc3RuYW1lO1xuXHRcdGlmIChob3N0bmFtZSA9PT0gVXJpLkhPU1ROQU1FX1BMQUNFSE9MREVSKSB7XG5cdFx0XHRyZXR1cm4gJyc7XG5cdFx0fVxuXHRcdHJldHVybiBob3N0bmFtZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBvcmlnaW4gcGFydCBvZiB1cmkuIEUuZy4gPGNvZGU+aHR0cDovL1tob3N0bmFtZV06W3BvcnRdPC9jb2RlPi5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0T3JpZ2luKCkge1xuXHRcdHZhciBob3N0ID0gdGhpcy5nZXRIb3N0KCk7XG5cdFx0aWYgKGhvc3QpIHtcblx0XHRcdHJldHVybiB0aGlzLmdldFByb3RvY29sKCkgKyAnLy8nICsgaG9zdDtcblx0XHR9XG5cdFx0cmV0dXJuICcnO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGZpcnN0IHZhbHVlIGZvciBhIGdpdmVuIHBhcmFtZXRlciBvciB1bmRlZmluZWQgaWYgdGhlIGdpdmVuXG5cdCAqIHBhcmFtZXRlciBuYW1lIGRvZXMgbm90IGFwcGVhciBpbiB0aGUgcXVlcnkgc3RyaW5nLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGFyYW1OYW1lIFVuZXNjYXBlZCBwYXJhbWV0ZXIgbmFtZS5cblx0ICogQHJldHVybiB7c3RyaW5nfHVuZGVmaW5lZH0gVGhlIGZpcnN0IHZhbHVlIGZvciBhIGdpdmVuIHBhcmFtZXRlciBvclxuXHQgKiAgIHVuZGVmaW5lZCBpZiB0aGUgZ2l2ZW4gcGFyYW1ldGVyIG5hbWUgZG9lcyBub3QgYXBwZWFyIGluIHRoZSBxdWVyeVxuXHQgKiAgIHN0cmluZy5cblx0ICovXG5cdGdldFBhcmFtZXRlclZhbHVlKG5hbWUpIHtcblx0XHR0aGlzLmVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCk7XG5cdFx0cmV0dXJuIHRoaXMucXVlcnkuZ2V0KG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHZhbHVlPGI+czwvYj4gZm9yIGEgZ2l2ZW4gcGFyYW1ldGVyIGFzIGEgbGlzdCBvZiBkZWNvZGVkXG5cdCAqIHF1ZXJ5IHBhcmFtZXRlciB2YWx1ZXMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBwYXJhbWV0ZXIgdG8gZ2V0IHZhbHVlcyBmb3IuXG5cdCAqIEByZXR1cm4geyFBcnJheTw/Pn0gVGhlIHZhbHVlcyBmb3IgYSBnaXZlbiBwYXJhbWV0ZXIgYXMgYSBsaXN0IG9mIGRlY29kZWRcblx0ICogICBxdWVyeSBwYXJhbWV0ZXIgdmFsdWVzLlxuXHQgKi9cblx0Z2V0UGFyYW1ldGVyVmFsdWVzKG5hbWUpIHtcblx0XHR0aGlzLmVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfKCk7XG5cdFx0cmV0dXJuIHRoaXMucXVlcnkuZ2V0QWxsKG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIG5hbWU8Yj5zPC9iPiBvZiB0aGUgcGFyYW1ldGVycy5cblx0ICogQHJldHVybiB7IUFycmF5PHN0cmluZz59IFRoZSBuYW1lcyBmb3IgdGhlIHBhcmFtZXRlcnMgYXMgYSBsaXN0IG9mXG5cdCAqICAgc3RyaW5ncy5cblx0ICovXG5cdGdldFBhcmFtZXRlck5hbWVzKCkge1xuXHRcdHRoaXMuZW5zdXJlUXVlcnlJbml0aWFsaXplZF8oKTtcblx0XHRyZXR1cm4gdGhpcy5xdWVyeS5uYW1lcygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGZ1bmN0aW9uIGN1cnJlbnRseSBiZWluZyB1c2VkIHRvIHBhcnNlIFVSSXMuXG5cdCAqIEByZXR1cm4geyFmdW5jdGlvbigpfVxuXHQgKi9cblx0c3RhdGljIGdldFBhcnNlRm4oKSB7XG5cdFx0cmV0dXJuIHBhcnNlRm5fO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHBhdGhuYW1lIHBhcnQgb2YgdXJpLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRQYXRobmFtZSgpIHtcblx0XHRyZXR1cm4gdGhpcy51cmwucGF0aG5hbWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcG9ydCBudW1iZXIgcGFydCBvZiB1cmkgYXMgc3RyaW5nLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRQb3J0KCkge1xuXHRcdHJldHVybiB0aGlzLnVybC5wb3J0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHByb3RvY29sIHBhcnQgb2YgdXJpLiBFLmcuIDxjb2RlPmh0dHA6PC9jb2RlPi5cblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0UHJvdG9jb2woKSB7XG5cdFx0cmV0dXJuIHRoaXMudXJsLnByb3RvY29sO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHNlYXJjaCBwYXJ0IG9mIHVyaS4gU2VhcmNoIHZhbHVlIGlzIHJldHJpZXZlZCBmcm9tIHF1ZXJ5XG5cdCAqIHBhcmFtZXRlcnMuXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldFNlYXJjaCgpIHtcblx0XHR2YXIgc2VhcmNoID0gJyc7XG5cdFx0dmFyIHF1ZXJ5c3RyaW5nID0gJyc7XG5cdFx0dGhpcy5nZXRQYXJhbWV0ZXJOYW1lcygpLmZvckVhY2goKG5hbWUpID0+IHtcblx0XHRcdHRoaXMuZ2V0UGFyYW1ldGVyVmFsdWVzKG5hbWUpLmZvckVhY2goKHZhbHVlKSA9PiB7XG5cdFx0XHRcdHF1ZXJ5c3RyaW5nICs9IG5hbWU7XG5cdFx0XHRcdGlmIChpc0RlZih2YWx1ZSkpIHtcblx0XHRcdFx0XHRxdWVyeXN0cmluZyArPSAnPScgKyBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHF1ZXJ5c3RyaW5nICs9ICcmJztcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHRcdHF1ZXJ5c3RyaW5nID0gcXVlcnlzdHJpbmcuc2xpY2UoMCwgLTEpO1xuXHRcdGlmIChxdWVyeXN0cmluZykge1xuXHRcdFx0c2VhcmNoICs9ICc/JyArIHF1ZXJ5c3RyaW5nO1xuXHRcdH1cblx0XHRyZXR1cm4gc2VhcmNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB1cmkgY29udGFpbnMgdGhlIHBhcmFtZXRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGhhc1BhcmFtZXRlcihuYW1lKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdHJldHVybiB0aGlzLnF1ZXJ5LmNvbnRhaW5zKG5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIHRoaXMgVVJMIHVuaXF1ZSBieSBhZGRpbmcgYSByYW5kb20gcGFyYW0gdG8gaXQuIFVzZWZ1bCBmb3IgYXZvaWRpbmdcblx0ICogY2FjaGUuXG5cdCAqL1xuXHRtYWtlVW5pcXVlKCkge1xuXHRcdHRoaXMuc2V0UGFyYW1ldGVyVmFsdWUoVXJpLlJBTkRPTV9QQVJBTSwgc3RyaW5nLmdldFJhbmRvbVN0cmluZygpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSBhZGRzIHByb3RvY29sIGFuZCBhIGhvc3RuYW1lIHBsYWNlaG9sZGVyIG9uIGEgcGFyaWFsIFVSSSBpZiBuZWVkZWQuXG5cdCAqIFJlbGV2ZW50IGZvciBjb21wYXRpYmlsaXR5IHdpdGggPGNvZGU+VVJMPC9jb2RlPiBuYXRpdmUgb2JqZWN0LlxuXHQgKiBAcGFyYW0ge3N0cmluZz19IG9wdF91cmlcblx0ICogQHJldHVybiB7c3RyaW5nfSBVUkkgd2l0aCBwcm90b2NvbCBhbmQgaG9zdG5hbWUgcGxhY2Vob2xkZXIuXG5cdCAqL1xuXHRtYXliZUFkZFByb3RvY29sQW5kSG9zdG5hbWVfKG9wdF91cmkpIHtcblx0XHR2YXIgdXJsID0gb3B0X3VyaTtcblx0XHRpZiAob3B0X3VyaS5pbmRleE9mKCc6Ly8nKSA9PT0gLTEgJiZcblx0XHRcdG9wdF91cmkuaW5kZXhPZignamF2YXNjcmlwdDonKSAhPT0gMCkgeyAvLyBqc2hpbnQgaWdub3JlOmxpbmVcblxuXHRcdFx0dXJsID0gVXJpLkRFRkFVTFRfUFJPVE9DT0w7XG5cdFx0XHRpZiAob3B0X3VyaVswXSAhPT0gJy8nIHx8IG9wdF91cmlbMV0gIT09ICcvJykge1xuXHRcdFx0XHR1cmwgKz0gJy8vJztcblx0XHRcdH1cblxuXHRcdFx0c3dpdGNoIChvcHRfdXJpLmNoYXJBdCgwKSkge1xuXHRcdFx0XHRjYXNlICcuJzpcblx0XHRcdFx0Y2FzZSAnPyc6XG5cdFx0XHRcdGNhc2UgJyMnOlxuXHRcdFx0XHRcdHVybCArPSBVcmkuSE9TVE5BTUVfUExBQ0VIT0xERVI7XG5cdFx0XHRcdFx0dXJsICs9ICcvJztcblx0XHRcdFx0XHR1cmwgKz0gb3B0X3VyaTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnJzpcblx0XHRcdFx0Y2FzZSAnLyc6XG5cdFx0XHRcdFx0aWYgKG9wdF91cmlbMV0gIT09ICcvJykge1xuXHRcdFx0XHRcdFx0dXJsICs9IFVyaS5IT1NUTkFNRV9QTEFDRUhPTERFUjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dXJsICs9IG9wdF91cmk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0dXJsICs9IG9wdF91cmk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB1cmw7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2VzIHRoZSBnaXZlbiB1cmkgc3RyaW5nIGludG8gYW4gb2JqZWN0LlxuXHQgKiBAcGFyYW0geyo9fSBvcHRfdXJpIE9wdGlvbmFsIHN0cmluZyBVUkkgdG8gcGFyc2Vcblx0ICovXG5cdHN0YXRpYyBwYXJzZShvcHRfdXJpKSB7XG5cdFx0cmV0dXJuIHBhcnNlRm5fKG9wdF91cmkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIG5hbWVkIHF1ZXJ5IHBhcmFtZXRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIHBhcmFtZXRlciB0byByZW1vdmUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHJlbW92ZVBhcmFtZXRlcihuYW1lKSB7XG5cdFx0dGhpcy5lbnN1cmVRdWVyeUluaXRpYWxpemVkXygpO1xuXHRcdHRoaXMucXVlcnkucmVtb3ZlKG5hbWUpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdW5pcXVlbmVzcyBwYXJhbWV0ZXIgb2YgdGhlIHVyaS5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0cmVtb3ZlVW5pcXVlKCkge1xuXHRcdHRoaXMucmVtb3ZlUGFyYW1ldGVyKFVyaS5SQU5ET01fUEFSQU0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGhhc2guXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBoYXNoXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldEhhc2goaGFzaCkge1xuXHRcdHRoaXMudXJsLmhhc2ggPSBoYXNoO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGhvc3RuYW1lLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaG9zdG5hbWVcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0c2V0SG9zdG5hbWUoaG9zdG5hbWUpIHtcblx0XHR0aGlzLnVybC5ob3N0bmFtZSA9IGhvc3RuYW1lO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHZhbHVlIG9mIHRoZSBuYW1lZCBxdWVyeSBwYXJhbWV0ZXJzLCBjbGVhcmluZyBwcmV2aW91cyB2YWx1ZXNcblx0ICogZm9yIHRoYXQga2V5LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFBhcmFtZXRlclZhbHVlKG5hbWUsIHZhbHVlKSB7XG5cdFx0dGhpcy5yZW1vdmVQYXJhbWV0ZXIobmFtZSk7XG5cdFx0dGhpcy5hZGRQYXJhbWV0ZXJWYWx1ZShuYW1lLCB2YWx1ZSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgdmFsdWVzIG9mIHRoZSBuYW1lZCBxdWVyeSBwYXJhbWV0ZXJzLCBjbGVhcmluZyBwcmV2aW91cyB2YWx1ZXNcblx0ICogZm9yIHRoYXQga2V5LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwYXJhbWV0ZXIgdG8gc2V0LlxuXHQgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFBhcmFtZXRlclZhbHVlcyhuYW1lLCB2YWx1ZXMpIHtcblx0XHR0aGlzLnJlbW92ZVBhcmFtZXRlcihuYW1lKTtcblx0XHR2YWx1ZXMuZm9yRWFjaCgodmFsdWUpID0+IHRoaXMuYWRkUGFyYW1ldGVyVmFsdWUobmFtZSwgdmFsdWUpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwYXRobmFtZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGhuYW1lXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdHNldFBhdGhuYW1lKHBhdGhuYW1lKSB7XG5cdFx0dGhpcy51cmwucGF0aG5hbWUgPSBwYXRobmFtZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwb3J0IG51bWJlci5cblx0ICogQHBhcmFtIHsqfSBwb3J0IFBvcnQgbnVtYmVyLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRzZXRQb3J0KHBvcnQpIHtcblx0XHR0aGlzLnVybC5wb3J0ID0gcG9ydDtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgcGFyc2luZyB0aGUgb3JpZ2luYWwgc3RyaW5nIHVyaVxuXHQgKiBpbnRvIGFuIG9iamVjdC5cblx0ICogQHBhcmFtIHshZnVuY3Rpb24oKX0gcGFyc2VGblxuXHQgKi9cblx0c3RhdGljIHNldFBhcnNlRm4ocGFyc2VGbikge1xuXHRcdHBhcnNlRm5fID0gcGFyc2VGbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwcm90b2NvbC4gSWYgbWlzc2luZyA8Y29kZT5odHRwOjwvY29kZT4gaXMgdXNlZCBhcyBkZWZhdWx0LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcHJvdG9jb2xcblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0c2V0UHJvdG9jb2wocHJvdG9jb2wpIHtcblx0XHR0aGlzLnVybC5wcm90b2NvbCA9IHByb3RvY29sO1xuXHRcdGlmICh0aGlzLnVybC5wcm90b2NvbFt0aGlzLnVybC5wcm90b2NvbC5sZW5ndGggLSAxXSAhPT0gJzonKSB7XG5cdFx0XHR0aGlzLnVybC5wcm90b2NvbCArPSAnOic7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHN0cmluZyBmb3JtIG9mIHRoZSB1cmwuXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0dG9TdHJpbmcoKSB7XG5cdFx0dmFyIGhyZWYgPSAnJztcblx0XHR2YXIgaG9zdCA9IHRoaXMuZ2V0SG9zdCgpO1xuXHRcdGlmIChob3N0KSB7XG5cdFx0XHRocmVmICs9IHRoaXMuZ2V0UHJvdG9jb2woKSArICcvLyc7XG5cdFx0fVxuXHRcdGhyZWYgKz0gaG9zdCArIHRoaXMuZ2V0UGF0aG5hbWUoKSArIHRoaXMuZ2V0U2VhcmNoKCkgKyB0aGlzLmdldEhhc2goKTtcblx0XHRyZXR1cm4gaHJlZjtcblx0fVxuXG5cdC8qKlxuXHQgKiBKb2lucyB0aGUgZ2l2ZW4gcGF0aHMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlUGF0aFxuXHQgKiBAcGFyYW0gey4uLnN0cmluZ30gLi4ucGF0aHMgQW55IG51bWJlciBvZiBwYXRocyB0byBiZSBqb2luZWQgd2l0aCB0aGUgYmFzZSB1cmwuXG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBqb2luUGF0aHMoYmFzZVBhdGgsIC4uLnBhdGhzKSB7XG5cdFx0aWYgKGJhc2VQYXRoLmNoYXJBdChiYXNlUGF0aC5sZW5ndGggLSAxKSA9PT0gJy8nKSB7XG5cdFx0XHRiYXNlUGF0aCA9IGJhc2VQYXRoLnN1YnN0cmluZygwLCBiYXNlUGF0aC5sZW5ndGggLSAxKTtcblx0XHR9XG5cdFx0cGF0aHMgPSBwYXRocy5tYXAocGF0aCA9PiBwYXRoLmNoYXJBdCgwKSA9PT0gJy8nID8gcGF0aC5zdWJzdHJpbmcoMSkgOiBwYXRoKTtcblx0XHRyZXR1cm4gW2Jhc2VQYXRoXS5jb25jYXQocGF0aHMpLmpvaW4oJy8nKS5yZXBsYWNlKC9cXC8kLywgJycpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVSTC1kZWNvZGVzIHRoZSBzdHJpbmcuIFdlIG5lZWQgdG8gc3BlY2lhbGx5IGhhbmRsZSAnKydzIGJlY2F1c2Vcblx0ICogdGhlIGphdmFzY3JpcHQgbGlicmFyeSBkb2Vzbid0IGNvbnZlcnQgdGhlbSB0byBzcGFjZXMuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byB1cmwgZGVjb2RlLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBkZWNvZGVkIHtAY29kZSBzdHJ9LlxuXHQgKi9cblx0c3RhdGljIHVybERlY29kZShzdHIpIHtcblx0XHRyZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHN0ci5yZXBsYWNlKC9cXCsvZywgJyAnKSk7XG5cdH1cblxufVxuXG4vKipcbiAqIERlZmF1bHQgcHJvdG9jb2wgdmFsdWUuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgaHR0cDpcbiAqIEBzdGF0aWNcbiAqL1xuY29uc3QgaXNTZWN1cmUgPSAoKSA9PlxuXHQodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiZcblx0XHR3aW5kb3cubG9jYXRpb24gJiZcblx0XHR3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgJiZcblx0XHR3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wuaW5kZXhPZignaHR0cHMnKSA9PT0gMCk7XG5cblVyaS5ERUZBVUxUX1BST1RPQ09MID0gaXNTZWN1cmUoKSA/ICdodHRwczonIDogJ2h0dHA6JztcblxuLyoqXG4gKiBIb3N0bmFtZSBwbGFjZWhvbGRlci4gUmVsZXZhbnQgdG8gaW50ZXJuYWwgdXNhZ2Ugb25seS5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cblVyaS5IT1NUTkFNRV9QTEFDRUhPTERFUiA9ICdob3N0bmFtZScgKyBEYXRlLm5vdygpO1xuXG4vKipcbiAqIE5hbWUgdXNlZCBieSB0aGUgcGFyYW0gZ2VuZXJhdGVkIGJ5IGBtYWtlVW5pcXVlYC5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cblVyaS5SQU5ET01fUEFSQU0gPSAnengnO1xuXG5leHBvcnQgZGVmYXVsdCBVcmk7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgVXJpIGZyb20gJ21ldGFsLXVyaSc7XG5cbi8qKlxuICogQSBjb2xsZWN0aW9uIG9mIHN0YXRpYyB1dGlsaXR5IGZ1bmN0aW9ucy5cbiAqIEBjb25zdFxuICovXG5jbGFzcyB1dGlscyB7XG5cblx0LyoqXG5cdCAqIENvcGllcyBhdHRyaWJ1dGVzIGZvcm0gc291cmNlIG5vZGUgdG8gdGFyZ2V0IG5vZGUuXG5cdCAqIEByZXR1cm4ge3ZvaWR9XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBjb3B5Tm9kZUF0dHJpYnV0ZXMoc291cmNlLCB0YXJnZXQpIHtcblx0XHRBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChzb3VyY2UuYXR0cmlidXRlcykuZm9yRWFjaCgoYXR0cmlidXRlKSA9PiB0YXJnZXQuc2V0QXR0cmlidXRlKGF0dHJpYnV0ZS5uYW1lLCBhdHRyaWJ1dGUudmFsdWUpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjdXJyZW50IGJyb3dzZXIgcGF0aCBpbmNsdWRpbmcgaGFzaGJhbmcuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBnZXRDdXJyZW50QnJvd3NlclBhdGgoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0Q3VycmVudEJyb3dzZXJQYXRoV2l0aG91dEhhc2goKSArIGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgY3VycmVudCBicm93c2VyIHBhdGggZXhjbHVkaW5nIGhhc2hiYW5nLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0Q3VycmVudEJyb3dzZXJQYXRoV2l0aG91dEhhc2goKSB7XG5cdFx0cmV0dXJuIGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnBhdGhuYW1lICsgZ2xvYmFscy53aW5kb3cubG9jYXRpb24uc2VhcmNoO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGdpdmVuIG5vZGUgb2Zmc2V0IGNvb3JkaW5hdGVzLlxuXHQgKiBAcmV0dXJuIHshb2JqZWN0fVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0Tm9kZU9mZnNldChub2RlKSB7XG5cdFx0bGV0IFtvZmZzZXRMZWZ0LCBvZmZzZXRUb3BdID0gWzAsIDBdO1xuXHRcdGRvIHtcblx0XHRcdG9mZnNldExlZnQgKz0gbm9kZS5vZmZzZXRMZWZ0O1xuXHRcdFx0b2Zmc2V0VG9wICs9IG5vZGUub2Zmc2V0VG9wO1xuXHRcdFx0bm9kZSA9IG5vZGUub2Zmc2V0UGFyZW50O1xuXHRcdH0gd2hpbGUgKG5vZGUpO1xuXHRcdHJldHVybiB7XG5cdFx0XHRvZmZzZXRMZWZ0LFxuXHRcdFx0b2Zmc2V0VG9wXG5cdFx0fTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFeHRyYWN0cyB0aGUgcGF0aCBwYXJ0IG9mIGFuIHVybC5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldFVybFBhdGgodXJsKSB7XG5cdFx0dmFyIHVyaSA9IG5ldyBVcmkodXJsKTtcblx0XHRyZXR1cm4gdXJpLmdldFBhdGhuYW1lKCkgKyB1cmkuZ2V0U2VhcmNoKCkgKyB1cmkuZ2V0SGFzaCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIHRoZSBwYXRoIHBhcnQgb2YgYW4gdXJsIHdpdGhvdXQgaGFzaGJhbmcuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBnZXRVcmxQYXRoV2l0aG91dEhhc2godXJsKSB7XG5cdFx0dmFyIHVyaSA9IG5ldyBVcmkodXJsKTtcblx0XHRyZXR1cm4gdXJpLmdldFBhdGhuYW1lKCkgKyB1cmkuZ2V0U2VhcmNoKCk7XG5cdH1cblxuXHQvKipcblx0ICogRXh0cmFjdHMgdGhlIHBhdGggcGFydCBvZiBhbiB1cmwgd2l0aG91dCBoYXNoYmFuZyBhbmQgcXVlcnkgc2VhcmNoLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgZ2V0VXJsUGF0aFdpdGhvdXRIYXNoQW5kU2VhcmNoKHVybCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHVybCk7XG5cdFx0cmV0dXJuIHVyaS5nZXRQYXRobmFtZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB1cmwgaXMgaW4gdGhlIHNhbWUgYnJvd3NlciBjdXJyZW50IHVybCBleGNsdWRpbmcgdGhlIGhhc2hiYW5nLlxuXHQgKiBAcGFyYW0gIHshc3RyaW5nfSB1cmxcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGlzQ3VycmVudEJyb3dzZXJQYXRoKHVybCkge1xuXHRcdGlmICh1cmwpIHtcblx0XHRcdGNvbnN0IGN1cnJlbnRCcm93c2VyUGF0aCA9IHRoaXMuZ2V0Q3VycmVudEJyb3dzZXJQYXRoV2l0aG91dEhhc2goKTtcblx0XHRcdC8vIHRoZSBnZXRVcmxQYXRoIHdpbGwgY3JlYXRlIGEgVXJpIGFuZCB3aWxsIG5vcm1hbGl6ZSB0aGUgcGF0aCBhbmRcblx0XHRcdC8vIHJlbW92ZSB0aGUgdHJhaWxsaW5nICcvJyBmb3IgcHJvcGVybHkgY29tcGFyaW5nIHBhdGhzLlxuXHRcdFx0cmV0dXJuIHV0aWxzLmdldFVybFBhdGhXaXRob3V0SGFzaCh1cmwpID09PSB0aGlzLmdldFVybFBhdGgoY3VycmVudEJyb3dzZXJQYXRoKTtcblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiBIVE1MNSBIaXN0b3J5IGFwaSBpcyBzdXBwb3J0ZWQuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBpc0h0bWw1SGlzdG9yeVN1cHBvcnRlZCgpIHtcblx0XHRyZXR1cm4gISEoZ2xvYmFscy53aW5kb3cuaGlzdG9yeSAmJiBnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnB1c2hTdGF0ZSk7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIGEgZ2l2ZW4gdXJsIGlzIGEgdmFsaWQgaHR0cChzKSB1cmkgYW5kIHJldHVybnMgdGhlIGZvcm1lZCBVcmlcblx0ICogb3IgZmFsc2UgaWYgdGhlIHBhcnNpbmcgZmFpbGVkXG5cdCAqIEByZXR1cm4ge1VyaXxib29sZWFufVxuXHQgKiBAc3RhdGljXG5cdCAqL1xuXHRzdGF0aWMgaXNXZWJVcmkodXJsKSB7XG5cdFx0dHJ5IHtcblx0XHRcdHJldHVybiBuZXcgVXJpKHVybCk7XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRjb25zb2xlLmVycm9yKGAke2Vyci5tZXNzYWdlfSAke3VybH1gKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhbGwgYXR0cmlidXRlcyBmb3JtIG5vZGUuXG5cdCAqIEByZXR1cm4ge3ZvaWR9XG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBjbGVhck5vZGVBdHRyaWJ1dGVzKG5vZGUpIHtcblx0XHRBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChub2RlLmF0dHJpYnV0ZXMpLmZvckVhY2goKGF0dHJpYnV0ZSkgPT4gbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0cmlidXRlLm5hbWUpKTtcblx0fVxuXG5cdC8qKlxuXHQqIFJlbW92ZXMgdHJhaWxpbmcgc2xhc2ggaW4gcGF0aC5cblx0KiBAcGFyYW0geyFzdHJpbmd9XG5cdCogQHJldHVybiB7c3RyaW5nfVxuXHQqL1xuXHRzdGF0aWMgcmVtb3ZlUGF0aFRyYWlsaW5nU2xhc2gocGF0aCkge1xuXHRcdHZhciBsZW5ndGggPSBwYXRoID8gcGF0aC5sZW5ndGggOiAwO1xuXHRcdGlmIChsZW5ndGggPiAxICYmIHBhdGhbbGVuZ3RoIC0gMV0gPT09ICcvJykge1xuXHRcdFx0cGF0aCA9IHBhdGguc3Vic3RyKDAsIGxlbmd0aCAtIDEpO1xuXHRcdH1cblx0XHRyZXR1cm4gcGF0aDtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCB1dGlscztcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0IGRlZmF1bHQge1xuXHRiYXNlUGF0aDogJ2RhdGEtc2VubmEtYmFzZS1wYXRoJyxcblx0bGlua1NlbGVjdG9yOiAnZGF0YS1zZW5uYS1saW5rLXNlbGVjdG9yJyxcblx0bG9hZGluZ0Nzc0NsYXNzOiAnZGF0YS1zZW5uYS1sb2FkaW5nLWNzcy1jbGFzcycsXG5cdHNlbm5hOiAnZGF0YS1zZW5uYScsXG5cdGRpc3BhdGNoOiAnZGF0YS1zZW5uYS1kaXNwYXRjaCcsXG5cdHN1cmZhY2U6ICdkYXRhLXNlbm5hLXN1cmZhY2UnLFxuXHR1cGRhdGVTY3JvbGxQb3NpdGlvbjogJ2RhdGEtc2VubmEtdXBkYXRlLXNjcm9sbC1wb3NpdGlvbidcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG5jb25zdCBNRVRBTF9EQVRBID0gJ19fbWV0YWxfZGF0YV9fJztcblxuY2xhc3MgZG9tRGF0YSB7XG5cdC8qKlxuXHQgKiBHZXRzIE1ldGFsLmpzJ3MgZGF0YSBmb3IgdGhlIGdpdmVuIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHBhcmFtIHtzdHJpbmc9fSBvcHRfbmFtZSBPcHRpb25hbCBwcm9wZXJ0eSBmcm9tIHRoZSBkYXRhIHRvIGJlIHJldHVybmVkLlxuXHQgKiBAcGFyYW0geyp9IG9wdF9pbml0aWFsVmFsIE9wdGluYWwgdmFsdWUgdG8gdGhlIHNldCB0aGUgcmVxdWVzdGVkIHByb3BlcnR5XG5cdCAqICAgICB0byBpZiBpdCBkb2Vzbid0IGV4aXN0IHlldCBpbiB0aGUgZGF0YS5cblx0ICogQHJldHVybiB7IU9iamVjdH1cblx0ICovXG5cdHN0YXRpYyBnZXQoZWxlbWVudCwgb3B0X25hbWUsIG9wdF9pbml0aWFsVmFsKSB7XG5cdFx0aWYgKCFlbGVtZW50W01FVEFMX0RBVEFdKSB7XG5cdFx0XHRlbGVtZW50W01FVEFMX0RBVEFdID0ge307XG5cdFx0fVxuXHRcdGlmICghb3B0X25hbWUpIHtcblx0XHRcdHJldHVybiBlbGVtZW50W01FVEFMX0RBVEFdO1xuXHRcdH1cblx0XHRpZiAoIWVsZW1lbnRbTUVUQUxfREFUQV1bb3B0X25hbWVdICYmIG9wdF9pbml0aWFsVmFsKSB7XG5cdFx0XHRlbGVtZW50W01FVEFMX0RBVEFdW29wdF9uYW1lXSA9IG9wdF9pbml0aWFsVmFsO1xuXHRcdH1cblx0XHRyZXR1cm4gZWxlbWVudFtNRVRBTF9EQVRBXVtvcHRfbmFtZV07XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IGhhcyBkYXRhIHN0b3JlZCBpbiBpdC5cblx0ICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0c3RhdGljIGhhcyhlbGVtZW50KSB7XG5cdFx0cmV0dXJuICEhZWxlbWVudFtNRVRBTF9EQVRBXTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBkb21EYXRhO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlIH0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEV2ZW50SGFuZGxlIHV0aWxpdHkuIEhvbGRzIGluZm9ybWF0aW9uIGFib3V0IGFuIGV2ZW50IHN1YnNjcmlwdGlvbiwgYW5kXG4gKiBhbGxvd3MgcmVtb3ZpbmcgdGhlbSBlYXNpbHkuXG4gKiBFdmVudEhhbmRsZSBpcyBhIERpc3Bvc2FibGUsIGJ1dCBpdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgdGhlXG4gKiBFdmVudEVtaXR0ZXIgdGhhdCBjcmVhdGVkIGl0IGlzIG5vdCB0aGUgb25lIHJlc3BvbnNpYmxlIGZvciBkaXNwb3NpbmcgaXQuXG4gKiBUaGF0IHJlc3BvbnNpYmlsaXR5IGlzIGZvciB0aGUgY29kZSB0aGF0IGhvbGRzIGEgcmVmZXJlbmNlIHRvIGl0LlxuICogQHBhcmFtIHshRXZlbnRFbWl0dGVyfSBlbWl0dGVyIEVtaXR0ZXIgdGhlIGV2ZW50IHdhcyBzdWJzY3JpYmVkIHRvLlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50IFRoZSBuYW1lIG9mIHRoZSBldmVudCB0aGF0IHdhcyBzdWJzY3JpYmVkIHRvLlxuICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cbiAqIEBjb25zdHJ1Y3RvclxuICogQGV4dGVuZHMge0Rpc3Bvc2FibGV9XG4gKi9cbmNsYXNzIEV2ZW50SGFuZGxlIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cdGNvbnN0cnVjdG9yKGVtaXR0ZXIsIGV2ZW50LCBsaXN0ZW5lcikge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgRXZlbnRFbWl0dGVyIGluc3RhbmNlIHRoYXQgdGhlIGV2ZW50IHdhcyBzdWJzY3JpYmVkIHRvLlxuXHRcdCAqIEB0eXBlIHtFdmVudEVtaXR0ZXJ9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZW1pdHRlcl8gPSBlbWl0dGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRoYXQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdFx0ICogQHR5cGUge3N0cmluZ31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ldmVudF8gPSBldmVudDtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0XHQgKiBAdHlwZSB7RnVuY3Rpb259XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMubGlzdGVuZXJfID0gbGlzdGVuZXI7XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0dGhpcy5lbWl0dGVyXyA9IG51bGw7XG5cdFx0dGhpcy5saXN0ZW5lcl8gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGxpc3RlbmVyIHN1YnNjcmlwdGlvbiBmcm9tIHRoZSBlbWl0dGVyLlxuXHQgKi9cblx0cmVtb3ZlTGlzdGVuZXIoKSB7XG5cdFx0aWYgKCF0aGlzLmVtaXR0ZXJfLmlzRGlzcG9zZWQoKSkge1xuXHRcdFx0dGhpcy5lbWl0dGVyXy5yZW1vdmVMaXN0ZW5lcih0aGlzLmV2ZW50XywgdGhpcy5saXN0ZW5lcl8pO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEhhbmRsZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgYXJyYXksIERpc3Bvc2FibGUsIGlzRnVuY3Rpb24sIGlzU3RyaW5nIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IEV2ZW50SGFuZGxlIGZyb20gJy4vRXZlbnRIYW5kbGUnO1xuXG5jb25zdCBzaW5nbGVBcnJheV8gPSBbMF07XG5cbi8qKlxuICogRXZlbnRFbWl0dGVyIHV0aWxpdHkuXG4gKiBAY29uc3RydWN0b3JcbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEVtaXR0ZXIgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGV2ZW50IGxpc3RlbmVycyBzY29wZWQgYnkgZXZlbnQgdHlwZS5cblx0XHQgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgIUFycmF5PCFmdW5jdGlvbigpPj59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZXZlbnRzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIYW5kbGVycyB0aGF0IGFyZSB0cmlnZ2VyZWQgd2hlbiBhbiBldmVudCBpcyBsaXN0ZW5lZCB0by5cblx0XHQgKiBAdHlwZSB7QXJyYXl9XG5cdFx0ICovXG5cdFx0dGhpcy5saXN0ZW5lckhhbmRsZXJzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBDb25maWd1cmF0aW9uIG9wdGlvbiB3aGljaCBkZXRlcm1pbmVzIGlmIGFuIGV2ZW50IGZhY2FkZSBzaG91bGQgYmUgc2VudFxuXHRcdCAqIGFzIGEgcGFyYW0gb2YgbGlzdGVuZXJzIHdoZW4gZW1pdHRpbmcgZXZlbnRzLiBJZiBzZXQgdG8gdHJ1ZSwgdGhlIGZhY2FkZVxuXHRcdCAqIHdpbGwgYmUgcGFzc2VkIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBvZiB0aGUgbGlzdGVuZXIuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuc2hvdWxkVXNlRmFjYWRlXyA9IGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBoYW5kbGVyIHRvIGdpdmVuIGhvbGRlciB2YXJpYWJsZS4gSWYgdGhlIGhvbGRlciBkb2Vzbid0IGhhdmUgYVxuXHQgKiB2YWx1ZSB5ZXQsIGl0IHdpbGwgcmVjZWl2ZSB0aGUgaGFuZGxlciBkaXJlY3RseS4gSWYgdGhlIGhvbGRlciBpcyBhbiBhcnJheSxcblx0ICogdGhlIHZhbHVlIHdpbGwganVzdCBiZSBhZGRlZCB0byBpdC4gT3RoZXJ3aXNlLCB0aGUgaG9sZGVyIHdpbGwgYmUgc2V0IHRvIGFcblx0ICogbmV3IGFycmF5IGNvbnRhaW5pbmcgaXRzIHByZXZpb3VzIHZhbHVlIHBsdXMgdGhlIG5ldyBoYW5kbGVyLlxuXHQgKiBAcGFyYW0geyp9IGhvbGRlclxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbigpfE9iamVjdH0gaGFuZGxlclxuXHQgKiBAcmV0dXJuIHsqfSBUaGUgaG9sZGVyJ3MgbmV3IHZhbHVlLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRhZGRIYW5kbGVyXyhob2xkZXIsIGhhbmRsZXIpIHtcblx0XHRpZiAoIWhvbGRlcikge1xuXHRcdFx0aG9sZGVyID0gaGFuZGxlcjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCFBcnJheS5pc0FycmF5KGhvbGRlcikpIHtcblx0XHRcdFx0aG9sZGVyID0gW2hvbGRlcl07XG5cdFx0XHR9XG5cdFx0XHRob2xkZXIucHVzaChoYW5kbGVyKTtcblx0XHR9XG5cdFx0cmV0dXJuIGhvbGRlcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50cy5cblx0ICogQHBhcmFtIHshKEFycmF5fHN0cmluZyl9IGV2ZW50XG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdF9kZWZhdWx0IEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGxpc3RlbmVyIGlzIGEgZGVmYXVsdFxuXHQgKiAgIGFjdGlvbiBmb3IgdGhpcyBldmVudC4gRGVmYXVsdCBhY3Rpb25zIGFyZSBydW4gbGFzdCwgYW5kIG9ubHkgaWYgbm8gcHJldmlvdXNcblx0ICogICBsaXN0ZW5lciBjYWxsIGBwcmV2ZW50RGVmYXVsdCgpYCBvbiB0aGUgcmVjZWl2ZWQgZXZlbnQgZmFjYWRlLlxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG5cdCAqL1xuXHRhZGRMaXN0ZW5lcihldmVudCwgbGlzdGVuZXIsIG9wdF9kZWZhdWx0KSB7XG5cdFx0dGhpcy52YWxpZGF0ZUxpc3RlbmVyXyhsaXN0ZW5lcik7XG5cblx0XHRjb25zdCBldmVudHMgPSB0aGlzLnRvRXZlbnRzQXJyYXlfKGV2ZW50KTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dGhpcy5hZGRTaW5nbGVMaXN0ZW5lcl8oZXZlbnRzW2ldLCBsaXN0ZW5lciwgb3B0X2RlZmF1bHQpO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgRXZlbnRIYW5kbGUodGhpcywgZXZlbnQsIGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciBhIHNpbmdsZSBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IG9wdF9kZWZhdWx0IEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGxpc3RlbmVyIGlzIGEgZGVmYXVsdFxuXHQgKiAgIGFjdGlvbiBmb3IgdGhpcyBldmVudC4gRGVmYXVsdCBhY3Rpb25zIGFyZSBydW4gbGFzdCwgYW5kIG9ubHkgaWYgbm8gcHJldmlvdXNcblx0ICogICBsaXN0ZW5lciBjYWxsIGBwcmV2ZW50RGVmYXVsdCgpYCBvbiB0aGUgcmVjZWl2ZWQgZXZlbnQgZmFjYWRlLlxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb249fSBvcHRfb3JpZ2luIFRoZSBvcmlnaW5hbCBmdW5jdGlvbiB0aGF0IHdhcyBhZGRlZCBhcyBhXG5cdCAqICAgbGlzdGVuZXIsIGlmIHRoZXJlIGlzIGFueS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0YWRkU2luZ2xlTGlzdGVuZXJfKGV2ZW50LCBsaXN0ZW5lciwgb3B0X2RlZmF1bHQsIG9wdF9vcmlnaW4pIHtcblx0XHR0aGlzLnJ1bkxpc3RlbmVySGFuZGxlcnNfKGV2ZW50KTtcblx0XHRpZiAob3B0X2RlZmF1bHQgfHwgb3B0X29yaWdpbikge1xuXHRcdFx0bGlzdGVuZXIgPSB7XG5cdFx0XHRcdGRlZmF1bHQ6IG9wdF9kZWZhdWx0LFxuXHRcdFx0XHRmbjogbGlzdGVuZXIsXG5cdFx0XHRcdG9yaWdpbjogb3B0X29yaWdpblxuXHRcdFx0fTtcblx0XHR9XG5cdFx0dGhpcy5ldmVudHNfID0gdGhpcy5ldmVudHNfIHx8IHt9O1xuXHRcdHRoaXMuZXZlbnRzX1tldmVudF0gPSB0aGlzLmFkZEhhbmRsZXJfKHRoaXMuZXZlbnRzX1tldmVudF0sIGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBCdWlsZHMgZmFjYWRlIGZvciB0aGUgZ2l2ZW4gZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHtPYmplY3R9XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGJ1aWxkRmFjYWRlXyhldmVudCkge1xuXHRcdGlmICh0aGlzLmdldFNob3VsZFVzZUZhY2FkZSgpKSB7XG5cdFx0XHRjb25zdCBmYWNhZGUgPSB7XG5cdFx0XHRcdHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRmYWNhZGUucHJldmVudGVkRGVmYXVsdCA9IHRydWU7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHRhcmdldDogdGhpcyxcblx0XHRcdFx0dHlwZTogZXZlbnRcblx0XHRcdH07XG5cdFx0XHRyZXR1cm4gZmFjYWRlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwb3NlcyBvZiB0aGlzIGluc3RhbmNlJ3Mgb2JqZWN0IHJlZmVyZW5jZXMuXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHRoaXMuZXZlbnRzXyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogRXhlY3V0ZSBlYWNoIG9mIHRoZSBsaXN0ZW5lcnMgaW4gb3JkZXIgd2l0aCB0aGUgc3VwcGxpZWQgYXJndW1lbnRzLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHBhcmFtIHsqfSBvcHRfYXJncyBbYXJnMV0sIFthcmcyXSwgWy4uLl1cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIGV2ZW50IGhhZCBsaXN0ZW5lcnMsIGZhbHNlIG90aGVyd2lzZS5cblx0ICovXG5cdGVtaXQoZXZlbnQpIHtcblx0XHRjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLmdldFJhd0xpc3RlbmVyc18oZXZlbnQpO1xuXHRcdGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Y29uc3QgYXJncyA9IGFycmF5LnNsaWNlKGFyZ3VtZW50cywgMSk7XG5cdFx0dGhpcy5ydW5MaXN0ZW5lcnNfKGxpc3RlbmVycywgYXJncywgdGhpcy5idWlsZEZhY2FkZV8oZXZlbnQpKTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBsaXN0ZW5lciBvYmplY3RzIGZvciB0aGUgZ2l2ZW4gZXZlbnQsIGlmIHRoZXJlIGFyZSBhbnkuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHshQXJyYXl9XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGdldFJhd0xpc3RlbmVyc18oZXZlbnQpIHtcblx0XHRjb25zdCBkaXJlY3RMaXN0ZW5lcnMgPSB0b0FycmF5KHRoaXMuZXZlbnRzXyAmJiB0aGlzLmV2ZW50c19bZXZlbnRdKTtcblx0XHRyZXR1cm4gZGlyZWN0TGlzdGVuZXJzLmNvbmNhdCh0b0FycmF5KHRoaXMuZXZlbnRzXyAmJiB0aGlzLmV2ZW50c19bJyonXSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9uIHdoaWNoIGRldGVybWluZXMgaWYgYW4gZXZlbnQgZmFjYWRlIHNob3VsZFxuXHQgKiBiZSBzZW50IGFzIGEgcGFyYW0gb2YgbGlzdGVuZXJzIHdoZW4gZW1pdHRpbmcgZXZlbnRzLiBJZiBzZXQgdG8gdHJ1ZSwgdGhlXG5cdCAqIGZhY2FkZSB3aWxsIGJlIHBhc3NlZCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgb2YgdGhlIGxpc3RlbmVyLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0Z2V0U2hvdWxkVXNlRmFjYWRlKCkge1xuXHRcdHJldHVybiB0aGlzLnNob3VsZFVzZUZhY2FkZV87XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHtBcnJheX0gQXJyYXkgb2YgbGlzdGVuZXJzLlxuXHQgKi9cblx0bGlzdGVuZXJzKGV2ZW50KSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0UmF3TGlzdGVuZXJzXyhldmVudCkubWFwKFxuXHRcdFx0bGlzdGVuZXIgPT4gbGlzdGVuZXIuZm4gPyBsaXN0ZW5lci5mbiA6IGxpc3RlbmVyXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBmaXhlZCBudW1iZXIgb2YgdGltZXMgZm9yIHRoZVxuXHQgKiBldmVudHMuIEFmdGVyIGVhY2ggZXZlbnQgaXMgdHJpZ2dlcmVkIHRoZSBzcGVjaWZpZWQgYW1vdW50IG9mIHRpbWVzLCB0aGVcblx0ICogbGlzdGVuZXIgaXMgcmVtb3ZlZCBmb3IgaXQuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudFxuXHQgKiBAcGFyYW0ge251bWJlcn0gYW1vdW50IFRoZSBhbW91bnQgb2YgdGltZXMgdGhpcyBldmVudCBzaG91bGQgYmUgbGlzdGVuZWRcblx0ICogdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG5cdCAqL1xuXHRtYW55KGV2ZW50LCBhbW91bnQsIGxpc3RlbmVyKSB7XG5cdFx0Y29uc3QgZXZlbnRzID0gdGhpcy50b0V2ZW50c0FycmF5XyhldmVudCk7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMubWFueV8oZXZlbnRzW2ldLCBhbW91bnQsIGxpc3RlbmVyKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IEV2ZW50SGFuZGxlKHRoaXMsIGV2ZW50LCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGEgZml4ZWQgbnVtYmVyIG9mIHRpbWVzIGZvciBhIHNpbmdsZVxuXHQgKiBldmVudC4gQWZ0ZXIgdGhlIGV2ZW50IGlzIHRyaWdnZXJlZCB0aGUgc3BlY2lmaWVkIGFtb3VudCBvZiB0aW1lcywgdGhlXG5cdCAqIGxpc3RlbmVyIGlzIHJlbW92ZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0ge251bWJlcn0gYW1vdW50IFRoZSBhbW91bnQgb2YgdGltZXMgdGhpcyBldmVudCBzaG91bGQgYmUgbGlzdGVuZWRcblx0ICogdG8uXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRtYW55XyhldmVudCwgYW1vdW50LCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IHNlbGYgPSB0aGlzO1xuXG5cdFx0aWYgKGFtb3VudCA8PSAwKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gaGFuZGxlckludGVybmFsKCkge1xuXHRcdFx0aWYgKC0tYW1vdW50ID09PSAwKSB7XG5cdFx0XHRcdHNlbGYucmVtb3ZlTGlzdGVuZXIoZXZlbnQsIGhhbmRsZXJJbnRlcm5hbCk7XG5cdFx0XHR9XG5cdFx0XHRsaXN0ZW5lci5hcHBseShzZWxmLCBhcmd1bWVudHMpO1xuXHRcdH1cblxuXHRcdHNlbGYuYWRkU2luZ2xlTGlzdGVuZXJfKGV2ZW50LCBoYW5kbGVySW50ZXJuYWwsIGZhbHNlLCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIGEgbGlzdGVuZXIgb2JqZWN0IG1hdGNoZXMgdGhlIGdpdmVuIGxpc3RlbmVyIGZ1bmN0aW9uLiBUbyBtYXRjaCxcblx0ICogaXQgbmVlZHMgdG8gZWl0aGVyIHBvaW50IHRvIHRoYXQgbGlzdGVuZXIgb3IgaGF2ZSBpdCBhcyBpdHMgb3JpZ2luLlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IGxpc3RlbmVyT2JqXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRtYXRjaGVzTGlzdGVuZXJfKGxpc3RlbmVyT2JqLCBsaXN0ZW5lcikge1xuXHRcdGNvbnN0IGZuID0gbGlzdGVuZXJPYmouZm4gfHwgbGlzdGVuZXJPYmo7XG5cdFx0cmV0dXJuIGZuID09PSBsaXN0ZW5lciB8fFxuXHRcdFx0KGxpc3RlbmVyT2JqLm9yaWdpbiAmJiBsaXN0ZW5lck9iai5vcmlnaW4gPT09IGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRzLlxuXHQgKiBDYXV0aW9uOiBjaGFuZ2VzIGFycmF5IGluZGljZXMgaW4gdGhlIGxpc3RlbmVyIGFycmF5IGJlaGluZCB0aGUgbGlzdGVuZXIuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRvZmYoZXZlbnQsIGxpc3RlbmVyKSB7XG5cdFx0dGhpcy52YWxpZGF0ZUxpc3RlbmVyXyhsaXN0ZW5lcik7XG5cdFx0aWYgKCF0aGlzLmV2ZW50c18pIHtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblxuXHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMudG9FdmVudHNBcnJheV8oZXZlbnQpO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0aGlzLmV2ZW50c19bZXZlbnRzW2ldXSA9IHRoaXMucmVtb3ZlTWF0Y2hpbmdMaXN0ZW5lck9ianNfKFxuXHRcdFx0XHR0b0FycmF5KHRoaXMuZXZlbnRzX1tldmVudHNbaV1dKSxcblx0XHRcdFx0bGlzdGVuZXJcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBlbmQgb2YgdGhlIGxpc3RlbmVycyBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudHMuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cblx0ICovXG5cdG9uKCkge1xuXHRcdHJldHVybiB0aGlzLmFkZExpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBoYW5kbGVyIHRoYXQgZ2V0cyB0cmlnZ2VyZWQgd2hlbiBhbiBldmVudCBpcyBsaXN0ZW5lZCB0byBvbiB0aGlzXG5cdCAqIGluc3RhbmNlLlxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbigpfVxuXHQgKi9cblx0b25MaXN0ZW5lcihoYW5kbGVyKSB7XG5cdFx0dGhpcy5saXN0ZW5lckhhbmRsZXJzXyA9IHRoaXMuYWRkSGFuZGxlcl8odGhpcy5saXN0ZW5lckhhbmRsZXJzXywgaGFuZGxlcik7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIG9uZSB0aW1lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRzLiBUaGlzIGxpc3RlbmVyIGlzIGludm9rZWQgb25seSB0aGVcblx0ICogbmV4dCB0aW1lIGVhY2ggZXZlbnQgaXMgZmlyZWQsIGFmdGVyIHdoaWNoIGl0IGlzIHJlbW92ZWQuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gQ2FuIGJlIHVzZWQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cblx0ICovXG5cdG9uY2UoZXZlbnRzLCBsaXN0ZW5lcikge1xuXHRcdHJldHVybiB0aGlzLm1hbnkoZXZlbnRzLCAxLCBsaXN0ZW5lcik7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzLCBvciB0aG9zZSBvZiB0aGUgc3BlY2lmaWVkIGV2ZW50cy4gSXQncyBub3QgYSBnb29kXG5cdCAqIGlkZWEgdG8gcmVtb3ZlIGxpc3RlbmVycyB0aGF0IHdlcmUgYWRkZWQgZWxzZXdoZXJlIGluIHRoZSBjb2RlLFxuXHQgKiBlc3BlY2lhbGx5IHdoZW4gaXQncyBvbiBhbiBlbWl0dGVyIHRoYXQgeW91IGRpZG4ndCBjcmVhdGUuXG5cdCAqIEBwYXJhbSB7KEFycmF5fHN0cmluZyk9fSBvcHRfZXZlbnRzXG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRyZW1vdmVBbGxMaXN0ZW5lcnMob3B0X2V2ZW50cykge1xuXHRcdGlmICh0aGlzLmV2ZW50c18pIHtcblx0XHRcdGlmIChvcHRfZXZlbnRzKSB7XG5cdFx0XHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMudG9FdmVudHNBcnJheV8ob3B0X2V2ZW50cyk7XG5cdFx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdFx0dGhpcy5ldmVudHNfW2V2ZW50c1tpXV0gPSBudWxsO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmV2ZW50c18gPSBudWxsO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lciBvYmplY3RzIGZyb20gdGhlIGdpdmVuIGFycmF5IHRoYXQgbWF0Y2ggdGhlIGdpdmVuXG5cdCAqIGxpc3RlbmVyIGZ1bmN0aW9uLlxuXHQgKiBAcGFyYW0ge0FycmF5LjxPYmplY3Q+fSBsaXN0ZW5lck9ianNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4ge0FycmF5LjxPYmplY3Q+fE9iamVjdH0gVGhlIG5ldyBsaXN0ZW5lcnMgYXJyYXkgZm9yIHRoaXMgZXZlbnQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHJlbW92ZU1hdGNoaW5nTGlzdGVuZXJPYmpzXyhsaXN0ZW5lck9ianMsIGxpc3RlbmVyKSB7XG5cdFx0Y29uc3QgZmluYWxMaXN0ZW5lcnMgPSBbXTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGxpc3RlbmVyT2Jqcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKCF0aGlzLm1hdGNoZXNMaXN0ZW5lcl8obGlzdGVuZXJPYmpzW2ldLCBsaXN0ZW5lcikpIHtcblx0XHRcdFx0ZmluYWxMaXN0ZW5lcnMucHVzaChsaXN0ZW5lck9ianNbaV0pO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gZmluYWxMaXN0ZW5lcnMubGVuZ3RoID4gMCA/IGZpbmFsTGlzdGVuZXJzIDogbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRzLlxuXHQgKiBDYXV0aW9uOiBjaGFuZ2VzIGFycmF5IGluZGljZXMgaW4gdGhlIGxpc3RlbmVyIGFycmF5IGJlaGluZCB0aGUgbGlzdGVuZXIuXG5cdCAqIEBwYXJhbSB7IShBcnJheXxzdHJpbmcpfSBldmVudHNcblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFPYmplY3R9IFJldHVybnMgZW1pdHRlciwgc28gY2FsbHMgY2FuIGJlIGNoYWluZWQuXG5cdCAqL1xuXHRyZW1vdmVMaXN0ZW5lcigpIHtcblx0XHRyZXR1cm4gdGhpcy5vZmYuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBoYW5kbGVycyB3aGVuIGFuIGV2ZW50IGlzIGxpc3RlbmVkIHRvLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0cnVuTGlzdGVuZXJIYW5kbGVyc18oZXZlbnQpIHtcblx0XHRsZXQgaGFuZGxlcnMgPSB0aGlzLmxpc3RlbmVySGFuZGxlcnNfO1xuXHRcdGlmIChoYW5kbGVycykge1xuXHRcdFx0aGFuZGxlcnMgPSB0b0FycmF5KGhhbmRsZXJzKTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgaGFuZGxlcnMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0aGFuZGxlcnNbaV0oZXZlbnQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBnaXZlbiBsaXN0ZW5lcnMuXG5cdCAqIEBwYXJhbSB7IUFycmF5fSBsaXN0ZW5lcnNcblx0ICogQHBhcmFtIHshQXJyYXl9IGFyZ3Ncblx0ICogQHBhcmFtIChPYmplY3QpIGZhY2FkZVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRydW5MaXN0ZW5lcnNfKGxpc3RlbmVycywgYXJncywgZmFjYWRlKSB7XG5cdFx0aWYgKGZhY2FkZSkge1xuXHRcdFx0YXJncy5wdXNoKGZhY2FkZSk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZGVmYXVsdExpc3RlbmVycyA9IFtdO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXS5mbiB8fCBsaXN0ZW5lcnNbaV07XG5cdFx0XHRpZiAobGlzdGVuZXJzW2ldLmRlZmF1bHQpIHtcblx0XHRcdFx0ZGVmYXVsdExpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoIWZhY2FkZSB8fCAhZmFjYWRlLnByZXZlbnRlZERlZmF1bHQpIHtcblx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgZGVmYXVsdExpc3RlbmVycy5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRkZWZhdWx0TGlzdGVuZXJzW2pdLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBjb25maWd1cmF0aW9uIG9wdGlvbiB3aGljaCBkZXRlcm1pbmVzIGlmIGFuIGV2ZW50IGZhY2FkZSBzaG91bGRcblx0ICogYmUgc2VudCBhcyBhIHBhcmFtIG9mIGxpc3RlbmVycyB3aGVuIGVtaXR0aW5nIGV2ZW50cy4gSWYgc2V0IHRvIHRydWUsIHRoZVxuXHQgKiBmYWNhZGUgd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIHRoZSBsaXN0ZW5lci5cblx0ICogQHBhcmFtIHtib29sZWFufSBzaG91bGRVc2VGYWNhZGVcblx0ICogQHJldHVybiB7IU9iamVjdH0gUmV0dXJucyBlbWl0dGVyLCBzbyBjYWxscyBjYW4gYmUgY2hhaW5lZC5cblx0ICovXG5cdHNldFNob3VsZFVzZUZhY2FkZShzaG91bGRVc2VGYWNhZGUpIHtcblx0XHR0aGlzLnNob3VsZFVzZUZhY2FkZV8gPSBzaG91bGRVc2VGYWNhZGU7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgdGhlIHBhcmFtZXRlciB0byBhbiBhcnJheSBpZiBvbmx5IG9uZSBldmVudCBpcyBnaXZlbi4gUmV1c2VzIHRoZVxuXHQgKiBzYW1lIGFycmF5IGVhY2ggdGltZSB0aGlzIGNvbnZlcnNpb24gaXMgZG9uZSwgdG8gYXZvaWQgdXNpbmcgbW9yZSBtZW1vcnlcblx0ICogdGhhbiBuZWNlc3NhcnkuXG5cdCAqIEBwYXJhbSAgeyEoQXJyYXl8c3RyaW5nKX0gZXZlbnRzXG5cdCAqIEByZXR1cm4geyFBcnJheX1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dG9FdmVudHNBcnJheV8oZXZlbnRzKSB7XG5cdFx0aWYgKGlzU3RyaW5nKGV2ZW50cykpIHtcblx0XHRcdHNpbmdsZUFycmF5X1swXSA9IGV2ZW50cztcblx0XHRcdGV2ZW50cyA9IHNpbmdsZUFycmF5Xztcblx0XHR9XG5cdFx0cmV0dXJuIGV2ZW50cztcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGxpc3RlbmVyIGlzIHZhbGlkLCB0aHJvd2luZyBhbiBleGNlcHRpb24gd2hlbiBpdCdzIG5vdC5cblx0ICogQHBhcmFtICB7Kn0gbGlzdGVuZXJcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dmFsaWRhdGVMaXN0ZW5lcl8obGlzdGVuZXIpIHtcblx0XHRpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCdMaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gdG9BcnJheSh2YWwpIHtcblx0dmFsID0gdmFsIHx8IFtdO1xuXHRyZXR1cm4gQXJyYXkuaXNBcnJheSh2YWwpID8gdmFsIDogW3ZhbF07XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50RW1pdHRlcjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgRGlzcG9zYWJsZSB9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBFdmVudEVtaXR0ZXJQcm94eSB1dGlsaXR5LiBJdCdzIHJlc3BvbnNpYmxlIGZvciBsaW5raW5nIHR3byBFdmVudEVtaXR0ZXJcbiAqIGluc3RhbmNlcyB0b2dldGhlciwgZW1pdHRpbmcgZXZlbnRzIGZyb20gdGhlIGZpcnN0IGVtaXR0ZXIgdGhyb3VnaCB0aGVcbiAqIHNlY29uZCBvbmUuIFRoYXQgbWVhbnMgdGhhdCBsaXN0ZW5pbmcgdG8gYSBzdXBwb3J0ZWQgZXZlbnQgb24gdGhlIHRhcmdldFxuICogZW1pdHRlciB3aWxsIG1lYW4gbGlzdGVuaW5nIHRvIGl0IG9uIHRoZSBvcmlnaW4gZW1pdHRlciBhcyB3ZWxsLlxuICogQHBhcmFtIHtFdmVudEVtaXR0ZXJ9IG9yaWdpbkVtaXR0ZXIgRXZlbnRzIG9yaWdpbmF0ZWQgb24gdGhpcyBlbWl0dGVyXG4gKiAgIHdpbGwgYmUgZmlyZWQgZm9yIHRoZSB0YXJnZXQgZW1pdHRlcidzIGxpc3RlbmVycyBhcyB3ZWxsLlxuICogQHBhcmFtIHtFdmVudEVtaXR0ZXJ9IHRhcmdldEVtaXR0ZXIgRXZlbnQgbGlzdGVuZXJzIGF0dGFjaGVkIHRvIHRoaXMgZW1pdHRlclxuICogICB3aWxsIGFsc28gYmUgdHJpZ2dlcmVkIHdoZW4gdGhlIGV2ZW50IGlzIGZpcmVkIGJ5IHRoZSBvcmlnaW4gZW1pdHRlci5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRfYmxhY2tsaXN0IE9wdGlvbmFsIGJsYWNrbGlzdCBvZiBldmVudHMgdGhhdCBzaG91bGQgbm90IGJlXG4gKiAgIHByb3hpZWQuXG4gKiBAY29uc3RydWN0b3JcbiAqIEBleHRlbmRzIHtEaXNwb3NhYmxlfVxuICovXG5jbGFzcyBFdmVudEVtaXR0ZXJQcm94eSBleHRlbmRzIERpc3Bvc2FibGUge1xuXHRjb25zdHJ1Y3RvcihvcmlnaW5FbWl0dGVyLCB0YXJnZXRFbWl0dGVyLCBvcHRfYmxhY2tsaXN0LCBvcHRfd2hpdGVsaXN0KSB7XG5cdFx0c3VwZXIoKTtcblxuXHRcdC8qKlxuXHRcdCAqIE1hcCBvZiBldmVudHMgdGhhdCBzaG91bGQgbm90IGJlIHByb3hpZWQuXG5cdFx0ICogQHR5cGUge09iamVjdH1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5ibGFja2xpc3RfID0gb3B0X2JsYWNrbGlzdDtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBvcmlnaW4gZW1pdHRlci4gVGhpcyBlbWl0dGVyJ3MgZXZlbnRzIHdpbGwgYmUgcHJveGllZCB0aHJvdWdoIHRoZVxuXHRcdCAqIHRhcmdldCBlbWl0dGVyLlxuXHRcdCAqIEB0eXBlIHtFdmVudEVtaXR0ZXJ9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMub3JpZ2luRW1pdHRlcl8gPSBvcmlnaW5FbWl0dGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogQSBsaXN0IG9mIGV2ZW50cyB0aGF0IGFyZSBwZW5kaW5nIHRvIGJlIGxpc3RlbmVkIGJ5IGFuIGFjdHVhbCBvcmlnaW5cblx0XHQgKiBlbWl0dGVyLiBFdmVudHMgYXJlIHN0b3JlZCBoZXJlIHdoZW4gdGhlIG9yaWdpbiBkb2Vzbid0IGV4aXN0LCBzbyB0aGV5XG5cdFx0ICogY2FuIGJlIHNldCBvbiBhIG5ldyBvcmlnaW4gd2hlbiBvbmUgaXMgc2V0LlxuXHRcdCAqIEB0eXBlIHtBcnJheX1cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5wZW5kaW5nRXZlbnRzXyA9IG51bGw7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBhIG1hcCBvZiBldmVudHMgZnJvbSB0aGUgb3JpZ2luIGVtaXR0ZXIgdGhhdCBhcmUgYWxyZWFkeSBiZWluZyBwcm94aWVkLlxuXHRcdCAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCAhRXZlbnRIYW5kbGU+fVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSB0YXJnZXQgZW1pdHRlci4gVGhpcyBlbWl0dGVyIHdpbGwgZW1pdCBhbGwgZXZlbnRzIHRoYXQgY29tZSBmcm9tXG5cdFx0ICogdGhlIG9yaWdpbiBlbWl0dGVyLlxuXHRcdCAqIEB0eXBlIHtFdmVudEVtaXR0ZXJ9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudGFyZ2V0RW1pdHRlcl8gPSB0YXJnZXRFbWl0dGVyO1xuXG5cdFx0LyoqXG5cdFx0ICogTWFwIG9mIGV2ZW50cyB0aGF0IHNob3VsZCBiZSBwcm94aWVkLiBJZiB3aGl0ZWxpc3QgaXMgc2V0IGJsYWNrbGlzdCBpcyBpZ25vcmVkLlxuXHRcdCAqIEB0eXBlIHtPYmplY3R9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMud2hpdGVsaXN0XyA9IG9wdF93aGl0ZWxpc3Q7XG5cblx0XHR0aGlzLnN0YXJ0UHJveHlfKCk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyB0aGUgZ2l2ZW4gbGlzdGVuZXIgZm9yIHRoZSBnaXZlbiBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGxpc3RlbmVyXG5cdCAqIEByZXR1cm4geyFFdmVudEhhbmRsZX0gVGhlIGxpc3RlbmVkIGV2ZW50J3MgaGFuZGxlLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRhZGRMaXN0ZW5lcl8oZXZlbnQsIGxpc3RlbmVyKSB7XG5cdFx0cmV0dXJuIHRoaXMub3JpZ2luRW1pdHRlcl8ub24oZXZlbnQsIGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHRoaXMucmVtb3ZlTGlzdGVuZXJzXygpO1xuXHRcdHRoaXMucHJveGllZEV2ZW50c18gPSBudWxsO1xuXHRcdHRoaXMub3JpZ2luRW1pdHRlcl8gPSBudWxsO1xuXHRcdHRoaXMudGFyZ2V0RW1pdHRlcl8gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEVtaXRzIHRoZSBzcGVjaWZpZWQgZXZlbnQgdHlwZSBvbiB0aGUgdGFyZ2V0IGVtaXR0ZXIuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGVtaXRPblRhcmdldF8oKSB7XG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXy5lbWl0LmFwcGx5KHRoaXMudGFyZ2V0RW1pdHRlcl8sIGFyZ3VtZW50cyk7XG5cdH1cblxuXHQvKipcblx0ICogUHJveGllcyB0aGUgZ2l2ZW4gZXZlbnQgZnJvbSB0aGUgb3JpZ2luIHRvIHRoZSB0YXJnZXQgZW1pdHRlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqL1xuXHRwcm94eUV2ZW50KGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuc2hvdWxkUHJveHlFdmVudF8oZXZlbnQpKSB7XG5cdFx0XHR0aGlzLnRyeVRvQWRkTGlzdGVuZXJfKGV2ZW50KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyB0aGUgcHJveHkgbGlzdGVuZXIgZm9yIGFsbCBldmVudHMuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyc18oKSB7XG5cdFx0aWYgKHRoaXMucHJveGllZEV2ZW50c18pIHtcblx0XHRcdGNvbnN0IGV2ZW50cyA9IE9iamVjdC5rZXlzKHRoaXMucHJveGllZEV2ZW50c18pO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzX1tldmVudHNbaV1dLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnByb3hpZWRFdmVudHNfID0gbnVsbDtcblx0XHR9XG5cdFx0dGhpcy5wZW5kaW5nRXZlbnRzXyA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogQ2hhbmdlcyB0aGUgb3JpZ2luIGVtaXR0ZXIuIFRoaXMgYXV0b21hdGljYWxseSBkZXRhY2hlcyBhbnkgZXZlbnRzIHRoYXRcblx0ICogd2VyZSBhbHJlYWR5IGJlaW5nIHByb3hpZWQgZnJvbSB0aGUgcHJldmlvdXMgZW1pdHRlciwgYW5kIHN0YXJ0cyBwcm94eWluZ1xuXHQgKiB0aGVtIG9uIHRoZSBuZXcgZW1pdHRlciBpbnN0ZWFkLlxuXHQgKiBAcGFyYW0geyFFdmVudEVtaXR0ZXJ9IG9yaWdpbkVtaXR0ZXJcblx0ICovXG5cdHNldE9yaWdpbkVtaXR0ZXIob3JpZ2luRW1pdHRlcikge1xuXHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMub3JpZ2luRW1pdHRlcl8gJiYgdGhpcy5wcm94aWVkRXZlbnRzXyA/XG5cdFx0XHRPYmplY3Qua2V5cyh0aGlzLnByb3hpZWRFdmVudHNfKSA6XG5cdFx0XHR0aGlzLnBlbmRpbmdFdmVudHNfO1xuXHRcdHRoaXMub3JpZ2luRW1pdHRlcl8gPSBvcmlnaW5FbWl0dGVyO1xuXHRcdGlmIChldmVudHMpIHtcblx0XHRcdHRoaXMucmVtb3ZlTGlzdGVuZXJzXygpO1xuXHRcdFx0ZXZlbnRzLmZvckVhY2goZXZlbnQgPT4gdGhpcy5wcm94eUV2ZW50KGV2ZW50KSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZXZlbnQgc2hvdWxkIGJlIHByb3hpZWQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRzaG91bGRQcm94eUV2ZW50XyhldmVudCkge1xuXHRcdGlmICh0aGlzLndoaXRlbGlzdF8gJiYgIXRoaXMud2hpdGVsaXN0X1tldmVudF0pIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0aWYgKHRoaXMuYmxhY2tsaXN0XyAmJiB0aGlzLmJsYWNrbGlzdF9bZXZlbnRdKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiAhdGhpcy5wcm94aWVkRXZlbnRzXyB8fCAhdGhpcy5wcm94aWVkRXZlbnRzX1tldmVudF07XG5cdH1cblxuXHQvKipcblx0ICogU3RhcnRzIHByb3h5aW5nIGFsbCBldmVudHMgZnJvbSB0aGUgb3JpZ2luIHRvIHRoZSB0YXJnZXQgZW1pdHRlci5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0c3RhcnRQcm94eV8oKSB7XG5cdFx0dGhpcy50YXJnZXRFbWl0dGVyXy5vbkxpc3RlbmVyKHRoaXMucHJveHlFdmVudC5iaW5kKHRoaXMpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIG9yaWdpbiBlbWl0dGVyLCBpZiBpdCBleGlzdHMuIE90aGVyd2lzZSwgc3RvcmVzXG5cdCAqIHRoZSBwZW5kaW5nIGxpc3RlbmVyIHNvIGl0IGNhbiBiZSB1c2VkIG9uIGEgZnV0dXJlIG9yaWdpbiBlbWl0dGVyLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0dHJ5VG9BZGRMaXN0ZW5lcl8oZXZlbnQpIHtcblx0XHRpZiAodGhpcy5vcmlnaW5FbWl0dGVyXykge1xuXHRcdFx0dGhpcy5wcm94aWVkRXZlbnRzXyA9IHRoaXMucHJveGllZEV2ZW50c18gfHwge307XG5cdFx0XHR0aGlzLnByb3hpZWRFdmVudHNfW2V2ZW50XSA9IHRoaXMuYWRkTGlzdGVuZXJfKFxuXHRcdFx0XHRldmVudCxcblx0XHRcdFx0dGhpcy5lbWl0T25UYXJnZXRfLmJpbmQodGhpcywgZXZlbnQpXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnBlbmRpbmdFdmVudHNfID0gdGhpcy5wZW5kaW5nRXZlbnRzXyB8fCBbXTtcblx0XHRcdHRoaXMucGVuZGluZ0V2ZW50c18ucHVzaChldmVudCk7XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50RW1pdHRlclByb3h5O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlIH0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIEV2ZW50SGFuZGxlciB1dGlsaXR5LiBJdCdzIHVzZWZ1bCBmb3IgZWFzaWx5IHJlbW92aW5nIGEgZ3JvdXAgb2ZcbiAqIGxpc3RlbmVycyBmcm9tIGRpZmZlcmVudCBFdmVudEVtaXR0ZXIgaW5zdGFuY2VzLlxuICogQGNvbnN0cnVjdG9yXG4gKiBAZXh0ZW5kcyB7RGlzcG9zYWJsZX1cbiAqL1xuY2xhc3MgRXZlbnRIYW5kbGVyIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBBbiBhcnJheSB0aGF0IGhvbGRzIHRoZSBhZGRlZCBldmVudCBoYW5kbGVzLCBzbyB0aGUgbGlzdGVuZXJzIGNhbiBiZVxuXHRcdCAqIHJlbW92ZWQgbGF0ZXIuXG5cdFx0ICogQHR5cGUge0FycmF5LjxFdmVudEhhbmRsZT59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZXZlbnRIYW5kbGVzXyA9IFtdO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgZXZlbnQgaGFuZGxlcyB0byBiZSByZW1vdmVkIGxhdGVyIHRocm91Z2ggdGhlIGByZW1vdmVBbGxMaXN0ZW5lcnNgXG5cdCAqIG1ldGhvZC5cblx0ICogQHBhcmFtIHsuLi4oIUV2ZW50SGFuZGxlKX0gdmFyX2FyZ3Ncblx0ICovXG5cdGFkZCgpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dGhpcy5ldmVudEhhbmRsZXNfLnB1c2goYXJndW1lbnRzW2ldKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogRGlzcG9zZXMgb2YgdGhpcyBpbnN0YW5jZSdzIG9iamVjdCByZWZlcmVuY2VzLlxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGRpc3Bvc2VJbnRlcm5hbCgpIHtcblx0XHR0aGlzLmV2ZW50SGFuZGxlc18gPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyB0aGF0IGhhdmUgYmVlbiBhZGRlZCB0aHJvdWdoIHRoZSBgYWRkYCBtZXRob2QuXG5cdCAqL1xuXHRyZW1vdmVBbGxMaXN0ZW5lcnMoKSB7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmV2ZW50SGFuZGxlc18ubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuZXZlbnRIYW5kbGVzX1tpXS5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdH1cblxuXHRcdHRoaXMuZXZlbnRIYW5kbGVzXyA9IFtdO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50SGFuZGxlcjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgYXJyYXksIGlzU3RyaW5nIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IGRvbURhdGEgZnJvbSAnLi9kb21EYXRhJztcbmltcG9ydCB7IEV2ZW50SGFuZGxlIH0gZnJvbSAnbWV0YWwtZXZlbnRzJztcblxuLyoqXG4gKiBUaGlzIGlzIGEgc3BlY2lhbCBFdmVudEhhbmRsZSwgdGhhdCBpcyByZXNwb25zaWJsZSBmb3IgZG9tIGRlbGVnYXRlZCBldmVudHNcbiAqIChvbmx5IHRoZSBvbmVzIHRoYXQgcmVjZWl2ZSBhIHRhcmdldCBlbGVtZW50LCBub3QgYSBzZWxlY3RvciBzdHJpbmcpLlxuICogQGV4dGVuZHMge0V2ZW50SGFuZGxlfVxuICovXG5jbGFzcyBEb21EZWxlZ2F0ZWRFdmVudEhhbmRsZSBleHRlbmRzIEV2ZW50SGFuZGxlIHtcblx0LyoqXG5cdCAqIFRoZSBjb25zdHJ1Y3RvciBmb3IgYERvbURlbGVnYXRlZEV2ZW50SGFuZGxlYC5cblx0ICogQHBhcmFtIHshRXZlbnR9IGVtaXR0ZXIgRWxlbWVudCB0aGUgZXZlbnQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCB3YXMgc3Vic2NyaWJlZCB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0ICogQHBhcmFtIHtzdHJpbmc9fSBvcHRfc2VsZWN0b3IgQW4gb3B0aW9uYWwgc2VsZWN0b3IgdXNlZCB3aGVuIGRlbGVnYXRpbmdcblx0ICogICAgIHRoZSBldmVudC5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihlbWl0dGVyLCBldmVudCwgbGlzdGVuZXIsIG9wdF9zZWxlY3Rvcikge1xuXHRcdHN1cGVyKGVtaXR0ZXIsIGV2ZW50LCBsaXN0ZW5lcik7XG5cdFx0dGhpcy5zZWxlY3Rvcl8gPSBvcHRfc2VsZWN0b3I7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdHJlbW92ZUxpc3RlbmVyKCkge1xuXHRcdGNvbnN0IGRlbGVnYXRpbmcgPSBkb21EYXRhLmdldCh0aGlzLmVtaXR0ZXJfLCAnZGVsZWdhdGluZycsIHt9KTtcblx0XHRjb25zdCBsaXN0ZW5lcnMgPSBkb21EYXRhLmdldCh0aGlzLmVtaXR0ZXJfLCAnbGlzdGVuZXJzJywge30pO1xuXHRcdGNvbnN0IHNlbGVjdG9yID0gdGhpcy5zZWxlY3Rvcl87XG5cdFx0Y29uc3QgYXJyID0gaXNTdHJpbmcoc2VsZWN0b3IpID8gZGVsZWdhdGluZ1t0aGlzLmV2ZW50X10uc2VsZWN0b3JzIDogbGlzdGVuZXJzO1xuXHRcdGNvbnN0IGtleSA9IGlzU3RyaW5nKHNlbGVjdG9yKSA/IHNlbGVjdG9yIDogdGhpcy5ldmVudF87XG5cblx0XHRhcnJheS5yZW1vdmUoYXJyW2tleV0gfHwgW10sIHRoaXMubGlzdGVuZXJfKTtcblx0XHRpZiAoYXJyW2tleV0gJiYgYXJyW2tleV0ubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRkZWxldGUgYXJyW2tleV07XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERvbURlbGVnYXRlZEV2ZW50SGFuZGxlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBFdmVudEhhbmRsZSB9IGZyb20gJ21ldGFsLWV2ZW50cyc7XG5cbi8qKlxuICogVGhpcyBpcyBhIHNwZWNpYWwgRXZlbnRIYW5kbGUsIHRoYXQgaXMgcmVzcG9uc2libGUgZm9yIGRvbSBldmVudHMsIGluc3RlYWRcbiAqIG9mIEV2ZW50RW1pdHRlciBldmVudHMuXG4gKiBAZXh0ZW5kcyB7RXZlbnRIYW5kbGV9XG4gKi9cbmNsYXNzIERvbUV2ZW50SGFuZGxlIGV4dGVuZHMgRXZlbnRIYW5kbGUge1xuXHQvKipcblx0ICogVGhlIGNvbnN0cnVjdG9yIGZvciBgRG9tRXZlbnRIYW5kbGVgLlxuXHQgKiBAcGFyYW0geyFFdmVudEVtaXR0ZXJ9IGVtaXR0ZXIgRW1pdHRlciB0aGUgZXZlbnQgd2FzIHN1YnNjcmliZWQgdG8uXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCB3YXMgc3Vic2NyaWJlZCB0by5cblx0ICogQHBhcmFtIHshRnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC5cblx0ICogQHBhcmFtIHtib29sZWFufSBvcHRfY2FwdHVyZSBGbGFnIGluZGljYXRpbmcgaWYgbGlzdGVuZXIgc2hvdWxkIGJlIHRyaWdnZXJlZFxuXHQgKiAgIGR1cmluZyBjYXB0dXJlIHBoYXNlLCBpbnN0ZWFkIG9mIGR1cmluZyB0aGUgYnViYmxpbmcgcGhhc2UuIERlZmF1bHRzIHRvIGZhbHNlLlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKGVtaXR0ZXIsIGV2ZW50LCBsaXN0ZW5lciwgb3B0X2NhcHR1cmUpIHtcblx0XHRzdXBlcihlbWl0dGVyLCBldmVudCwgbGlzdGVuZXIpO1xuXHRcdHRoaXMuY2FwdHVyZV8gPSBvcHRfY2FwdHVyZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0cmVtb3ZlTGlzdGVuZXIoKSB7XG5cdFx0dGhpcy5lbWl0dGVyXy5yZW1vdmVFdmVudExpc3RlbmVyKHRoaXMuZXZlbnRfLCB0aGlzLmxpc3RlbmVyXywgdGhpcy5jYXB0dXJlXyk7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRG9tRXZlbnRIYW5kbGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmLCBpc0RvY3VtZW50LCBpc0RvY3VtZW50RnJhZ21lbnQsIGlzRWxlbWVudCwgaXNPYmplY3QsIGlzU3RyaW5nLCBvYmplY3QgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgZG9tRGF0YSBmcm9tICcuL2RvbURhdGEnO1xuaW1wb3J0IERvbURlbGVnYXRlZEV2ZW50SGFuZGxlIGZyb20gJy4vRG9tRGVsZWdhdGVkRXZlbnRIYW5kbGUnO1xuaW1wb3J0IERvbUV2ZW50SGFuZGxlIGZyb20gJy4vRG9tRXZlbnRIYW5kbGUnO1xuXG5jb25zdCBlbGVtZW50c0J5VGFnXyA9IHt9O1xuY29uc3Qgc3VwcG9ydENhY2hlXyA9IHt9O1xuZXhwb3J0IGNvbnN0IGN1c3RvbUV2ZW50cyA9IHt9O1xuXG5jb25zdCBMQVNUX0NPTlRBSU5FUiA9ICdfX21ldGFsX2xhc3RfY29udGFpbmVyX18nO1xuY29uc3QgVVNFX0NBUFRVUkUgPSB7XG5cdGJsdXI6IHRydWUsXG5cdGVycm9yOiB0cnVlLFxuXHRmb2N1czogdHJ1ZSxcblx0aW52YWxpZDogdHJ1ZSxcblx0bG9hZDogdHJ1ZSxcblx0c2Nyb2xsOiB0cnVlXG59O1xuXG4vKipcbiAqIEFkZHMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyB0byBhbiBlbGVtZW50LlxuICogQHBhcmFtIHshRWxlbWVudHwhTm9kZWxpc3R9IGVsZW1lbnRzIFRoZSBlbGVtZW50IG9yIGVsZW1lbnRzIHRvIGFkZCBDU1MgY2xhc3NlcyB0by5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIGFkZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZENsYXNzZXMoZWxlbWVudHMsIGNsYXNzZXMpIHtcblx0aWYgKCFpc09iamVjdChlbGVtZW50cykgfHwgIWlzU3RyaW5nKGNsYXNzZXMpKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0aWYgKCFlbGVtZW50cy5sZW5ndGgpIHtcblx0XHRlbGVtZW50cyA9IFtlbGVtZW50c107XG5cdH1cblxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKCdjbGFzc0xpc3QnIGluIGVsZW1lbnRzW2ldKSB7XG5cdFx0XHRhZGRDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhZGRDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIEFkZHMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyB0byBhbiBlbGVtZW50IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gYWRkIENTUyBjbGFzc2VzIHRvLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgQ1NTIGNsYXNzZXMgdG8gYWRkLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkQ2xhc3Nlc1dpdGhOYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpIHtcblx0Y2xhc3Nlcy5zcGxpdCgnICcpLmZvckVhY2goZnVuY3Rpb24oY2xhc3NOYW1lKSB7XG5cdFx0aWYgKGNsYXNzTmFtZSkge1xuXHRcdFx0ZWxlbWVudC5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuLyoqXG4gKiBBZGRzIHRoZSByZXF1ZXN0ZWQgQ1NTIGNsYXNzZXMgdG8gYW4gZWxlbWVudCB3aXRob3V0IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gYWRkIENTUyBjbGFzc2VzIHRvLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgQ1NTIGNsYXNzZXMgdG8gYWRkLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkQ2xhc3Nlc1dpdGhvdXROYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpIHtcblx0Y29uc3QgZWxlbWVudENsYXNzTmFtZSA9IGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYDtcblx0bGV0IGNsYXNzZXNUb0FwcGVuZCA9ICcnO1xuXG5cdGNsYXNzZXMgPSBjbGFzc2VzLnNwbGl0KCcgJyk7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjbGFzc2VzLmxlbmd0aDsgaSsrKSB7XG5cdFx0Y29uc3QgY2xhc3NOYW1lID0gY2xhc3Nlc1tpXTtcblxuXHRcdGlmIChlbGVtZW50Q2xhc3NOYW1lLmluZGV4T2YoYCAke2NsYXNzTmFtZX0gYCkgPT09IC0xKSB7XG5cdFx0XHRjbGFzc2VzVG9BcHBlbmQgKz0gYCAke2NsYXNzTmFtZX1gO1xuXHRcdH1cblx0fVxuXG5cdGlmIChjbGFzc2VzVG9BcHBlbmQpIHtcblx0XHRlbGVtZW50LmNsYXNzTmFtZSA9IGVsZW1lbnQuY2xhc3NOYW1lICsgY2xhc3Nlc1RvQXBwZW5kO1xuXHR9XG59XG5cbi8qKlxuICogQWRkcyBhbiBldmVudCBsaXN0ZW5lciB0byB0aGUgZ2l2ZW4gZWxlbWVudCwgdG8gYmUgdHJpZ2dlcmVkIHZpYSBkZWxlZ2F0ZS5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCl9IGxpc3RlbmVyXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBhZGRFbGVtZW50TGlzdGVuZXJfKGVsZW1lbnQsIGV2ZW50TmFtZSwgbGlzdGVuZXIpIHtcblx0YWRkVG9BcnJfKGRvbURhdGEuZ2V0KGVsZW1lbnQsICdsaXN0ZW5lcnMnLCB7fSksIGV2ZW50TmFtZSwgbGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIEFkZHMgYW4gZXZlbnQgbGlzdGVuZXIgdG8gdGhlIGdpdmVuIGVsZW1lbnQsIHRvIGJlIHRyaWdnZXJlZCB2aWEgZGVsZWdhdGVcbiAqIHNlbGVjdG9ycy5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICogQHBhcmFtIHshZnVuY3Rpb24oKX0gbGlzdGVuZXJcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGFkZFNlbGVjdG9yTGlzdGVuZXJfKGVsZW1lbnQsIGV2ZW50TmFtZSwgc2VsZWN0b3IsIGxpc3RlbmVyKSB7XG5cdGNvbnN0IGRlbGVnYXRpbmdEYXRhID0gZG9tRGF0YS5nZXQoZWxlbWVudCwgJ2RlbGVnYXRpbmcnLCB7fSk7XG5cdGFkZFRvQXJyXyhkZWxlZ2F0aW5nRGF0YVtldmVudE5hbWVdLnNlbGVjdG9ycywgc2VsZWN0b3IsIGxpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBBZGRzIGEgdmFsdWUgdG8gYW4gYXJyYXkgaW5zaWRlIGFuIG9iamVjdCwgY3JlYXRpbmcgaXQgZmlyc3QgaWYgaXQgZG9lc24ndFxuICogeWV0IGV4aXN0LlxuICogQHBhcmFtIHshQXJyYXl9IGFyclxuICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICogQHBhcmFtIHsqfSB2YWx1ZVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkVG9BcnJfKGFyciwga2V5LCB2YWx1ZSkge1xuXHRpZiAoIWFycltrZXldKSB7XG5cdFx0YXJyW2tleV0gPSBbXTtcblx0fVxuXHRhcnJba2V5XS5wdXNoKHZhbHVlKTtcbn1cblxuLyoqXG4gKiBBdHRhY2hlcyBhIGRlbGVnYXRlIGxpc3RlbmVyLCB1bmxlc3MgdGhlcmUncyBhbHJlYWR5IG9uZSBhdHRhY2hlZC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGF0dGFjaERlbGVnYXRlRXZlbnRfKGVsZW1lbnQsIGV2ZW50TmFtZSkge1xuXHRsZXQgZGVsZWdhdGluZ0RhdGEgPSBkb21EYXRhLmdldChlbGVtZW50LCAnZGVsZWdhdGluZycsIHt9KTtcblx0aWYgKCFkZWxlZ2F0aW5nRGF0YVtldmVudE5hbWVdKSB7XG5cdFx0ZGVsZWdhdGluZ0RhdGFbZXZlbnROYW1lXSA9IHtcblx0XHRcdGhhbmRsZTogb24oXG5cdFx0XHRcdGVsZW1lbnQsXG5cdFx0XHRcdGV2ZW50TmFtZSxcblx0XHRcdFx0aGFuZGxlRGVsZWdhdGVFdmVudF8sXG5cdFx0XHRcdCEhVVNFX0NBUFRVUkVbZXZlbnROYW1lXVxuXHRcdFx0KSxcblx0XHRcdHNlbGVjdG9yczoge31cblx0XHR9O1xuXHR9XG59XG5cbi8qKlxuICogR2V0cyB0aGUgY2xvc2VzdCBlbGVtZW50IHVwIHRoZSB0cmVlIGZyb20gdGhlIGdpdmVuIGVsZW1lbnQgKGluY2x1ZGluZ1xuICogaXRzZWxmKSB0aGF0IG1hdGNoZXMgdGhlIHNwZWNpZmllZCBzZWxlY3Rvciwgb3IgbnVsbCBpZiBub25lIG1hdGNoLlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JcbiAqIEByZXR1cm4ge0VsZW1lbnR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbG9zZXN0KGVsZW1lbnQsIHNlbGVjdG9yKSB7XG5cdHdoaWxlIChlbGVtZW50ICYmICFtYXRjaChlbGVtZW50LCBzZWxlY3RvcikpIHtcblx0XHRlbGVtZW50ID0gZWxlbWVudC5wYXJlbnROb2RlO1xuXHR9XG5cdHJldHVybiBlbGVtZW50O1xufVxuXG4vKipcbiAqIEFwcGVuZHMgYSBjaGlsZCBub2RlIHdpdGggdGV4dCBvciBvdGhlciBub2RlcyB0byBhIHBhcmVudCBub2RlLiBJZlxuICogY2hpbGQgaXMgYSBIVE1MIHN0cmluZyBpdCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgY29udmVydGVkIHRvIGEgZG9jdW1lbnRcbiAqIGZyYWdtZW50IGJlZm9yZSBhcHBlbmRpbmcgaXQgdG8gdGhlIHBhcmVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IHBhcmVudCBUaGUgbm9kZSB0byBhcHBlbmQgbm9kZXMgdG8uXG4gKiBAcGFyYW0geyEoRWxlbWVudHxOb2RlTGlzdHxzdHJpbmcpfSBjaGlsZCBUaGUgdGhpbmcgdG8gYXBwZW5kIHRvIHRoZSBwYXJlbnQuXG4gKiBAcmV0dXJuIHshRWxlbWVudH0gVGhlIGFwcGVuZGVkIGNoaWxkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwZW5kKHBhcmVudCwgY2hpbGQpIHtcblx0aWYgKGlzU3RyaW5nKGNoaWxkKSkge1xuXHRcdGNoaWxkID0gYnVpbGRGcmFnbWVudChjaGlsZCk7XG5cdH1cblx0aWYgKGNoaWxkIGluc3RhbmNlb2YgTm9kZUxpc3QpIHtcblx0XHRjb25zdCBjaGlsZEFyciA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGNoaWxkKTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkQXJyLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRwYXJlbnQuYXBwZW5kQ2hpbGQoY2hpbGRBcnJbaV0pO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRwYXJlbnQuYXBwZW5kQ2hpbGQoY2hpbGQpO1xuXHR9XG5cdHJldHVybiBjaGlsZDtcbn1cblxuLyoqXG4gKiBIZWxwZXIgZm9yIGNvbnZlcnRpbmcgYSBIVE1MIHN0cmluZyBpbnRvIGEgZG9jdW1lbnQgZnJhZ21lbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gaHRtbFN0cmluZyBUaGUgSFRNTCBzdHJpbmcgdG8gY29udmVydC5cbiAqIEByZXR1cm4geyFFbGVtZW50fSBUaGUgcmVzdWx0aW5nIGRvY3VtZW50IGZyYWdtZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRGcmFnbWVudChodG1sU3RyaW5nKSB7XG5cdGNvbnN0IHRlbXBEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblx0dGVtcERpdi5pbm5lckhUTUwgPSBgPGJyPiR7aHRtbFN0cmluZ31gO1xuXHR0ZW1wRGl2LnJlbW92ZUNoaWxkKHRlbXBEaXYuZmlyc3RDaGlsZCk7XG5cblx0Y29uc3QgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cdHdoaWxlICh0ZW1wRGl2LmZpcnN0Q2hpbGQpIHtcblx0XHRmcmFnbWVudC5hcHBlbmRDaGlsZCh0ZW1wRGl2LmZpcnN0Q2hpbGQpO1xuXHR9XG5cdHJldHVybiBmcmFnbWVudDtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGZpcnN0IGVsZW1lbnQgY29udGFpbnMgdGhlIHNlY29uZCBvbmUuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50MVxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudDJcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb250YWlucyhlbGVtZW50MSwgZWxlbWVudDIpIHtcblx0aWYgKGlzRG9jdW1lbnQoZWxlbWVudDEpKSB7XG5cdFx0Ly8gZG9jdW1lbnQuY29udGFpbnMgaXMgbm90IGRlZmluZWQgb24gSUU5LCBzbyBjYWxsIGl0IG9uIGRvY3VtZW50RWxlbWVudCBpbnN0ZWFkLlxuXHRcdHJldHVybiBlbGVtZW50MS5kb2N1bWVudEVsZW1lbnQuY29udGFpbnMoZWxlbWVudDIpO1xuXHR9IGVsc2Uge1xuXHRcdHJldHVybiBlbGVtZW50MS5jb250YWlucyhlbGVtZW50Mik7XG5cdH1cbn1cblxuLyoqXG4gKiBMaXN0ZW5zIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQgb24gdGhlIGdpdmVuIERPTSBlbGVtZW50LCBidXQgb25seSBjYWxscyB0aGVcbiAqIGdpdmVuIGNhbGxiYWNrIGxpc3RlbmVyIHdoZW4gaXQncyB0cmlnZ2VyZWQgYnkgZWxlbWVudHMgdGhhdCBtYXRjaCB0aGVcbiAqIGdpdmVuIHNlbGVjdG9yIG9yIHRhcmdldCBlbGVtZW50LlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgRE9NIGVsZW1lbnQgdGhlIGV2ZW50IHNob3VsZCBiZSBsaXN0ZW5lZCBvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGxpc3RlbiB0by5cbiAqIEBwYXJhbSB7IUVsZW1lbnR8c3RyaW5nfSBzZWxlY3Rvck9yVGFyZ2V0IEVpdGhlciBhbiBlbGVtZW50IG9yIGNzcyBzZWxlY3RvclxuICogICAgIHRoYXQgc2hvdWxkIG1hdGNoIHRoZSBldmVudCBmb3IgdGhlIGxpc3RlbmVyIHRvIGJlIHRyaWdnZXJlZC5cbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCFPYmplY3QpfSBjYWxsYmFjayBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnRcbiAqICAgICBpcyB0cmlnZ2VyZWQuIEl0IHdpbGwgcmVjZWl2ZSB0aGUgbm9ybWFsaXplZCBldmVudCBvYmplY3QuXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfZGVmYXVsdCBPcHRpb25hbCBmbGFnIGluZGljYXRpbmcgaWYgdGhpcyBpcyBhIGRlZmF1bHRcbiAqICAgICBsaXN0ZW5lci4gVGhhdCBtZWFucyB0aGF0IGl0IHdvdWxkIG9ubHkgYmUgZXhlY3V0ZWQgYWZ0ZXIgYWxsIG5vblxuICogICAgIGRlZmF1bHQgbGlzdGVuZXJzLCBhbmQgb25seSBpZiB0aGUgZXZlbnQgaXNuJ3QgcHJldmVudGVkIHZpYVxuICogICAgIGBwcmV2ZW50RGVmYXVsdGAuXG4gKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWxlZ2F0ZShlbGVtZW50LCBldmVudE5hbWUsIHNlbGVjdG9yT3JUYXJnZXQsIGNhbGxiYWNrLCBvcHRfZGVmYXVsdCkge1xuXHRjb25zdCBjdXN0b21Db25maWcgPSBjdXN0b21FdmVudHNbZXZlbnROYW1lXTtcblx0aWYgKGN1c3RvbUNvbmZpZyAmJiBjdXN0b21Db25maWcuZGVsZWdhdGUpIHtcblx0XHRldmVudE5hbWUgPSBjdXN0b21Db25maWcub3JpZ2luYWxFdmVudDtcblx0XHRjYWxsYmFjayA9IGN1c3RvbUNvbmZpZy5oYW5kbGVyLmJpbmQoY3VzdG9tQ29uZmlnLCBjYWxsYmFjayk7XG5cdH1cblxuXHRpZiAob3B0X2RlZmF1bHQpIHtcblx0XHQvLyBXcmFwIGNhbGxiYWNrIHNvIHdlIGRvbid0IHNldCBwcm9wZXJ0eSBkaXJlY3RseSBvbiBpdC5cblx0XHRjYWxsYmFjayA9IGNhbGxiYWNrLmJpbmQoKTtcblx0XHRjYWxsYmFjay5kZWZhdWx0TGlzdGVuZXJfID0gdHJ1ZTtcblx0fVxuXG5cdGF0dGFjaERlbGVnYXRlRXZlbnRfKGVsZW1lbnQsIGV2ZW50TmFtZSk7XG5cdGlmIChpc1N0cmluZyhzZWxlY3Rvck9yVGFyZ2V0KSkge1xuXHRcdGFkZFNlbGVjdG9yTGlzdGVuZXJfKGVsZW1lbnQsIGV2ZW50TmFtZSwgc2VsZWN0b3JPclRhcmdldCwgY2FsbGJhY2spO1xuXHR9IGVsc2Uge1xuXHRcdGFkZEVsZW1lbnRMaXN0ZW5lcl8oc2VsZWN0b3JPclRhcmdldCwgZXZlbnROYW1lLCBjYWxsYmFjayk7XG5cdH1cblxuXHRyZXR1cm4gbmV3IERvbURlbGVnYXRlZEV2ZW50SGFuZGxlKFxuXHRcdGlzU3RyaW5nKHNlbGVjdG9yT3JUYXJnZXQpID8gZWxlbWVudCA6IHNlbGVjdG9yT3JUYXJnZXQsXG5cdFx0ZXZlbnROYW1lLFxuXHRcdGNhbGxiYWNrLFxuXHRcdGlzU3RyaW5nKHNlbGVjdG9yT3JUYXJnZXQpID8gc2VsZWN0b3JPclRhcmdldCA6IG51bGxcblx0KTtcbn1cblxuLyoqXG4gKiBWZXJpZmllcyBpZiB0aGUgZWxlbWVudCBpcyBhYmxlIHRvIHRyaWdnZXIgdGhlIENsaWNrIGV2ZW50LFxuICogc2ltdWxhdGluZyBicm93c2VycyBiZWhhdmlvdXIsIGF2b2lkaW5nIGV2ZW50IGxpc3RlbmVycyB0byBiZSBjYWxsZWQgYnkgdHJpZ2dlckV2ZW50IG1ldGhvZC5cbiAqIEBwYXJhbSB7RWxlbWVudH0gbm9kZSBFbGVtZW50IHRvIGJlIGNoZWNrZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIFRoZSBldmVudCBuYW1lLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gaXNBYmxlVG9JbnRlcmFjdFdpdGhfKG5vZGUsIGV2ZW50TmFtZSwgb3B0X2V2ZW50T2JqKSB7XG5cdGlmIChvcHRfZXZlbnRPYmogJiYgZXZlbnROYW1lID09PSAnY2xpY2snICYmIG9wdF9ldmVudE9iai5idXR0b24gPT09IDIpIHtcblx0XHQvLyBGaXJlZm94IHRyaWdnZXJzIFwiY2xpY2tcIiBldmVudHMgb24gdGhlIGRvY3VtZW50IGZvciByaWdodCBjbGlja3MuIFRoaXNcblx0XHQvLyBjYXVzZXMgb3VyIGRlbGVnYXRlIGxvZ2ljIHRvIHRyaWdnZXIgaXQgZm9yIHJlZ3VsYXIgZWxlbWVudHMgdG9vLCB3aGljaFxuXHRcdC8vIHNob3VsZG4ndCBoYXBwZW4uIElnbm9yaW5nIHRoZW0gaGVyZS5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRjb25zdCBtYXRjaGVzU2VsZWN0b3IgPSBbJ0JVVFRPTicsICdJTlBVVCcsICdTRUxFQ1QnLCAnVEVYVEFSRUEnLCAnRklFTERTRVQnXTtcblx0aWYgKGV2ZW50TmFtZSA9PT0gJ2NsaWNrJyAmJiBtYXRjaGVzU2VsZWN0b3IuaW5kZXhPZihub2RlLnRhZ05hbWUpID4gLTEpIHtcblx0XHRyZXR1cm4gIShub2RlLmRpc2FibGVkIHx8IHBhcmVudChub2RlLCAnZmllbGRzZXRbZGlzYWJsZWRdJykpO1xuXHR9XG5cdHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEluc2VydHMgbm9kZSBpbiBkb2N1bWVudCBhcyBsYXN0IGVsZW1lbnQuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGUgRWxlbWVudCB0byByZW1vdmUgY2hpbGRyZW4gZnJvbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVudGVyRG9jdW1lbnQobm9kZSkge1xuXHRub2RlICYmIGFwcGVuZChkb2N1bWVudC5ib2R5LCBub2RlKTtcbn1cblxuLyoqXG4gKiBSZW1vdmVzIG5vZGUgZnJvbSBkb2N1bWVudC5cbiAqIEBwYXJhbSB7RWxlbWVudH0gbm9kZSBFbGVtZW50IHRvIHJlbW92ZSBjaGlsZHJlbiBmcm9tLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXhpdERvY3VtZW50KG5vZGUpIHtcblx0aWYgKG5vZGUgJiYgbm9kZS5wYXJlbnROb2RlKSB7XG5cdFx0bm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuXHR9XG59XG5cbi8qKlxuICogVGhpcyBpcyBjYWxsZWQgd2hlbiBhbiBldmVudCBpcyB0cmlnZ2VyZWQgYnkgYSBkZWxlZ2F0ZSBsaXN0ZW5lci4gQWxsXG4gKiBtYXRjaGluZyBsaXN0ZW5lcnMgb2YgdGhpcyBldmVudCB0eXBlIGZyb20gYHRhcmdldGAgdG8gYGN1cnJlbnRUYXJnZXRgIHdpbGxcbiAqIGJlIHRyaWdnZXJlZC5cbiAqIEBwYXJhbSB7IUV2ZW50fSBldmVudCBUaGUgZXZlbnQgcGF5bG9hZC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IEZhbHNlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdHJpZ2dlcmVkIGNhbGxiYWNrcyByZXR1cm5zXG4gKiAgICAgZmFsc2UsIG9yIHRydWUgb3RoZXJ3aXNlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gaGFuZGxlRGVsZWdhdGVFdmVudF8oZXZlbnQpIHtcblx0bm9ybWFsaXplRGVsZWdhdGVFdmVudF8oZXZlbnQpO1xuXHRsZXQgcmV0ID0gdHJ1ZTtcblx0Y29uc3QgY29udGFpbmVyID0gZXZlbnQuY3VycmVudFRhcmdldDtcblx0Y29uc3QgZGVmRm5zID0gW107XG5cblx0cmV0ICY9IHRyaWdnZXJEZWxlZ2F0ZWRMaXN0ZW5lcnNfKGNvbnRhaW5lciwgZXZlbnQsIGRlZkZucyk7XG5cdHJldCAmPSB0cmlnZ2VyRGVmYXVsdERlbGVnYXRlZExpc3RlbmVyc18oZGVmRm5zLCBldmVudCk7XG5cblx0ZXZlbnQuZGVsZWdhdGVUYXJnZXQgPSBudWxsO1xuXHRldmVudFtMQVNUX0NPTlRBSU5FUl0gPSBjb250YWluZXI7XG5cdHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IGhhcyB0aGUgcmVxdWVzdGVkIGNzcyBjbGFzcy5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc05hbWVcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNDbGFzcyhlbGVtZW50LCBjbGFzc05hbWUpIHtcblx0aWYgKCdjbGFzc0xpc3QnIGluIGVsZW1lbnQpIHtcblx0XHRyZXR1cm4gaGFzQ2xhc3NXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc05hbWUpO1xuXHR9IGVsc2Uge1xuXHRcdHJldHVybiBoYXNDbGFzc1dpdGhvdXROYXRpdmVfKGVsZW1lbnQsIGNsYXNzTmFtZSk7XG5cdH1cbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGdpdmVuIGVsZW1lbnQgaGFzIHRoZSByZXF1ZXN0ZWQgY3NzIGNsYXNzIHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc05hbWVcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBoYXNDbGFzc1dpdGhOYXRpdmVfKGVsZW1lbnQsIGNsYXNzTmFtZSkge1xuXHRyZXR1cm4gZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NOYW1lKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGdpdmVuIGVsZW1lbnQgaGFzIHRoZSByZXF1ZXN0ZWQgY3NzIGNsYXNzIHdpdGhvdXQgdXNpbmcgY2xhc3NMaXN0LlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzTmFtZVxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGhhc0NsYXNzV2l0aG91dE5hdGl2ZV8oZWxlbWVudCwgY2xhc3NOYW1lKSB7XG5cdHJldHVybiAoYCAke2VsZW1lbnQuY2xhc3NOYW1lfSBgKS5pbmRleE9mKGAgJHtjbGFzc05hbWV9IGApID49IDA7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBlbGVtZW50IGlzIGVtcHR5IG9yIG5vdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0VtcHR5KGVsZW1lbnQpIHtcblx0cmV0dXJuIGVsZW1lbnQuY2hpbGROb2Rlcy5sZW5ndGggPT09IDA7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgYW4gZWxlbWVudCBtYXRjaGVzIGEgZ2l2ZW4gc2VsZWN0b3IuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoKGVsZW1lbnQsIHNlbGVjdG9yKSB7XG5cdGlmICghZWxlbWVudCB8fCBlbGVtZW50Lm5vZGVUeXBlICE9PSAxKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Y29uc3QgcCA9IEVsZW1lbnQucHJvdG90eXBlO1xuXHRjb25zdCBtID0gcC5tYXRjaGVzIHx8IHAud2Via2l0TWF0Y2hlc1NlbGVjdG9yIHx8IHAubW96TWF0Y2hlc1NlbGVjdG9yIHx8IHAubXNNYXRjaGVzU2VsZWN0b3IgfHwgcC5vTWF0Y2hlc1NlbGVjdG9yO1xuXHRpZiAobSkge1xuXHRcdHJldHVybiBtLmNhbGwoZWxlbWVudCwgc2VsZWN0b3IpO1xuXHR9XG5cblx0cmV0dXJuIG1hdGNoRmFsbGJhY2tfKGVsZW1lbnQsIHNlbGVjdG9yKTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhbiBlbGVtZW50IG1hdGNoZXMgYSBnaXZlbiBzZWxlY3RvciwgdXNpbmcgYW4gaW50ZXJuYWwgaW1wbGVtZW50YXRpb25cbiAqIGluc3RlYWQgb2YgY2FsbGluZyBleGlzdGluZyBqYXZhc2NyaXB0IGZ1bmN0aW9ucy5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gbWF0Y2hGYWxsYmFja18oZWxlbWVudCwgc2VsZWN0b3IpIHtcblx0Y29uc3Qgbm9kZXMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yLCBlbGVtZW50LnBhcmVudE5vZGUpO1xuXHRmb3IgKGxldCBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgKytpKSB7XG5cdFx0aWYgKG5vZGVzW2ldID09PSBlbGVtZW50KSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIG5leHQgc2libGluZyBvZiB0aGUgZ2l2ZW4gZWxlbWVudCB0aGF0IG1hdGNoZXMgdGhlIHNwZWNpZmllZFxuICogc2VsZWN0b3IsIG9yIG51bGwgaWYgdGhlcmUgaXMgbm9uZS5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7P3N0cmluZ30gc2VsZWN0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5leHQoZWxlbWVudCwgc2VsZWN0b3IpIHtcblx0ZG8ge1xuXHRcdGVsZW1lbnQgPSBlbGVtZW50Lm5leHRTaWJsaW5nO1xuXHRcdGlmIChlbGVtZW50ICYmIG1hdGNoKGVsZW1lbnQsIHNlbGVjdG9yKSkge1xuXHRcdFx0cmV0dXJuIGVsZW1lbnQ7XG5cdFx0fVxuXHR9IHdoaWxlIChlbGVtZW50KTtcblx0cmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogTm9ybWFsaXplcyB0aGUgZXZlbnQgcGF5bG9hZCBmb3IgZGVsZWdhdGUgbGlzdGVuZXJzLlxuICogQHBhcmFtIHshRXZlbnR9IGV2ZW50XG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBub3JtYWxpemVEZWxlZ2F0ZUV2ZW50XyhldmVudCkge1xuXHRldmVudC5zdG9wUHJvcGFnYXRpb24gPSBzdG9wUHJvcGFnYXRpb25fO1xuXHRldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24gPSBzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb25fO1xufVxuXG4vKipcbiAqIExpc3RlbnMgdG8gdGhlIHNwZWNpZmllZCBldmVudCBvbiB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQuIFRoaXMgZnVuY3Rpb24gbm9ybWFsaXplc1xuICogRE9NIGV2ZW50IHBheWxvYWRzIGFuZCBmdW5jdGlvbnMgc28gdGhleSdsbCB3b3JrIHRoZSBzYW1lIHdheSBvbiBhbGwgc3VwcG9ydGVkXG4gKiBicm93c2Vycy5cbiAqIEBwYXJhbSB7IUVsZW1lbnR8c3RyaW5nfSBlbGVtZW50IFRoZSBET00gZWxlbWVudCB0byBsaXN0ZW4gdG8gdGhlIGV2ZW50IG9uLCBvclxuICogICBhIHNlbGVjdG9yIHRoYXQgc2hvdWxkIGJlIGRlbGVnYXRlZCBvbiB0aGUgZW50aXJlIGRvY3VtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gbGlzdGVuIHRvLlxuICogQHBhcmFtIHshZnVuY3Rpb24oIU9iamVjdCl9IGNhbGxiYWNrIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpc1xuICogICB0cmlnZ2VyZWQuIEl0IHdpbGwgcmVjZWl2ZSB0aGUgbm9ybWFsaXplZCBldmVudCBvYmplY3QuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG9wdF9jYXB0dXJlIEZsYWcgaW5kaWNhdGluZyBpZiBsaXN0ZW5lciBzaG91bGQgYmUgdHJpZ2dlcmVkXG4gKiAgIGR1cmluZyBjYXB0dXJlIHBoYXNlLCBpbnN0ZWFkIG9mIGR1cmluZyB0aGUgYnViYmxpbmcgcGhhc2UuIERlZmF1bHRzIHRvIGZhbHNlLlxuICogQHJldHVybiB7IURvbUV2ZW50SGFuZGxlfSBDYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gb24oZWxlbWVudCwgZXZlbnROYW1lLCBjYWxsYmFjaywgb3B0X2NhcHR1cmUpIHtcblx0aWYgKGlzU3RyaW5nKGVsZW1lbnQpKSB7XG5cdFx0cmV0dXJuIGRlbGVnYXRlKGRvY3VtZW50LCBldmVudE5hbWUsIGVsZW1lbnQsIGNhbGxiYWNrKTtcblx0fVxuXHRjb25zdCBjdXN0b21Db25maWcgPSBjdXN0b21FdmVudHNbZXZlbnROYW1lXTtcblx0aWYgKGN1c3RvbUNvbmZpZyAmJiBjdXN0b21Db25maWcuZXZlbnQpIHtcblx0XHRldmVudE5hbWUgPSBjdXN0b21Db25maWcub3JpZ2luYWxFdmVudDtcblx0XHRjYWxsYmFjayA9IGN1c3RvbUNvbmZpZy5oYW5kbGVyLmJpbmQoY3VzdG9tQ29uZmlnLCBjYWxsYmFjayk7XG5cdH1cblx0ZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG9wdF9jYXB0dXJlKTtcblx0cmV0dXJuIG5ldyBEb21FdmVudEhhbmRsZShlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRfY2FwdHVyZSk7XG59XG5cbi8qKlxuICogTGlzdGVucyB0byB0aGUgc3BlY2lmaWVkIGV2ZW50IG9uIHRoZSBnaXZlbiBET00gZWxlbWVudCBvbmNlLiBUaGlzXG4gKiBmdW5jdGlvbiBub3JtYWxpemVzIERPTSBldmVudCBwYXlsb2FkcyBhbmQgZnVuY3Rpb25zIHNvIHRoZXknbGwgd29yayB0aGVcbiAqIHNhbWUgd2F5IG9uIGFsbCBzdXBwb3J0ZWQgYnJvd3NlcnMuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBET00gZWxlbWVudCB0byBsaXN0ZW4gdG8gdGhlIGV2ZW50IG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gbGlzdGVuIHRvLlxuICogQHBhcmFtIHshZnVuY3Rpb24oIU9iamVjdCl9IGNhbGxiYWNrIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudFxuICogICBpcyB0cmlnZ2VyZWQuIEl0IHdpbGwgcmVjZWl2ZSB0aGUgbm9ybWFsaXplZCBldmVudCBvYmplY3QuXG4gKiBAcmV0dXJuIHshRG9tRXZlbnRIYW5kbGV9IENhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbmNlKGVsZW1lbnQsIGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcblx0Y29uc3QgZG9tRXZlbnRIYW5kbGUgPSBvbihlbGVtZW50LCBldmVudE5hbWUsIGZ1bmN0aW9uKCkge1xuXHRcdGRvbUV2ZW50SGFuZGxlLnJlbW92ZUxpc3RlbmVyKCk7XG5cdFx0cmV0dXJuIGNhbGxiYWNrLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG5cdH0pO1xuXHRyZXR1cm4gZG9tRXZlbnRIYW5kbGU7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgZmlyc3QgcGFyZW50IGZyb20gdGhlIGdpdmVuIGVsZW1lbnQgdGhhdCBtYXRjaGVzIHRoZSBzcGVjaWZpZWRcbiAqIHNlbGVjdG9yLCBvciBudWxsIGlmIG5vbmUgbWF0Y2guXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JcbiAqIEByZXR1cm4ge0VsZW1lbnR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJlbnQoZWxlbWVudCwgc2VsZWN0b3IpIHtcblx0cmV0dXJuIGNsb3Nlc3QoZWxlbWVudC5wYXJlbnROb2RlLCBzZWxlY3Rvcik7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgY3VzdG9tIGV2ZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgY3VzdG9tIGV2ZW50LlxuICogQHBhcmFtIHshT2JqZWN0fSBjdXN0b21Db25maWcgQW4gb2JqZWN0IHdpdGggaW5mb3JtYXRpb24gYWJvdXQgaG93IHRoZSBldmVudFxuICogICBzaG91bGQgYmUgaGFuZGxlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCBjdXN0b21Db25maWcpIHtcblx0Y3VzdG9tRXZlbnRzW2V2ZW50TmFtZV0gPSBjdXN0b21Db25maWc7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBhbGwgdGhlIGNoaWxkIG5vZGVzIG9uIGEgRE9NIG5vZGUuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGUgRWxlbWVudCB0byByZW1vdmUgY2hpbGRyZW4gZnJvbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUNoaWxkcmVuKG5vZGUpIHtcblx0bGV0IGNoaWxkO1xuXHR3aGlsZSAoKGNoaWxkID0gbm9kZS5maXJzdENoaWxkKSkge1xuXHRcdG5vZGUucmVtb3ZlQ2hpbGQoY2hpbGQpO1xuXHR9XG59XG5cbi8qKlxuICogUmVtb3ZlcyB0aGUgcmVxdWVzdGVkIENTUyBjbGFzc2VzIGZyb20gYW4gZWxlbWVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR8IU5vZGVMaXN0fSBlbGVtZW50cyBUaGUgZWxlbWVudCBvciBlbGVtZW50cyB0byByZW1vdmUgQ1NTIGNsYXNzZXMgZnJvbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIHJlbW92ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUNsYXNzZXMoZWxlbWVudHMsIGNsYXNzZXMpIHtcblx0aWYgKCFpc09iamVjdChlbGVtZW50cykgfHwgIWlzU3RyaW5nKGNsYXNzZXMpKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0aWYgKCFlbGVtZW50cy5sZW5ndGgpIHtcblx0XHRlbGVtZW50cyA9IFtlbGVtZW50c107XG5cdH1cblxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKCdjbGFzc0xpc3QnIGluIGVsZW1lbnRzW2ldKSB7XG5cdFx0XHRyZW1vdmVDbGFzc2VzV2l0aE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZW1vdmVDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudHNbaV0sIGNsYXNzZXMpO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIFJlbW92ZXMgdGhlIHJlcXVlc3RlZCBDU1MgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQgdXNpbmcgY2xhc3NMaXN0LlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB0byByZW1vdmUgQ1NTIGNsYXNzZXMgZnJvbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIENTUyBjbGFzc2VzIHRvIHJlbW92ZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZUNsYXNzZXNXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGNsYXNzZXMuc3BsaXQoJyAnKS5mb3JFYWNoKGZ1bmN0aW9uKGNsYXNzTmFtZSkge1xuXHRcdGlmIChjbGFzc05hbWUpIHtcblx0XHRcdGVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuXHRcdH1cblx0fSk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyB0aGUgcmVxdWVzdGVkIENTUyBjbGFzc2VzIGZyb20gYW4gZWxlbWVudCB3aXRob3V0IHVzaW5nIGNsYXNzTGlzdC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gcmVtb3ZlIENTUyBjbGFzc2VzIGZyb20uXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NlcyBDU1MgY2xhc3NlcyB0byByZW1vdmUuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiByZW1vdmVDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudCwgY2xhc3Nlcykge1xuXHRsZXQgZWxlbWVudENsYXNzTmFtZSA9IGAgJHtlbGVtZW50LmNsYXNzTmFtZX0gYDtcblxuXHRjbGFzc2VzID0gY2xhc3Nlcy5zcGxpdCgnICcpO1xuXG5cdGZvciAobGV0IGkgPSAwOyBpIDwgY2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuXHRcdGVsZW1lbnRDbGFzc05hbWUgPSBlbGVtZW50Q2xhc3NOYW1lLnJlcGxhY2UoYCAke2NsYXNzZXNbaV19IGAsICcgJyk7XG5cdH1cblxuXHRlbGVtZW50LmNsYXNzTmFtZSA9IGVsZW1lbnRDbGFzc05hbWUudHJpbSgpO1xufVxuXG4vKipcbiAqIFJlcGxhY2VzIHRoZSBmaXJzdCBlbGVtZW50IHdpdGggdGhlIHNlY29uZC5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudDFcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudDJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2UoZWxlbWVudDEsIGVsZW1lbnQyKSB7XG5cdGlmIChlbGVtZW50MSAmJiBlbGVtZW50MiAmJiBlbGVtZW50MSAhPT0gZWxlbWVudDIgJiYgZWxlbWVudDEucGFyZW50Tm9kZSkge1xuXHRcdGVsZW1lbnQxLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGVsZW1lbnQyLCBlbGVtZW50MSk7XG5cdFx0ZWxlbWVudDEucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChlbGVtZW50MSk7XG5cdH1cbn1cblxuLyoqXG4gKiBUaGUgZnVuY3Rpb24gdGhhdCByZXBsYWNlcyBgc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uX2AgZm9yIGV2ZW50cy5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbl8oKSB7XG5cdGNvbnN0IGV2ZW50ID0gdGhpczsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRldmVudC5zdG9wcGVkID0gdHJ1ZTtcblx0ZXZlbnQuc3RvcHBlZEltbWVkaWF0ZSA9IHRydWU7XG5cdEV2ZW50LnByb3RvdHlwZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24uY2FsbChldmVudCk7XG59XG5cbi8qKlxuICogVGhlIGZ1bmN0aW9uIHRoYXQgcmVwbGFjZXMgYHN0b3BQcm9wYWdhdGlvbmAgZm9yIGV2ZW50cy5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHN0b3BQcm9wYWdhdGlvbl8oKSB7XG5cdGNvbnN0IGV2ZW50ID0gdGhpczsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRldmVudC5zdG9wcGVkID0gdHJ1ZTtcblx0RXZlbnQucHJvdG90eXBlLnN0b3BQcm9wYWdhdGlvbi5jYWxsKGV2ZW50KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGdpdmVuIGVsZW1lbnQgc3VwcG9ydHMgdGhlIGdpdmVuIGV2ZW50IHR5cGUuXG4gKiBAcGFyYW0geyFFbGVtZW50fHN0cmluZ30gZWxlbWVudCBUaGUgRE9NIGVsZW1lbnQgb3IgZWxlbWVudCB0YWcgbmFtZSB0byBjaGVjay5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGNoZWNrLlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1cHBvcnRzRXZlbnQoZWxlbWVudCwgZXZlbnROYW1lKSB7XG5cdGlmIChjdXN0b21FdmVudHNbZXZlbnROYW1lXSkge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0aWYgKGlzU3RyaW5nKGVsZW1lbnQpKSB7XG5cdFx0aWYgKCFlbGVtZW50c0J5VGFnX1tlbGVtZW50XSkge1xuXHRcdFx0ZWxlbWVudHNCeVRhZ19bZWxlbWVudF0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGVsZW1lbnQpO1xuXHRcdH1cblx0XHRlbGVtZW50ID0gZWxlbWVudHNCeVRhZ19bZWxlbWVudF07XG5cdH1cblxuXHRjb25zdCB0YWcgPSBlbGVtZW50LnRhZ05hbWU7XG5cdGlmICghc3VwcG9ydENhY2hlX1t0YWddIHx8ICFzdXBwb3J0Q2FjaGVfW3RhZ10uaGFzT3duUHJvcGVydHkoZXZlbnROYW1lKSkge1xuXHRcdHN1cHBvcnRDYWNoZV9bdGFnXSA9IHN1cHBvcnRDYWNoZV9bdGFnXSB8fCB7fTtcblx0XHRzdXBwb3J0Q2FjaGVfW3RhZ11bZXZlbnROYW1lXSA9ICdvbicgKyBldmVudE5hbWUgaW4gZWxlbWVudDtcblx0fVxuXHRyZXR1cm4gc3VwcG9ydENhY2hlX1t0YWddW2V2ZW50TmFtZV07XG59XG5cbi8qKlxuICogVGhpcyB0cmlnZ2VycyBhbGwgZGVmYXVsdCBtYXRjaGVkIGRlbGVnYXRlZCBsaXN0ZW5lcnMgb2YgYSBnaXZlbiBldmVudCB0eXBlLlxuICogQHBhcmFtIHshQXJyYXl9IGRlZmF1bHRGbnMgQXJyYXkgdG8gY29sbGVjdCBkZWZhdWx0IGxpc3RlbmVycyBpbiwgaW5zdGVhZFxuICogQHBhcmFtIHshRXZlbnR9IGV2ZW50XG4gKiBAcmV0dXJuIHtib29sZWFufSBGYWxzZSBpZiBhdCBsZWFzdCBvbmUgb2YgdGhlIHRyaWdnZXJlZCBjYWxsYmFja3MgcmV0dXJuc1xuICogICAgIGZhbHNlLCBvciB0cnVlIG90aGVyd2lzZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHRyaWdnZXJEZWZhdWx0RGVsZWdhdGVkTGlzdGVuZXJzXyhkZWZGbnMsIGV2ZW50KSB7XG5cdGxldCByZXQgPSB0cnVlO1xuXG5cdGZvciAobGV0IGkgPSAwOyBpIDwgZGVmRm5zLmxlbmd0aCAmJiAhZXZlbnQuZGVmYXVsdFByZXZlbnRlZDsgaSsrKSB7XG5cdFx0ZXZlbnQuZGVsZWdhdGVUYXJnZXQgPSBkZWZGbnNbaV0uZWxlbWVudDtcblx0XHRyZXQgJj0gZGVmRm5zW2ldLmZuKGV2ZW50KTtcblx0fVxuXG5cdHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogVGhpcyB0cmlnZ2VycyBhbGwgbWF0Y2hlZCBkZWxlZ2F0ZWQgbGlzdGVuZXJzIG9mIGEgZ2l2ZW4gZXZlbnQgdHlwZSB3aGVuIGl0c1xuICogZGVsZWdhdGVkIHRhcmdldCBpcyBhYmxlIHRvIGludGVyYWN0LlxuICogQHBhcmFtIHshRWxlbWVudH0gY29udGFpbmVyXG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnRcbiAqIEBwYXJhbSB7IUFycmF5fSBkZWZhdWx0Rm5zIEFycmF5IHRvIGNvbGxlY3QgZGVmYXVsdCBsaXN0ZW5lcnMgaW4sIGluc3RlYWRcbiAqICAgICBvZiBydW5uaW5nIHRoZW0uXG4gKiBAcmV0dXJuIHtib29sZWFufSBGYWxzZSBpZiBhdCBsZWFzdCBvbmUgb2YgdGhlIHRyaWdnZXJlZCBjYWxsYmFja3MgcmV0dXJuc1xuICogICAgIGZhbHNlLCBvciB0cnVlIG90aGVyd2lzZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHRyaWdnZXJEZWxlZ2F0ZWRMaXN0ZW5lcnNfKGNvbnRhaW5lciwgZXZlbnQsIGRlZmF1bHRGbnMpIHtcblx0bGV0IHJldCA9IHRydWU7XG5cdGxldCBjdXJyRWxlbWVudCA9IGV2ZW50LnRhcmdldDtcblx0Y29uc3QgbGltaXQgPSBjb250YWluZXIucGFyZW50Tm9kZTtcblxuXHR3aGlsZSAoY3VyckVsZW1lbnQgJiYgY3VyckVsZW1lbnQgIT09IGxpbWl0ICYmICFldmVudC5zdG9wcGVkKSB7XG5cdFx0aWYgKGlzQWJsZVRvSW50ZXJhY3RXaXRoXyhjdXJyRWxlbWVudCwgZXZlbnQudHlwZSwgZXZlbnQpKSB7XG5cdFx0XHRldmVudC5kZWxlZ2F0ZVRhcmdldCA9IGN1cnJFbGVtZW50O1xuXHRcdFx0cmV0ICY9IHRyaWdnZXJFbGVtZW50TGlzdGVuZXJzXyhjdXJyRWxlbWVudCwgZXZlbnQsIGRlZmF1bHRGbnMpO1xuXHRcdFx0cmV0ICY9IHRyaWdnZXJTZWxlY3Rvckxpc3RlbmVyc18oY29udGFpbmVyLCBjdXJyRWxlbWVudCwgZXZlbnQsIGRlZmF1bHRGbnMpO1xuXHRcdH1cblx0XHRjdXJyRWxlbWVudCA9IGN1cnJFbGVtZW50LnBhcmVudE5vZGU7XG5cdH1cblxuXHRyZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIENvbnZlcnRzIHRoZSBnaXZlbiBhcmd1bWVudCB0byBhIERPTSBlbGVtZW50LiBTdHJpbmdzIGFyZSBhc3N1bWVkIHRvXG4gKiBiZSBzZWxlY3RvcnMsIGFuZCBzbyBhIG1hdGNoZWQgZWxlbWVudCB3aWxsIGJlIHJldHVybmVkLiBJZiB0aGUgYXJnXG4gKiBpcyBhbHJlYWR5IGEgRE9NIGVsZW1lbnQgaXQgd2lsbCBiZSB0aGUgcmV0dXJuIHZhbHVlLlxuICogQHBhcmFtIHtzdHJpbmd8RWxlbWVudHxEb2N1bWVudH0gc2VsZWN0b3JPckVsZW1lbnRcbiAqIEByZXR1cm4ge0VsZW1lbnR9IFRoZSBjb252ZXJ0ZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBub25lIHdhcyBmb3VuZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvRWxlbWVudChzZWxlY3Rvck9yRWxlbWVudCkge1xuXHRpZiAoaXNFbGVtZW50KHNlbGVjdG9yT3JFbGVtZW50KSB8fCBpc0RvY3VtZW50KHNlbGVjdG9yT3JFbGVtZW50KSB8fCBpc0RvY3VtZW50RnJhZ21lbnQoc2VsZWN0b3JPckVsZW1lbnQpKSB7XG5cdFx0cmV0dXJuIHNlbGVjdG9yT3JFbGVtZW50O1xuXHR9IGVsc2UgaWYgKGlzU3RyaW5nKHNlbGVjdG9yT3JFbGVtZW50KSkge1xuXHRcdGlmIChzZWxlY3Rvck9yRWxlbWVudFswXSA9PT0gJyMnICYmIHNlbGVjdG9yT3JFbGVtZW50LmluZGV4T2YoJyAnKSA9PT0gLTEpIHtcblx0XHRcdHJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChzZWxlY3Rvck9yRWxlbWVudC5zdWJzdHIoMSkpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvck9yRWxlbWVudCk7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG59XG5cbi8qKlxuICogQWRkcyBvciByZW1vdmVzIG9uZSBvciBtb3JlIGNsYXNzZXMgZnJvbSBhbiBlbGVtZW50LiBJZiBhbnkgb2YgdGhlIGNsYXNzZXNcbiAqIGlzIHByZXNlbnQsIGl0IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBlbGVtZW50LCBvciBhZGRlZCBvdGhlcndpc2UuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHdoaWNoIGNsYXNzZXMgd2lsbCBiZSB0b2dnbGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzZXMgVGhlIGNsYXNzZXMgd2hpY2ggaGF2ZSB0byBhZGRlZCBvciByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b2dnbGVDbGFzc2VzKGVsZW1lbnQsIGNsYXNzZXMpIHtcblx0aWYgKCFpc09iamVjdChlbGVtZW50KSB8fCAhaXNTdHJpbmcoY2xhc3NlcykpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRpZiAoJ2NsYXNzTGlzdCcgaW4gZWxlbWVudCkge1xuXHRcdHRvZ2dsZUNsYXNzZXNXaXRoTmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKTtcblx0fSBlbHNlIHtcblx0XHR0b2dnbGVDbGFzc2VzV2l0aG91dE5hdGl2ZV8oZWxlbWVudCwgY2xhc3Nlcyk7XG5cdH1cbn1cblxuLyoqXG4gKiBBZGRzIG9yIHJlbW92ZXMgb25lIG9yIG1vcmUgY2xhc3NlcyBmcm9tIGFuIGVsZW1lbnQgdXNpbmcgY2xhc3NMaXN0LlxuICogSWYgYW55IG9mIHRoZSBjbGFzc2VzIGlzIHByZXNlbnQsIGl0IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBlbGVtZW50LFxuICogb3IgYWRkZWQgb3RoZXJ3aXNlLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB3aGljaCBjbGFzc2VzIHdpbGwgYmUgdG9nZ2xlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc2VzIFRoZSBjbGFzc2VzIHdoaWNoIGhhdmUgdG8gYWRkZWQgb3IgcmVtb3ZlZCBmcm9tIHRoZSBlbGVtZW50LlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gdG9nZ2xlQ2xhc3Nlc1dpdGhOYXRpdmVfKGVsZW1lbnQsIGNsYXNzZXMpIHtcblx0Y2xhc3Nlcy5zcGxpdCgnICcpLmZvckVhY2goZnVuY3Rpb24oY2xhc3NOYW1lKSB7XG5cdFx0ZWxlbWVudC5jbGFzc0xpc3QudG9nZ2xlKGNsYXNzTmFtZSk7XG5cdH0pO1xufVxuXG4vKipcbiAqIEFkZHMgb3IgcmVtb3ZlcyBvbmUgb3IgbW9yZSBjbGFzc2VzIGZyb20gYW4gZWxlbWVudCB3aXRob3V0IHVzaW5nIGNsYXNzTGlzdC5cbiAqIElmIGFueSBvZiB0aGUgY2xhc3NlcyBpcyBwcmVzZW50LCBpdCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZWxlbWVudCxcbiAqIG9yIGFkZGVkIG90aGVyd2lzZS5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgd2hpY2ggY2xhc3NlcyB3aWxsIGJlIHRvZ2dsZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NlcyBUaGUgY2xhc3NlcyB3aGljaCBoYXZlIHRvIGFkZGVkIG9yIHJlbW92ZWQgZnJvbSB0aGUgZWxlbWVudC5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHRvZ2dsZUNsYXNzZXNXaXRob3V0TmF0aXZlXyhlbGVtZW50LCBjbGFzc2VzKSB7XG5cdGxldCBlbGVtZW50Q2xhc3NOYW1lID0gYCAke2VsZW1lbnQuY2xhc3NOYW1lfSBgO1xuXG5cdGNsYXNzZXMgPSBjbGFzc2VzLnNwbGl0KCcgJyk7XG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjbGFzc2VzLmxlbmd0aDsgaSsrKSB7XG5cdFx0Y29uc3QgY2xhc3NOYW1lID0gYCAke2NsYXNzZXNbaV19IGA7XG5cdFx0Y29uc3QgY2xhc3NJbmRleCA9IGVsZW1lbnRDbGFzc05hbWUuaW5kZXhPZihjbGFzc05hbWUpO1xuXG5cdFx0aWYgKGNsYXNzSW5kZXggPT09IC0xKSB7XG5cdFx0XHRlbGVtZW50Q2xhc3NOYW1lID0gYCR7ZWxlbWVudENsYXNzTmFtZX0ke2NsYXNzZXNbaV19IGA7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGNvbnN0IGJlZm9yZSA9IGVsZW1lbnRDbGFzc05hbWUuc3Vic3RyaW5nKDAsIGNsYXNzSW5kZXgpO1xuXHRcdFx0Y29uc3QgYWZ0ZXIgPSBlbGVtZW50Q2xhc3NOYW1lLnN1YnN0cmluZyhjbGFzc0luZGV4ICsgY2xhc3NOYW1lLmxlbmd0aCk7XG5cdFx0XHRlbGVtZW50Q2xhc3NOYW1lID0gYCR7YmVmb3JlfSAke2FmdGVyfWA7XG5cdFx0fVxuXHR9XG5cblx0ZWxlbWVudC5jbGFzc05hbWUgPSBlbGVtZW50Q2xhc3NOYW1lLnRyaW0oKTtcbn1cblxuLyoqXG4gKiBUcmlnZ2VycyBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZ2l2ZW4gZXZlbnQgdHlwZSB0aGF0IGFyZSBzdG9yZWQgaW4gdGhlXG4gKiBzcGVjaWZpZWQgZWxlbWVudC5cbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7IUV2ZW50fSBldmVudFxuICogQHBhcmFtIHshQXJyYXl9IGRlZmF1bHRGbnMgQXJyYXkgdG8gY29sbGVjdCBkZWZhdWx0IGxpc3RlbmVycyBpbiwgaW5zdGVhZFxuICogICAgIG9mIHJ1bm5pbmcgdGhlbS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IEZhbHNlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdHJpZ2dlcmVkIGNhbGxiYWNrcyByZXR1cm5zXG4gKiAgICAgZmFsc2UsIG9yIHRydWUgb3RoZXJ3aXNlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gdHJpZ2dlckVsZW1lbnRMaXN0ZW5lcnNfKGVsZW1lbnQsIGV2ZW50LCBkZWZhdWx0Rm5zKSB7XG5cdGNvbnN0IGxhc3RDb250YWluZXIgPSBldmVudFtMQVNUX0NPTlRBSU5FUl07XG5cdGlmICghaXNEZWYobGFzdENvbnRhaW5lcikgfHwgIWNvbnRhaW5zKGxhc3RDb250YWluZXIsIGVsZW1lbnQpKSB7XG5cdFx0Y29uc3QgbGlzdGVuZXJzID0gZG9tRGF0YS5nZXQoZWxlbWVudCwgJ2xpc3RlbmVycycsIHt9KVtldmVudC50eXBlXTtcblx0XHRyZXR1cm4gdHJpZ2dlckxpc3RlbmVyc18obGlzdGVuZXJzLCBldmVudCwgZWxlbWVudCwgZGVmYXVsdEZucyk7XG5cdH1cblx0cmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogVHJpZ2dlcnMgdGhlIHNwZWNpZmllZCBldmVudCBvbiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAqIE5PVEU6IFRoaXMgc2hvdWxkIG1vc3RseSBiZSB1c2VkIGZvciB0ZXN0aW5nLCBub3Qgb24gcmVhbCBjb2RlLlxuICogQHBhcmFtIHshRWxlbWVudH0gZWxlbWVudCBUaGUgbm9kZSB0aGF0IHNob3VsZCB0cmlnZ2VyIHRoZSBldmVudC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGJlIHRyaWdncmVkLlxuICogQHBhcmFtIHtPYmplY3Q9fSBvcHRfZXZlbnRPYmogQW4gb2JqZWN0IHdpdGggZGF0YSB0aGF0IHNob3VsZCBiZSBvbiB0aGVcbiAqICAgdHJpZ2dlcmVkIGV2ZW50J3MgcGF5bG9hZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyaWdnZXJFdmVudChlbGVtZW50LCBldmVudE5hbWUsIG9wdF9ldmVudE9iaikge1xuXHRpZiAoaXNBYmxlVG9JbnRlcmFjdFdpdGhfKGVsZW1lbnQsIGV2ZW50TmFtZSwgb3B0X2V2ZW50T2JqKSkge1xuXHRcdGNvbnN0IGV2ZW50T2JqID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0hUTUxFdmVudHMnKTtcblx0XHRldmVudE9iai5pbml0RXZlbnQoZXZlbnROYW1lLCB0cnVlLCB0cnVlKTtcblx0XHRvYmplY3QubWl4aW4oZXZlbnRPYmosIG9wdF9ldmVudE9iaik7XG5cdFx0ZWxlbWVudC5kaXNwYXRjaEV2ZW50KGV2ZW50T2JqKTtcblx0fVxufVxuXG4vKipcbiAqIFRyaWdnZXJzIHRoZSBnaXZlbiBsaXN0ZW5lcnMgYXJyYXkuXG4gKiBAcGFyYW0ge0FycmF5PCFmdW5jdGlvbigpPn0gbGlzdGVuZXJzXG4gKiBAcGFyYW0geyFFdmVudH0gZXZlbnRcbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7IUFycmF5fSBkZWZhdWx0Rm5zIEFycmF5IHRvIGNvbGxlY3QgZGVmYXVsdCBsaXN0ZW5lcnMgaW4sIGluc3RlYWRcbiAqICAgICBvZiBydW5uaW5nIHRoZW0uXG4gKiBAcmV0dXJuIHtib29sZWFufSBGYWxzZSBpZiBhdCBsZWFzdCBvbmUgb2YgdGhlIHRyaWdnZXJlZCBjYWxsYmFja3MgcmV0dXJuc1xuICogICAgIGZhbHNlLCBvciB0cnVlIG90aGVyd2lzZS5cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHRyaWdnZXJMaXN0ZW5lcnNfKGxpc3RlbmVycywgZXZlbnQsIGVsZW1lbnQsIGRlZmF1bHRGbnMpIHtcblx0bGV0IHJldCA9IHRydWU7XG5cdGxpc3RlbmVycyA9IGxpc3RlbmVycyB8fCBbXTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoICYmICFldmVudC5zdG9wcGVkSW1tZWRpYXRlOyBpKyspIHtcblx0XHRpZiAobGlzdGVuZXJzW2ldLmRlZmF1bHRMaXN0ZW5lcl8pIHtcblx0XHRcdGRlZmF1bHRGbnMucHVzaCh7XG5cdFx0XHRcdGVsZW1lbnQsXG5cdFx0XHRcdGZuOiBsaXN0ZW5lcnNbaV1cblx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXQgJj0gbGlzdGVuZXJzW2ldKGV2ZW50KTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHJldDtcbn1cblxuLyoqXG4gKiBUcmlnZ2VycyBhbGwgc2VsZWN0b3IgbGlzdGVuZXJzIGZvciB0aGUgZ2l2ZW4gZXZlbnQuXG4gKiBAcGFyYW0geyFFbGVtZW50fSBjb250YWluZXJcbiAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7IUV2ZW50fSBldmVudFxuICogQHBhcmFtIHshQXJyYXl9IGRlZmF1bHRGbnMgQXJyYXkgdG8gY29sbGVjdCBkZWZhdWx0IGxpc3RlbmVycyBpbiwgaW5zdGVhZFxuICogICAgIG9mIHJ1bm5pbmcgdGhlbS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IEZhbHNlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdHJpZ2dlcmVkIGNhbGxiYWNrcyByZXR1cm5zXG4gKiAgICAgZmFsc2UsIG9yIHRydWUgb3RoZXJ3aXNlLlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gdHJpZ2dlclNlbGVjdG9yTGlzdGVuZXJzXyhjb250YWluZXIsIGVsZW1lbnQsIGV2ZW50LCBkZWZhdWx0Rm5zKSB7XG5cdGxldCByZXQgPSB0cnVlO1xuXHRjb25zdCBkYXRhID0gZG9tRGF0YS5nZXQoY29udGFpbmVyLCAnZGVsZWdhdGluZycsIHt9KTtcblx0Y29uc3QgbWFwID0gZGF0YVtldmVudC50eXBlXS5zZWxlY3RvcnM7XG5cdGNvbnN0IHNlbGVjdG9ycyA9IE9iamVjdC5rZXlzKG1hcCk7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0b3JzLmxlbmd0aCAmJiAhZXZlbnQuc3RvcHBlZEltbWVkaWF0ZTsgaSsrKSB7XG5cdFx0aWYgKG1hdGNoKGVsZW1lbnQsIHNlbGVjdG9yc1tpXSkpIHtcblx0XHRcdGNvbnN0IGxpc3RlbmVycyA9IG1hcFtzZWxlY3RvcnNbaV1dO1xuXHRcdFx0cmV0ICY9IHRyaWdnZXJMaXN0ZW5lcnNfKGxpc3RlbmVycywgZXZlbnQsIGVsZW1lbnQsIGRlZmF1bHRGbnMpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gcmV0O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBUaGlzIGZpbGUgZXhpc3RzIGp1c3QgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LCBtYWtpbmcgc3VyZSB0aGF0IG9sZFxuLy8gZGVmYXVsdCBpbXBvcnRzIGZvciB0aGlzIGZpbGUgc3RpbGwgd29yay4gSXQncyBiZXN0IHRvIHVzZSB0aGUgbmFtZWQgZXhwb3J0c1xuLy8gZm9yIGVhY2ggZnVuY3Rpb24gaW5zdGVhZCB0aG91Z2gsIHNpbmNlIHRoYXQgYWxsb3dzIGJ1bmRsZXJzIGxpa2UgUm9sbHVwIHRvXG4vLyByZWR1Y2UgdGhlIGJ1bmRsZSBzaXplIGJ5IHJlbW92aW5nIHVudXNlZCBjb2RlLlxuaW1wb3J0ICogYXMgZG9tIGZyb20gJy4vZG9tTmFtZWQnO1xuXG5leHBvcnQgZGVmYXVsdCBkb207XG5leHBvcnQgeyBkb20gfTtcbmV4cG9ydCAqIGZyb20gJy4vZG9tTmFtZWQnO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBkZWxlZ2F0ZSwgb24sIHN1cHBvcnRzRXZlbnQgfSBmcm9tICcuL2RvbSc7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXJQcm94eSB9IGZyb20gJ21ldGFsLWV2ZW50cyc7XG5cbi8qKlxuICogRG9tRXZlbnRFbWl0dGVyUHJveHkgdXRpbGl0eS4gSXQgZXh0ZW5kcyBgRXZlbnRFbWl0dGVyUHJveHlgIHRvIGFsc28gYWNjZXB0XG4gKiBkb20gZWxlbWVudHMgYXMgb3JpZ2luIGVtaXR0ZXJzLlxuICogQGV4dGVuZHMge0V2ZW50RW1pdHRlclByb3h5fVxuICovXG5jbGFzcyBEb21FdmVudEVtaXR0ZXJQcm94eSBleHRlbmRzIEV2ZW50RW1pdHRlclByb3h5IHtcblx0LyoqXG5cdCAqIEFkZHMgdGhlIGdpdmVuIGxpc3RlbmVyIGZvciB0aGUgZ2l2ZW4gZXZlbnQuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcGFyYW0geyFmdW5jdGlvbigpfSBsaXN0ZW5lclxuXHQgKiBAcmV0dXJuIHshRXZlbnRIYW5kbGV9IFRoZSBsaXN0ZW5lZCBldmVudCdzIGhhbmRsZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKiBAb3ZlcnJpZGVcblx0ICovXG5cdGFkZExpc3RlbmVyXyhldmVudCwgbGlzdGVuZXIpIHtcblx0XHRpZiAodGhpcy5vcmlnaW5FbWl0dGVyXy5hZGRFdmVudExpc3RlbmVyKSB7XG5cdFx0XHRpZiAodGhpcy5pc0RlbGVnYXRlRXZlbnRfKGV2ZW50KSkge1xuXHRcdFx0XHRjb25zdCBpbmRleCA9IGV2ZW50LmluZGV4T2YoJzonLCA5KTtcblx0XHRcdFx0Y29uc3QgZXZlbnROYW1lID0gZXZlbnQuc3Vic3RyaW5nKDksIGluZGV4KTtcblx0XHRcdFx0Y29uc3Qgc2VsZWN0b3IgPSBldmVudC5zdWJzdHJpbmcoaW5kZXggKyAxKTtcblx0XHRcdFx0cmV0dXJuIGRlbGVnYXRlKHRoaXMub3JpZ2luRW1pdHRlcl8sIGV2ZW50TmFtZSwgc2VsZWN0b3IsIGxpc3RlbmVyKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiBvbih0aGlzLm9yaWdpbkVtaXR0ZXJfLCBldmVudCwgbGlzdGVuZXIpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gc3VwZXIuYWRkTGlzdGVuZXJfKGV2ZW50LCBsaXN0ZW5lcik7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gZXZlbnQgaXMgb2YgdGhlIGRlbGVnYXRlIHR5cGUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRpc0RlbGVnYXRlRXZlbnRfKGV2ZW50KSB7XG5cdFx0cmV0dXJuIGV2ZW50LnN1YnN0cigwLCA5KSA9PT0gJ2RlbGVnYXRlOic7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBldmVudCBpcyBzdXBwb3J0ZWQgYnkgdGhlIG9yaWdpbiBlbGVtZW50LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0aXNTdXBwb3J0ZWREb21FdmVudF8oZXZlbnQpIHtcblx0XHRpZiAoIXRoaXMub3JpZ2luRW1pdHRlcl8gfHwgIXRoaXMub3JpZ2luRW1pdHRlcl8uYWRkRXZlbnRMaXN0ZW5lcikge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiAodGhpcy5pc0RlbGVnYXRlRXZlbnRfKGV2ZW50KSAmJiBldmVudC5pbmRleE9mKCc6JywgOSkgIT09IC0xKSB8fFxuXHRcdFx0c3VwcG9ydHNFdmVudCh0aGlzLm9yaWdpbkVtaXR0ZXJfLCBldmVudCk7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBldmVudCBzaG91bGQgYmUgcHJveGllZC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcm90ZWN0ZWRcblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRzaG91bGRQcm94eUV2ZW50XyhldmVudCkge1xuXHRcdHJldHVybiBzdXBlci5zaG91bGRQcm94eUV2ZW50XyhldmVudCkgJiYgdGhpcy5pc1N1cHBvcnRlZERvbUV2ZW50XyhldmVudCk7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRG9tRXZlbnRFbWl0dGVyUHJveHk7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGFwcGVuZCB9IGZyb20gJy4vZG9tJztcbmltcG9ydCB7IHN0cmluZyB9IGZyb20gJ21ldGFsJztcblxuLyoqXG4gKiBDbGFzcyB3aXRoIHN0YXRpYyBtZXRob2RzIHJlc3BvbnNpYmxlIGZvciBkb2luZyBicm93c2VyIGZlYXR1cmUgY2hlY2tzLlxuICovXG5jbGFzcyBmZWF0dXJlcyB7XG5cdC8qKlxuXHQgKiBTb21lIGJyb3dzZXJzIHN0aWxsIHN1cHBvcnRzIHByZWZpeGVkIGFuaW1hdGlvbiBldmVudHMuIFRoaXMgbWV0aG9kIGNhblxuXHQgKiBiZSB1c2VkIHRvIHJldHJpZXZlIHRoZSBjdXJyZW50IGJyb3dzZXIgZXZlbnQgbmFtZSBmb3IgYm90aCwgYW5pbWF0aW9uXG5cdCAqIGFuZCB0cmFuc2l0aW9uLlxuXHQgKiBAcmV0dXJuIHtvYmplY3R9XG5cdCAqL1xuXHRzdGF0aWMgY2hlY2tBbmltYXRpb25FdmVudE5hbWUoKSB7XG5cdFx0aWYgKGZlYXR1cmVzLmFuaW1hdGlvbkV2ZW50TmFtZV8gPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0ZmVhdHVyZXMuYW5pbWF0aW9uRXZlbnROYW1lXyA9IHtcblx0XHRcdFx0YW5pbWF0aW9uOiBmZWF0dXJlcy5jaGVja0FuaW1hdGlvbkV2ZW50TmFtZV8oJ2FuaW1hdGlvbicpLFxuXHRcdFx0XHR0cmFuc2l0aW9uOiBmZWF0dXJlcy5jaGVja0FuaW1hdGlvbkV2ZW50TmFtZV8oJ3RyYW5zaXRpb24nKVxuXHRcdFx0fTtcblx0XHR9XG5cdFx0cmV0dXJuIGZlYXR1cmVzLmFuaW1hdGlvbkV2ZW50TmFtZV87XG5cdH1cblxuXHQvKipcblx0ICogQHByb3RlY3RlZFxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBUeXBlIHRvIHRlc3Q6IGFuaW1hdGlvbiwgdHJhbnNpdGlvbi5cblx0ICogQHJldHVybiB7c3RyaW5nfSBCcm93c2VyIGV2ZW50IG5hbWUuXG5cdCAqL1xuXHRzdGF0aWMgY2hlY2tBbmltYXRpb25FdmVudE5hbWVfKHR5cGUpIHtcblx0XHRjb25zdCBwcmVmaXhlcyA9IFsnV2Via2l0JywgJ01TJywgJ08nLCAnJ107XG5cdFx0Y29uc3QgdHlwZVRpdGxlQ2FzZSA9IHN0cmluZy5yZXBsYWNlSW50ZXJ2YWwodHlwZSwgMCwgMSwgdHlwZS5zdWJzdHJpbmcoMCwgMSkudG9VcHBlckNhc2UoKSk7XG5cdFx0Y29uc3Qgc3VmZml4ZXMgPSBbYCR7dHlwZVRpdGxlQ2FzZX1FbmRgLCBgJHt0eXBlVGl0bGVDYXNlfUVuZGAsIGAke3R5cGVUaXRsZUNhc2V9RW5kYCwgYCR7dHlwZX1lbmRgXTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHByZWZpeGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAoZmVhdHVyZXMuYW5pbWF0aW9uRWxlbWVudF8uc3R5bGVbcHJlZml4ZXNbaV0gKyB0eXBlVGl0bGVDYXNlXSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHJldHVybiBwcmVmaXhlc1tpXS50b0xvd2VyQ2FzZSgpICsgc3VmZml4ZXNbaV07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBgJHt0eXBlfWVuZGA7XG5cdH1cblxuXHQvKipcblx0ICogU29tZSBicm93c2VycyAobGlrZSBJRTkpIGNoYW5nZSB0aGUgb3JkZXIgb2YgZWxlbWVudCBhdHRyaWJ1dGVzLCB3aGVuIGh0bWxcblx0ICogaXMgcmVuZGVyZWQuIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGNoZWNrIGlmIHRoaXMgYmVoYXZpb3IgaGFwcGVucyBvblxuXHQgKiB0aGUgY3VycmVudCBicm93c2VyLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0c3RhdGljIGNoZWNrQXR0ck9yZGVyQ2hhbmdlKCkge1xuXHRcdGlmIChmZWF0dXJlcy5hdHRyT3JkZXJDaGFuZ2VfID09PSB1bmRlZmluZWQpIHtcblx0XHRcdGNvbnN0IG9yaWdpbmFsQ29udGVudCA9ICc8ZGl2IGRhdGEtY29tcG9uZW50PVwiXCIgZGF0YS1yZWY9XCJcIj48L2Rpdj4nO1xuXHRcdFx0Y29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXHRcdFx0YXBwZW5kKGVsZW1lbnQsIG9yaWdpbmFsQ29udGVudCk7XG5cdFx0XHRmZWF0dXJlcy5hdHRyT3JkZXJDaGFuZ2VfID0gb3JpZ2luYWxDb250ZW50ICE9PSBlbGVtZW50LmlubmVySFRNTDtcblx0XHR9XG5cdFx0cmV0dXJuIGZlYXR1cmVzLmF0dHJPcmRlckNoYW5nZV87XG5cdH1cbn1cblxuZmVhdHVyZXMuYW5pbWF0aW9uRWxlbWVudF8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbmZlYXR1cmVzLmFuaW1hdGlvbkV2ZW50TmFtZV8gPSB1bmRlZmluZWQ7XG5mZWF0dXJlcy5hdHRyT3JkZXJDaGFuZ2VfID0gdW5kZWZpbmVkO1xuXG5leHBvcnQgZGVmYXVsdCBmZWF0dXJlcztcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgYXN5bmMgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBleGl0RG9jdW1lbnQsIG9uY2UgfSBmcm9tICcuL2RvbSc7XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbnMgZm9yIHJ1bm5pbmcgamF2YXNjcmlwdCBjb2RlIGluIHRoZSBnbG9iYWwgc2NvcGUuXG4gKi9cbmNsYXNzIGdsb2JhbEV2YWwge1xuXHQvKipcblx0ICogRXZhbHVhdGVzIHRoZSBnaXZlbiBzdHJpbmcgaW4gdGhlIGdsb2JhbCBzY29wZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHRleHRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2FwcGVuZEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGFwcGVuZCB0aGUgbm9kZVxuXHQgKiAgIGludG8gZG9jdW1lbnQuXG5cdCAqIEByZXR1cm4ge0VsZW1lbnR9IHNjcmlwdFxuXHQgKi9cblx0c3RhdGljIHJ1bih0ZXh0LCBvcHRfYXBwZW5kRm4pIHtcblx0XHRjb25zdCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcblx0XHRzY3JpcHQudGV4dCA9IHRleHQ7XG5cdFx0aWYgKG9wdF9hcHBlbmRGbikge1xuXHRcdFx0b3B0X2FwcGVuZEZuKHNjcmlwdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcblx0XHR9XG5cdFx0ZXhpdERvY3VtZW50KHNjcmlwdCk7XG5cdFx0cmV0dXJuIHNjcmlwdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgdGhlIGdpdmVuIGphdmFzY3JpcHQgZmlsZSBpbiB0aGUgZ2xvYmFsIHNjb3BlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3JjIFRoZSBmaWxlJ3MgcGF0aC5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2NhbGxiYWNrIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHNjcmlwdCBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9hcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKiBAcmV0dXJuIHtFbGVtZW50fSBzY3JpcHRcblx0ICovXG5cdHN0YXRpYyBydW5GaWxlKHNyYywgb3B0X2NhbGxiYWNrLCBvcHRfYXBwZW5kRm4pIHtcblx0XHRjb25zdCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcblx0XHRzY3JpcHQuc3JjID0gc3JjO1xuXG5cdFx0Y29uc3QgY2FsbGJhY2sgPSBmdW5jdGlvbigpIHtcblx0XHRcdGV4aXREb2N1bWVudChzY3JpcHQpO1xuXHRcdFx0b3B0X2NhbGxiYWNrICYmIG9wdF9jYWxsYmFjaygpO1xuXHRcdH07XG5cdFx0b25jZShzY3JpcHQsICdsb2FkJywgY2FsbGJhY2spO1xuXHRcdG9uY2Uoc2NyaXB0LCAnZXJyb3InLCBjYWxsYmFjayk7XG5cblx0XHRpZiAob3B0X2FwcGVuZEZuKSB7XG5cdFx0XHRvcHRfYXBwZW5kRm4oc2NyaXB0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuXHRcdH1cblxuXHRcdHJldHVybiBzY3JpcHQ7XG5cdH1cblxuXHQvKipcblx0ICogRXZhbHVhdGVzIHRoZSBjb2RlIHJlZmVyZW5jZWQgYnkgdGhlIGdpdmVuIHNjcmlwdCBlbGVtZW50LlxuXHQgKiBAcGFyYW0geyFFbGVtZW50fSBzY3JpcHRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2NhbGxiYWNrIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHNjcmlwdCBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9hcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKiBAcmV0dXJuIHtFbGVtZW50fSBzY3JpcHRcblx0ICovXG5cdHN0YXRpYyBydW5TY3JpcHQoc2NyaXB0LCBvcHRfY2FsbGJhY2ssIG9wdF9hcHBlbmRGbikge1xuXHRcdGNvbnN0IGNhbGxiYWNrID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRvcHRfY2FsbGJhY2sgJiYgb3B0X2NhbGxiYWNrKCk7XG5cdFx0fTtcblx0XHRpZiAoc2NyaXB0LnR5cGUgJiYgc2NyaXB0LnR5cGUgIT09ICd0ZXh0L2phdmFzY3JpcHQnKSB7XG5cdFx0XHRhc3luYy5uZXh0VGljayhjYWxsYmFjayk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGV4aXREb2N1bWVudChzY3JpcHQpO1xuXHRcdGlmIChzY3JpcHQuc3JjKSB7XG5cdFx0XHRyZXR1cm4gZ2xvYmFsRXZhbC5ydW5GaWxlKHNjcmlwdC5zcmMsIG9wdF9jYWxsYmFjaywgb3B0X2FwcGVuZEZuKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0YXN5bmMubmV4dFRpY2soY2FsbGJhY2spO1xuXHRcdFx0cmV0dXJuIGdsb2JhbEV2YWwucnVuKHNjcmlwdC50ZXh0LCBvcHRfYXBwZW5kRm4pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgYW55IHNjcmlwdCB0YWdzIHByZXNlbnQgaW4gdGhlIGdpdmVuIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2NhbGxiYWNrIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHNjcmlwdCBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9hcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKi9cblx0c3RhdGljIHJ1blNjcmlwdHNJbkVsZW1lbnQoZWxlbWVudCwgb3B0X2NhbGxiYWNrLCBvcHRfYXBwZW5kRm4pIHtcblx0XHRjb25zdCBzY3JpcHRzID0gZWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKCdzY3JpcHQnKTtcblx0XHRpZiAoc2NyaXB0cy5sZW5ndGgpIHtcblx0XHRcdGdsb2JhbEV2YWwucnVuU2NyaXB0c0luT3JkZXIoc2NyaXB0cywgMCwgb3B0X2NhbGxiYWNrLCBvcHRfYXBwZW5kRm4pO1xuXHRcdH0gZWxzZSBpZiAob3B0X2NhbGxiYWNrKSB7XG5cdFx0XHRhc3luYy5uZXh0VGljayhvcHRfY2FsbGJhY2spO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBnaXZlbiBzY3JpcHRzIGVsZW1lbnRzIGluIHRoZSBvcmRlciB0aGF0IHRoZXkgYXBwZWFyLlxuXHQgKiBAcGFyYW0geyFOb2RlTGlzdH0gc2NyaXB0c1xuXHQgKiBAcGFyYW0ge251bWJlcn0gaW5kZXhcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2NhbGxiYWNrIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHNjcmlwdCBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9hcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKi9cblx0c3RhdGljIHJ1blNjcmlwdHNJbk9yZGVyKHNjcmlwdHMsIGluZGV4LCBvcHRfY2FsbGJhY2ssIG9wdF9hcHBlbmRGbikge1xuXHRcdGdsb2JhbEV2YWwucnVuU2NyaXB0KHNjcmlwdHMuaXRlbShpbmRleCksIGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKGluZGV4IDwgc2NyaXB0cy5sZW5ndGggLSAxKSB7XG5cdFx0XHRcdGdsb2JhbEV2YWwucnVuU2NyaXB0c0luT3JkZXIoc2NyaXB0cywgaW5kZXggKyAxLCBvcHRfY2FsbGJhY2ssIG9wdF9hcHBlbmRGbik7XG5cdFx0XHR9IGVsc2UgaWYgKG9wdF9jYWxsYmFjaykge1xuXHRcdFx0XHRhc3luYy5uZXh0VGljayhvcHRfY2FsbGJhY2spO1xuXHRcdFx0fVxuXHRcdH0sIG9wdF9hcHBlbmRGbik7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgZ2xvYmFsRXZhbDtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgYXN5bmMgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBvbmNlIH0gZnJvbSAnLi9kb20nO1xuXG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb25zIGZvciBydW5uaW5nIHN0eWxlcy5cbiAqL1xuY2xhc3MgZ2xvYmFsRXZhbFN0eWxlcyB7XG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgdGhlIGdpdmVuIHN0eWxlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKCk9fSBvcHRfYXBwZW5kRm4gT3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwZW5kIHRoZSBub2RlXG5cdCAqICAgaW50byBkb2N1bWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gc3R5bGVcblx0ICovXG5cdHN0YXRpYyBydW4odGV4dCwgb3B0X2FwcGVuZEZuKSB7XG5cdFx0Y29uc3Qgc3R5bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xuXHRcdHN0eWxlLmlubmVySFRNTCA9IHRleHQ7XG5cdFx0aWYgKG9wdF9hcHBlbmRGbikge1xuXHRcdFx0b3B0X2FwcGVuZEZuKHN0eWxlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzdHlsZSk7XG5cdFx0fVxuXHRcdHJldHVybiBzdHlsZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgdGhlIGdpdmVuIHN0eWxlIGZpbGUuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBocmVmIFRoZSBmaWxlJ3MgcGF0aC5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2NhbGxiYWNrIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHN0eWxlcyBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9hcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKiBAcmV0dXJuIHtFbGVtZW50fSBzdHlsZVxuXHQgKi9cblx0c3RhdGljIHJ1bkZpbGUoaHJlZiwgb3B0X2NhbGxiYWNrLCBvcHRfYXBwZW5kRm4pIHtcblx0XHRjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGluaycpO1xuXHRcdGxpbmsucmVsID0gJ3N0eWxlc2hlZXQnO1xuXHRcdGxpbmsuaHJlZiA9IGhyZWY7XG5cdFx0Z2xvYmFsRXZhbFN0eWxlcy5ydW5TdHlsZShsaW5rLCBvcHRfY2FsbGJhY2ssIG9wdF9hcHBlbmRGbik7XG5cdFx0cmV0dXJuIGxpbms7XG5cdH1cblxuXHQvKipcblx0ICogRXZhbHVhdGVzIHRoZSBjb2RlIHJlZmVyZW5jZWQgYnkgdGhlIGdpdmVuIHN0eWxlL2xpbmsgZWxlbWVudC5cblx0ICogQHBhcmFtIHshRWxlbWVudH0gc3R5bGVcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2NhbGxiYWNrIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKiAgIHdoZW4gdGhlIHNjcmlwdCBoYXMgYmVlbiBydW4uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb24oKT19IG9wdF9hcHBlbmRGbiBPcHRpb25hbCBmdW5jdGlvbiB0byBhcHBlbmQgdGhlIG5vZGVcblx0ICogICBpbnRvIGRvY3VtZW50LlxuXHQgKiAgQHJldHVybiB7RWxlbWVudH0gc3R5bGVcblx0ICovXG5cdHN0YXRpYyBydW5TdHlsZShzdHlsZSwgb3B0X2NhbGxiYWNrLCBvcHRfYXBwZW5kRm4pIHtcblx0XHRjb25zdCBjYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0b3B0X2NhbGxiYWNrICYmIG9wdF9jYWxsYmFjaygpO1xuXHRcdH07XG5cdFx0aWYgKHN0eWxlLnJlbCAmJiBzdHlsZS5yZWwgIT09ICdzdHlsZXNoZWV0Jykge1xuXHRcdFx0YXN5bmMubmV4dFRpY2soY2FsbGJhY2spO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChzdHlsZS50YWdOYW1lID09PSAnU1RZTEUnKSB7XG5cdFx0XHRhc3luYy5uZXh0VGljayhjYWxsYmFjayk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdG9uY2Uoc3R5bGUsICdsb2FkJywgY2FsbGJhY2spO1xuXHRcdFx0b25jZShzdHlsZSwgJ2Vycm9yJywgY2FsbGJhY2spO1xuXHRcdH1cblxuXHRcdGlmIChvcHRfYXBwZW5kRm4pIHtcblx0XHRcdG9wdF9hcHBlbmRGbihzdHlsZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGUpO1xuXHRcdH1cblxuXHRcdHJldHVybiBzdHlsZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFdmFsdWF0ZXMgYW55IHN0eWxlIHByZXNlbnQgaW4gdGhlIGdpdmVuIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2NhbGxiYWNrIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZVxuXHQgKiAgIHN0eWxlIGhhcyBiZWVuIHJ1bi5cblx0ICogQHBhcmFtIHtmdW5jdGlvbigpPX0gb3B0X2FwcGVuZEZuIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGFwcGVuZCB0aGUgbm9kZVxuXHQgKiAgIGludG8gZG9jdW1lbnQuXG5cdCAqL1xuXHRzdGF0aWMgcnVuU3R5bGVzSW5FbGVtZW50KGVsZW1lbnQsIG9wdF9jYWxsYmFjaywgb3B0X2FwcGVuZEZuKSB7XG5cdFx0Y29uc3Qgc3R5bGVzID0gZWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKCdzdHlsZSxsaW5rJyk7XG5cdFx0aWYgKHN0eWxlcy5sZW5ndGggPT09IDAgJiYgb3B0X2NhbGxiYWNrKSB7XG5cdFx0XHRhc3luYy5uZXh0VGljayhvcHRfY2FsbGJhY2spO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGxldCBsb2FkQ291bnQgPSAwO1xuXHRcdGNvbnN0IGNhbGxiYWNrID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAob3B0X2NhbGxiYWNrICYmICsrbG9hZENvdW50ID09PSBzdHlsZXMubGVuZ3RoKSB7XG5cdFx0XHRcdGFzeW5jLm5leHRUaWNrKG9wdF9jYWxsYmFjayk7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHN0eWxlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Z2xvYmFsRXZhbFN0eWxlcy5ydW5TdHlsZShzdHlsZXNbaV0sIGNhbGxiYWNrLCBvcHRfYXBwZW5kRm4pO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBnbG9iYWxFdmFsU3R5bGVzO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyByZWdpc3RlckN1c3RvbUV2ZW50LCBjb250YWlucyB9IGZyb20gJy4vZG9tJztcbmltcG9ydCBmZWF0dXJlcyBmcm9tICcuL2ZlYXR1cmVzJztcblxuY29uc3QgbW91c2VFdmVudE1hcCA9IHtcblx0bW91c2VlbnRlcjogJ21vdXNlb3ZlcicsXG5cdG1vdXNlbGVhdmU6ICdtb3VzZW91dCcsXG5cdHBvaW50ZXJlbnRlcjogJ3BvaW50ZXJvdmVyJyxcblx0cG9pbnRlcmxlYXZlOiAncG9pbnRlcm91dCdcbn07XG5PYmplY3Qua2V5cyhtb3VzZUV2ZW50TWFwKS5mb3JFYWNoKGZ1bmN0aW9uKGV2ZW50TmFtZSkge1xuXHRyZWdpc3RlckN1c3RvbUV2ZW50KGV2ZW50TmFtZSwge1xuXHRcdGRlbGVnYXRlOiB0cnVlLFxuXHRcdGhhbmRsZXI6IGZ1bmN0aW9uKGNhbGxiYWNrLCBldmVudCkge1xuXHRcdFx0Y29uc3QgcmVsYXRlZCA9IGV2ZW50LnJlbGF0ZWRUYXJnZXQ7XG5cdFx0XHRjb25zdCB0YXJnZXQgPSBldmVudC5kZWxlZ2F0ZVRhcmdldDtcblx0XHRcdGlmICghcmVsYXRlZCB8fCAocmVsYXRlZCAhPT0gdGFyZ2V0ICYmICFjb250YWlucyh0YXJnZXQsIHJlbGF0ZWQpKSkge1xuXHRcdFx0XHRldmVudC5jdXN0b21UeXBlID0gZXZlbnROYW1lO1xuXHRcdFx0XHRyZXR1cm4gY2FsbGJhY2soZXZlbnQpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0b3JpZ2luYWxFdmVudDogbW91c2VFdmVudE1hcFtldmVudE5hbWVdXG5cdH0pO1xufSk7XG5cbmNvbnN0IGFuaW1hdGlvbkV2ZW50TWFwID0ge1xuXHRhbmltYXRpb246ICdhbmltYXRpb25lbmQnLFxuXHR0cmFuc2l0aW9uOiAndHJhbnNpdGlvbmVuZCdcbn07XG5PYmplY3Qua2V5cyhhbmltYXRpb25FdmVudE1hcCkuZm9yRWFjaChmdW5jdGlvbihldmVudFR5cGUpIHtcblx0Y29uc3QgZXZlbnROYW1lID0gYW5pbWF0aW9uRXZlbnRNYXBbZXZlbnRUeXBlXTtcblx0cmVnaXN0ZXJDdXN0b21FdmVudChldmVudE5hbWUsIHtcblx0XHRldmVudDogdHJ1ZSxcblx0XHRkZWxlZ2F0ZTogdHJ1ZSxcblx0XHRoYW5kbGVyOiBmdW5jdGlvbihjYWxsYmFjaywgZXZlbnQpIHtcblx0XHRcdGV2ZW50LmN1c3RvbVR5cGUgPSBldmVudE5hbWU7XG5cdFx0XHRyZXR1cm4gY2FsbGJhY2soZXZlbnQpO1xuXHRcdH0sXG5cdFx0b3JpZ2luYWxFdmVudDogZmVhdHVyZXMuY2hlY2tBbmltYXRpb25FdmVudE5hbWUoKVtldmVudFR5cGVdXG5cdH0pO1xufSk7XG4iLCIvKiFcbiAqIFByb21pc2VzIHBvbHlmaWxsIGZyb20gR29vZ2xlJ3MgQ2xvc3VyZSBMaWJyYXJ5LlxuICpcbiAqICAgICAgQ29weXJpZ2h0IDIwMTMgVGhlIENsb3N1cmUgTGlicmFyeSBBdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIE5PVEUoZWR1YXJkbyk6IFByb21pc2Ugc3VwcG9ydCBpcyBub3QgcmVhZHkgb24gYWxsIHN1cHBvcnRlZCBicm93c2VycyxcbiAqIHRoZXJlZm9yZSBtZXRhbC1wcm9taXNlIGlzIHRlbXBvcmFyaWx5IHVzaW5nIEdvb2dsZSdzIHByb21pc2VzIGFzIHBvbHlmaWxsLlxuICogSXQgc3VwcG9ydHMgY2FuY2VsbGFibGUgcHJvbWlzZXMgYW5kIGhhcyBjbGVhbiBhbmQgZmFzdCBpbXBsZW1lbnRhdGlvbi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmLCBpc0Z1bmN0aW9uLCBpc09iamVjdCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCB7IGFzeW5jIH0gZnJvbSAnbWV0YWwnO1xuXG4vKipcbiAqIFByb3ZpZGVzIGEgbW9yZSBzdHJpY3QgaW50ZXJmYWNlIGZvciBUaGVuYWJsZXMgaW4gdGVybXMgb2ZcbiAqIGh0dHA6Ly9wcm9taXNlc2FwbHVzLmNvbSBmb3IgaW50ZXJvcCB3aXRoIHtAc2VlIENhbmNlbGxhYmxlUHJvbWlzZX0uXG4gKlxuICogQGludGVyZmFjZVxuICogQGV4dGVuZHMge0lUaGVuYWJsZS48VFlQRT59XG4gKiBAdGVtcGxhdGUgVFlQRVxuICovXG52YXIgVGhlbmFibGUgPSBmdW5jdGlvbigpIHt9O1xuXG4vKipcbiAqIEFkZHMgY2FsbGJhY2tzIHRoYXQgd2lsbCBvcGVyYXRlIG9uIHRoZSByZXN1bHQgb2YgdGhlIFRoZW5hYmxlLCByZXR1cm5pbmcgYVxuICogbmV3IGNoaWxkIFByb21pc2UuXG4gKlxuICogSWYgdGhlIFRoZW5hYmxlIGlzIGZ1bGZpbGxlZCwgdGhlIHtAY29kZSBvbkZ1bGZpbGxlZH0gY2FsbGJhY2sgd2lsbCBiZVxuICogaW52b2tlZCB3aXRoIHRoZSBmdWxmaWxsbWVudCB2YWx1ZSBhcyBhcmd1bWVudCwgYW5kIHRoZSBjaGlsZCBQcm9taXNlIHdpbGxcbiAqIGJlIGZ1bGZpbGxlZCB3aXRoIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGNhbGxiYWNrLiBJZiB0aGUgY2FsbGJhY2sgdGhyb3dzXG4gKiBhbiBleGNlcHRpb24sIHRoZSBjaGlsZCBQcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWQgd2l0aCB0aGUgdGhyb3duIHZhbHVlXG4gKiBpbnN0ZWFkLlxuICpcbiAqIElmIHRoZSBUaGVuYWJsZSBpcyByZWplY3RlZCwgdGhlIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFjayB3aWxsIGJlIGludm9rZWRcbiAqIHdpdGggdGhlIHJlamVjdGlvbiByZWFzb24gYXMgYXJndW1lbnQsIGFuZCB0aGUgY2hpbGQgUHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkXG4gKiB3aXRoIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGNhbGxiYWNrIG9yIHRocm93biB2YWx1ZS5cbiAqXG4gKiBAcGFyYW0gez8oZnVuY3Rpb24odGhpczpUSElTLCBUWVBFKTpcbiAqICAgICAgICAgICAgIChSRVNVTFR8SVRoZW5hYmxlLjxSRVNVTFQ+fFRoZW5hYmxlKSk9fSBvcHRfb25GdWxmaWxsZWQgQVxuICogICAgIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBpbnZva2VkIHdpdGggdGhlIGZ1bGZpbGxtZW50IHZhbHVlIGlmIHRoZSBQcm9taXNlXG4gKiAgICAgaXMgZnVsbGZpbGxlZC5cbiAqIEBwYXJhbSB7PyhmdW5jdGlvbigqKTogKik9fSBvcHRfb25SZWplY3RlZCBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBpbnZva2VkXG4gKiAgICAgd2l0aCB0aGUgcmVqZWN0aW9uIHJlYXNvbiBpZiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZC5cbiAqIEBwYXJhbSB7VEhJUz19IG9wdF9jb250ZXh0IEFuIG9wdGlvbmFsIGNvbnRleHQgb2JqZWN0IHRoYXQgd2lsbCBiZSB0aGVcbiAqICAgICBleGVjdXRpb24gY29udGV4dCBmb3IgdGhlIGNhbGxiYWNrcy4gQnkgZGVmYXVsdCwgZnVuY3Rpb25zIGFyZSBleGVjdXRlZFxuICogICAgIHdpdGggdGhlIGRlZmF1bHQgdGhpcy5cbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2UuPFJFU1VMVD59IEEgbmV3IFByb21pc2UgdGhhdCB3aWxsIHJlY2VpdmUgdGhlXG4gKiAgICAgcmVzdWx0IG9mIHRoZSBmdWxmaWxsbWVudCBvciByZWplY3Rpb24gY2FsbGJhY2suXG4gKiBAdGVtcGxhdGUgUkVTVUxULFRISVNcbiAqL1xuVGhlbmFibGUucHJvdG90eXBlLnRoZW4gPSBmdW5jdGlvbigpIHt9O1xuXG5cbi8qKlxuICogQW4gZXhwYW5kbyBwcm9wZXJ0eSB0byBpbmRpY2F0ZSB0aGF0IGFuIG9iamVjdCBpbXBsZW1lbnRzXG4gKiB7QGNvZGUgVGhlbmFibGV9LlxuICpcbiAqIHtAc2VlIGFkZEltcGxlbWVudGF0aW9ufS5cbiAqXG4gKiBAY29uc3RcbiAqL1xuVGhlbmFibGUuSU1QTEVNRU5URURfQllfUFJPUCA9ICckZ29vZ19UaGVuYWJsZSc7XG5cblxuLyoqXG4gKiBNYXJrcyBhIGdpdmVuIGNsYXNzIChjb25zdHJ1Y3RvcikgYXMgYW4gaW1wbGVtZW50YXRpb24gb2YgVGhlbmFibGUsIHNvXG4gKiB0aGF0IHdlIGNhbiBxdWVyeSB0aGF0IGZhY3QgYXQgcnVudGltZS4gVGhlIGNsYXNzIG11c3QgaGF2ZSBhbHJlYWR5XG4gKiBpbXBsZW1lbnRlZCB0aGUgaW50ZXJmYWNlLlxuICogRXhwb3J0cyBhICd0aGVuJyBtZXRob2Qgb24gdGhlIGNvbnN0cnVjdG9yIHByb3RvdHlwZSwgc28gdGhhdCB0aGUgb2JqZWN0c1xuICogYWxzbyBpbXBsZW1lbnQgdGhlIGV4dGVybiB7QHNlZSBUaGVuYWJsZX0gaW50ZXJmYWNlIGZvciBpbnRlcm9wIHdpdGhcbiAqIG90aGVyIFByb21pc2UgaW1wbGVtZW50YXRpb25zLlxuICogQHBhcmFtIHtmdW5jdGlvbihuZXc6VGhlbmFibGUsLi4uWz9dKX0gY3RvciBUaGUgY2xhc3MgY29uc3RydWN0b3IuIFRoZVxuICogICAgIGNvcnJlc3BvbmRpbmcgY2xhc3MgbXVzdCBoYXZlIGFscmVhZHkgaW1wbGVtZW50ZWQgdGhlIGludGVyZmFjZS5cbiAqL1xuVGhlbmFibGUuYWRkSW1wbGVtZW50YXRpb24gPSBmdW5jdGlvbihjdG9yKSB7XG4gIGN0b3IucHJvdG90eXBlLnRoZW4gPSBjdG9yLnByb3RvdHlwZS50aGVuO1xuICBjdG9yLnByb3RvdHlwZS4kZ29vZ19UaGVuYWJsZSA9IHRydWU7XG59O1xuXG5cbi8qKlxuICogQHBhcmFtIHsqfSBvYmplY3RcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgYSBnaXZlbiBpbnN0YW5jZSBpbXBsZW1lbnRzIHtAY29kZSBUaGVuYWJsZX0uXG4gKiAgICAgVGhlIGNsYXNzL3N1cGVyY2xhc3Mgb2YgdGhlIGluc3RhbmNlIG11c3QgY2FsbCB7QGNvZGUgYWRkSW1wbGVtZW50YXRpb259LlxuICovXG5UaGVuYWJsZS5pc0ltcGxlbWVudGVkQnkgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgaWYgKCFvYmplY3QpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgdHJ5IHtcbiAgICByZXR1cm4gISFvYmplY3QuJGdvb2dfVGhlbmFibGU7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBQcm9wZXJ0eSBhY2Nlc3Mgc2VlbXMgdG8gYmUgZm9yYmlkZGVuLlxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuXG4vKipcbiAqIExpa2UgYmluZCgpLCBleGNlcHQgdGhhdCBhICd0aGlzIG9iamVjdCcgaXMgbm90IHJlcXVpcmVkLiBVc2VmdWwgd2hlbiB0aGVcbiAqIHRhcmdldCBmdW5jdGlvbiBpcyBhbHJlYWR5IGJvdW5kLlxuICpcbiAqIFVzYWdlOlxuICogdmFyIGcgPSBwYXJ0aWFsKGYsIGFyZzEsIGFyZzIpO1xuICogZyhhcmczLCBhcmc0KTtcbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBBIGZ1bmN0aW9uIHRvIHBhcnRpYWxseSBhcHBseS5cbiAqIEBwYXJhbSB7Li4uKn0gdmFyX2FyZ3MgQWRkaXRpb25hbCBhcmd1bWVudHMgdGhhdCBhcmUgcGFydGlhbGx5IGFwcGxpZWQgdG8gZm4uXG4gKiBAcmV0dXJuIHshRnVuY3Rpb259IEEgcGFydGlhbGx5LWFwcGxpZWQgZm9ybSBvZiB0aGUgZnVuY3Rpb24gYmluZCgpIHdhc1xuICogICAgIGludm9rZWQgYXMgYSBtZXRob2Qgb2YuXG4gKi9cbnZhciBwYXJ0aWFsID0gZnVuY3Rpb24oZm4pIHtcbiAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgLy8gQ2xvbmUgdGhlIGFycmF5ICh3aXRoIHNsaWNlKCkpIGFuZCBhcHBlbmQgYWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICAvLyB0byB0aGUgZXhpc3RpbmcgYXJndW1lbnRzLlxuICAgIHZhciBuZXdBcmdzID0gYXJncy5zbGljZSgpO1xuICAgIG5ld0FyZ3MucHVzaC5hcHBseShuZXdBcmdzLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBuZXdBcmdzKTtcbiAgfTtcbn07XG5cbi8qKlxuICogUHJvbWlzZXMgcHJvdmlkZSBhIHJlc3VsdCB0aGF0IG1heSBiZSByZXNvbHZlZCBhc3luY2hyb25vdXNseS4gQSBQcm9taXNlIG1heVxuICogYmUgcmVzb2x2ZWQgYnkgYmVpbmcgZnVsZmlsbGVkIG9yIHJlamVjdGVkIHdpdGggYSB2YWx1ZSwgd2hpY2ggd2lsbCBiZSBrbm93blxuICogYXMgdGhlIGZ1bGZpbGxtZW50IHZhbHVlIG9yIHRoZSByZWplY3Rpb24gcmVhc29uLiBXaGV0aGVyIGZ1bGZpbGxlZCBvclxuICogcmVqZWN0ZWQsIHRoZSBQcm9taXNlIHJlc3VsdCBpcyBpbW11dGFibGUgb25jZSBpdCBpcyBzZXQuXG4gKlxuICogUHJvbWlzZXMgbWF5IHJlcHJlc2VudCByZXN1bHRzIG9mIGFueSB0eXBlLCBpbmNsdWRpbmcgdW5kZWZpbmVkLiBSZWplY3Rpb25cbiAqIHJlYXNvbnMgYXJlIHR5cGljYWxseSBFcnJvcnMsIGJ1dCBtYXkgYWxzbyBiZSBvZiBhbnkgdHlwZS4gQ2xvc3VyZSBQcm9taXNlc1xuICogYWxsb3cgZm9yIG9wdGlvbmFsIHR5cGUgYW5ub3RhdGlvbnMgdGhhdCBlbmZvcmNlIHRoYXQgZnVsZmlsbG1lbnQgdmFsdWVzIGFyZVxuICogb2YgdGhlIGFwcHJvcHJpYXRlIHR5cGVzIGF0IGNvbXBpbGUgdGltZS5cbiAqXG4gKiBUaGUgcmVzdWx0IG9mIGEgUHJvbWlzZSBpcyBhY2Nlc3NpYmxlIGJ5IGNhbGxpbmcge0Bjb2RlIHRoZW59IGFuZCByZWdpc3RlcmluZ1xuICoge0Bjb2RlIG9uRnVsZmlsbGVkfSBhbmQge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrcy4gT25jZSB0aGUgUHJvbWlzZVxuICogcmVzb2x2ZXMsIHRoZSByZWxldmFudCBjYWxsYmFja3MgYXJlIGludm9rZWQgd2l0aCB0aGUgZnVsZmlsbG1lbnQgdmFsdWUgb3JcbiAqIHJlamVjdGlvbiByZWFzb24gYXMgYXJndW1lbnQuIENhbGxiYWNrcyBhcmUgYWx3YXlzIGludm9rZWQgaW4gdGhlIG9yZGVyIHRoZXlcbiAqIHdlcmUgcmVnaXN0ZXJlZCwgZXZlbiB3aGVuIGFkZGl0aW9uYWwge0Bjb2RlIHRoZW59IGNhbGxzIGFyZSBtYWRlIGZyb20gaW5zaWRlXG4gKiBhbm90aGVyIGNhbGxiYWNrLiBBIGNhbGxiYWNrIGlzIGFsd2F5cyBydW4gYXN5bmNocm9ub3VzbHkgc29tZXRpbWUgYWZ0ZXIgdGhlXG4gKiBzY29wZSBjb250YWluaW5nIHRoZSByZWdpc3RlcmluZyB7QGNvZGUgdGhlbn0gaW52b2NhdGlvbiBoYXMgcmV0dXJuZWQuXG4gKlxuICogSWYgYSBQcm9taXNlIGlzIHJlc29sdmVkIHdpdGggYW5vdGhlciBQcm9taXNlLCB0aGUgZmlyc3QgUHJvbWlzZSB3aWxsIGJsb2NrXG4gKiB1bnRpbCB0aGUgc2Vjb25kIGlzIHJlc29sdmVkLCBhbmQgdGhlbiBhc3N1bWVzIHRoZSBzYW1lIHJlc3VsdCBhcyB0aGUgc2Vjb25kXG4gKiBQcm9taXNlLiBUaGlzIGFsbG93cyBQcm9taXNlcyB0byBkZXBlbmQgb24gdGhlIHJlc3VsdHMgb2Ygb3RoZXIgUHJvbWlzZXMsXG4gKiBsaW5raW5nIHRvZ2V0aGVyIG11bHRpcGxlIGFzeW5jaHJvbm91cyBvcGVyYXRpb25zLlxuICpcbiAqIFRoaXMgaW1wbGVtZW50YXRpb24gaXMgY29tcGF0aWJsZSB3aXRoIHRoZSBQcm9taXNlcy9BKyBzcGVjaWZpY2F0aW9uIGFuZFxuICogcGFzc2VzIHRoYXQgc3BlY2lmaWNhdGlvbidzIGNvbmZvcm1hbmNlIHRlc3Qgc3VpdGUuIEEgQ2xvc3VyZSBQcm9taXNlIG1heSBiZVxuICogcmVzb2x2ZWQgd2l0aCBhIFByb21pc2UgaW5zdGFuY2UgKG9yIHN1ZmZpY2llbnRseSBjb21wYXRpYmxlIFByb21pc2UtbGlrZVxuICogb2JqZWN0KSBjcmVhdGVkIGJ5IG90aGVyIFByb21pc2UgaW1wbGVtZW50YXRpb25zLiBGcm9tIHRoZSBzcGVjaWZpY2F0aW9uLFxuICogUHJvbWlzZS1saWtlIG9iamVjdHMgYXJlIGtub3duIGFzIFwiVGhlbmFibGVzXCIuXG4gKlxuICogQHNlZSBodHRwOi8vcHJvbWlzZXNhcGx1cy5jb20vXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbihcbiAqICAgICAgICAgICAgIHRoaXM6UkVTT0xWRVJfQ09OVEVYVCxcbiAqICAgICAgICAgICAgIGZ1bmN0aW9uKChUWVBFfElUaGVuYWJsZS48VFlQRT58VGhlbmFibGUpKSxcbiAqICAgICAgICAgICAgIGZ1bmN0aW9uKCopKTogdm9pZH0gcmVzb2x2ZXJcbiAqICAgICBJbml0aWFsaXphdGlvbiBmdW5jdGlvbiB0aGF0IGlzIGludm9rZWQgaW1tZWRpYXRlbHkgd2l0aCB7QGNvZGUgcmVzb2x2ZX1cbiAqICAgICBhbmQge0Bjb2RlIHJlamVjdH0gZnVuY3Rpb25zIGFzIGFyZ3VtZW50cy4gVGhlIFByb21pc2UgaXMgcmVzb2x2ZWQgb3JcbiAqICAgICByZWplY3RlZCB3aXRoIHRoZSBmaXJzdCBhcmd1bWVudCBwYXNzZWQgdG8gZWl0aGVyIGZ1bmN0aW9uLlxuICogQHBhcmFtIHtSRVNPTFZFUl9DT05URVhUPX0gb3B0X2NvbnRleHQgQW4gb3B0aW9uYWwgY29udGV4dCBmb3IgZXhlY3V0aW5nIHRoZVxuICogICAgIHJlc29sdmVyIGZ1bmN0aW9uLiBJZiB1bnNwZWNpZmllZCwgdGhlIHJlc29sdmVyIGZ1bmN0aW9uIHdpbGwgYmUgZXhlY3V0ZWRcbiAqICAgICBpbiB0aGUgZGVmYXVsdCBzY29wZS5cbiAqIEBjb25zdHJ1Y3RvclxuICogQHN0cnVjdFxuICogQGZpbmFsXG4gKiBAaW1wbGVtZW50cyB7VGhlbmFibGUuPFRZUEU+fVxuICogQHRlbXBsYXRlIFRZUEUsUkVTT0xWRVJfQ09OVEVYVFxuICovXG52YXIgQ2FuY2VsbGFibGVQcm9taXNlID0gZnVuY3Rpb24ocmVzb2x2ZXIsIG9wdF9jb250ZXh0KSB7XG4gIC8qKlxuICAgKiBUaGUgaW50ZXJuYWwgc3RhdGUgb2YgdGhpcyBQcm9taXNlLiBFaXRoZXIgUEVORElORywgRlVMRklMTEVELCBSRUpFQ1RFRCwgb3JcbiAgICogQkxPQ0tFRC5cbiAgICogQHByaXZhdGUge0NhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV99XG4gICAqL1xuICB0aGlzLnN0YXRlXyA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUEVORElORztcblxuICAvKipcbiAgICogVGhlIHJlc29sdmVkIHJlc3VsdCBvZiB0aGUgUHJvbWlzZS4gSW1tdXRhYmxlIG9uY2Ugc2V0IHdpdGggZWl0aGVyIGFcbiAgICogZnVsZmlsbG1lbnQgdmFsdWUgb3IgcmVqZWN0aW9uIHJlYXNvbi5cbiAgICogQHByaXZhdGUgeyp9XG4gICAqL1xuICB0aGlzLnJlc3VsdF8gPSB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEZvciBQcm9taXNlcyBjcmVhdGVkIGJ5IGNhbGxpbmcge0Bjb2RlIHRoZW4oKX0sIHRoZSBvcmlnaW5hdGluZyBwYXJlbnQuXG4gICAqIEBwcml2YXRlIHtDYW5jZWxsYWJsZVByb21pc2V9XG4gICAqL1xuICB0aGlzLnBhcmVudF8gPSBudWxsO1xuXG4gIC8qKlxuICAgKiBUaGUgbGlzdCBvZiB7QGNvZGUgb25GdWxmaWxsZWR9IGFuZCB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2tzIGFkZGVkIHRvXG4gICAqIHRoaXMgUHJvbWlzZSBieSBjYWxscyB0byB7QGNvZGUgdGhlbigpfS5cbiAgICogQHByaXZhdGUge0FycmF5LjxDYW5jZWxsYWJsZVByb21pc2UuQ2FsbGJhY2tFbnRyeV8+fVxuICAgKi9cbiAgdGhpcy5jYWxsYmFja0VudHJpZXNfID0gbnVsbDtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgUHJvbWlzZSBpcyBpbiB0aGUgcXVldWUgb2YgUHJvbWlzZXMgdG8gZXhlY3V0ZS5cbiAgICogQHByaXZhdGUge2Jvb2xlYW59XG4gICAqL1xuICB0aGlzLmV4ZWN1dGluZ18gPSBmYWxzZTtcblxuICBpZiAoQ2FuY2VsbGFibGVQcm9taXNlLlVOSEFORExFRF9SRUpFQ1RJT05fREVMQVkgPiAwKSB7XG4gICAgLyoqXG4gICAgICogQSB0aW1lb3V0IElEIHVzZWQgd2hlbiB0aGUge0Bjb2RlIFVOSEFORExFRF9SRUpFQ1RJT05fREVMQVl9IGlzIGdyZWF0ZXJcbiAgICAgKiB0aGFuIDAgbWlsbGlzZWNvbmRzLiBUaGUgSUQgaXMgc2V0IHdoZW4gdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQsIGFuZFxuICAgICAqIGNsZWFyZWQgb25seSBpZiBhbiB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2sgaXMgaW52b2tlZCBmb3IgdGhlXG4gICAgICogUHJvbWlzZSAob3Igb25lIG9mIGl0cyBkZXNjZW5kYW50cykgYmVmb3JlIHRoZSBkZWxheSBpcyBleGNlZWRlZC5cbiAgICAgKlxuICAgICAqIElmIHRoZSByZWplY3Rpb24gaXMgbm90IGhhbmRsZWQgYmVmb3JlIHRoZSB0aW1lb3V0IGNvbXBsZXRlcywgdGhlXG4gICAgICogcmVqZWN0aW9uIHJlYXNvbiBpcyBwYXNzZWQgdG8gdGhlIHVuaGFuZGxlZCByZWplY3Rpb24gaGFuZGxlci5cbiAgICAgKiBAcHJpdmF0ZSB7bnVtYmVyfVxuICAgICAqL1xuICAgIHRoaXMudW5oYW5kbGVkUmVqZWN0aW9uSWRfID0gMDtcbiAgfSBlbHNlIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA9PT0gMCkge1xuICAgIC8qKlxuICAgICAqIFdoZW4gdGhlIHtAY29kZSBVTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZfSBpcyBzZXQgdG8gMCBtaWxsaXNlY29uZHMsIGFcbiAgICAgKiBib29sZWFuIHRoYXQgaXMgc2V0IGlmIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLCBhbmQgcmVzZXQgdG8gZmFsc2UgaWYgYW5cbiAgICAgKiB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2sgaXMgaW52b2tlZCBmb3IgdGhlIFByb21pc2UgKG9yIG9uZSBvZiBpdHNcbiAgICAgKiBkZXNjZW5kYW50cykuIElmIHRoZSByZWplY3Rpb24gaXMgbm90IGhhbmRsZWQgYmVmb3JlIHRoZSBuZXh0IHRpbWVzdGVwLFxuICAgICAqIHRoZSByZWplY3Rpb24gcmVhc29uIGlzIHBhc3NlZCB0byB0aGUgdW5oYW5kbGVkIHJlamVjdGlvbiBoYW5kbGVyLlxuICAgICAqIEBwcml2YXRlIHtib29sZWFufVxuICAgICAqL1xuICAgIHRoaXMuaGFkVW5oYW5kbGVkUmVqZWN0aW9uXyA9IGZhbHNlO1xuICB9XG5cbiAgdHJ5IHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgcmVzb2x2ZXIuY2FsbChcbiAgICAgIG9wdF9jb250ZXh0LCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICBzZWxmLnJlc29sdmVfKENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uRlVMRklMTEVELCB2YWx1ZSk7XG4gICAgICB9LCBmdW5jdGlvbihyZWFzb24pIHtcbiAgICAgICAgc2VsZi5yZXNvbHZlXyhDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVELCByZWFzb24pO1xuICAgICAgfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aGlzLnJlc29sdmVfKENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQsIGUpO1xuICB9XG59O1xuXG4vKipcbiAqIFRoZSBkZWxheSBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIGEgcmVqZWN0ZWQgUHJvbWlzZSdzIHJlYXNvbiBpcyBwYXNzZWQgdG9cbiAqIHRoZSByZWplY3Rpb24gaGFuZGxlci4gQnkgZGVmYXVsdCwgdGhlIHJlamVjdGlvbiBoYW5kbGVyIHJldGhyb3dzIHRoZVxuICogcmVqZWN0aW9uIHJlYXNvbiBzbyB0aGF0IGl0IGFwcGVhcnMgaW4gdGhlIGRldmVsb3BlciBjb25zb2xlIG9yXG4gKiB7QGNvZGUgd2luZG93Lm9uZXJyb3J9IGhhbmRsZXIuXG4gKiBSZWplY3Rpb25zIGFyZSByZXRocm93biBhcyBxdWlja2x5IGFzIHBvc3NpYmxlIGJ5IGRlZmF1bHQuIEEgbmVnYXRpdmUgdmFsdWVcbiAqIGRpc2FibGVzIHJlamVjdGlvbiBoYW5kbGluZyBlbnRpcmVseS5cbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5VTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZID0gMDtcblxuXG4vKipcbiAqIFRoZSBwb3NzaWJsZSBpbnRlcm5hbCBzdGF0ZXMgZm9yIGEgUHJvbWlzZS4gVGhlc2Ugc3RhdGVzIGFyZSBub3QgZGlyZWN0bHlcbiAqIG9ic2VydmFibGUgdG8gZXh0ZXJuYWwgY2FsbGVycy5cbiAqIEBlbnVtIHtudW1iZXJ9XG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfID0ge1xuICAvKiogVGhlIFByb21pc2UgaXMgd2FpdGluZyBmb3IgcmVzb2x1dGlvbi4gKi9cbiAgUEVORElORzogMCxcblxuICAvKiogVGhlIFByb21pc2UgaXMgYmxvY2tlZCB3YWl0aW5nIGZvciB0aGUgcmVzdWx0IG9mIGFub3RoZXIgVGhlbmFibGUuICovXG4gIEJMT0NLRUQ6IDEsXG5cbiAgLyoqIFRoZSBQcm9taXNlIGhhcyBiZWVuIHJlc29sdmVkIHdpdGggYSBmdWxmaWxsbWVudCB2YWx1ZS4gKi9cbiAgRlVMRklMTEVEOiAyLFxuXG4gIC8qKiBUaGUgUHJvbWlzZSBoYXMgYmVlbiByZXNvbHZlZCB3aXRoIGEgcmVqZWN0aW9uIHJlYXNvbi4gKi9cbiAgUkVKRUNURUQ6IDNcbn07XG5cblxuLyoqXG4gKiBUeXBlZGVmIGZvciBlbnRyaWVzIGluIHRoZSBjYWxsYmFjayBjaGFpbi4gRWFjaCBjYWxsIHRvIHtAY29kZSB0aGVufSxcbiAqIHtAY29kZSB0aGVuQ2F0Y2h9LCBvciB7QGNvZGUgdGhlbkFsd2F5c30gY3JlYXRlcyBhbiBlbnRyeSBjb250YWluaW5nIHRoZVxuICogZnVuY3Rpb25zIHRoYXQgbWF5IGJlIGludm9rZWQgb25jZSB0aGUgUHJvbWlzZSBpcyByZXNvbHZlZC5cbiAqXG4gKiBAdHlwZWRlZiB7e1xuICogICBjaGlsZDogQ2FuY2VsbGFibGVQcm9taXNlLFxuICogICBvbkZ1bGZpbGxlZDogZnVuY3Rpb24oKiksXG4gKiAgIG9uUmVqZWN0ZWQ6IGZ1bmN0aW9uKCopXG4gKiB9fVxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLkNhbGxiYWNrRW50cnlfID0gbnVsbDtcblxuXG4vKipcbiAqIEBwYXJhbSB7KFRZUEV8VGhlbmFibGUuPFRZUEU+fFRoZW5hYmxlKT19IG9wdF92YWx1ZVxuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZS48VFlQRT59IEEgbmV3IFByb21pc2UgdGhhdCBpcyBpbW1lZGlhdGVseSByZXNvbHZlZFxuICogICAgIHdpdGggdGhlIGdpdmVuIHZhbHVlLlxuICogQHRlbXBsYXRlIFRZUEVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUgPSBmdW5jdGlvbihvcHRfdmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgcmVzb2x2ZShvcHRfdmFsdWUpO1xuICAgIH0pO1xufTtcblxuXG4vKipcbiAqIEBwYXJhbSB7Kj19IG9wdF9yZWFzb25cbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2V9IEEgbmV3IFByb21pc2UgdGhhdCBpcyBpbW1lZGlhdGVseSByZWplY3RlZCB3aXRoIHRoZVxuICogICAgIGdpdmVuIHJlYXNvbi5cbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnJlamVjdCA9IGZ1bmN0aW9uKG9wdF9yZWFzb24pIHtcbiAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICByZWplY3Qob3B0X3JlYXNvbik7XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQHBhcmFtIHshQXJyYXkuPCEoVGhlbmFibGUuPFRZUEU+fFRoZW5hYmxlKT59IHByb21pc2VzXG4gKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlLjxUWVBFPn0gQSBQcm9taXNlIHRoYXQgcmVjZWl2ZXMgdGhlIHJlc3VsdCBvZiB0aGVcbiAqICAgICBmaXJzdCBQcm9taXNlIChvciBQcm9taXNlLWxpa2UpIGlucHV0IHRvIGNvbXBsZXRlLlxuICogQHRlbXBsYXRlIFRZUEVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnJhY2UgPSBmdW5jdGlvbihwcm9taXNlcykge1xuICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGlmICghcHJvbWlzZXMubGVuZ3RoKSB7XG4gICAgICAgIHJlc29sdmUodW5kZWZpbmVkKTtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGkgPSAwLCBwcm9taXNlOyAocHJvbWlzZSA9IHByb21pc2VzW2ldKTsgaSsrKSB7XG4gICAgICAgIHByb21pc2UudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgfVxuICAgIH0pO1xufTtcblxuXG4vKipcbiAqIEBwYXJhbSB7IUFycmF5LjwhKFRoZW5hYmxlLjxUWVBFPnxUaGVuYWJsZSk+fSBwcm9taXNlc1xuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZS48IUFycmF5LjxUWVBFPj59IEEgUHJvbWlzZSB0aGF0IHJlY2VpdmVzIGEgbGlzdCBvZlxuICogICAgIGV2ZXJ5IGZ1bGZpbGxlZCB2YWx1ZSBvbmNlIGV2ZXJ5IGlucHV0IFByb21pc2UgKG9yIFByb21pc2UtbGlrZSkgaXNcbiAqICAgICBzdWNjZXNzZnVsbHkgZnVsZmlsbGVkLCBvciBpcyByZWplY3RlZCBieSB0aGUgZmlyc3QgcmVqZWN0aW9uIHJlc3VsdC5cbiAqIEB0ZW1wbGF0ZSBUWVBFXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5hbGwgPSBmdW5jdGlvbihwcm9taXNlcykge1xuICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIHZhciB0b0Z1bGZpbGwgPSBwcm9taXNlcy5sZW5ndGg7XG4gICAgICB2YXIgdmFsdWVzID0gW107XG5cbiAgICAgIGlmICghdG9GdWxmaWxsKSB7XG4gICAgICAgIHJlc29sdmUodmFsdWVzKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgb25GdWxmaWxsID0gZnVuY3Rpb24oaW5kZXgsIHZhbHVlKSB7XG4gICAgICAgIHRvRnVsZmlsbC0tO1xuICAgICAgICB2YWx1ZXNbaW5kZXhdID0gdmFsdWU7XG4gICAgICAgIGlmICh0b0Z1bGZpbGwgPT09IDApIHtcbiAgICAgICAgICByZXNvbHZlKHZhbHVlcyk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIHZhciBvblJlamVjdCA9IGZ1bmN0aW9uKHJlYXNvbikge1xuICAgICAgICByZWplY3QocmVhc29uKTtcbiAgICAgIH07XG5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBwcm9taXNlOyAocHJvbWlzZSA9IHByb21pc2VzW2ldKTsgaSsrKSB7XG4gICAgICAgIHByb21pc2UudGhlbihwYXJ0aWFsKG9uRnVsZmlsbCwgaSksIG9uUmVqZWN0KTtcbiAgICAgIH1cbiAgICB9KTtcbn07XG5cblxuLyoqXG4gKiBAcGFyYW0geyFBcnJheS48IShUaGVuYWJsZS48VFlQRT58VGhlbmFibGUpPn0gcHJvbWlzZXNcbiAqIEByZXR1cm4geyFDYW5jZWxsYWJsZVByb21pc2UuPFRZUEU+fSBBIFByb21pc2UgdGhhdCByZWNlaXZlcyB0aGUgdmFsdWUgb2ZcbiAqICAgICB0aGUgZmlyc3QgaW5wdXQgdG8gYmUgZnVsZmlsbGVkLCBvciBpcyByZWplY3RlZCB3aXRoIGEgbGlzdCBvZiBldmVyeVxuICogICAgIHJlamVjdGlvbiByZWFzb24gaWYgYWxsIGlucHV0cyBhcmUgcmVqZWN0ZWQuXG4gKiBAdGVtcGxhdGUgVFlQRVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UuZmlyc3RGdWxmaWxsZWQgPSBmdW5jdGlvbihwcm9taXNlcykge1xuICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIHZhciB0b1JlamVjdCA9IHByb21pc2VzLmxlbmd0aDtcbiAgICAgIHZhciByZWFzb25zID0gW107XG5cbiAgICAgIGlmICghdG9SZWplY3QpIHtcbiAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBvbkZ1bGZpbGwgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICByZXNvbHZlKHZhbHVlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBvblJlamVjdCA9IGZ1bmN0aW9uKGluZGV4LCByZWFzb24pIHtcbiAgICAgICAgdG9SZWplY3QtLTtcbiAgICAgICAgcmVhc29uc1tpbmRleF0gPSByZWFzb247XG4gICAgICAgIGlmICh0b1JlamVjdCA9PT0gMCkge1xuICAgICAgICAgIHJlamVjdChyZWFzb25zKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIHByb21pc2U7IChwcm9taXNlID0gcHJvbWlzZXNbaV0pOyBpKyspIHtcbiAgICAgICAgcHJvbWlzZS50aGVuKG9uRnVsZmlsbCwgcGFydGlhbChvblJlamVjdCwgaSkpO1xuICAgICAgfVxuICAgIH0pO1xufTtcblxuXG4vKipcbiAqIEFkZHMgY2FsbGJhY2tzIHRoYXQgd2lsbCBvcGVyYXRlIG9uIHRoZSByZXN1bHQgb2YgdGhlIFByb21pc2UsIHJldHVybmluZyBhXG4gKiBuZXcgY2hpbGQgUHJvbWlzZS5cbiAqXG4gKiBJZiB0aGUgUHJvbWlzZSBpcyBmdWxmaWxsZWQsIHRoZSB7QGNvZGUgb25GdWxmaWxsZWR9IGNhbGxiYWNrIHdpbGwgYmUgaW52b2tlZFxuICogd2l0aCB0aGUgZnVsZmlsbG1lbnQgdmFsdWUgYXMgYXJndW1lbnQsIGFuZCB0aGUgY2hpbGQgUHJvbWlzZSB3aWxsIGJlXG4gKiBmdWxmaWxsZWQgd2l0aCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBjYWxsYmFjay4gSWYgdGhlIGNhbGxiYWNrIHRocm93cyBhblxuICogZXhjZXB0aW9uLCB0aGUgY2hpbGQgUHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkIHdpdGggdGhlIHRocm93biB2YWx1ZSBpbnN0ZWFkLlxuICpcbiAqIElmIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLCB0aGUge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrIHdpbGwgYmUgaW52b2tlZFxuICogd2l0aCB0aGUgcmVqZWN0aW9uIHJlYXNvbiBhcyBhcmd1bWVudCwgYW5kIHRoZSBjaGlsZCBQcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWRcbiAqIHdpdGggdGhlIHJldHVybiB2YWx1ZSAob3IgdGhyb3duIHZhbHVlKSBvZiB0aGUgY2FsbGJhY2suXG4gKlxuICogQG92ZXJyaWRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudGhlbiA9IGZ1bmN0aW9uKG9wdF9vbkZ1bGZpbGxlZCwgb3B0X29uUmVqZWN0ZWQsIG9wdF9jb250ZXh0KSB7XG4gIHJldHVybiB0aGlzLmFkZENoaWxkUHJvbWlzZV8oXG4gICAgaXNGdW5jdGlvbihvcHRfb25GdWxmaWxsZWQpID8gb3B0X29uRnVsZmlsbGVkIDogbnVsbCxcbiAgICBpc0Z1bmN0aW9uKG9wdF9vblJlamVjdGVkKSA/IG9wdF9vblJlamVjdGVkIDogbnVsbCxcbiAgICBvcHRfY29udGV4dCk7XG59O1xuVGhlbmFibGUuYWRkSW1wbGVtZW50YXRpb24oQ2FuY2VsbGFibGVQcm9taXNlKTtcblxuXG4vKipcbiAqIEFkZHMgYSBjYWxsYmFjayB0aGF0IHdpbGwgYmUgaW52b2tlZCB3aGV0aGVyIHRoZSBQcm9taXNlIGlzIGZ1bGZpbGxlZCBvclxuICogcmVqZWN0ZWQuIFRoZSBjYWxsYmFjayByZWNlaXZlcyBubyBhcmd1bWVudCwgYW5kIG5vIG5ldyBjaGlsZCBQcm9taXNlIGlzXG4gKiBjcmVhdGVkLiBUaGlzIGlzIHVzZWZ1bCBmb3IgZW5zdXJpbmcgdGhhdCBjbGVhbnVwIHRha2VzIHBsYWNlIGFmdGVyIGNlcnRhaW5cbiAqIGFzeW5jaHJvbm91cyBvcGVyYXRpb25zLiBDYWxsYmFja3MgYWRkZWQgd2l0aCB7QGNvZGUgdGhlbkFsd2F5c30gd2lsbCBiZVxuICogZXhlY3V0ZWQgaW4gdGhlIHNhbWUgb3JkZXIgd2l0aCBvdGhlciBjYWxscyB0byB7QGNvZGUgdGhlbn0sXG4gKiB7QGNvZGUgdGhlbkFsd2F5c30sIG9yIHtAY29kZSB0aGVuQ2F0Y2h9LlxuICpcbiAqIFNpbmNlIGl0IGRvZXMgbm90IHByb2R1Y2UgYSBuZXcgY2hpbGQgUHJvbWlzZSwgY2FuY2VsbGF0aW9uIHByb3BhZ2F0aW9uIGlzXG4gKiBub3QgcHJldmVudGVkIGJ5IGFkZGluZyBjYWxsYmFja3Mgd2l0aCB7QGNvZGUgdGhlbkFsd2F5c30uIEEgUHJvbWlzZSB0aGF0IGhhc1xuICogYSBjbGVhbnVwIGhhbmRsZXIgYWRkZWQgd2l0aCB7QGNvZGUgdGhlbkFsd2F5c30gd2lsbCBiZSBjYW5jZWxlZCBpZiBhbGwgb2ZcbiAqIGl0cyBjaGlsZHJlbiBjcmVhdGVkIGJ5IHtAY29kZSB0aGVufSAob3Ige0Bjb2RlIHRoZW5DYXRjaH0pIGFyZSBjYW5jZWxlZC5cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKHRoaXM6VEhJUyk6IHZvaWR9IG9uUmVzb2x2ZWQgQSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgaW52b2tlZFxuICogICAgIHdoZW4gdGhlIFByb21pc2UgaXMgcmVzb2x2ZWQuXG4gKiBAcGFyYW0ge1RISVM9fSBvcHRfY29udGV4dCBBbiBvcHRpb25hbCBjb250ZXh0IG9iamVjdCB0aGF0IHdpbGwgYmUgdGhlXG4gKiAgICAgZXhlY3V0aW9uIGNvbnRleHQgZm9yIHRoZSBjYWxsYmFja3MuIEJ5IGRlZmF1bHQsIGZ1bmN0aW9ucyBhcmUgZXhlY3V0ZWRcbiAqICAgICBpbiB0aGUgZ2xvYmFsIHNjb3BlLlxuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZS48VFlQRT59IFRoaXMgUHJvbWlzZSwgZm9yIGNoYWluaW5nIGFkZGl0aW9uYWwgY2FsbHMuXG4gKiBAdGVtcGxhdGUgVEhJU1xuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnRoZW5BbHdheXMgPSBmdW5jdGlvbihvblJlc29sdmVkLCBvcHRfY29udGV4dCkge1xuICB2YXIgY2FsbGJhY2sgPSBmdW5jdGlvbigpIHtcbiAgICB0cnkge1xuICAgICAgLy8gRW5zdXJlIHRoYXQgbm8gYXJndW1lbnRzIGFyZSBwYXNzZWQgdG8gb25SZXNvbHZlZC5cbiAgICAgIG9uUmVzb2x2ZWQuY2FsbChvcHRfY29udGV4dCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBDYW5jZWxsYWJsZVByb21pc2UuaGFuZGxlUmVqZWN0aW9uXy5jYWxsKG51bGwsIGVycik7XG4gICAgfVxuICB9O1xuXG4gIHRoaXMuYWRkQ2FsbGJhY2tFbnRyeV8oe1xuICAgIGNoaWxkOiBudWxsLFxuICAgIG9uUmVqZWN0ZWQ6IGNhbGxiYWNrLFxuICAgIG9uRnVsZmlsbGVkOiBjYWxsYmFja1xuICB9KTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5cbi8qKlxuICogQWRkcyBhIGNhbGxiYWNrIHRoYXQgd2lsbCBiZSBpbnZva2VkIG9ubHkgaWYgdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQuIFRoaXNcbiAqIGlzIGVxdWl2YWxlbnQgdG8ge0Bjb2RlIHRoZW4obnVsbCwgb25SZWplY3RlZCl9LlxuICpcbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKHRoaXM6VEhJUywgKik6ICp9IG9uUmVqZWN0ZWQgQSBmdW5jdGlvbiB0aGF0IHdpbGwgYmVcbiAqICAgICBpbnZva2VkIHdpdGggdGhlIHJlamVjdGlvbiByZWFzb24gaWYgdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQuXG4gKiBAcGFyYW0ge1RISVM9fSBvcHRfY29udGV4dCBBbiBvcHRpb25hbCBjb250ZXh0IG9iamVjdCB0aGF0IHdpbGwgYmUgdGhlXG4gKiAgICAgZXhlY3V0aW9uIGNvbnRleHQgZm9yIHRoZSBjYWxsYmFja3MuIEJ5IGRlZmF1bHQsIGZ1bmN0aW9ucyBhcmUgZXhlY3V0ZWRcbiAqICAgICBpbiB0aGUgZ2xvYmFsIHNjb3BlLlxuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZX0gQSBuZXcgUHJvbWlzZSB0aGF0IHdpbGwgcmVjZWl2ZSB0aGUgcmVzdWx0IG9mIHRoZVxuICogICAgIGNhbGxiYWNrLlxuICogQHRlbXBsYXRlIFRISVNcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS50aGVuQ2F0Y2ggPSBmdW5jdGlvbihvblJlamVjdGVkLCBvcHRfY29udGV4dCkge1xuICByZXR1cm4gdGhpcy5hZGRDaGlsZFByb21pc2VfKG51bGwsIG9uUmVqZWN0ZWQsIG9wdF9jb250ZXh0KTtcbn07XG5cbi8qKlxuICogQWxpYXMgb2Yge0BsaW5rIENhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudGhlbkNhdGNofVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmNhdGNoID0gQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS50aGVuQ2F0Y2g7XG5cblxuLyoqXG4gKiBDYW5jZWxzIHRoZSBQcm9taXNlIGlmIGl0IGlzIHN0aWxsIHBlbmRpbmcgYnkgcmVqZWN0aW5nIGl0IHdpdGggYSBjYW5jZWxcbiAqIEVycm9yLiBObyBhY3Rpb24gaXMgcGVyZm9ybWVkIGlmIHRoZSBQcm9taXNlIGlzIGFscmVhZHkgcmVzb2x2ZWQuXG4gKlxuICogQWxsIGNoaWxkIFByb21pc2VzIG9mIHRoZSBjYW5jZWxlZCBQcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWQgd2l0aCB0aGUgc2FtZVxuICogY2FuY2VsIGVycm9yLCBhcyB3aXRoIG5vcm1hbCBQcm9taXNlIHJlamVjdGlvbi4gSWYgdGhlIFByb21pc2UgdG8gYmUgY2FuY2VsZWRcbiAqIGlzIHRoZSBvbmx5IGNoaWxkIG9mIGEgcGVuZGluZyBQcm9taXNlLCB0aGUgcGFyZW50IFByb21pc2Ugd2lsbCBhbHNvIGJlXG4gKiBjYW5jZWxlZC4gQ2FuY2VsbGF0aW9uIG1heSBwcm9wYWdhdGUgdXB3YXJkIHRocm91Z2ggbXVsdGlwbGUgZ2VuZXJhdGlvbnMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmc9fSBvcHRfbWVzc2FnZSBBbiBvcHRpb25hbCBkZWJ1Z2dpbmcgbWVzc2FnZSBmb3IgZGVzY3JpYmluZyB0aGVcbiAqICAgICBjYW5jZWxsYXRpb24gcmVhc29uLlxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmNhbmNlbCA9IGZ1bmN0aW9uKG9wdF9tZXNzYWdlKSB7XG4gIGlmICh0aGlzLnN0YXRlXyA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5QRU5ESU5HKSB7XG4gICAgYXN5bmMucnVuKGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGVyciA9IG5ldyBDYW5jZWxsYWJsZVByb21pc2UuQ2FuY2VsbGF0aW9uRXJyb3Iob3B0X21lc3NhZ2UpO1xuICAgICAgZXJyLklTX0NBTkNFTExBVElPTl9FUlJPUiA9IHRydWU7XG4gICAgICB0aGlzLmNhbmNlbEludGVybmFsXyhlcnIpO1xuICAgIH0sIHRoaXMpO1xuICB9XG59O1xuXG5cbi8qKlxuICogQ2FuY2VscyB0aGlzIFByb21pc2Ugd2l0aCB0aGUgZ2l2ZW4gZXJyb3IuXG4gKlxuICogQHBhcmFtIHshRXJyb3J9IGVyciBUaGUgY2FuY2VsbGF0aW9uIGVycm9yLlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5jYW5jZWxJbnRlcm5hbF8gPSBmdW5jdGlvbihlcnIpIHtcbiAgaWYgKHRoaXMuc3RhdGVfID09PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkcpIHtcbiAgICBpZiAodGhpcy5wYXJlbnRfKSB7XG4gICAgICAvLyBDYW5jZWwgdGhlIFByb21pc2UgYW5kIHJlbW92ZSBpdCBmcm9tIHRoZSBwYXJlbnQncyBjaGlsZCBsaXN0LlxuICAgICAgdGhpcy5wYXJlbnRfLmNhbmNlbENoaWxkXyh0aGlzLCBlcnIpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlc29sdmVfKENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQsIGVycik7XG4gICAgfVxuICB9XG59O1xuXG5cbi8qKlxuICogQ2FuY2VscyBhIGNoaWxkIFByb21pc2UgZnJvbSB0aGUgbGlzdCBvZiBjYWxsYmFjayBlbnRyaWVzLiBJZiB0aGUgUHJvbWlzZSBoYXNcbiAqIG5vdCBhbHJlYWR5IGJlZW4gcmVzb2x2ZWQsIHJlamVjdCBpdCB3aXRoIGEgY2FuY2VsIGVycm9yLiBJZiB0aGVyZSBhcmUgbm9cbiAqIG90aGVyIGNoaWxkcmVuIGluIHRoZSBsaXN0IG9mIGNhbGxiYWNrIGVudHJpZXMsIHByb3BhZ2F0ZSB0aGUgY2FuY2VsbGF0aW9uXG4gKiBieSBjYW5jZWxpbmcgdGhpcyBQcm9taXNlIGFzIHdlbGwuXG4gKlxuICogQHBhcmFtIHshQ2FuY2VsbGFibGVQcm9taXNlfSBjaGlsZFByb21pc2UgVGhlIFByb21pc2UgdG8gY2FuY2VsLlxuICogQHBhcmFtIHshRXJyb3J9IGVyciBUaGUgY2FuY2VsIGVycm9yIHRvIHVzZSBmb3IgcmVqZWN0aW5nIHRoZSBQcm9taXNlLlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5jYW5jZWxDaGlsZF8gPSBmdW5jdGlvbihjaGlsZFByb21pc2UsIGVycikge1xuICBpZiAoIXRoaXMuY2FsbGJhY2tFbnRyaWVzXykge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgY2hpbGRDb3VudCA9IDA7XG4gIHZhciBjaGlsZEluZGV4ID0gLTE7XG5cbiAgLy8gRmluZCB0aGUgY2FsbGJhY2sgZW50cnkgZm9yIHRoZSBjaGlsZFByb21pc2UsIGFuZCBjb3VudCB3aGV0aGVyIHRoZXJlIGFyZVxuICAvLyBhZGRpdGlvbmFsIGNoaWxkIFByb21pc2VzLlxuICBmb3IgKHZhciBpID0gMCwgZW50cnk7IChlbnRyeSA9IHRoaXMuY2FsbGJhY2tFbnRyaWVzX1tpXSk7IGkrKykge1xuICAgIHZhciBjaGlsZCA9IGVudHJ5LmNoaWxkO1xuICAgIGlmIChjaGlsZCkge1xuICAgICAgY2hpbGRDb3VudCsrO1xuICAgICAgaWYgKGNoaWxkID09PSBjaGlsZFByb21pc2UpIHtcbiAgICAgICAgY2hpbGRJbmRleCA9IGk7XG4gICAgICB9XG4gICAgICBpZiAoY2hpbGRJbmRleCA+PSAwICYmIGNoaWxkQ291bnQgPiAxKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIElmIHRoZSBjaGlsZCBQcm9taXNlIHdhcyB0aGUgb25seSBjaGlsZCwgY2FuY2VsIHRoaXMgUHJvbWlzZSBhcyB3ZWxsLlxuICAvLyBPdGhlcndpc2UsIHJlamVjdCBvbmx5IHRoZSBjaGlsZCBQcm9taXNlIHdpdGggdGhlIGNhbmNlbCBlcnJvci5cbiAgaWYgKGNoaWxkSW5kZXggPj0gMCkge1xuICAgIGlmICh0aGlzLnN0YXRlXyA9PT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5QRU5ESU5HICYmIGNoaWxkQ291bnQgPT09IDEpIHtcbiAgICAgIHRoaXMuY2FuY2VsSW50ZXJuYWxfKGVycik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBjYWxsYmFja0VudHJ5ID0gdGhpcy5jYWxsYmFja0VudHJpZXNfLnNwbGljZShjaGlsZEluZGV4LCAxKVswXTtcbiAgICAgIHRoaXMuZXhlY3V0ZUNhbGxiYWNrXyhcbiAgICAgICAgY2FsbGJhY2tFbnRyeSwgQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCwgZXJyKTtcbiAgICB9XG4gIH1cbn07XG5cblxuLyoqXG4gKiBBZGRzIGEgY2FsbGJhY2sgZW50cnkgdG8gdGhlIGN1cnJlbnQgUHJvbWlzZSwgYW5kIHNjaGVkdWxlcyBjYWxsYmFja1xuICogZXhlY3V0aW9uIGlmIHRoZSBQcm9taXNlIGhhcyBhbHJlYWR5IGJlZW4gcmVzb2x2ZWQuXG4gKlxuICogQHBhcmFtIHtDYW5jZWxsYWJsZVByb21pc2UuQ2FsbGJhY2tFbnRyeV99IGNhbGxiYWNrRW50cnkgUmVjb3JkIGNvbnRhaW5pbmdcbiAqICAgICB7QGNvZGUgb25GdWxmaWxsZWR9IGFuZCB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2tzIHRvIGV4ZWN1dGUgYWZ0ZXJcbiAqICAgICB0aGUgUHJvbWlzZSBpcyByZXNvbHZlZC5cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuYWRkQ2FsbGJhY2tFbnRyeV8gPSBmdW5jdGlvbihjYWxsYmFja0VudHJ5KSB7XG4gIGlmICgoIXRoaXMuY2FsbGJhY2tFbnRyaWVzXyB8fCAhdGhpcy5jYWxsYmFja0VudHJpZXNfLmxlbmd0aCkgJiZcbiAgICAodGhpcy5zdGF0ZV8gPT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uRlVMRklMTEVEIHx8XG4gICAgdGhpcy5zdGF0ZV8gPT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQpKSB7XG4gICAgdGhpcy5zY2hlZHVsZUNhbGxiYWNrc18oKTtcbiAgfVxuICBpZiAoIXRoaXMuY2FsbGJhY2tFbnRyaWVzXykge1xuICAgIHRoaXMuY2FsbGJhY2tFbnRyaWVzXyA9IFtdO1xuICB9XG4gIHRoaXMuY2FsbGJhY2tFbnRyaWVzXy5wdXNoKGNhbGxiYWNrRW50cnkpO1xufTtcblxuXG4vKipcbiAqIENyZWF0ZXMgYSBjaGlsZCBQcm9taXNlIGFuZCBhZGRzIGl0IHRvIHRoZSBjYWxsYmFjayBlbnRyeSBsaXN0LiBUaGUgcmVzdWx0IG9mXG4gKiB0aGUgY2hpbGQgUHJvbWlzZSBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBzdGF0ZSBvZiB0aGUgcGFyZW50IFByb21pc2UgYW5kIHRoZVxuICogcmVzdWx0IG9mIHRoZSB7QGNvZGUgb25GdWxmaWxsZWR9IG9yIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFja3MgYXNcbiAqIHNwZWNpZmllZCBpbiB0aGUgUHJvbWlzZSByZXNvbHV0aW9uIHByb2NlZHVyZS5cbiAqXG4gKiBAc2VlIGh0dHA6Ly9wcm9taXNlc2FwbHVzLmNvbS8jdGhlX19tZXRob2RcbiAqXG4gKiBAcGFyYW0gez9mdW5jdGlvbih0aGlzOlRISVMsIFRZUEUpOlxuICogICAgICAgICAgKFJFU1VMVHxDYW5jZWxsYWJsZVByb21pc2UuPFJFU1VMVD58VGhlbmFibGUpfSBvbkZ1bGZpbGxlZCBBIGNhbGxiYWNrIHRoYXRcbiAqICAgICB3aWxsIGJlIGludm9rZWQgaWYgdGhlIFByb21pc2UgaXMgZnVsbGZpbGxlZCwgb3IgbnVsbC5cbiAqIEBwYXJhbSB7P2Z1bmN0aW9uKHRoaXM6VEhJUywgKik6ICp9IG9uUmVqZWN0ZWQgQSBjYWxsYmFjayB0aGF0IHdpbGwgYmVcbiAqICAgICBpbnZva2VkIGlmIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLCBvciBudWxsLlxuICogQHBhcmFtIHtUSElTPX0gb3B0X2NvbnRleHQgQW4gb3B0aW9uYWwgZXhlY3V0aW9uIGNvbnRleHQgZm9yIHRoZSBjYWxsYmFja3MuXG4gKiAgICAgaW4gdGhlIGRlZmF1bHQgY2FsbGluZyBjb250ZXh0LlxuICogQHJldHVybiB7IUNhbmNlbGxhYmxlUHJvbWlzZX0gVGhlIGNoaWxkIFByb21pc2UuXG4gKiBAdGVtcGxhdGUgUkVTVUxULFRISVNcbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUuYWRkQ2hpbGRQcm9taXNlXyA9IGZ1bmN0aW9uKFxub25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQsIG9wdF9jb250ZXh0KSB7XG5cbiAgdmFyIGNhbGxiYWNrRW50cnkgPSB7XG4gICAgY2hpbGQ6IG51bGwsXG4gICAgb25GdWxmaWxsZWQ6IG51bGwsXG4gICAgb25SZWplY3RlZDogbnVsbFxuICB9O1xuXG4gIGNhbGxiYWNrRW50cnkuY2hpbGQgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgIC8vIEludm9rZSBvbkZ1bGZpbGxlZCwgb3IgcmVzb2x2ZSB3aXRoIHRoZSBwYXJlbnQncyB2YWx1ZSBpZiBhYnNlbnQuXG4gICAgY2FsbGJhY2tFbnRyeS5vbkZ1bGZpbGxlZCA9IG9uRnVsZmlsbGVkID8gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBvbkZ1bGZpbGxlZC5jYWxsKG9wdF9jb250ZXh0LCB2YWx1ZSk7XG4gICAgICAgIHJlc29sdmUocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgIH1cbiAgICB9IDogcmVzb2x2ZTtcblxuICAgIC8vIEludm9rZSBvblJlamVjdGVkLCBvciByZWplY3Qgd2l0aCB0aGUgcGFyZW50J3MgcmVhc29uIGlmIGFic2VudC5cbiAgICBjYWxsYmFja0VudHJ5Lm9uUmVqZWN0ZWQgPSBvblJlamVjdGVkID8gZnVuY3Rpb24ocmVhc29uKSB7XG4gICAgICB0cnkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gb25SZWplY3RlZC5jYWxsKG9wdF9jb250ZXh0LCByZWFzb24pO1xuICAgICAgICBpZiAoIWlzRGVmKHJlc3VsdCkgJiYgcmVhc29uLklTX0NBTkNFTExBVElPTl9FUlJPUikge1xuICAgICAgICAgIC8vIFByb3BhZ2F0ZSBjYW5jZWxsYXRpb24gdG8gY2hpbGRyZW4gaWYgbm8gb3RoZXIgcmVzdWx0IGlzIHJldHVybmVkLlxuICAgICAgICAgIHJlamVjdChyZWFzb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUocmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgfVxuICAgIH0gOiByZWplY3Q7XG4gIH0pO1xuXG4gIGNhbGxiYWNrRW50cnkuY2hpbGQucGFyZW50XyA9IHRoaXM7XG4gIHRoaXMuYWRkQ2FsbGJhY2tFbnRyeV8oXG4gICAgLyoqIEB0eXBlIHtDYW5jZWxsYWJsZVByb21pc2UuQ2FsbGJhY2tFbnRyeV99ICovIChjYWxsYmFja0VudHJ5KSk7XG4gIHJldHVybiBjYWxsYmFja0VudHJ5LmNoaWxkO1xufTtcblxuXG4vKipcbiAqIFVuYmxvY2tzIHRoZSBQcm9taXNlIGFuZCBmdWxmaWxscyBpdCB3aXRoIHRoZSBnaXZlbiB2YWx1ZS5cbiAqXG4gKiBAcGFyYW0ge1RZUEV9IHZhbHVlXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnVuYmxvY2tBbmRGdWxmaWxsXyA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIGlmICh0aGlzLnN0YXRlXyAhPT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5CTE9DS0VEKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDYW5jZWxsYWJsZVByb21pc2UgaXMgbm90IGJsb2NrZWQuJyk7XG4gIH1cbiAgdGhpcy5zdGF0ZV8gPSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkc7XG4gIHRoaXMucmVzb2x2ZV8oQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5GVUxGSUxMRUQsIHZhbHVlKTtcbn07XG5cblxuLyoqXG4gKiBVbmJsb2NrcyB0aGUgUHJvbWlzZSBhbmQgcmVqZWN0cyBpdCB3aXRoIHRoZSBnaXZlbiByZWplY3Rpb24gcmVhc29uLlxuICpcbiAqIEBwYXJhbSB7Kn0gcmVhc29uXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnVuYmxvY2tBbmRSZWplY3RfID0gZnVuY3Rpb24ocmVhc29uKSB7XG4gIGlmICh0aGlzLnN0YXRlXyAhPT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5CTE9DS0VEKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDYW5jZWxsYWJsZVByb21pc2UgaXMgbm90IGJsb2NrZWQuJyk7XG4gIH1cbiAgdGhpcy5zdGF0ZV8gPSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlBFTkRJTkc7XG4gIHRoaXMucmVzb2x2ZV8oQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5SRUpFQ1RFRCwgcmVhc29uKTtcbn07XG5cblxuLyoqXG4gKiBBdHRlbXB0cyB0byByZXNvbHZlIGEgUHJvbWlzZSB3aXRoIGEgZ2l2ZW4gcmVzb2x1dGlvbiBzdGF0ZSBhbmQgdmFsdWUuIFRoaXNcbiAqIGlzIGEgbm8tb3AgaWYgdGhlIGdpdmVuIFByb21pc2UgaGFzIGFscmVhZHkgYmVlbiByZXNvbHZlZC5cbiAqXG4gKiBJZiB0aGUgZ2l2ZW4gcmVzdWx0IGlzIGEgVGhlbmFibGUgKHN1Y2ggYXMgYW5vdGhlciBQcm9taXNlKSwgdGhlIFByb21pc2Ugd2lsbFxuICogYmUgcmVzb2x2ZWQgd2l0aCB0aGUgc2FtZSBzdGF0ZSBhbmQgcmVzdWx0IGFzIHRoZSBUaGVuYWJsZSBvbmNlIGl0IGlzIGl0c2VsZlxuICogcmVzb2x2ZWQuXG4gKlxuICogSWYgdGhlIGdpdmVuIHJlc3VsdCBpcyBub3QgYSBUaGVuYWJsZSwgdGhlIFByb21pc2Ugd2lsbCBiZSBmdWxmaWxsZWQgb3JcbiAqIHJlamVjdGVkIHdpdGggdGhhdCByZXN1bHQgYmFzZWQgb24gdGhlIGdpdmVuIHN0YXRlLlxuICpcbiAqIEBzZWUgaHR0cDovL3Byb21pc2VzYXBsdXMuY29tLyN0aGVfcHJvbWlzZV9yZXNvbHV0aW9uX3Byb2NlZHVyZVxuICpcbiAqIEBwYXJhbSB7Q2FuY2VsbGFibGVQcm9taXNlLlN0YXRlX30gc3RhdGVcbiAqIEBwYXJhbSB7Kn0geCBUaGUgcmVzdWx0IHRvIGFwcGx5IHRvIHRoZSBQcm9taXNlLlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5yZXNvbHZlXyA9IGZ1bmN0aW9uKHN0YXRlLCB4KSB7XG4gIGlmICh0aGlzLnN0YXRlXyAhPT0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5QRU5ESU5HKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKHRoaXMgPT09IHgpIHtcbiAgICBzdGF0ZSA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQ7XG4gICAgeCA9IG5ldyBUeXBlRXJyb3IoJ0NhbmNlbGxhYmxlUHJvbWlzZSBjYW5ub3QgcmVzb2x2ZSB0byBpdHNlbGYnKTtcblxuICB9IGVsc2UgaWYgKFRoZW5hYmxlLmlzSW1wbGVtZW50ZWRCeSh4KSkge1xuICAgIHggPSAvKiogQHR5cGUgeyFUaGVuYWJsZX0gKi8gKHgpO1xuICAgIHRoaXMuc3RhdGVfID0gQ2FuY2VsbGFibGVQcm9taXNlLlN0YXRlXy5CTE9DS0VEO1xuICAgIHgudGhlbih0aGlzLnVuYmxvY2tBbmRGdWxmaWxsXywgdGhpcy51bmJsb2NrQW5kUmVqZWN0XywgdGhpcyk7XG4gICAgcmV0dXJuO1xuXG4gIH0gZWxzZSBpZiAoaXNPYmplY3QoeCkpIHtcbiAgICB0cnkge1xuICAgICAgdmFyIHRoZW4gPSB4LnRoZW47XG4gICAgICBpZiAoaXNGdW5jdGlvbih0aGVuKSkge1xuICAgICAgICB0aGlzLnRyeVRoZW5fKHgsIHRoZW4pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgc3RhdGUgPSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLlJFSkVDVEVEO1xuICAgICAgeCA9IGU7XG4gICAgfVxuICB9XG5cbiAgdGhpcy5yZXN1bHRfID0geDtcbiAgdGhpcy5zdGF0ZV8gPSBzdGF0ZTtcbiAgdGhpcy5zY2hlZHVsZUNhbGxiYWNrc18oKTtcblxuICBpZiAoc3RhdGUgPT09IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uUkVKRUNURUQgJiYgIXguSVNfQ0FOQ0VMTEFUSU9OX0VSUk9SKSB7XG4gICAgQ2FuY2VsbGFibGVQcm9taXNlLmFkZFVuaGFuZGxlZFJlamVjdGlvbl8odGhpcywgeCk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBBdHRlbXB0cyB0byBjYWxsIHRoZSB7QGNvZGUgdGhlbn0gbWV0aG9kIG9uIGFuIG9iamVjdCBpbiB0aGUgaG9wZXMgdGhhdCBpdCBpc1xuICogYSBQcm9taXNlLWNvbXBhdGlibGUgaW5zdGFuY2UuIFRoaXMgYWxsb3dzIGludGVyb3BlcmF0aW9uIGJldHdlZW4gZGlmZmVyZW50XG4gKiBQcm9taXNlIGltcGxlbWVudGF0aW9ucywgaG93ZXZlciBhIG5vbi1jb21wbGlhbnQgb2JqZWN0IG1heSBjYXVzZSBhIFByb21pc2VcbiAqIHRvIGhhbmcgaW5kZWZpbml0ZWx5LiBJZiB0aGUge0Bjb2RlIHRoZW59IG1ldGhvZCB0aHJvd3MgYW4gZXhjZXB0aW9uLCB0aGVcbiAqIGRlcGVuZGVudCBQcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWQgd2l0aCB0aGUgdGhyb3duIHZhbHVlLlxuICpcbiAqIEBzZWUgaHR0cDovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC03MFxuICpcbiAqIEBwYXJhbSB7VGhlbmFibGV9IHRoZW5hYmxlIEFuIG9iamVjdCB3aXRoIGEge0Bjb2RlIHRoZW59IG1ldGhvZCB0aGF0IG1heSBiZVxuICogICAgIGNvbXBhdGlibGUgd2l0aCB0aGUgUHJvbWlzZS9BKyBzcGVjaWZpY2F0aW9uLlxuICogQHBhcmFtIHshRnVuY3Rpb259IHRoZW4gVGhlIHtAY29kZSB0aGVufSBtZXRob2Qgb2YgdGhlIFRoZW5hYmxlIG9iamVjdC5cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudHJ5VGhlbl8gPSBmdW5jdGlvbih0aGVuYWJsZSwgdGhlbikge1xuICB0aGlzLnN0YXRlXyA9IENhbmNlbGxhYmxlUHJvbWlzZS5TdGF0ZV8uQkxPQ0tFRDtcbiAgdmFyIHByb21pc2UgPSB0aGlzO1xuICB2YXIgY2FsbGVkID0gZmFsc2U7XG5cbiAgdmFyIHJlc29sdmUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIGlmICghY2FsbGVkKSB7XG4gICAgICBjYWxsZWQgPSB0cnVlO1xuICAgICAgcHJvbWlzZS51bmJsb2NrQW5kRnVsZmlsbF8odmFsdWUpO1xuICAgIH1cbiAgfTtcblxuICB2YXIgcmVqZWN0ID0gZnVuY3Rpb24ocmVhc29uKSB7XG4gICAgaWYgKCFjYWxsZWQpIHtcbiAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgICBwcm9taXNlLnVuYmxvY2tBbmRSZWplY3RfKHJlYXNvbik7XG4gICAgfVxuICB9O1xuXG4gIHRyeSB7XG4gICAgdGhlbi5jYWxsKHRoZW5hYmxlLCByZXNvbHZlLCByZWplY3QpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmVqZWN0KGUpO1xuICB9XG59O1xuXG5cbi8qKlxuICogRXhlY3V0ZXMgdGhlIHBlbmRpbmcgY2FsbGJhY2tzIG9mIGEgcmVzb2x2ZWQgUHJvbWlzZSBhZnRlciBhIHRpbWVvdXQuXG4gKlxuICogU2VjdGlvbiAyLjIuNCBvZiB0aGUgUHJvbWlzZXMvQSsgc3BlY2lmaWNhdGlvbiByZXF1aXJlcyB0aGF0IFByb21pc2VcbiAqIGNhbGxiYWNrcyBtdXN0IG9ubHkgYmUgaW52b2tlZCBmcm9tIGEgY2FsbCBzdGFjayB0aGF0IG9ubHkgY29udGFpbnMgUHJvbWlzZVxuICogaW1wbGVtZW50YXRpb24gY29kZSwgd2hpY2ggd2UgYWNjb21wbGlzaCBieSBpbnZva2luZyBjYWxsYmFjayBleGVjdXRpb24gYWZ0ZXJcbiAqIGEgdGltZW91dC4gSWYge0Bjb2RlIHN0YXJ0RXhlY3V0aW9uX30gaXMgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGZvciB0aGUgc2FtZVxuICogUHJvbWlzZSwgdGhlIGNhbGxiYWNrIGNoYWluIHdpbGwgYmUgZXZhbHVhdGVkIG9ubHkgb25jZS4gQWRkaXRpb25hbCBjYWxsYmFja3NcbiAqIG1heSBiZSBhZGRlZCBkdXJpbmcgdGhlIGV2YWx1YXRpb24gcGhhc2UsIGFuZCB3aWxsIGJlIGV4ZWN1dGVkIGluIHRoZSBzYW1lXG4gKiBldmVudCBsb29wLlxuICpcbiAqIEFsbCBQcm9taXNlcyBhZGRlZCB0byB0aGUgd2FpdGluZyBsaXN0IGR1cmluZyB0aGUgc2FtZSBicm93c2VyIGV2ZW50IGxvb3BcbiAqIHdpbGwgYmUgZXhlY3V0ZWQgaW4gb25lIGJhdGNoIHRvIGF2b2lkIHVzaW5nIGEgc2VwYXJhdGUgdGltZW91dCBwZXIgUHJvbWlzZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnNjaGVkdWxlQ2FsbGJhY2tzXyA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMuZXhlY3V0aW5nXykge1xuICAgIHRoaXMuZXhlY3V0aW5nXyA9IHRydWU7XG4gICAgYXN5bmMucnVuKHRoaXMuZXhlY3V0ZUNhbGxiYWNrc18sIHRoaXMpO1xuICB9XG59O1xuXG5cbi8qKlxuICogRXhlY3V0ZXMgYWxsIHBlbmRpbmcgY2FsbGJhY2tzIGZvciB0aGlzIFByb21pc2UuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5leGVjdXRlQ2FsbGJhY2tzXyA9IGZ1bmN0aW9uKCkge1xuICB3aGlsZSAodGhpcy5jYWxsYmFja0VudHJpZXNfICYmIHRoaXMuY2FsbGJhY2tFbnRyaWVzXy5sZW5ndGgpIHtcbiAgICB2YXIgZW50cmllcyA9IHRoaXMuY2FsbGJhY2tFbnRyaWVzXztcbiAgICB0aGlzLmNhbGxiYWNrRW50cmllc18gPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5leGVjdXRlQ2FsbGJhY2tfKGVudHJpZXNbaV0sIHRoaXMuc3RhdGVfLCB0aGlzLnJlc3VsdF8pO1xuICAgIH1cbiAgfVxuICB0aGlzLmV4ZWN1dGluZ18gPSBmYWxzZTtcbn07XG5cblxuLyoqXG4gKiBFeGVjdXRlcyBhIHBlbmRpbmcgY2FsbGJhY2sgZm9yIHRoaXMgUHJvbWlzZS4gSW52b2tlcyBhbiB7QGNvZGUgb25GdWxmaWxsZWR9XG4gKiBvciB7QGNvZGUgb25SZWplY3RlZH0gY2FsbGJhY2sgYmFzZWQgb24gdGhlIHJlc29sdmVkIHN0YXRlIG9mIHRoZSBQcm9taXNlLlxuICpcbiAqIEBwYXJhbSB7IUNhbmNlbGxhYmxlUHJvbWlzZS5DYWxsYmFja0VudHJ5X30gY2FsbGJhY2tFbnRyeSBBbiBlbnRyeSBjb250YWluaW5nIHRoZVxuICogICAgIG9uRnVsZmlsbGVkIGFuZC9vciBvblJlamVjdGVkIGNhbGxiYWNrcyBmb3IgdGhpcyBzdGVwLlxuICogQHBhcmFtIHtDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVffSBzdGF0ZSBUaGUgcmVzb2x1dGlvbiBzdGF0dXMgb2YgdGhlIFByb21pc2UsXG4gKiAgICAgZWl0aGVyIEZVTEZJTExFRCBvciBSRUpFQ1RFRC5cbiAqIEBwYXJhbSB7Kn0gcmVzdWx0IFRoZSByZXNvbHZlZCByZXN1bHQgb2YgdGhlIFByb21pc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5DYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmV4ZWN1dGVDYWxsYmFja18gPSBmdW5jdGlvbihcbmNhbGxiYWNrRW50cnksIHN0YXRlLCByZXN1bHQpIHtcbiAgaWYgKHN0YXRlID09PSBDYW5jZWxsYWJsZVByb21pc2UuU3RhdGVfLkZVTEZJTExFRCkge1xuICAgIGNhbGxiYWNrRW50cnkub25GdWxmaWxsZWQocmVzdWx0KTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLnJlbW92ZVVuaGFuZGxlZFJlamVjdGlvbl8oKTtcbiAgICBjYWxsYmFja0VudHJ5Lm9uUmVqZWN0ZWQocmVzdWx0KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIE1hcmtzIHRoaXMgcmVqZWN0ZWQgUHJvbWlzZSBhcyBoYXZpbmcgYmVpbmcgaGFuZGxlZC4gQWxzbyBtYXJrcyBhbnkgcGFyZW50XG4gKiBQcm9taXNlcyBpbiB0aGUgcmVqZWN0ZWQgc3RhdGUgYXMgaGFuZGxlZC4gVGhlIHJlamVjdGlvbiBoYW5kbGVyIHdpbGwgbm9cbiAqIGxvbmdlciBiZSBpbnZva2VkIGZvciB0aGlzIFByb21pc2UgKGlmIGl0IGhhcyBub3QgYmVlbiBjYWxsZWQgYWxyZWFkeSkuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5yZW1vdmVVbmhhbmRsZWRSZWplY3Rpb25fID0gZnVuY3Rpb24oKSB7XG4gIHZhciBwO1xuICBpZiAoQ2FuY2VsbGFibGVQcm9taXNlLlVOSEFORExFRF9SRUpFQ1RJT05fREVMQVkgPiAwKSB7XG4gICAgZm9yIChwID0gdGhpczsgcCAmJiBwLnVuaGFuZGxlZFJlamVjdGlvbklkXzsgcCA9IHAucGFyZW50Xykge1xuICAgICAgY2xlYXJUaW1lb3V0KHAudW5oYW5kbGVkUmVqZWN0aW9uSWRfKTtcbiAgICAgIHAudW5oYW5kbGVkUmVqZWN0aW9uSWRfID0gMDtcbiAgICB9XG4gIH0gZWxzZSBpZiAoQ2FuY2VsbGFibGVQcm9taXNlLlVOSEFORExFRF9SRUpFQ1RJT05fREVMQVkgPT09IDApIHtcbiAgICBmb3IgKHAgPSB0aGlzOyBwICYmIHAuaGFkVW5oYW5kbGVkUmVqZWN0aW9uXzsgcCA9IHAucGFyZW50Xykge1xuICAgICAgcC5oYWRVbmhhbmRsZWRSZWplY3Rpb25fID0gZmFsc2U7XG4gICAgfVxuICB9XG59O1xuXG5cbi8qKlxuICogTWFya3MgdGhpcyByZWplY3RlZCBQcm9taXNlIGFzIHVuaGFuZGxlZC4gSWYgbm8ge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrXG4gKiBpcyBjYWxsZWQgZm9yIHRoaXMgUHJvbWlzZSBiZWZvcmUgdGhlIHtAY29kZSBVTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZfVxuICogZXhwaXJlcywgdGhlIHJlYXNvbiB3aWxsIGJlIHBhc3NlZCB0byB0aGUgdW5oYW5kbGVkIHJlamVjdGlvbiBoYW5kbGVyLiBUaGVcbiAqIGhhbmRsZXIgdHlwaWNhbGx5IHJldGhyb3dzIHRoZSByZWplY3Rpb24gcmVhc29uIHNvIHRoYXQgaXQgYmVjb21lcyB2aXNpYmxlIGluXG4gKiB0aGUgZGV2ZWxvcGVyIGNvbnNvbGUuXG4gKlxuICogQHBhcmFtIHshQ2FuY2VsbGFibGVQcm9taXNlfSBwcm9taXNlIFRoZSByZWplY3RlZCBQcm9taXNlLlxuICogQHBhcmFtIHsqfSByZWFzb24gVGhlIFByb21pc2UgcmVqZWN0aW9uIHJlYXNvbi5cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5hZGRVbmhhbmRsZWRSZWplY3Rpb25fID0gZnVuY3Rpb24ocHJvbWlzZSwgcmVhc29uKSB7XG4gIGlmIChDYW5jZWxsYWJsZVByb21pc2UuVU5IQU5ETEVEX1JFSkVDVElPTl9ERUxBWSA+IDApIHtcbiAgICBwcm9taXNlLnVuaGFuZGxlZFJlamVjdGlvbklkXyA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICBDYW5jZWxsYWJsZVByb21pc2UuaGFuZGxlUmVqZWN0aW9uXy5jYWxsKG51bGwsIHJlYXNvbik7XG4gICAgfSwgQ2FuY2VsbGFibGVQcm9taXNlLlVOSEFORExFRF9SRUpFQ1RJT05fREVMQVkpO1xuXG4gIH0gZWxzZSBpZiAoQ2FuY2VsbGFibGVQcm9taXNlLlVOSEFORExFRF9SRUpFQ1RJT05fREVMQVkgPT09IDApIHtcbiAgICBwcm9taXNlLmhhZFVuaGFuZGxlZFJlamVjdGlvbl8gPSB0cnVlO1xuICAgIGFzeW5jLnJ1bihmdW5jdGlvbigpIHtcbiAgICAgIGlmIChwcm9taXNlLmhhZFVuaGFuZGxlZFJlamVjdGlvbl8pIHtcbiAgICAgICAgQ2FuY2VsbGFibGVQcm9taXNlLmhhbmRsZVJlamVjdGlvbl8uY2FsbChudWxsLCByZWFzb24pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59O1xuXG5cbi8qKlxuICogQSBtZXRob2QgdGhhdCBpcyBpbnZva2VkIHdpdGggdGhlIHJlamVjdGlvbiByZWFzb25zIGZvciBQcm9taXNlcyB0aGF0IGFyZVxuICogcmVqZWN0ZWQgYnV0IGhhdmUgbm8ge0Bjb2RlIG9uUmVqZWN0ZWR9IGNhbGxiYWNrcyByZWdpc3RlcmVkIHlldC5cbiAqIEB0eXBlIHtmdW5jdGlvbigqKX1cbiAqIEBwcml2YXRlXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5oYW5kbGVSZWplY3Rpb25fID0gYXN5bmMudGhyb3dFeGNlcHRpb247XG5cblxuLyoqXG4gKiBTZXRzIGEgaGFuZGxlciB0aGF0IHdpbGwgYmUgY2FsbGVkIHdpdGggcmVhc29ucyBmcm9tIHVuaGFuZGxlZCByZWplY3RlZFxuICogUHJvbWlzZXMuIElmIHRoZSByZWplY3RlZCBQcm9taXNlIChvciBvbmUgb2YgaXRzIGRlc2NlbmRhbnRzKSBoYXMgYW5cbiAqIHtAY29kZSBvblJlamVjdGVkfSBjYWxsYmFjayByZWdpc3RlcmVkLCB0aGUgcmVqZWN0aW9uIHdpbGwgYmUgY29uc2lkZXJlZFxuICogaGFuZGxlZCwgYW5kIHRoZSByZWplY3Rpb24gaGFuZGxlciB3aWxsIG5vdCBiZSBjYWxsZWQuXG4gKlxuICogQnkgZGVmYXVsdCwgdW5oYW5kbGVkIHJlamVjdGlvbnMgYXJlIHJldGhyb3duIHNvIHRoYXQgdGhlIGVycm9yIG1heSBiZVxuICogY2FwdHVyZWQgYnkgdGhlIGRldmVsb3BlciBjb25zb2xlIG9yIGEge0Bjb2RlIHdpbmRvdy5vbmVycm9yfSBoYW5kbGVyLlxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb24oKil9IGhhbmRsZXIgQSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgY2FsbGVkIHdpdGggcmVhc29ucyBmcm9tXG4gKiAgICAgcmVqZWN0ZWQgUHJvbWlzZXMuIERlZmF1bHRzIHRvIHtAY29kZSBhc3luYy50aHJvd0V4Y2VwdGlvbn0uXG4gKi9cbkNhbmNlbGxhYmxlUHJvbWlzZS5zZXRVbmhhbmRsZWRSZWplY3Rpb25IYW5kbGVyID0gZnVuY3Rpb24oaGFuZGxlcikge1xuICBDYW5jZWxsYWJsZVByb21pc2UuaGFuZGxlUmVqZWN0aW9uXyA9IGhhbmRsZXI7XG59O1xuXG5cblxuLyoqXG4gKiBFcnJvciB1c2VkIGFzIGEgcmVqZWN0aW9uIHJlYXNvbiBmb3IgY2FuY2VsZWQgUHJvbWlzZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmc9fSBvcHRfbWVzc2FnZVxuICogQGNvbnN0cnVjdG9yXG4gKiBAZXh0ZW5kcyB7RXJyb3J9XG4gKiBAZmluYWxcbiAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLkNhbmNlbGxhdGlvbkVycm9yID0gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG9wdF9tZXNzYWdlKSB7XG4gICAgIHN1cGVyKG9wdF9tZXNzYWdlKTtcblxuICAgICBpZiAob3B0X21lc3NhZ2UpIHtcbiAgICAgICB0aGlzLm1lc3NhZ2UgPSBvcHRfbWVzc2FnZTtcbiAgICAgfVxuICAgfVxufTtcblxuLyoqIEBvdmVycmlkZSAqL1xuQ2FuY2VsbGFibGVQcm9taXNlLkNhbmNlbGxhdGlvbkVycm9yLnByb3RvdHlwZS5uYW1lID0gJ2NhbmNlbCc7XG5cbmV4cG9ydCB7Q2FuY2VsbGFibGVQcm9taXNlfTtcbmV4cG9ydCBkZWZhdWx0IENhbmNlbGxhYmxlUHJvbWlzZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gICogRGVib3VuY2VzIGZ1bmN0aW9uIGV4ZWN1dGlvbi5cbiAgKiBAcGFyYW0geyFmdW5jdGlvbigpfSBmblxuICAqIEBwYXJhbSB7bnVtYmVyfSBkZWxheVxuICAqIEByZXR1cm4geyFmdW5jdGlvbigpfVxuICAqL1xuZnVuY3Rpb24gZGVib3VuY2UoZm4sIGRlbGF5KSB7XG5cdHJldHVybiBmdW5jdGlvbiBkZWJvdW5jZWQoKSB7XG5cdFx0dmFyIGFyZ3MgPSBhcmd1bWVudHM7XG5cdFx0Y2FuY2VsRGVib3VuY2UoZGVib3VuY2VkKTtcblx0XHRkZWJvdW5jZWQuaWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdFx0Zm4uYXBwbHkobnVsbCwgYXJncyk7XG5cdFx0fSwgZGVsYXkpO1xuXHR9O1xufVxuXG4vKipcbiAqIENhbmNlbHMgdGhlIHNjaGVkdWxlZCBkZWJvdW5jZWQgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIGNhbmNlbERlYm91bmNlKGRlYm91bmNlZCkge1xuXHRjbGVhclRpbWVvdXQoZGVib3VuY2VkLmlkKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZGVib3VuY2U7XG5leHBvcnQgeyBjYW5jZWxEZWJvdW5jZSwgZGVib3VuY2UgfTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IGNvcmUgZnJvbSAnbWV0YWwnO1xuXG5jb25zdCBSRUdFWCA9IC8oW1xcL10pPyg/Oig/OlxcOihcXHcrKSg/OlxcKCgoPzpcXFxcLnxbXlxcXFwoKV0pKilcXCkpP3xcXCgoKD86XFxcXC58W15cXFxcKCldKSspXFwpKShbKyo/XSk/KS9nO1xuXG4vKipcbiAqIENvbnZlcnRzIHRoZSBnaXZlbiBhcnJheSBvZiByZWdleCBtYXRjaGVzIHRvIGEgbW9yZSByZWFkYWJsZSBvYmplY3QgZm9ybWF0LlxuICogQHBhcmFtIHshQXJyYXk8c3RyaW5nPn0gbWF0Y2hlc1xuICogQHJldHVybiB7IU9iamVjdH1cbiAqL1xuZnVuY3Rpb24gY29udmVydE1hdGNoZXNUb09iaihtYXRjaGVzKSB7XG5cdHJldHVybiB7XG5cdFx0bWF0Y2g6IG1hdGNoZXNbMF0sXG5cdFx0cHJlZml4OiBtYXRjaGVzWzFdLFxuXHRcdG5hbWU6IG1hdGNoZXNbMl0sXG5cdFx0cGFyYW1QYXR0ZXJuOiBtYXRjaGVzWzNdLFxuXHRcdHVubmFtZWRQYXR0ZXJuOiBtYXRjaGVzWzRdLFxuXHRcdG1vZGlmaWVyOiBtYXRjaGVzWzVdXG5cdH07XG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIHRva2VucyBwYXJzZWQgZnJvbSBhIHJvdXRlIGZvcm1hdCBzdHJpbmcgdG8gYSByZWdleC5cbiAqIEBwYXJhbSB7IUFycmF5PHN0cmluZ3whT2JqZWN0Pn0gdG9rZW5zXG4gKiBAcmV0dXJuIHshUmVnRXhwfVxuICovXG5mdW5jdGlvbiBjb252ZXJ0VG9rZW5zVG9SZWdleCh0b2tlbnMpIHtcblx0bGV0IHJlZ2V4ID0gJyc7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKGNvcmUuaXNTdHJpbmcodG9rZW5zW2ldKSkge1xuXHRcdFx0cmVnZXggKz0gZXNjYXBlKHRva2Vuc1tpXSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGxldCBjYXB0dXJlID0gZW5jbG9zZU5vbkNhcHR1cmluZ0dyb3VwKHRva2Vuc1tpXS5wYXR0ZXJuKTtcblx0XHRcdGlmICh0b2tlbnNbaV0ucmVwZWF0KSB7XG5cdFx0XHRcdGNhcHR1cmUgKz0gZW5jbG9zZU5vbkNhcHR1cmluZ0dyb3VwKCdcXFxcLycgKyBjYXB0dXJlKSArICcqJztcblx0XHRcdH1cblx0XHRcdGNhcHR1cmUgPSBlc2NhcGUodG9rZW5zW2ldLnByZWZpeCkgKyBgKCR7Y2FwdHVyZX0pYDtcblx0XHRcdGlmICh0b2tlbnNbaV0ub3B0aW9uYWwpIHtcblx0XHRcdFx0aWYgKCF0b2tlbnNbaV0ucGFydGlhbCkge1xuXHRcdFx0XHRcdGNhcHR1cmUgPSBlbmNsb3NlTm9uQ2FwdHVyaW5nR3JvdXAoY2FwdHVyZSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Y2FwdHVyZSArPSAnPyc7XG5cdFx0XHR9XG5cdFx0XHRyZWdleCArPSBjYXB0dXJlO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gbmV3IFJlZ0V4cCgnXicgKyBtYWtlVHJhaWxpbmdTbGFzaE9wdGlvbmFsKHJlZ2V4KSArICckJyk7XG59XG5cbi8qKlxuICogRW5jbG9zZXMgdGhlIGdpdmVuIHJlZ2V4IHBhdHRlcm4gaW50byBhIG5vbiBjYXB0dXJpbmcgZ3JvdXAuXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0dGVyblxuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiBlbmNsb3NlTm9uQ2FwdHVyaW5nR3JvdXAocGF0dGVybikge1xuXHRyZXR1cm4gYCg/OiR7cGF0dGVybn0pYDtcbn1cblxuLyoqXG4gKiBFc2NhcGVzIHRoZSBnaXZlbiBzdHJpbmcgdG8gc2hvdyB1cCBpbiB0aGUgcGF0aCByZWdleC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gZXNjYXBlKHN0cikge1xuXHRyZXR1cm4gc3RyLnJlcGxhY2UoLyhbLisqPz1eIToke30oKVtcXF18XFwvXFxcXF0pL2csICdcXFxcJDEnKTtcbn1cblxuLyoqXG4gKiBNYWtlcyB0cmFpbGluZyBzbGFzaCBvcHRpb25hbCBvbiBwYXRocy5cbiAqIEBwYXJhbSB7c3RyaW5nfSByZWdleFxuICogQHBhcmFtIHtzdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIG1ha2VUcmFpbGluZ1NsYXNoT3B0aW9uYWwocmVnZXgpIHtcblx0aWYgKC9cXC8kLy50ZXN0KHJlZ2V4KSkge1xuXHRcdHJlZ2V4ICs9ICc/Jztcblx0fSBlbHNlIHtcblx0XHRyZWdleCArPSAnXFxcXC8/Jztcblx0fVxuXHRyZXR1cm4gcmVnZXg7XG59XG5cbi8qKlxuICogUGFyc2VzIHRoZSBnaXZlbiByb3V0ZSBmb3JtYXQgc3RyaW5nIGludG8gdG9rZW5zIHJlcHJlc2VudGluZyBpdHMgY29udGVudHMuXG4gKiBAcGFyYW0geyFBcnJheXxzdHJpbmd9IHJvdXRlT3JUb2tlbnMgRWl0aGVyIGEgcm91dGUgZm9ybWF0IHN0cmluZyBvciB0b2tlbnNcbiAqICAgICBwcmV2aW91c2x5IHBhcnNlZCB2aWEgdGhlIGBwYXJzZWAgZnVuY3Rpb24uXG4gKiBAcmV0dXJuIHshQXJyYXk8c3RyaW5nfCFPYmplY3Q+fSBBbiBhcnJheSBvZiB0b2tlbnMgdGhhdCBjYW4gYmUgZWl0aGVyIHBsYWluXG4gKiAgICAgc3RyaW5ncyAocGFydCBvZiB0aGUgcm91dGUpIG9yIG9iamVjdHMgY29udGFpbmluZyBpbmZvcm1hdGlvbnMgb24gcGFyYW1zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2Uocm91dGVPclRva2Vucykge1xuXHRpZiAoIWNvcmUuaXNTdHJpbmcocm91dGVPclRva2VucykpIHtcblx0XHRyZXR1cm4gcm91dGVPclRva2Vucztcblx0fVxuXG5cdGNvbnN0IHJvdXRlID0gcm91dGVPclRva2Vucztcblx0bGV0IHVubmFtZWRDb3VudCA9IDA7XG5cdGNvbnN0IHRva2VucyA9IFtdO1xuXHRsZXQgY3VyclBhdGggPSAnJztcblx0bGV0IGluZGV4ID0gMDtcblxuXHRsZXQgbWF0Y2hlcyA9IFJFR0VYLmV4ZWMocm91dGUpO1xuXHR3aGlsZSAobWF0Y2hlcykge1xuXHRcdGNvbnN0IGRhdGEgPSBjb252ZXJ0TWF0Y2hlc1RvT2JqKG1hdGNoZXMpO1xuXG5cdFx0Y3VyclBhdGggPSByb3V0ZS5zbGljZShpbmRleCwgbWF0Y2hlcy5pbmRleCk7XG5cdFx0aW5kZXggPSBtYXRjaGVzLmluZGV4ICsgZGF0YS5tYXRjaC5sZW5ndGg7XG5cdFx0dG9rZW5zLnB1c2goY3VyclBhdGgpO1xuXG5cdFx0dG9rZW5zLnB1c2goe1xuXHRcdFx0bmFtZTogZGF0YS5uYW1lID8gZGF0YS5uYW1lIDogJycgKyB1bm5hbWVkQ291bnQrKyxcblx0XHRcdHBhcnRpYWw6IHJvdXRlW2luZGV4XSAmJiByb3V0ZVtpbmRleF0gIT09IGRhdGEucHJlZml4LFxuXHRcdFx0cHJlZml4OiBkYXRhLnByZWZpeCB8fCAnJyxcblx0XHRcdHBhdHRlcm46IGRhdGEucGFyYW1QYXR0ZXJuIHx8IGRhdGEudW5uYW1lZFBhdHRlcm4gfHwgJ1teXFxcXC9dKycsXG5cdFx0XHRyZXBlYXQ6IGRhdGEubW9kaWZpZXIgPT09ICcqJyB8fCBkYXRhLm1vZGlmaWVyID09PSAnKycsXG5cdFx0XHRvcHRpb25hbDogZGF0YS5tb2RpZmllciA9PT0gJyonIHx8IGRhdGEubW9kaWZpZXIgPT09ICc/J1xuXHRcdH0pO1xuXG5cdFx0bWF0Y2hlcyA9IFJFR0VYLmV4ZWMocm91dGUpO1xuXHR9XG5cblx0aWYgKGluZGV4IDwgcm91dGUubGVuZ3RoKSB7XG5cdFx0dG9rZW5zLnB1c2gocm91dGUuc3Vic3RyKGluZGV4KSk7XG5cdH1cblx0cmV0dXJuIHRva2Vucztcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gcm91dGUgZm9ybWF0IHN0cmluZyB0byBhIHJlZ2V4IHRoYXQgY2FuIGV4dHJhY3QgcGFyYW1cbiAqIGRhdGEgZnJvbSBwYXRocyBtYXRjaGluZyBpdC5cbiAqIEBwYXJhbSB7IUFycmF5fHN0cmluZ30gcm91dGVPclRva2VucyBFaXRoZXIgYSByb3V0ZSBmb3JtYXQgc3RyaW5nIG9yIHRva2Vuc1xuICogICAgIHByZXZpb3VzbHkgcGFyc2VkIHZpYSB0aGUgYHBhcnNlYCBmdW5jdGlvbi5cbiAqIEByZXR1cm4geyFSZWdFeHB9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1JlZ2V4KHJvdXRlT3JUb2tlbnMpIHtcblx0cmV0dXJuIGNvbnZlcnRUb2tlbnNUb1JlZ2V4KHBhcnNlKHJvdXRlT3JUb2tlbnMpKTtcbn1cblxuLyoqXG4gKiBFeHRyYWN0cyBkYXRhIGZyb20gdGhlIGdpdmVuIHBhdGggYWNjb3JkaW5nIHRvIHRoZSBzcGVjaWZpZWQgcm91dGUgZm9ybWF0LlxuICogQHBhcmFtIHshQXJyYXl8c3RyaW5nfSByb3V0ZU9yVG9rZW5zIEVpdGhlciBhIHJvdXRlIGZvcm1hdCBzdHJpbmcgb3IgdG9rZW5zXG4gKiAgICAgcHJldmlvdXNseSBwYXJzZWQgdmlhIHRoZSBgcGFyc2VgIGZ1bmN0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IFRoZSBwYXRoIHRvIGV4dHJhY3QgcGFyYW0gZGF0YSBmcm9tLlxuICogQHJldHVybiB7T2JqZWN0PHN0cmluZywgc3RyaW5nPn0gVGhlIGRhdGEgb2JqZWN0LCBvciBudWxsIGlmIHRoZSBwYXRoIGRvZXNuJ3RcbiAqICAgICBtYXRjaCB0aGUgZ2l2ZW4gZm9ybWF0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdERhdGEocm91dGVPclRva2VucywgcGF0aCkge1xuXHRjb25zdCBkYXRhID0ge307XG5cdGNvbnN0IHRva2VucyA9IHBhcnNlKHJvdXRlT3JUb2tlbnMpO1xuXHRjb25zdCBtYXRjaCA9IHBhdGgubWF0Y2goY29udmVydFRva2Vuc1RvUmVnZXgodG9rZW5zKSk7XG5cblx0aWYgKCFtYXRjaCkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0bGV0IHBhcmFtSW5kZXggPSAxO1xuXHRmb3IgKGxldCBpID0gMDsgaSA8IHRva2Vucy5sZW5ndGg7IGkrKykge1xuXHRcdGlmICghY29yZS5pc1N0cmluZyh0b2tlbnNbaV0pKSB7XG5cdFx0XHRsZXQgdmFsdWUgPSBtYXRjaFtwYXJhbUluZGV4KytdO1xuXHRcdFx0aWYgKGNvcmUuaXNEZWYodmFsdWUpKSB7XG5cdFx0XHRcdGlmICh0b2tlbnNbaV0ucmVwZWF0KSB7XG5cdFx0XHRcdFx0dmFsdWUgPSB2YWx1ZS5zcGxpdCgnLycpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRhdGFbdG9rZW5zW2ldLm5hbWVdID0gdmFsdWU7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdHJldHVybiBkYXRhO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBpc0RlZkFuZE5vdE51bGwsIGlzRnVuY3Rpb24sIGlzU3RyaW5nIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgZXh0cmFjdERhdGEsIHBhcnNlLCB0b1JlZ2V4IH0gZnJvbSAnbWV0YWwtcGF0aC1wYXJzZXInO1xuXG5jbGFzcyBSb3V0ZSB7XG5cblx0LyoqXG5cdCAqIFJvdXRlIGNsYXNzLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd8UmVnRXhwfEZ1bmN0aW9ufSBwYXRoXG5cdCAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBoYW5kbGVyXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IocGF0aCwgaGFuZGxlcikge1xuXHRcdGlmICghaXNEZWZBbmROb3ROdWxsKHBhdGgpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1JvdXRlIHBhdGggbm90IHNwZWNpZmllZC4nKTtcblx0XHR9XG5cdFx0aWYgKCFpc0Z1bmN0aW9uKGhhbmRsZXIpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1JvdXRlIGhhbmRsZXIgaXMgbm90IGEgZnVuY3Rpb24uJyk7XG5cdFx0fVxuXG5cdFx0LyoqXG5cdFx0ICogRGVmaW5lcyB0aGUgaGFuZGxlciB3aGljaCB3aWxsIGV4ZWN1dGUgb25jZSBhIFVSTCBpbiB0aGUgYXBwbGljYXRpb25cblx0XHQgKiBtYXRjaGVzIHRoZSBwYXRoLlxuXHRcdCAqIEB0eXBlIHshRnVuY3Rpb259XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuaGFuZGxlciA9IGhhbmRsZXI7XG5cblx0XHQvKipcblx0XHQgKiBEZWZpbmVzIHRoZSBwYXRoIHdoaWNoIHdpbGwgdHJpZ2dlciB0aGUgcm91dGUgaGFuZGxlci5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ3xSZWdFeHB8RnVuY3Rpb259XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucGF0aCA9IHBhdGg7XG5cdH1cblxuXHQvKipcblx0KiBCdWlsZHMgcGFyc2VkIGRhdGEgKHJlZ2V4IGFuZCB0b2tlbnMpIGZvciB0aGlzIHJvdXRlLlxuXHQqIEByZXR1cm4geyFPYmplY3R9XG5cdCogQHByb3RlY3RlZFxuXHQqL1xuXHRidWlsZFBhcnNlZERhdGFfKCkge1xuXHRcdGlmICghdGhpcy5wYXJzZWREYXRhXykge1xuXHRcdFx0dmFyIHRva2VucyA9IHBhcnNlKHRoaXMucGF0aCk7XG5cdFx0XHR2YXIgcmVnZXggPSB0b1JlZ2V4KHRva2Vucyk7XG5cdFx0XHR0aGlzLnBhcnNlZERhdGFfID0ge1xuXHRcdFx0XHRyZWdleCxcblx0XHRcdFx0dG9rZW5zXG5cdFx0XHR9O1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5wYXJzZWREYXRhXztcblx0fVxuXG5cdC8qKlxuXHQgKiBFeHRyYWN0cyBwYXJhbSBkYXRhIGZyb20gdGhlIGdpdmVuIHBhdGgsIGFjY29yZGluZyB0byB0aGlzIHJvdXRlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBUaGUgdXJsIHBhdGggdG8gZXh0cmFjdCBwYXJhbXMgZnJvbS5cblx0ICogQHJldHVybiB7T2JqZWN0fSBUaGUgZXh0cmFjdGVkIGRhdGEsIGlmIHRoZSBwYXRoIG1hdGNoZXMgdGhpcyByb3V0ZSwgb3Jcblx0ICogICAgIG51bGwgb3RoZXJ3aXNlLlxuXHQgKi9cblx0ZXh0cmFjdFBhcmFtcyhwYXRoKSB7XG5cdFx0aWYgKGlzU3RyaW5nKHRoaXMucGF0aCkpIHtcblx0XHRcdHJldHVybiBleHRyYWN0RGF0YSh0aGlzLmJ1aWxkUGFyc2VkRGF0YV8oKS50b2tlbnMsIHBhdGgpO1xuXHRcdH1cblx0XHRyZXR1cm4ge307XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcm91dGUgaGFuZGxlci5cblx0ICogQHJldHVybiB7IUZ1bmN0aW9ufVxuXHQgKi9cblx0Z2V0SGFuZGxlcigpIHtcblx0XHRyZXR1cm4gdGhpcy5oYW5kbGVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHJvdXRlIHBhdGguXG5cdCAqIEByZXR1cm4geyFzdHJpbmd8UmVnRXhwfEZ1bmN0aW9ufVxuXHQgKi9cblx0Z2V0UGF0aCgpIHtcblx0XHRyZXR1cm4gdGhpcy5wYXRoO1xuXHR9XG5cblx0LyoqXG4gXHQgKiBNYXRjaGVzIGlmIHRoZSByb3V0ZXIgY2FuIGhhbmRsZSB0aGUgdGVzdGVkIHBhdGguXG4gXHQgKiBAcGFyYW0geyFzdHJpbmd9IHZhbHVlIFBhdGggdG8gdGVzdCAobWF5IGNvbnRhaW4gdGhlIHF1ZXJ5c3RyaW5nIHBhcnQpLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufSBSZXR1cm5zIHRydWUgaWYgbWF0Y2hlcyBhbnkgcm91dGUuXG5cdCAqL1xuXHRtYXRjaGVzUGF0aCh2YWx1ZSkge1xuXHRcdHZhciBwYXRoID0gdGhpcy5wYXRoO1xuXG5cdFx0aWYgKGlzRnVuY3Rpb24ocGF0aCkpIHtcblx0XHRcdHJldHVybiBwYXRoKHZhbHVlKTtcblx0XHR9XG5cdFx0aWYgKGlzU3RyaW5nKHBhdGgpKSB7XG5cdFx0XHRwYXRoID0gdGhpcy5idWlsZFBhcnNlZERhdGFfKCkucmVnZXg7XG5cdFx0fVxuXHRcdGlmIChwYXRoIGluc3RhbmNlb2YgUmVnRXhwKSB7XG5cdFx0XHRyZXR1cm4gdmFsdWUuc2VhcmNoKHBhdGgpID4gLTE7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgUm91dGU7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IERpc3Bvc2FibGUgfSBmcm9tICdtZXRhbCc7XG5cbmNsYXNzIENhY2hlYWJsZSBleHRlbmRzIERpc3Bvc2FibGUge1xuXG5cdC8qKlxuXHQgKiBBYnN0cmFjdCBjbGFzcyBmb3IgZGVmaW5pbmcgY2FjaGVhYmxlIGJlaGF2aW9yLlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgY2FjaGVkIGRhdGEuXG5cdFx0ICogQHR5cGUgeyFPYmplY3R9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmNhY2hlID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHdoZXRoZXIgY2xhc3MgaXMgY2FjaGVhYmxlLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuY2FjaGVhYmxlID0gZmFsc2U7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBjb250ZW50IHRvIHRoZSBjYWNoZS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGNvbnRlbnQgQ29udGVudCB0byBiZSBjYWNoZWQuXG5cdCAqIEBjaGFpbmFibGVcblx0ICovXG5cdGFkZENhY2hlKGNvbnRlbnQpIHtcblx0XHRpZiAodGhpcy5jYWNoZWFibGUpIHtcblx0XHRcdHRoaXMuY2FjaGUgPSBjb250ZW50O1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhcnMgdGhlIGNhY2hlLlxuXHQgKiBAY2hhaW5hYmxlXG5cdCAqL1xuXHRjbGVhckNhY2hlKCkge1xuXHRcdHRoaXMuY2FjaGUgPSBudWxsO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2VzIG9mIHRoaXMgaW5zdGFuY2UncyBvYmplY3QgcmVmZXJlbmNlcy5cblx0ICogQG92ZXJyaWRlXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0dGhpcy5jbGVhckNhY2hlKCk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgY2FjaGVkIGNvbnRlbnQuXG5cdCAqIEByZXR1cm4ge09iamVjdH0gQ2FjaGVkIGNvbnRlbnQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGdldENhY2hlKCkge1xuXHRcdHJldHVybiB0aGlzLmNhY2hlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFdoZXRoZXIgdGhlIGNsYXNzIGlzIGNhY2hlYWJsZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIHdoZW4gY2xhc3MgaXMgY2FjaGVhYmxlLCBmYWxzZSBvdGhlcndpc2UuXG5cdCAqL1xuXHRpc0NhY2hlYWJsZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5jYWNoZWFibGU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB3aGV0aGVyIHRoZSBjbGFzcyBpcyBjYWNoZWFibGUuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gY2FjaGVhYmxlXG5cdCAqL1xuXHRzZXRDYWNoZWFibGUoY2FjaGVhYmxlKSB7XG5cdFx0aWYgKCFjYWNoZWFibGUpIHtcblx0XHRcdHRoaXMuY2xlYXJDYWNoZSgpO1xuXHRcdH1cblx0XHR0aGlzLmNhY2hlYWJsZSA9IGNhY2hlYWJsZTtcblx0fVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IENhY2hlYWJsZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgZ2xvYmFsRXZhbCB9IGZyb20gJ21ldGFsLWRvbSc7XG5pbXBvcnQgQ2FjaGVhYmxlIGZyb20gJy4uL2NhY2hlYWJsZS9DYWNoZWFibGUnO1xuaW1wb3J0IENhbmNlbGxhYmxlUHJvbWlzZSBmcm9tICdtZXRhbC1wcm9taXNlJztcblxuY2xhc3MgU2NyZWVuIGV4dGVuZHMgQ2FjaGVhYmxlIHtcblxuXHQvKipcblx0ICogU2NyZWVuIGNsYXNzIGlzIGEgc3BlY2lhbCB0eXBlIG9mIHJvdXRlIGhhbmRsZXIgdGhhdCBwcm92aWRlcyBoZWxwZXJcblx0ICogdXRpbGl0aWVzIHRoYXQgYWRkcyBsaWZlY3ljbGUgYW5kIG1ldGhvZHMgdG8gcHJvdmlkZSBjb250ZW50IHRvIGVhY2hcblx0ICogcmVnaXN0ZXJlZCBzdXJmYWNlLlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICogQGV4dGVuZHMge0NhY2hlYWJsZX1cblx0ICovXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgc2NyZWVuIGlkLlxuXHRcdCAqIEB0eXBlIHtzdHJpbmd9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuaWQgPSB0aGlzLm1ha2VJZF8oZ2V0VWlkKCkpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHNjcmVlbiB0aXRsZS4gUmVsZXZhbnQgd2hlbiB0aGUgcGFnZSB0aXRsZSBzaG91bGQgYmVcblx0XHQgKiB1cGFkYXRlZCB3aGVuIHNjcmVlbiBpcyByZW5kZXJlZC5cblx0XHQgKiBAdHlwZSB7P3N0cmluZz19XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnRpdGxlID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBGaXJlcyB3aGVuIHRoZSBzY3JlZW4gaXMgYWN0aXZlLiBBbGxvd3MgYSBzY3JlZW4gdG8gcGVyZm9ybSBhbnkgc2V0dXBcblx0ICogdGhhdCByZXF1aXJlcyBpdHMgRE9NIHRvIGJlIHZpc2libGUuIExpZmVjeWNsZS5cblx0ICovXG5cdGFjdGl2YXRlKCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gYWN0aXZhdGUnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHaXZlcyB0aGUgU2NyZWVuIGEgY2hhbmNlIHRvIGNhbmNlbCB0aGUgbmF2aWdhdGlvbiBhbmQgc3RvcCBpdHNlbGYgZnJvbVxuXHQgKiBiZWluZyBkZWFjdGl2YXRlZC4gQ2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCBpZiB0aGUgc2NyZWVuIGhhcyB1bnNhdmVkXG5cdCAqIHN0YXRlLiBMaWZlY3ljbGUuIENsZWFuLXVwIHNob3VsZCBub3QgYmUgcHJlZm9ybWVkIGhlcmUsIHNpbmNlIHRoZVxuXHQgKiBuYXZpZ2F0aW9uIG1heSBzdGlsbCBiZSBjYW5jZWxsZWQuIERvIGNsZWFuLXVwIGluIGRlYWN0aXZhdGUuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW49fSBJZiByZXR1cm5zIHRydWUsIHRoZSBjdXJyZW50IHNjcmVlbiBpcyBsb2NrZWQgYW5kIHRoZVxuXHQgKiAgICAgbmV4dCBuYWdpdmF0aW9uIGludGVycnVwdGVkLlxuXHQgKi9cblx0YmVmb3JlRGVhY3RpdmF0ZSgpIHtcblx0XHRjb25zb2xlLmxvZygnU2NyZWVuIFsnICsgdGhpcyArICddIGJlZm9yZURlYWN0aXZhdGUnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHaXZlcyB0aGUgU2NyZWVuIGEgY2hhbmNlIGZvcm1hdCB0aGUgcGF0aCBiZWZvcmUgaGlzdG9yeSB1cGRhdGUuXG5cdCAqIEBwYXRoIHshc3RyaW5nfSBwYXRoIE5hdmlnYXRpb24gcGF0aC5cblx0ICogQHJldHVybiB7IXN0cmluZ30gTmF2aWdhdGlvbiBwYXRoIHRvIHVzZSBvbiBoaXN0b3J5LlxuXHQgKi9cblx0YmVmb3JlVXBkYXRlSGlzdG9yeVBhdGgocGF0aCkge1xuXHRcdHJldHVybiBwYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdpdmVzIHRoZSBTY3JlZW4gYSBjaGFuY2UgZm9ybWF0IHRoZSBzdGF0ZSBiZWZvcmUgaGlzdG9yeSB1cGRhdGUuXG5cdCAqIEBwYXRoIHshb2JqZWN0fSBzdGF0ZSBIaXN0b3J5IHN0YXRlLlxuXHQgKiBAcmV0dXJuIHshb2JqZWN0fSBIaXN0b3J5IHN0YXRlIHRvIHVzZSBvbiBoaXN0b3J5LlxuXHQgKi9cblx0YmVmb3JlVXBkYXRlSGlzdG9yeVN0YXRlKHN0YXRlKSB7XG5cdFx0cmV0dXJuIHN0YXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBkbyBhbnkgY2xlYW51cCBuZWNlc3NhcnkgYWZ0ZXIgaXQgaGFzIGJlZW5cblx0ICogZGVhY3RpdmF0ZWQsIGZvciBleGFtcGxlIGNhbmNlbGxpbmcgb3V0c3RhbmRpbmcgcmVxdWVzdHMgb3Igc3RvcHBpbmdcblx0ICogdGltZXJzLiBMaWZlY3ljbGUuXG5cdCAqL1xuXHRkZWFjdGl2YXRlKCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZGVhY3RpdmF0ZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2UgYSBzY3JlZW4sIGVpdGhlciBhZnRlciBpdCBpcyBkZWFjdGl2YXRlZCAoaW4gdGhlIGNhc2Ugb2YgYVxuXHQgKiBub24tY2FjaGVhYmxlIHZpZXcpIG9yIHdoZW4gdGhlIEFwcCBpcyBpdHNlbGYgZGlzcG9zZWQgZm9yIHdoYXRldmVyXG5cdCAqIHJlYXNvbi4gTGlmZWN5Y2xlLlxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHN1cGVyLmRpc3Bvc2VJbnRlcm5hbCgpO1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZGlzcG9zZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBldmFsdWF0ZSBzY3JpcHRzIGJlZm9yZSB0aGUgZWxlbWVudCBpcyBtYWRlIHZpc2libGUuXG5cdCAqIExpZmVjeWNsZS5cblx0ICogQHBhcmFtIHshb2JqZWN0fSBzdXJmYWNlcyBNYXAgb2Ygc3VyZmFjZXMgdG8gZmxpcCBrZXllZCBieSBzdXJmYWNlIGlkLlxuXHQgKiBAcmV0dXJuIHs/Q2FuY2VsbGFibGVQcm9taXNlPX0gVGhpcyBjYW4gcmV0dXJuIGEgcHJvbWlzZSwgd2hpY2ggd2lsbFxuXHQgKiAgICAgcGF1c2UgdGhlIG5hdmlnYXRpb24gdW50aWwgaXQgaXMgcmVzb2x2ZWQuXG5cdCAqL1xuXHRldmFsdWF0ZVNjcmlwdHMoc3VyZmFjZXMpIHtcblx0XHRPYmplY3Qua2V5cyhzdXJmYWNlcykuZm9yRWFjaChzSWQgPT4ge1xuXHRcdFx0aWYgKHN1cmZhY2VzW3NJZF0uYWN0aXZlQ2hpbGQpIHtcblx0XHRcdFx0Z2xvYmFsRXZhbC5ydW5TY3JpcHRzSW5FbGVtZW50KHN1cmZhY2VzW3NJZF0uYWN0aXZlQ2hpbGQpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBldmFsdWF0ZSBzdHlsZXMgYmVmb3JlIHRoZSBlbGVtZW50IGlzIG1hZGUgdmlzaWJsZS5cblx0ICogTGlmZWN5Y2xlLlxuXHQgKiBAcGFyYW0geyFvYmplY3R9IHN1cmZhY2VzIE1hcCBvZiBzdXJmYWNlcyB0byBmbGlwIGtleWVkIGJ5IHN1cmZhY2UgaWQuXG5cdCAqIEByZXR1cm4gez9DYW5jZWxsYWJsZVByb21pc2U9fSBUaGlzIGNhbiByZXR1cm4gYSBwcm9taXNlLCB3aGljaCB3aWxsXG5cdCAqICAgICBwYXVzZSB0aGUgbmF2aWdhdGlvbiB1bnRpbCBpdCBpcyByZXNvbHZlZC5cblx0ICovXG5cdGV2YWx1YXRlU3R5bGVzKCkge1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFsbG93cyBhIHNjcmVlbiB0byBwZXJmb3JtIGFueSBzZXR1cCBpbW1lZGlhdGVseSBiZWZvcmUgdGhlIGVsZW1lbnQgaXNcblx0ICogbWFkZSB2aXNpYmxlLiBMaWZlY3ljbGUuXG5cdCAqIEBwYXJhbSB7IW9iamVjdH0gc3VyZmFjZXMgTWFwIG9mIHN1cmZhY2VzIHRvIGZsaXAga2V5ZWQgYnkgc3VyZmFjZSBpZC5cblx0ICogQHJldHVybiB7P0NhbmNlbGxhYmxlUHJvbWlzZT19IFRoaXMgY2FuIHJldHVybiBhIHByb21pc2UsIHdoaWNoIHdpbGwgcGF1c2UgdGhlXG5cdCAqICAgICBuYXZpZ2F0aW9uIHVudGlsIGl0IGlzIHJlc29sdmVkLlxuXHQgKi9cblx0ZmxpcChzdXJmYWNlcykge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gZmxpcCcpO1xuXG5cdFx0dmFyIHRyYW5zaXRpb25zID0gW107XG5cblx0XHRPYmplY3Qua2V5cyhzdXJmYWNlcykuZm9yRWFjaChzSWQgPT4ge1xuXHRcdFx0dmFyIHN1cmZhY2UgPSBzdXJmYWNlc1tzSWRdO1xuXHRcdFx0dmFyIGRlZmVycmVkID0gc3VyZmFjZS5zaG93KHRoaXMuaWQpO1xuXHRcdFx0dHJhbnNpdGlvbnMucHVzaChkZWZlcnJlZCk7XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLmFsbCh0cmFuc2l0aW9ucyk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc2NyZWVuIGlkLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRnZXRJZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBjb250ZW50IGZvciB0aGUgZ2l2ZW4gc3VyZmFjZSwgb3IgbnVsbCBpZiB0aGUgc3VyZmFjZSBpc24ndFxuXHQgKiB1c2VkIGJ5IHRoaXMgc2NyZWVuLiBUaGlzIHdpbGwgYmUgY2FsbGVkIHdoZW4gYSBzY3JlZW4gaXMgaW5pdGlhbGx5XG5cdCAqIGNvbnN0cnVjdGVkIG9yLCBpZiBhIHNjcmVlbiBpcyBub24tY2FjaGVhYmxlLCB3aGVuIG5hdmlnYXRlZC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzdXJmYWNlSWQgVGhlIGlkIG9mIHRoZSBzdXJmYWNlIERPTSBlbGVtZW50LlxuXHQgKiBAcGFyYW0geyFPYmplY3R9IHBhcmFtcyBQYXJhbXMgZXh0cmFjdGVkIGZyb20gdGhlIGN1cnJlbnQgcGF0aC5cblx0ICogQHJldHVybiB7P3N0cmluZ3xFbGVtZW50PX0gVGhpcyBjYW4gcmV0dXJuIGEgc3RyaW5nIG9yIG5vZGUgcmVwcmVzZW50aW5nXG5cdCAqICAgICB0aGUgY29udGVudCBvZiB0aGUgc3VyZmFjZS4gSWYgcmV0dXJucyBmYWxzeSB2YWx1ZXMgc3VyZmFjZSBkZWZhdWx0XG5cdCAqICAgICBjb250ZW50IGlzIHJlc3RvcmVkLlxuXHQgKi9cblx0Z2V0U3VyZmFjZUNvbnRlbnQoKSB7XG5cdFx0Y29uc29sZS5sb2coJ1NjcmVlbiBbJyArIHRoaXMgKyAnXSBnZXRTdXJmYWNlQ29udGVudCcpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHNjcmVlbiB0aXRsZS5cblx0ICogQHJldHVybiB7P3N0cmluZz19XG5cdCAqL1xuXHRnZXRUaXRsZSgpIHtcblx0XHRyZXR1cm4gdGhpcy50aXRsZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGFsbCBjb250ZW50cyBmb3IgdGhlIHN1cmZhY2VzLiBUaGlzIHdpbGwgcGFzcyB0aGUgbG9hZGVkIGNvbnRlbnRcblx0ICogdG8gPGNvZGU+U2NyZWVuLmxvYWQ8L2NvZGU+IHdpdGggYWxsIGluZm9ybWF0aW9uIHlvdVxuXHQgKiBuZWVkIHRvIGZ1bGZpbGwgdGhlIHN1cmZhY2VzLiBMaWZlY3ljbGUuXG5cdCAqIEBwYXJhbSB7IXN0cmluZz19IHBhdGggVGhlIHJlcXVlc3RlZCBwYXRoLlxuXHQgKiBAcmV0dXJuIHshQ2FuY2VsbGFibGVQcm9taXNlfSBUaGlzIGNhbiByZXR1cm4gYSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZVxuXHQgKiAgICAgY29udGVudHMgb2YgdGhlIHN1cmZhY2VzIG9yIGEgcHJvbWlzZSwgd2hpY2ggd2lsbCBwYXVzZSB0aGUgbmF2aWdhdGlvblxuXHQgKiAgICAgdW50aWwgaXQgaXMgcmVzb2x2ZWQuIFRoaXMgaXMgdXNlZnVsIGZvciBsb2FkaW5nIGFzeW5jIGNvbnRlbnQuXG5cdCAqL1xuXHRsb2FkKCkge1xuXHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyB0aGlzICsgJ10gbG9hZCcpO1xuXHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIHRoZSBpZCBmb3IgdGhlIHNjcmVlbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBpZCBUaGUgc2NyZWVuIGlkIHRoZSBjb250ZW50IGJlbG9uZ3MgdG9vLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRtYWtlSWRfKGlkKSB7XG5cdFx0cmV0dXJuICdzY3JlZW5fJyArIGlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHNjcmVlbiBpZC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBpZFxuXHQgKi9cblx0c2V0SWQoaWQpIHtcblx0XHR0aGlzLmlkID0gaWQ7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgc2NyZWVuIHRpdGxlLlxuXHQgKiBAcGFyYW0gez9zdHJpbmc9fSB0aXRsZVxuXHQgKi9cblx0c2V0VGl0bGUodGl0bGUpIHtcblx0XHR0aGlzLnRpdGxlID0gdGl0bGU7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0dG9TdHJpbmcoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaWQ7XG5cdH1cblxufVxuXG4vKipcbiAqIEBwYXJhbSB7Kn0gb2JqZWN0XG4gKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIGEgZ2l2ZW4gaW5zdGFuY2UgaW1wbGVtZW50c1xuICogPGNvZGU+U2NyZWVuPC9jb2RlPi5cbiAqL1xuU2NyZWVuLmlzSW1wbGVtZW50ZWRCeSA9IGZ1bmN0aW9uKG9iamVjdCkge1xuXHRyZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgU2NyZWVuO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgU2NyZWVuO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IHsgRGlzcG9zYWJsZSwgaXNEZWZBbmROb3ROdWxsIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgYXBwZW5kLCByZW1vdmVDaGlsZHJlbiwgZXhpdERvY3VtZW50IH0gZnJvbSAnbWV0YWwtZG9tJztcbmltcG9ydCBDYW5jZWxsYWJsZVByb21pc2UgZnJvbSAnbWV0YWwtcHJvbWlzZSc7XG5cbmNsYXNzIFN1cmZhY2UgZXh0ZW5kcyBEaXNwb3NhYmxlIHtcblxuXHQvKipcblx0ICogU3VyZmFjZSBjbGFzcyByZXByZXNlbnRpbmcgdGhlIHJlZmVyZW5jZXMgdG8gZWxlbWVudHMgb24gdGhlIHBhZ2UgdGhhdFxuXHQgKiBjYW4gcG90ZW50aWFsbHkgYmUgdXBkYXRlZCBieSA8Y29kZT5BcHA8L2NvZGU+LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaWRcblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihpZCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHRpZiAoIWlkKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1N1cmZhY2UgZWxlbWVudCBpZCBub3Qgc3BlY2lmaWVkLiBBIHN1cmZhY2UgZWxlbWVudCByZXF1aXJlcyBhIHZhbGlkIGlkLicpO1xuXHRcdH1cblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBhY3RpdmUgY2hpbGQgZWxlbWVudC5cblx0XHQgKiBAdHlwZSB7RWxlbWVudH1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYWN0aXZlQ2hpbGQgPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGRlZmF1bHQgY2hpbGQgZWxlbWVudC5cblx0XHQgKiBAdHlwZSB7RWxlbWVudH1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuZGVmYXVsdENoaWxkID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBlbGVtZW50IHdpdGggdGhlIHNwZWNpZmllZCBzdXJmYWNlIGlkLCBpZiBub3QgZm91bmQgY3JlYXRlcyBhXG5cdFx0ICogbmV3IGVsZW1lbnQgd2l0aCB0aGUgc3BlY2lmaWVkIGlkLlxuXHRcdCAqIEB0eXBlIHtFbGVtZW50fVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5lbGVtZW50ID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBzdXJmYWNlIGlkLlxuXHRcdCAqIEB0eXBlIHtTdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmlkID0gaWQ7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgZGVmYXVsdCB0cmFuc2l0aW9uRm4gZm9yIHRoZSBzdXJmYWNlcy5cblx0XHQgKiBAcGFyYW0gez9FbGVtZW50PX0gZnJvbSBUaGUgdmlzaWJsZSBzdXJmYWNlIGVsZW1lbnQuXG5cdFx0ICogQHBhcmFtIHs/RWxlbWVudD19IHRvIFRoZSBzdXJmYWNlIGVsZW1lbnQgdG8gYmUgZmxpcHBlZC5cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0dGhpcy50cmFuc2l0aW9uRm4gPSBudWxsO1xuXG5cdFx0dGhpcy5kZWZhdWx0Q2hpbGQgPSB0aGlzLmdldENoaWxkKFN1cmZhY2UuREVGQVVMVCk7XG5cdFx0dGhpcy5tYXliZVdyYXBDb250ZW50QXNEZWZhdWx0XygpO1xuXHRcdHRoaXMuYWN0aXZlQ2hpbGQgPSB0aGlzLmRlZmF1bHRDaGlsZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIHNjcmVlbiBjb250ZW50IHRvIGEgc3VyZmFjZS4gSWYgY29udGVudCBoYXNuJ3QgYmVlbiBwYXNzZWQsIHNlZSBpZlxuXHQgKiBhbiBlbGVtZW50IGV4aXN0cyBpbiB0aGUgRE9NIHRoYXQgbWF0Y2hlcyB0aGUgaWQuIEJ5IGNvbnZlbnRpb24sIHRoZVxuXHQgKiBlbGVtZW50IHNob3VsZCBhbHJlYWR5IGJlIG5lc3RlZCBpbiB0aGUgcmlnaHQgZWxlbWVudCBhbmQgc2hvdWxkIGhhdmUgYW5cblx0ICogaWQgdGhhdCBpcyBhIGNvbmNhdGVudGF0aW9uIG9mIHRoZSBzdXJmYWNlIGlkICsgJy0nICsgdGhlIHNjcmVlbiBpZC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzY3JlZW5JZCBUaGUgc2NyZWVuIGlkIHRoZSBjb250ZW50IGJlbG9uZ3MgdG9vLlxuXHQgKiBAcGFyYW0gez9zdHJpbmd8RWxlbWVudD19IG9wdF9jb250ZW50IFRoZSBzdHJpbmcgY29udGVudCBvciBlbGVtZW50IHRvXG5cdCAqICAgICBhZGQgYmUgYWRkZWQgYXMgc3VyZmFjZSBjb250ZW50LlxuXHQgKiBAcmV0dXJuIHtFbGVtZW50fVxuXHQgKi9cblx0YWRkQ29udGVudChzY3JlZW5JZCwgb3B0X2NvbnRlbnQpIHtcblx0XHR2YXIgY2hpbGQgPSB0aGlzLmRlZmF1bHRDaGlsZDtcblxuXHRcdGlmIChpc0RlZkFuZE5vdE51bGwob3B0X2NvbnRlbnQpKSB7XG5cdFx0XHRjaGlsZCA9IHRoaXMuZ2V0Q2hpbGQoc2NyZWVuSWQpO1xuXHRcdFx0aWYgKGNoaWxkKSB7XG5cdFx0XHRcdHJlbW92ZUNoaWxkcmVuKGNoaWxkKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNoaWxkID0gdGhpcy5jcmVhdGVDaGlsZChzY3JlZW5JZCk7XG5cdFx0XHRcdHRoaXMudHJhbnNpdGlvbihjaGlsZCwgbnVsbCk7XG5cdFx0XHR9XG5cdFx0XHRhcHBlbmQoY2hpbGQsIG9wdF9jb250ZW50KTtcblx0XHR9XG5cblx0XHR2YXIgZWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudCgpO1xuXG5cdFx0aWYgKGVsZW1lbnQgJiYgY2hpbGQpIHtcblx0XHRcdGFwcGVuZChlbGVtZW50LCBjaGlsZCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGNoaWxkO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgY2hpbGQgbm9kZSBmb3IgdGhlIHN1cmZhY2UuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2NyZWVuSWQgVGhlIHNjcmVlbiBpZC5cblx0ICogQHJldHVybiB7RWxlbWVudH1cblx0ICovXG5cdGNyZWF0ZUNoaWxkKHNjcmVlbklkKSB7XG5cdFx0dmFyIGNoaWxkID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblx0XHRjaGlsZC5zZXRBdHRyaWJ1dGUoJ2lkJywgdGhpcy5tYWtlSWRfKHNjcmVlbklkKSk7XG5cdFx0cmV0dXJuIGNoaWxkO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgY2hpbGQgbm9kZSBvZiB0aGUgc3VyZmFjZS5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBzY3JlZW5JZCBUaGUgc2NyZWVuIGlkLlxuXHQgKiBAcmV0dXJuIHs/RWxlbWVudH1cblx0ICovXG5cdGdldENoaWxkKHNjcmVlbklkKSB7XG5cdFx0cmV0dXJuIGdsb2JhbHMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5tYWtlSWRfKHNjcmVlbklkKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc3VyZmFjZSBlbGVtZW50IGZyb20gZWxlbWVudCwgYW5kIHNldHMgaXQgdG8gdGhlIGVsIHByb3BlcnR5IG9mXG5cdCAqIHRoZSBjdXJyZW50IGluc3RhbmNlLlxuXHQgKiA8Y29kZT50aGlzLmVsZW1lbnQ8L2NvZGU+IHdpbGwgYmUgdXNlZC5cblx0ICogQHJldHVybiB7P0VsZW1lbnR9IFRoZSBjdXJyZW50IHN1cmZhY2UgZWxlbWVudC5cblx0ICovXG5cdGdldEVsZW1lbnQoKSB7XG5cdFx0aWYgKHRoaXMuZWxlbWVudCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWxlbWVudDtcblx0XHR9XG5cdFx0dGhpcy5lbGVtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmlkKTtcblx0XHRyZXR1cm4gdGhpcy5lbGVtZW50O1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHN1cmZhY2UgaWQuXG5cdCAqIEByZXR1cm4ge1N0cmluZ31cblx0ICovXG5cdGdldElkKCkge1xuXHRcdHJldHVybiB0aGlzLmlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHN1cmZhY2UgdHJhbnNpdGlvbiBmdW5jdGlvbi5cblx0ICogU2VlIDxjb2RlPlN1cmZhY2UuZGVmYXVsdFRyYW5zaXRpb248L2NvZGU+LlxuXHQgKiBAcmV0dXJuIHs/RnVuY3Rpb249fSBUaGUgdHJhbnNpdGlvbiBmdW5jdGlvbi5cblx0ICovXG5cdGdldFRyYW5zaXRpb25GbigpIHtcblx0XHRyZXR1cm4gdGhpcy50cmFuc2l0aW9uRm47XG5cdH1cblxuXHQvKipcblx0ICogTWFrZXMgdGhlIGlkIGZvciB0aGUgZWxlbWVudCB0aGF0IGhvbGRzIGNvbnRlbnQgZm9yIGEgc2NyZWVuLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNjcmVlbklkIFRoZSBzY3JlZW4gaWQgdGhlIGNvbnRlbnQgYmVsb25ncyB0b28uXG5cdCAqIEByZXR1cm4ge1N0cmluZ31cblx0ICogQHByaXZhdGVcblx0ICovXG5cdG1ha2VJZF8oc2NyZWVuSWQpIHtcblx0XHRyZXR1cm4gdGhpcy5pZCArICctJyArIHNjcmVlbklkO1xuXHR9XG5cblx0LyoqXG5cdCAqIElmIGRlZmF1bHQgY2hpbGQgaXMgbWlzc2luZywgd3JhcHMgc3VyZmFjZSBjb250ZW50IGFzIGRlZmF1bHQgY2hpbGQuIElmXG5cdCAqIHN1cmZhY2UgaGF2ZSBzdGF0aWMgY29udGVudCwgbWFrZSBzdXJlIHRvIHBsYWNlIGFcblx0ICogPGNvZGU+c3VyZmFjZUlkLWRlZmF1bHQ8L2NvZGU+IGVsZW1lbnQgaW5zaWRlIHN1cmZhY2UsIG9ubHkgY29udGVudHNcblx0ICogaW5zaWRlIHRoZSBkZWZhdWx0IGNoaWxkIHdpbGwgYmUgcmVwbGFjZWQgYnkgbmF2aWdhdGlvbi5cblx0ICovXG5cdG1heWJlV3JhcENvbnRlbnRBc0RlZmF1bHRfKCkge1xuXHRcdHZhciBlbGVtZW50ID0gdGhpcy5nZXRFbGVtZW50KCk7XG5cdFx0aWYgKGVsZW1lbnQgJiYgIXRoaXMuZGVmYXVsdENoaWxkKSB7XG5cdFx0XHR2YXIgZnJhZ21lbnQgPSBnbG9iYWxzLmRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcblx0XHRcdHdoaWxlIChlbGVtZW50LmZpcnN0Q2hpbGQpIHtcblx0XHRcdFx0ZnJhZ21lbnQuYXBwZW5kQ2hpbGQoZWxlbWVudC5maXJzdENoaWxkKTtcblx0XHRcdH1cblx0XHRcdHRoaXMuZGVmYXVsdENoaWxkID0gdGhpcy5hZGRDb250ZW50KFN1cmZhY2UuREVGQVVMVCwgZnJhZ21lbnQpO1xuXHRcdFx0dGhpcy50cmFuc2l0aW9uKG51bGwsIHRoaXMuZGVmYXVsdENoaWxkKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgc3VyZmFjZSBpZC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBpZFxuXHQgKi9cblx0c2V0SWQoaWQpIHtcblx0XHR0aGlzLmlkID0gaWQ7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgc3VyZmFjZSB0cmFuc2l0aW9uIGZ1bmN0aW9uLlxuXHQgKiBTZWUgPGNvZGU+U3VyZmFjZS5kZWZhdWx0VHJhbnNpdGlvbjwvY29kZT4uXG5cdCAqIEBwYXJhbSB7P0Z1bmN0aW9uPX0gdHJhbnNpdGlvbkZuIFRoZSB0cmFuc2l0aW9uIGZ1bmN0aW9uLlxuXHQgKi9cblx0c2V0VHJhbnNpdGlvbkZuKHRyYW5zaXRpb25Gbikge1xuXHRcdHRoaXMudHJhbnNpdGlvbkZuID0gdHJhbnNpdGlvbkZuO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNob3dzIHNjcmVlbiBjb250ZW50IGZyb20gYSBzdXJmYWNlLlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gc2NyZWVuSWQgVGhlIHNjcmVlbiBpZCB0byBzaG93LlxuXHQgKiBAcmV0dXJuIHtDYW5jZWxsYWJsZVByb21pc2V9IFBhdXNlcyB0aGUgbmF2aWdhdGlvbiB1bnRpbCBpdCBpcyByZXNvbHZlZC5cblx0ICovXG5cdHNob3coc2NyZWVuSWQpIHtcblx0XHR2YXIgZnJvbSA9IHRoaXMuYWN0aXZlQ2hpbGQ7XG5cdFx0dmFyIHRvID0gdGhpcy5nZXRDaGlsZChzY3JlZW5JZCk7XG5cdFx0aWYgKCF0bykge1xuXHRcdFx0dG8gPSB0aGlzLmRlZmF1bHRDaGlsZDtcblx0XHR9XG5cdFx0dGhpcy5hY3RpdmVDaGlsZCA9IHRvO1xuXHRcdHJldHVybiB0aGlzLnRyYW5zaXRpb24oZnJvbSwgdG8pLnRoZW5BbHdheXMoKCkgPT4ge1xuXHRcdFx0aWYgKGZyb20gJiYgZnJvbSAhPT0gdG8pIHtcblx0XHRcdFx0ZXhpdERvY3VtZW50KGZyb20pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgc2NyZWVuIGNvbnRlbnQgZnJvbSBhIHN1cmZhY2UuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2NyZWVuSWQgVGhlIHNjcmVlbiBpZCB0byByZW1vdmUuXG5cdCAqL1xuXHRyZW1vdmUoc2NyZWVuSWQpIHtcblx0XHR2YXIgY2hpbGQgPSB0aGlzLmdldENoaWxkKHNjcmVlbklkKTtcblx0XHRpZiAoY2hpbGQpIHtcblx0XHRcdGV4aXREb2N1bWVudChjaGlsZCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm4ge1N0cmluZ31cblx0ICovXG5cdHRvU3RyaW5nKCkge1xuXHRcdHJldHVybiB0aGlzLmlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIEludm9rZXMgdGhlIHRyYW5zaXRpb24gZnVuY3Rpb24gc3BlY2lmaWVkIG9uIDxjb2RlPnRyYW5zaXRpb248L2NvZGU+IGF0dHJpYnV0ZS5cblx0ICogQHBhcmFtIHs/RWxlbWVudD19IGZyb21cblx0ICogQHBhcmFtIHs/RWxlbWVudD19IHRvXG5cdCAqIEByZXR1cm4gez9DYW5jZWxsYWJsZVByb21pc2U9fSBUaGlzIGNhbiByZXR1cm4gYSBwcm9taXNlLCB3aGljaCB3aWxsIHBhdXNlIHRoZVxuXHQgKiAgICAgbmF2aWdhdGlvbiB1bnRpbCBpdCBpcyByZXNvbHZlZC5cblx0ICovXG5cdHRyYW5zaXRpb24oZnJvbSwgdG8pIHtcblx0XHR2YXIgdHJhbnNpdGlvbkZuID0gdGhpcy50cmFuc2l0aW9uRm4gfHwgU3VyZmFjZS5kZWZhdWx0VHJhbnNpdGlvbjtcblx0XHRyZXR1cm4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUodHJhbnNpdGlvbkZuLmNhbGwodGhpcywgZnJvbSwgdG8pKTtcblx0fVxuXG59XG5cbi8qKlxuICAgKiBIb2xkcyB0aGUgZGVmYXVsdCBzdXJmYWNlIG5hbWUuIEVsZW1lbnRzIG9uIHRoZSBwYWdlIG11c3QgY29udGFpbiBhIGNoaWxkXG4gICAqIGVsZW1lbnQgY29udGFpbmluZyB0aGUgZGVmYXVsdCBjb250ZW50LCB0aGlzIGVsZW1lbnQgbXVzdCBiZSBhcyBmb2xsb3dpbmc6XG4gICAqXG4gICAqIEV4YW1wbGU6XG4gICAqIDxjb2RlPlxuICAgKiAgIDxkaXYgaWQ9XCJteXN1cmZhY2VcIj5cbiAgICogICAgIDxkaXYgaWQ9XCJteXN1cmZhY2UtZGVmYXVsdFwiPkRlZmF1bHQgc3VyZmFjZSBjb250ZW50LjwvZGl2PlxuICAgKiAgIDwvZGl2PlxuICAgKiA8L2NvZGU+XG4gICAqXG4gICAqIFRoZSBkZWZhdWx0IGNvbnRlbnQgaXMgcmVsZXZhbnQgZm9yIHRoZSBpbml0aWFsIHBhZ2UgY29udGVudC4gV2hlbiBhXG4gICAqIHNjcmVlbiBkb2Vzbid0IHByb3ZpZGUgY29udGVudCBmb3IgdGhlIHN1cmZhY2UgdGhlIGRlZmF1bHQgY29udGVudCBpc1xuICAgKiByZXN0b3JlZCBpbnRvIHRoZSBwYWdlLlxuICAgKlxuICAgKiBAdHlwZSB7IVN0cmluZ31cbiAgICogQGRlZmF1bHQgZGVmYXVsdFxuICAgKiBAc3RhdGljXG4gICAqL1xuU3VyZmFjZS5ERUZBVUxUID0gJ2RlZmF1bHQnO1xuXG4vKipcbiAqIEhvbGRzIHRoZSBkZWZhdWx0IHRyYW5zaXRpb24gZm9yIGFsbCBzdXJmYWNlcy4gRWFjaCBzdXJmYWNlIGNvdWxkIGhhdmUgaXRzXG4gKiBvd24gdHJhbnNpdGlvbi5cbiAqXG4gKiBFeGFtcGxlOlxuICpcbiAqIDxjb2RlPlxuICogc3VyZmFjZS5zZXRUcmFuc2l0aW9uRm4oZnVuY3Rpb24oZnJvbSwgdG8pIHtcbiAqICAgaWYgKGZyb20pIHtcbiAqICAgICBmcm9tLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gKiAgICAgZnJvbS5jbGFzc0xpc3QucmVtb3ZlKCdmbGlwcGVkJyk7XG4gKiAgIH1cbiAqICAgaWYgKHRvKSB7XG4gKiAgICAgdG8uc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gKiAgICAgdG8uY2xhc3NMaXN0LmFkZCgnZmxpcHBlZCcpO1xuICogICB9XG4gKiAgIHJldHVybiBudWxsO1xuICogfSk7XG4gKiA8L2NvZGU+XG4gKlxuICogQHBhcmFtIHs/RWxlbWVudD19IGZyb20gVGhlIHZpc2libGUgc3VyZmFjZSBlbGVtZW50LlxuICogQHBhcmFtIHs/RWxlbWVudD19IHRvIFRoZSBzdXJmYWNlIGVsZW1lbnQgdG8gYmUgZmxpcHBlZC5cbiAqIEBzdGF0aWNcbiAqL1xuU3VyZmFjZS5kZWZhdWx0VHJhbnNpdGlvbiA9IGZ1bmN0aW9uKGZyb20sIHRvKSB7XG5cdGlmIChmcm9tKSB7XG5cdFx0ZnJvbS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXHRcdGZyb20uY2xhc3NMaXN0LnJlbW92ZSgnZmxpcHBlZCcpO1xuXHR9XG5cdGlmICh0bykge1xuXHRcdHRvLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuXHRcdHRvLmNsYXNzTGlzdC5hZGQoJ2ZsaXBwZWQnKTtcblx0fVxufTtcblxuZXhwb3J0IGRlZmF1bHQgU3VyZmFjZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgYWRkQ2xhc3NlcywgZGVsZWdhdGUsIG1hdGNoLCBvbiwgcmVtb3ZlQ2xhc3NlcyB9IGZyb20gJ21ldGFsLWRvbSc7XG5pbXBvcnQgeyBhcnJheSwgYXN5bmMsIGlzRGVmQW5kTm90TnVsbCwgaXNTdHJpbmcgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIsIEV2ZW50SGFuZGxlciB9IGZyb20gJ21ldGFsLWV2ZW50cyc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuaW1wb3J0IGRlYm91bmNlIGZyb20gJ21ldGFsLWRlYm91bmNlJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgUm91dGUgZnJvbSAnLi4vcm91dGUvUm91dGUnO1xuaW1wb3J0IFNjcmVlbiBmcm9tICcuLi9zY3JlZW4vU2NyZWVuJztcbmltcG9ydCBTdXJmYWNlIGZyb20gJy4uL3N1cmZhY2UvU3VyZmFjZSc7XG5pbXBvcnQgVXJpIGZyb20gJ21ldGFsLXVyaSc7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi4vdXRpbHMvdXRpbHMnO1xuXG5jbGFzcyBBcHAgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuXG5cdC8qKlxuXHQgKiBBcHAgY2xhc3MgdGhhdCBoYW5kbGUgcm91dGVzIGFuZCBzY3JlZW5zIGxpZmVjeWNsZS5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqIEBleHRlbmRzIHtFdmVudEVtaXR0ZXJ9XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGFjdGl2ZSBzY3JlZW4uXG5cdFx0ICogQHR5cGUgez9TY3JlZW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYWN0aXZlU2NyZWVuID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBhY3RpdmUgcGF0aCBjb250YWluaW5nIHRoZSBxdWVyeSBwYXJhbWV0ZXJzLlxuXHRcdCAqIEB0eXBlIHs/c3RyaW5nfVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmFjdGl2ZVBhdGggPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogQWxsb3dzIHByZXZlbnQgbmF2aWdhdGUgZnJvbSBkb20gcHJldmVudGVkIGV2ZW50LlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IHRydWVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5hbGxvd1ByZXZlbnROYXZpZ2F0ZSA9IHRydWU7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBsaW5rIGJhc2UgcGF0aC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCAnJ1xuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmJhc2VQYXRoID0gJyc7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgdmFsdWUgb2YgdGhlIGJyb3dzZXIgcGF0aCBiZWZvcmUgYSBuYXZpZ2F0aW9uIGlzIHBlcmZvcm1lZC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCB0aGUgY3VycmVudCBicm93c2VyIHBhdGguXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuYnJvd3NlclBhdGhCZWZvcmVOYXZpZ2F0ZSA9IHV0aWxzLmdldEN1cnJlbnRCcm93c2VyUGF0aFdpdGhvdXRIYXNoKCk7XG5cblx0XHQvKipcblx0XHQgKiBDYXB0dXJlcyBzY3JvbGwgcG9zaXRpb24gZnJvbSBzY3JvbGwgZXZlbnQuXG5cdFx0ICogQHR5cGUgeyFib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IHRydWVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5jYXB0dXJlU2Nyb2xsUG9zaXRpb25Gcm9tU2Nyb2xsRXZlbnQgPSB0cnVlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGRlZmF1bHQgcGFnZSB0aXRsZS5cblx0XHQgKiBAdHlwZSB7c3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IG51bGxcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5kZWZhdWx0VGl0bGUgPSBnbG9iYWxzLmRvY3VtZW50LnRpdGxlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGZvcm0gc2VsZWN0b3IgdG8gZGVmaW5lIGZvcm1zIHRoYXQgYXJlIHJvdXRlZC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBmb3JtW2VuY3R5cGU9XCJtdWx0aXBhcnQvZm9ybS1kYXRhXCJdOm5vdChbZGF0YS1zZW5uYS1vZmZdKVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmZvcm1TZWxlY3RvciA9ICdmb3JtW2VuY3R5cGU9XCJtdWx0aXBhcnQvZm9ybS1kYXRhXCJdOm5vdChbZGF0YS1zZW5uYS1vZmZdKSc7XG5cblx0XHQvKipcblx0XHQgKiBXaGVuIGVuYWJsZWQsIHRoZSByb3V0ZSBtYXRjaGluZyBpZ25vcmVzIHF1ZXJ5IHN0cmluZyBmcm9tIHRoZSBwYXRoLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoID0gZmFsc2U7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgbGluayBzZWxlY3RvciB0byBkZWZpbmUgbGlua3MgdGhhdCBhcmUgcm91dGVkLlxuXHRcdCAqIEB0eXBlIHshc3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IGE6bm90KFtkYXRhLXNlbm5hLW9mZl0pXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMubGlua1NlbGVjdG9yID0gJ2E6bm90KFtkYXRhLXNlbm5hLW9mZl0pOm5vdChbdGFyZ2V0PVwiX2JsYW5rXCJdKSc7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgbG9hZGluZyBjc3MgY2xhc3MuXG5cdFx0ICogQHR5cGUgeyFzdHJpbmd9XG5cdFx0ICogQGRlZmF1bHQgc2VubmEtbG9hZGluZ1xuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmxvYWRpbmdDc3NDbGFzcyA9ICdzZW5uYS1sb2FkaW5nJztcblxuXHRcdC8qKlxuXHRcdCAqIFVzaW5nIHRoZSBIaXN0b3J5IEFQSSB0byBtYW5hZ2UgeW91ciBVUkxzIGlzIGF3ZXNvbWUgYW5kLCBhcyBpdCBoYXBwZW5zLFxuXHRcdCAqIGEgY3J1Y2lhbCBmZWF0dXJlIG9mIGdvb2Qgd2ViIGFwcHMuIE9uZSBvZiBpdHMgZG93bnNpZGVzLCBob3dldmVyLCBpc1xuXHRcdCAqIHRoYXQgc2Nyb2xsIHBvc2l0aW9ucyBhcmUgc3RvcmVkIGFuZCB0aGVuLCBtb3JlIGltcG9ydGFudGx5LCByZXN0b3JlZFxuXHRcdCAqIHdoZW5ldmVyIHlvdSB0cmF2ZXJzZSB0aGUgaGlzdG9yeS4gVGhpcyBvZnRlbiBtZWFucyB1bnNpZ2h0bHkganVtcHMgYXNcblx0XHQgKiB0aGUgc2Nyb2xsIHBvc2l0aW9uIGNoYW5nZXMgYXV0b21hdGljYWxseSwgYW5kIGVzcGVjaWFsbHkgc28gaWYgeW91ciBhcHBcblx0XHQgKiBkb2VzIHRyYW5zaXRpb25zLCBvciBjaGFuZ2VzIHRoZSBjb250ZW50cyBvZiB0aGUgcGFnZSBpbiBhbnkgd2F5LlxuXHRcdCAqIFVsdGltYXRlbHkgdGhpcyBsZWFkcyB0byBhbiBob3JyaWJsZSB1c2VyIGV4cGVyaWVuY2UuIFRoZSBnb29kIG5ld3MgaXMsXG5cdFx0ICogaG93ZXZlciwgdGhhdCB0aGVyZeKAmXMgYSBwb3RlbnRpYWwgZml4OiBoaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uLlxuXHRcdCAqIGh0dHBzOi8vZGV2ZWxvcGVycy5nb29nbGUuY29tL3dlYi91cGRhdGVzLzIwMTUvMDkvaGlzdG9yeS1hcGktc2Nyb2xsLXJlc3RvcmF0aW9uXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMubmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25TdXBwb3J0ZWQgPSAoJ3Njcm9sbFJlc3RvcmF0aW9uJyBpbiBnbG9iYWxzLndpbmRvdy5oaXN0b3J5KTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gc2V0IHRvIHRydWUgdGhlcmUgaXMgYSBwZW5kaW5nTmF2aWdhdGUgdGhhdCBoYXMgbm90IHlldCBiZWVuXG5cdFx0ICogcmVzb2x2ZWQgb3IgcmVqZWN0ZWQuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQGRlZmF1bHQgZmFsc2Vcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5pc05hdmlnYXRpb25QZW5kaW5nID0gZmFsc2U7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyBhIGRlZmVycmVkIHdpdGggdGhlIGN1cnJlbnQgbmF2aWdhdGlvbi5cblx0XHQgKiBAdHlwZSB7P0NhbmNlbGxhYmxlUHJvbWlzZX1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSB3aW5kb3cgaG9yaXpvbnRhbCBzY3JvbGwgcG9zaXRpb24gd2hlbiB0aGUgbmF2aWdhdGlvbiB1c2luZ1xuXHRcdCAqIGJhY2sgb3IgZm9yd2FyZCBoYXBwZW5zIHRvIGJlIHJlc3RvcmVkIGFmdGVyIHRoZSBzdXJmYWNlcyBhcmUgdXBkYXRlZC5cblx0XHQgKiBAdHlwZSB7IU51bWJlcn1cblx0XHQgKiBAZGVmYXVsdCAwXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucG9wc3RhdGVTY3JvbGxMZWZ0ID0gMDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSB3aW5kb3cgdmVydGljYWwgc2Nyb2xsIHBvc2l0aW9uIHdoZW4gdGhlIG5hdmlnYXRpb24gdXNpbmdcblx0XHQgKiBiYWNrIG9yIGZvcndhcmQgaGFwcGVucyB0byBiZSByZXN0b3JlZCBhZnRlciB0aGUgc3VyZmFjZXMgYXJlIHVwZGF0ZWQuXG5cdFx0ICogQHR5cGUgeyFOdW1iZXJ9XG5cdFx0ICogQGRlZmF1bHQgMFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnBvcHN0YXRlU2Nyb2xsVG9wID0gMDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSByZWRpcmVjdCBwYXRoIGNvbnRhaW5pbmcgdGhlIHF1ZXJ5IHBhcmFtZXRlcnMuXG5cdFx0ICogQHR5cGUgez9zdHJpbmd9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMucmVkaXJlY3RQYXRoID0gbnVsbDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBzY3JlZW4gcm91dGVzIGNvbmZpZ3VyYXRpb24uXG5cdFx0ICogQHR5cGUgez9BcnJheX1cblx0XHQgKiBAZGVmYXVsdCBbXVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnJvdXRlcyA9IFtdO1xuXG5cdFx0LyoqXG5cdFx0ICogTWFwcyB0aGUgc2NyZWVuIGluc3RhbmNlcyBieSB0aGUgdXJsIGNvbnRhaW5pbmcgdGhlIHBhcmFtZXRlcnMuXG5cdFx0ICogQHR5cGUgez9PYmplY3R9XG5cdFx0ICogQGRlZmF1bHQge31cblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy5zY3JlZW5zID0ge307XG5cblx0XHQvKipcblx0XHQgKiBXaGVuIHNldCB0byB0cnVlIHRoZSBmaXJzdCBlcnJvbmVvdXMgcG9wc3RhdGUgZmlyZWQgb24gcGFnZSBsb2FkIHdpbGwgYmVcblx0XHQgKiBpZ25vcmVkLCBvbmx5IGlmIDxjb2RlPmdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc3RhdGU8L2NvZGU+IGlzIGFsc29cblx0XHQgKiA8Y29kZT5udWxsPC9jb2RlPi5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnNraXBMb2FkUG9wc3RhdGUgPSBmYWxzZTtcblxuXHRcdC8qKlxuXHRcdCAqIE1hcHMgdGhhdCBpbmRleCB0aGUgc3VyZmFjZXMgaW5zdGFuY2VzIGJ5IHRoZSBzdXJmYWNlIGlkLlxuXHRcdCAqIEB0eXBlIHs/T2JqZWN0fVxuXHRcdCAqIEBkZWZhdWx0IHt9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuc3VyZmFjZXMgPSB7fTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gc2V0IHRvIHRydWUsIG1vdmVzIHRoZSBzY3JvbGwgcG9zaXRpb24gYWZ0ZXIgcG9wc3RhdGUsIG9yIHRvIHRoZVxuXHRcdCAqIHRvcCBvZiB0aGUgdmlld3BvcnQgZm9yIG5ldyBuYXZpZ2F0aW9uLiBJZiBmYWxzZSwgdGhlIGJyb3dzZXIgd2lsbFxuXHRcdCAqIHRha2UgY2FyZSBvZiBzY3JvbGwgcmVzdG9yYXRpb24uXG5cdFx0ICogQHR5cGUgeyFib29sZWFufVxuXHRcdCAqIEBkZWZhdWx0IHRydWVcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy51cGRhdGVTY3JvbGxQb3NpdGlvbiA9IHRydWU7XG5cblx0XHR0aGlzLmFwcEV2ZW50SGFuZGxlcnNfID0gbmV3IEV2ZW50SGFuZGxlcigpO1xuXG5cdFx0dGhpcy5hcHBFdmVudEhhbmRsZXJzXy5hZGQoXG5cdFx0XHRvbihnbG9iYWxzLndpbmRvdywgJ3Njcm9sbCcsIGRlYm91bmNlKHRoaXMub25TY3JvbGxfLmJpbmQodGhpcyksIDEwMCkpLFxuXHRcdFx0b24oZ2xvYmFscy53aW5kb3csICdsb2FkJywgdGhpcy5vbkxvYWRfLmJpbmQodGhpcykpLFxuXHRcdFx0b24oZ2xvYmFscy53aW5kb3csICdwb3BzdGF0ZScsIHRoaXMub25Qb3BzdGF0ZV8uYmluZCh0aGlzKSlcblx0XHQpO1xuXG5cdFx0dGhpcy5vbignc3RhcnROYXZpZ2F0ZScsIHRoaXMub25TdGFydE5hdmlnYXRlXyk7XG5cdFx0dGhpcy5vbignYmVmb3JlTmF2aWdhdGUnLCB0aGlzLm9uQmVmb3JlTmF2aWdhdGVfKTtcblx0XHR0aGlzLm9uKCdiZWZvcmVOYXZpZ2F0ZScsIHRoaXMub25CZWZvcmVOYXZpZ2F0ZURlZmF1bHRfLCB0cnVlKTtcblx0XHR0aGlzLm9uKCdiZWZvcmVVbmxvYWQnLCB0aGlzLm9uQmVmb3JlVW5sb2FkRGVmYXVsdF8pO1xuXG5cdFx0dGhpcy5zZXRMaW5rU2VsZWN0b3IodGhpcy5saW5rU2VsZWN0b3IpO1xuXHRcdHRoaXMuc2V0Rm9ybVNlbGVjdG9yKHRoaXMuZm9ybVNlbGVjdG9yKTtcblxuXHRcdHRoaXMubWF5YmVPdmVybG9hZEJlZm9yZVVubG9hZF8oKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIG9uZSBvciBtb3JlIHNjcmVlbnMgdG8gdGhlIGFwcGxpY2F0aW9uLlxuXHQgKlxuXHQgKiBFeGFtcGxlOlxuXHQgKlxuXHQgKiA8Y29kZT5cblx0ICogICBhcHAuYWRkUm91dGVzKHsgcGF0aDogJy9mb28nLCBoYW5kbGVyOiBGb29TY3JlZW4gfSk7XG5cdCAqICAgb3Jcblx0ICogICBhcHAuYWRkUm91dGVzKFt7IHBhdGg6ICcvZm9vJywgaGFuZGxlcjogZnVuY3Rpb24ocm91dGUpIHsgcmV0dXJuIG5ldyBGb29TY3JlZW4oKTsgfSB9XSk7XG5cdCAqIDwvY29kZT5cblx0ICpcblx0ICogQHBhcmFtIHtPYmplY3R9IG9yIHtBcnJheX0gcm91dGVzIFNpbmdsZSBvYmplY3Qgb3IgYW4gYXJyYXkgb2Ygb2JqZWN0LlxuXHQgKiAgICAgRWFjaCBvYmplY3Qgc2hvdWxkIGNvbnRhaW4gPGNvZGU+cGF0aDwvY29kZT4gYW5kIDxjb2RlPnNjcmVlbjwvY29kZT4uXG5cdCAqICAgICBUaGUgPGNvZGU+cGF0aDwvY29kZT4gc2hvdWxkIGJlIGEgc3RyaW5nIG9yIGEgcmVnZXggdGhhdCBtYXBzIHRoZVxuXHQgKiAgICAgbmF2aWdhdGlvbiByb3V0ZSB0byBhIHNjcmVlbiBjbGFzcyBkZWZpbml0aW9uIChub3QgYW4gaW5zdGFuY2UpLCBlLmc6XG5cdCAqICAgICAgICAgPGNvZGU+eyBwYXRoOiBcIi9ob21lOnBhcmFtMVwiLCBoYW5kbGVyOiBNeVNjcmVlbiB9PC9jb2RlPlxuXHQgKiAgICAgICAgIDxjb2RlPnsgcGF0aDogL2Zvby4rLywgaGFuZGxlcjogTXlTY3JlZW4gfTwvY29kZT5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkUm91dGVzKHJvdXRlcykge1xuXHRcdGlmICghQXJyYXkuaXNBcnJheShyb3V0ZXMpKSB7XG5cdFx0XHRyb3V0ZXMgPSBbcm91dGVzXTtcblx0XHR9XG5cdFx0cm91dGVzLmZvckVhY2goKHJvdXRlKSA9PiB7XG5cdFx0XHRpZiAoIShyb3V0ZSBpbnN0YW5jZW9mIFJvdXRlKSkge1xuXHRcdFx0XHRyb3V0ZSA9IG5ldyBSb3V0ZShyb3V0ZS5wYXRoLCByb3V0ZS5oYW5kbGVyKTtcblx0XHRcdH1cblx0XHRcdHRoaXMucm91dGVzLnB1c2gocm91dGUpO1xuXHRcdH0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgb25lIG9yIG1vcmUgc3VyZmFjZXMgdG8gdGhlIGFwcGxpY2F0aW9uLlxuXHQgKiBAcGFyYW0ge1N1cmZhY2V8U3RyaW5nfEFycmF5LjxTdXJmYWNlfFN0cmluZz59IHN1cmZhY2VzXG5cdCAqICAgICBTdXJmYWNlIGVsZW1lbnQgaWQgb3Igc3VyZmFjZSBpbnN0YW5jZS4gWW91IGNhbiBhbHNvIHBhc3MgYW4gQXJyYXlcblx0ICogICAgIHdoaWNoY29udGFpbnMgc3VyZmFjZSBpbnN0YW5jZXMgb3IgaWQuIEluIGNhc2Ugb2YgSUQsIHRoZXNlIHNob3VsZCBiZVxuXHQgKiAgICAgdGhlIGlkIG9mIHN1cmZhY2UgZWxlbWVudC5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0YWRkU3VyZmFjZXMoc3VyZmFjZXMpIHtcblx0XHRpZiAoIUFycmF5LmlzQXJyYXkoc3VyZmFjZXMpKSB7XG5cdFx0XHRzdXJmYWNlcyA9IFtzdXJmYWNlc107XG5cdFx0fVxuXHRcdHN1cmZhY2VzLmZvckVhY2goKHN1cmZhY2UpID0+IHtcblx0XHRcdGlmIChpc1N0cmluZyhzdXJmYWNlKSkge1xuXHRcdFx0XHRzdXJmYWNlID0gbmV3IFN1cmZhY2Uoc3VyZmFjZSk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnN1cmZhY2VzW3N1cmZhY2UuZ2V0SWQoKV0gPSBzdXJmYWNlO1xuXHRcdH0pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgaWYgY2FuIG5hdmlnYXRlIHRvIHBhdGguXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gdXJsXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHRjYW5OYXZpZ2F0ZSh1cmwpIHtcblx0XHRjb25zdCB1cmkgPSB1dGlscy5pc1dlYlVyaSh1cmwpO1xuXG5cdFx0aWYgKCF1cmkpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRjb25zdCBwYXRoID0gdXRpbHMuZ2V0VXJsUGF0aCh1cmwpO1xuXG5cdFx0aWYgKCF0aGlzLmlzTGlua1NhbWVPcmlnaW5fKHVyaS5nZXRIb3N0bmFtZSgpKSkge1xuXHRcdFx0Y29uc29sZS5sb2coJ09mZnNpdGUgbGluayBjbGlja2VkJyk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGlmICghdGhpcy5pc1NhbWVCYXNlUGF0aF8ocGF0aCkpIHtcblx0XHRcdGNvbnNvbGUubG9nKCdMaW5rIGNsaWNrZWQgb3V0c2lkZSBhcHBcXCdzIGJhc2UgcGF0aCcpO1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHQvLyBQcmV2ZW50cyBuYXZpZ2F0aW9uIGlmIGl0J3MgYSBoYXNoIGNoYW5nZSBvbiB0aGUgc2FtZSB1cmwuXG5cdFx0aWYgKHVyaS5nZXRIYXNoKCkgJiYgdXRpbHMuaXNDdXJyZW50QnJvd3NlclBhdGgocGF0aCkpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0aWYgKCF0aGlzLmZpbmRSb3V0ZShwYXRoKSkge1xuXHRcdFx0Y29uc29sZS5sb2coJ05vIHJvdXRlIGZvciAnICsgcGF0aCk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogQ2xlYXIgc2NyZWVucyBjYWNoZS5cblx0ICogQGNoYWluYWJsZVxuXHQgKi9cblx0Y2xlYXJTY3JlZW5zQ2FjaGUoKSB7XG5cdFx0T2JqZWN0LmtleXModGhpcy5zY3JlZW5zKS5mb3JFYWNoKChwYXRoKSA9PiB7XG5cdFx0XHRpZiAocGF0aCA9PT0gdGhpcy5hY3RpdmVQYXRoKSB7XG5cdFx0XHRcdHRoaXMuYWN0aXZlU2NyZWVuLmNsZWFyQ2FjaGUoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMucmVtb3ZlU2NyZWVuKHBhdGgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHJpZXZlcyBvciBjcmVhdGUgYSBzY3JlZW4gaW5zdGFuY2UgdG8gYSBwYXRoLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcmV0dXJuIHtTY3JlZW59XG5cdCAqL1xuXHRjcmVhdGVTY3JlZW5JbnN0YW5jZShwYXRoLCByb3V0ZSkge1xuXHRcdGlmICghdGhpcy5wZW5kaW5nTmF2aWdhdGUgJiYgcGF0aCA9PT0gdGhpcy5hY3RpdmVQYXRoKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnQWxyZWFkeSBhdCBkZXN0aW5hdGlvbiwgcmVmcmVzaCBuYXZpZ2F0aW9uJyk7XG5cdFx0XHRyZXR1cm4gdGhpcy5hY3RpdmVTY3JlZW47XG5cdFx0fVxuXHRcdC8qIGpzaGludCBuZXdjYXA6IGZhbHNlICovXG5cdFx0dmFyIHNjcmVlbiA9IHRoaXMuc2NyZWVuc1twYXRoXTtcblx0XHRpZiAoIXNjcmVlbikge1xuXHRcdFx0dmFyIGhhbmRsZXIgPSByb3V0ZS5nZXRIYW5kbGVyKCk7XG5cdFx0XHRpZiAoaGFuZGxlciA9PT0gU2NyZWVuIHx8IFNjcmVlbi5pc0ltcGxlbWVudGVkQnkoaGFuZGxlci5wcm90b3R5cGUpKSB7XG5cdFx0XHRcdHNjcmVlbiA9IG5ldyBoYW5kbGVyKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzY3JlZW4gPSBoYW5kbGVyKHJvdXRlKSB8fCBuZXcgU2NyZWVuKCk7XG5cdFx0XHR9XG5cdFx0XHRjb25zb2xlLmxvZygnQ3JlYXRlIHNjcmVlbiBmb3IgWycgKyBwYXRoICsgJ10gWycgKyBzY3JlZW4gKyAnXScpO1xuXHRcdH1cblx0XHRyZXR1cm4gc2NyZWVuO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRkaXNwb3NlSW50ZXJuYWwoKSB7XG5cdFx0aWYgKHRoaXMuYWN0aXZlU2NyZWVuKSB7XG5cdFx0XHR0aGlzLnJlbW92ZVNjcmVlbih0aGlzLmFjdGl2ZVBhdGgpO1xuXHRcdH1cblx0XHR0aGlzLmNsZWFyU2NyZWVuc0NhY2hlKCk7XG5cdFx0dGhpcy5mb3JtRXZlbnRIYW5kbGVyXy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdHRoaXMubGlua0V2ZW50SGFuZGxlcl8ucmVtb3ZlTGlzdGVuZXIoKTtcblx0XHR0aGlzLmFwcEV2ZW50SGFuZGxlcnNfLnJlbW92ZUFsbExpc3RlbmVycygpO1xuXHRcdHN1cGVyLmRpc3Bvc2VJbnRlcm5hbCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc3BhdGNoZXMgdG8gdGhlIGZpcnN0IHJvdXRlIGhhbmRsZXIgdGhhdCBtYXRjaGVzIHRoZSBjdXJyZW50IHBhdGgsIGlmXG5cdCAqIGFueS5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBSZXR1cm5zIGEgcGVuZGluZyByZXF1ZXN0IGNhbmNlbGxhYmxlIHByb21pc2UuXG5cdCAqL1xuXHRkaXNwYXRjaCgpIHtcblx0XHRyZXR1cm4gdGhpcy5uYXZpZ2F0ZSh1dGlscy5nZXRDdXJyZW50QnJvd3NlclBhdGgoKSwgdHJ1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogU3RhcnRzIG5hdmlnYXRpb24gdG8gYSBwYXRoLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfcmVwbGFjZUhpc3RvcnkgUmVwbGFjZXMgYnJvd3NlciBoaXN0b3J5LlxuXHQgKiBAcmV0dXJuIHtDYW5jZWxsYWJsZVByb21pc2V9IFJldHVybnMgYSBwZW5kaW5nIHJlcXVlc3QgY2FuY2VsbGFibGUgcHJvbWlzZS5cblx0ICovXG5cdGRvTmF2aWdhdGVfKHBhdGgsIG9wdF9yZXBsYWNlSGlzdG9yeSkge1xuXHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbiAmJiB0aGlzLmFjdGl2ZVNjcmVlbi5iZWZvcmVEZWFjdGl2YXRlKCkpIHtcblx0XHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gQ2FuY2VsbGFibGVQcm9taXNlLnJlamVjdChuZXcgQ2FuY2VsbGFibGVQcm9taXNlLkNhbmNlbGxhdGlvbkVycm9yKCdDYW5jZWxsZWQgYnkgYWN0aXZlIHNjcmVlbicpKTtcblx0XHRcdHJldHVybiB0aGlzLnBlbmRpbmdOYXZpZ2F0ZTtcblx0XHR9XG5cblx0XHR2YXIgcm91dGUgPSB0aGlzLmZpbmRSb3V0ZShwYXRoKTtcblx0XHRpZiAoIXJvdXRlKSB7XG5cdFx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZSA9IENhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcignTm8gcm91dGUgZm9yICcgKyBwYXRoKSk7XG5cdFx0XHRyZXR1cm4gdGhpcy5wZW5kaW5nTmF2aWdhdGU7XG5cdFx0fVxuXG5cdFx0Y29uc29sZS5sb2coJ05hdmlnYXRlIHRvIFsnICsgcGF0aCArICddJyk7XG5cblx0XHR0aGlzLnN0b3BQZW5kaW5nTmF2aWdhdGVfKCk7XG5cdFx0dGhpcy5pc05hdmlnYXRpb25QZW5kaW5nID0gdHJ1ZTtcblxuXHRcdHZhciBuZXh0U2NyZWVuID0gdGhpcy5jcmVhdGVTY3JlZW5JbnN0YW5jZShwYXRoLCByb3V0ZSk7XG5cblx0XHRyZXR1cm4gbmV4dFNjcmVlbi5sb2FkKHBhdGgpXG5cdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbikge1xuXHRcdFx0XHRcdHRoaXMuYWN0aXZlU2NyZWVuLmRlYWN0aXZhdGUoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLnByZXBhcmVOYXZpZ2F0ZUhpc3RvcnlfKHBhdGgsIG5leHRTY3JlZW4sIG9wdF9yZXBsYWNlSGlzdG9yeSk7XG5cdFx0XHRcdHRoaXMucHJlcGFyZU5hdmlnYXRlU3VyZmFjZXNfKFxuXHRcdFx0XHRcdG5leHRTY3JlZW4sXG5cdFx0XHRcdFx0dGhpcy5zdXJmYWNlcyxcblx0XHRcdFx0XHR0aGlzLmV4dHJhY3RQYXJhbXMocm91dGUsIHBhdGgpXG5cdFx0XHRcdCk7XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW4oKCkgPT4gbmV4dFNjcmVlbi5ldmFsdWF0ZVN0eWxlcyh0aGlzLnN1cmZhY2VzKSlcblx0XHRcdC50aGVuKCgpID0+IG5leHRTY3JlZW4uZmxpcCh0aGlzLnN1cmZhY2VzKSlcblx0XHRcdC50aGVuKCgpID0+IG5leHRTY3JlZW4uZXZhbHVhdGVTY3JpcHRzKHRoaXMuc3VyZmFjZXMpKVxuXHRcdFx0LnRoZW4oKCkgPT4gdGhpcy5tYXliZVVwZGF0ZVNjcm9sbFBvc2l0aW9uU3RhdGVfKCkpXG5cdFx0XHQudGhlbigoKSA9PiB0aGlzLnN5bmNTY3JvbGxQb3NpdGlvblN5bmNUaGVuQXN5bmNfKCkpXG5cdFx0XHQudGhlbigoKSA9PiB0aGlzLmZpbmFsaXplTmF2aWdhdGVfKHBhdGgsIG5leHRTY3JlZW4pKVxuXHRcdFx0LnRoZW4oKCkgPT4gdGhpcy5tYXliZU92ZXJsb2FkQmVmb3JlVW5sb2FkXygpKVxuXHRcdFx0LmNhdGNoKChyZWFzb24pID0+IHtcblx0XHRcdFx0dGhpcy5pc05hdmlnYXRpb25QZW5kaW5nID0gZmFsc2U7XG5cdFx0XHRcdHRoaXMuaGFuZGxlTmF2aWdhdGVFcnJvcl8ocGF0aCwgbmV4dFNjcmVlbiwgcmVhc29uKTtcblx0XHRcdFx0dGhyb3cgcmVhc29uO1xuXHRcdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogRXh0cmFjdHMgcGFyYW1zIGFjY29yZGluZyB0byB0aGUgZ2l2ZW4gcGF0aCBhbmQgcm91dGUuXG5cdCAqIEBwYXJhbSB7IVJvdXRlfSByb3V0ZVxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcGF0aFxuXHQgKiBAcGFyYW0geyFPYmplY3R9XG5cdCAqL1xuXHRleHRyYWN0UGFyYW1zKHJvdXRlLCBwYXRoKSB7XG5cdFx0cmV0dXJuIHJvdXRlLmV4dHJhY3RQYXJhbXModGhpcy5nZXRSb3V0ZVBhdGgocGF0aCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpbmFsaXplcyBhIHNjcmVlbiBuYXZpZ2F0aW9uLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcGFyYW0geyFTY3JlZW59IG5leHRTY3JlZW5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0ZmluYWxpemVOYXZpZ2F0ZV8ocGF0aCwgbmV4dFNjcmVlbikge1xuXHRcdG5leHRTY3JlZW4uYWN0aXZhdGUoKTtcblxuXHRcdGlmICh0aGlzLmFjdGl2ZVNjcmVlbiAmJiAhdGhpcy5hY3RpdmVTY3JlZW4uaXNDYWNoZWFibGUoKSkge1xuXHRcdFx0aWYgKHRoaXMuYWN0aXZlU2NyZWVuICE9PSBuZXh0U2NyZWVuKSB7XG5cdFx0XHRcdHRoaXMucmVtb3ZlU2NyZWVuKHRoaXMuYWN0aXZlUGF0aCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5hY3RpdmVQYXRoID0gcGF0aDtcblx0XHR0aGlzLmFjdGl2ZVNjcmVlbiA9IG5leHRTY3JlZW47XG5cdFx0dGhpcy5icm93c2VyUGF0aEJlZm9yZU5hdmlnYXRlID0gdXRpbHMuZ2V0Q3VycmVudEJyb3dzZXJQYXRoV2l0aG91dEhhc2goKTtcblx0XHR0aGlzLnNjcmVlbnNbcGF0aF0gPSBuZXh0U2NyZWVuO1xuXHRcdHRoaXMuaXNOYXZpZ2F0aW9uUGVuZGluZyA9IGZhbHNlO1xuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlID0gbnVsbDtcblx0XHRnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQgPSBudWxsO1xuXHRcdGdsb2JhbHMuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCA9IG51bGw7XG5cdFx0Y29uc29sZS5sb2coJ05hdmlnYXRpb24gZG9uZScpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpbmRzIGEgcm91dGUgZm9yIHRoZSB0ZXN0IHBhdGguIFJldHVybnMgdHJ1ZSBpZiBtYXRjaGVzIGhhcyBhIHJvdXRlLFxuXHQgKiBvdGhlcndpc2UgcmV0dXJucyBudWxsLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcmV0dXJuIHs/T2JqZWN0fSBSb3V0ZSBoYW5kbGVyIGlmIG1hdGNoIGFueSBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiB0aGVcblx0ICogICAgIHBhdGggaXMgdGhlIHNhbWUgYXMgdGhlIGN1cnJlbnQgdXJsIGFuZCB0aGUgcGF0aCBjb250YWlucyBhIGZyYWdtZW50LlxuXHQgKi9cblx0ZmluZFJvdXRlKHBhdGgpIHtcblx0XHRwYXRoID0gdGhpcy5nZXRSb3V0ZVBhdGgocGF0aCk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnJvdXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIHJvdXRlID0gdGhpcy5yb3V0ZXNbaV07XG5cdFx0XHRpZiAocm91dGUubWF0Y2hlc1BhdGgocGF0aCkpIHtcblx0XHRcdFx0cmV0dXJuIHJvdXRlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYWxsb3cgcHJldmVudCBuYXZpZ2F0ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldEFsbG93UHJldmVudE5hdmlnYXRlKCkge1xuXHRcdHJldHVybiB0aGlzLmFsbG93UHJldmVudE5hdmlnYXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgbGluayBiYXNlIHBhdGguXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqL1xuXHRnZXRCYXNlUGF0aCgpIHtcblx0XHRyZXR1cm4gdGhpcy5iYXNlUGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBkZWZhdWx0IHBhZ2UgdGl0bGUuXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gZGVmYXVsdFRpdGxlXG5cdCAqL1xuXHRnZXREZWZhdWx0VGl0bGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZGVmYXVsdFRpdGxlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGZvcm0gc2VsZWN0b3IuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqL1xuXHRnZXRGb3JtU2VsZWN0b3IoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZm9ybVNlbGVjdG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrIGlmIHJvdXRlIG1hdGNoaW5nIGlzIGlnbm9yaW5nIHF1ZXJ5IHN0cmluZyBmcm9tIHRoZSByb3V0ZSBwYXRoLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0Z2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKCkge1xuXHRcdHJldHVybiB0aGlzLmlnbm9yZVF1ZXJ5U3RyaW5nRnJvbVJvdXRlUGF0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBsaW5rIHNlbGVjdG9yLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfVxuXHQgKi9cblx0Z2V0TGlua1NlbGVjdG9yKCkge1xuXHRcdHJldHVybiB0aGlzLmxpbmtTZWxlY3Rvcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBsb2FkaW5nIGNzcyBjbGFzcy5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICovXG5cdGdldExvYWRpbmdDc3NDbGFzcygpIHtcblx0XHRyZXR1cm4gdGhpcy5sb2FkaW5nQ3NzQ2xhc3M7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgZ2l2ZW4gcGF0aCBmb3JtYXR0ZWQgdG8gYmUgbWF0Y2hlZCBieSBhIHJvdXRlLiBUaGlzIHdpbGwsXG5cdCAqIGZvciBleGFtcGxlLCByZW1vdmUgdGhlIGJhc2UgcGF0aCBmcm9tIGl0LCBidXQgbWFrZSBzdXJlIGl0IHdpbGwgZW5kXG5cdCAqIHdpdGggYSAnLycuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdGdldFJvdXRlUGF0aChwYXRoKSB7XG5cdFx0aWYgKHRoaXMuZ2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKCkpIHtcblx0XHRcdHBhdGggPSB1dGlscy5nZXRVcmxQYXRoV2l0aG91dEhhc2hBbmRTZWFyY2gocGF0aCk7XG5cdFx0XHRyZXR1cm4gdXRpbHMuZ2V0VXJsUGF0aFdpdGhvdXRIYXNoQW5kU2VhcmNoKHBhdGguc3Vic3RyKHRoaXMuYmFzZVBhdGgubGVuZ3RoKSk7XG5cdFx0fVxuXG5cdFx0cGF0aCA9IHV0aWxzLmdldFVybFBhdGhXaXRob3V0SGFzaChwYXRoKTtcblx0XHRyZXR1cm4gdXRpbHMuZ2V0VXJsUGF0aFdpdGhvdXRIYXNoKHBhdGguc3Vic3RyKHRoaXMuYmFzZVBhdGgubGVuZ3RoKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgdXBkYXRlIHNjcm9sbCBwb3NpdGlvbiB2YWx1ZS5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGdldFVwZGF0ZVNjcm9sbFBvc2l0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLnVwZGF0ZVNjcm9sbFBvc2l0aW9uO1xuXHR9XG5cblx0LyoqXG5cdCAqIEhhbmRsZSBuYXZpZ2F0aW9uIGVycm9yLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHBhdGggUGF0aCBjb250YWluaW5nIHRoZSBxdWVyeXN0cmluZyBwYXJ0LlxuXHQgKiBAcGFyYW0geyFTY3JlZW59IG5leHRTY3JlZW5cblx0ICogQHBhcmFtIHshRXJyb3J9IGVycm9yXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGhhbmRsZU5hdmlnYXRlRXJyb3JfKHBhdGgsIG5leHRTY3JlZW4sIGVycm9yKSB7XG5cdFx0Y29uc29sZS5sb2coJ05hdmlnYXRpb24gZXJyb3IgZm9yIFsnICsgbmV4dFNjcmVlbiArICddICgnICsgZXJyb3IgKyAnKScpO1xuXHRcdHRoaXMuZW1pdCgnbmF2aWdhdGlvbkVycm9yJywge1xuXHRcdFx0ZXJyb3IsXG5cdFx0XHRuZXh0U2NyZWVuLFxuXHRcdFx0cGF0aFxuXHRcdH0pO1xuXHRcdGlmICghdXRpbHMuaXNDdXJyZW50QnJvd3NlclBhdGgocGF0aCkpIHtcblx0XHRcdGlmICh0aGlzLmlzTmF2aWdhdGlvblBlbmRpbmcgJiYgdGhpcy5wZW5kaW5nTmF2aWdhdGUpIHtcblx0XHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUudGhlbkFsd2F5cygoKSA9PiB0aGlzLnJlbW92ZVNjcmVlbihwYXRoKSwgdGhpcyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnJlbW92ZVNjcmVlbihwYXRoKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIGFwcCBoYXMgcm91dGVzLlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0aGFzUm91dGVzKCkge1xuXHRcdHJldHVybiB0aGlzLnJvdXRlcy5sZW5ndGggPiAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRlc3RzIGlmIGhvc3RuYW1lIGlzIGFuIG9mZnNpdGUgbGluay5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBob3N0bmFtZSBMaW5rIGhvc3RuYW1lIHRvIGNvbXBhcmUgd2l0aFxuXHQgKiAgICAgPGNvZGU+Z2xvYmFscy53aW5kb3cubG9jYXRpb24uaG9zdG5hbWU8L2NvZGU+LlxuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRpc0xpbmtTYW1lT3JpZ2luXyhob3N0bmFtZSkge1xuXHRcdHJldHVybiBob3N0bmFtZSA9PT0gZ2xvYmFscy53aW5kb3cubG9jYXRpb24uaG9zdG5hbWU7XG5cdH1cblxuXHQvKipcblx0ICogVGVzdHMgaWYgbGluayBlbGVtZW50IGhhcyB0aGUgc2FtZSBhcHAncyBiYXNlIHBhdGguXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBMaW5rIHBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0aXNTYW1lQmFzZVBhdGhfKHBhdGgpIHtcblx0XHRyZXR1cm4gcGF0aC5pbmRleE9mKHRoaXMuYmFzZVBhdGgpID09PSAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIExvY2sgdGhlIGRvY3VtZW50IHNjcm9sbCBpbiBvcmRlciB0byBhdm9pZCB0aGUgYnJvd3NlciBuYXRpdmUgYmFjayBhbmRcblx0ICogZm9yd2FyZCBuYXZpZ2F0aW9uIHRvIGNoYW5nZSB0aGUgc2Nyb2xsIHBvc2l0aW9uLiBJbiB0aGUgZW5kIG9mXG5cdCAqIG5hdmlnYXRpb24gbGlmZWN5Y2xlIHNjcm9sbCBpcyByZXBvc2l0aW9uZWQuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGxvY2tIaXN0b3J5U2Nyb2xsUG9zaXRpb25fKCkge1xuXHRcdHZhciBzdGF0ZSA9IGdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc3RhdGU7XG5cdFx0aWYgKCFzdGF0ZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvLyBCcm93c2VycyBhcmUgaW5jb25zaXN0ZW50IHdoZW4gcmUtcG9zaXRpb25pbmcgdGhlIHNjcm9sbCBoaXN0b3J5IG9uXG5cdFx0Ly8gcG9wc3RhdGUuIEF0IHNvbWUgYnJvd3NlcnMsIGhpc3Rvcnkgc2Nyb2xsIGhhcHBlbnMgYmVmb3JlIHBvcHN0YXRlLCB0aGVuXG5cdFx0Ly8gbG9jayB0aGUgc2Nyb2xsIG9uIHRoZSBsYXN0IGtub3duIHBvc2l0aW9uIGFzIHNvb24gYXMgcG9zc2libGUgYWZ0ZXIgdGhlXG5cdFx0Ly8gY3VycmVudCBKUyBleGVjdXRpb24gY29udGV4dCBhbmQgY2FwdHVyZSB0aGUgY3VycmVudCB2YWx1ZS4gU29tZSBvdGhlcnMsXG5cdFx0Ly8gaGlzdG9yeSBzY3JvbGwgaGFwcGVucyBhZnRlciBwb3BzdGF0ZSwgaW4gdGhpcyBjYXNlLCB3ZSBiaW5kIGFuIG9uY2Vcblx0XHQvLyBzY3JvbGwgZXZlbnQgdG8gbG9jayB0aGUgbGFzIGtub3duIHBvc2l0aW9uLiBMYXN0bHksIHRoZSBwcmV2aW91cyB0d29cblx0XHQvLyBiZWhhdmlvcnMgY2FuIGhhcHBlbiBldmVuIG9uIHRoZSBzYW1lIGJyb3dzZXIsIGhlbmNlIHRoZSByYWNlIHdpbGwgZGVjaWRlXG5cdFx0Ly8gdGhlIHdpbm5lci5cblx0XHR2YXIgd2lubmVyID0gZmFsc2U7XG5cdFx0dmFyIHN3aXRjaFNjcm9sbFBvc2l0aW9uUmFjZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0Z2xvYmFscy5kb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBzd2l0Y2hTY3JvbGxQb3NpdGlvblJhY2UsIGZhbHNlKTtcblx0XHRcdGlmICghd2lubmVyKSB7XG5cdFx0XHRcdGdsb2JhbHMud2luZG93LnNjcm9sbFRvKHN0YXRlLnNjcm9sbExlZnQsIHN0YXRlLnNjcm9sbFRvcCk7XG5cdFx0XHRcdHdpbm5lciA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRhc3luYy5uZXh0VGljayhzd2l0Y2hTY3JvbGxQb3NpdGlvblJhY2UpO1xuXHRcdGdsb2JhbHMuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgc3dpdGNoU2Nyb2xsUG9zaXRpb25SYWNlLCBmYWxzZSk7XG5cdH1cblxuXHQvKipcblx0ICogSWYgc3VwcG9ydGVkIGJ5IHRoZSBicm93c2VyLCBkaXNhYmxlcyBuYXRpdmUgc2Nyb2xsIHJlc3RvcmF0aW9uIGFuZFxuXHQgKiBzdG9yZXMgY3VycmVudCB2YWx1ZS5cblx0ICovXG5cdG1heWJlRGlzYWJsZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uKCkge1xuXHRcdGlmICh0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uU3VwcG9ydGVkKSB7XG5cdFx0XHR0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uXyA9IGdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc2Nyb2xsUmVzdG9yYXRpb247XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uID0gJ21hbnVhbCc7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIG5hdmlnYXRlIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGhyZWYgSW5mb3JtYXRpb24gYWJvdXQgdGhlIGxpbmsncyBocmVmLlxuXHQgKiBAcGFyYW0ge0V2ZW50fSBldmVudCBEb20gZXZlbnQgdGhhdCBpbml0aWF0ZWQgdGhlIG5hdmlnYXRpb24uXG5cdCAqL1xuXHRtYXliZU5hdmlnYXRlXyhocmVmLCBldmVudCkge1xuXHRcdGlmICghdGhpcy5jYW5OYXZpZ2F0ZShocmVmKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGdsb2JhbHMuY2FwdHVyZWRGb3JtRWxlbWVudCA9IGV2ZW50LmNhcHR1cmVkRm9ybUVsZW1lbnQ7XG5cdFx0Z2xvYmFscy5jYXB0dXJlZEZvcm1CdXR0b25FbGVtZW50ID0gZXZlbnQuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudDtcblxuXHRcdHZhciBuYXZpZ2F0ZUZhaWxlZCA9IGZhbHNlO1xuXHRcdHRyeSB7XG5cdFx0XHR0aGlzLm5hdmlnYXRlKHV0aWxzLmdldFVybFBhdGgoaHJlZiksIGZhbHNlLCBldmVudCk7XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHQvLyBEbyBub3QgcHJldmVudCBsaW5rIG5hdmlnYXRpb24gaW4gY2FzZSBzb21lIHN5bmNocm9ub3VzIGVycm9yIG9jY3Vyc1xuXHRcdFx0bmF2aWdhdGVGYWlsZWQgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICghbmF2aWdhdGVGYWlsZWQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyB3aGV0aGVyIHRoZSBvbmJlZm9yZXVubG9hZCBnbG9iYWwgZXZlbnQgaGFuZGxlciBpcyBvdmVybG9hZGVkXG5cdCAqIGJ5IGNsaWVudCBjb2RlLiBJZiBzbywgaXQgcmVwbGFjZXMgd2l0aCBhIGZ1bmN0aW9uIHRoYXQgaGFsdHMgdGhlIG5vcm1hbFxuXHQgKiBldmVudCBmbG93IGluIHJlbGF0aW9uIHdpdGggdGhlIGNsaWVudCBvbmJlZm9yZXVubG9hZCBmdW5jdGlvbi5cblx0ICogVGhpcyBjYW4gYmUgaW4gbW9zdCBwYXJ0IHVzZWQgdG8gcHJlbWF0dXJlbHkgdGVybWluYXRlIG5hdmlnYXRpb24gdG8gb3RoZXIgcGFnZXNcblx0ICogYWNjb3JkaW5nIHRvIHRoZSBnaXZlbiBjb25zdHJhaXQocykuIFxuXHQgKiBAcHJvdGVjdGVkIFxuXHQgKi9cblx0bWF5YmVPdmVybG9hZEJlZm9yZVVubG9hZF8oKSB7XG5cdFx0aWYgKCdmdW5jdGlvbicgPT09IHR5cGVvZiB3aW5kb3cub25iZWZvcmV1bmxvYWQpIHtcblx0XHRcdHdpbmRvdy5fb25iZWZvcmV1bmxvYWQgPSB3aW5kb3cub25iZWZvcmV1bmxvYWQ7XG5cblx0XHRcdHdpbmRvdy5vbmJlZm9yZXVubG9hZCA9IGV2ZW50ID0+IHtcblx0XHRcdFx0dGhpcy5lbWl0KCdiZWZvcmVVbmxvYWQnLCBldmVudCk7XG5cdFx0XHRcdGlmIChldmVudCAmJiBldmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cblx0XHRcdC8vIG1hcmsgdGhlIHVwZGF0ZWQgaGFuZGxlciBkdWUgdW53YW50ZWQgcmVjdXJzaW9uIFxuXHRcdFx0d2luZG93Lm9uYmVmb3JldW5sb2FkLl9vdmVybG9hZGVkID0gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogTWF5YmUgcmVwb3NpdGlvbiBzY3JvbGwgdG8gaGFzaGVkIGFuY2hvci5cblx0ICovXG5cdG1heWJlUmVwb3NpdGlvblNjcm9sbFRvSGFzaGVkQW5jaG9yKCkge1xuXHRcdGNvbnN0IGhhc2ggPSBnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5oYXNoO1xuXHRcdGlmIChoYXNoKSB7XG5cdFx0XHRsZXQgYW5jaG9yRWxlbWVudCA9IGdsb2JhbHMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaGFzaC5zdWJzdHJpbmcoMSkpO1xuXHRcdFx0aWYgKGFuY2hvckVsZW1lbnQpIHtcblx0XHRcdFx0Y29uc3Qge29mZnNldExlZnQsIG9mZnNldFRvcH0gPSB1dGlscy5nZXROb2RlT2Zmc2V0KGFuY2hvckVsZW1lbnQpO1xuXHRcdFx0XHRnbG9iYWxzLndpbmRvdy5zY3JvbGxUbyhvZmZzZXRMZWZ0LCBvZmZzZXRUb3ApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBJZiBzdXBwb3J0ZWQgYnkgdGhlIGJyb3dzZXIsIHJlc3RvcmVzIG5hdGl2ZSBzY3JvbGwgcmVzdG9yYXRpb24gdG8gdGhlXG5cdCAqIHZhbHVlIGNhcHR1cmVkIGJ5IGBtYXliZURpc2FibGVOYXRpdmVTY3JvbGxSZXN0b3JhdGlvbmAuXG5cdCAqL1xuXHRtYXliZVJlc3RvcmVOYXRpdmVTY3JvbGxSZXN0b3JhdGlvbigpIHtcblx0XHRpZiAodGhpcy5uYXRpdmVTY3JvbGxSZXN0b3JhdGlvblN1cHBvcnRlZCAmJiB0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uXykge1xuXHRcdFx0Z2xvYmFscy53aW5kb3cuaGlzdG9yeS5zY3JvbGxSZXN0b3JhdGlvbiA9IHRoaXMubmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25fO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYXliZSByZXN0b3JlIHJlZGlyZWN0ZWQgcGF0aCBoYXNoIGluIGNhc2UgYm90aCB0aGUgY3VycmVudCBwYXRoIGFuZFxuXHQgKiB0aGUgZ2l2ZW4gcGF0aCBhcmUgdGhlIHNhbWUuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIGJlZm9yZSBuYXZpZ2F0aW9uLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHJlZGlyZWN0UGF0aCBQYXRoIGFmdGVyIG5hdmlnYXRpb24uXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gaGFzaCBIYXNoIHRvIGJlIGFkZGVkIHRvIHRoZSBwYXRoLlxuXHQgKiBAcmV0dXJuIHshc3RyaW5nfSBSZXR1cm5zIHRoZSBwYXRoIHdpdGggdGhlIGhhc2ggcmVzdG9yZWQuXG5cdCAqL1xuXHRtYXliZVJlc3RvcmVSZWRpcmVjdFBhdGhIYXNoXyhwYXRoLCByZWRpcmVjdFBhdGgsIGhhc2gpIHtcblx0XHRpZiAocmVkaXJlY3RQYXRoID09PSB1dGlscy5nZXRVcmxQYXRoV2l0aG91dEhhc2gocGF0aCkpIHtcblx0XHRcdHJldHVybiByZWRpcmVjdFBhdGggKyBoYXNoO1xuXHRcdH1cblx0XHRyZXR1cm4gcmVkaXJlY3RQYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHVwZGF0ZSBzY3JvbGwgcG9zaXRpb24gaW4gaGlzdG9yeSBzdGF0ZSB0byBhbmNob3Igb24gcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyBhbmNob3Jcblx0ICovXG5cdG1heWJlVXBkYXRlU2Nyb2xsUG9zaXRpb25TdGF0ZV8oKSB7XG5cdFx0dmFyIGhhc2ggPSBnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5oYXNoO1xuXHRcdHZhciBhbmNob3JFbGVtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChoYXNoLnN1YnN0cmluZygxKSk7XG5cdFx0aWYgKGFuY2hvckVsZW1lbnQpIHtcblx0XHRcdGNvbnN0IHtvZmZzZXRMZWZ0LCBvZmZzZXRUb3B9ID0gdXRpbHMuZ2V0Tm9kZU9mZnNldChhbmNob3JFbGVtZW50KTtcblx0XHRcdHRoaXMuc2F2ZUhpc3RvcnlDdXJyZW50UGFnZVNjcm9sbFBvc2l0aW9uXyhvZmZzZXRUb3AsIG9mZnNldExlZnQpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBOYXZpZ2F0ZXMgdG8gdGhlIHNwZWNpZmllZCBwYXRoIGlmIHRoZXJlIGlzIGEgcm91dGUgaGFuZGxlciB0aGF0IG1hdGNoZXMuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIHRvIG5hdmlnYXRlIGNvbnRhaW5pbmcgdGhlIGJhc2UgcGF0aC5cblx0ICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3JlcGxhY2VIaXN0b3J5IFJlcGxhY2VzIGJyb3dzZXIgaGlzdG9yeS5cblx0ICogQHBhcmFtIHtFdmVudD19IGV2ZW50IE9wdGlvbmFsIGV2ZW50IG9iamVjdCB0aGF0IHRyaWdnZXJlZCB0aGUgbmF2aWdhdGlvbi5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBSZXR1cm5zIGEgcGVuZGluZyByZXF1ZXN0IGNhbmNlbGxhYmxlIHByb21pc2UuXG5cdCAqL1xuXHRuYXZpZ2F0ZShwYXRoLCBvcHRfcmVwbGFjZUhpc3RvcnksIG9wdF9ldmVudCkge1xuXHRcdGlmICghdXRpbHMuaXNIdG1sNUhpc3RvcnlTdXBwb3J0ZWQoKSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdIVE1MNSBIaXN0b3J5IGlzIG5vdCBzdXBwb3J0ZWQuIFNlbm5hIHdpbGwgbm90IGludGVyY2VwdCBuYXZpZ2F0aW9uLicpO1xuXHRcdH1cblxuXHRcdC8vIFdoZW4gcmVsb2FkaW5nIHRoZSBzYW1lIHBhdGggZG8gcmVwbGFjZVN0YXRlIGluc3RlYWQgb2YgcHVzaFN0YXRlIHRvXG5cdFx0Ly8gYXZvaWQgcG9sbHV0aW5nIGhpc3Rvcnkgd2l0aCBzdGF0ZXMgd2l0aCB0aGUgc2FtZSBwYXRoLlxuXHRcdGlmIChwYXRoID09PSB0aGlzLmFjdGl2ZVBhdGgpIHtcblx0XHRcdG9wdF9yZXBsYWNlSGlzdG9yeSA9IHRydWU7XG5cdFx0fVxuXG5cdFx0dGhpcy5lbWl0KCdiZWZvcmVOYXZpZ2F0ZScsIHtcblx0XHRcdGV2ZW50OiBvcHRfZXZlbnQsXG5cdFx0XHRwYXRoOiBwYXRoLFxuXHRcdFx0cmVwbGFjZUhpc3Rvcnk6ICEhb3B0X3JlcGxhY2VIaXN0b3J5XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gdGhpcy5wZW5kaW5nTmF2aWdhdGU7XG5cdH1cblxuXHQvKipcblx0ICogQmVmb3JlcyBuYXZpZ2F0aW9uIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IEV2ZW50IGZhY2FkZSBjb250YWluaW5nIDxjb2RlPnBhdGg8L2NvZGU+IGFuZFxuXHQgKiAgICAgPGNvZGU+cmVwbGFjZUhpc3Rvcnk8L2NvZGU+LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvbkJlZm9yZU5hdmlnYXRlXyhldmVudCkge1xuXHRcdGlmIChnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQpIHtcblx0XHRcdGV2ZW50LmZvcm0gPSBnbG9iYWxzLmNhcHR1cmVkRm9ybUVsZW1lbnQ7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEJlZm9yZXMgbmF2aWdhdGlvbiB0byBhIHBhdGguIFJ1bnMgYWZ0ZXIgZXh0ZXJuYWwgbGlzdGVuZXJzLlxuXHQgKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgRXZlbnQgZmFjYWRlIGNvbnRhaW5pbmcgPGNvZGU+cGF0aDwvY29kZT4gYW5kXG5cdCAqICAgICA8Y29kZT5yZXBsYWNlSGlzdG9yeTwvY29kZT4uXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG9uQmVmb3JlTmF2aWdhdGVEZWZhdWx0XyhldmVudCkge1xuXHRcdGlmICh0aGlzLnBlbmRpbmdOYXZpZ2F0ZSkge1xuXHRcdFx0aWYgKHRoaXMucGVuZGluZ05hdmlnYXRlLnBhdGggPT09IGV2ZW50LnBhdGgpIHtcblx0XHRcdFx0Y29uc29sZS5sb2coJ1dhaXRpbmcuLi4nKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuZW1pdCgnYmVmb3JlVW5sb2FkJywgZXZlbnQpO1xuXG5cdFx0dGhpcy5lbWl0KCdzdGFydE5hdmlnYXRlJywge1xuXHRcdFx0Zm9ybTogZXZlbnQuZm9ybSxcblx0XHRcdHBhdGg6IGV2ZW50LnBhdGgsXG5cdFx0XHRyZXBsYWNlSGlzdG9yeTogZXZlbnQucmVwbGFjZUhpc3Rvcnlcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDdXN0b20gZXZlbnQgaGFuZGxlciB0aGF0IGV4ZWN1dGVzIHRoZSBvcmlnaW5hbCBsaXN0ZW5lciB0aGF0IGhhcyBiZWVuXG5cdCAqIGFkZGVkIGJ5IHRoZSBjbGllbnQgY29kZSBhbmQgdGVybWluYXRlcyB0aGUgbmF2aWdhdGlvbiBhY2NvcmRpbmdseS5cblx0ICogQHBhcmFtIHshRXZlbnR9IGV2ZW50IG9yaWdpbmFsIEV2ZW50IGZhY2FkZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0b25CZWZvcmVVbmxvYWREZWZhdWx0XyhldmVudCkge1xuXHRcdHZhciBmdW5jID0gd2luZG93Ll9vbmJlZm9yZXVubG9hZDtcblx0XHRpZiAoZnVuYyAmJiAhZnVuYy5fb3ZlcmxvYWRlZCAmJiBmdW5jKCkpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEludGVyY2VwdHMgZG9jdW1lbnQgY2xpY2tzIGFuZCB0ZXN0IGxpbmsgZWxlbWVudHMgaW4gb3JkZXIgdG8gZGVjaWRlXG5cdCAqIHdoZXRoZXIgU3VyZmFjZSBhcHAgY2FuIG5hdmlnYXRlLlxuXHQgKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgRXZlbnQgZmFjYWRlXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG9uRG9jQ2xpY2tEZWxlZ2F0ZV8oZXZlbnQpIHtcblx0XHRpZiAoZXZlbnQuYWx0S2V5IHx8IGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQubWV0YUtleSB8fCBldmVudC5zaGlmdEtleSB8fCBldmVudC5idXR0b24pIHtcblx0XHRcdGNvbnNvbGUubG9nKCdOYXZpZ2F0ZSBhYm9ydGVkLCBpbnZhbGlkIG1vdXNlIGJ1dHRvbiBvciBtb2RpZmllciBrZXkgcHJlc3NlZC4nKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5tYXliZU5hdmlnYXRlXyhldmVudC5kZWxlZ2F0ZVRhcmdldC5ocmVmLCBldmVudCk7XG5cdH1cblxuXHQvKipcblx0ICogSW50ZXJjZXB0cyBkb2N1bWVudCBmb3JtIHN1Ym1pdHMgYW5kIHRlc3QgYWN0aW9uIHBhdGggaW4gb3JkZXIgdG8gZGVjaWRlXG5cdCAqIHdoZXRoZXIgU3VyZmFjZSBhcHAgY2FuIG5hdmlnYXRlLlxuXHQgKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgRXZlbnQgZmFjYWRlXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG9uRG9jU3VibWl0RGVsZWdhdGVfKGV2ZW50KSB7XG5cdFx0dmFyIGZvcm0gPSBldmVudC5kZWxlZ2F0ZVRhcmdldDtcblx0XHRpZiAoZm9ybS5tZXRob2QgPT09ICdnZXQnKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnR0VUIG1ldGhvZCBub3Qgc3VwcG9ydGVkJyk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGV2ZW50LmNhcHR1cmVkRm9ybUVsZW1lbnQgPSBmb3JtO1xuXHRcdGNvbnN0IGJ1dHRvblNlbGVjdG9yID0gJ2J1dHRvbjpub3QoW3R5cGVdKSxidXR0b25bdHlwZT1zdWJtaXRdLGlucHV0W3R5cGU9c3VibWl0XSc7XG5cdFx0aWYgKG1hdGNoKGdsb2JhbHMuZG9jdW1lbnQuYWN0aXZlRWxlbWVudCwgYnV0dG9uU2VsZWN0b3IpKSB7XG5cdFx0XHRldmVudC5jYXB0dXJlZEZvcm1CdXR0b25FbGVtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5hY3RpdmVFbGVtZW50O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRldmVudC5jYXB0dXJlZEZvcm1CdXR0b25FbGVtZW50ID0gZm9ybS5xdWVyeVNlbGVjdG9yKGJ1dHRvblNlbGVjdG9yKTtcblx0XHR9XG5cdFx0dGhpcy5tYXliZU5hdmlnYXRlXyhmb3JtLmFjdGlvbiwgZXZlbnQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIExpc3RlbnMgdG8gdGhlIHdpbmRvdydzIGxvYWQgZXZlbnQgaW4gb3JkZXIgdG8gYXZvaWQgaXNzdWVzIHdpdGggc29tZSBicm93c2Vyc1xuXHQgKiB0aGF0IHRyaWdnZXIgcG9wc3RhdGUgY2FsbHMgb24gdGhlIGZpcnN0IGxvYWQuIEZvciBtb3JlIGluZm9ybWF0aW9uIHNlZVxuXHQgKiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY0MjE3NjkvcG9wc3RhdGUtb24tcGFnZXMtbG9hZC1pbi1jaHJvbWUuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG9uTG9hZF8oKSB7XG5cdFx0dGhpcy5za2lwTG9hZFBvcHN0YXRlID0gdHJ1ZTtcblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdC8vIFRoZSB0aW1lb3V0IGVuc3VyZXMgdGhhdCBwb3BzdGF0ZSBldmVudHMgd2lsbCBiZSB1bmJsb2NrZWQgcmlnaHRcblx0XHRcdC8vIGFmdGVyIHRoZSBsb2FkIGV2ZW50IG9jY3VyZWQsIGJ1dCBub3QgaW4gdGhlIHNhbWUgZXZlbnQtbG9vcCBjeWNsZS5cblx0XHRcdHRoaXMuc2tpcExvYWRQb3BzdGF0ZSA9IGZhbHNlO1xuXHRcdH0sIDApO1xuXHRcdC8vIFRyeSB0byByZXBvc2l0aW9uIHNjcm9sbCB0byB0aGUgaGFzaGVkIGFuY2hvciB3aGVuIHBhZ2UgbG9hZHMuXG5cdFx0dGhpcy5tYXliZVJlcG9zaXRpb25TY3JvbGxUb0hhc2hlZEFuY2hvcigpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEhhbmRsZXMgYnJvd3NlciBoaXN0b3J5IGNoYW5nZXMgYW5kIGZpcmVzIGFwcCdzIG5hdmlnYXRpb24gaWYgdGhlIHN0YXRlXG5cdCAqIGJlbG93cyB0byB1cy4gSWYgd2UgZGV0ZWN0IGEgcG9wc3RhdGUgYW5kIHRoZSBzdGF0ZSBpcyA8Y29kZT5udWxsPC9jb2RlPixcblx0ICogYXNzdW1lIGl0IGlzIG5hdmlnYXRpbmcgdG8gYW4gZXh0ZXJuYWwgcGFnZSBvciB0byBhIHBhZ2Ugd2UgZG9uJ3QgaGF2ZVxuXHQgKiByb3V0ZSwgdGhlbiA8Y29kZT5nbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTwvY29kZT4gaXMgaW52b2tlZCBpbiBvcmRlciB0b1xuXHQgKiByZWxvYWQgdGhlIGNvbnRlbnQgdG8gdGhlIGN1cnJlbnQgdXJsLlxuXHQgKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgRXZlbnQgZmFjYWRlXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG9uUG9wc3RhdGVfKGV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuc2tpcExvYWRQb3BzdGF0ZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIERvIG5vdCBuYXZpZ2F0ZSBpZiB0aGUgcG9wc3RhdGUgd2FzIHRyaWdnZXJlZCBieSBhIGhhc2ggY2hhbmdlLlxuXHRcdGlmICh1dGlscy5pc0N1cnJlbnRCcm93c2VyUGF0aCh0aGlzLmJyb3dzZXJQYXRoQmVmb3JlTmF2aWdhdGUpKSB7XG5cdFx0XHR0aGlzLm1heWJlUmVwb3NpdGlvblNjcm9sbFRvSGFzaGVkQW5jaG9yKCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHN0YXRlID0gZXZlbnQuc3RhdGU7XG5cblx0XHRpZiAoIXN0YXRlKSB7XG5cdFx0XHRpZiAoZ2xvYmFscy53aW5kb3cubG9jYXRpb24uaGFzaCkge1xuXHRcdFx0XHQvLyBJZiBzZW5uYSBpcyBvbiBhbiByZWRpcmVjdCBwYXRoIGFuZCBhIGhhc2ggcG9wc3RhdGUgaGFwcGVuc1xuXHRcdFx0XHQvLyB0byBhIGRpZmZlcmVudCB1cmwsIHJlbG9hZCB0aGUgYnJvd3Nlci4gVGhpcyBiZWhhdmlvciBkb2Vzbid0XG5cdFx0XHRcdC8vIHJlcXVpcmUgc2VubmEgdG8gcm91dGUgaGFzaGVkIGxpbmtzIGFuZCBpcyBjbG9zZXIgdG8gbmF0aXZlXG5cdFx0XHRcdC8vIGJyb3dzZXIgYmVoYXZpb3IuXG5cdFx0XHRcdGlmICh0aGlzLnJlZGlyZWN0UGF0aCAmJiAhdXRpbHMuaXNDdXJyZW50QnJvd3NlclBhdGgodGhpcy5yZWRpcmVjdFBhdGgpKSB7XG5cdFx0XHRcdFx0dGhpcy5yZWxvYWRQYWdlKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly8gQWx3YXlzIHRyeSB0byByZXBvc2l0aW9uIHNjcm9sbCB0byB0aGUgaGFzaGVkIGFuY2hvciB3aGVuXG5cdFx0XHRcdC8vIGhhc2ggcG9wc3RhdGUgaGFwcGVucy5cblx0XHRcdFx0dGhpcy5tYXliZVJlcG9zaXRpb25TY3JvbGxUb0hhc2hlZEFuY2hvcigpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5yZWxvYWRQYWdlKCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKHN0YXRlLnNlbm5hKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnSGlzdG9yeSBuYXZpZ2F0aW9uIHRvIFsnICsgc3RhdGUucGF0aCArICddJyk7XG5cdFx0XHR0aGlzLnBvcHN0YXRlU2Nyb2xsVG9wID0gc3RhdGUuc2Nyb2xsVG9wO1xuXHRcdFx0dGhpcy5wb3BzdGF0ZVNjcm9sbExlZnQgPSBzdGF0ZS5zY3JvbGxMZWZ0O1xuXHRcdFx0aWYgKCF0aGlzLm5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uU3VwcG9ydGVkKSB7XG5cdFx0XHRcdHRoaXMubG9ja0hpc3RvcnlTY3JvbGxQb3NpdGlvbl8oKTtcblx0XHRcdH1cblx0XHRcdHRoaXMubmF2aWdhdGUoc3RhdGUucGF0aCwgdHJ1ZSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIExpc3RlbnMgZG9jdW1lbnQgc2Nyb2xsIGNoYW5nZXMgaW4gb3JkZXIgdG8gY2FwdHVyZSB0aGUgcG9zc2libGUgbG9ja1xuXHQgKiBzY3JvbGwgcG9zaXRpb24gZm9yIGhpc3Rvcnkgc2Nyb2xsaW5nLlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHRvblNjcm9sbF8oKSB7XG5cdFx0aWYgKHRoaXMuY2FwdHVyZVNjcm9sbFBvc2l0aW9uRnJvbVNjcm9sbEV2ZW50KSB7XG5cdFx0XHR0aGlzLnNhdmVIaXN0b3J5Q3VycmVudFBhZ2VTY3JvbGxQb3NpdGlvbl8oZ2xvYmFscy53aW5kb3cucGFnZVlPZmZzZXQsIGdsb2JhbHMud2luZG93LnBhZ2VYT2Zmc2V0KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU3RhcnRzIG5hdmlnYXRpb24gdG8gYSBwYXRoLlxuXHQgKiBAcGFyYW0geyFFdmVudH0gZXZlbnQgRXZlbnQgZmFjYWRlIGNvbnRhaW5pbmcgPGNvZGU+cGF0aDwvY29kZT4gYW5kXG5cdCAqICAgICA8Y29kZT5yZXBsYWNlSGlzdG9yeTwvY29kZT4uXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdG9uU3RhcnROYXZpZ2F0ZV8oZXZlbnQpIHtcblx0XHR0aGlzLm1heWJlRGlzYWJsZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uKCk7XG5cdFx0dGhpcy5jYXB0dXJlU2Nyb2xsUG9zaXRpb25Gcm9tU2Nyb2xsRXZlbnQgPSBmYWxzZTtcblx0XHRhZGRDbGFzc2VzKGdsb2JhbHMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCB0aGlzLmxvYWRpbmdDc3NDbGFzcyk7XG5cblx0XHR2YXIgZW5kTmF2aWdhdGVQYXlsb2FkID0ge1xuXHRcdFx0Zm9ybTogZXZlbnQuZm9ybSxcblx0XHRcdHBhdGg6IGV2ZW50LnBhdGhcblx0XHR9O1xuXG5cdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUgPSB0aGlzLmRvTmF2aWdhdGVfKGV2ZW50LnBhdGgsIGV2ZW50LnJlcGxhY2VIaXN0b3J5KVxuXHRcdFx0LmNhdGNoKChyZWFzb24pID0+IHtcblx0XHRcdFx0ZW5kTmF2aWdhdGVQYXlsb2FkLmVycm9yID0gcmVhc29uO1xuXHRcdFx0XHR0aHJvdyByZWFzb247XG5cdFx0XHR9KVxuXHRcdFx0LnRoZW5BbHdheXMoKCkgPT4ge1xuXHRcdFx0XHRpZiAoIXRoaXMucGVuZGluZ05hdmlnYXRlKSB7XG5cdFx0XHRcdFx0cmVtb3ZlQ2xhc3NlcyhnbG9iYWxzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgdGhpcy5sb2FkaW5nQ3NzQ2xhc3MpO1xuXHRcdFx0XHRcdHRoaXMubWF5YmVSZXN0b3JlTmF0aXZlU2Nyb2xsUmVzdG9yYXRpb24oKTtcblx0XHRcdFx0XHR0aGlzLmNhcHR1cmVTY3JvbGxQb3NpdGlvbkZyb21TY3JvbGxFdmVudCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5lbWl0KCdlbmROYXZpZ2F0ZScsIGVuZE5hdmlnYXRlUGF5bG9hZCk7XG5cdFx0XHR9KTtcblxuXHRcdHRoaXMucGVuZGluZ05hdmlnYXRlLnBhdGggPSBldmVudC5wYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByZWZldGNoZXMgdGhlIHNwZWNpZmllZCBwYXRoIGlmIHRoZXJlIGlzIGEgcm91dGUgaGFuZGxlciB0aGF0IG1hdGNoZXMuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gcGF0aCBQYXRoIHRvIG5hdmlnYXRlIGNvbnRhaW5pbmcgdGhlIGJhc2UgcGF0aC5cblx0ICogQHJldHVybiB7Q2FuY2VsbGFibGVQcm9taXNlfSBSZXR1cm5zIGEgcGVuZGluZyByZXF1ZXN0IGNhbmNlbGxhYmxlIHByb21pc2UuXG5cdCAqL1xuXHRwcmVmZXRjaChwYXRoKSB7XG5cdFx0dmFyIHJvdXRlID0gdGhpcy5maW5kUm91dGUocGF0aCk7XG5cdFx0aWYgKCFyb3V0ZSkge1xuXHRcdFx0cmV0dXJuIENhbmNlbGxhYmxlUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxhYmxlUHJvbWlzZS5DYW5jZWxsYXRpb25FcnJvcignTm8gcm91dGUgZm9yICcgKyBwYXRoKSk7XG5cdFx0fVxuXG5cdFx0Y29uc29sZS5sb2coJ1ByZWZldGNoaW5nIFsnICsgcGF0aCArICddJyk7XG5cblx0XHR2YXIgbmV4dFNjcmVlbiA9IHRoaXMuY3JlYXRlU2NyZWVuSW5zdGFuY2UocGF0aCwgcm91dGUpO1xuXG5cdFx0cmV0dXJuIG5leHRTY3JlZW4ubG9hZChwYXRoKVxuXHRcdFx0LnRoZW4oKCkgPT4gdGhpcy5zY3JlZW5zW3BhdGhdID0gbmV4dFNjcmVlbilcblx0XHRcdC5jYXRjaCgocmVhc29uKSA9PiB7XG5cdFx0XHRcdHRoaXMuaGFuZGxlTmF2aWdhdGVFcnJvcl8ocGF0aCwgbmV4dFNjcmVlbiwgcmVhc29uKTtcblx0XHRcdFx0dGhyb3cgcmVhc29uO1xuXHRcdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUHJlcGFyZXMgc2NyZWVuIGZsaXAuIFVwZGF0ZXMgaGlzdG9yeSBzdGF0ZSBhbmQgc3VyZmFjZXMgY29udGVudC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHBhcmFtIHshU2NyZWVufSBuZXh0U2NyZWVuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9yZXBsYWNlSGlzdG9yeSBSZXBsYWNlcyBicm93c2VyIGhpc3RvcnkuXG5cdCAqL1xuXHRwcmVwYXJlTmF2aWdhdGVIaXN0b3J5XyhwYXRoLCBuZXh0U2NyZWVuLCBvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHRsZXQgdGl0bGUgPSBuZXh0U2NyZWVuLmdldFRpdGxlKCk7XG5cdFx0aWYgKCFpc1N0cmluZyh0aXRsZSkpIHtcblx0XHRcdHRpdGxlID0gdGhpcy5nZXREZWZhdWx0VGl0bGUoKTtcblx0XHR9XG5cdFx0bGV0IHJlZGlyZWN0UGF0aCA9IG5leHRTY3JlZW4uYmVmb3JlVXBkYXRlSGlzdG9yeVBhdGgocGF0aCk7XG5cdFx0Y29uc3QgaGlzdG9yeVN0YXRlID0ge1xuXHRcdFx0Zm9ybTogaXNEZWZBbmROb3ROdWxsKGdsb2JhbHMuY2FwdHVyZWRGb3JtRWxlbWVudCksXG5cdFx0XHRwYXRoLFxuXHRcdFx0cmVkaXJlY3RQYXRoLFxuXHRcdFx0c2Nyb2xsTGVmdDogMCxcblx0XHRcdHNjcm9sbFRvcDogMCxcblx0XHRcdHNlbm5hOiB0cnVlXG5cdFx0fTtcblx0XHRpZiAob3B0X3JlcGxhY2VIaXN0b3J5KSB7XG5cdFx0XHRoaXN0b3J5U3RhdGUuc2Nyb2xsVG9wID0gdGhpcy5wb3BzdGF0ZVNjcm9sbFRvcDtcblx0XHRcdGhpc3RvcnlTdGF0ZS5zY3JvbGxMZWZ0ID0gdGhpcy5wb3BzdGF0ZVNjcm9sbExlZnQ7XG5cdFx0fVxuXHRcdGNvbnN0IGhhc2ggPSBuZXcgVXJpKHBhdGgpLmdldEhhc2goKTtcblx0XHRyZWRpcmVjdFBhdGggPSB0aGlzLm1heWJlUmVzdG9yZVJlZGlyZWN0UGF0aEhhc2hfKHBhdGgsIHJlZGlyZWN0UGF0aCwgaGFzaCk7XG5cdFx0dGhpcy51cGRhdGVIaXN0b3J5Xyh0aXRsZSwgcmVkaXJlY3RQYXRoLCBuZXh0U2NyZWVuLmJlZm9yZVVwZGF0ZUhpc3RvcnlTdGF0ZShoaXN0b3J5U3RhdGUpLCBvcHRfcmVwbGFjZUhpc3RvcnkpO1xuXHRcdHRoaXMucmVkaXJlY3RQYXRoID0gcmVkaXJlY3RQYXRoO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByZXBhcmVzIHNjcmVlbiBmbGlwLiBVcGRhdGVzIGhpc3Rvcnkgc3RhdGUgYW5kIHN1cmZhY2VzIGNvbnRlbnQuXG5cdCAqIEBwYXJhbSB7IVNjcmVlbn0gbmV4dFNjcmVlblxuXHQgKiBAcGFyYW0geyFPYmplY3R9IHN1cmZhY2VzIE1hcCBvZiBzdXJmYWNlcyB0byBmbGlwIGtleWVkIGJ5IHN1cmZhY2UgaWQuXG5cdCAqIEBwYXJhbSB7IU9iamVjdH0gcGFyYW1zIFBhcmFtcyBleHRyYWN0ZWQgZnJvbSB0aGUgY3VycmVudCBwYXRoLlxuXHQgKi9cblx0cHJlcGFyZU5hdmlnYXRlU3VyZmFjZXNfKG5leHRTY3JlZW4sIHN1cmZhY2VzLCBwYXJhbXMpIHtcblx0XHRPYmplY3Qua2V5cyhzdXJmYWNlcykuZm9yRWFjaCgoaWQpID0+IHtcblx0XHRcdHZhciBzdXJmYWNlQ29udGVudCA9IG5leHRTY3JlZW4uZ2V0U3VyZmFjZUNvbnRlbnQoaWQsIHBhcmFtcyk7XG5cdFx0XHRzdXJmYWNlc1tpZF0uYWRkQ29udGVudChuZXh0U2NyZWVuLmdldElkKCksIHN1cmZhY2VDb250ZW50KTtcblx0XHRcdGNvbnNvbGUubG9nKCdTY3JlZW4gWycgKyBuZXh0U2NyZWVuLmdldElkKCkgKyAnXSBhZGQgY29udGVudCB0byBzdXJmYWNlICcgK1xuXHRcdFx0XHQnWycgKyBzdXJmYWNlc1tpZF0gKyAnXSBbJyArIChpc0RlZkFuZE5vdE51bGwoc3VyZmFjZUNvbnRlbnQpID8gJy4uLicgOiAnZW1wdHknKSArICddJyk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVsb2FkcyB0aGUgcGFnZSBieSBwZXJmb3JtaW5nIGB3aW5kb3cubG9jYXRpb24ucmVsb2FkKClgLlxuXHQgKi9cblx0cmVsb2FkUGFnZSgpIHtcblx0XHRnbG9iYWxzLndpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHJvdXRlIGluc3RhbmNlIGZyb20gYXBwIHJvdXRlcy5cblx0ICogQHBhcmFtIHtSb3V0ZX0gcm91dGVcblx0ICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhbiBlbGVtZW50IHdhcyByZW1vdmVkLlxuXHQgKi9cblx0cmVtb3ZlUm91dGUocm91dGUpIHtcblx0XHRyZXR1cm4gYXJyYXkucmVtb3ZlKHRoaXMucm91dGVzLCByb3V0ZSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlcyBhIHNjcmVlbi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICovXG5cdHJlbW92ZVNjcmVlbihwYXRoKSB7XG5cdFx0dmFyIHNjcmVlbiA9IHRoaXMuc2NyZWVuc1twYXRoXTtcblx0XHRpZiAoc2NyZWVuKSB7XG5cdFx0XHRPYmplY3Qua2V5cyh0aGlzLnN1cmZhY2VzKS5mb3JFYWNoKChzdXJmYWNlSWQpID0+IHRoaXMuc3VyZmFjZXNbc3VyZmFjZUlkXS5yZW1vdmUoc2NyZWVuLmdldElkKCkpKTtcblx0XHRcdHNjcmVlbi5kaXNwb3NlKCk7XG5cdFx0XHRkZWxldGUgdGhpcy5zY3JlZW5zW3BhdGhdO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTYXZlcyBnaXZlbiBzY3JvbGwgcG9zaXRpb24gaW50byBoaXN0b3J5IHN0YXRlLlxuXHQgKiBAcGFyYW0geyFudW1iZXJ9IHNjcm9sbFRvcCBOdW1iZXIgY29udGFpbmluZyB0aGUgdG9wIHNjcm9sbCBwb3NpdGlvbiB0byBiZSBzYXZlZC5cblx0ICogQHBhcmFtIHshbnVtYmVyfSBzY3JvbGxMZWZ0IE51bWJlciBjb250YWluaW5nIHRoZSBsZWZ0IHNjcm9sbCBwb3NpdGlvbiB0byBiZSBzYXZlZC5cblx0ICovXG5cdHNhdmVIaXN0b3J5Q3VycmVudFBhZ2VTY3JvbGxQb3NpdGlvbl8oc2Nyb2xsVG9wLCBzY3JvbGxMZWZ0KSB7XG5cdFx0dmFyIHN0YXRlID0gZ2xvYmFscy53aW5kb3cuaGlzdG9yeS5zdGF0ZTtcblx0XHRpZiAoc3RhdGUgJiYgc3RhdGUuc2VubmEpIHtcblx0XHRcdFtzdGF0ZS5zY3JvbGxUb3AsIHN0YXRlLnNjcm9sbExlZnRdID0gW3Njcm9sbFRvcCwgc2Nyb2xsTGVmdF07XG5cdFx0XHRnbG9iYWxzLndpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShzdGF0ZSwgbnVsbCwgbnVsbCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgYWxsb3cgcHJldmVudCBuYXZpZ2F0ZS5cblx0ICogQHBhcmFtIHtib29sZWFufSBhbGxvd1ByZXZlbnROYXZpZ2F0ZVxuXHQgKi9cblx0c2V0QWxsb3dQcmV2ZW50TmF2aWdhdGUoYWxsb3dQcmV2ZW50TmF2aWdhdGUpIHtcblx0XHR0aGlzLmFsbG93UHJldmVudE5hdmlnYXRlID0gYWxsb3dQcmV2ZW50TmF2aWdhdGU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyBsaW5rIGJhc2UgcGF0aC5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoXG5cdCAqL1xuXHRzZXRCYXNlUGF0aChiYXNlUGF0aCkge1xuXHRcdHRoaXMuYmFzZVBhdGggPSB1dGlscy5yZW1vdmVQYXRoVHJhaWxpbmdTbGFzaChiYXNlUGF0aCk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgZGVmYXVsdCBwYWdlIHRpdGxlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZGVmYXVsdFRpdGxlXG5cdCAqL1xuXHRzZXREZWZhdWx0VGl0bGUoZGVmYXVsdFRpdGxlKSB7XG5cdFx0dGhpcy5kZWZhdWx0VGl0bGUgPSBkZWZhdWx0VGl0bGU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgZm9ybSBzZWxlY3Rvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBmb3JtU2VsZWN0b3Jcblx0ICovXG5cdHNldEZvcm1TZWxlY3Rvcihmb3JtU2VsZWN0b3IpIHtcblx0XHR0aGlzLmZvcm1TZWxlY3RvciA9IGZvcm1TZWxlY3Rvcjtcblx0XHRpZiAodGhpcy5mb3JtRXZlbnRIYW5kbGVyXykge1xuXHRcdFx0dGhpcy5mb3JtRXZlbnRIYW5kbGVyXy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdH1cblx0XHR0aGlzLmZvcm1FdmVudEhhbmRsZXJfID0gZGVsZWdhdGUoZG9jdW1lbnQsICdzdWJtaXQnLCB0aGlzLmZvcm1TZWxlY3RvciwgdGhpcy5vbkRvY1N1Ym1pdERlbGVnYXRlXy5iaW5kKHRoaXMpLCB0aGlzLmFsbG93UHJldmVudE5hdmlnYXRlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIGlmIHJvdXRlIG1hdGNoaW5nIHNob3VsZCBpZ25vcmUgcXVlcnkgc3RyaW5nIGZyb20gdGhlIHJvdXRlIHBhdGguXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoXG5cdCAqL1xuXHRzZXRJZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGgoaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoKSB7XG5cdFx0dGhpcy5pZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGggPSBpZ25vcmVRdWVyeVN0cmluZ0Zyb21Sb3V0ZVBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgbGluayBzZWxlY3Rvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBsaW5rU2VsZWN0b3Jcblx0ICovXG5cdHNldExpbmtTZWxlY3RvcihsaW5rU2VsZWN0b3IpIHtcblx0XHR0aGlzLmxpbmtTZWxlY3RvciA9IGxpbmtTZWxlY3Rvcjtcblx0XHRpZiAodGhpcy5saW5rRXZlbnRIYW5kbGVyXykge1xuXHRcdFx0dGhpcy5saW5rRXZlbnRIYW5kbGVyXy5yZW1vdmVMaXN0ZW5lcigpO1xuXHRcdH1cblx0XHR0aGlzLmxpbmtFdmVudEhhbmRsZXJfID0gZGVsZWdhdGUoZG9jdW1lbnQsICdjbGljaycsIHRoaXMubGlua1NlbGVjdG9yLCB0aGlzLm9uRG9jQ2xpY2tEZWxlZ2F0ZV8uYmluZCh0aGlzKSwgdGhpcy5hbGxvd1ByZXZlbnROYXZpZ2F0ZSk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgbG9hZGluZyBjc3MgY2xhc3MuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gbG9hZGluZ0Nzc0NsYXNzXG5cdCAqL1xuXHRzZXRMb2FkaW5nQ3NzQ2xhc3MobG9hZGluZ0Nzc0NsYXNzKSB7XG5cdFx0dGhpcy5sb2FkaW5nQ3NzQ2xhc3MgPSBsb2FkaW5nQ3NzQ2xhc3M7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgdXBkYXRlIHNjcm9sbCBwb3NpdGlvbiB2YWx1ZS5cblx0ICogQHBhcmFtIHtib29sZWFufSB1cGRhdGVTY3JvbGxQb3NpdGlvblxuXHQgKi9cblx0c2V0VXBkYXRlU2Nyb2xsUG9zaXRpb24odXBkYXRlU2Nyb2xsUG9zaXRpb24pIHtcblx0XHR0aGlzLnVwZGF0ZVNjcm9sbFBvc2l0aW9uID0gdXBkYXRlU2Nyb2xsUG9zaXRpb247XG5cdH1cblxuXHQvKipcblx0ICogQ2FuY2VscyBwZW5kaW5nIG5hdmlnYXRlIHdpdGggPGNvZGU+Q2FuY2VsIHBlbmRpbmcgbmF2aWdhdGlvbjwvY29kZT4gZXJyb3IuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHN0b3BQZW5kaW5nTmF2aWdhdGVfKCkge1xuXHRcdGlmICh0aGlzLnBlbmRpbmdOYXZpZ2F0ZSkge1xuXHRcdFx0dGhpcy5wZW5kaW5nTmF2aWdhdGUuY2FuY2VsKCdDYW5jZWwgcGVuZGluZyBuYXZpZ2F0aW9uJyk7XG5cdFx0XHR0aGlzLnBlbmRpbmdOYXZpZ2F0ZSA9IG51bGw7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFN5bmMgZG9jdW1lbnQgc2Nyb2xsIHBvc2l0aW9uIHR3aWNlLCB0aGUgZmlyc3Qgb25lIHN5bmNocm9ub3VzIGFuZCB0aGVuXG5cdCAqIG9uZSBpbnNpZGUgPGNvZGU+YXN5bmMubmV4dFRpY2s8L2NvZGU+LiBSZWxldmFudCB0byBicm93c2VycyB0aGF0IGZpcmVzXG5cdCAqIHNjcm9sbCByZXN0b3JhdGlvbiBhc3luY2hyb25vdXNseSBhZnRlciBwb3BzdGF0ZS5cblx0ICogQHByb3RlY3RlZFxuXHQgKiBAcmV0dXJuIHs/Q2FuY2VsbGFibGVQcm9taXNlPX1cblx0ICovXG5cdHN5bmNTY3JvbGxQb3NpdGlvblN5bmNUaGVuQXN5bmNfKCkge1xuXHRcdHZhciBzdGF0ZSA9IGdsb2JhbHMud2luZG93Lmhpc3Rvcnkuc3RhdGU7XG5cdFx0aWYgKCFzdGF0ZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBzY3JvbGxUb3AgPSBzdGF0ZS5zY3JvbGxUb3A7XG5cdFx0dmFyIHNjcm9sbExlZnQgPSBzdGF0ZS5zY3JvbGxMZWZ0O1xuXG5cdFx0dmFyIHN5bmMgPSAoKSA9PiB7XG5cdFx0XHRpZiAodGhpcy51cGRhdGVTY3JvbGxQb3NpdGlvbikge1xuXHRcdFx0XHRnbG9iYWxzLndpbmRvdy5zY3JvbGxUbyhzY3JvbGxMZWZ0LCBzY3JvbGxUb3ApO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0XHRyZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSkgPT4gc3luYygpICYgYXN5bmMubmV4dFRpY2soKCkgPT4gc3luYygpICYgcmVzb2x2ZSgpKSk7XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlcyBvciByZXBsYWNlIGJyb3dzZXIgaGlzdG9yeS5cblx0ICogQHBhcmFtIHs/c3RyaW5nfSB0aXRsZSBEb2N1bWVudCB0aXRsZS5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBwYXRoIFBhdGggY29udGFpbmluZyB0aGUgcXVlcnlzdHJpbmcgcGFydC5cblx0ICogQHBhcmFtIHshb2JqZWN0fSBzdGF0ZVxuXHQgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfcmVwbGFjZUhpc3RvcnkgUmVwbGFjZXMgYnJvd3NlciBoaXN0b3J5LlxuXHQgKiBAcHJvdGVjdGVkXG5cdCAqL1xuXHR1cGRhdGVIaXN0b3J5Xyh0aXRsZSwgcGF0aCwgc3RhdGUsIG9wdF9yZXBsYWNlSGlzdG9yeSkge1xuXHRcdGlmIChvcHRfcmVwbGFjZUhpc3RvcnkpIHtcblx0XHRcdGdsb2JhbHMud2luZG93Lmhpc3RvcnkucmVwbGFjZVN0YXRlKHN0YXRlLCB0aXRsZSwgcGF0aCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGdsb2JhbHMud2luZG93Lmhpc3RvcnkucHVzaFN0YXRlKHN0YXRlLCB0aXRsZSwgcGF0aCk7XG5cdFx0fVxuXG5cdFx0bGV0IHRpdGxlTm9kZSA9IGdsb2JhbHMuZG9jdW1lbnQucXVlcnlTZWxlY3RvcigndGl0bGUnKTtcblx0XHRpZiAodGl0bGVOb2RlKSB7XG5cdFx0XHR0aXRsZU5vZGUuaW5uZXJIVE1MID0gdGl0bGU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGdsb2JhbHMuZG9jdW1lbnQudGl0bGUgPSB0aXRsZTtcblx0XHR9XG5cdH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBBcHA7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmLCBpc0RlZkFuZE5vdE51bGwgfSBmcm9tICdtZXRhbCc7XG5pbXBvcnQgVXJpIGZyb20gJ21ldGFsLXVyaSc7XG5pbXBvcnQgeyBDYW5jZWxsYWJsZVByb21pc2UgYXMgUHJvbWlzZSB9IGZyb20gJ21ldGFsLXByb21pc2UnO1xuXG5jbGFzcyBBamF4IHtcblxuXHQvKipcblx0ICogWG1sSHR0cFJlcXVlc3QncyBnZXRBbGxSZXNwb25zZUhlYWRlcnMoKSBtZXRob2QgcmV0dXJucyBhIHN0cmluZyBvZlxuXHQgKiByZXNwb25zZSBoZWFkZXJzIGFjY29yZGluZyB0byB0aGUgZm9ybWF0IGRlc2NyaWJlZCBvbiB0aGUgc3BlYzpcblx0ICoge0BsaW5rIGh0dHA6Ly93d3cudzMub3JnL1RSL1hNTEh0dHBSZXF1ZXN0LyN0aGUtZ2V0YWxscmVzcG9uc2VoZWFkZXJzLW1ldGhvZH0uXG5cdCAqIFRoaXMgbWV0aG9kIHBhcnNlcyB0aGF0IHN0cmluZyBpbnRvIGEgdXNlci1mcmllbmRseSBuYW1lL3ZhbHVlIHBhaXJcblx0ICogb2JqZWN0LlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gYWxsSGVhZGVycyBBbGwgaGVhZGVycyBhcyBzdHJpbmcuXG5cdCAqIEByZXR1cm4geyFBcnJheS48T2JqZWN0PHN0cmluZywgc3RyaW5nPj59XG5cdCAqL1xuXHRzdGF0aWMgcGFyc2VSZXNwb25zZUhlYWRlcnMoYWxsSGVhZGVycykge1xuXHRcdHZhciBoZWFkZXJzID0gW107XG5cdFx0aWYgKCFhbGxIZWFkZXJzKSB7XG5cdFx0XHRyZXR1cm4gaGVhZGVycztcblx0XHR9XG5cdFx0dmFyIHBhaXJzID0gYWxsSGVhZGVycy5zcGxpdCgnXFx1MDAwZFxcdTAwMGEnKTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHBhaXJzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR2YXIgaW5kZXggPSBwYWlyc1tpXS5pbmRleE9mKCdcXHUwMDNhXFx1MDAyMCcpO1xuXHRcdFx0aWYgKGluZGV4ID4gMCkge1xuXHRcdFx0XHR2YXIgbmFtZSA9IHBhaXJzW2ldLnN1YnN0cmluZygwLCBpbmRleCk7XG5cdFx0XHRcdHZhciB2YWx1ZSA9IHBhaXJzW2ldLnN1YnN0cmluZyhpbmRleCArIDIpO1xuXHRcdFx0XHRoZWFkZXJzLnB1c2goe1xuXHRcdFx0XHRcdG5hbWU6IG5hbWUsXG5cdFx0XHRcdFx0dmFsdWU6IHZhbHVlXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gaGVhZGVycztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXF1ZXN0cyB0aGUgdXJsIHVzaW5nIFhNTEh0dHBSZXF1ZXN0LlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHVybFxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IG1ldGhvZFxuXHQgKiBAcGFyYW0gez9zdHJpbmd9IGJvZHlcblx0ICogQHBhcmFtIHtNdWx0aU1hcD19IG9wdF9oZWFkZXJzXG5cdCAqIEBwYXJhbSB7TXVsdGlNYXA9fSBvcHRfcGFyYW1zXG5cdCAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X3RpbWVvdXRcblx0ICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3N5bmNcblx0ICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3dpdGhDcmVkZW50aWFsc1xuXHQgKiBAcmV0dXJuIHtQcm9taXNlfSBEZWZlcnJlZCBhamF4IHJlcXVlc3QuXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdHN0YXRpYyByZXF1ZXN0KHVybCwgbWV0aG9kLCBib2R5LCBvcHRfaGVhZGVycywgb3B0X3BhcmFtcywgb3B0X3RpbWVvdXQsIG9wdF9zeW5jLCBvcHRfd2l0aENyZWRlbnRpYWxzKSB7XG5cdFx0dXJsID0gdXJsIHx8ICcnO1xuXHRcdG1ldGhvZCA9IG1ldGhvZCB8fCAnR0VUJztcblxuXHRcdHZhciByZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG5cdFx0dmFyIHByZXZpb3VzUmVhZHlTdGF0ZSA9IDA7XG5cblx0XHR2YXIgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuXHRcdFx0cmVxdWVzdC5vbmxvYWQgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKHJlcXVlc3QuYWJvcnRlZCkge1xuXHRcdFx0XHRcdHJlcXVlc3Qub25lcnJvcigpO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXNvbHZlKHJlcXVlc3QpO1xuXHRcdFx0fTtcblx0XHRcdHJlcXVlc3Qub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmIChwcmV2aW91c1JlYWR5U3RhdGUgJiYgcHJldmlvdXNSZWFkeVN0YXRlIDwgMyAmJiA0ID09PSByZXF1ZXN0LnJlYWR5U3RhdGUpIHtcblx0XHRcdFx0XHRyZXF1ZXN0LnRlcm1pbmF0ZWRQcmVtYXR1cmVseSA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0cHJldmlvdXNSZWFkeVN0YXRlID0gcmVxdWVzdC5yZWFkeVN0YXRlO1xuXHRcdFx0fTtcblx0XHRcdHJlcXVlc3Qub25lcnJvciA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9ICdSZXF1ZXN0IGVycm9yJztcblx0XHRcdFx0aWYgKHJlcXVlc3QudGVybWluYXRlZFByZW1hdHVyZWx5KSB7XG5cdFx0XHRcdFx0bWVzc2FnZSA9ICdSZXF1ZXN0IHRlcm1pbmF0ZWQgcHJlbWF0dXJlbHknO1xuXHRcdFx0XHR9IFxuXHRcdFx0XHR2YXIgZXJyb3IgPSBuZXcgRXJyb3IobWVzc2FnZSk7XG5cdFx0XHRcdGVycm9yLnJlcXVlc3QgPSByZXF1ZXN0O1xuXHRcdFx0XHRyZWplY3QoZXJyb3IpO1xuXHRcdFx0fTtcblx0XHR9KS50aGVuQ2F0Y2goZnVuY3Rpb24ocmVhc29uKSB7XG5cdFx0XHRyZXF1ZXN0LmFib3J0KCk7XG5cdFx0XHR0aHJvdyByZWFzb247XG5cdFx0fSkudGhlbkFsd2F5cyhmdW5jdGlvbigpIHtcblx0XHRcdGNsZWFyVGltZW91dCh0aW1lb3V0KTtcblx0XHR9KTtcblxuXHRcdHVybCA9IG5ldyBVcmkodXJsKTtcblxuXHRcdGlmIChvcHRfcGFyYW1zKSB7XG5cdFx0XHR1cmwuYWRkUGFyYW1ldGVyc0Zyb21NdWx0aU1hcChvcHRfcGFyYW1zKS50b1N0cmluZygpO1xuXHRcdH1cblxuXHRcdHVybCA9IHVybC50b1N0cmluZygpO1xuXG5cdFx0cmVxdWVzdC5vcGVuKG1ldGhvZCwgdXJsLCAhb3B0X3N5bmMpO1xuXG5cdFx0aWYgKG9wdF93aXRoQ3JlZGVudGlhbHMpIHtcblx0XHRcdHJlcXVlc3Qud2l0aENyZWRlbnRpYWxzID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAob3B0X2hlYWRlcnMpIHtcblx0XHRcdG9wdF9oZWFkZXJzLm5hbWVzKCkuZm9yRWFjaChmdW5jdGlvbihuYW1lKSB7XG5cdFx0XHRcdHJlcXVlc3Quc2V0UmVxdWVzdEhlYWRlcihuYW1lLCBvcHRfaGVhZGVycy5nZXRBbGwobmFtZSkuam9pbignLCAnKSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRyZXF1ZXN0LnNlbmQoaXNEZWYoYm9keSkgPyBib2R5IDogbnVsbCk7XG5cblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKG9wdF90aW1lb3V0KSkge1xuXHRcdFx0dmFyIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRwcm9taXNlLmNhbmNlbCgnUmVxdWVzdCB0aW1lb3V0Jyk7XG5cdFx0XHR9LCBvcHRfdGltZW91dCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHByb21pc2U7XG5cdH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBBamF4O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIEhvbGRzIHZhbHVlIGVycm9yIG1lc3NhZ2VzLlxuICogQGNvbnN0XG4gKi9cbmNsYXNzIGVycm9ycyB7XG59XG5cbi8qKlxuICogSW52YWxpZCBzdGF0dXMgZXJyb3IgbWVzc2FnZS5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cbmVycm9ycy5JTlZBTElEX1NUQVRVUyA9ICdJbnZhbGlkIHN0YXR1cyBjb2RlJztcblxuLyoqXG4gKiBSZXF1ZXN0IGVycm9yIG1lc3NhZ2UuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQHN0YXRpY1xuICovXG5lcnJvcnMuUkVRVUVTVF9FUlJPUiA9ICdSZXF1ZXN0IGVycm9yJztcblxuLyoqXG4gKiBSZXF1ZXN0IHRpbWVvdXQgZXJyb3IgbWVzc2FnZS5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAc3RhdGljXG4gKi9cbmVycm9ycy5SRVFVRVNUX1RJTUVPVVQgPSAnUmVxdWVzdCB0aW1lb3V0JztcblxuLyoqXG4gKiBSZXF1ZXN0IGlzIGJsb2NrZWQgYnkgQ09SUyBpc3N1ZSBtZXNzYWdlLlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBzdGF0aWNcbiAqL1xuZXJyb3JzLlJFUVVFU1RfUFJFTUFUVVJFX1RFUk1JTkFUSU9OID0gJ1JlcXVlc3QgdGVybWluYXRlZCBwcmVtYXR1cmVseSc7XG5cbmV4cG9ydCBkZWZhdWx0IGVycm9ycztcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBNZXRhbC5qcyBicm93c2VyIHVzZXIgYWdlbnQgZGV0ZWN0aW9uLiBJdCdzIGV4dHJlbWVseSByZWNvbW1lbmRlZCB0aGUgdXNhZ2VcbiAqIG9mIGZlYXR1cmUgY2hlY2tpbmcgb3ZlciBicm93c2VyIHVzZXIgYWdlbnQgc25pZmZpbmcuIFVuZm9ydHVuYXRlbHksIGluIHNvbWVcbiAqIHNpdHVhdGlvbnMgZmVhdHVyZSBjaGVja2luZyBjYW4gYmUgc2xvdyBvciBldmVuIGltcG9zc2libGUsIHRoZXJlZm9yZSB1c2VcbiAqIHRoaXMgdXRpbGl0eSB3aXRoIGNhdXRpb24uXG4gKiBAc2VlIDxhIGhyZWY9XCJodHRwOi8vd3d3LnVzZXJhZ2VudHN0cmluZy5jb20vXCI+VXNlciBhZ2VudCBzdHJpbmdzPC9hPi5cbiAqL1xuY2xhc3MgVUEge1xuXHQvKipcblx0ICogR2V0cyB0aGUgbmF0aXZlIHVzZXJBZ2VudCBzdHJpbmcgZnJvbSBuYXZpZ2F0b3IgaWYgaXQgZXhpc3RzLiBJZlxuXHQgKiBuYXZpZ2F0b3Igb3IgbmF2aWdhdG9yLnVzZXJBZ2VudCBzdHJpbmcgaXMgbWlzc2luZywgcmV0dXJucyBhbiBlbXB0eVxuXHQgKiBzdHJpbmcuXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICogQHByaXZhdGVcblx0ICogQHN0YXRpY1xuXHQgKi9cblx0c3RhdGljIGdldE5hdGl2ZVVzZXJBZ2VudCgpIHtcblx0XHR2YXIgbmF2aWdhdG9yID0gVUEuZ2xvYmFscy53aW5kb3cubmF2aWdhdG9yO1xuXHRcdGlmIChuYXZpZ2F0b3IpIHtcblx0XHRcdHZhciB1c2VyQWdlbnQgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuXHRcdFx0aWYgKHVzZXJBZ2VudCkge1xuXHRcdFx0XHRyZXR1cm4gdXNlckFnZW50O1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gJyc7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgbmF0aXZlIHBsYXRmb3JtIHN0cmluZyBmcm9tIG5hdmlnYXRvciBpZiBpdCBleGlzdHMuIElmXG5cdCAqIG5hdmlnYXRvciBvciBuYXZpZ2F0b3IucGxhdGZvcm0gc3RyaW5nIGlzIG1pc3NpbmcsIHJldHVybnMgYW4gZW1wdHlcblx0ICogc3RyaW5nLlxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqIEBwcml2YXRlXG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyBnZXROYXRpdmVQbGF0Zm9ybSgpIHtcblx0XHR2YXIgbmF2aWdhdG9yID0gVUEuZ2xvYmFscy53aW5kb3cubmF2aWdhdG9yO1xuXHRcdGlmIChuYXZpZ2F0b3IpIHtcblx0XHRcdHZhciBwbGF0Zm9ybSA9IG5hdmlnYXRvci5wbGF0Zm9ybTtcblx0XHRcdGlmIChwbGF0Zm9ybSkge1xuXHRcdFx0XHRyZXR1cm4gcGxhdGZvcm07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiAnJztcblx0fVxuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHRoZSBwbGF0Zm9ybSBjb250YWlucyB0aGUgZ2l2ZW4gc3RyaW5nLCBpZ25vcmluZyBjYXNlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcml2YXRlXG5cdCAqIEBzdGF0aWNcblx0Ki9cblx0c3RhdGljIG1hdGNoUGxhdGZvcm0oc3RyKSB7XG5cdFx0cmV0dXJuIFVBLnBsYXRmb3JtLmluZGV4T2Yoc3RyKSAhPT0gLTE7XG5cdH1cblxuXHQvKipcblx0ICogV2hldGhlciB0aGUgdXNlciBhZ2VudCBjb250YWlucyB0aGUgZ2l2ZW4gc3RyaW5nLCBpZ25vcmluZyBjYXNlLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqIEBwcml2YXRlXG5cdCAqIEBzdGF0aWNcblx0Ki9cblx0c3RhdGljIG1hdGNoVXNlckFnZW50KHN0cikge1xuXHRcdHJldHVybiBVQS51c2VyQWdlbnQuaW5kZXhPZihzdHIpICE9PSAtMTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUZXN0cyB0aGUgdXNlciBhZ2VudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHVzZXJBZ2VudCBUaGUgdXNlciBhZ2VudCBzdHJpbmcuXG5cdCAqIEBzdGF0aWNcblx0ICovXG5cdHN0YXRpYyB0ZXN0VXNlckFnZW50KHVzZXJBZ2VudCA9ICcnLCBwbGF0Zm9ybSA9ICcnKSB7XG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHVzZXIgYWdlbnQgdmFsdWUgZXh0cmFjdGVkIGZyb20gYnJvd3NlciBuYXRpdmUgdXNlciBhZ2VudC5cblx0XHQgKiBAdHlwZSB7c3RyaW5nfVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS51c2VyQWdlbnQgPSB1c2VyQWdlbnQ7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgcGxhdGZvcm0gdmFsdWUgZXh0cmFjdGVkIGZyb20gYnJvd3NlciBuYXRpdmUgcGxhdGZvcm0uXG5cdFx0ICogQHR5cGUge3N0cmluZ31cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBPUyBpcyBNYWMuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzTWFjID0gVUEubWF0Y2hQbGF0Zm9ybSgnTWFjJyk7XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgT1MgaXMgV2luLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc1dpbiA9IFVBLm1hdGNoUGxhdGZvcm0oJ1dpbicpO1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciB0aGUgdXNlcidzIGJyb3dzZXIgaXMgT3BlcmEuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzT3BlcmEgPSBVQS5tYXRjaFVzZXJBZ2VudCgnT3BlcmEnKSB8fCBVQS5tYXRjaFVzZXJBZ2VudCgnT1BSJyk7XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgYnJvd3NlciBpcyBJRS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNJZSA9IFVBLm1hdGNoVXNlckFnZW50KCdUcmlkZW50JykgfHwgVUEubWF0Y2hVc2VyQWdlbnQoJ01TSUUnKTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBicm93c2VyIGlzIEVkZ2UuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzRWRnZSA9IFVBLm1hdGNoVXNlckFnZW50KCdFZGdlJyk7XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgYnJvd3NlciBpcyBJRSBvciBFZGdlLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc0llT3JFZGdlID0gVUEuaXNJZSB8fCBVQS5pc0VkZ2U7XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgYnJvd3NlciBpcyBDaHJvbWUuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICogQHN0YXRpY1xuXHRcdCAqL1xuXHRcdFVBLmlzQ2hyb21lID0gKFVBLm1hdGNoVXNlckFnZW50KCdDaHJvbWUnKSB8fCBVQS5tYXRjaFVzZXJBZ2VudCgnQ3JpT1MnKSkgJiYgIVVBLmlzT3BlcmEgJiYgIVVBLmlzRWRnZTtcblxuXHRcdC8qKlxuXHRcdCAqIFdoZXRoZXIgdGhlIHVzZXIncyBicm93c2VyIGlzIFNhZmFyaS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKiBAc3RhdGljXG5cdFx0ICovXG5cdFx0VUEuaXNTYWZhcmkgPSBVQS5tYXRjaFVzZXJBZ2VudCgnU2FmYXJpJykgJiYgIShVQS5pc0Nocm9tZSB8fCBVQS5pc09wZXJhIHx8IFVBLmlzRWRnZSk7XG5cblx0XHQvKipcblx0XHQgKiBXaGV0aGVyIHRoZSB1c2VyJ3MgYnJvd3NlciBpcyBGaXJlZm94LlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqIEBzdGF0aWNcblx0XHQgKi9cblx0XHRVQS5pc0ZpcmVmb3ggPSBVQS5tYXRjaFVzZXJBZ2VudCgnRmlyZWZveCcpO1xuXHR9XG59XG5cbi8qKlxuICogRXhwb3NlcyBnbG9iYWwgcmVmZXJlbmNlcy5cbiAqIEB0eXBlIHtvYmplY3R9XG4gKiBAc3RhdGljXG4gKi9cblVBLmdsb2JhbHMgPSB7XG5cdHdpbmRvdzogd2luZG93XG59O1xuXG5VQS50ZXN0VXNlckFnZW50KFVBLmdldE5hdGl2ZVVzZXJBZ2VudCgpLCBVQS5nZXROYXRpdmVQbGF0Zm9ybSgpKTtcblxuZXhwb3J0IGRlZmF1bHQgVUE7XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGlzRGVmQW5kTm90TnVsbCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBBamF4IGZyb20gJ21ldGFsLWFqYXgnO1xuaW1wb3J0IHsgTXVsdGlNYXAgfSBmcm9tICdtZXRhbC1zdHJ1Y3RzJztcbmltcG9ydCBDYW5jZWxsYWJsZVByb21pc2UgZnJvbSAnbWV0YWwtcHJvbWlzZSc7XG5pbXBvcnQgZXJyb3JzIGZyb20gJy4uL2Vycm9ycy9lcnJvcnMnO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4uL3V0aWxzL3V0aWxzJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgU2NyZWVuIGZyb20gJy4vU2NyZWVuJztcbmltcG9ydCBVcmkgZnJvbSAnbWV0YWwtdXJpJztcbmltcG9ydCBVQSBmcm9tICdtZXRhbC11c2VyYWdlbnQnO1xuXG5jbGFzcyBSZXF1ZXN0U2NyZWVuIGV4dGVuZHMgU2NyZWVuIHtcblxuXHQvKipcblx0ICogUmVxdWVzdCBzY3JlZW4gYWJzdHJhY3QgY2xhc3MgdG8gcGVyZm9ybSBpbyBvcGVyYXRpb25zIG9uIGRlc2NlbmRhbnRcblx0ICogc2NyZWVucy5cblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqIEBleHRlbmRzIHtTY3JlZW59XG5cdCAqL1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXG5cdFx0LyoqXG5cdFx0ICogQGluaGVyaXREb2Ncblx0XHQgKiBAZGVmYXVsdCB0cnVlXG5cdFx0ICovXG5cdFx0dGhpcy5jYWNoZWFibGUgPSB0cnVlO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgZGVmYXVsdCBodHRwIGhlYWRlcnMgdG8gc2V0IG9uIHJlcXVlc3QuXG5cdFx0ICogQHR5cGUgez9PYmplY3Q9fVxuXHRcdCAqIEBkZWZhdWx0IHtcblx0XHQgKiAgICdYLVBKQVgnOiAndHJ1ZScsXG5cdFx0ICogICAnWC1SZXF1ZXN0ZWQtV2l0aCc6ICdYTUxIdHRwUmVxdWVzdCdcblx0XHQgKiB9XG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMuaHR0cEhlYWRlcnMgPSB7XG5cdFx0XHQnWC1QSkFYJzogJ3RydWUnLFxuXHRcdFx0J1gtUmVxdWVzdGVkLVdpdGgnOiAnWE1MSHR0cFJlcXVlc3QnXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIGRlZmF1bHQgaHR0cCBtZXRob2QgdG8gcGVyZm9ybSB0aGUgcmVxdWVzdC5cblx0XHQgKiBAdHlwZSB7IXN0cmluZ31cblx0XHQgKiBAZGVmYXVsdCBSZXF1ZXN0U2NyZWVuLkdFVFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLmh0dHBNZXRob2QgPSBSZXF1ZXN0U2NyZWVuLkdFVDtcblxuXHRcdC8qKlxuXHRcdCAqIEhvbGRzIHRoZSBYSFIgb2JqZWN0IHJlc3BvbnNpYmxlIGZvciB0aGUgcmVxdWVzdC5cblx0XHQgKiBAdHlwZSB7WE1MSHR0cFJlcXVlc3R9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqIEBwcm90ZWN0ZWRcblx0XHQgKi9cblx0XHR0aGlzLnJlcXVlc3QgPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIHJlcXVlc3QgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuXG5cdFx0ICogQHR5cGUgeyFudW1iZXJ9XG5cdFx0ICogQGRlZmF1bHQgMzAwMDBcblx0XHQgKiBAcHJvdGVjdGVkXG5cdFx0ICovXG5cdFx0dGhpcy50aW1lb3V0ID0gMzAwMDA7XG5cdH1cblxuXHQvKipcblx0ICogQXNzZXJ0cyB0aGF0IHJlc3BvbnNlIHN0YXR1cyBjb2RlIGlzIHZhbGlkLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gc3RhdHVzXG5cdCAqIEBwcm90ZWN0ZWRcblx0ICovXG5cdGFzc2VydFZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlKHN0YXR1cykge1xuXHRcdGlmICghdGhpcy5pc1ZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlKHN0YXR1cykpIHtcblx0XHRcdHZhciBlcnJvciA9IG5ldyBFcnJvcihlcnJvcnMuSU5WQUxJRF9TVEFUVVMpO1xuXHRcdFx0ZXJyb3IuaW52YWxpZFN0YXR1cyA9IHRydWU7XG5cdFx0XHRlcnJvci5zdGF0dXNDb2RlID0gc3RhdHVzO1xuXHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0RG9jXG5cdCAqL1xuXHRiZWZvcmVVcGRhdGVIaXN0b3J5UGF0aChwYXRoKSB7XG5cdFx0dmFyIHJlZGlyZWN0UGF0aCA9IHRoaXMuZ2V0UmVxdWVzdFBhdGgoKTtcblx0XHRpZiAocmVkaXJlY3RQYXRoICYmIHJlZGlyZWN0UGF0aCAhPT0gcGF0aCkge1xuXHRcdFx0cmV0dXJuIHJlZGlyZWN0UGF0aDtcblx0XHR9XG5cdFx0cmV0dXJuIHBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGJlZm9yZVVwZGF0ZUhpc3RvcnlTdGF0ZShzdGF0ZSkge1xuXHRcdC8vIElmIHN0YXRlIGlzIG91cnMgYW5kIG5hdmlnYXRlIHRvIHBvc3Qtd2l0aG91dC1yZWRpcmVjdC1nZXQgc2V0XG5cdFx0Ly8gaGlzdG9yeSBzdGF0ZSB0byBudWxsLCB0aGF0IHdheSBTZW5uYSB3aWxsIHJlbG9hZCB0aGUgcGFnZSBvblxuXHRcdC8vIHBvcHN0YXRlIHNpbmNlIGl0IGNhbm5vdCBwcmVkaWN0IHBvc3QgZGF0YS5cblx0XHRpZiAoc3RhdGUuc2VubmEgJiYgc3RhdGUuZm9ybSAmJiBzdGF0ZS5yZWRpcmVjdFBhdGggPT09IHN0YXRlLnBhdGgpIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblx0XHRyZXR1cm4gc3RhdGU7XG5cdH1cblxuXHQvKipcblx0ICogRm9ybWF0cyBsb2FkIHBhdGggYmVmb3JlIGludm9raW5nIGFqYXggY2FsbC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGhcblx0ICogQHJldHVybiB7c3RyaW5nfSBGb3JtYXR0ZWQgcGF0aDtcblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0Zm9ybWF0TG9hZFBhdGgocGF0aCkge1xuXHRcdHZhciB1cmkgPSBuZXcgVXJpKHBhdGgpO1xuXG5cdFx0dXJpLnNldEhvc3RuYW1lKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLmhvc3RuYW1lKTtcblx0XHR1cmkuc2V0UHJvdG9jb2woZ2xvYmFscy53aW5kb3cubG9jYXRpb24ucHJvdG9jb2wpO1xuXG5cdFx0aWYgKGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnBvcnQpIHtcblx0XHRcdHVyaS5zZXRQb3J0KGdsb2JhbHMud2luZG93LmxvY2F0aW9uLnBvcnQpO1xuXHRcdH1cblxuXHRcdGlmIChVQS5pc0llT3JFZGdlICYmIHRoaXMuaHR0cE1ldGhvZCA9PT0gUmVxdWVzdFNjcmVlbi5HRVQpIHtcblx0XHRcdHJldHVybiB1cmkubWFrZVVuaXF1ZSgpLnRvU3RyaW5nKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVyaS50b1N0cmluZygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGh0dHAgaGVhZGVycy5cblx0ICogQHJldHVybiB7P09iamVjdD19XG5cdCAqL1xuXHRnZXRIdHRwSGVhZGVycygpIHtcblx0XHRyZXR1cm4gdGhpcy5odHRwSGVhZGVycztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBodHRwIG1ldGhvZC5cblx0ICogQHJldHVybiB7IXN0cmluZ31cblx0ICovXG5cdGdldEh0dHBNZXRob2QoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaHR0cE1ldGhvZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHJlcXVlc3QgcGF0aC5cblx0ICogQHJldHVybiB7c3RyaW5nPX1cblx0ICovXG5cdGdldFJlcXVlc3RQYXRoKCkge1xuXHRcdHZhciByZXF1ZXN0ID0gdGhpcy5nZXRSZXF1ZXN0KCk7XG5cdFx0aWYgKHJlcXVlc3QpIHtcblx0XHRcdHZhciByZXF1ZXN0UGF0aCA9IHJlcXVlc3QucmVxdWVzdFBhdGg7XG5cdFx0XHR2YXIgcmVzcG9uc2VVcmwgPSB0aGlzLm1heWJlRXh0cmFjdFJlc3BvbnNlVXJsRnJvbVJlcXVlc3QocmVxdWVzdCk7XG5cdFx0XHRpZiAocmVzcG9uc2VVcmwpIHtcblx0XHRcdFx0cmVxdWVzdFBhdGggPSByZXNwb25zZVVybDtcblx0XHRcdH1cblx0XHRcdGlmIChVQS5pc0llT3JFZGdlICYmIHRoaXMuaHR0cE1ldGhvZCA9PT0gUmVxdWVzdFNjcmVlbi5HRVQpIHtcblx0XHRcdFx0cmVxdWVzdFBhdGggPSBuZXcgVXJpKHJlcXVlc3RQYXRoKS5yZW1vdmVVbmlxdWUoKS50b1N0cmluZygpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHV0aWxzLmdldFVybFBhdGgocmVxdWVzdFBhdGgpO1xuXHRcdH1cblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByZXF1ZXN0IG9iamVjdC5cblx0ICogQHJldHVybiB7P09iamVjdH1cblx0ICovXG5cdGdldFJlcXVlc3QoKSB7XG5cdFx0cmV0dXJuIHRoaXMucmVxdWVzdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByZXF1ZXN0IHRpbWVvdXQuXG5cdCAqIEByZXR1cm4geyFudW1iZXJ9XG5cdCAqL1xuXHRnZXRUaW1lb3V0KCkge1xuXHRcdHJldHVybiB0aGlzLnRpbWVvdXQ7XG5cdH1cblxuXHQvKipcblx0ICogQ2hlY2tzIGlmIHJlc3BvbnNlIHN1Y2NlZWRlZC4gQW55IHN0YXR1cyBjb2RlIDJ4eCBvciAzeHggaXMgY29uc2lkZXJlZFxuXHQgKiB2YWxpZC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHN0YXR1c0NvZGVcblx0ICovXG5cdGlzVmFsaWRSZXNwb25zZVN0YXR1c0NvZGUoc3RhdHVzQ29kZSkge1xuXHRcdHJldHVybiBzdGF0dXNDb2RlID49IDIwMCAmJiBzdGF0dXNDb2RlIDw9IDM5OTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0bG9hZChwYXRoKSB7XG5cdFx0Y29uc3QgY2FjaGUgPSB0aGlzLmdldENhY2hlKCk7XG5cdFx0aWYgKGlzRGVmQW5kTm90TnVsbChjYWNoZSkpIHtcblx0XHRcdHJldHVybiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZShjYWNoZSk7XG5cdFx0fVxuXHRcdGxldCBib2R5ID0gbnVsbDtcblx0XHRsZXQgaHR0cE1ldGhvZCA9IHRoaXMuaHR0cE1ldGhvZDtcblx0XHRjb25zdCBoZWFkZXJzID0gbmV3IE11bHRpTWFwKCk7XG5cdFx0T2JqZWN0LmtleXModGhpcy5odHRwSGVhZGVycykuZm9yRWFjaChoZWFkZXIgPT4gaGVhZGVycy5hZGQoaGVhZGVyLCB0aGlzLmh0dHBIZWFkZXJzW2hlYWRlcl0pKTtcblx0XHRpZiAoZ2xvYmFscy5jYXB0dXJlZEZvcm1FbGVtZW50KSB7XG5cdFx0XHRib2R5ID0gbmV3IEZvcm1EYXRhKGdsb2JhbHMuY2FwdHVyZWRGb3JtRWxlbWVudCk7XG5cdFx0XHR0aGlzLm1heWJlQXBwZW5kU3VibWl0QnV0dG9uVmFsdWVfKGJvZHkpO1xuXHRcdFx0aHR0cE1ldGhvZCA9IFJlcXVlc3RTY3JlZW4uUE9TVDtcblx0XHRcdGlmIChVQS5pc0llT3JFZGdlKSB7XG5cdFx0XHRcdGhlYWRlcnMuYWRkKCdJZi1Ob25lLU1hdGNoJywgJ1wiMFwiJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGNvbnN0IHJlcXVlc3RQYXRoID0gdGhpcy5mb3JtYXRMb2FkUGF0aChwYXRoKTtcblx0XHRyZXR1cm4gQWpheFxuXHRcdFx0LnJlcXVlc3QocmVxdWVzdFBhdGgsIGh0dHBNZXRob2QsIGJvZHksIGhlYWRlcnMsIG51bGwsIHRoaXMudGltZW91dClcblx0XHRcdC50aGVuKHhociA9PiB7XG5cdFx0XHRcdHRoaXMuc2V0UmVxdWVzdCh4aHIpO1xuXHRcdFx0XHR0aGlzLmFzc2VydFZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlKHhoci5zdGF0dXMpO1xuXHRcdFx0XHRpZiAoaHR0cE1ldGhvZCA9PT0gUmVxdWVzdFNjcmVlbi5HRVQgJiYgdGhpcy5pc0NhY2hlYWJsZSgpKSB7XG5cdFx0XHRcdFx0dGhpcy5hZGRDYWNoZSh4aHIucmVzcG9uc2VUZXh0KTtcblx0XHRcdFx0fVxuXHRcdFx0XHR4aHIucmVxdWVzdFBhdGggPSByZXF1ZXN0UGF0aDtcblx0XHRcdFx0cmV0dXJuIHhoci5yZXNwb25zZVRleHQ7XG5cdFx0XHR9KVxuXHRcdFx0LmNhdGNoKChyZWFzb24pID0+IHtcblx0XHRcdFx0c3dpdGNoIChyZWFzb24ubWVzc2FnZSkge1xuXHRcdFx0XHRcdGNhc2UgZXJyb3JzLlJFUVVFU1RfVElNRU9VVDpcblx0XHRcdFx0XHRcdHJlYXNvbi50aW1lb3V0ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgZXJyb3JzLlJFUVVFU1RfRVJST1I6XG5cdFx0XHRcdFx0XHRyZWFzb24ucmVxdWVzdEVycm9yID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgZXJyb3JzLlJFUVVFU1RfUFJFTUFUVVJFX1RFUk1JTkFUSU9OOlxuXHRcdFx0XHRcdFx0cmVhc29uLnJlcXVlc3RFcnJvciA9IHRydWU7XG5cdFx0XHRcdFx0XHRyZWFzb24ucmVxdWVzdFByZW1hdHVyZVRlcm1pbmF0aW9uID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRocm93IHJlYXNvbjtcblx0XHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYWRpdGlvbmFsIGRhdGEgdG8gdGhlIGJvZHkgb2YgdGhlIHJlcXVlc3QgaW4gY2FzZSBhIHN1Ym1pdCBidXR0b25cblx0ICogaXMgY2FwdHVyZWQgZHVyaW5nIGZvcm0gc3VibWlzc2lvbi5cblx0ICogQHBhcmFtIHshRm9ybURhdGF9IGJvZHkgVGhlIEZvcm1EYXRhIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3QgYm9keS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0bWF5YmVBcHBlbmRTdWJtaXRCdXR0b25WYWx1ZV8oYm9keSkge1xuXHRcdGNvbnN0IGJ1dHRvbiA9IGdsb2JhbHMuY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudDtcblx0XHRpZiAoYnV0dG9uICYmIGJ1dHRvbi5uYW1lKSB7XG5cdFx0XHRib2R5LmFwcGVuZChidXR0b24ubmFtZSwgYnV0dG9uLnZhbHVlKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogVGhlIGZvbGxvd2luZyBtZXRob2QgdHJpZXMgdG8gZXh0cmFjdCB0aGUgcmVzcG9uc2UgdXJsIHZhbHVlIGJ5IGNoZWNraW5nXG5cdCAqIHRoZSBjdXN0b20gcmVzcG9uc2UgaGVhZGVyICdYLVJlcXVlc3QtVVJMJyBpZiBwcm9wZXIgdmFsdWUgaXMgbm90IHByZXNlbnRcblx0ICogaW4gWE1MSHR0cFJlcXVlc3QuIFRoZSB2YWx1ZSBvZiByZXNwb25zZVVSTCB3aWxsIGJlIHRoZSBmaW5hbCBVUkxcblx0ICogb2J0YWluZWQgYWZ0ZXIgYW55IHJlZGlyZWN0cy4gSW50ZXJuZXQgRXhwbG9yZXIsIEVkZ2UgYW5kIFNhZmFyaSA8PSA3XG5cdCAqIGRvZXMgbm90IHlldCBzdXBwb3J0IHRoZSBmZWF0dXJlLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBzZWU6XG5cdCAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9YTUxIdHRwUmVxdWVzdC9yZXNwb25zZVVSTFxuXHQgKiBodHRwczovL3hoci5zcGVjLndoYXR3Zy5vcmcvI3RoZS1yZXNwb25zZXVybC1hdHRyaWJ1dGVcblx0ICogQHBhcmFtIHtYTUxIdHRwUmVxdWVzdH0gcmVxdWVzdFxuXHQgKiBAcmV0dXJuIHs/c3RyaW5nfSBSZXNwb25zZSB1cmwgYmVzdCBtYXRjaC5cblx0ICovXG5cdG1heWJlRXh0cmFjdFJlc3BvbnNlVXJsRnJvbVJlcXVlc3QocmVxdWVzdCkge1xuXHRcdHZhciByZXNwb25zZVVybCA9IHJlcXVlc3QucmVzcG9uc2VVUkw7XG5cdFx0aWYgKHJlc3BvbnNlVXJsKSB7XG5cdFx0XHRyZXR1cm4gcmVzcG9uc2VVcmw7XG5cdFx0fVxuXHRcdHJldHVybiByZXF1ZXN0LmdldFJlc3BvbnNlSGVhZGVyKFJlcXVlc3RTY3JlZW4uWF9SRVFVRVNUX1VSTF9IRUFERVIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGh0dHAgaGVhZGVycy5cblx0ICogQHBhcmFtIHs/T2JqZWN0PX0gaHR0cEhlYWRlcnNcblx0ICovXG5cdHNldEh0dHBIZWFkZXJzKGh0dHBIZWFkZXJzKSB7XG5cdFx0dGhpcy5odHRwSGVhZGVycyA9IGh0dHBIZWFkZXJzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGh0dHAgbWV0aG9kLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IGh0dHBNZXRob2Rcblx0ICovXG5cdHNldEh0dHBNZXRob2QoaHR0cE1ldGhvZCkge1xuXHRcdHRoaXMuaHR0cE1ldGhvZCA9IGh0dHBNZXRob2QudG9Mb3dlckNhc2UoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSByZXF1ZXN0IG9iamVjdC5cblx0ICogQHBhcmFtIHs/T2JqZWN0fSByZXF1ZXN0XG5cdCAqL1xuXHRzZXRSZXF1ZXN0KHJlcXVlc3QpIHtcblx0XHR0aGlzLnJlcXVlc3QgPSByZXF1ZXN0O1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHJlcXVlc3QgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuXG5cdCAqIEBwYXJhbSB7IW51bWJlcn0gdGltZW91dFxuXHQgKi9cblx0c2V0VGltZW91dCh0aW1lb3V0KSB7XG5cdFx0dGhpcy50aW1lb3V0ID0gdGltZW91dDtcblx0fVxuXG59XG5cbi8qKlxuICogSG9sZHMgdmFsdWUgZm9yIG1ldGhvZCBnZXQuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgJ2dldCdcbiAqIEBzdGF0aWNcbiAqL1xuUmVxdWVzdFNjcmVlbi5HRVQgPSAnZ2V0JztcblxuLyoqXG4gKiBIb2xkcyB2YWx1ZSBmb3IgbWV0aG9kIHBvc3QuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICogQGRlZmF1bHQgJ3Bvc3QnXG4gKiBAc3RhdGljXG4gKi9cblJlcXVlc3RTY3JlZW4uUE9TVCA9ICdwb3N0JztcblxuLyoqXG4gKiBGYWxsYmFjayBodHRwIGhlYWRlciB0byByZXRyaWV2ZSByZXNwb25zZSByZXF1ZXN0IHVybC5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAZGVmYXVsdCAnWC1SZXF1ZXN0LVVSTCdcbiAqIEBzdGF0aWNcbiAqL1xuUmVxdWVzdFNjcmVlbi5YX1JFUVVFU1RfVVJMX0hFQURFUiA9ICdYLVJlcXVlc3QtVVJMJztcblxuZXhwb3J0IGRlZmF1bHQgUmVxdWVzdFNjcmVlbjtcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnbWV0YWwnO1xuaW1wb3J0IHsgYnVpbGRGcmFnbWVudCwgZXhpdERvY3VtZW50LCBnbG9iYWxFdmFsLCBnbG9iYWxFdmFsU3R5bGVzLCBtYXRjaCB9IGZyb20gJ21ldGFsLWRvbSc7XG5pbXBvcnQgQ2FuY2VsbGFibGVQcm9taXNlIGZyb20gJ21ldGFsLXByb21pc2UnO1xuaW1wb3J0IGdsb2JhbHMgZnJvbSAnLi4vZ2xvYmFscy9nbG9iYWxzJztcbmltcG9ydCBSZXF1ZXN0U2NyZWVuIGZyb20gJy4vUmVxdWVzdFNjcmVlbic7XG5pbXBvcnQgU3VyZmFjZSBmcm9tICcuLi9zdXJmYWNlL1N1cmZhY2UnO1xuaW1wb3J0IFVBIGZyb20gJ21ldGFsLXVzZXJhZ2VudCc7XG5pbXBvcnQgVXJpIGZyb20gJ21ldGFsLXVyaSc7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi4vdXRpbHMvdXRpbHMnO1xuXG5jbGFzcyBIdG1sU2NyZWVuIGV4dGVuZHMgUmVxdWVzdFNjcmVlbiB7XG5cblx0LyoqXG5cdCAqIFNjcmVlbiBjbGFzcyB0aGF0IHBlcmZvcm0gYSByZXF1ZXN0IGFuZCBleHRyYWN0cyBzdXJmYWNlIGNvbnRlbnRzIGZyb21cblx0ICogdGhlIHJlc3BvbnNlIGNvbnRlbnQuXG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKiBAZXh0ZW5kcyB7UmVxdWVzdFNjcmVlbn1cblx0ICovXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgdGl0bGUgc2VsZWN0b3IuIFJlbGV2YW50IHRvIGV4dHJhY3QgdGhlIDxjb2RlPjx0aXRsZT48L2NvZGU+XG5cdFx0ICogZWxlbWVudCBmcm9tIHJlcXVlc3QgZnJhZ21lbnRzIHRvIHVzZSBhcyB0aGUgc2NyZWVuIHRpdGxlLlxuXHRcdCAqIEB0eXBlIHshc3RyaW5nfVxuXHRcdCAqIEBkZWZhdWx0IHRpdGxlXG5cdFx0ICogQHByb3RlY3RlZFxuXHRcdCAqL1xuXHRcdHRoaXMudGl0bGVTZWxlY3RvciA9ICd0aXRsZSc7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGFjdGl2YXRlKCkge1xuXHRcdHN1cGVyLmFjdGl2YXRlKCk7XG5cdFx0dGhpcy5yZWxlYXNlVmlydHVhbERvY3VtZW50KCk7XG5cdFx0dGhpcy5wZW5kaW5nU3R5bGVzID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGxvY2F0ZXMgdmlydHVhbCBkb2N1bWVudCBmb3IgY29udGVudC4gQWZ0ZXIgYWxsb2NhdGVkIHZpcnR1YWwgZG9jdW1lbnRcblx0ICogY2FuIGJlIGFjY2Vzc2VkIGJ5IDxjb2RlPnRoaXMudmlydHVhbERvY3VtZW50PC9jb2RlPi5cblx0ICogQHBhcmFtIHshc3RyaW5nfSBodG1sU3RyaW5nXG5cdCAqL1xuXHRhbGxvY2F0ZVZpcnR1YWxEb2N1bWVudEZvckNvbnRlbnQoaHRtbFN0cmluZykge1xuXHRcdGlmICghdGhpcy52aXJ0dWFsRG9jdW1lbnQpIHtcblx0XHRcdHRoaXMudmlydHVhbERvY3VtZW50ID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdodG1sJyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5jb3B5Tm9kZUF0dHJpYnV0ZXNGcm9tQ29udGVudF8oaHRtbFN0cmluZywgdGhpcy52aXJ0dWFsRG9jdW1lbnQpO1xuXG5cdFx0dGhpcy52aXJ0dWFsRG9jdW1lbnQuaW5uZXJIVE1MID0gaHRtbFN0cmluZztcblx0fVxuXG5cdC8qKlxuXHQgKiBDdXN0b21pemVzIGxvZ2ljIHRvIGFwcGVuZCBzdHlsZXMgaW50byBkb2N1bWVudC4gUmVsZXZhbnQgdG8gd2hlblxuXHQgKiB0cmFja2luZyBhIHN0eWxlIGJ5IGlkIG1ha2Ugc3VyZSB0byByZS1wb3NpdGlvbnMgdGhlIG5ldyBzdHlsZSBpbiB0aGVcblx0ICogc2FtZSBkb20gb3JkZXIuXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbmV3U3R5bGVcblx0ICovXG5cdGFwcGVuZFN0eWxlSW50b0RvY3VtZW50XyhuZXdTdHlsZSkge1xuXHRcdHZhciBpc1RlbXBvcmFyeVN0eWxlID0gbWF0Y2gobmV3U3R5bGUsIEh0bWxTY3JlZW4uc2VsZWN0b3JzLnN0eWxlc1RlbXBvcmFyeSk7XG5cdFx0aWYgKGlzVGVtcG9yYXJ5U3R5bGUpIHtcblx0XHRcdHRoaXMucGVuZGluZ1N0eWxlcy5wdXNoKG5ld1N0eWxlKTtcblx0XHR9XG5cdFx0aWYgKG5ld1N0eWxlLmlkKSB7XG5cdFx0XHR2YXIgc3R5bGVJbkRvYyA9IGdsb2JhbHMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQobmV3U3R5bGUuaWQpO1xuXHRcdFx0aWYgKHN0eWxlSW5Eb2MpIHtcblx0XHRcdFx0c3R5bGVJbkRvYy5wYXJlbnROb2RlLmluc2VydEJlZm9yZShuZXdTdHlsZSwgc3R5bGVJbkRvYy5uZXh0U2libGluZyk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cdFx0Z2xvYmFscy5kb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKG5ld1N0eWxlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZiBib2R5IGlzIHVzZWQgYXMgc3VyZmFjZSBmb3JjZXMgdGhlIHJlcXVlc3RlZCBkb2N1bWVudHMgdG8gaGF2ZSBzYW1lIGlkXG5cdCAqIG9mIHRoZSBpbml0aWFsIHBhZ2UuXG5cdCAqL1xuXHRhc3NlcnRTYW1lQm9keUlkSW5WaXJ0dWFsRG9jdW1lbnQoKSB7XG5cdFx0dmFyIGJvZHlTdXJmYWNlID0gdGhpcy52aXJ0dWFsRG9jdW1lbnQucXVlcnlTZWxlY3RvcignYm9keScpO1xuXHRcdGlmICghZ2xvYmFscy5kb2N1bWVudC5ib2R5LmlkKSB7XG5cdFx0XHRnbG9iYWxzLmRvY3VtZW50LmJvZHkuaWQgPSAnc2VubmFfc3VyZmFjZV8nICsgZ2V0VWlkKCk7XG5cdFx0fVxuXHRcdGlmIChib2R5U3VyZmFjZSkge1xuXHRcdFx0Ym9keVN1cmZhY2UuaWQgPSBnbG9iYWxzLmRvY3VtZW50LmJvZHkuaWQ7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENvcGllcyBhdHRyaWJ1dGVzIGZyb20gdGhlIDxodG1sPiB0YWcgb2YgY29udGVudCB0byB0aGUgZ2l2ZW4gbm9kZS5cblx0ICovXG5cdGNvcHlOb2RlQXR0cmlidXRlc0Zyb21Db250ZW50Xyhjb250ZW50LCBub2RlKSB7XG5cdFx0Y29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvWzxdXFxzKmh0bWwvaWcsICc8c2VubmEnKTtcblx0XHRjb250ZW50ID0gY29udGVudC5yZXBsYWNlKC9cXC9odG1sXFxzKlxcPi9pZywgJy9zZW5uYT4nKTtcblx0XHRub2RlLmlubmVySFRNTCA9IGNvbnRlbnQ7XG5cdFx0dmFyIHBsYWNlaG9sZGVyID0gbm9kZS5xdWVyeVNlbGVjdG9yKCdzZW5uYScpO1xuXHRcdGlmIChwbGFjZWhvbGRlcikge1xuXHRcdFx0dXRpbHMuY2xlYXJOb2RlQXR0cmlidXRlcyhub2RlKTtcblx0XHRcdHV0aWxzLmNvcHlOb2RlQXR0cmlidXRlcyhwbGFjZWhvbGRlciwgbm9kZSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEBPdmVycmlkZVxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdHRoaXMuZGlzcG9zZVBlbmRpbmdTdHlsZXMoKTtcblx0XHRzdXBlci5kaXNwb3NlSW50ZXJuYWwoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwb3NlcyBwZW5kaW5nIHN0eWxlcyBpZiBzY3JlZW4gZ2V0IGRpc3Bvc2VkIHByaW9yIHRvIGl0cyBsb2FkaW5nLlxuXHQgKi9cblx0ZGlzcG9zZVBlbmRpbmdTdHlsZXMoKSB7XG5cdFx0aWYgKHRoaXMucGVuZGluZ1N0eWxlcykge1xuXHRcdFx0dGhpcy5wZW5kaW5nU3R5bGVzLmZvckVhY2goKHN0eWxlKSA9PiBleGl0RG9jdW1lbnQoc3R5bGUpKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQE92ZXJyaWRlXG5cdCAqL1xuXHRldmFsdWF0ZVNjcmlwdHMoc3VyZmFjZXMpIHtcblx0XHR2YXIgZXZhbHVhdGVUcmFja2VkU2NyaXB0cyA9IHRoaXMuZXZhbHVhdGVUcmFja2VkUmVzb3VyY2VzXyhcblx0XHRcdGdsb2JhbEV2YWwucnVuU2NyaXB0c0luRWxlbWVudCwgSHRtbFNjcmVlbi5zZWxlY3RvcnMuc2NyaXB0cyxcblx0XHRcdEh0bWxTY3JlZW4uc2VsZWN0b3JzLnNjcmlwdHNUZW1wb3JhcnksIEh0bWxTY3JlZW4uc2VsZWN0b3JzLnNjcmlwdHNQZXJtYW5lbnQpO1xuXG5cdFx0cmV0dXJuIGV2YWx1YXRlVHJhY2tlZFNjcmlwdHMudGhlbigoKSA9PiBzdXBlci5ldmFsdWF0ZVNjcmlwdHMoc3VyZmFjZXMpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAT3ZlcnJpZGVcblx0ICovXG5cdGV2YWx1YXRlU3R5bGVzKHN1cmZhY2VzKSB7XG5cdFx0dGhpcy5wZW5kaW5nU3R5bGVzID0gW107XG5cdFx0dmFyIGV2YWx1YXRlVHJhY2tlZFN0eWxlcyA9IHRoaXMuZXZhbHVhdGVUcmFja2VkUmVzb3VyY2VzXyhcblx0XHRcdGdsb2JhbEV2YWxTdHlsZXMucnVuU3R5bGVzSW5FbGVtZW50LCBIdG1sU2NyZWVuLnNlbGVjdG9ycy5zdHlsZXMsXG5cdFx0XHRIdG1sU2NyZWVuLnNlbGVjdG9ycy5zdHlsZXNUZW1wb3JhcnksIEh0bWxTY3JlZW4uc2VsZWN0b3JzLnN0eWxlc1Blcm1hbmVudCxcblx0XHRcdHRoaXMuYXBwZW5kU3R5bGVJbnRvRG9jdW1lbnRfLmJpbmQodGhpcykpO1xuXG5cdFx0cmV0dXJuIGV2YWx1YXRlVHJhY2tlZFN0eWxlcy50aGVuKCgpID0+IHN1cGVyLmV2YWx1YXRlU3R5bGVzKHN1cmZhY2VzKSk7XG5cdH1cblxuXHQvKipcblx0ICogRXZhbHVhdGVzIHRyYWNrZWQgcmVzb3VyY2VzIGluc2lkZSBpbmNvbWluZyBmcmFnbWVudCBhbmQgcmVtb3ZlIGV4aXN0aW5nXG5cdCAqIHRlbXBvcmFyeSByZXNvdXJjZXMuXG5cdCAqIEBwYXJhbSB7P2Z1bmN0aW9uKCl9IGFwcGVuZEZuIEZ1bmN0aW9uIHRvIGFwcGVuZCB0aGUgbm9kZSBpbnRvIGRvY3VtZW50LlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNlbGVjdG9yIFNlbGVjdG9yIHVzZWQgdG8gZmluZCByZXNvdXJjZXMgdG8gdHJhY2suXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3JUZW1wb3JhcnkgU2VsZWN0b3IgdXNlZCB0byBmaW5kIHRlbXBvcmFyeVxuXHQgKiAgICAgcmVzb3VyY2VzIHRvIHRyYWNrLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNlbGVjdG9yUGVybWFuZW50IFNlbGVjdG9yIHVzZWQgdG8gZmluZCBwZXJtYW5lbnRcblx0ICogICAgIHJlc291cmNlcyB0byB0cmFjay5cblx0ICogQHBhcmFtIHshZnVuY3Rpb259IG9wdF9hcHBlbmRSZXNvdXJjZUZuIE9wdGlvbmFsIGZ1bmN0aW9uIHVzZWQgdG9cblx0ICogICAgIGV2YWx1YXRlIGZyYWdtZW50IGNvbnRhaW5pbmcgcmVzb3VyY2VzLlxuXHQgKiBAcmV0dXJuIHtDYW5jZWxsYWJsZVByb21pc2V9IERlZmVycmVkIHRoYXQgd2FpdHMgcmVzb3VyY2VzIGV2YWx1YXRpb24gdG9cblx0ICogICAgIGNvbXBsZXRlLlxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0ZXZhbHVhdGVUcmFja2VkUmVzb3VyY2VzXyhldmFsdWF0b3JGbiwgc2VsZWN0b3IsIHNlbGVjdG9yVGVtcG9yYXJ5LCBzZWxlY3RvclBlcm1hbmVudCwgb3B0X2FwcGVuZFJlc291cmNlRm4pIHtcblx0XHR2YXIgdHJhY2tlZCA9IHRoaXMudmlydHVhbFF1ZXJ5U2VsZWN0b3JBbGxfKHNlbGVjdG9yKTtcblx0XHR2YXIgdGVtcG9yYXJpZXNJbkRvYyA9IHRoaXMucXVlcnlTZWxlY3RvckFsbF8oc2VsZWN0b3JUZW1wb3JhcnkpO1xuXHRcdHZhciBwZXJtYW5lbnRzSW5Eb2MgPSB0aGlzLnF1ZXJ5U2VsZWN0b3JBbGxfKHNlbGVjdG9yUGVybWFuZW50KTtcblxuXHRcdC8vIEFkZHMgcGVybWFuZW50IHJlc291cmNlcyBpbiBkb2N1bWVudCB0byBjYWNoZS5cblx0XHRwZXJtYW5lbnRzSW5Eb2MuZm9yRWFjaCgocmVzb3VyY2UpID0+IHtcblx0XHRcdHZhciByZXNvdXJjZUtleSA9IHRoaXMuZ2V0UmVzb3VyY2VLZXlfKHJlc291cmNlKTtcblx0XHRcdGlmIChyZXNvdXJjZUtleSkge1xuXHRcdFx0XHRIdG1sU2NyZWVuLnBlcm1hbmVudFJlc291cmNlc0luRG9jW3Jlc291cmNlS2V5XSA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHR2YXIgZnJhZyA9IGJ1aWxkRnJhZ21lbnQoKTtcblx0XHR0cmFja2VkLmZvckVhY2goKHJlc291cmNlKSA9PiB7XG5cdFx0XHR2YXIgcmVzb3VyY2VLZXkgPSB0aGlzLmdldFJlc291cmNlS2V5XyhyZXNvdXJjZSk7XG5cdFx0XHQvLyBEbyBub3QgbG9hZCBwZXJtYW5lbnQgcmVzb3VyY2VzIGlmIGFscmVhZHkgaW4gZG9jdW1lbnQuXG5cdFx0XHRpZiAoIUh0bWxTY3JlZW4ucGVybWFuZW50UmVzb3VyY2VzSW5Eb2NbcmVzb3VyY2VLZXldKSB7XG5cdFx0XHRcdGZyYWcuYXBwZW5kQ2hpbGQocmVzb3VyY2UpO1xuXHRcdFx0fVxuXHRcdFx0Ly8gSWYgcmVzb3VyY2UgaGFzIGtleSBhbmQgaXMgcGVybWFuZW50IGFkZCB0byBjYWNoZS5cblx0XHRcdGlmIChyZXNvdXJjZUtleSAmJiBtYXRjaChyZXNvdXJjZSwgc2VsZWN0b3JQZXJtYW5lbnQpKSB7XG5cdFx0XHRcdEh0bWxTY3JlZW4ucGVybWFuZW50UmVzb3VyY2VzSW5Eb2NbcmVzb3VyY2VLZXldID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKChyZXNvbHZlKSA9PiB7XG5cdFx0XHRldmFsdWF0b3JGbihmcmFnLCAoKSA9PiB7XG5cdFx0XHRcdHRlbXBvcmFyaWVzSW5Eb2MuZm9yRWFjaCgocmVzb3VyY2UpID0+IGV4aXREb2N1bWVudChyZXNvdXJjZSkpO1xuXHRcdFx0XHRyZXNvbHZlKCk7XG5cdFx0XHR9LCBvcHRfYXBwZW5kUmVzb3VyY2VGbik7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogQE92ZXJyaWRlXG5cdCAqL1xuXHRmbGlwKHN1cmZhY2VzKSB7XG5cdFx0cmV0dXJuIHN1cGVyLmZsaXAoc3VyZmFjZXMpLnRoZW4oKCkgPT4ge1xuXHRcdFx0dXRpbHMuY2xlYXJOb2RlQXR0cmlidXRlcyhkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpO1xuXHRcdFx0dXRpbHMuY29weU5vZGVBdHRyaWJ1dGVzKHRoaXMudmlydHVhbERvY3VtZW50LCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIGEga2V5IHRvIGlkZW50aWZ5IHRoZSByZXNvdXJjZSBiYXNlZCBvbiBpdHMgYXR0cmlidXRlcy5cblx0ICogQHBhcmFtIHtFbGVtZW50fSByZXNvdXJjZVxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9IEV4dHJhY3RlZCBrZXkgYmFzZWQgb24gcmVzb3VyY2UgYXR0cmlidXRlcyBpbiBvcmRlciBvZlxuXHQgKiAgICAgcHJlZmVyZW5jZTogaWQsIGhyZWYsIHNyYy5cblx0ICovXG5cdGdldFJlc291cmNlS2V5XyhyZXNvdXJjZSkge1xuXHRcdHJldHVybiByZXNvdXJjZS5pZCB8fCByZXNvdXJjZS5ocmVmIHx8IHJlc291cmNlLnNyYyB8fCAnJztcblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdERvY1xuXHQgKi9cblx0Z2V0U3VyZmFjZUNvbnRlbnQoc3VyZmFjZUlkKSB7XG5cdFx0dmFyIHN1cmZhY2UgPSB0aGlzLnZpcnR1YWxEb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjJyArIHN1cmZhY2VJZCk7XG5cdFx0aWYgKHN1cmZhY2UpIHtcblx0XHRcdHZhciBkZWZhdWx0Q2hpbGQgPSBzdXJmYWNlLnF1ZXJ5U2VsZWN0b3IoJyMnICsgc3VyZmFjZUlkICsgJy0nICsgU3VyZmFjZS5ERUZBVUxUKTtcblx0XHRcdGlmIChkZWZhdWx0Q2hpbGQpIHtcblx0XHRcdFx0cmV0dXJuIGRlZmF1bHRDaGlsZC5pbm5lckhUTUw7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gc3VyZmFjZS5pbm5lckhUTUw7IC8vIElmIGRlZmF1bHQgY29udGVudCBub3QgZm91bmQsIHVzZSBzdXJmYWNlIGNvbnRlbnRcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgdGl0bGUgc2VsZWN0b3IuXG5cdCAqIEByZXR1cm4geyFzdHJpbmd9XG5cdCAqL1xuXHRnZXRUaXRsZVNlbGVjdG9yKCkge1xuXHRcdHJldHVybiB0aGlzLnRpdGxlU2VsZWN0b3I7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXREb2Ncblx0ICovXG5cdGxvYWQocGF0aCkge1xuXHRcdHJldHVybiBzdXBlci5sb2FkKHBhdGgpXG5cdFx0XHQudGhlbihjb250ZW50ID0+IHtcblx0XHRcdFx0dGhpcy5hbGxvY2F0ZVZpcnR1YWxEb2N1bWVudEZvckNvbnRlbnQoY29udGVudCk7XG5cdFx0XHRcdHRoaXMucmVzb2x2ZVRpdGxlRnJvbVZpcnR1YWxEb2N1bWVudCgpO1xuXHRcdFx0XHR0aGlzLmFzc2VydFNhbWVCb2R5SWRJblZpcnR1YWxEb2N1bWVudCgpO1xuXHRcdFx0XHRpZiAoVUEuaXNJZSkge1xuXHRcdFx0XHRcdHRoaXMubWFrZVRlbXBvcmFyeVN0eWxlc0hyZWZzVW5pcXVlXygpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBjb250ZW50O1xuXHRcdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUXVlcmllcyB0ZW1wb3Jhcnkgc3R5bGVzIGZyb20gdmlydHVhbCBkb2N1bWVudCwgYW5kIG1ha2VzIHRoZW0gdW5pcXVlLlxuXHQgKiBUaGlzIGlzIG5lY2Vzc2FyeSBmb3IgY2FjaGluZyBhbmQgbG9hZCBldmVudCBmaXJpbmcgaXNzdWVzIHNwZWNpZmljIHRvXG5cdCAqIElFMTEuIGh0dHBzOi8vZGV2ZWxvcGVyLm1pY3Jvc29mdC5jb20vZW4tdXMvbWljcm9zb2Z0LWVkZ2UvcGxhdGZvcm0vaXNzdWVzLzc5NDAxNzEvXG5cdCAqL1xuXHRtYWtlVGVtcG9yYXJ5U3R5bGVzSHJlZnNVbmlxdWVfKCkge1xuXHRcdHZhciB0ZW1wb3Jhcmllc0luRG9jID0gdGhpcy52aXJ0dWFsUXVlcnlTZWxlY3RvckFsbF8oSHRtbFNjcmVlbi5zZWxlY3RvcnMuc3R5bGVzVGVtcG9yYXJ5KTtcblx0XHR0ZW1wb3Jhcmllc0luRG9jLmZvckVhY2goKHN0eWxlKSA9PiB0aGlzLnJlcGxhY2VTdHlsZUFuZE1ha2VVbmlxdWVfKHN0eWxlKSk7XG5cdH1cblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBlbGVtZW50IGZyb20gZ2l2ZW4sIGNvcGllcyBhdHRyaWJ1dGVzLCBtdXRhdGVzIGhyZWYgdG8gYmVcblx0ICogdW5pcXVlIHRvIHByZXZlbnQgY2FjaGluZyBhbmQgbW9yZSB0aGFuIG9uZSBsb2FkL2Vycm9yIGV2ZW50IGZyb20gZmlyaW5nLlxuXHQgKi9cblx0cmVwbGFjZVN0eWxlQW5kTWFrZVVuaXF1ZV8oc3R5bGUpIHtcblx0XHRpZiAoc3R5bGUuaHJlZikge1xuXHRcdFx0dmFyIG5ld1N0eWxlID0gZ2xvYmFscy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KHN0eWxlLnRhZ05hbWUpO1xuXHRcdFx0c3R5bGUuaHJlZiA9IG5ldyBVcmkoc3R5bGUuaHJlZikubWFrZVVuaXF1ZSgpLnRvU3RyaW5nKCk7XG5cdFx0XHR1dGlscy5jb3B5Tm9kZUF0dHJpYnV0ZXMoc3R5bGUsIG5ld1N0eWxlKTtcblx0XHRcdHN0eWxlLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1N0eWxlLCBzdHlsZSk7XG5cdFx0XHRzdHlsZS5kaXNhYmxlZCA9IHRydWU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFF1ZXJpZXMgZWxlbWVudHMgZnJvbSB2aXJ0dWFsIGRvY3VtZW50IGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIGVsZW1lbnRzLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNlbGVjdG9yXG5cdCAqIEByZXR1cm4ge2FycmF5LjxFbGVtZW50Pn1cblx0ICovXG5cdHZpcnR1YWxRdWVyeVNlbGVjdG9yQWxsXyhzZWxlY3Rvcikge1xuXHRcdHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLnZpcnR1YWxEb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKSk7XG5cdH1cblxuXHQvKipcblx0ICogUXVlcmllcyBlbGVtZW50cyBmcm9tIGRvY3VtZW50IGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIGVsZW1lbnRzLlxuXHQgKiBAcGFyYW0geyFzdHJpbmd9IHNlbGVjdG9yXG5cdCAqIEByZXR1cm4ge2FycmF5LjxFbGVtZW50Pn1cblx0ICovXG5cdHF1ZXJ5U2VsZWN0b3JBbGxfKHNlbGVjdG9yKSB7XG5cdFx0cmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGdsb2JhbHMuZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbGVhc2VzIHZpcnR1YWwgZG9jdW1lbnQgYWxsb2NhdGVkIGZvciBjb250ZW50LlxuXHQgKi9cblx0cmVsZWFzZVZpcnR1YWxEb2N1bWVudCgpIHtcblx0XHR0aGlzLnZpcnR1YWxEb2N1bWVudCA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogUmVzb2x2ZXMgdGl0bGUgZnJvbSBhbGxvY2F0ZWQgdmlydHVhbCBkb2N1bWVudC5cblx0ICovXG5cdHJlc29sdmVUaXRsZUZyb21WaXJ0dWFsRG9jdW1lbnQoKSB7XG5cdFx0dmFyIHRpdGxlID0gdGhpcy52aXJ0dWFsRG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLnRpdGxlU2VsZWN0b3IpO1xuXHRcdGlmICh0aXRsZSkge1xuXHRcdFx0dGhpcy5zZXRUaXRsZSh0aXRsZS50ZXh0Q29udGVudC50cmltKCkpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB0aXRsZSBzZWxlY3Rvci5cblx0ICogQHBhcmFtIHshc3RyaW5nfSB0aXRsZVNlbGVjdG9yXG5cdCAqL1xuXHRzZXRUaXRsZVNlbGVjdG9yKHRpdGxlU2VsZWN0b3IpIHtcblx0XHR0aGlzLnRpdGxlU2VsZWN0b3IgPSB0aXRsZVNlbGVjdG9yO1xuXHR9XG5cbn1cblxuLyoqXG4gKiBIZWxwZXIgc2VsZWN0b3JzIGZvciB0cmFja2luZyByZXNvdXJjZXMuXG4gKiBAdHlwZSB7b2JqZWN0fVxuICogQHByb3RlY3RlZFxuICogQHN0YXRpY1xuICovXG5IdG1sU2NyZWVuLnNlbGVjdG9ycyA9IHtcblx0c2NyaXB0czogJ3NjcmlwdFtkYXRhLXNlbm5hLXRyYWNrXScsXG5cdHNjcmlwdHNQZXJtYW5lbnQ6ICdzY3JpcHRbZGF0YS1zZW5uYS10cmFjaz1cInBlcm1hbmVudFwiXScsXG5cdHNjcmlwdHNUZW1wb3Jhcnk6ICdzY3JpcHRbZGF0YS1zZW5uYS10cmFjaz1cInRlbXBvcmFyeVwiXScsXG5cdHN0eWxlczogJ3N0eWxlW2RhdGEtc2VubmEtdHJhY2tdLGxpbmtbZGF0YS1zZW5uYS10cmFja10nLFxuXHRzdHlsZXNQZXJtYW5lbnQ6ICdzdHlsZVtkYXRhLXNlbm5hLXRyYWNrPVwicGVybWFuZW50XCJdLGxpbmtbZGF0YS1zZW5uYS10cmFjaz1cInBlcm1hbmVudFwiXScsXG5cdHN0eWxlc1RlbXBvcmFyeTogJ3N0eWxlW2RhdGEtc2VubmEtdHJhY2s9XCJ0ZW1wb3JhcnlcIl0sbGlua1tkYXRhLXNlbm5hLXRyYWNrPVwidGVtcG9yYXJ5XCJdJ1xufTtcblxuLyoqXG4gKiBDYWNoZXMgcGVybWFuZW50IHJlc291cmNlIGtleXMuXG4gKiBAdHlwZSB7b2JqZWN0fVxuICogQHByb3RlY3RlZFxuICogQHN0YXRpY1xuICovXG5IdG1sU2NyZWVuLnBlcm1hbmVudFJlc291cmNlc0luRG9jID0ge307XG5cbmV4cG9ydCBkZWZhdWx0IEh0bWxTY3JlZW47XG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IERpc3Bvc2FibGUsIGdldFVpZCwgaXNEZWZBbmROb3ROdWxsLCBpc0VsZW1lbnQsIG9iamVjdCB9IGZyb20gJ21ldGFsJztcbmltcG9ydCBkYXRhQXR0cmlidXRlcyBmcm9tICcuL2RhdGFBdHRyaWJ1dGVzJztcbmltcG9ydCBnbG9iYWxzIGZyb20gJy4uL2dsb2JhbHMvZ2xvYmFscyc7XG5pbXBvcnQgQXBwIGZyb20gJy4vQXBwJztcbmltcG9ydCBIdG1sU2NyZWVuIGZyb20gJy4uL3NjcmVlbi9IdG1sU2NyZWVuJztcbmltcG9ydCBSb3V0ZSBmcm9tICcuLi9yb3V0ZS9Sb3V0ZSc7XG5cbmNsYXNzIEFwcERhdGFBdHRyaWJ1dGVIYW5kbGVyIGV4dGVuZHMgRGlzcG9zYWJsZSB7XG5cblx0LyoqXG5cdCAqIEluaXRpbGl6ZXMgQXBwLCByZWdpc3RlciBzdXJmYWNlcyBhbmQgcm91dGVzIGZyb20gZGF0YSBhdHRyaWJ1dGVzLlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG5cblx0XHQvKipcblx0XHQgKiBIb2xkcyB0aGUgYXBwIHJlZmVyZW5jZSBpbml0aWFsaXplZCBieSBkYXRhIGF0dHJpYnV0ZXMuXG5cdFx0ICogQHR5cGUge0FwcH1cblx0XHQgKiBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0dGhpcy5hcHAgPSBudWxsO1xuXG5cdFx0LyoqXG5cdFx0ICogSG9sZHMgdGhlIGJhc2UgZWxlbWVudCB0byBzZWFyY2ggaW5pdGlhbGl6YXRpb24gZGF0YSBhdHRyaWJ1dGVzLiBUaGlzXG5cdFx0ICogZWxlbWVudCBpcyB0aGUgY29udGFpbmVyIHVzZWQgdG8gZW5hYmxlIGluaXRpYWxpemF0aW9uIGJhc2VkIG9uIHRoZVxuXHRcdCAqIHByZXNlbmNlIG9mIGBkYXRhLXNlbm5hYCBhdHRyaWJ1dGUuXG5cdFx0ICogQHR5cGUge0VsZW1lbnR9XG5cdFx0ICogQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdHRoaXMuYmFzZUVsZW1lbnQgPSBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEluaXRzIGFwcGxpY2F0aW9uIGJhc2VkIG9uIGluZm9ybWF0aW9uIHNjYW5uZWQgZnJvbSBkb2N1bWVudC5cblx0ICovXG5cdGhhbmRsZSgpIHtcblx0XHRpZiAoIWlzRWxlbWVudCh0aGlzLmJhc2VFbGVtZW50KSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTZW5uYSBkYXRhIGF0dHJpYnV0ZSBoYW5kbGVyIGJhc2UgZWxlbWVudCAnICtcblx0XHRcdFx0J25vdCBzZXQgb3IgaW52YWxpZCwgdHJ5IHNldHRpbmcgYSB2YWxpZCBlbGVtZW50IHRoYXQgJyArXG5cdFx0XHRcdCdjb250YWlucyBhIGBkYXRhLXNlbm5hYCBhdHRyaWJ1dGUuJyk7XG5cdFx0fVxuXG5cdFx0aWYgKCF0aGlzLmJhc2VFbGVtZW50Lmhhc0F0dHJpYnV0ZShkYXRhQXR0cmlidXRlcy5zZW5uYSkpIHtcblx0XHRcdGNvbnNvbGUubG9nKCdTZW5uYSB3YXMgbm90IGluaXRpYWxpemVkIGZyb20gZGF0YSBhdHRyaWJ1dGVzLiAnICtcblx0XHRcdFx0J0luIG9yZGVyIHRvIGVuYWJsZSBpdHMgdXNhZ2UgZnJvbSBkYXRhIGF0dHJpYnV0ZXMgdHJ5IHNldHRpbmcgJyArXG5cdFx0XHRcdCdpbiB0aGUgYmFzZSBlbGVtZW50LCBlLmcuIGA8Ym9keSBkYXRhLXNlbm5hPmAuJyk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMuYXBwKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1Nlbm5hIGFwcCB3YXMgYWxyZWFkeSBpbml0aWFsaXplZC4nKTtcblx0XHR9XG5cblx0XHRjb25zb2xlLmxvZygnU2VubmEgaW5pdGlhbGl6ZWQgZnJvbSBkYXRhIGF0dHJpYnV0ZS4nKTtcblxuXHRcdHRoaXMuYXBwID0gbmV3IEFwcCgpO1xuXHRcdHRoaXMubWF5YmVBZGRSb3V0ZXNfKCk7XG5cdFx0dGhpcy5tYXliZUFkZFN1cmZhY2VzXygpO1xuXHRcdHRoaXMubWF5YmVTZXRCYXNlUGF0aF8oKTtcblx0XHR0aGlzLm1heWJlU2V0TGlua1NlbGVjdG9yXygpO1xuXHRcdHRoaXMubWF5YmVTZXRMb2FkaW5nQ3NzQ2xhc3NfKCk7XG5cdFx0dGhpcy5tYXliZVNldFVwZGF0ZVNjcm9sbFBvc2l0aW9uXygpO1xuXHRcdHRoaXMubWF5YmVEaXNwYXRjaF8oKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwb3NlcyBvZiB0aGlzIGluc3RhbmNlJ3Mgb2JqZWN0IHJlZmVyZW5jZXMuXG5cdCAqIEBvdmVycmlkZVxuXHQgKi9cblx0ZGlzcG9zZUludGVybmFsKCkge1xuXHRcdGlmICh0aGlzLmFwcCkge1xuXHRcdFx0dGhpcy5hcHAuZGlzcG9zZSgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBhcHAgcmVmZXJlbmNlLlxuXHQgKiBAcmV0dXJuIHtBcHB9XG5cdCAqL1xuXHRnZXRBcHAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuYXBwO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGJhc2UgZWxlbWVudC5cblx0ICogQHJldHVybiB7RWxlbWVudH0gYmFzZUVsZW1lbnRcblx0ICovXG5cdGdldEJhc2VFbGVtZW50KCkge1xuXHRcdHJldHVybiB0aGlzLmJhc2VFbGVtZW50O1xuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIGFkZHMgYXBwIHJvdXRlcyBmcm9tIGxpbmsgZWxlbWVudHMgdGhhdCBhcmUgYHNlbm5hLXJvdXRlYC5cblx0ICovXG5cdG1heWJlQWRkUm91dGVzXygpIHtcblx0XHR2YXIgcm91dGVzU2VsZWN0b3IgPSAnbGlua1tyZWw9XCJzZW5uYS1yb3V0ZVwiXSc7XG5cdFx0dGhpcy5xdWVyeVNlbGVjdG9yQWxsQXNBcnJheV8ocm91dGVzU2VsZWN0b3IpLmZvckVhY2goKGxpbmspID0+IHRoaXMubWF5YmVQYXJzZUxpbmtSb3V0ZV8obGluaykpO1xuXHRcdGlmICghdGhpcy5hcHAuaGFzUm91dGVzKCkpIHtcblx0XHRcdHRoaXMuYXBwLmFkZFJvdXRlcyhuZXcgUm91dGUoLy4qLywgSHRtbFNjcmVlbikpO1xuXHRcdFx0Y29uc29sZS5sb2coJ1Nlbm5hIGNhblxcJ3QgZmluZCByb3V0ZSBlbGVtZW50cywgYWRkaW5nIGRlZmF1bHQuJyk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIGFkZHMgYXBwIHN1cmZhY2VzIGJ5IHNjYW5uaW5nIGBkYXRhLXNlbm5hLXN1cmZhY2VgIGRhdGEgYXR0cmlidXRlLlxuXHQgKi9cblx0bWF5YmVBZGRTdXJmYWNlc18oKSB7XG5cdFx0dmFyIHN1cmZhY2VzU2VsZWN0b3IgPSAnWycgKyBkYXRhQXR0cmlidXRlcy5zdXJmYWNlICsgJ10nO1xuXHRcdHRoaXMucXVlcnlTZWxlY3RvckFsbEFzQXJyYXlfKHN1cmZhY2VzU2VsZWN0b3IpLmZvckVhY2goKHN1cmZhY2VFbGVtZW50KSA9PiB7XG5cdFx0XHR0aGlzLnVwZGF0ZUVsZW1lbnRJZElmU3BlY2lhbFN1cmZhY2VfKHN1cmZhY2VFbGVtZW50KTtcblx0XHRcdHRoaXMuYXBwLmFkZFN1cmZhY2VzKHN1cmZhY2VFbGVtZW50LmlkKTtcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNwYXRjaGVzIGFwcCBuYXZpZ2F0aW9uIHRvIHRoZSBjdXJyZW50IHBhdGggd2hlbiBpbml0aWFsaXplcy5cblx0ICovXG5cdG1heWJlRGlzcGF0Y2hfKCkge1xuXHRcdGlmICh0aGlzLmJhc2VFbGVtZW50Lmhhc0F0dHJpYnV0ZShkYXRhQXR0cmlidXRlcy5kaXNwYXRjaCkpIHtcblx0XHRcdHRoaXMuYXBwLmRpc3BhdGNoKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYXBwIHJvdXRlIGJ5IHBhcnNpbmcgdmFsaWQgbGluayBlbGVtZW50cy4gQSB2YWxpZCBsaW5rIGVsZW1lbnQgaXMgb2Zcblx0ICogdGhlIGtpbmQgYHJlbD1cInNlbm5hLXJvdXRlXCJgLlxuXHQgKiBAcGFyYW0ge0VsZW1lbnR9IGxpbmtcblx0ICovXG5cdG1heWJlUGFyc2VMaW5rUm91dGVfKGxpbmspIHtcblx0XHR2YXIgcm91dGUgPSBuZXcgUm91dGUodGhpcy5tYXliZVBhcnNlTGlua1JvdXRlUGF0aF8obGluayksIHRoaXMubWF5YmVQYXJzZUxpbmtSb3V0ZUhhbmRsZXJfKGxpbmspKTtcblx0XHR0aGlzLmFwcC5hZGRSb3V0ZXMocm91dGUpO1xuXHRcdGNvbnNvbGUubG9nKCdTZW5uYSBzY2FubmVkIHJvdXRlICcgKyByb3V0ZS5nZXRQYXRoKCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHBhcnNlIGxpbmsgcm91dGUgaGFuZGxlci5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBsaW5rXG5cdCAqIEByZXR1cm4gez9zdHJpbmd9XG5cdCAqL1xuXHRtYXliZVBhcnNlTGlua1JvdXRlSGFuZGxlcl8obGluaykge1xuXHRcdHZhciBoYW5kbGVyID0gbGluay5nZXRBdHRyaWJ1dGUoJ3R5cGUnKTtcblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKGhhbmRsZXIpKSB7XG5cdFx0XHRoYW5kbGVyID0gb2JqZWN0LmdldE9iamVjdEJ5TmFtZShoYW5kbGVyKTtcblx0XHR9XG5cdFx0cmV0dXJuIGhhbmRsZXI7XG5cdH1cblxuXHQvKipcblx0ICogTWF5YmUgcGFyc2UgbGluayByb3V0ZSBwYXRoLlxuXHQgKiBAcGFyYW0ge0VsZW1lbnR9IGxpbmtcblx0ICogQHJldHVybiB7P3N0cmluZ31cblx0ICovXG5cdG1heWJlUGFyc2VMaW5rUm91dGVQYXRoXyhsaW5rKSB7XG5cdFx0dmFyIHBhdGggPSBsaW5rLmdldEF0dHJpYnV0ZSgnaHJlZicpO1xuXHRcdGlmIChpc0RlZkFuZE5vdE51bGwocGF0aCkpIHtcblx0XHRcdGlmIChwYXRoLmluZGV4T2YoJ3JlZ2V4OicpID09PSAwKSB7XG5cdFx0XHRcdHBhdGggPSBuZXcgUmVnRXhwKHBhdGguc3Vic3RyaW5nKDYpKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHBhdGg7XG5cdH1cblxuXHQvKipcblx0ICogTWF5YmUgc2V0cyBhcHAgYmFzZSBwYXRoIGZyb20gYGRhdGEtc2VubmEtYmFzZS1wYXRoYCBkYXRhIGF0dHJpYnV0ZS5cblx0ICovXG5cdG1heWJlU2V0QmFzZVBhdGhfKCkge1xuXHRcdHZhciBiYXNlUGF0aCA9IHRoaXMuYmFzZUVsZW1lbnQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGVzLmJhc2VQYXRoKTtcblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKGJhc2VQYXRoKSkge1xuXHRcdFx0dGhpcy5hcHAuc2V0QmFzZVBhdGgoYmFzZVBhdGgpO1xuXHRcdFx0Y29uc29sZS5sb2coJ1Nlbm5hIHNjYW5uZWQgYmFzZSBwYXRoICcgKyBiYXNlUGF0aCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHNldHMgYXBwIGxpbmsgc2VsZWN0b3IgZnJvbSBgZGF0YS1zZW5uYS1saW5rLXNlbGVjdG9yYCBkYXRhXG5cdCAqIGF0dHJpYnV0ZS5cblx0ICovXG5cdG1heWJlU2V0TGlua1NlbGVjdG9yXygpIHtcblx0XHR2YXIgbGlua1NlbGVjdG9yID0gdGhpcy5iYXNlRWxlbWVudC5nZXRBdHRyaWJ1dGUoZGF0YUF0dHJpYnV0ZXMubGlua1NlbGVjdG9yKTtcblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKGxpbmtTZWxlY3RvcikpIHtcblx0XHRcdHRoaXMuYXBwLnNldExpbmtTZWxlY3RvcihsaW5rU2VsZWN0b3IpO1xuXHRcdFx0Y29uc29sZS5sb2coJ1Nlbm5hIHNjYW5uZWQgbGluayBzZWxlY3RvciAnICsgbGlua1NlbGVjdG9yKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogTWF5YmUgc2V0cyBhcHAgbGluayBsb2FkaW5nIGNzcyBjbGFzcyBmcm9tIGBkYXRhLXNlbm5hLWxvYWRpbmctY3NzLWNsYXNzYFxuXHQgKiBkYXRhIGF0dHJpYnV0ZS5cblx0ICovXG5cdG1heWJlU2V0TG9hZGluZ0Nzc0NsYXNzXygpIHtcblx0XHR2YXIgbG9hZGluZ0Nzc0NsYXNzID0gdGhpcy5iYXNlRWxlbWVudC5nZXRBdHRyaWJ1dGUoZGF0YUF0dHJpYnV0ZXMubG9hZGluZ0Nzc0NsYXNzKTtcblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKGxvYWRpbmdDc3NDbGFzcykpIHtcblx0XHRcdHRoaXMuYXBwLnNldExvYWRpbmdDc3NDbGFzcyhsb2FkaW5nQ3NzQ2xhc3MpO1xuXHRcdFx0Y29uc29sZS5sb2coJ1Nlbm5hIHNjYW5uZWQgbG9hZGluZyBjc3MgY2xhc3MgJyArIGxvYWRpbmdDc3NDbGFzcyk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1heWJlIHNldHMgYXBwIHVwZGF0ZSBzY3JvbGwgcG9zaXRpb24gZnJvbVxuXHQgKiBgZGF0YS1zZW5uYS11cGRhdGUtc2Nyb2xsLXBvc2l0aW9uYCBkYXRhIGF0dHJpYnV0ZS5cblx0ICovXG5cdG1heWJlU2V0VXBkYXRlU2Nyb2xsUG9zaXRpb25fKCkge1xuXHRcdHZhciB1cGRhdGVTY3JvbGxQb3NpdGlvbiA9IHRoaXMuYmFzZUVsZW1lbnQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGVzLnVwZGF0ZVNjcm9sbFBvc2l0aW9uKTtcblx0XHRpZiAoaXNEZWZBbmROb3ROdWxsKHVwZGF0ZVNjcm9sbFBvc2l0aW9uKSkge1xuXHRcdFx0aWYgKHVwZGF0ZVNjcm9sbFBvc2l0aW9uID09PSAnZmFsc2UnKSB7XG5cdFx0XHRcdHRoaXMuYXBwLnNldFVwZGF0ZVNjcm9sbFBvc2l0aW9uKGZhbHNlKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuYXBwLnNldFVwZGF0ZVNjcm9sbFBvc2l0aW9uKHRydWUpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc29sZS5sb2coJ1Nlbm5hIHNjYW5uZWQgdXBkYXRlIHNjcm9sbCBwb3NpdGlvbiAnICsgdXBkYXRlU2Nyb2xsUG9zaXRpb24pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBRdWVyaWVzIGVsZW1lbnRzIGZyb20gZG9jdW1lbnQgYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgZWxlbWVudHMuXG5cdCAqIEBwYXJhbSB7IXN0cmluZ30gc2VsZWN0b3Jcblx0ICogQHJldHVybiB7YXJyYXkuPEVsZW1lbnQ+fVxuXHQgKi9cblx0cXVlcnlTZWxlY3RvckFsbEFzQXJyYXlfKHNlbGVjdG9yKSB7XG5cdFx0cmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGdsb2JhbHMuZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZXMgZWxlbWVudCBpZCBpZiBoYW5kbGVkIGFzIHNwZWNpYWwgc3VyZmFjZSBlbGVtZW50LiBTb21lIHN1cmZhY2VzXG5cdCAqIGFyZSBzbGlnaHRseSBkaWZmZXJlbnQgZnJvbSBvdGhlcnMsIGxpa2Ugd2hlbiB0aHJlYXRpbmcgPGNvZGU+Ym9keTwvY29kZT5cblx0ICogYXMgc3VyZmFjZS5cblx0ICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG5cdCAqL1xuXHR1cGRhdGVFbGVtZW50SWRJZlNwZWNpYWxTdXJmYWNlXyhlbGVtZW50KSB7XG5cdFx0aWYgKCFlbGVtZW50LmlkICYmIGVsZW1lbnQgPT09IGdsb2JhbHMuZG9jdW1lbnQuYm9keSkge1xuXHRcdFx0ZWxlbWVudC5pZCA9ICdzZW5uYV9zdXJmYWNlXycgKyBnZXRVaWQoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgYmFzZSBlbGVtZW50LlxuXHQgKiBAcGFyYW0ge0VsZW1lbnR9IGJhc2VFbGVtZW50XG5cdCAqL1xuXHRzZXRCYXNlRWxlbWVudChiYXNlRWxlbWVudCkge1xuXHRcdHRoaXMuYmFzZUVsZW1lbnQgPSBiYXNlRWxlbWVudDtcblx0fVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEFwcERhdGFBdHRyaWJ1dGVIYW5kbGVyO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgZ2xvYmFscyBmcm9tICcuLi9nbG9iYWxzL2dsb2JhbHMnO1xuaW1wb3J0IEFwcERhdGFBdHRyaWJ1dGVIYW5kbGVyIGZyb20gJy4vQXBwRGF0YUF0dHJpYnV0ZUhhbmRsZXInO1xuXG4vKipcbiAqIERhdGEgYXR0cmlidXRlIGhhbmRsZXIuXG4gKiBAdHlwZSB7QXBwRGF0YUF0dHJpYnV0ZUhhbmRsZXJ9XG4gKi9cbnZhciBkYXRhQXR0cmlidXRlSGFuZGxlciA9IG5ldyBBcHBEYXRhQXR0cmlidXRlSGFuZGxlcigpO1xuXG5nbG9iYWxzLmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCBmdW5jdGlvbigpIHtcblx0ZGF0YUF0dHJpYnV0ZUhhbmRsZXIuc2V0QmFzZUVsZW1lbnQoZ2xvYmFscy5kb2N1bWVudC5ib2R5KTtcblx0ZGF0YUF0dHJpYnV0ZUhhbmRsZXIuaGFuZGxlKCk7XG59KTtcblxuZXhwb3J0IGRlZmF1bHQgZGF0YUF0dHJpYnV0ZUhhbmRsZXI7IiwiLyoqXG4gKiBAcmV0dXJucyBTdHJpbmcgY3VycmVudCBzZW5uYSB2ZXJzaW9uXG4gKi9cbmV4cG9ydCBkZWZhdWx0ICc8JT0gdmVyc2lvbiAlPic7Il0sIm5hbWVzIjpbImdsb2JhbHMiLCJ3aW5kb3ciLCJkb2N1bWVudCIsImNvbXBhdGliaWxpdHlNb2RlRGF0YV8iLCJ1bmlxdWVJZENvdW50ZXJfIiwiVUlEX1BST1BFUlRZIiwiTWF0aCIsInJhbmRvbSIsImFic3RyYWN0TWV0aG9kIiwiRXJyb3IiLCJkaXNhYmxlQ29tcGF0aWJpbGl0eU1vZGUiLCJ1bmRlZmluZWQiLCJlbmFibGVDb21wYXRpYmlsaXR5TW9kZSIsIm9wdF9kYXRhIiwiZ2V0Q29tcGF0aWJpbGl0eU1vZGVEYXRhIiwiX19NRVRBTF9DT01QQVRJQklMSVRZX18iLCJnZXRGaXJzdFRydXRoeV8iLCJhIiwiYiIsImdldEZ1bmN0aW9uTmFtZSIsImZuIiwibmFtZSIsInN0ciIsInRvU3RyaW5nIiwic3Vic3RyaW5nIiwiaW5kZXhPZiIsImdldFN0YXRpY1Byb3BlcnR5IiwiY3RvciIsInByb3BlcnR5TmFtZSIsIm9wdF9tZXJnZUZuIiwibWVyZ2VkTmFtZSIsImhhc093blByb3BlcnR5IiwibWVyZ2VkIiwiX19wcm90b19fIiwiaXNQcm90b3R5cGVPZiIsIkZ1bmN0aW9uIiwibWVyZ2VGbiIsImdldFVpZCIsIm9wdF9vYmplY3QiLCJvcHRfbm9Jbmhlcml0YW5jZSIsImlkIiwiaWRlbnRpdHlGdW5jdGlvbiIsIm9wdF9yZXR1cm5WYWx1ZSIsImlzQm9vbGVhbiIsInZhbCIsImlzRGVmIiwiaXNEZWZBbmROb3ROdWxsIiwiaXNOdWxsIiwiaXNEb2N1bWVudCIsIm5vZGVUeXBlIiwiaXNEb2N1bWVudEZyYWdtZW50IiwiaXNFbGVtZW50IiwiaXNGdW5jdGlvbiIsImlzTnVtYmVyIiwiaXNXaW5kb3ciLCJpc09iamVjdCIsInR5cGUiLCJpc1Byb21pc2UiLCJ0aGVuIiwiaXNTdHJpbmciLCJTdHJpbmciLCJpc1NlcnZlclNpZGUiLCJwcm9jZXNzIiwiZW52IiwiTk9ERV9FTlYiLCJicm93c2VyIiwibnVsbEZ1bmN0aW9uIiwiYXJyYXkiLCJhcnIxIiwiYXJyMiIsImxlbmd0aCIsImkiLCJhcnIiLCJvcHRfb3V0cHV0Iiwib3V0cHV0IiwiQXJyYXkiLCJpc0FycmF5IiwiZmxhdHRlbiIsInB1c2giLCJvYmoiLCJydiIsInJlbW92ZUF0IiwicHJvdG90eXBlIiwic3BsaWNlIiwiY2FsbCIsInN0YXJ0Iiwib3B0X2VuZCIsInNsaWNlZCIsImVuZCIsImFzeW5jIiwidGhyb3dFeGNlcHRpb24iLCJleGNlcHRpb24iLCJuZXh0VGljayIsInJ1biIsImNhbGxiYWNrIiwib3B0X2NvbnRleHQiLCJ3b3JrUXVldWVTY2hlZHVsZWRfIiwicHJvY2Vzc1dvcmtRdWV1ZSIsIndvcmtRdWV1ZV8iLCJXb3JrSXRlbV8iLCJ3b3JrSXRlbXMiLCJ3b3JrSXRlbSIsInNjb3BlIiwiZSIsImNiIiwiYmluZCIsIndyYXBDYWxsYmFja18iLCJzZXRJbW1lZGlhdGUiLCJzZXRJbW1lZGlhdGVfIiwiZ2V0U2V0SW1tZWRpYXRlRW11bGF0b3JfIiwiQ2hhbm5lbCIsIk1lc3NhZ2VDaGFubmVsIiwicG9zdE1lc3NhZ2UiLCJhZGRFdmVudExpc3RlbmVyIiwiaWZyYW1lIiwiY3JlYXRlRWxlbWVudCIsInN0eWxlIiwiZGlzcGxheSIsInNyYyIsImRvY3VtZW50RWxlbWVudCIsImFwcGVuZENoaWxkIiwid2luIiwiY29udGVudFdpbmRvdyIsImRvYyIsIm9wZW4iLCJ3cml0ZSIsImNsb3NlIiwibWVzc2FnZSIsIm9yaWdpbiIsImxvY2F0aW9uIiwicHJvdG9jb2wiLCJob3N0Iiwib25tZXNzYWdlIiwiZGF0YSIsInBvcnQxIiwicG9ydDIiLCJjaGFubmVsIiwiaGVhZCIsInRhaWwiLCJuZXh0Iiwic2NyaXB0Iiwib25yZWFkeXN0YXRlY2hhbmdlIiwicGFyZW50Tm9kZSIsInJlbW92ZUNoaWxkIiwiRGlzcG9zYWJsZSIsImRpc3Bvc2VkXyIsImRpc3Bvc2VJbnRlcm5hbCIsIm9iamVjdCIsInRhcmdldCIsImtleSIsInNvdXJjZSIsImFyZ3VtZW50cyIsIm9wdF9vYmoiLCJwYXJ0cyIsInNwbGl0IiwicmVkdWNlIiwicGFydCIsIm1hcHBlZE9iaiIsImtleXMiLCJPYmplY3QiLCJvYmoxIiwib2JqMiIsImtleXMxIiwia2V5czIiLCJzdHJpbmciLCJzdHIxIiwic3RyMiIsInRlc3QxIiwidG9Mb3dlckNhc2UiLCJ0ZXN0MiIsInJlcGxhY2UiLCJ4IiwiZmxvb3IiLCJhYnMiLCJEYXRlIiwibm93IiwiaGFzaCIsImxlbiIsImNoYXJDb2RlQXQiLCJ2YWx1ZSIsInBhcnNlRnJvbUFuY2hvciIsIm9wdF91cmkiLCJsaW5rIiwiaHJlZiIsInRlc3QiLCJUeXBlRXJyb3IiLCJob3N0bmFtZSIsInBhc3N3b3JkIiwicGF0aG5hbWUiLCJwb3J0Iiwic2VhcmNoIiwidXNlcm5hbWUiLCJwYXJzZSIsIlVSTCIsInVybCIsImNyZWF0ZSIsIk11bHRpTWFwIiwidmFsdWVzIiwic2l6ZSIsIm1hcCIsIm5hbWVzIiwiSlNPTiIsInN0cmluZ2lmeSIsInNldCIsIlRyZWVOb2RlIiwidmFsdWVfIiwicGFyZW50XyIsImNoaWxkcmVuXyIsImNoaWxkIiwic2V0UGFyZW50Iiwibm9kZSIsImN1cnJlbnQiLCJnZXRQYXJlbnQiLCJhbmNlc3RvcnMiLCJpbmRleCIsImdldENoaWxkcmVuIiwiRU1QVFlfQVJSQVkiLCJkZXB0aCIsInJvb3QiLCJnZXRDaGlsZENvdW50IiwicmVtb3ZlIiwicGFyZW50Iiwib3B0X3ByZW9yZGVyRm4iLCJvcHRfcG9zdG9yZGVyRm4iLCJmb3JFYWNoIiwidHJhdmVyc2UiLCJhc3NlcnRDaGlsZEhhc05vUGFyZW50IiwicGFyc2VGbl8iLCJVcmkiLCJtYXliZUFkZFByb3RvY29sQW5kSG9zdG5hbWVfIiwibXVsdGltYXAiLCJnZXRBbGwiLCJhZGRQYXJhbWV0ZXJWYWx1ZSIsImVuc3VyZVF1ZXJ5SW5pdGlhbGl6ZWRfIiwicXVlcnkiLCJhZGQiLCJwYXJhbSIsInVybERlY29kZSIsImdldEhvc3RuYW1lIiwiZ2V0UG9ydCIsIkhPU1ROQU1FX1BMQUNFSE9MREVSIiwiZ2V0SG9zdCIsImdldFByb3RvY29sIiwiZ2V0IiwicXVlcnlzdHJpbmciLCJnZXRQYXJhbWV0ZXJOYW1lcyIsImdldFBhcmFtZXRlclZhbHVlcyIsImVuY29kZVVSSUNvbXBvbmVudCIsInNsaWNlIiwiY29udGFpbnMiLCJzZXRQYXJhbWV0ZXJWYWx1ZSIsIlJBTkRPTV9QQVJBTSIsImdldFJhbmRvbVN0cmluZyIsIkRFRkFVTFRfUFJPVE9DT0wiLCJjaGFyQXQiLCJyZW1vdmVQYXJhbWV0ZXIiLCJnZXRQYXRobmFtZSIsImdldFNlYXJjaCIsImdldEhhc2giLCJwYXJzZUZuIiwiYmFzZVBhdGgiLCJwYXRocyIsInBhdGgiLCJjb25jYXQiLCJqb2luIiwiZGVjb2RlVVJJQ29tcG9uZW50IiwiaXNTZWN1cmUiLCJ1dGlscyIsImF0dHJpYnV0ZXMiLCJhdHRyaWJ1dGUiLCJzZXRBdHRyaWJ1dGUiLCJnZXRDdXJyZW50QnJvd3NlclBhdGhXaXRob3V0SGFzaCIsIm9mZnNldExlZnQiLCJvZmZzZXRUb3AiLCJvZmZzZXRQYXJlbnQiLCJ1cmkiLCJjdXJyZW50QnJvd3NlclBhdGgiLCJnZXRVcmxQYXRoV2l0aG91dEhhc2giLCJnZXRVcmxQYXRoIiwiaGlzdG9yeSIsInB1c2hTdGF0ZSIsImVyciIsImVycm9yIiwicmVtb3ZlQXR0cmlidXRlIiwic3Vic3RyIiwiTUVUQUxfREFUQSIsImRvbURhdGEiLCJlbGVtZW50Iiwib3B0X25hbWUiLCJvcHRfaW5pdGlhbFZhbCIsIkV2ZW50SGFuZGxlIiwiZW1pdHRlciIsImV2ZW50IiwibGlzdGVuZXIiLCJlbWl0dGVyXyIsImV2ZW50XyIsImxpc3RlbmVyXyIsInJlbW92ZUxpc3RlbmVyIiwiaXNEaXNwb3NlZCIsInNpbmdsZUFycmF5XyIsIkV2ZW50RW1pdHRlciIsImV2ZW50c18iLCJsaXN0ZW5lckhhbmRsZXJzXyIsInNob3VsZFVzZUZhY2FkZV8iLCJob2xkZXIiLCJoYW5kbGVyIiwib3B0X2RlZmF1bHQiLCJ2YWxpZGF0ZUxpc3RlbmVyXyIsImV2ZW50cyIsInRvRXZlbnRzQXJyYXlfIiwiYWRkU2luZ2xlTGlzdGVuZXJfIiwib3B0X29yaWdpbiIsInJ1bkxpc3RlbmVySGFuZGxlcnNfIiwiYWRkSGFuZGxlcl8iLCJnZXRTaG91bGRVc2VGYWNhZGUiLCJmYWNhZGUiLCJwcmV2ZW50ZWREZWZhdWx0IiwibGlzdGVuZXJzIiwiZ2V0UmF3TGlzdGVuZXJzXyIsImFyZ3MiLCJydW5MaXN0ZW5lcnNfIiwiYnVpbGRGYWNhZGVfIiwiZGlyZWN0TGlzdGVuZXJzIiwidG9BcnJheSIsImFtb3VudCIsIm1hbnlfIiwic2VsZiIsImhhbmRsZXJJbnRlcm5hbCIsImFwcGx5IiwibGlzdGVuZXJPYmoiLCJyZW1vdmVNYXRjaGluZ0xpc3RlbmVyT2Jqc18iLCJhZGRMaXN0ZW5lciIsIm1hbnkiLCJvcHRfZXZlbnRzIiwibGlzdGVuZXJPYmpzIiwiZmluYWxMaXN0ZW5lcnMiLCJtYXRjaGVzTGlzdGVuZXJfIiwib2ZmIiwiaGFuZGxlcnMiLCJkZWZhdWx0TGlzdGVuZXJzIiwiZGVmYXVsdCIsImoiLCJzaG91bGRVc2VGYWNhZGUiLCJFdmVudEVtaXR0ZXJQcm94eSIsIm9yaWdpbkVtaXR0ZXIiLCJ0YXJnZXRFbWl0dGVyIiwib3B0X2JsYWNrbGlzdCIsIm9wdF93aGl0ZWxpc3QiLCJibGFja2xpc3RfIiwib3JpZ2luRW1pdHRlcl8iLCJwZW5kaW5nRXZlbnRzXyIsInByb3hpZWRFdmVudHNfIiwidGFyZ2V0RW1pdHRlcl8iLCJ3aGl0ZWxpc3RfIiwic3RhcnRQcm94eV8iLCJvbiIsInJlbW92ZUxpc3RlbmVyc18iLCJlbWl0Iiwic2hvdWxkUHJveHlFdmVudF8iLCJ0cnlUb0FkZExpc3RlbmVyXyIsInByb3h5RXZlbnQiLCJvbkxpc3RlbmVyIiwiYWRkTGlzdGVuZXJfIiwiZW1pdE9uVGFyZ2V0XyIsIkV2ZW50SGFuZGxlciIsImV2ZW50SGFuZGxlc18iLCJEb21EZWxlZ2F0ZWRFdmVudEhhbmRsZSIsIm9wdF9zZWxlY3RvciIsInNlbGVjdG9yXyIsImRlbGVnYXRpbmciLCJzZWxlY3RvciIsInNlbGVjdG9ycyIsIkRvbUV2ZW50SGFuZGxlIiwib3B0X2NhcHR1cmUiLCJjYXB0dXJlXyIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJlbGVtZW50c0J5VGFnXyIsInN1cHBvcnRDYWNoZV8iLCJjdXN0b21FdmVudHMiLCJMQVNUX0NPTlRBSU5FUiIsIlVTRV9DQVBUVVJFIiwiYWRkQ2xhc3NlcyIsImVsZW1lbnRzIiwiY2xhc3NlcyIsImFkZENsYXNzZXNXaXRoTmF0aXZlXyIsImNsYXNzTmFtZSIsImNsYXNzTGlzdCIsImFkZENsYXNzZXNXaXRob3V0TmF0aXZlXyIsImVsZW1lbnRDbGFzc05hbWUiLCJjbGFzc2VzVG9BcHBlbmQiLCJhZGRFbGVtZW50TGlzdGVuZXJfIiwiZXZlbnROYW1lIiwiYWRkU2VsZWN0b3JMaXN0ZW5lcl8iLCJkZWxlZ2F0aW5nRGF0YSIsImFkZFRvQXJyXyIsImF0dGFjaERlbGVnYXRlRXZlbnRfIiwiaGFuZGxlRGVsZWdhdGVFdmVudF8iLCJjbG9zZXN0IiwibWF0Y2giLCJhcHBlbmQiLCJidWlsZEZyYWdtZW50IiwiTm9kZUxpc3QiLCJjaGlsZEFyciIsImh0bWxTdHJpbmciLCJ0ZW1wRGl2IiwiaW5uZXJIVE1MIiwiZmlyc3RDaGlsZCIsImZyYWdtZW50IiwiY3JlYXRlRG9jdW1lbnRGcmFnbWVudCIsImVsZW1lbnQxIiwiZWxlbWVudDIiLCJkZWxlZ2F0ZSIsInNlbGVjdG9yT3JUYXJnZXQiLCJjdXN0b21Db25maWciLCJvcmlnaW5hbEV2ZW50IiwiZGVmYXVsdExpc3RlbmVyXyIsImlzQWJsZVRvSW50ZXJhY3RXaXRoXyIsIm9wdF9ldmVudE9iaiIsImJ1dHRvbiIsIm1hdGNoZXNTZWxlY3RvciIsInRhZ05hbWUiLCJkaXNhYmxlZCIsImV4aXREb2N1bWVudCIsInJldCIsImNvbnRhaW5lciIsImN1cnJlbnRUYXJnZXQiLCJkZWZGbnMiLCJ0cmlnZ2VyRGVsZWdhdGVkTGlzdGVuZXJzXyIsInRyaWdnZXJEZWZhdWx0RGVsZWdhdGVkTGlzdGVuZXJzXyIsImRlbGVnYXRlVGFyZ2V0IiwicCIsIkVsZW1lbnQiLCJtIiwibWF0Y2hlcyIsIndlYmtpdE1hdGNoZXNTZWxlY3RvciIsIm1vek1hdGNoZXNTZWxlY3RvciIsIm1zTWF0Y2hlc1NlbGVjdG9yIiwib01hdGNoZXNTZWxlY3RvciIsIm1hdGNoRmFsbGJhY2tfIiwibm9kZXMiLCJxdWVyeVNlbGVjdG9yQWxsIiwibm9ybWFsaXplRGVsZWdhdGVFdmVudF8iLCJzdG9wUHJvcGFnYXRpb24iLCJzdG9wUHJvcGFnYXRpb25fIiwic3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uIiwic3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uXyIsIm9uY2UiLCJkb21FdmVudEhhbmRsZSIsInJlZ2lzdGVyQ3VzdG9tRXZlbnQiLCJyZW1vdmVDaGlsZHJlbiIsInJlbW92ZUNsYXNzZXMiLCJyZW1vdmVDbGFzc2VzV2l0aE5hdGl2ZV8iLCJyZW1vdmVDbGFzc2VzV2l0aG91dE5hdGl2ZV8iLCJ0cmltIiwic3RvcHBlZCIsInN0b3BwZWRJbW1lZGlhdGUiLCJzdXBwb3J0c0V2ZW50IiwidGFnIiwiZGVmYXVsdFByZXZlbnRlZCIsImRlZmF1bHRGbnMiLCJjdXJyRWxlbWVudCIsImxpbWl0IiwidHJpZ2dlckVsZW1lbnRMaXN0ZW5lcnNfIiwidHJpZ2dlclNlbGVjdG9yTGlzdGVuZXJzXyIsImxhc3RDb250YWluZXIiLCJ0cmlnZ2VyTGlzdGVuZXJzXyIsIkRvbUV2ZW50RW1pdHRlclByb3h5IiwiaXNEZWxlZ2F0ZUV2ZW50XyIsImJhYmVsSGVscGVycy5nZXQiLCJpc1N1cHBvcnRlZERvbUV2ZW50XyIsImZlYXR1cmVzIiwiYW5pbWF0aW9uRXZlbnROYW1lXyIsImNoZWNrQW5pbWF0aW9uRXZlbnROYW1lXyIsInByZWZpeGVzIiwidHlwZVRpdGxlQ2FzZSIsInJlcGxhY2VJbnRlcnZhbCIsInRvVXBwZXJDYXNlIiwic3VmZml4ZXMiLCJhbmltYXRpb25FbGVtZW50XyIsImF0dHJPcmRlckNoYW5nZV8iLCJvcmlnaW5hbENvbnRlbnQiLCJnbG9iYWxFdmFsIiwidGV4dCIsIm9wdF9hcHBlbmRGbiIsIm9wdF9jYWxsYmFjayIsInJ1bkZpbGUiLCJzY3JpcHRzIiwicnVuU2NyaXB0c0luT3JkZXIiLCJydW5TY3JpcHQiLCJpdGVtIiwiZ2xvYmFsRXZhbFN0eWxlcyIsInJlbCIsInJ1blN0eWxlIiwic3R5bGVzIiwibG9hZENvdW50IiwibW91c2VFdmVudE1hcCIsInJlbGF0ZWQiLCJyZWxhdGVkVGFyZ2V0IiwiY3VzdG9tVHlwZSIsImFuaW1hdGlvbkV2ZW50TWFwIiwiZXZlbnRUeXBlIiwiY2hlY2tBbmltYXRpb25FdmVudE5hbWUiLCJUaGVuYWJsZSIsIklNUExFTUVOVEVEX0JZX1BST1AiLCJhZGRJbXBsZW1lbnRhdGlvbiIsIiRnb29nX1RoZW5hYmxlIiwiaXNJbXBsZW1lbnRlZEJ5IiwicGFydGlhbCIsIm5ld0FyZ3MiLCJDYW5jZWxsYWJsZVByb21pc2UiLCJyZXNvbHZlciIsInN0YXRlXyIsIlN0YXRlXyIsIlBFTkRJTkciLCJyZXN1bHRfIiwiY2FsbGJhY2tFbnRyaWVzXyIsImV4ZWN1dGluZ18iLCJVTkhBTkRMRURfUkVKRUNUSU9OX0RFTEFZIiwidW5oYW5kbGVkUmVqZWN0aW9uSWRfIiwiaGFkVW5oYW5kbGVkUmVqZWN0aW9uXyIsInJlc29sdmVfIiwiRlVMRklMTEVEIiwicmVhc29uIiwiUkVKRUNURUQiLCJDYWxsYmFja0VudHJ5XyIsInJlc29sdmUiLCJvcHRfdmFsdWUiLCJyZWplY3QiLCJvcHRfcmVhc29uIiwicmFjZSIsInByb21pc2VzIiwicHJvbWlzZSIsImFsbCIsInRvRnVsZmlsbCIsIm9uRnVsZmlsbCIsIm9uUmVqZWN0IiwiZmlyc3RGdWxmaWxsZWQiLCJ0b1JlamVjdCIsInJlYXNvbnMiLCJvcHRfb25GdWxmaWxsZWQiLCJvcHRfb25SZWplY3RlZCIsImFkZENoaWxkUHJvbWlzZV8iLCJ0aGVuQWx3YXlzIiwib25SZXNvbHZlZCIsImhhbmRsZVJlamVjdGlvbl8iLCJhZGRDYWxsYmFja0VudHJ5XyIsInRoZW5DYXRjaCIsIm9uUmVqZWN0ZWQiLCJjYXRjaCIsImNhbmNlbCIsIm9wdF9tZXNzYWdlIiwiQ2FuY2VsbGF0aW9uRXJyb3IiLCJJU19DQU5DRUxMQVRJT05fRVJST1IiLCJjYW5jZWxJbnRlcm5hbF8iLCJjYW5jZWxDaGlsZF8iLCJjaGlsZFByb21pc2UiLCJjaGlsZENvdW50IiwiY2hpbGRJbmRleCIsImVudHJ5IiwiY2FsbGJhY2tFbnRyeSIsImV4ZWN1dGVDYWxsYmFja18iLCJzY2hlZHVsZUNhbGxiYWNrc18iLCJvbkZ1bGZpbGxlZCIsInJlc3VsdCIsInVuYmxvY2tBbmRGdWxmaWxsXyIsIkJMT0NLRUQiLCJ1bmJsb2NrQW5kUmVqZWN0XyIsInN0YXRlIiwidHJ5VGhlbl8iLCJhZGRVbmhhbmRsZWRSZWplY3Rpb25fIiwidGhlbmFibGUiLCJjYWxsZWQiLCJleGVjdXRlQ2FsbGJhY2tzXyIsImVudHJpZXMiLCJyZW1vdmVVbmhhbmRsZWRSZWplY3Rpb25fIiwic2V0VGltZW91dCIsInNldFVuaGFuZGxlZFJlamVjdGlvbkhhbmRsZXIiLCJkZWJvdW5jZSIsImRlbGF5IiwiZGVib3VuY2VkIiwiY2FuY2VsRGVib3VuY2UiLCJSRUdFWCIsImNvbnZlcnRNYXRjaGVzVG9PYmoiLCJjb252ZXJ0VG9rZW5zVG9SZWdleCIsInRva2VucyIsInJlZ2V4IiwiY29yZSIsImVzY2FwZSIsImNhcHR1cmUiLCJlbmNsb3NlTm9uQ2FwdHVyaW5nR3JvdXAiLCJwYXR0ZXJuIiwicmVwZWF0IiwicHJlZml4Iiwib3B0aW9uYWwiLCJSZWdFeHAiLCJtYWtlVHJhaWxpbmdTbGFzaE9wdGlvbmFsIiwicm91dGVPclRva2VucyIsInJvdXRlIiwidW5uYW1lZENvdW50IiwiY3VyclBhdGgiLCJleGVjIiwicGFyYW1QYXR0ZXJuIiwidW5uYW1lZFBhdHRlcm4iLCJtb2RpZmllciIsInRvUmVnZXgiLCJleHRyYWN0RGF0YSIsInBhcmFtSW5kZXgiLCJSb3V0ZSIsInBhcnNlZERhdGFfIiwiYnVpbGRQYXJzZWREYXRhXyIsIkNhY2hlYWJsZSIsImNhY2hlIiwiY2FjaGVhYmxlIiwiY29udGVudCIsImNsZWFyQ2FjaGUiLCJTY3JlZW4iLCJtYWtlSWRfIiwidGl0bGUiLCJsb2ciLCJzdXJmYWNlcyIsInNJZCIsImFjdGl2ZUNoaWxkIiwicnVuU2NyaXB0c0luRWxlbWVudCIsInRyYW5zaXRpb25zIiwic3VyZmFjZSIsImRlZmVycmVkIiwic2hvdyIsIlN1cmZhY2UiLCJkZWZhdWx0Q2hpbGQiLCJ0cmFuc2l0aW9uRm4iLCJnZXRDaGlsZCIsIkRFRkFVTFQiLCJtYXliZVdyYXBDb250ZW50QXNEZWZhdWx0XyIsInNjcmVlbklkIiwib3B0X2NvbnRlbnQiLCJjcmVhdGVDaGlsZCIsInRyYW5zaXRpb24iLCJnZXRFbGVtZW50IiwiZ2V0RWxlbWVudEJ5SWQiLCJhZGRDb250ZW50IiwiZnJvbSIsInRvIiwiZGVmYXVsdFRyYW5zaXRpb24iLCJBcHAiLCJhY3RpdmVTY3JlZW4iLCJhY3RpdmVQYXRoIiwiYWxsb3dQcmV2ZW50TmF2aWdhdGUiLCJicm93c2VyUGF0aEJlZm9yZU5hdmlnYXRlIiwiY2FwdHVyZVNjcm9sbFBvc2l0aW9uRnJvbVNjcm9sbEV2ZW50IiwiZGVmYXVsdFRpdGxlIiwiZm9ybVNlbGVjdG9yIiwiaWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoIiwibGlua1NlbGVjdG9yIiwibG9hZGluZ0Nzc0NsYXNzIiwibmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25TdXBwb3J0ZWQiLCJpc05hdmlnYXRpb25QZW5kaW5nIiwicGVuZGluZ05hdmlnYXRlIiwicG9wc3RhdGVTY3JvbGxMZWZ0IiwicG9wc3RhdGVTY3JvbGxUb3AiLCJyZWRpcmVjdFBhdGgiLCJyb3V0ZXMiLCJzY3JlZW5zIiwic2tpcExvYWRQb3BzdGF0ZSIsInVwZGF0ZVNjcm9sbFBvc2l0aW9uIiwiYXBwRXZlbnRIYW5kbGVyc18iLCJvblNjcm9sbF8iLCJvbkxvYWRfIiwib25Qb3BzdGF0ZV8iLCJvblN0YXJ0TmF2aWdhdGVfIiwib25CZWZvcmVOYXZpZ2F0ZV8iLCJvbkJlZm9yZU5hdmlnYXRlRGVmYXVsdF8iLCJvbkJlZm9yZVVubG9hZERlZmF1bHRfIiwic2V0TGlua1NlbGVjdG9yIiwic2V0Rm9ybVNlbGVjdG9yIiwibWF5YmVPdmVybG9hZEJlZm9yZVVubG9hZF8iLCJnZXRJZCIsImlzV2ViVXJpIiwiaXNMaW5rU2FtZU9yaWdpbl8iLCJpc1NhbWVCYXNlUGF0aF8iLCJpc0N1cnJlbnRCcm93c2VyUGF0aCIsImZpbmRSb3V0ZSIsInJlbW92ZVNjcmVlbiIsInNjcmVlbiIsImdldEhhbmRsZXIiLCJjbGVhclNjcmVlbnNDYWNoZSIsImZvcm1FdmVudEhhbmRsZXJfIiwibGlua0V2ZW50SGFuZGxlcl8iLCJyZW1vdmVBbGxMaXN0ZW5lcnMiLCJuYXZpZ2F0ZSIsImdldEN1cnJlbnRCcm93c2VyUGF0aCIsIm9wdF9yZXBsYWNlSGlzdG9yeSIsImJlZm9yZURlYWN0aXZhdGUiLCJzdG9wUGVuZGluZ05hdmlnYXRlXyIsIm5leHRTY3JlZW4iLCJjcmVhdGVTY3JlZW5JbnN0YW5jZSIsImxvYWQiLCJkZWFjdGl2YXRlIiwicHJlcGFyZU5hdmlnYXRlSGlzdG9yeV8iLCJwcmVwYXJlTmF2aWdhdGVTdXJmYWNlc18iLCJleHRyYWN0UGFyYW1zIiwiZXZhbHVhdGVTdHlsZXMiLCJmbGlwIiwiZXZhbHVhdGVTY3JpcHRzIiwibWF5YmVVcGRhdGVTY3JvbGxQb3NpdGlvblN0YXRlXyIsInN5bmNTY3JvbGxQb3NpdGlvblN5bmNUaGVuQXN5bmNfIiwiZmluYWxpemVOYXZpZ2F0ZV8iLCJoYW5kbGVOYXZpZ2F0ZUVycm9yXyIsImdldFJvdXRlUGF0aCIsImFjdGl2YXRlIiwiaXNDYWNoZWFibGUiLCJjYXB0dXJlZEZvcm1FbGVtZW50IiwiY2FwdHVyZWRGb3JtQnV0dG9uRWxlbWVudCIsIm1hdGNoZXNQYXRoIiwiZ2V0SWdub3JlUXVlcnlTdHJpbmdGcm9tUm91dGVQYXRoIiwiZ2V0VXJsUGF0aFdpdGhvdXRIYXNoQW5kU2VhcmNoIiwid2lubmVyIiwic3dpdGNoU2Nyb2xsUG9zaXRpb25SYWNlIiwic2Nyb2xsVG8iLCJzY3JvbGxMZWZ0Iiwic2Nyb2xsVG9wIiwibmF0aXZlU2Nyb2xsUmVzdG9yYXRpb25fIiwic2Nyb2xsUmVzdG9yYXRpb24iLCJjYW5OYXZpZ2F0ZSIsIm5hdmlnYXRlRmFpbGVkIiwicHJldmVudERlZmF1bHQiLCJvbmJlZm9yZXVubG9hZCIsIl9vbmJlZm9yZXVubG9hZCIsIl9vdmVybG9hZGVkIiwiYW5jaG9yRWxlbWVudCIsImdldE5vZGVPZmZzZXQiLCJzYXZlSGlzdG9yeUN1cnJlbnRQYWdlU2Nyb2xsUG9zaXRpb25fIiwib3B0X2V2ZW50IiwiaXNIdG1sNUhpc3RvcnlTdXBwb3J0ZWQiLCJmb3JtIiwicmVwbGFjZUhpc3RvcnkiLCJmdW5jIiwiYWx0S2V5IiwiY3RybEtleSIsIm1ldGFLZXkiLCJzaGlmdEtleSIsIm1heWJlTmF2aWdhdGVfIiwibWV0aG9kIiwiYnV0dG9uU2VsZWN0b3IiLCJhY3RpdmVFbGVtZW50IiwicXVlcnlTZWxlY3RvciIsImFjdGlvbiIsIm1heWJlUmVwb3NpdGlvblNjcm9sbFRvSGFzaGVkQW5jaG9yIiwicmVsb2FkUGFnZSIsInNlbm5hIiwibG9ja0hpc3RvcnlTY3JvbGxQb3NpdGlvbl8iLCJwYWdlWU9mZnNldCIsInBhZ2VYT2Zmc2V0IiwibWF5YmVEaXNhYmxlTmF0aXZlU2Nyb2xsUmVzdG9yYXRpb24iLCJlbmROYXZpZ2F0ZVBheWxvYWQiLCJkb05hdmlnYXRlXyIsIm1heWJlUmVzdG9yZU5hdGl2ZVNjcm9sbFJlc3RvcmF0aW9uIiwiZ2V0VGl0bGUiLCJnZXREZWZhdWx0VGl0bGUiLCJiZWZvcmVVcGRhdGVIaXN0b3J5UGF0aCIsImhpc3RvcnlTdGF0ZSIsIm1heWJlUmVzdG9yZVJlZGlyZWN0UGF0aEhhc2hfIiwidXBkYXRlSGlzdG9yeV8iLCJiZWZvcmVVcGRhdGVIaXN0b3J5U3RhdGUiLCJwYXJhbXMiLCJzdXJmYWNlQ29udGVudCIsImdldFN1cmZhY2VDb250ZW50IiwicmVsb2FkIiwic3VyZmFjZUlkIiwiZGlzcG9zZSIsInJlcGxhY2VTdGF0ZSIsInJlbW92ZVBhdGhUcmFpbGluZ1NsYXNoIiwib25Eb2NTdWJtaXREZWxlZ2F0ZV8iLCJvbkRvY0NsaWNrRGVsZWdhdGVfIiwic3luYyIsInRpdGxlTm9kZSIsIkFqYXgiLCJhbGxIZWFkZXJzIiwiaGVhZGVycyIsInBhaXJzIiwiYm9keSIsIm9wdF9oZWFkZXJzIiwib3B0X3BhcmFtcyIsIm9wdF90aW1lb3V0Iiwib3B0X3N5bmMiLCJvcHRfd2l0aENyZWRlbnRpYWxzIiwicmVxdWVzdCIsIlhNTEh0dHBSZXF1ZXN0IiwicHJldmlvdXNSZWFkeVN0YXRlIiwiUHJvbWlzZSIsIm9ubG9hZCIsImFib3J0ZWQiLCJvbmVycm9yIiwicmVhZHlTdGF0ZSIsInRlcm1pbmF0ZWRQcmVtYXR1cmVseSIsImFib3J0IiwidGltZW91dCIsImFkZFBhcmFtZXRlcnNGcm9tTXVsdGlNYXAiLCJ3aXRoQ3JlZGVudGlhbHMiLCJzZXRSZXF1ZXN0SGVhZGVyIiwic2VuZCIsImVycm9ycyIsIklOVkFMSURfU1RBVFVTIiwiUkVRVUVTVF9FUlJPUiIsIlJFUVVFU1RfVElNRU9VVCIsIlJFUVVFU1RfUFJFTUFUVVJFX1RFUk1JTkFUSU9OIiwiVUEiLCJuYXZpZ2F0b3IiLCJ1c2VyQWdlbnQiLCJwbGF0Zm9ybSIsImlzTWFjIiwibWF0Y2hQbGF0Zm9ybSIsImlzV2luIiwiaXNPcGVyYSIsIm1hdGNoVXNlckFnZW50IiwiaXNJZSIsImlzRWRnZSIsImlzSWVPckVkZ2UiLCJpc0Nocm9tZSIsImlzU2FmYXJpIiwiaXNGaXJlZm94IiwidGVzdFVzZXJBZ2VudCIsImdldE5hdGl2ZVVzZXJBZ2VudCIsImdldE5hdGl2ZVBsYXRmb3JtIiwiUmVxdWVzdFNjcmVlbiIsImh0dHBIZWFkZXJzIiwiaHR0cE1ldGhvZCIsIkdFVCIsInN0YXR1cyIsImlzVmFsaWRSZXNwb25zZVN0YXR1c0NvZGUiLCJpbnZhbGlkU3RhdHVzIiwic3RhdHVzQ29kZSIsImdldFJlcXVlc3RQYXRoIiwic2V0SG9zdG5hbWUiLCJzZXRQcm90b2NvbCIsInNldFBvcnQiLCJtYWtlVW5pcXVlIiwiZ2V0UmVxdWVzdCIsInJlcXVlc3RQYXRoIiwicmVzcG9uc2VVcmwiLCJtYXliZUV4dHJhY3RSZXNwb25zZVVybEZyb21SZXF1ZXN0IiwicmVtb3ZlVW5pcXVlIiwiZ2V0Q2FjaGUiLCJoZWFkZXIiLCJGb3JtRGF0YSIsIm1heWJlQXBwZW5kU3VibWl0QnV0dG9uVmFsdWVfIiwiUE9TVCIsImZvcm1hdExvYWRQYXRoIiwic2V0UmVxdWVzdCIsInhociIsImFzc2VydFZhbGlkUmVzcG9uc2VTdGF0dXNDb2RlIiwiYWRkQ2FjaGUiLCJyZXNwb25zZVRleHQiLCJyZXF1ZXN0RXJyb3IiLCJyZXF1ZXN0UHJlbWF0dXJlVGVybWluYXRpb24iLCJyZXNwb25zZVVSTCIsImdldFJlc3BvbnNlSGVhZGVyIiwiWF9SRVFVRVNUX1VSTF9IRUFERVIiLCJIdG1sU2NyZWVuIiwidGl0bGVTZWxlY3RvciIsInJlbGVhc2VWaXJ0dWFsRG9jdW1lbnQiLCJwZW5kaW5nU3R5bGVzIiwidmlydHVhbERvY3VtZW50IiwiY29weU5vZGVBdHRyaWJ1dGVzRnJvbUNvbnRlbnRfIiwibmV3U3R5bGUiLCJpc1RlbXBvcmFyeVN0eWxlIiwic3R5bGVzVGVtcG9yYXJ5Iiwic3R5bGVJbkRvYyIsImluc2VydEJlZm9yZSIsIm5leHRTaWJsaW5nIiwiYm9keVN1cmZhY2UiLCJwbGFjZWhvbGRlciIsImNsZWFyTm9kZUF0dHJpYnV0ZXMiLCJjb3B5Tm9kZUF0dHJpYnV0ZXMiLCJkaXNwb3NlUGVuZGluZ1N0eWxlcyIsImV2YWx1YXRlVHJhY2tlZFNjcmlwdHMiLCJldmFsdWF0ZVRyYWNrZWRSZXNvdXJjZXNfIiwic2NyaXB0c1RlbXBvcmFyeSIsInNjcmlwdHNQZXJtYW5lbnQiLCJldmFsdWF0ZVRyYWNrZWRTdHlsZXMiLCJydW5TdHlsZXNJbkVsZW1lbnQiLCJzdHlsZXNQZXJtYW5lbnQiLCJhcHBlbmRTdHlsZUludG9Eb2N1bWVudF8iLCJldmFsdWF0b3JGbiIsInNlbGVjdG9yVGVtcG9yYXJ5Iiwic2VsZWN0b3JQZXJtYW5lbnQiLCJvcHRfYXBwZW5kUmVzb3VyY2VGbiIsInRyYWNrZWQiLCJ2aXJ0dWFsUXVlcnlTZWxlY3RvckFsbF8iLCJ0ZW1wb3Jhcmllc0luRG9jIiwicXVlcnlTZWxlY3RvckFsbF8iLCJwZXJtYW5lbnRzSW5Eb2MiLCJyZXNvdXJjZSIsInJlc291cmNlS2V5IiwiZ2V0UmVzb3VyY2VLZXlfIiwicGVybWFuZW50UmVzb3VyY2VzSW5Eb2MiLCJmcmFnIiwiYWxsb2NhdGVWaXJ0dWFsRG9jdW1lbnRGb3JDb250ZW50IiwicmVzb2x2ZVRpdGxlRnJvbVZpcnR1YWxEb2N1bWVudCIsImFzc2VydFNhbWVCb2R5SWRJblZpcnR1YWxEb2N1bWVudCIsIm1ha2VUZW1wb3JhcnlTdHlsZXNIcmVmc1VuaXF1ZV8iLCJyZXBsYWNlU3R5bGVBbmRNYWtlVW5pcXVlXyIsInJlcGxhY2VDaGlsZCIsInNldFRpdGxlIiwidGV4dENvbnRlbnQiLCJBcHBEYXRhQXR0cmlidXRlSGFuZGxlciIsImFwcCIsImJhc2VFbGVtZW50IiwiaGFzQXR0cmlidXRlIiwiZGF0YUF0dHJpYnV0ZXMiLCJtYXliZUFkZFJvdXRlc18iLCJtYXliZUFkZFN1cmZhY2VzXyIsIm1heWJlU2V0QmFzZVBhdGhfIiwibWF5YmVTZXRMaW5rU2VsZWN0b3JfIiwibWF5YmVTZXRMb2FkaW5nQ3NzQ2xhc3NfIiwibWF5YmVTZXRVcGRhdGVTY3JvbGxQb3NpdGlvbl8iLCJtYXliZURpc3BhdGNoXyIsInJvdXRlc1NlbGVjdG9yIiwicXVlcnlTZWxlY3RvckFsbEFzQXJyYXlfIiwibWF5YmVQYXJzZUxpbmtSb3V0ZV8iLCJoYXNSb3V0ZXMiLCJhZGRSb3V0ZXMiLCJzdXJmYWNlc1NlbGVjdG9yIiwic3VyZmFjZUVsZW1lbnQiLCJ1cGRhdGVFbGVtZW50SWRJZlNwZWNpYWxTdXJmYWNlXyIsImFkZFN1cmZhY2VzIiwiZGlzcGF0Y2giLCJtYXliZVBhcnNlTGlua1JvdXRlUGF0aF8iLCJtYXliZVBhcnNlTGlua1JvdXRlSGFuZGxlcl8iLCJnZXRQYXRoIiwiZ2V0QXR0cmlidXRlIiwiZ2V0T2JqZWN0QnlOYW1lIiwic2V0QmFzZVBhdGgiLCJzZXRMb2FkaW5nQ3NzQ2xhc3MiLCJzZXRVcGRhdGVTY3JvbGxQb3NpdGlvbiIsImRhdGFBdHRyaWJ1dGVIYW5kbGVyIiwic2V0QmFzZUVsZW1lbnQiLCJoYW5kbGUiXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLElBQUlBLFVBQVVBLFdBQVcsRUFBekI7O0FBRUEsSUFBSSxPQUFPQyxNQUFQLEtBQWtCLFdBQXRCLEVBQW1DO1NBQzFCQSxNQUFSLEdBQWlCQSxNQUFqQjs7O0FBR0QsSUFBSSxPQUFPQyxRQUFQLEtBQW9CLFdBQXhCLEVBQXFDO1NBQzVCQSxRQUFSLEdBQW1CQSxRQUFuQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDTEQ7Ozs7O0FBS0EsSUFBSUMsK0JBQUo7Ozs7Ozs7QUFPQSxJQUFJQyxtQkFBbUIsQ0FBdkI7Ozs7Ozs7QUFPQSxBQUFPLElBQU1DLDBCQUF5QkMsS0FBS0MsTUFBTCxLQUFnQixHQUFqQixLQUEwQixDQUFsRCxDQUFOOzs7Ozs7Ozs7Ozs7QUFZUCxBQUFPLFNBQVNDLGNBQVQsR0FBMEI7UUFDMUJDLE1BQU0sK0JBQU4sQ0FBTjs7Ozs7O0FBTUQsQUFBTyxTQUFTQyx3QkFBVCxHQUFvQzsyQkFDakJDLFNBQXpCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBbUJELEFBQU8sU0FBU0MsdUJBQVQsR0FBZ0Q7TUFBZkMsUUFBZSx1RUFBSixFQUFJOzsyQkFDN0JBLFFBQXpCOzs7Ozs7OztBQVFELEFBQU8sU0FBU0Msd0JBQVQsR0FBb0M7O01BRXRDWCwyQkFBMkJRLFNBQS9CLEVBQTBDO1FBQ3JDLE9BQU9WLE1BQVAsS0FBa0IsV0FBbEIsSUFBaUNBLE9BQU9jLHVCQUE1QyxFQUFxRTs4QkFDNUNkLE9BQU9jLHVCQUEvQjs7O1NBR0taLHNCQUFQOzs7Ozs7Ozs7O0FBVUQsU0FBU2EsZUFBVCxDQUF5QkMsQ0FBekIsRUFBNEJDLENBQTVCLEVBQStCO1NBQ3ZCRCxLQUFLQyxDQUFaOzs7Ozs7Ozs7O0FBVUQsQUFBTyxTQUFTQyxlQUFULENBQXlCQyxFQUF6QixFQUE2QjtNQUMvQixDQUFDQSxHQUFHQyxJQUFSLEVBQWM7UUFDUEMsTUFBTUYsR0FBR0csUUFBSCxFQUFaO09BQ0dGLElBQUgsR0FBVUMsSUFBSUUsU0FBSixDQUFjLENBQWQsRUFBaUJGLElBQUlHLE9BQUosQ0FBWSxHQUFaLENBQWpCLENBQVY7O1NBRU1MLEdBQUdDLElBQVY7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBaUJELEFBQU8sU0FBU0ssaUJBQVQsQ0FBMkJDLElBQTNCLEVBQWlDQyxZQUFqQyxFQUErQ0MsV0FBL0MsRUFBNEQ7TUFDNURDLGFBQWFGLGVBQWUsU0FBbEM7TUFDSSxDQUFDRCxLQUFLSSxjQUFMLENBQW9CRCxVQUFwQixDQUFMLEVBQXNDO1FBQ2pDRSxTQUFTTCxLQUFLSSxjQUFMLENBQW9CSCxZQUFwQixJQUFvQ0QsS0FBS0MsWUFBTCxDQUFwQyxHQUF5RCxJQUF0RTtRQUNJRCxLQUFLTSxTQUFMLElBQWtCLENBQUNOLEtBQUtNLFNBQUwsQ0FBZUMsYUFBZixDQUE2QkMsUUFBN0IsQ0FBdkIsRUFBK0Q7VUFDeERDLFVBQVVQLGVBQWViLGVBQS9CO2VBQ1NvQixRQUNSSixNQURRLEVBRVJOLGtCQUFrQkMsS0FBS00sU0FBdkIsRUFBa0NMLFlBQWxDLEVBQWdEUSxPQUFoRCxDQUZRLENBQVQ7O1NBS0lOLFVBQUwsSUFBbUJFLE1BQW5COztTQUVNTCxLQUFLRyxVQUFMLENBQVA7Ozs7Ozs7Ozs7Ozs7O0FBY0QsQUFBTyxTQUFTTyxNQUFULENBQWdCQyxVQUFoQixFQUE0QkMsaUJBQTVCLEVBQStDO01BQ2pERCxVQUFKLEVBQWdCO1FBQ1hFLEtBQUtGLFdBQVdqQyxZQUFYLENBQVQ7UUFDSWtDLHFCQUFxQixDQUFDRCxXQUFXUCxjQUFYLENBQTBCMUIsWUFBMUIsQ0FBMUIsRUFBbUU7V0FDN0QsSUFBTDs7V0FFTW1DLE9BQU9GLFdBQVdqQyxZQUFYLElBQTJCRCxrQkFBbEMsQ0FBUDs7U0FFTUEsa0JBQVA7Ozs7Ozs7O0FBUUQsQUFBTyxTQUFTcUMsZ0JBQVQsQ0FBMEJDLGVBQTFCLEVBQTJDO1NBQzFDQSxlQUFQOzs7Ozs7OztBQVFELEFBQU8sU0FBU0MsU0FBVCxDQUFtQkMsR0FBbkIsRUFBd0I7U0FDdkIsT0FBT0EsR0FBUCxLQUFlLFNBQXRCOzs7Ozs7OztBQVFELEFBQU8sU0FBU0MsS0FBVCxDQUFlRCxHQUFmLEVBQW9CO1NBQ25CQSxRQUFRakMsU0FBZjs7Ozs7Ozs7QUFRRCxBQUFPLFNBQVNtQyxlQUFULENBQXlCRixHQUF6QixFQUE4QjtTQUM3QkMsTUFBTUQsR0FBTixLQUFjLENBQUNHLE9BQU9ILEdBQVAsQ0FBdEI7Ozs7Ozs7O0FBUUQsQUFBTyxTQUFTSSxVQUFULENBQW9CSixHQUFwQixFQUF5QjtTQUN4QkEsT0FBTyxRQUFPQSxHQUFQLHlDQUFPQSxHQUFQLE9BQWUsUUFBdEIsSUFBa0NBLElBQUlLLFFBQUosS0FBaUIsQ0FBMUQ7Ozs7Ozs7O0FBUUQsQUFBTyxTQUFTQyxrQkFBVCxDQUE0Qk4sR0FBNUIsRUFBaUM7U0FDaENBLE9BQU8sUUFBT0EsR0FBUCx5Q0FBT0EsR0FBUCxPQUFlLFFBQXRCLElBQWtDQSxJQUFJSyxRQUFKLEtBQWlCLEVBQTFEOzs7Ozs7OztBQVFELEFBQU8sU0FBU0UsU0FBVCxDQUFtQlAsR0FBbkIsRUFBd0I7U0FDdkJBLE9BQU8sUUFBT0EsR0FBUCx5Q0FBT0EsR0FBUCxPQUFlLFFBQXRCLElBQWtDQSxJQUFJSyxRQUFKLEtBQWlCLENBQTFEOzs7Ozs7OztBQVFELEFBQU8sU0FBU0csVUFBVCxDQUFvQlIsR0FBcEIsRUFBeUI7U0FDeEIsT0FBT0EsR0FBUCxLQUFlLFVBQXRCOzs7Ozs7OztBQVFELEFBQU8sU0FBU0csTUFBVCxDQUFnQkgsR0FBaEIsRUFBcUI7U0FDcEJBLFFBQVEsSUFBZjs7Ozs7Ozs7QUFRRCxBQUFPLFNBQVNTLFFBQVQsQ0FBa0JULEdBQWxCLEVBQXVCO1NBQ3RCLE9BQU9BLEdBQVAsS0FBZSxRQUF0Qjs7Ozs7Ozs7QUFRRCxBQUFPLFNBQVNVLFFBQVQsQ0FBa0JWLEdBQWxCLEVBQXVCO1NBQ3RCQSxRQUFRLElBQVIsSUFBZ0JBLFFBQVFBLElBQUkzQyxNQUFuQzs7Ozs7Ozs7O0FBU0QsQUFBTyxTQUFTc0QsUUFBVCxDQUFrQlgsR0FBbEIsRUFBdUI7TUFDdkJZLGNBQWNaLEdBQWQseUNBQWNBLEdBQWQsQ0FBTjtTQUNPWSxTQUFTLFFBQVQsSUFBcUJaLFFBQVEsSUFBN0IsSUFBcUNZLFNBQVMsVUFBckQ7Ozs7Ozs7O0FBUUQsQUFBTyxTQUFTQyxTQUFULENBQW1CYixHQUFuQixFQUF3QjtTQUN2QkEsT0FBTyxRQUFPQSxHQUFQLHlDQUFPQSxHQUFQLE9BQWUsUUFBdEIsSUFBa0MsT0FBT0EsSUFBSWMsSUFBWCxLQUFvQixVQUE3RDs7Ozs7Ozs7QUFRRCxBQUFPLFNBQVNDLFFBQVQsQ0FBa0JmLEdBQWxCLEVBQXVCO1NBQ3RCLE9BQU9BLEdBQVAsS0FBZSxRQUFmLElBQTJCQSxlQUFlZ0IsTUFBakQ7Ozs7Ozs7OztBQVNELEFBQU8sU0FBU0MsWUFBVCxHQUF3QjtTQUN2QixPQUFPQyxPQUFQLEtBQW1CLFdBQW5CLElBQ04sT0FBT0EsUUFBUUMsR0FBZixLQUF1QixXQURqQixJQUVORCxRQUFRQyxHQUFSLENBQVlDLFFBQVosS0FBeUIsTUFGbkIsSUFHTixDQUFDRixRQUFRRyxPQUhWOzs7Ozs7O0FBVUQsQUFBTyxTQUFTQyxZQUFULEdBQXdCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDNVMvQjs7Ozs7SUNFTUM7Ozs7Ozs7Ozs7Ozs7O3dCQU9RQyxNQUFNQyxNQUFNO09BQ3BCRCxTQUFTQyxJQUFiLEVBQW1CO1dBQ1gsSUFBUDs7T0FFR0QsS0FBS0UsTUFBTCxLQUFnQkQsS0FBS0MsTUFBekIsRUFBaUM7V0FDekIsS0FBUDs7UUFFSSxJQUFJQyxJQUFJLENBQWIsRUFBZ0JBLElBQUlILEtBQUtFLE1BQXpCLEVBQWlDQyxHQUFqQyxFQUFzQztRQUNqQ0gsS0FBS0csQ0FBTCxNQUFZRixLQUFLRSxDQUFMLENBQWhCLEVBQXlCO1lBQ2pCLEtBQVA7OztVQUdLLElBQVA7Ozs7Ozs7Ozs7O29DQVF3QkMsS0FBSztRQUN4QixJQUFJRCxJQUFJLENBQWIsRUFBZ0JBLElBQUlDLElBQUlGLE1BQXhCLEVBQWdDQyxHQUFoQyxFQUFxQztRQUNoQ0MsSUFBSUQsQ0FBSixNQUFXNUQsU0FBZixFQUEwQjtZQUNsQjZELElBQUlELENBQUosQ0FBUDs7Ozs7Ozs7Ozs7Ozs7MEJBV1lDLEtBQUtDLFlBQVk7T0FDM0JDLFNBQVNELGNBQWMsRUFBM0I7UUFDSyxJQUFJRixJQUFJLENBQWIsRUFBZ0JBLElBQUlDLElBQUlGLE1BQXhCLEVBQWdDQyxHQUFoQyxFQUFxQztRQUNoQ0ksTUFBTUMsT0FBTixDQUFjSixJQUFJRCxDQUFKLENBQWQsQ0FBSixFQUEyQjtXQUNwQk0sT0FBTixDQUFjTCxJQUFJRCxDQUFKLENBQWQsRUFBc0JHLE1BQXRCO0tBREQsTUFFTztZQUNDSSxJQUFQLENBQVlOLElBQUlELENBQUosQ0FBWjs7O1VBR0tHLE1BQVA7Ozs7Ozs7Ozs7Ozs7eUJBVWFGLEtBQUtPLEtBQUs7T0FDakJSLElBQUlDLElBQUkvQyxPQUFKLENBQVlzRCxHQUFaLENBQVY7T0FDSUMsV0FBSjtPQUNNQSxLQUFLVCxLQUFLLENBQWhCLEVBQXFCO1VBQ2RVLFFBQU4sQ0FBZVQsR0FBZixFQUFvQkQsQ0FBcEI7O1VBRU1TLEVBQVA7Ozs7Ozs7Ozs7OzsyQkFTZVIsS0FBS0QsR0FBRztVQUNoQkksTUFBTU8sU0FBTixDQUFnQkMsTUFBaEIsQ0FBdUJDLElBQXZCLENBQTRCWixHQUE1QixFQUFpQ0QsQ0FBakMsRUFBb0MsQ0FBcEMsRUFBdUNELE1BQXZDLEtBQWtELENBQXpEOzs7Ozs7Ozs7Ozs7Ozs7O3dCQWFZRSxLQUFLYSxPQUFPQyxTQUFTO09BQzNCQyxTQUFTLEVBQWY7T0FDTUMsTUFBTTNDLE1BQU15QyxPQUFOLElBQWlCQSxPQUFqQixHQUEyQmQsSUFBSUYsTUFBM0M7UUFDSyxJQUFJQyxJQUFJYyxLQUFiLEVBQW9CZCxJQUFJaUIsR0FBeEIsRUFBNkJqQixHQUE3QixFQUFrQztXQUMxQk8sSUFBUCxDQUFZTixJQUFJRCxDQUFKLENBQVo7O1VBRU1nQixNQUFQOzs7Ozs7QUNuR0Y7Ozs7O0FBS0EsQUFFQSxJQUFNRSxRQUFRLEVBQWQ7Ozs7Ozs7OztBQVVBQSxNQUFNQyxjQUFOLEdBQXVCLFVBQVNDLFNBQVQsRUFBb0I7O09BRXBDQyxRQUFOLENBQWUsWUFBVztRQUNuQkQsU0FBTjtFQUREO0NBRkQ7Ozs7Ozs7Ozs7QUFnQkFGLE1BQU1JLEdBQU4sR0FBWSxVQUFTQyxRQUFULEVBQW1CQyxXQUFuQixFQUFnQztLQUN2QyxDQUFDTixNQUFNSSxHQUFOLENBQVVHLG1CQUFmLEVBQW9DOztRQUU3QkosUUFBTixDQUFlSCxNQUFNSSxHQUFOLENBQVVJLGdCQUF6QjtRQUNNSixHQUFOLENBQVVHLG1CQUFWLEdBQWdDLElBQWhDOzs7T0FHS0gsR0FBTixDQUFVSyxVQUFWLENBQXFCcEIsSUFBckIsQ0FDQyxJQUFJVyxNQUFNSSxHQUFOLENBQVVNLFNBQWQsQ0FBd0JMLFFBQXhCLEVBQWtDQyxXQUFsQyxDQUREO0NBUEQ7OztBQWFBTixNQUFNSSxHQUFOLENBQVVHLG1CQUFWLEdBQWdDLEtBQWhDOzs7QUFJQVAsTUFBTUksR0FBTixDQUFVSyxVQUFWLEdBQXVCLEVBQXZCOzs7Ozs7O0FBT0FULE1BQU1JLEdBQU4sQ0FBVUksZ0JBQVYsR0FBNkIsWUFBVzs7UUFFaENSLE1BQU1JLEdBQU4sQ0FBVUssVUFBVixDQUFxQjVCLE1BQTVCLEVBQW9DOztNQUU3QjhCLFlBQVlYLE1BQU1JLEdBQU4sQ0FBVUssVUFBNUI7UUFDTUwsR0FBTixDQUFVSyxVQUFWLEdBQXVCLEVBQXZCO09BQ0ssSUFBSTNCLElBQUksQ0FBYixFQUFnQkEsSUFBSTZCLFVBQVU5QixNQUE5QixFQUFzQ0MsR0FBdEMsRUFBMkM7T0FDcEM4QixXQUFXRCxVQUFVN0IsQ0FBVixDQUFqQjtPQUNJO2FBQ01uRCxFQUFULENBQVlnRSxJQUFaLENBQWlCaUIsU0FBU0MsS0FBMUI7SUFERCxDQUVFLE9BQU9DLENBQVAsRUFBVTtVQUNMYixjQUFOLENBQXFCYSxDQUFyQjs7Ozs7O09BTUdWLEdBQU4sQ0FBVUcsbUJBQVYsR0FBZ0MsS0FBaEM7Q0FqQkQ7Ozs7Ozs7Ozs7O0FBOEJBUCxNQUFNSSxHQUFOLENBQVVNLFNBQVYsR0FBc0IsVUFBUy9FLEVBQVQsRUFBYWtGLEtBQWIsRUFBb0I7O01BRXBDbEYsRUFBTCxHQUFVQSxFQUFWOztNQUVLa0YsS0FBTCxHQUFhQSxLQUFiO0NBSkQ7Ozs7Ozs7Ozs7O0FBaUJBYixNQUFNRyxRQUFOLEdBQWlCLFVBQVNFLFFBQVQsRUFBbUJDLFdBQW5CLEVBQWdDO0tBQzVDUyxLQUFLVixRQUFUO0tBQ0lDLFdBQUosRUFBaUI7T0FDWEQsU0FBU1csSUFBVCxDQUFjVixXQUFkLENBQUw7O01BRUlOLE1BQU1HLFFBQU4sQ0FBZWMsYUFBZixDQUE2QkYsRUFBN0IsQ0FBTDs7Ozs7O0tBTUksT0FBT0csWUFBUCxLQUF3QixVQUE1QixFQUF3QztlQUMxQkgsRUFBYjs7OztLQUlHLENBQUNmLE1BQU1HLFFBQU4sQ0FBZWdCLGFBQXBCLEVBQW1DO1FBQzVCaEIsUUFBTixDQUFlZ0IsYUFBZixHQUErQm5CLE1BQU1HLFFBQU4sQ0FBZWlCLHdCQUFmLEVBQS9COztPQUVLakIsUUFBTixDQUFlZ0IsYUFBZixDQUE2QkosRUFBN0I7Q0FuQkQ7Ozs7Ozs7QUE0QkFmLE1BQU1HLFFBQU4sQ0FBZWdCLGFBQWYsR0FBK0IsSUFBL0I7Ozs7Ozs7O0FBU0FuQixNQUFNRyxRQUFOLENBQWVpQix3QkFBZixHQUEwQyxZQUFXOzs7S0FHaERDLGdCQUFKOzs7Ozs7S0FNSSxPQUFPQyxjQUFQLEtBQTBCLFVBQTlCLEVBQTBDO1lBQy9CQSxjQUFWOzs7Ozs7O0tBT0csT0FBT0QsT0FBUCxLQUFtQixXQUFuQixJQUFrQyxPQUFPN0csTUFBUCxLQUFrQixXQUFwRCxJQUNIQSxPQUFPK0csV0FESixJQUNtQi9HLE9BQU9nSCxnQkFEOUIsRUFDZ0Q7O1lBRXJDLG1CQUFXOztPQUVkQyxTQUFTaEgsU0FBU2lILGFBQVQsQ0FBdUIsUUFBdkIsQ0FBZjtVQUNPQyxLQUFQLENBQWFDLE9BQWIsR0FBdUIsTUFBdkI7VUFDT0MsR0FBUCxHQUFhLEVBQWI7WUFDU0MsZUFBVCxDQUF5QkMsV0FBekIsQ0FBcUNOLE1BQXJDO09BQ01PLE1BQU1QLE9BQU9RLGFBQW5CO09BQ01DLE1BQU1GLElBQUl2SCxRQUFoQjtPQUNJMEgsSUFBSjtPQUNJQyxLQUFKLENBQVUsRUFBVjtPQUNJQyxLQUFKO09BQ01DLFVBQVUsa0JBQWtCekgsS0FBS0MsTUFBTCxFQUFsQztPQUNNeUgsU0FBU1AsSUFBSVEsUUFBSixDQUFhQyxRQUFiLEdBQXdCLElBQXhCLEdBQStCVCxJQUFJUSxRQUFKLENBQWFFLElBQTNEO09BQ01DLFlBQVksVUFBUzdCLENBQVQsRUFBWTs7O1FBR3pCQSxFQUFFeUIsTUFBRixLQUFhQSxNQUFiLElBQXVCekIsRUFBRThCLElBQUYsS0FBV04sT0FBdEMsRUFBK0M7OztTQUcxQ08sS0FBTCxDQUFXRixTQUFYO0lBTmlCLENBT2hCM0IsSUFQZ0IsQ0FPWCxJQVBXLENBQWxCO09BUUlRLGdCQUFKLENBQXFCLFNBQXJCLEVBQWdDbUIsU0FBaEMsRUFBMkMsS0FBM0M7UUFDS0UsS0FBTCxHQUFhLEVBQWI7UUFDS0MsS0FBTCxHQUFhO2lCQUNDLHVCQUFXO1NBQ25CdkIsV0FBSixDQUFnQmUsT0FBaEIsRUFBeUJDLE1BQXpCOztJQUZGO0dBdkJEOztLQThCRyxPQUFPbEIsT0FBUCxLQUFtQixXQUF2QixFQUFvQztNQUM3QjBCLFVBQVUsSUFBSTFCLE9BQUosRUFBaEI7O01BRUkyQixPQUFPLEVBQVg7TUFDSUMsT0FBT0QsSUFBWDtVQUNRSCxLQUFSLENBQWNGLFNBQWQsR0FBMEIsWUFBVztVQUM3QkssS0FBS0UsSUFBWjtPQUNNbkMsS0FBS2lDLEtBQUtqQyxFQUFoQjtRQUNLQSxFQUFMLEdBQVUsSUFBVjs7R0FIRDtTQU1PLFVBQVNBLEVBQVQsRUFBYTtRQUNkbUMsSUFBTCxHQUFZO1FBQ1BuQztJQURMO1VBR09rQyxLQUFLQyxJQUFaO1dBQ1FKLEtBQVIsQ0FBY3ZCLFdBQWQsQ0FBMEIsQ0FBMUI7R0FMRDs7OztLQVVHLE9BQU85RyxRQUFQLEtBQW9CLFdBQXBCLElBQW1DLHdCQUN0Q0EsU0FBU2lILGFBQVQsQ0FBdUIsUUFBdkIsQ0FERCxFQUNtQztTQUMzQixVQUFTWCxFQUFULEVBQWE7T0FDZm9DLFNBQVMxSSxTQUFTaUgsYUFBVCxDQUF1QixRQUF2QixDQUFiO1VBQ08wQixrQkFBUCxHQUE0QixZQUFXOztXQUUvQkEsa0JBQVAsR0FBNEIsSUFBNUI7V0FDT0MsVUFBUCxDQUFrQkMsV0FBbEIsQ0FBOEJILE1BQTlCO2FBQ1MsSUFBVDs7U0FFSyxJQUFMO0lBTkQ7WUFRU3JCLGVBQVQsQ0FBeUJDLFdBQXpCLENBQXFDb0IsTUFBckM7R0FWRDs7OztRQWVNLFVBQVNwQyxFQUFULEVBQWE7YUFDUkEsRUFBWCxFQUFlLENBQWY7RUFERDtDQXhGRDs7Ozs7Ozs7O0FBcUdBZixNQUFNRyxRQUFOLENBQWVjLGFBQWYsR0FBK0IsVUFBU2hFLGVBQVQsRUFBMEI7UUFDakRBLGVBQVA7Q0FERDs7QUNoUEE7Ozs7Ozs7O0lBT01zRzt1QkFDUzs7Ozs7Ozs7T0FNUkMsU0FBTCxHQUFpQixLQUFqQjs7Ozs7Ozs7Ozs0QkFNUztPQUNMLENBQUMsS0FBS0EsU0FBVixFQUFxQjtTQUNmQyxlQUFMO1NBQ0tELFNBQUwsR0FBaUIsSUFBakI7Ozs7Ozs7Ozs7OztvQ0FTZ0I7Ozs7Ozs7OzsrQkFNTDtVQUNMLEtBQUtBLFNBQVo7Ozs7OztJQ3ZDSUU7Ozs7Ozs7Ozs7Ozs7O3dCQU9RQyxRQUFRO09BQ2hCQyxZQUFKO09BQVNDLGVBQVQ7UUFDSyxJQUFJL0UsSUFBSSxDQUFiLEVBQWdCQSxJQUFJZ0YsVUFBVWpGLE1BQTlCLEVBQXNDQyxHQUF0QyxFQUEyQzthQUNqQ2dGLFVBQVVoRixDQUFWLENBQVQ7U0FDSzhFLEdBQUwsSUFBWUMsTUFBWixFQUFvQjtZQUNaRCxHQUFQLElBQWNDLE9BQU9ELEdBQVAsQ0FBZDs7O1VBR0tELE1BQVA7Ozs7Ozs7Ozs7Ozs7a0NBVXNCL0gsTUFBTW1JLFNBQVM7T0FDL0JsRCxRQUFRa0QsV0FBV3ZKLE1BQXpCO09BQ013SixRQUFRcEksS0FBS3FJLEtBQUwsQ0FBVyxHQUFYLENBQWQ7VUFDT0QsTUFBTUUsTUFBTixDQUFhLFVBQUNDLElBQUQsRUFBT1AsR0FBUDtXQUFlTyxLQUFLUCxHQUFMLENBQWY7SUFBYixFQUF1Qy9DLEtBQXZDLENBQVA7Ozs7Ozs7Ozs7Ozs7c0JBVVV2QixLQUFLM0QsSUFBSTtPQUNieUksWUFBWSxFQUFsQjtPQUNNQyxPQUFPQyxPQUFPRCxJQUFQLENBQVkvRSxHQUFaLENBQWI7UUFDSyxJQUFJUixJQUFJLENBQWIsRUFBZ0JBLElBQUl1RixLQUFLeEYsTUFBekIsRUFBaUNDLEdBQWpDLEVBQXNDO2NBQzNCdUYsS0FBS3ZGLENBQUwsQ0FBVixJQUFxQm5ELEdBQUcwSSxLQUFLdkYsQ0FBTCxDQUFILEVBQVlRLElBQUkrRSxLQUFLdkYsQ0FBTCxDQUFKLENBQVosQ0FBckI7O1VBRU1zRixTQUFQOzs7Ozs7Ozs7OzsrQkFRbUJHLE1BQU1DLE1BQU07T0FDM0JELFNBQVNDLElBQWIsRUFBbUI7V0FDWCxJQUFQOzs7T0FHS0MsUUFBUUgsT0FBT0QsSUFBUCxDQUFZRSxJQUFaLENBQWQ7T0FDTUcsUUFBUUosT0FBT0QsSUFBUCxDQUFZRyxJQUFaLENBQWQ7T0FDSUMsTUFBTTVGLE1BQU4sS0FBaUI2RixNQUFNN0YsTUFBM0IsRUFBbUM7V0FDM0IsS0FBUDs7O1FBR0ksSUFBSUMsSUFBSSxDQUFiLEVBQWdCQSxJQUFJMkYsTUFBTTVGLE1BQTFCLEVBQWtDQyxHQUFsQyxFQUF1QztRQUNsQ3lGLEtBQUtFLE1BQU0zRixDQUFOLENBQUwsTUFBbUIwRixLQUFLQyxNQUFNM0YsQ0FBTixDQUFMLENBQXZCLEVBQXVDO1lBQy9CLEtBQVA7OztVQUdLLElBQVA7Ozs7OztJQ3BFSTZGOzs7Ozs7Ozs7Ozs7Ozs7eUNBUXlCQyxNQUFNQyxNQUFNO09BQ25DQyxRQUFRM0csT0FBT3lHLElBQVAsRUFBYUcsV0FBYixFQUFkO09BQ01DLFFBQVE3RyxPQUFPMEcsSUFBUCxFQUFhRSxXQUFiLEVBQWQ7O09BRUlELFFBQVFFLEtBQVosRUFBbUI7V0FDWCxDQUFDLENBQVI7SUFERCxNQUVPLElBQUlGLFVBQVVFLEtBQWQsRUFBcUI7V0FDcEIsQ0FBUDtJQURNLE1BRUE7V0FDQyxDQUFQOzs7Ozs7Ozs7Ozs7Ozt5Q0FXNEJuSixLQUFLO1VBQzNCQSxJQUFJb0osT0FBSixDQUFZLGFBQVosRUFBMkIsR0FBM0IsRUFBZ0NBLE9BQWhDLENBQXdDLDBCQUF4QyxFQUFvRSxFQUFwRSxDQUFQOzs7Ozs7Ozs7Ozs7OEJBU2tCcEosS0FBSztVQUNoQnNDLE9BQU90QyxHQUFQLEVBQ0xvSixPQURLLENBQ0csK0JBREgsRUFDb0MsTUFEcEMsRUFFTEEsT0FGSyxDQUVHLE9BRkgsRUFFWSxPQUZaLENBQVA7Ozs7Ozs7Ozs7b0NBU3dCO09BQ2xCQyxJQUFJLFVBQVY7VUFDT3JLLEtBQUtzSyxLQUFMLENBQVd0SyxLQUFLQyxNQUFMLEtBQWdCb0ssQ0FBM0IsRUFBOEJwSixRQUE5QixDQUF1QyxFQUF2QyxJQUNOakIsS0FBS3VLLEdBQUwsQ0FBU3ZLLEtBQUtzSyxLQUFMLENBQVd0SyxLQUFLQyxNQUFMLEtBQWdCb0ssQ0FBM0IsSUFBZ0NHLEtBQUtDLEdBQUwsRUFBekMsRUFBcUR4SixRQUFyRCxDQUE4RCxFQUE5RCxDQUREOzs7Ozs7Ozs7Ozs7Ozs7MkJBYWVxQixLQUFLO09BQ2hCb0ksT0FBTyxDQUFYO1FBQ0ssSUFBSXpHLElBQUksQ0FBUixFQUFXMEcsTUFBTXJJLElBQUkwQixNQUExQixFQUFrQ0MsSUFBSTBHLEdBQXRDLEVBQTJDMUcsR0FBM0MsRUFBZ0Q7V0FDeEMsS0FBS3lHLElBQUwsR0FBWXBJLElBQUlzSSxVQUFKLENBQWUzRyxDQUFmLENBQW5CO1lBQ1EsV0FBUjs7VUFFTXlHLElBQVA7Ozs7Ozs7Ozs7Ozs7OztrQ0FZc0IxSixLQUFLK0QsT0FBT0csS0FBSzJGLE9BQU87VUFDdkM3SixJQUFJRSxTQUFKLENBQWMsQ0FBZCxFQUFpQjZELEtBQWpCLElBQTBCOEYsS0FBMUIsR0FBa0M3SixJQUFJRSxTQUFKLENBQWNnRSxHQUFkLENBQXpDOzs7Ozs7QUNsRkY7Ozs7O0FBSUEsU0FBUzRGLGVBQVQsQ0FBeUJDLE9BQXpCLEVBQWtDO0tBQzdCQyxPQUFPcEwsU0FBU2lILGFBQVQsQ0FBdUIsR0FBdkIsQ0FBWDtNQUNLb0UsSUFBTCxHQUFZRixPQUFaOztLQUVHQyxLQUFLcEQsUUFBTCxLQUFrQixHQUFsQixJQUF5QixDQUFDLElBQUlzRCxJQUFKLENBQVNGLEtBQUtDLElBQWQsQ0FBN0IsRUFBa0Q7UUFDM0MsSUFBSUUsU0FBSixDQUFpQkosT0FBakIseUJBQU47OztRQUdNO1FBQ0FDLEtBQUtOLElBREw7WUFFSU0sS0FBS0ksUUFGVDtZQUdJSixLQUFLSyxRQUhUO1lBSUlMLEtBQUtNLFFBQUwsQ0FBYyxDQUFkLE1BQXFCLEdBQXJCLEdBQTJCTixLQUFLTSxRQUFoQyxHQUEyQyxNQUFNTixLQUFLTSxRQUoxRDtRQUtBTixLQUFLTyxJQUxMO1lBTUlQLEtBQUtwRCxRQU5UO1VBT0VvRCxLQUFLUSxNQVBQO1lBUUlSLEtBQUtTO0VBUmhCOzs7QUNURDs7Ozs7QUFLQSxTQUFTQyxLQUFULENBQWVYLE9BQWYsRUFBd0I7S0FDbkJqSSxXQUFXNkksR0FBWCxLQUFtQkEsSUFBSTNILE1BQTNCLEVBQW1DO01BQzVCNEgsTUFBTSxJQUFJRCxHQUFKLENBQVFaLE9BQVIsQ0FBWjs7Ozs7TUFLSWEsSUFBSUwsSUFBSixJQUFZSyxJQUFJWCxJQUFKLENBQVM5SixPQUFULENBQWlCeUssSUFBSUwsSUFBckIsTUFBK0IsQ0FBQyxDQUFoRCxFQUFtRDtTQUM1QyxJQUFJSixTQUFKLENBQWlCSixPQUFqQix5QkFBTjs7O1NBR01hLEdBQVA7RUFWRCxNQVdPO1NBQ0NkLGdCQUFnQkMsT0FBaEIsQ0FBUDs7OztBQ25CRjs7O0FBR0EsSUFBSWMsU0FBU3BDLE9BQU9vQyxNQUFwQjs7Ozs7Ozs7SUFPTUM7OztxQkFDUzs7Ozs7UUFFUnRDLElBQUwsR0FBWXFDLE9BQU8sSUFBUCxDQUFaO1FBQ0tFLE1BQUwsR0FBY0YsT0FBTyxJQUFQLENBQWQ7Ozs7Ozs7Ozs7Ozs7O3NCQVNHOUssTUFBTThKLE9BQU87UUFDWHJCLElBQUwsQ0FBVXpJLEtBQUttSixXQUFMLEVBQVYsSUFBZ0NuSixJQUFoQztRQUNLZ0wsTUFBTCxDQUFZaEwsS0FBS21KLFdBQUwsRUFBWixJQUFrQyxLQUFLNkIsTUFBTCxDQUFZaEwsS0FBS21KLFdBQUwsRUFBWixLQUFtQyxFQUFyRTtRQUNLNkIsTUFBTCxDQUFZaEwsS0FBS21KLFdBQUwsRUFBWixFQUFnQzFGLElBQWhDLENBQXFDcUcsS0FBckM7VUFDTyxJQUFQOzs7Ozs7Ozs7OzBCQU9PO1FBQ0ZyQixJQUFMLEdBQVlxQyxPQUFPLElBQVAsQ0FBWjtRQUNLRSxNQUFMLEdBQWNGLE9BQU8sSUFBUCxDQUFkO1VBQ08sSUFBUDs7Ozs7Ozs7Ozs7OzJCQVNROUssTUFBTTtVQUNQQSxLQUFLbUosV0FBTCxNQUFzQixLQUFLNkIsTUFBbEM7Ozs7Ozs7OztvQ0FNaUI7UUFDWkEsTUFBTCxHQUFjLElBQWQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7eUJBdUJHaEwsTUFBTTtPQUNMZ0wsU0FBUyxLQUFLQSxNQUFMLENBQVloTCxLQUFLbUosV0FBTCxFQUFaLENBQWI7T0FDSTZCLE1BQUosRUFBWTtXQUNKQSxPQUFPLENBQVAsQ0FBUDs7Ozs7Ozs7Ozs7O3lCQVNLaEwsTUFBTTtVQUNMLEtBQUtnTCxNQUFMLENBQVloTCxLQUFLbUosV0FBTCxFQUFaLENBQVA7Ozs7Ozs7Ozs7NEJBT1M7VUFDRixLQUFLOEIsSUFBTCxPQUFnQixDQUF2Qjs7Ozs7Ozs7OzswQkFPTzs7O1VBQ0F2QyxPQUFPRCxJQUFQLENBQVksS0FBS3VDLE1BQWpCLEVBQXlCRSxHQUF6QixDQUE2QixVQUFDbEQsR0FBRDtXQUFTLE9BQUtTLElBQUwsQ0FBVVQsR0FBVixDQUFUO0lBQTdCLENBQVA7Ozs7Ozs7Ozs7O3lCQVFNaEksTUFBTTtVQUNMLEtBQUt5SSxJQUFMLENBQVV6SSxLQUFLbUosV0FBTCxFQUFWLENBQVA7VUFDTyxLQUFLNkIsTUFBTCxDQUFZaEwsS0FBS21KLFdBQUwsRUFBWixDQUFQO1VBQ08sSUFBUDs7Ozs7Ozs7Ozs7Ozt5QkFVR25KLE1BQU04SixPQUFPO1FBQ1hyQixJQUFMLENBQVV6SSxLQUFLbUosV0FBTCxFQUFWLElBQWdDbkosSUFBaEM7UUFDS2dMLE1BQUwsQ0FBWWhMLEtBQUttSixXQUFMLEVBQVosSUFBa0MsQ0FBQ1csS0FBRCxDQUFsQztVQUNPLElBQVA7Ozs7Ozs7Ozs7eUJBT007VUFDQyxLQUFLcUIsS0FBTCxHQUFhbEksTUFBcEI7Ozs7Ozs7Ozs7NkJBT1U7VUFDSG1JLEtBQUtDLFNBQUwsQ0FBZSxLQUFLTCxNQUFwQixDQUFQOzs7OzZCQXBGaUJ0SCxLQUFLO09BQ2xCd0gsTUFBTSxJQUFJSCxRQUFKLEVBQVY7T0FDSXRDLE9BQU9DLE9BQU9ELElBQVAsQ0FBWS9FLEdBQVosQ0FBWDtRQUNLLElBQUlSLElBQUksQ0FBYixFQUFnQkEsSUFBSXVGLEtBQUt4RixNQUF6QixFQUFpQ0MsR0FBakMsRUFBc0M7UUFDakNvSSxHQUFKLENBQVE3QyxLQUFLdkYsQ0FBTCxDQUFSLEVBQWlCUSxJQUFJK0UsS0FBS3ZGLENBQUwsQ0FBSixDQUFqQjs7VUFFTWdJLEdBQVA7Ozs7RUExRHFCdkQ7O0FDVnZCOzs7Ozs7SUFLTTREO21CQUVPekIsS0FBWixFQUFtQjs7Ozs7OztPQUtiMEIsTUFBTCxHQUFjMUIsS0FBZDs7Ozs7O09BTUsyQixPQUFMLEdBQWUsSUFBZjs7Ozs7O09BTUtDLFNBQUwsR0FBaUIsSUFBakI7Ozs7Ozs7Ozs7OzJCQU9RQyxPQUFPOzBCQUNRQSxLQUF2QjtTQUNNQyxTQUFOLENBQWdCLElBQWhCO1FBQ0tGLFNBQUwsR0FBaUIsS0FBS0EsU0FBTCxJQUFrQixFQUFuQztRQUNLQSxTQUFMLENBQWVqSSxJQUFmLENBQW9Ca0ksS0FBcEI7Ozs7Ozs7Ozs7OzJCQVFRRSxNQUFNO09BQ1ZDLFVBQVVELEtBQUtFLFNBQUwsRUFBZDtVQUNPRCxPQUFQLEVBQWdCO1FBQ1hBLFlBQVksSUFBaEIsRUFBc0I7WUFDZCxJQUFQOztjQUVTQSxRQUFRQyxTQUFSLEVBQVY7O1VBRU0sS0FBUDs7Ozs7Ozs7O2lDQU1jO09BQ1ZDLFlBQVksRUFBaEI7T0FDSUgsT0FBTyxLQUFLRSxTQUFMLEVBQVg7VUFDT0YsSUFBUCxFQUFhO2NBQ0ZwSSxJQUFWLENBQWVvSSxJQUFmO1dBQ09BLEtBQUtFLFNBQUwsRUFBUDs7VUFFTUMsU0FBUDs7Ozs7Ozs7Ozs7OzZCQVNVQyxPQUFPO1VBQ1YsS0FBS0MsV0FBTCxHQUFtQkQsS0FBbkIsS0FBNkIsSUFBcEM7Ozs7Ozs7OztnQ0FNYTtVQUNOLEtBQUtQLFNBQUwsSUFBa0JILFNBQVNZLFdBQWxDOzs7Ozs7Ozs7a0NBTWU7VUFDUixLQUFLRCxXQUFMLEdBQW1CakosTUFBMUI7Ozs7Ozs7Ozs2QkFNVTtPQUNObUosUUFBUSxDQUFaO09BQ0lQLE9BQU8sSUFBWDtVQUNPQSxLQUFLRSxTQUFMLEVBQVAsRUFBeUI7O1dBRWpCRixLQUFLRSxTQUFMLEVBQVA7O1VBRU1LLEtBQVA7Ozs7Ozs7Ozs4QkFNVztVQUNKLEtBQUtYLE9BQVo7Ozs7Ozs7Ozs7NEJBT1M7T0FDTFksT0FBTyxJQUFYO1VBQ09BLEtBQUtOLFNBQUwsRUFBUCxFQUF5QjtXQUNqQk0sS0FBS04sU0FBTCxFQUFQOztVQUVNTSxJQUFQOzs7Ozs7Ozs7OzZCQU9VO1VBQ0gsS0FBS2IsTUFBWjs7Ozs7Ozs7OzJCQU1RO1VBQ0QsQ0FBQyxLQUFLYyxhQUFMLEVBQVI7Ozs7Ozs7Ozs7OzhCQVFXWCxPQUFPO09BQ2Q3SSxNQUFNeUosTUFBTixDQUFhLEtBQUtMLFdBQUwsRUFBYixFQUFpQ1AsS0FBakMsQ0FBSixFQUE2QztXQUNyQ0EsS0FBUDs7VUFFTSxJQUFQOzs7Ozs7Ozs7Ozs7OzRCQVVTYSxRQUFRO1FBQ1pmLE9BQUwsR0FBZWUsTUFBZjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzJCQXFCUUMsZ0JBQWdCQyxpQkFBaUI7T0FDckNELGNBQUosRUFBb0I7bUJBQ0osSUFBZjs7UUFFSVAsV0FBTCxHQUFtQlMsT0FBbkIsQ0FBMkIsVUFBQ2hCLEtBQUQ7V0FBV0EsTUFBTWlCLFFBQU4sQ0FBZUgsY0FBZixFQUErQkMsZUFBL0IsQ0FBWDtJQUEzQjtPQUNJQSxlQUFKLEVBQXFCO29CQUNKLElBQWhCOzs7Ozs7Ozs7Ozs7O0FBVUhuQixTQUFTWSxXQUFULEdBQXVCLEVBQXZCOzs7Ozs7O0FBT0EsSUFBTVUseUJBQXlCLFNBQXpCQSxzQkFBeUIsQ0FBU2xCLEtBQVQsRUFBZ0I7S0FDMUNBLE1BQU1JLFNBQU4sRUFBSixFQUF1QjtRQUNoQixJQUFJM00sS0FBSixDQUFVLCtCQUFWLENBQU47O0NBRkY7O0FDeE1BLElBQUkwTixXQUFXbkMsS0FBZjs7SUFFTW9DOzs7Ozs7Ozs7Ozs7Ozs7OztnQkFpQnFCO01BQWQvQyxPQUFjLHVFQUFKLEVBQUk7OztPQUNwQmEsR0FBTCxHQUFXa0MsSUFBSXBDLEtBQUosQ0FBVSxLQUFLcUMsNEJBQUwsQ0FBa0NoRCxPQUFsQyxDQUFWLENBQVg7Ozs7Ozs7Ozs7Ozs7OzRDQVV5QmlELFVBQVU7OztZQUMxQjlCLEtBQVQsR0FBaUJ3QixPQUFqQixDQUF5QixVQUFDM00sSUFBRCxFQUFVO2FBQ3pCa04sTUFBVCxDQUFnQmxOLElBQWhCLEVBQXNCMk0sT0FBdEIsQ0FBOEIsVUFBQzdDLEtBQUQsRUFBVztXQUNuQ3FELGlCQUFMLENBQXVCbk4sSUFBdkIsRUFBNkI4SixLQUE3QjtLQUREO0lBREQ7VUFLTyxJQUFQOzs7Ozs7Ozs7Ozs7b0NBU2lCOUosTUFBTThKLE9BQU87UUFDekJzRCx1QkFBTDtPQUNJNUwsTUFBTXNJLEtBQU4sQ0FBSixFQUFrQjtZQUNUdkgsT0FBT3VILEtBQVAsQ0FBUjs7UUFFSXVELEtBQUwsQ0FBV0MsR0FBWCxDQUFldE4sSUFBZixFQUFxQjhKLEtBQXJCO1VBQ08sSUFBUDs7Ozs7Ozs7Ozs7O3FDQVNrQjlKLE1BQU1nTCxRQUFROzs7VUFDekIyQixPQUFQLENBQWUsVUFBQzdDLEtBQUQ7V0FBVyxPQUFLcUQsaUJBQUwsQ0FBdUJuTixJQUF2QixFQUE2QjhKLEtBQTdCLENBQVg7SUFBZjtVQUNPLElBQVA7Ozs7Ozs7Ozs7OzRDQVF5Qjs7O09BQ3JCLEtBQUt1RCxLQUFULEVBQWdCOzs7UUFHWEEsS0FBTCxHQUFhLElBQUl0QyxRQUFKLEVBQWI7T0FDSU4sU0FBUyxLQUFLSSxHQUFMLENBQVNKLE1BQXRCO09BQ0lBLE1BQUosRUFBWTtXQUNKdEssU0FBUCxDQUFpQixDQUFqQixFQUFvQmtJLEtBQXBCLENBQTBCLEdBQTFCLEVBQStCc0UsT0FBL0IsQ0FBdUMsVUFBQ1ksS0FBRCxFQUFXO3dCQUM5QkEsTUFBTWxGLEtBQU4sQ0FBWSxHQUFaLENBRDhCOztTQUM1Q0wsR0FENEM7U0FDdkM4QixLQUR1Qzs7U0FFN0N0SSxNQUFNc0ksS0FBTixDQUFKLEVBQWtCO2NBQ1RpRCxJQUFJUyxTQUFKLENBQWMxRCxLQUFkLENBQVI7O1lBRUlxRCxpQkFBTCxDQUF1Qm5GLEdBQXZCLEVBQTRCOEIsS0FBNUI7S0FMRDs7Ozs7Ozs7Ozs7NEJBY1E7VUFDRixLQUFLZSxHQUFMLENBQVNsQixJQUFULElBQWlCLEVBQXhCOzs7Ozs7Ozs7OzRCQU9TO09BQ0w3QyxPQUFPLEtBQUsyRyxXQUFMLEVBQVg7T0FDSTNHLElBQUosRUFBVTtRQUNMMEQsT0FBTyxLQUFLa0QsT0FBTCxFQUFYO1FBQ0lsRCxRQUFRQSxTQUFTLElBQXJCLEVBQTJCO2FBQ2xCLE1BQU1BLElBQWQ7OztVQUdLMUQsSUFBUDs7Ozs7Ozs7OztnQ0FPYTtPQUNUdUQsV0FBVyxLQUFLUSxHQUFMLENBQVNSLFFBQXhCO09BQ0lBLGFBQWEwQyxJQUFJWSxvQkFBckIsRUFBMkM7V0FDbkMsRUFBUDs7VUFFTXRELFFBQVA7Ozs7Ozs7Ozs7OEJBT1c7T0FDUHZELE9BQU8sS0FBSzhHLE9BQUwsRUFBWDtPQUNJOUcsSUFBSixFQUFVO1dBQ0YsS0FBSytHLFdBQUwsS0FBcUIsSUFBckIsR0FBNEIvRyxJQUFuQzs7VUFFTSxFQUFQOzs7Ozs7Ozs7Ozs7OztvQ0FXaUI5RyxNQUFNO1FBQ2xCb04sdUJBQUw7VUFDTyxLQUFLQyxLQUFMLENBQVdTLEdBQVgsQ0FBZTlOLElBQWYsQ0FBUDs7Ozs7Ozs7Ozs7OztxQ0FVa0JBLE1BQU07UUFDbkJvTix1QkFBTDtVQUNPLEtBQUtDLEtBQUwsQ0FBV0gsTUFBWCxDQUFrQmxOLElBQWxCLENBQVA7Ozs7Ozs7Ozs7O3NDQVFtQjtRQUNkb04sdUJBQUw7VUFDTyxLQUFLQyxLQUFMLENBQVdsQyxLQUFYLEVBQVA7Ozs7Ozs7Ozs7Ozs7Ozs7Z0NBZWE7VUFDTixLQUFLTixHQUFMLENBQVNOLFFBQWhCOzs7Ozs7Ozs7OzRCQU9TO1VBQ0YsS0FBS00sR0FBTCxDQUFTTCxJQUFoQjs7Ozs7Ozs7OztnQ0FPYTtVQUNOLEtBQUtLLEdBQUwsQ0FBU2hFLFFBQWhCOzs7Ozs7Ozs7Ozs4QkFRVzs7O09BQ1A0RCxTQUFTLEVBQWI7T0FDSXNELGNBQWMsRUFBbEI7UUFDS0MsaUJBQUwsR0FBeUJyQixPQUF6QixDQUFpQyxVQUFDM00sSUFBRCxFQUFVO1dBQ3JDaU8sa0JBQUwsQ0FBd0JqTyxJQUF4QixFQUE4QjJNLE9BQTlCLENBQXNDLFVBQUM3QyxLQUFELEVBQVc7b0JBQ2pDOUosSUFBZjtTQUNJd0IsTUFBTXNJLEtBQU4sQ0FBSixFQUFrQjtxQkFDRixNQUFNb0UsbUJBQW1CcEUsS0FBbkIsQ0FBckI7O29CQUVjLEdBQWY7S0FMRDtJQUREO2lCQVNjaUUsWUFBWUksS0FBWixDQUFrQixDQUFsQixFQUFxQixDQUFDLENBQXRCLENBQWQ7T0FDSUosV0FBSixFQUFpQjtjQUNOLE1BQU1BLFdBQWhCOztVQUVNdEQsTUFBUDs7Ozs7Ozs7Ozs7K0JBUVl6SyxNQUFNO1FBQ2JvTix1QkFBTDtVQUNPLEtBQUtDLEtBQUwsQ0FBV2UsUUFBWCxDQUFvQnBPLElBQXBCLENBQVA7Ozs7Ozs7Ozs7K0JBT1k7UUFDUHFPLGlCQUFMLENBQXVCdEIsSUFBSXVCLFlBQTNCLEVBQXlDdkYsT0FBT3dGLGVBQVAsRUFBekM7VUFDTyxJQUFQOzs7Ozs7Ozs7Ozs7K0NBUzRCdkUsU0FBUztPQUNqQ2EsTUFBTWIsT0FBVjtPQUNJQSxRQUFRNUosT0FBUixDQUFnQixLQUFoQixNQUEyQixDQUFDLENBQTVCLElBQ0g0SixRQUFRNUosT0FBUixDQUFnQixhQUFoQixNQUFtQyxDQURwQyxFQUN1Qzs7O1VBRWhDMk0sSUFBSXlCLGdCQUFWO1FBQ0l4RSxRQUFRLENBQVIsTUFBZSxHQUFmLElBQXNCQSxRQUFRLENBQVIsTUFBZSxHQUF6QyxFQUE4QztZQUN0QyxJQUFQOzs7WUFHT0EsUUFBUXlFLE1BQVIsQ0FBZSxDQUFmLENBQVI7VUFDTSxHQUFMO1VBQ0ssR0FBTDtVQUNLLEdBQUw7YUFDUTFCLElBQUlZLG9CQUFYO2FBQ08sR0FBUDthQUNPM0QsT0FBUDs7VUFFSSxFQUFMO1VBQ0ssR0FBTDtVQUNLQSxRQUFRLENBQVIsTUFBZSxHQUFuQixFQUF3QjtjQUNoQitDLElBQUlZLG9CQUFYOzthQUVNM0QsT0FBUDs7O2FBR09BLE9BQVA7OztVQUdJYSxHQUFQOzs7Ozs7Ozs7Ozs7Ozs7OztrQ0FnQmU3SyxNQUFNO1FBQ2hCb04sdUJBQUw7UUFDS0MsS0FBTCxDQUFXZCxNQUFYLENBQWtCdk0sSUFBbEI7VUFDTyxJQUFQOzs7Ozs7Ozs7O2lDQU9jO1FBQ1QwTyxlQUFMLENBQXFCM0IsSUFBSXVCLFlBQXpCO1VBQ08sSUFBUDs7Ozs7Ozs7Ozs7MEJBUU8zRSxNQUFNO1FBQ1JrQixHQUFMLENBQVNsQixJQUFULEdBQWdCQSxJQUFoQjtVQUNPLElBQVA7Ozs7Ozs7Ozs7OzhCQVFXVSxVQUFVO1FBQ2hCUSxHQUFMLENBQVNSLFFBQVQsR0FBb0JBLFFBQXBCO1VBQ08sSUFBUDs7Ozs7Ozs7Ozs7OztvQ0FVaUJySyxNQUFNOEosT0FBTztRQUN6QjRFLGVBQUwsQ0FBcUIxTyxJQUFyQjtRQUNLbU4saUJBQUwsQ0FBdUJuTixJQUF2QixFQUE2QjhKLEtBQTdCO1VBQ08sSUFBUDs7Ozs7Ozs7Ozs7OztxQ0FVa0I5SixNQUFNZ0wsUUFBUTs7O1FBQzNCMEQsZUFBTCxDQUFxQjFPLElBQXJCO1VBQ08yTSxPQUFQLENBQWUsVUFBQzdDLEtBQUQ7V0FBVyxPQUFLcUQsaUJBQUwsQ0FBdUJuTixJQUF2QixFQUE2QjhKLEtBQTdCLENBQVg7SUFBZjtVQUNPLElBQVA7Ozs7Ozs7Ozs7OzhCQVFXUyxVQUFVO1FBQ2hCTSxHQUFMLENBQVNOLFFBQVQsR0FBb0JBLFFBQXBCO1VBQ08sSUFBUDs7Ozs7Ozs7Ozs7MEJBUU9DLE1BQU07UUFDUkssR0FBTCxDQUFTTCxJQUFULEdBQWdCQSxJQUFoQjtVQUNPLElBQVA7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs4QkFpQlczRCxVQUFVO1FBQ2hCZ0UsR0FBTCxDQUFTaEUsUUFBVCxHQUFvQkEsUUFBcEI7T0FDSSxLQUFLZ0UsR0FBTCxDQUFTaEUsUUFBVCxDQUFrQixLQUFLZ0UsR0FBTCxDQUFTaEUsUUFBVCxDQUFrQjVELE1BQWxCLEdBQTJCLENBQTdDLE1BQW9ELEdBQXhELEVBQTZEO1NBQ3ZENEgsR0FBTCxDQUFTaEUsUUFBVCxJQUFxQixHQUFyQjs7VUFFTSxJQUFQOzs7Ozs7Ozs7OzZCQU9VO09BQ05xRCxPQUFPLEVBQVg7T0FDSXBELE9BQU8sS0FBSzhHLE9BQUwsRUFBWDtPQUNJOUcsSUFBSixFQUFVO1lBQ0QsS0FBSytHLFdBQUwsS0FBcUIsSUFBN0I7O1dBRU8vRyxPQUFPLEtBQUs2SCxXQUFMLEVBQVAsR0FBNEIsS0FBS0MsU0FBTCxFQUE1QixHQUErQyxLQUFLQyxPQUFMLEVBQXZEO1VBQ08zRSxJQUFQOzs7Ozs7Ozs7Ozs7K0JBNU9tQjtVQUNaNEMsUUFBUDs7OzsyQkFnSFk5QyxTQUFTO1VBQ2Q4QyxTQUFTOUMsT0FBVCxDQUFQOzs7OzZCQThGaUI4RSxTQUFTO2NBQ2ZBLE9BQVg7Ozs7NEJBb0NnQkMsVUFBb0I7cUNBQVBDLEtBQU87U0FBQTs7O09BQ2hDRCxTQUFTTixNQUFULENBQWdCTSxTQUFTOUwsTUFBVCxHQUFrQixDQUFsQyxNQUF5QyxHQUE3QyxFQUFrRDtlQUN0QzhMLFNBQVM1TyxTQUFULENBQW1CLENBQW5CLEVBQXNCNE8sU0FBUzlMLE1BQVQsR0FBa0IsQ0FBeEMsQ0FBWDs7V0FFTytMLE1BQU05RCxHQUFOLENBQVU7V0FBUStELEtBQUtSLE1BQUwsQ0FBWSxDQUFaLE1BQW1CLEdBQW5CLEdBQXlCUSxLQUFLOU8sU0FBTCxDQUFlLENBQWYsQ0FBekIsR0FBNkM4TyxJQUFyRDtJQUFWLENBQVI7VUFDTyxDQUFDRixRQUFELEVBQVdHLE1BQVgsQ0FBa0JGLEtBQWxCLEVBQXlCRyxJQUF6QixDQUE4QixHQUE5QixFQUFtQzlGLE9BQW5DLENBQTJDLEtBQTNDLEVBQWtELEVBQWxELENBQVA7Ozs7Ozs7Ozs7Ozs0QkFTZ0JwSixLQUFLO1VBQ2RtUCxtQkFBbUJuUCxJQUFJb0osT0FBSixDQUFZLEtBQVosRUFBbUIsR0FBbkIsQ0FBbkIsQ0FBUDs7Ozs7Ozs7Ozs7Ozs7QUFXRixJQUFNZ0csV0FBVyxTQUFYQSxRQUFXO1FBQ2YsT0FBT3pRLE1BQVAsS0FBa0IsV0FBbEIsSUFDQUEsT0FBT2dJLFFBRFAsSUFFQWhJLE9BQU9nSSxRQUFQLENBQWdCQyxRQUZoQixJQUdBakksT0FBT2dJLFFBQVAsQ0FBZ0JDLFFBQWhCLENBQXlCekcsT0FBekIsQ0FBaUMsT0FBakMsTUFBOEMsQ0FKL0I7Q0FBakI7O0FBTUEyTSxJQUFJeUIsZ0JBQUosR0FBdUJhLGFBQWEsUUFBYixHQUF3QixPQUEvQzs7Ozs7OztBQU9BdEMsSUFBSVksb0JBQUosR0FBMkIsYUFBYWxFLEtBQUtDLEdBQUwsRUFBeEM7Ozs7Ozs7QUFPQXFELElBQUl1QixZQUFKLEdBQW1CLElBQW5COztBQ2pkQTs7Ozs7SUFJTWdCOzs7Ozs7Ozs7Ozs7OztxQ0FPcUJySCxRQUFRRixRQUFRO1NBQ25DbEUsU0FBTixDQUFnQnNLLEtBQWhCLENBQXNCcEssSUFBdEIsQ0FBMkJrRSxPQUFPc0gsVUFBbEMsRUFBOEM1QyxPQUE5QyxDQUFzRCxVQUFDNkMsU0FBRDtXQUFlekgsT0FBTzBILFlBQVAsQ0FBb0JELFVBQVV4UCxJQUE5QixFQUFvQ3dQLFVBQVUxRixLQUE5QyxDQUFmO0lBQXREOzs7Ozs7Ozs7OzswQ0FROEI7VUFDdkIsS0FBSzRGLGdDQUFMLEtBQTBDL1EsUUFBUUMsTUFBUixDQUFlZ0ksUUFBZixDQUF3QitDLElBQXpFOzs7Ozs7Ozs7OztxREFReUM7VUFDbENoTCxRQUFRQyxNQUFSLENBQWVnSSxRQUFmLENBQXdCMkQsUUFBeEIsR0FBbUM1TCxRQUFRQyxNQUFSLENBQWVnSSxRQUFmLENBQXdCNkQsTUFBbEU7Ozs7Ozs7Ozs7O2dDQVFvQm9CLE1BQU07T0FDckI4RCxVQURxQixHQUNLLENBREw7T0FDVEMsU0FEUyxHQUNRLENBRFI7O01BRXZCO2tCQUNZL0QsS0FBSzhELFVBQW5CO2lCQUNhOUQsS0FBSytELFNBQWxCO1dBQ08vRCxLQUFLZ0UsWUFBWjtJQUhELFFBSVNoRSxJQUpUO1VBS087MEJBQUE7O0lBQVA7Ozs7Ozs7Ozs7OzZCQVdpQmhCLEtBQUs7T0FDbEJpRixNQUFNLElBQUkvQyxHQUFKLENBQVFsQyxHQUFSLENBQVY7VUFDT2lGLElBQUluQixXQUFKLEtBQW9CbUIsSUFBSWxCLFNBQUosRUFBcEIsR0FBc0NrQixJQUFJakIsT0FBSixFQUE3Qzs7Ozs7Ozs7Ozs7d0NBUTRCaEUsS0FBSztPQUM3QmlGLE1BQU0sSUFBSS9DLEdBQUosQ0FBUWxDLEdBQVIsQ0FBVjtVQUNPaUYsSUFBSW5CLFdBQUosS0FBb0JtQixJQUFJbEIsU0FBSixFQUEzQjs7Ozs7Ozs7Ozs7aURBUXFDL0QsS0FBSztPQUN0Q2lGLE1BQU0sSUFBSS9DLEdBQUosQ0FBUWxDLEdBQVIsQ0FBVjtVQUNPaUYsSUFBSW5CLFdBQUosRUFBUDs7Ozs7Ozs7Ozs7O3VDQVMyQjlELEtBQUs7T0FDNUJBLEdBQUosRUFBUztRQUNGa0YscUJBQXFCLEtBQUtMLGdDQUFMLEVBQTNCOzs7V0FHT0osTUFBTVUscUJBQU4sQ0FBNEJuRixHQUE1QixNQUFxQyxLQUFLb0YsVUFBTCxDQUFnQkYsa0JBQWhCLENBQTVDOztVQUVNLEtBQVA7Ozs7Ozs7Ozs7OzRDQVFnQztVQUN6QixDQUFDLEVBQUVwUixRQUFRQyxNQUFSLENBQWVzUixPQUFmLElBQTBCdlIsUUFBUUMsTUFBUixDQUFlc1IsT0FBZixDQUF1QkMsU0FBbkQsQ0FBUjs7Ozs7Ozs7Ozs7OzJCQVNldEYsS0FBSztPQUNoQjtXQUNJLElBQUlrQyxHQUFKLENBQVFsQyxHQUFSLENBQVA7SUFERCxDQUVFLE9BQU91RixHQUFQLEVBQVk7WUFDTEMsS0FBUixDQUFpQkQsSUFBSTFKLE9BQXJCLFNBQWdDbUUsR0FBaEM7V0FDTyxLQUFQOzs7Ozs7Ozs7Ozs7c0NBU3lCZ0IsTUFBTTtTQUMxQmhJLFNBQU4sQ0FBZ0JzSyxLQUFoQixDQUFzQnBLLElBQXRCLENBQTJCOEgsS0FBSzBELFVBQWhDLEVBQTRDNUMsT0FBNUMsQ0FBb0QsVUFBQzZDLFNBQUQ7V0FBZTNELEtBQUt5RSxlQUFMLENBQXFCZCxVQUFVeFAsSUFBL0IsQ0FBZjtJQUFwRDs7Ozs7Ozs7Ozs7MENBUThCaVAsTUFBTTtPQUNoQ2hNLFNBQVNnTSxPQUFPQSxLQUFLaE0sTUFBWixHQUFxQixDQUFsQztPQUNJQSxTQUFTLENBQVQsSUFBY2dNLEtBQUtoTSxTQUFTLENBQWQsTUFBcUIsR0FBdkMsRUFBNEM7V0FDcENnTSxLQUFLc0IsTUFBTCxDQUFZLENBQVosRUFBZXROLFNBQVMsQ0FBeEIsQ0FBUDs7VUFFTWdNLElBQVA7Ozs7OztBQy9JRixxQkFBZTtXQUNKLHNCQURJO2VBRUEsMEJBRkE7a0JBR0csOEJBSEg7UUFJUCxZQUpPO1dBS0oscUJBTEk7VUFNTCxvQkFOSzt1QkFPUTtDQVB2Qjs7QUNBQSxJQUFNdUIsYUFBYSxnQkFBbkI7O0lBRU1DOzs7Ozs7Ozs7Ozs7Ozs7O3lCQVNNQyxTQUFTQyxVQUFVQyxnQkFBZ0I7T0FDekMsQ0FBQ0YsUUFBUUYsVUFBUixDQUFMLEVBQTBCO1lBQ2pCQSxVQUFSLElBQXNCLEVBQXRCOztPQUVHLENBQUNHLFFBQUwsRUFBZTtXQUNQRCxRQUFRRixVQUFSLENBQVA7O09BRUcsQ0FBQ0UsUUFBUUYsVUFBUixFQUFvQkcsUUFBcEIsQ0FBRCxJQUFrQ0MsY0FBdEMsRUFBc0Q7WUFDN0NKLFVBQVIsRUFBb0JHLFFBQXBCLElBQWdDQyxjQUFoQzs7VUFFTUYsUUFBUUYsVUFBUixFQUFvQkcsUUFBcEIsQ0FBUDs7Ozs7Ozs7Ozs7c0JBUVVELFNBQVM7VUFDWixDQUFDLENBQUNBLFFBQVFGLFVBQVIsQ0FBVDs7Ozs7O0FDNUJGOzs7Ozs7Ozs7Ozs7O0lBWU1LOzs7c0JBQ09DLE9BQVosRUFBcUJDLEtBQXJCLEVBQTRCQyxRQUE1QixFQUFzQzs7Ozs7Ozs7OztRQVFoQ0MsUUFBTCxHQUFnQkgsT0FBaEI7Ozs7Ozs7UUFPS0ksTUFBTCxHQUFjSCxLQUFkOzs7Ozs7O1FBT0tJLFNBQUwsR0FBaUJILFFBQWpCOzs7Ozs7Ozs7Ozs7b0NBT2lCO1FBQ1pJLGNBQUw7UUFDS0gsUUFBTCxHQUFnQixJQUFoQjtRQUNLRSxTQUFMLEdBQWlCLElBQWpCOzs7Ozs7Ozs7bUNBTWdCO09BQ1osQ0FBQyxLQUFLRixRQUFMLENBQWNJLFVBQWQsRUFBTCxFQUFpQztTQUMzQkosUUFBTCxDQUFjRyxjQUFkLENBQTZCLEtBQUtGLE1BQWxDLEVBQTBDLEtBQUtDLFNBQS9DOzs7OztFQXpDdUJ4Sjs7QUNYMUIsSUFBTTJKLGVBQWUsQ0FBQyxDQUFELENBQXJCOzs7Ozs7OztJQU9NQzs7O3lCQUNTOzs7Ozs7Ozs7O1FBUVJDLE9BQUwsR0FBZSxJQUFmOzs7Ozs7UUFNS0MsaUJBQUwsR0FBeUIsSUFBekI7Ozs7Ozs7OztRQVNLQyxnQkFBTCxHQUF3QixLQUF4Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7OzhCQWFXQyxRQUFRQyxTQUFTO09BQ3hCLENBQUNELE1BQUwsRUFBYTthQUNIQyxPQUFUO0lBREQsTUFFTztRQUNGLENBQUN0TyxNQUFNQyxPQUFOLENBQWNvTyxNQUFkLENBQUwsRUFBNEI7Y0FDbEIsQ0FBQ0EsTUFBRCxDQUFUOztXQUVNbE8sSUFBUCxDQUFZbU8sT0FBWjs7VUFFTUQsTUFBUDs7Ozs7Ozs7Ozs7Ozs7OzhCQVlXWixPQUFPQyxVQUFVYSxhQUFhO1FBQ3BDQyxpQkFBTCxDQUF1QmQsUUFBdkI7O09BRU1lLFNBQVMsS0FBS0MsY0FBTCxDQUFvQmpCLEtBQXBCLENBQWY7UUFDSyxJQUFJN04sSUFBSSxDQUFiLEVBQWdCQSxJQUFJNk8sT0FBTzlPLE1BQTNCLEVBQW1DQyxHQUFuQyxFQUF3QztTQUNsQytPLGtCQUFMLENBQXdCRixPQUFPN08sQ0FBUCxDQUF4QixFQUFtQzhOLFFBQW5DLEVBQTZDYSxXQUE3Qzs7O1VBR00sSUFBSWhCLFdBQUosQ0FBZ0IsSUFBaEIsRUFBc0JFLEtBQXRCLEVBQTZCQyxRQUE3QixDQUFQOzs7Ozs7Ozs7Ozs7Ozs7Ozs7cUNBZWtCRCxPQUFPQyxVQUFVYSxhQUFhSyxZQUFZO1FBQ3ZEQyxvQkFBTCxDQUEwQnBCLEtBQTFCO09BQ0ljLGVBQWVLLFVBQW5CLEVBQStCO2VBQ25CO2NBQ0RMLFdBREM7U0FFTmIsUUFGTTthQUdGa0I7S0FIVDs7UUFNSVYsT0FBTCxHQUFlLEtBQUtBLE9BQUwsSUFBZ0IsRUFBL0I7UUFDS0EsT0FBTCxDQUFhVCxLQUFiLElBQXNCLEtBQUtxQixXQUFMLENBQWlCLEtBQUtaLE9BQUwsQ0FBYVQsS0FBYixDQUFqQixFQUFzQ0MsUUFBdEMsQ0FBdEI7Ozs7Ozs7Ozs7OzsrQkFTWUQsT0FBTztPQUNmLEtBQUtzQixrQkFBTCxFQUFKLEVBQStCO1FBQ3hCQyxTQUFTO3FCQUNFLDBCQUFXO2FBQ25CQyxnQkFBUCxHQUEwQixJQUExQjtNQUZhO2FBSU4sSUFKTTtXQUtSeEI7S0FMUDtXQU9PdUIsTUFBUDs7Ozs7Ozs7Ozs7b0NBUWdCO1FBQ1pkLE9BQUwsR0FBZSxJQUFmOzs7Ozs7Ozs7Ozs7dUJBU0lULE9BQU87T0FDTHlCLFlBQVksS0FBS0MsZ0JBQUwsQ0FBc0IxQixLQUF0QixDQUFsQjtPQUNJeUIsVUFBVXZQLE1BQVYsS0FBcUIsQ0FBekIsRUFBNEI7V0FDcEIsS0FBUDs7O09BR0t5UCxPQUFPNVAsTUFBTXFMLEtBQU4sQ0FBWWpHLFNBQVosRUFBdUIsQ0FBdkIsQ0FBYjtRQUNLeUssYUFBTCxDQUFtQkgsU0FBbkIsRUFBOEJFLElBQTlCLEVBQW9DLEtBQUtFLFlBQUwsQ0FBa0I3QixLQUFsQixDQUFwQztVQUNPLElBQVA7Ozs7Ozs7Ozs7OzttQ0FTZ0JBLE9BQU87T0FDakI4QixrQkFBa0JDLFVBQVEsS0FBS3RCLE9BQUwsSUFBZ0IsS0FBS0EsT0FBTCxDQUFhVCxLQUFiLENBQXhCLENBQXhCO1VBQ084QixnQkFBZ0IzRCxNQUFoQixDQUF1QjRELFVBQVEsS0FBS3RCLE9BQUwsSUFBZ0IsS0FBS0EsT0FBTCxDQUFhLEdBQWIsQ0FBeEIsQ0FBdkIsQ0FBUDs7Ozs7Ozs7Ozs7O3VDQVNvQjtVQUNiLEtBQUtFLGdCQUFaOzs7Ozs7Ozs7Ozs0QkFRU1gsT0FBTztVQUNULEtBQUswQixnQkFBTCxDQUFzQjFCLEtBQXRCLEVBQTZCN0YsR0FBN0IsQ0FDTjtXQUFZOEYsU0FBU2pSLEVBQVQsR0FBY2lSLFNBQVNqUixFQUF2QixHQUE0QmlSLFFBQXhDO0lBRE0sQ0FBUDs7Ozs7Ozs7Ozs7Ozs7Ozt1QkFlSUQsT0FBT2dDLFFBQVEvQixVQUFVO09BQ3ZCZSxTQUFTLEtBQUtDLGNBQUwsQ0FBb0JqQixLQUFwQixDQUFmO1FBQ0ssSUFBSTdOLElBQUksQ0FBYixFQUFnQkEsSUFBSTZPLE9BQU85TyxNQUEzQixFQUFtQ0MsR0FBbkMsRUFBd0M7U0FDbEM4UCxLQUFMLENBQVdqQixPQUFPN08sQ0FBUCxDQUFYLEVBQXNCNlAsTUFBdEIsRUFBOEIvQixRQUE5Qjs7O1VBR00sSUFBSUgsV0FBSixDQUFnQixJQUFoQixFQUFzQkUsS0FBdEIsRUFBNkJDLFFBQTdCLENBQVA7Ozs7Ozs7Ozs7Ozs7Ozs7d0JBYUtELE9BQU9nQyxRQUFRL0IsVUFBVTtPQUN4QmlDLE9BQU8sSUFBYjs7T0FFSUYsVUFBVSxDQUFkLEVBQWlCOzs7O1lBSVJHLGVBQVQsR0FBMkI7UUFDdEIsRUFBRUgsTUFBRixLQUFhLENBQWpCLEVBQW9CO1VBQ2QzQixjQUFMLENBQW9CTCxLQUFwQixFQUEyQm1DLGVBQTNCOzthQUVRQyxLQUFULENBQWVGLElBQWYsRUFBcUIvSyxTQUFyQjs7O1FBR0krSixrQkFBTCxDQUF3QmxCLEtBQXhCLEVBQStCbUMsZUFBL0IsRUFBZ0QsS0FBaEQsRUFBdURsQyxRQUF2RDs7Ozs7Ozs7Ozs7Ozs7bUNBV2dCb0MsYUFBYXBDLFVBQVU7T0FDakNqUixLQUFLcVQsWUFBWXJULEVBQVosSUFBa0JxVCxXQUE3QjtVQUNPclQsT0FBT2lSLFFBQVAsSUFDTG9DLFlBQVl6TSxNQUFaLElBQXNCeU0sWUFBWXpNLE1BQVosS0FBdUJxSyxRQUQvQzs7Ozs7Ozs7Ozs7OztzQkFXR0QsT0FBT0MsVUFBVTtRQUNmYyxpQkFBTCxDQUF1QmQsUUFBdkI7T0FDSSxDQUFDLEtBQUtRLE9BQVYsRUFBbUI7V0FDWCxJQUFQOzs7T0FHS08sU0FBUyxLQUFLQyxjQUFMLENBQW9CakIsS0FBcEIsQ0FBZjtRQUNLLElBQUk3TixJQUFJLENBQWIsRUFBZ0JBLElBQUk2TyxPQUFPOU8sTUFBM0IsRUFBbUNDLEdBQW5DLEVBQXdDO1NBQ2xDc08sT0FBTCxDQUFhTyxPQUFPN08sQ0FBUCxDQUFiLElBQTBCLEtBQUttUSwyQkFBTCxDQUN6QlAsVUFBUSxLQUFLdEIsT0FBTCxDQUFhTyxPQUFPN08sQ0FBUCxDQUFiLENBQVIsQ0FEeUIsRUFFekI4TixRQUZ5QixDQUExQjs7O1VBTU0sSUFBUDs7Ozs7Ozs7Ozs7O3VCQVNJO1VBQ0csS0FBS3NDLFdBQUwsQ0FBaUJILEtBQWpCLENBQXVCLElBQXZCLEVBQTZCakwsU0FBN0IsQ0FBUDs7Ozs7Ozs7Ozs7NkJBUVUwSixTQUFTO1FBQ2RILGlCQUFMLEdBQXlCLEtBQUtXLFdBQUwsQ0FBaUIsS0FBS1gsaUJBQXRCLEVBQXlDRyxPQUF6QyxDQUF6Qjs7Ozs7Ozs7Ozs7Ozt1QkFVSUcsUUFBUWYsVUFBVTtVQUNmLEtBQUt1QyxJQUFMLENBQVV4QixNQUFWLEVBQWtCLENBQWxCLEVBQXFCZixRQUFyQixDQUFQOzs7Ozs7Ozs7Ozs7O3FDQVVrQndDLFlBQVk7T0FDMUIsS0FBS2hDLE9BQVQsRUFBa0I7UUFDYmdDLFVBQUosRUFBZ0I7U0FDVHpCLFNBQVMsS0FBS0MsY0FBTCxDQUFvQndCLFVBQXBCLENBQWY7VUFDSyxJQUFJdFEsSUFBSSxDQUFiLEVBQWdCQSxJQUFJNk8sT0FBTzlPLE1BQTNCLEVBQW1DQyxHQUFuQyxFQUF3QztXQUNsQ3NPLE9BQUwsQ0FBYU8sT0FBTzdPLENBQVAsQ0FBYixJQUEwQixJQUExQjs7S0FIRixNQUtPO1VBQ0RzTyxPQUFMLEdBQWUsSUFBZjs7O1VBR0ssSUFBUDs7Ozs7Ozs7Ozs7Ozs7OENBVzJCaUMsY0FBY3pDLFVBQVU7T0FDN0MwQyxpQkFBaUIsRUFBdkI7UUFDSyxJQUFJeFEsSUFBSSxDQUFiLEVBQWdCQSxJQUFJdVEsYUFBYXhRLE1BQWpDLEVBQXlDQyxHQUF6QyxFQUE4QztRQUN6QyxDQUFDLEtBQUt5USxnQkFBTCxDQUFzQkYsYUFBYXZRLENBQWIsQ0FBdEIsRUFBdUM4TixRQUF2QyxDQUFMLEVBQXVEO29CQUN2Q3ZOLElBQWYsQ0FBb0JnUSxhQUFhdlEsQ0FBYixDQUFwQjs7O1VBR0t3USxlQUFlelEsTUFBZixHQUF3QixDQUF4QixHQUE0QnlRLGNBQTVCLEdBQTZDLElBQXBEOzs7Ozs7Ozs7Ozs7O21DQVVnQjtVQUNULEtBQUtFLEdBQUwsQ0FBU1QsS0FBVCxDQUFlLElBQWYsRUFBcUJqTCxTQUFyQixDQUFQOzs7Ozs7Ozs7Ozt1Q0FRb0I2SSxPQUFPO09BQ3ZCOEMsV0FBVyxLQUFLcEMsaUJBQXBCO09BQ0lvQyxRQUFKLEVBQWM7ZUFDRmYsVUFBUWUsUUFBUixDQUFYO1NBQ0ssSUFBSTNRLElBQUksQ0FBYixFQUFnQkEsSUFBSTJRLFNBQVM1USxNQUE3QixFQUFxQ0MsR0FBckMsRUFBMEM7Y0FDaENBLENBQVQsRUFBWTZOLEtBQVo7Ozs7Ozs7Ozs7Ozs7OztnQ0FZV3lCLFdBQVdFLE1BQU1KLFFBQVE7T0FDbENBLE1BQUosRUFBWTtTQUNON08sSUFBTCxDQUFVNk8sTUFBVjs7O09BR0t3QixtQkFBbUIsRUFBekI7UUFDSyxJQUFJNVEsSUFBSSxDQUFiLEVBQWdCQSxJQUFJc1AsVUFBVXZQLE1BQTlCLEVBQXNDQyxHQUF0QyxFQUEyQztRQUNwQzhOLFdBQVd3QixVQUFVdFAsQ0FBVixFQUFhbkQsRUFBYixJQUFtQnlTLFVBQVV0UCxDQUFWLENBQXBDO1FBQ0lzUCxVQUFVdFAsQ0FBVixFQUFhNlEsT0FBakIsRUFBMEI7c0JBQ1J0USxJQUFqQixDQUFzQnVOLFFBQXRCO0tBREQsTUFFTztjQUNHbUMsS0FBVCxDQUFlLElBQWYsRUFBcUJULElBQXJCOzs7T0FHRSxDQUFDSixNQUFELElBQVcsQ0FBQ0EsT0FBT0MsZ0JBQXZCLEVBQXlDO1NBQ25DLElBQUl5QixJQUFJLENBQWIsRUFBZ0JBLElBQUlGLGlCQUFpQjdRLE1BQXJDLEVBQTZDK1EsR0FBN0MsRUFBa0Q7c0JBQ2hDQSxDQUFqQixFQUFvQmIsS0FBcEIsQ0FBMEIsSUFBMUIsRUFBZ0NULElBQWhDOzs7Ozs7Ozs7Ozs7Ozs7cUNBWWdCdUIsaUJBQWlCO1FBQzlCdkMsZ0JBQUwsR0FBd0J1QyxlQUF4QjtVQUNPLElBQVA7Ozs7Ozs7Ozs7Ozs7O2lDQVdjbEMsUUFBUTtPQUNsQnpQLFNBQVN5UCxNQUFULENBQUosRUFBc0I7aUJBQ1IsQ0FBYixJQUFrQkEsTUFBbEI7YUFDU1QsWUFBVDs7VUFFTVMsTUFBUDs7Ozs7Ozs7Ozs7b0NBUWlCZixVQUFVO09BQ3ZCLENBQUNqUCxXQUFXaVAsUUFBWCxDQUFMLEVBQTJCO1VBQ3BCLElBQUk1RyxTQUFKLENBQWMsNkJBQWQsQ0FBTjs7Ozs7RUE1WndCekM7O0FBaWEzQixTQUFTbUwsU0FBVCxDQUFpQnZSLEdBQWpCLEVBQXNCO09BQ2ZBLE9BQU8sRUFBYjtRQUNPK0IsTUFBTUMsT0FBTixDQUFjaEMsR0FBZCxJQUFxQkEsR0FBckIsR0FBMkIsQ0FBQ0EsR0FBRCxDQUFsQzs7O0FDM2FEOzs7Ozs7Ozs7Ozs7Ozs7SUFjTTJTOzs7NEJBQ09DLGFBQVosRUFBMkJDLGFBQTNCLEVBQTBDQyxhQUExQyxFQUF5REMsYUFBekQsRUFBd0U7Ozs7Ozs7Ozs7UUFRbEVDLFVBQUwsR0FBa0JGLGFBQWxCOzs7Ozs7OztRQVFLRyxjQUFMLEdBQXNCTCxhQUF0Qjs7Ozs7Ozs7O1FBU0tNLGNBQUwsR0FBc0IsSUFBdEI7Ozs7Ozs7UUFPS0MsY0FBTCxHQUFzQixJQUF0Qjs7Ozs7Ozs7UUFRS0MsY0FBTCxHQUFzQlAsYUFBdEI7Ozs7Ozs7UUFPS1EsVUFBTCxHQUFrQk4sYUFBbEI7O1FBRUtPLFdBQUw7Ozs7Ozs7Ozs7Ozs7OzsrQkFVWTlELE9BQU9DLFVBQVU7VUFDdEIsS0FBS3dELGNBQUwsQ0FBb0JNLEVBQXBCLENBQXVCL0QsS0FBdkIsRUFBOEJDLFFBQTlCLENBQVA7Ozs7Ozs7OztvQ0FNaUI7UUFDWitELGdCQUFMO1FBQ0tMLGNBQUwsR0FBc0IsSUFBdEI7UUFDS0YsY0FBTCxHQUFzQixJQUF0QjtRQUNLRyxjQUFMLEdBQXNCLElBQXRCOzs7Ozs7Ozs7O2tDQU9lO1FBQ1ZBLGNBQUwsQ0FBb0JLLElBQXBCLENBQXlCN0IsS0FBekIsQ0FBK0IsS0FBS3dCLGNBQXBDLEVBQW9Eek0sU0FBcEQ7Ozs7Ozs7Ozs7NkJBT1U2SSxPQUFPO09BQ2IsS0FBS2tFLGlCQUFMLENBQXVCbEUsS0FBdkIsQ0FBSixFQUFtQztTQUM3Qm1FLGlCQUFMLENBQXVCbkUsS0FBdkI7Ozs7Ozs7Ozs7O3FDQVFpQjtPQUNkLEtBQUsyRCxjQUFULEVBQXlCO1FBQ2xCM0MsU0FBU3JKLE9BQU9ELElBQVAsQ0FBWSxLQUFLaU0sY0FBakIsQ0FBZjtTQUNLLElBQUl4UixJQUFJLENBQWIsRUFBZ0JBLElBQUk2TyxPQUFPOU8sTUFBM0IsRUFBbUNDLEdBQW5DLEVBQXdDO1VBQ2xDd1IsY0FBTCxDQUFvQjNDLE9BQU83TyxDQUFQLENBQXBCLEVBQStCa08sY0FBL0I7O1NBRUlzRCxjQUFMLEdBQXNCLElBQXRCOztRQUVJRCxjQUFMLEdBQXNCLElBQXRCOzs7Ozs7Ozs7Ozs7bUNBU2dCTixlQUFlOzs7T0FDekJwQyxTQUFTLEtBQUt5QyxjQUFMLElBQXVCLEtBQUtFLGNBQTVCLEdBQ2RoTSxPQUFPRCxJQUFQLENBQVksS0FBS2lNLGNBQWpCLENBRGMsR0FFZCxLQUFLRCxjQUZOO1FBR0tELGNBQUwsR0FBc0JMLGFBQXRCO09BQ0lwQyxNQUFKLEVBQVk7U0FDTmdELGdCQUFMO1dBQ09wSSxPQUFQLENBQWU7WUFBUyxPQUFLd0ksVUFBTCxDQUFnQnBFLEtBQWhCLENBQVQ7S0FBZjs7Ozs7Ozs7Ozs7OztvQ0FVZ0JBLE9BQU87T0FDcEIsS0FBSzZELFVBQUwsSUFBbUIsQ0FBQyxLQUFLQSxVQUFMLENBQWdCN0QsS0FBaEIsQ0FBeEIsRUFBZ0Q7V0FDeEMsS0FBUDs7T0FFRyxLQUFLd0QsVUFBTCxJQUFtQixLQUFLQSxVQUFMLENBQWdCeEQsS0FBaEIsQ0FBdkIsRUFBK0M7V0FDdkMsS0FBUDs7VUFFTSxDQUFDLEtBQUsyRCxjQUFOLElBQXdCLENBQUMsS0FBS0EsY0FBTCxDQUFvQjNELEtBQXBCLENBQWhDOzs7Ozs7Ozs7O2dDQU9hO1FBQ1I0RCxjQUFMLENBQW9CUyxVQUFwQixDQUErQixLQUFLRCxVQUFMLENBQWdCL1AsSUFBaEIsQ0FBcUIsSUFBckIsQ0FBL0I7Ozs7Ozs7Ozs7OztvQ0FTaUIyTCxPQUFPO09BQ3BCLEtBQUt5RCxjQUFULEVBQXlCO1NBQ25CRSxjQUFMLEdBQXNCLEtBQUtBLGNBQUwsSUFBdUIsRUFBN0M7U0FDS0EsY0FBTCxDQUFvQjNELEtBQXBCLElBQTZCLEtBQUtzRSxZQUFMLENBQzVCdEUsS0FENEIsRUFFNUIsS0FBS3VFLGFBQUwsQ0FBbUJsUSxJQUFuQixDQUF3QixJQUF4QixFQUE4QjJMLEtBQTlCLENBRjRCLENBQTdCO0lBRkQsTUFNTztTQUNEMEQsY0FBTCxHQUFzQixLQUFLQSxjQUFMLElBQXVCLEVBQTdDO1NBQ0tBLGNBQUwsQ0FBb0JoUixJQUFwQixDQUF5QnNOLEtBQXpCOzs7OztFQW5LNkJwSjs7QUNkaEM7Ozs7Ozs7SUFNTTROOzs7eUJBQ1M7Ozs7Ozs7Ozs7O1FBU1JDLGFBQUwsR0FBcUIsRUFBckI7Ozs7Ozs7Ozs7Ozs7d0JBUUs7UUFDQSxJQUFJdFMsSUFBSSxDQUFiLEVBQWdCQSxJQUFJZ0YsVUFBVWpGLE1BQTlCLEVBQXNDQyxHQUF0QyxFQUEyQztTQUNyQ3NTLGFBQUwsQ0FBbUIvUixJQUFuQixDQUF3QnlFLFVBQVVoRixDQUFWLENBQXhCOzs7Ozs7Ozs7OztvQ0FRZ0I7UUFDWnNTLGFBQUwsR0FBcUIsSUFBckI7Ozs7Ozs7Ozt1Q0FNb0I7UUFDZixJQUFJdFMsSUFBSSxDQUFiLEVBQWdCQSxJQUFJLEtBQUtzUyxhQUFMLENBQW1CdlMsTUFBdkMsRUFBK0NDLEdBQS9DLEVBQW9EO1NBQzlDc1MsYUFBTCxDQUFtQnRTLENBQW5CLEVBQXNCa08sY0FBdEI7OztRQUdJb0UsYUFBTCxHQUFxQixFQUFyQjs7OztFQXhDeUI3Tjs7QUNKM0I7Ozs7OztJQUtNOE47Ozs7Ozs7Ozs7OztrQ0FVTzNFLE9BQVosRUFBcUJDLEtBQXJCLEVBQTRCQyxRQUE1QixFQUFzQzBFLFlBQXRDLEVBQW9EOzs7K0lBQzdDNUUsT0FENkMsRUFDcENDLEtBRG9DLEVBQzdCQyxRQUQ2Qjs7UUFFOUMyRSxTQUFMLEdBQWlCRCxZQUFqQjs7Ozs7Ozs7Ozs7bUNBTWdCO09BQ1ZFLGFBQWFuRixRQUFRM0MsR0FBUixDQUFZLEtBQUttRCxRQUFqQixFQUEyQixZQUEzQixFQUF5QyxFQUF6QyxDQUFuQjtPQUNNdUIsWUFBWS9CLFFBQVEzQyxHQUFSLENBQVksS0FBS21ELFFBQWpCLEVBQTJCLFdBQTNCLEVBQXdDLEVBQXhDLENBQWxCO09BQ000RSxXQUFXLEtBQUtGLFNBQXRCO09BQ014UyxNQUFNYixTQUFTdVQsUUFBVCxJQUFxQkQsV0FBVyxLQUFLMUUsTUFBaEIsRUFBd0I0RSxTQUE3QyxHQUF5RHRELFNBQXJFO09BQ014SyxNQUFNMUYsU0FBU3VULFFBQVQsSUFBcUJBLFFBQXJCLEdBQWdDLEtBQUszRSxNQUFqRDs7U0FFTTNFLE1BQU4sQ0FBYXBKLElBQUk2RSxHQUFKLEtBQVksRUFBekIsRUFBNkIsS0FBS21KLFNBQWxDO09BQ0loTyxJQUFJNkUsR0FBSixLQUFZN0UsSUFBSTZFLEdBQUosRUFBUy9FLE1BQVQsS0FBb0IsQ0FBcEMsRUFBdUM7V0FDL0JFLElBQUk2RSxHQUFKLENBQVA7Ozs7O0VBM0JtQzZJOztBQ1B0Qzs7Ozs7O0lBS01rRjs7Ozs7Ozs7Ozs7O3lCQVVPakYsT0FBWixFQUFxQkMsS0FBckIsRUFBNEJDLFFBQTVCLEVBQXNDZ0YsV0FBdEMsRUFBbUQ7Ozs2SEFDNUNsRixPQUQ0QyxFQUNuQ0MsS0FEbUMsRUFDNUJDLFFBRDRCOztRQUU3Q2lGLFFBQUwsR0FBZ0JELFdBQWhCOzs7Ozs7Ozs7OzttQ0FNZ0I7UUFDWC9FLFFBQUwsQ0FBY2lGLG1CQUFkLENBQWtDLEtBQUtoRixNQUF2QyxFQUErQyxLQUFLQyxTQUFwRCxFQUErRCxLQUFLOEUsUUFBcEU7Ozs7RUFuQjJCcEY7O0FDRjdCLElBQU1zRixpQkFBaUIsRUFBdkI7QUFDQSxJQUFNQyxnQkFBZ0IsRUFBdEI7QUFDQSxBQUFPLElBQU1DLGVBQWUsRUFBckI7O0FBRVAsSUFBTUMsaUJBQWlCLDBCQUF2QjtBQUNBLElBQU1DLGNBQWM7T0FDYixJQURhO1FBRVosSUFGWTtRQUdaLElBSFk7VUFJVixJQUpVO09BS2IsSUFMYTtTQU1YO0NBTlQ7Ozs7Ozs7QUFjQSxBQUFPLFNBQVNDLFVBQVQsQ0FBb0JDLFFBQXBCLEVBQThCQyxPQUE5QixFQUF1QztLQUN6QyxDQUFDeFUsU0FBU3VVLFFBQVQsQ0FBRCxJQUF1QixDQUFDblUsU0FBU29VLE9BQVQsQ0FBNUIsRUFBK0M7Ozs7S0FJM0MsQ0FBQ0QsU0FBU3hULE1BQWQsRUFBc0I7YUFDVixDQUFDd1QsUUFBRCxDQUFYOzs7TUFHSSxJQUFJdlQsSUFBSSxDQUFiLEVBQWdCQSxJQUFJdVQsU0FBU3hULE1BQTdCLEVBQXFDQyxHQUFyQyxFQUEwQztNQUNyQyxlQUFldVQsU0FBU3ZULENBQVQsQ0FBbkIsRUFBZ0M7eUJBQ1R1VCxTQUFTdlQsQ0FBVCxDQUF0QixFQUFtQ3dULE9BQW5DO0dBREQsTUFFTzs0QkFDbUJELFNBQVN2VCxDQUFULENBQXpCLEVBQXNDd1QsT0FBdEM7Ozs7Ozs7Ozs7O0FBV0gsU0FBU0MscUJBQVQsQ0FBK0JqRyxPQUEvQixFQUF3Q2dHLE9BQXhDLEVBQWlEO1NBQ3hDck8sS0FBUixDQUFjLEdBQWQsRUFBbUJzRSxPQUFuQixDQUEyQixVQUFTaUssU0FBVCxFQUFvQjtNQUMxQ0EsU0FBSixFQUFlO1dBQ05DLFNBQVIsQ0FBa0J2SixHQUFsQixDQUFzQnNKLFNBQXRCOztFQUZGOzs7Ozs7Ozs7QUFhRCxTQUFTRSx3QkFBVCxDQUFrQ3BHLE9BQWxDLEVBQTJDZ0csT0FBM0MsRUFBb0Q7S0FDN0NLLHlCQUF1QnJHLFFBQVFrRyxTQUEvQixNQUFOO0tBQ0lJLGtCQUFrQixFQUF0Qjs7V0FFVU4sUUFBUXJPLEtBQVIsQ0FBYyxHQUFkLENBQVY7O01BRUssSUFBSW5GLElBQUksQ0FBYixFQUFnQkEsSUFBSXdULFFBQVF6VCxNQUE1QixFQUFvQ0MsR0FBcEMsRUFBeUM7TUFDbEMwVCxZQUFZRixRQUFReFQsQ0FBUixDQUFsQjs7TUFFSTZULGlCQUFpQjNXLE9BQWpCLE9BQTZCd1csU0FBN0IsWUFBK0MsQ0FBQyxDQUFwRCxFQUF1RDs0QkFDL0JBLFNBQXZCOzs7O0tBSUVJLGVBQUosRUFBcUI7VUFDWkosU0FBUixHQUFvQmxHLFFBQVFrRyxTQUFSLEdBQW9CSSxlQUF4Qzs7Ozs7Ozs7Ozs7QUFXRixTQUFTQyxtQkFBVCxDQUE2QnZHLE9BQTdCLEVBQXNDd0csU0FBdEMsRUFBaURsRyxRQUFqRCxFQUEyRDtXQUNoRFAsUUFBUTNDLEdBQVIsQ0FBWTRDLE9BQVosRUFBcUIsV0FBckIsRUFBa0MsRUFBbEMsQ0FBVixFQUFpRHdHLFNBQWpELEVBQTREbEcsUUFBNUQ7Ozs7Ozs7Ozs7OztBQVlELFNBQVNtRyxvQkFBVCxDQUE4QnpHLE9BQTlCLEVBQXVDd0csU0FBdkMsRUFBa0RyQixRQUFsRCxFQUE0RDdFLFFBQTVELEVBQXNFO0tBQy9Eb0csaUJBQWlCM0csUUFBUTNDLEdBQVIsQ0FBWTRDLE9BQVosRUFBcUIsWUFBckIsRUFBbUMsRUFBbkMsQ0FBdkI7V0FDVTBHLGVBQWVGLFNBQWYsRUFBMEJwQixTQUFwQyxFQUErQ0QsUUFBL0MsRUFBeUQ3RSxRQUF6RDs7Ozs7Ozs7Ozs7QUFXRCxTQUFTcUcsU0FBVCxDQUFtQmxVLEdBQW5CLEVBQXdCNkUsR0FBeEIsRUFBNkI4QixLQUE3QixFQUFvQztLQUMvQixDQUFDM0csSUFBSTZFLEdBQUosQ0FBTCxFQUFlO01BQ1ZBLEdBQUosSUFBVyxFQUFYOztLQUVHQSxHQUFKLEVBQVN2RSxJQUFULENBQWNxRyxLQUFkOzs7Ozs7Ozs7QUFTRCxTQUFTd04sb0JBQVQsQ0FBOEI1RyxPQUE5QixFQUF1Q3dHLFNBQXZDLEVBQWtEO0tBQzdDRSxpQkFBaUIzRyxRQUFRM0MsR0FBUixDQUFZNEMsT0FBWixFQUFxQixZQUFyQixFQUFtQyxFQUFuQyxDQUFyQjtLQUNJLENBQUMwRyxlQUFlRixTQUFmLENBQUwsRUFBZ0M7aUJBQ2hCQSxTQUFmLElBQTRCO1dBQ25CcEMsR0FDUHBFLE9BRE8sRUFFUHdHLFNBRk8sRUFHUEssb0JBSE8sRUFJUCxDQUFDLENBQUNoQixZQUFZVyxTQUFaLENBSkssQ0FEbUI7Y0FPaEI7R0FQWjs7Ozs7Ozs7Ozs7QUFtQkYsQUFBTyxTQUFTTSxPQUFULENBQWlCOUcsT0FBakIsRUFBMEJtRixRQUExQixFQUFvQztRQUNuQ25GLFdBQVcsQ0FBQytHLE1BQU0vRyxPQUFOLEVBQWVtRixRQUFmLENBQW5CLEVBQTZDO1lBQ2xDbkYsUUFBUWpKLFVBQWxCOztRQUVNaUosT0FBUDs7Ozs7Ozs7Ozs7QUFXRCxBQUFPLFNBQVNnSCxNQUFULENBQWdCbEwsTUFBaEIsRUFBd0JiLEtBQXhCLEVBQStCO0tBQ2pDckosU0FBU3FKLEtBQVQsQ0FBSixFQUFxQjtVQUNaZ00sY0FBY2hNLEtBQWQsQ0FBUjs7S0FFR0EsaUJBQWlCaU0sUUFBckIsRUFBK0I7TUFDeEJDLFdBQVd2VSxNQUFNTyxTQUFOLENBQWdCc0ssS0FBaEIsQ0FBc0JwSyxJQUF0QixDQUEyQjRILEtBQTNCLENBQWpCO09BQ0ssSUFBSXpJLElBQUksQ0FBYixFQUFnQkEsSUFBSTJVLFNBQVM1VSxNQUE3QixFQUFxQ0MsR0FBckMsRUFBMEM7VUFDbENpRCxXQUFQLENBQW1CMFIsU0FBUzNVLENBQVQsQ0FBbkI7O0VBSEYsTUFLTztTQUNDaUQsV0FBUCxDQUFtQndGLEtBQW5COztRQUVNQSxLQUFQOzs7Ozs7OztBQVFELEFBQU8sU0FBU2dNLGFBQVQsQ0FBdUJHLFVBQXZCLEVBQW1DO0tBQ25DQyxVQUFVbFosU0FBU2lILGFBQVQsQ0FBdUIsS0FBdkIsQ0FBaEI7U0FDUWtTLFNBQVIsWUFBMkJGLFVBQTNCO1NBQ1FwUSxXQUFSLENBQW9CcVEsUUFBUUUsVUFBNUI7O0tBRU1DLFdBQVdyWixTQUFTc1osc0JBQVQsRUFBakI7UUFDT0osUUFBUUUsVUFBZixFQUEyQjtXQUNqQjlSLFdBQVQsQ0FBcUI0UixRQUFRRSxVQUE3Qjs7UUFFTUMsUUFBUDs7Ozs7Ozs7O0FBU0QsQUFBTyxTQUFTOUosUUFBVCxDQUFrQmdLLFFBQWxCLEVBQTRCQyxRQUE1QixFQUFzQztLQUN4QzFXLFdBQVd5VyxRQUFYLENBQUosRUFBMEI7O1NBRWxCQSxTQUFTbFMsZUFBVCxDQUF5QmtJLFFBQXpCLENBQWtDaUssUUFBbEMsQ0FBUDtFQUZELE1BR087U0FDQ0QsU0FBU2hLLFFBQVQsQ0FBa0JpSyxRQUFsQixDQUFQOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CRixBQUFPLFNBQVNDLFFBQVQsQ0FBa0I1SCxPQUFsQixFQUEyQndHLFNBQTNCLEVBQXNDcUIsZ0JBQXRDLEVBQXdEOVQsUUFBeEQsRUFBa0VvTixXQUFsRSxFQUErRTtLQUMvRTJHLGVBQWVuQyxhQUFhYSxTQUFiLENBQXJCO0tBQ0lzQixnQkFBZ0JBLGFBQWFGLFFBQWpDLEVBQTJDO2NBQzlCRSxhQUFhQyxhQUF6QjthQUNXRCxhQUFhNUcsT0FBYixDQUFxQnhNLElBQXJCLENBQTBCb1QsWUFBMUIsRUFBd0MvVCxRQUF4QyxDQUFYOzs7S0FHR29OLFdBQUosRUFBaUI7O2FBRUxwTixTQUFTVyxJQUFULEVBQVg7V0FDU3NULGdCQUFULEdBQTRCLElBQTVCOzs7c0JBR29CaEksT0FBckIsRUFBOEJ3RyxTQUE5QjtLQUNJNVUsU0FBU2lXLGdCQUFULENBQUosRUFBZ0M7dUJBQ1Y3SCxPQUFyQixFQUE4QndHLFNBQTlCLEVBQXlDcUIsZ0JBQXpDLEVBQTJEOVQsUUFBM0Q7RUFERCxNQUVPO3NCQUNjOFQsZ0JBQXBCLEVBQXNDckIsU0FBdEMsRUFBaUR6UyxRQUFqRDs7O1FBR00sSUFBSWdSLHVCQUFKLENBQ05uVCxTQUFTaVcsZ0JBQVQsSUFBNkI3SCxPQUE3QixHQUF1QzZILGdCQURqQyxFQUVOckIsU0FGTSxFQUdOelMsUUFITSxFQUlObkMsU0FBU2lXLGdCQUFULElBQTZCQSxnQkFBN0IsR0FBZ0QsSUFKMUMsQ0FBUDs7Ozs7Ozs7OztBQWVELFNBQVNJLHFCQUFULENBQStCOU0sSUFBL0IsRUFBcUNxTCxTQUFyQyxFQUFnRDBCLFlBQWhELEVBQThEO0tBQ3pEQSxnQkFBZ0IxQixjQUFjLE9BQTlCLElBQXlDMEIsYUFBYUMsTUFBYixLQUF3QixDQUFyRSxFQUF3RTs7OztTQUloRSxLQUFQOzs7S0FHS0Msa0JBQWtCLENBQUMsUUFBRCxFQUFXLE9BQVgsRUFBb0IsUUFBcEIsRUFBOEIsVUFBOUIsRUFBMEMsVUFBMUMsQ0FBeEI7S0FDSTVCLGNBQWMsT0FBZCxJQUF5QjRCLGdCQUFnQjFZLE9BQWhCLENBQXdCeUwsS0FBS2tOLE9BQTdCLElBQXdDLENBQUMsQ0FBdEUsRUFBeUU7U0FDakUsRUFBRWxOLEtBQUttTixRQUFMLElBQWlCeE0sT0FBT1gsSUFBUCxFQUFhLG9CQUFiLENBQW5CLENBQVA7O1FBRU0sSUFBUDs7Ozs7OztBQU9EOzs7Ozs7QUFRQSxBQUFPLFNBQVNvTixZQUFULENBQXNCcE4sSUFBdEIsRUFBNEI7S0FDOUJBLFFBQVFBLEtBQUtwRSxVQUFqQixFQUE2QjtPQUN2QkEsVUFBTCxDQUFnQkMsV0FBaEIsQ0FBNEJtRSxJQUE1Qjs7Ozs7Ozs7Ozs7OztBQWFGLFNBQVMwTCxvQkFBVCxDQUE4QnhHLEtBQTlCLEVBQXFDO3lCQUNaQSxLQUF4QjtLQUNJbUksTUFBTSxJQUFWO0tBQ01DLFlBQVlwSSxNQUFNcUksYUFBeEI7S0FDTUMsU0FBUyxFQUFmOztRQUVPQywyQkFBMkJILFNBQTNCLEVBQXNDcEksS0FBdEMsRUFBNkNzSSxNQUE3QyxDQUFQO1FBQ09FLGtDQUFrQ0YsTUFBbEMsRUFBMEN0SSxLQUExQyxDQUFQOztPQUVNeUksY0FBTixHQUF1QixJQUF2QjtPQUNNbEQsY0FBTixJQUF3QjZDLFNBQXhCO1FBQ09ELEdBQVA7Ozs7Ozs7OztBQVNEOztBQVFBLEFBc0JBOzs7OztBQUtBOzs7Ozs7OztBQVVBLEFBQU8sU0FBU3pCLEtBQVQsQ0FBZS9HLE9BQWYsRUFBd0JtRixRQUF4QixFQUFrQztLQUNwQyxDQUFDbkYsT0FBRCxJQUFZQSxRQUFROU8sUUFBUixLQUFxQixDQUFyQyxFQUF3QztTQUNoQyxLQUFQOzs7S0FHSzZYLElBQUlDLFFBQVE3VixTQUFsQjtLQUNNOFYsSUFBSUYsRUFBRUcsT0FBRixJQUFhSCxFQUFFSSxxQkFBZixJQUF3Q0osRUFBRUssa0JBQTFDLElBQWdFTCxFQUFFTSxpQkFBbEUsSUFBdUZOLEVBQUVPLGdCQUFuRztLQUNJTCxDQUFKLEVBQU87U0FDQ0EsRUFBRTVWLElBQUYsQ0FBTzJNLE9BQVAsRUFBZ0JtRixRQUFoQixDQUFQOzs7UUFHTW9FLGVBQWV2SixPQUFmLEVBQXdCbUYsUUFBeEIsQ0FBUDs7Ozs7Ozs7Ozs7QUFXRCxTQUFTb0UsY0FBVCxDQUF3QnZKLE9BQXhCLEVBQWlDbUYsUUFBakMsRUFBMkM7S0FDcENxRSxRQUFRcmIsU0FBU3NiLGdCQUFULENBQTBCdEUsUUFBMUIsRUFBb0NuRixRQUFRakosVUFBNUMsQ0FBZDtNQUNLLElBQUl2RSxJQUFJLENBQWIsRUFBZ0JBLElBQUlnWCxNQUFNalgsTUFBMUIsRUFBa0MsRUFBRUMsQ0FBcEMsRUFBdUM7TUFDbENnWCxNQUFNaFgsQ0FBTixNQUFhd04sT0FBakIsRUFBMEI7VUFDbEIsSUFBUDs7O1FBR0ssS0FBUDs7Ozs7Ozs7O0FBU0Q7Ozs7Ozs7QUFlQSxTQUFTMEosdUJBQVQsQ0FBaUNySixLQUFqQyxFQUF3QztPQUNqQ3NKLGVBQU4sR0FBd0JDLGdCQUF4QjtPQUNNQyx3QkFBTixHQUFpQ0MseUJBQWpDOzs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JELEFBQU8sU0FBUzFGLEVBQVQsQ0FBWXBFLE9BQVosRUFBcUJ3RyxTQUFyQixFQUFnQ3pTLFFBQWhDLEVBQTBDdVIsV0FBMUMsRUFBdUQ7S0FDekQxVCxTQUFTb08sT0FBVCxDQUFKLEVBQXVCO1NBQ2Y0SCxTQUFTelosUUFBVCxFQUFtQnFZLFNBQW5CLEVBQThCeEcsT0FBOUIsRUFBdUNqTSxRQUF2QyxDQUFQOztLQUVLK1QsZUFBZW5DLGFBQWFhLFNBQWIsQ0FBckI7S0FDSXNCLGdCQUFnQkEsYUFBYXpILEtBQWpDLEVBQXdDO2NBQzNCeUgsYUFBYUMsYUFBekI7YUFDV0QsYUFBYTVHLE9BQWIsQ0FBcUJ4TSxJQUFyQixDQUEwQm9ULFlBQTFCLEVBQXdDL1QsUUFBeEMsQ0FBWDs7U0FFT21CLGdCQUFSLENBQXlCc1IsU0FBekIsRUFBb0N6UyxRQUFwQyxFQUE4Q3VSLFdBQTlDO1FBQ08sSUFBSUQsY0FBSixDQUFtQnJGLE9BQW5CLEVBQTRCd0csU0FBNUIsRUFBdUN6UyxRQUF2QyxFQUFpRHVSLFdBQWpELENBQVA7Ozs7Ozs7Ozs7Ozs7QUFhRCxBQUFPLFNBQVN5RSxJQUFULENBQWMvSixPQUFkLEVBQXVCd0csU0FBdkIsRUFBa0N6UyxRQUFsQyxFQUE0QztLQUM1Q2lXLGlCQUFpQjVGLEdBQUdwRSxPQUFILEVBQVl3RyxTQUFaLEVBQXVCLFlBQVc7aUJBQ3pDOUYsY0FBZjtTQUNPM00sU0FBUzBPLEtBQVQsQ0FBZSxJQUFmLEVBQXFCakwsU0FBckIsQ0FBUDtFQUZzQixDQUF2QjtRQUlPd1MsY0FBUDs7Ozs7Ozs7OztBQVVELEFBQU8sU0FBU2xPLE1BQVQsQ0FBZ0JrRSxPQUFoQixFQUF5Qm1GLFFBQXpCLEVBQW1DO1FBQ2xDMkIsUUFBUTlHLFFBQVFqSixVQUFoQixFQUE0Qm9PLFFBQTVCLENBQVA7Ozs7Ozs7OztBQVNELEFBQU8sU0FBUzhFLG1CQUFULENBQTZCekQsU0FBN0IsRUFBd0NzQixZQUF4QyxFQUFzRDtjQUMvQ3RCLFNBQWIsSUFBMEJzQixZQUExQjs7Ozs7OztBQU9ELEFBQU8sU0FBU29DLGNBQVQsQ0FBd0IvTyxJQUF4QixFQUE4QjtLQUNoQ0YsY0FBSjtRQUNRQSxRQUFRRSxLQUFLb00sVUFBckIsRUFBa0M7T0FDNUJ2USxXQUFMLENBQWlCaUUsS0FBakI7Ozs7Ozs7OztBQVNGLEFBQU8sU0FBU2tQLGFBQVQsQ0FBdUJwRSxRQUF2QixFQUFpQ0MsT0FBakMsRUFBMEM7S0FDNUMsQ0FBQ3hVLFNBQVN1VSxRQUFULENBQUQsSUFBdUIsQ0FBQ25VLFNBQVNvVSxPQUFULENBQTVCLEVBQStDOzs7O0tBSTNDLENBQUNELFNBQVN4VCxNQUFkLEVBQXNCO2FBQ1YsQ0FBQ3dULFFBQUQsQ0FBWDs7O01BR0ksSUFBSXZULElBQUksQ0FBYixFQUFnQkEsSUFBSXVULFNBQVN4VCxNQUE3QixFQUFxQ0MsR0FBckMsRUFBMEM7TUFDckMsZUFBZXVULFNBQVN2VCxDQUFULENBQW5CLEVBQWdDOzRCQUNOdVQsU0FBU3ZULENBQVQsQ0FBekIsRUFBc0N3VCxPQUF0QztHQURELE1BRU87K0JBQ3NCRCxTQUFTdlQsQ0FBVCxDQUE1QixFQUF5Q3dULE9BQXpDOzs7Ozs7Ozs7OztBQVdILFNBQVNvRSx3QkFBVCxDQUFrQ3BLLE9BQWxDLEVBQTJDZ0csT0FBM0MsRUFBb0Q7U0FDM0NyTyxLQUFSLENBQWMsR0FBZCxFQUFtQnNFLE9BQW5CLENBQTJCLFVBQVNpSyxTQUFULEVBQW9CO01BQzFDQSxTQUFKLEVBQWU7V0FDTkMsU0FBUixDQUFrQnRLLE1BQWxCLENBQXlCcUssU0FBekI7O0VBRkY7Ozs7Ozs7OztBQWFELFNBQVNtRSwyQkFBVCxDQUFxQ3JLLE9BQXJDLEVBQThDZ0csT0FBOUMsRUFBdUQ7S0FDbERLLHlCQUF1QnJHLFFBQVFrRyxTQUEvQixNQUFKOztXQUVVRixRQUFRck8sS0FBUixDQUFjLEdBQWQsQ0FBVjs7TUFFSyxJQUFJbkYsSUFBSSxDQUFiLEVBQWdCQSxJQUFJd1QsUUFBUXpULE1BQTVCLEVBQW9DQyxHQUFwQyxFQUF5QztxQkFDckI2VCxpQkFBaUIxTixPQUFqQixPQUE2QnFOLFFBQVF4VCxDQUFSLENBQTdCLFFBQTRDLEdBQTVDLENBQW5COzs7U0FHTzBULFNBQVIsR0FBb0JHLGlCQUFpQmlFLElBQWpCLEVBQXBCOzs7Ozs7OztBQVFEOzs7Ozs7QUFXQSxTQUFTUix5QkFBVCxHQUFxQztLQUM5QnpKLFFBQVEsSUFBZCxDQURvQztPQUU5QmtLLE9BQU4sR0FBZ0IsSUFBaEI7T0FDTUMsZ0JBQU4sR0FBeUIsSUFBekI7T0FDTXJYLFNBQU4sQ0FBZ0IwVyx3QkFBaEIsQ0FBeUN4VyxJQUF6QyxDQUE4Q2dOLEtBQTlDOzs7Ozs7O0FBT0QsU0FBU3VKLGdCQUFULEdBQTRCO0tBQ3JCdkosUUFBUSxJQUFkLENBRDJCO09BRXJCa0ssT0FBTixHQUFnQixJQUFoQjtPQUNNcFgsU0FBTixDQUFnQndXLGVBQWhCLENBQWdDdFcsSUFBaEMsQ0FBcUNnTixLQUFyQzs7Ozs7Ozs7O0FBU0QsQUFBTyxTQUFTb0ssYUFBVCxDQUF1QnpLLE9BQXZCLEVBQWdDd0csU0FBaEMsRUFBMkM7S0FDN0NiLGFBQWFhLFNBQWIsQ0FBSixFQUE2QjtTQUNyQixJQUFQOzs7S0FHRzVVLFNBQVNvTyxPQUFULENBQUosRUFBdUI7TUFDbEIsQ0FBQ3lGLGVBQWV6RixPQUFmLENBQUwsRUFBOEI7a0JBQ2RBLE9BQWYsSUFBMEI3UixTQUFTaUgsYUFBVCxDQUF1QjRLLE9BQXZCLENBQTFCOztZQUVTeUYsZUFBZXpGLE9BQWYsQ0FBVjs7O0tBR0swSyxNQUFNMUssUUFBUXFJLE9BQXBCO0tBQ0ksQ0FBQzNDLGNBQWNnRixHQUFkLENBQUQsSUFBdUIsQ0FBQ2hGLGNBQWNnRixHQUFkLEVBQW1CMWEsY0FBbkIsQ0FBa0N3VyxTQUFsQyxDQUE1QixFQUEwRTtnQkFDM0RrRSxHQUFkLElBQXFCaEYsY0FBY2dGLEdBQWQsS0FBc0IsRUFBM0M7Z0JBQ2NBLEdBQWQsRUFBbUJsRSxTQUFuQixJQUFnQyxPQUFPQSxTQUFQLElBQW9CeEcsT0FBcEQ7O1FBRU0wRixjQUFjZ0YsR0FBZCxFQUFtQmxFLFNBQW5CLENBQVA7Ozs7Ozs7Ozs7O0FBV0QsU0FBU3FDLGlDQUFULENBQTJDRixNQUEzQyxFQUFtRHRJLEtBQW5ELEVBQTBEO0tBQ3JEbUksTUFBTSxJQUFWOztNQUVLLElBQUloVyxJQUFJLENBQWIsRUFBZ0JBLElBQUltVyxPQUFPcFcsTUFBWCxJQUFxQixDQUFDOE4sTUFBTXNLLGdCQUE1QyxFQUE4RG5ZLEdBQTlELEVBQW1FO1FBQzVEc1csY0FBTixHQUF1QkgsT0FBT25XLENBQVAsRUFBVXdOLE9BQWpDO1NBQ08ySSxPQUFPblcsQ0FBUCxFQUFVbkQsRUFBVixDQUFhZ1IsS0FBYixDQUFQOzs7UUFHTW1JLEdBQVA7Ozs7Ozs7Ozs7Ozs7O0FBY0QsU0FBU0ksMEJBQVQsQ0FBb0NILFNBQXBDLEVBQStDcEksS0FBL0MsRUFBc0R1SyxVQUF0RCxFQUFrRTtLQUM3RHBDLE1BQU0sSUFBVjtLQUNJcUMsY0FBY3hLLE1BQU1oSixNQUF4QjtLQUNNeVQsUUFBUXJDLFVBQVUxUixVQUF4Qjs7UUFFTzhULGVBQWVBLGdCQUFnQkMsS0FBL0IsSUFBd0MsQ0FBQ3pLLE1BQU1rSyxPQUF0RCxFQUErRDtNQUMxRHRDLHNCQUFzQjRDLFdBQXRCLEVBQW1DeEssTUFBTTVPLElBQXpDLEVBQStDNE8sS0FBL0MsQ0FBSixFQUEyRDtTQUNwRHlJLGNBQU4sR0FBdUIrQixXQUF2QjtVQUNPRSx5QkFBeUJGLFdBQXpCLEVBQXNDeEssS0FBdEMsRUFBNkN1SyxVQUE3QyxDQUFQO1VBQ09JLDBCQUEwQnZDLFNBQTFCLEVBQXFDb0MsV0FBckMsRUFBa0R4SyxLQUFsRCxFQUF5RHVLLFVBQXpELENBQVA7O2dCQUVhQyxZQUFZOVQsVUFBMUI7OztRQUdNeVIsR0FBUDs7Ozs7Ozs7OztBQVVEOzs7Ozs7OztBQW9CQTs7QUFZQSxBQTJDQTs7Ozs7Ozs7Ozs7QUFXQSxTQUFTdUMsd0JBQVQsQ0FBa0MvSyxPQUFsQyxFQUEyQ0ssS0FBM0MsRUFBa0R1SyxVQUFsRCxFQUE4RDtLQUN2REssZ0JBQWdCNUssTUFBTXVGLGNBQU4sQ0FBdEI7S0FDSSxDQUFDOVUsTUFBTW1hLGFBQU4sQ0FBRCxJQUF5QixDQUFDdk4sU0FBU3VOLGFBQVQsRUFBd0JqTCxPQUF4QixDQUE5QixFQUFnRTtNQUN6RDhCLFlBQVkvQixRQUFRM0MsR0FBUixDQUFZNEMsT0FBWixFQUFxQixXQUFyQixFQUFrQyxFQUFsQyxFQUFzQ0ssTUFBTTVPLElBQTVDLENBQWxCO1NBQ095WixrQkFBa0JwSixTQUFsQixFQUE2QnpCLEtBQTdCLEVBQW9DTCxPQUFwQyxFQUE2QzRLLFVBQTdDLENBQVA7O1FBRU0sSUFBUDs7Ozs7Ozs7Ozs7QUFXRDs7Ozs7Ozs7Ozs7OztBQW9CQSxTQUFTTSxpQkFBVCxDQUEyQnBKLFNBQTNCLEVBQXNDekIsS0FBdEMsRUFBNkNMLE9BQTdDLEVBQXNENEssVUFBdEQsRUFBa0U7S0FDN0RwQyxNQUFNLElBQVY7YUFDWTFHLGFBQWEsRUFBekI7TUFDSyxJQUFJdFAsSUFBSSxDQUFiLEVBQWdCQSxJQUFJc1AsVUFBVXZQLE1BQWQsSUFBd0IsQ0FBQzhOLE1BQU1tSyxnQkFBL0MsRUFBaUVoWSxHQUFqRSxFQUFzRTtNQUNqRXNQLFVBQVV0UCxDQUFWLEVBQWF3VixnQkFBakIsRUFBbUM7Y0FDdkJqVixJQUFYLENBQWdCO29CQUFBO1FBRVgrTyxVQUFVdFAsQ0FBVjtJQUZMO0dBREQsTUFLTztVQUNDc1AsVUFBVXRQLENBQVYsRUFBYTZOLEtBQWIsQ0FBUDs7O1FBR0ttSSxHQUFQOzs7Ozs7Ozs7Ozs7OztBQWNELFNBQVN3Qyx5QkFBVCxDQUFtQ3ZDLFNBQW5DLEVBQThDekksT0FBOUMsRUFBdURLLEtBQXZELEVBQThEdUssVUFBOUQsRUFBMEU7S0FDckVwQyxNQUFNLElBQVY7S0FDTWxTLE9BQU95SixRQUFRM0MsR0FBUixDQUFZcUwsU0FBWixFQUF1QixZQUF2QixFQUFxQyxFQUFyQyxDQUFiO0tBQ01qTyxNQUFNbEUsS0FBSytKLE1BQU01TyxJQUFYLEVBQWlCMlQsU0FBN0I7S0FDTUEsWUFBWXBOLE9BQU9ELElBQVAsQ0FBWXlDLEdBQVosQ0FBbEI7TUFDSyxJQUFJaEksSUFBSSxDQUFiLEVBQWdCQSxJQUFJNFMsVUFBVTdTLE1BQWQsSUFBd0IsQ0FBQzhOLE1BQU1tSyxnQkFBL0MsRUFBaUVoWSxHQUFqRSxFQUFzRTtNQUNqRXVVLE1BQU0vRyxPQUFOLEVBQWVvRixVQUFVNVMsQ0FBVixDQUFmLENBQUosRUFBa0M7T0FDM0JzUCxZQUFZdEgsSUFBSTRLLFVBQVU1UyxDQUFWLENBQUosQ0FBbEI7VUFDTzBZLGtCQUFrQnBKLFNBQWxCLEVBQTZCekIsS0FBN0IsRUFBb0NMLE9BQXBDLEVBQTZDNEssVUFBN0MsQ0FBUDs7O1FBR0twQyxHQUFQOzs7QUNoMEJEOzs7OztBQ0dBOzs7Ozs7SUFLTTJDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OytCQVNROUssT0FBT0MsVUFBVTtPQUN6QixLQUFLd0QsY0FBTCxDQUFvQjVPLGdCQUF4QixFQUEwQztRQUNyQyxLQUFLa1csZ0JBQUwsQ0FBc0IvSyxLQUF0QixDQUFKLEVBQWtDO1NBQzNCOUUsUUFBUThFLE1BQU0zUSxPQUFOLENBQWMsR0FBZCxFQUFtQixDQUFuQixDQUFkO1NBQ004VyxZQUFZbkcsTUFBTTVRLFNBQU4sQ0FBZ0IsQ0FBaEIsRUFBbUI4TCxLQUFuQixDQUFsQjtTQUNNNEosV0FBVzlFLE1BQU01USxTQUFOLENBQWdCOEwsUUFBUSxDQUF4QixDQUFqQjtZQUNPcU0sU0FBUyxLQUFLOUQsY0FBZCxFQUE4QjBDLFNBQTlCLEVBQXlDckIsUUFBekMsRUFBbUQ3RSxRQUFuRCxDQUFQO0tBSkQsTUFLTztZQUNDOEQsR0FBRyxLQUFLTixjQUFSLEVBQXdCekQsS0FBeEIsRUFBK0JDLFFBQS9CLENBQVA7O0lBUEYsTUFTTzttSkFDb0JELEtBQTFCLEVBQWlDQyxRQUFqQzs7Ozs7Ozs7Ozs7OzttQ0FVZUQsT0FBTztVQUNoQkEsTUFBTVIsTUFBTixDQUFhLENBQWIsRUFBZ0IsQ0FBaEIsTUFBdUIsV0FBOUI7Ozs7Ozs7Ozs7O3VDQVFvQlEsT0FBTztPQUN2QixDQUFDLEtBQUt5RCxjQUFOLElBQXdCLENBQUMsS0FBS0EsY0FBTCxDQUFvQjVPLGdCQUFqRCxFQUFtRTtXQUMzRCxJQUFQOztVQUVPLEtBQUtrVyxnQkFBTCxDQUFzQi9LLEtBQXRCLEtBQWdDQSxNQUFNM1EsT0FBTixDQUFjLEdBQWQsRUFBbUIsQ0FBbkIsTUFBMEIsQ0FBQyxDQUE1RCxJQUNOK2EsY0FBYyxLQUFLM0csY0FBbkIsRUFBbUN6RCxLQUFuQyxDQUREOzs7Ozs7Ozs7Ozs7O29DQVdpQkEsT0FBTztVQUNqQmdMLDZJQUF3QmhMLEtBQXhCLEtBQWtDLEtBQUtpTCxvQkFBTCxDQUEwQmpMLEtBQTFCLENBQXpDOzs7O0VBdkRpQ21EOztBQ0xuQzs7OztJQUdNK0g7Ozs7Ozs7Ozs7Ozs7OzRDQU80QjtPQUM1QkEsU0FBU0MsbUJBQVQsS0FBaUM1YyxTQUFyQyxFQUFnRDthQUN0QzRjLG1CQUFULEdBQStCO2dCQUNuQkQsU0FBU0Usd0JBQVQsQ0FBa0MsV0FBbEMsQ0FEbUI7aUJBRWxCRixTQUFTRSx3QkFBVCxDQUFrQyxZQUFsQztLQUZiOztVQUtNRixTQUFTQyxtQkFBaEI7Ozs7Ozs7Ozs7OzJDQVErQi9aLE1BQU07T0FDL0JpYSxXQUFXLENBQUMsUUFBRCxFQUFXLElBQVgsRUFBaUIsR0FBakIsRUFBc0IsRUFBdEIsQ0FBakI7T0FDTUMsZ0JBQWdCdFQsT0FBT3VULGVBQVAsQ0FBdUJuYSxJQUF2QixFQUE2QixDQUE3QixFQUFnQyxDQUFoQyxFQUFtQ0EsS0FBS2hDLFNBQUwsQ0FBZSxDQUFmLEVBQWtCLENBQWxCLEVBQXFCb2MsV0FBckIsRUFBbkMsQ0FBdEI7T0FDTUMsV0FBVyxDQUFJSCxhQUFKLFVBQTJCQSxhQUEzQixVQUFrREEsYUFBbEQsVUFBeUVsYSxJQUF6RSxTQUFqQjtRQUNLLElBQUllLElBQUksQ0FBYixFQUFnQkEsSUFBSWtaLFNBQVNuWixNQUE3QixFQUFxQ0MsR0FBckMsRUFBMEM7UUFDckMrWSxTQUFTUSxpQkFBVCxDQUEyQjFXLEtBQTNCLENBQWlDcVcsU0FBU2xaLENBQVQsSUFBY21aLGFBQS9DLE1BQWtFL2MsU0FBdEUsRUFBaUY7WUFDekU4YyxTQUFTbFosQ0FBVCxFQUFZaUcsV0FBWixLQUE0QnFULFNBQVN0WixDQUFULENBQW5DOzs7VUFHUWYsSUFBVjs7Ozs7Ozs7Ozs7O3lDQVM2QjtPQUN6QjhaLFNBQVNTLGdCQUFULEtBQThCcGQsU0FBbEMsRUFBNkM7UUFDdENxZCxrQkFBa0IsMkNBQXhCO1FBQ01qTSxVQUFVN1IsU0FBU2lILGFBQVQsQ0FBdUIsS0FBdkIsQ0FBaEI7V0FDTzRLLE9BQVAsRUFBZ0JpTSxlQUFoQjthQUNTRCxnQkFBVCxHQUE0QkMsb0JBQW9Cak0sUUFBUXNILFNBQXhEOztVQUVNaUUsU0FBU1MsZ0JBQWhCOzs7Ozs7QUFJRlQsU0FBU1EsaUJBQVQsR0FBNkI1ZCxTQUFTaUgsYUFBVCxDQUF1QixLQUF2QixDQUE3QjtBQUNBbVcsU0FBU0MsbUJBQVQsR0FBK0I1YyxTQUEvQjtBQUNBMmMsU0FBU1MsZ0JBQVQsR0FBNEJwZCxTQUE1Qjs7QUN4REE7Ozs7SUFHTXNkOzs7Ozs7Ozs7Ozs7Ozs7c0JBUU1DLE1BQU1DLGNBQWM7T0FDeEJ2VixTQUFTMUksU0FBU2lILGFBQVQsQ0FBdUIsUUFBdkIsQ0FBZjtVQUNPK1csSUFBUCxHQUFjQSxJQUFkO09BQ0lDLFlBQUosRUFBa0I7aUJBQ0p2VixNQUFiO0lBREQsTUFFTzthQUNHSCxJQUFULENBQWNqQixXQUFkLENBQTBCb0IsTUFBMUI7O2dCQUVZQSxNQUFiO1VBQ09BLE1BQVA7Ozs7Ozs7Ozs7Ozs7OzswQkFZY3RCLEtBQUs4VyxjQUFjRCxjQUFjO09BQ3pDdlYsU0FBUzFJLFNBQVNpSCxhQUFULENBQXVCLFFBQXZCLENBQWY7VUFDT0csR0FBUCxHQUFhQSxHQUFiOztPQUVNeEIsV0FBVyxTQUFYQSxRQUFXLEdBQVc7aUJBQ2Q4QyxNQUFiO29CQUNnQndWLGNBQWhCO0lBRkQ7UUFJS3hWLE1BQUwsRUFBYSxNQUFiLEVBQXFCOUMsUUFBckI7UUFDSzhDLE1BQUwsRUFBYSxPQUFiLEVBQXNCOUMsUUFBdEI7O09BRUlxWSxZQUFKLEVBQWtCO2lCQUNKdlYsTUFBYjtJQURELE1BRU87YUFDR0gsSUFBVCxDQUFjakIsV0FBZCxDQUEwQm9CLE1BQTFCOzs7VUFHTUEsTUFBUDs7Ozs7Ozs7Ozs7Ozs7OzRCQVlnQkEsUUFBUXdWLGNBQWNELGNBQWM7T0FDOUNyWSxXQUFXLFNBQVhBLFFBQVcsR0FBVztvQkFDWHNZLGNBQWhCO0lBREQ7T0FHSXhWLE9BQU9wRixJQUFQLElBQWVvRixPQUFPcEYsSUFBUCxLQUFnQixpQkFBbkMsRUFBc0Q7VUFDL0NvQyxRQUFOLENBQWVFLFFBQWY7OztnQkFHWThDLE1BQWI7T0FDSUEsT0FBT3RCLEdBQVgsRUFBZ0I7V0FDUjJXLFdBQVdJLE9BQVgsQ0FBbUJ6VixPQUFPdEIsR0FBMUIsRUFBK0I4VyxZQUEvQixFQUE2Q0QsWUFBN0MsQ0FBUDtJQURELE1BRU87VUFDQXZZLFFBQU4sQ0FBZUUsUUFBZjtXQUNPbVksV0FBV3BZLEdBQVgsQ0FBZStDLE9BQU9zVixJQUF0QixFQUE0QkMsWUFBNUIsQ0FBUDs7Ozs7Ozs7Ozs7Ozs7O3NDQVl5QnBNLFNBQVNxTSxjQUFjRCxjQUFjO09BQ3pERyxVQUFVdk0sUUFBUXlKLGdCQUFSLENBQXlCLFFBQXpCLENBQWhCO09BQ0k4QyxRQUFRaGEsTUFBWixFQUFvQjtlQUNSaWEsaUJBQVgsQ0FBNkJELE9BQTdCLEVBQXNDLENBQXRDLEVBQXlDRixZQUF6QyxFQUF1REQsWUFBdkQ7SUFERCxNQUVPLElBQUlDLFlBQUosRUFBa0I7VUFDbEJ4WSxRQUFOLENBQWV3WSxZQUFmOzs7Ozs7Ozs7Ozs7Ozs7O29DQWF1QkUsU0FBU2hSLE9BQU84USxjQUFjRCxjQUFjO2NBQ3pESyxTQUFYLENBQXFCRixRQUFRRyxJQUFSLENBQWFuUixLQUFiLENBQXJCLEVBQTBDLFlBQVc7UUFDaERBLFFBQVFnUixRQUFRaGEsTUFBUixHQUFpQixDQUE3QixFQUFnQztnQkFDcEJpYSxpQkFBWCxDQUE2QkQsT0FBN0IsRUFBc0NoUixRQUFRLENBQTlDLEVBQWlEOFEsWUFBakQsRUFBK0RELFlBQS9EO0tBREQsTUFFTyxJQUFJQyxZQUFKLEVBQWtCO1dBQ2xCeFksUUFBTixDQUFld1ksWUFBZjs7SUFKRixFQU1HRCxZQU5IOzs7Ozs7QUN6R0Y7Ozs7SUFHTU87Ozs7Ozs7Ozs7Ozs7OztzQkFRTVIsTUFBTUMsY0FBYztPQUN4Qi9XLFFBQVFsSCxTQUFTaUgsYUFBVCxDQUF1QixPQUF2QixDQUFkO1NBQ01rUyxTQUFOLEdBQWtCNkUsSUFBbEI7T0FDSUMsWUFBSixFQUFrQjtpQkFDSi9XLEtBQWI7SUFERCxNQUVPO2FBQ0dxQixJQUFULENBQWNqQixXQUFkLENBQTBCSixLQUExQjs7VUFFTUEsS0FBUDs7Ozs7Ozs7Ozs7Ozs7OzBCQVljbUUsTUFBTTZTLGNBQWNELGNBQWM7T0FDMUM3UyxPQUFPcEwsU0FBU2lILGFBQVQsQ0FBdUIsTUFBdkIsQ0FBYjtRQUNLd1gsR0FBTCxHQUFXLFlBQVg7UUFDS3BULElBQUwsR0FBWUEsSUFBWjtvQkFDaUJxVCxRQUFqQixDQUEwQnRULElBQTFCLEVBQWdDOFMsWUFBaEMsRUFBOENELFlBQTlDO1VBQ083UyxJQUFQOzs7Ozs7Ozs7Ozs7Ozs7MkJBWWVsRSxPQUFPZ1gsY0FBY0QsY0FBYztPQUM1Q3JZLFdBQVcsU0FBWEEsUUFBVyxHQUFXO29CQUNYc1ksY0FBaEI7SUFERDtPQUdJaFgsTUFBTXVYLEdBQU4sSUFBYXZYLE1BQU11WCxHQUFOLEtBQWMsWUFBL0IsRUFBNkM7VUFDdEMvWSxRQUFOLENBQWVFLFFBQWY7Ozs7T0FJR3NCLE1BQU1nVCxPQUFOLEtBQWtCLE9BQXRCLEVBQStCO1VBQ3hCeFUsUUFBTixDQUFlRSxRQUFmO0lBREQsTUFFTztTQUNEc0IsS0FBTCxFQUFZLE1BQVosRUFBb0J0QixRQUFwQjtTQUNLc0IsS0FBTCxFQUFZLE9BQVosRUFBcUJ0QixRQUFyQjs7O09BR0dxWSxZQUFKLEVBQWtCO2lCQUNKL1csS0FBYjtJQURELE1BRU87YUFDR3FCLElBQVQsQ0FBY2pCLFdBQWQsQ0FBMEJKLEtBQTFCOzs7VUFHTUEsS0FBUDs7Ozs7Ozs7Ozs7Ozs7cUNBV3lCMkssU0FBU3FNLGNBQWNELGNBQWM7T0FDeERVLFNBQVM5TSxRQUFReUosZ0JBQVIsQ0FBeUIsWUFBekIsQ0FBZjtPQUNJcUQsT0FBT3ZhLE1BQVAsS0FBa0IsQ0FBbEIsSUFBdUI4WixZQUEzQixFQUF5QztVQUNsQ3hZLFFBQU4sQ0FBZXdZLFlBQWY7Ozs7T0FJR1UsWUFBWSxDQUFoQjtPQUNNaFosV0FBVyxTQUFYQSxRQUFXLEdBQVc7UUFDdkJzWSxnQkFBZ0IsRUFBRVUsU0FBRixLQUFnQkQsT0FBT3ZhLE1BQTNDLEVBQW1EO1dBQzVDc0IsUUFBTixDQUFld1ksWUFBZjs7SUFGRjtRQUtLLElBQUk3WixJQUFJLENBQWIsRUFBZ0JBLElBQUlzYSxPQUFPdmEsTUFBM0IsRUFBbUNDLEdBQW5DLEVBQXdDO3FCQUN0QnFhLFFBQWpCLENBQTBCQyxPQUFPdGEsQ0FBUCxDQUExQixFQUFxQ3VCLFFBQXJDLEVBQStDcVksWUFBL0M7Ozs7Ozs7QUMvRkgsSUFBTVksZ0JBQWdCO2FBQ1QsV0FEUzthQUVULFVBRlM7ZUFHUCxhQUhPO2VBSVA7Q0FKZjtBQU1BaFYsT0FBT0QsSUFBUCxDQUFZaVYsYUFBWixFQUEyQi9RLE9BQTNCLENBQW1DLFVBQVN1SyxTQUFULEVBQW9CO3FCQUNsQ0EsU0FBcEIsRUFBK0I7WUFDcEIsSUFEb0I7V0FFckIsaUJBQVN6UyxRQUFULEVBQW1Cc00sS0FBbkIsRUFBMEI7T0FDNUI0TSxVQUFVNU0sTUFBTTZNLGFBQXRCO09BQ003VixTQUFTZ0osTUFBTXlJLGNBQXJCO09BQ0ksQ0FBQ21FLE9BQUQsSUFBYUEsWUFBWTVWLE1BQVosSUFBc0IsQ0FBQ3FHLFNBQVNyRyxNQUFULEVBQWlCNFYsT0FBakIsQ0FBeEMsRUFBb0U7VUFDN0RFLFVBQU4sR0FBbUIzRyxTQUFuQjtXQUNPelMsU0FBU3NNLEtBQVQsQ0FBUDs7R0FQNEI7aUJBVWYyTSxjQUFjeEcsU0FBZDtFQVZoQjtDQUREOztBQWVBLElBQU00RyxvQkFBb0I7WUFDZCxjQURjO2FBRWI7Q0FGYjtBQUlBcFYsT0FBT0QsSUFBUCxDQUFZcVYsaUJBQVosRUFBK0JuUixPQUEvQixDQUF1QyxVQUFTb1IsU0FBVCxFQUFvQjtLQUNwRDdHLFlBQVk0RyxrQkFBa0JDLFNBQWxCLENBQWxCO3FCQUNvQjdHLFNBQXBCLEVBQStCO1NBQ3ZCLElBRHVCO1lBRXBCLElBRm9CO1dBR3JCLGlCQUFTelMsUUFBVCxFQUFtQnNNLEtBQW5CLEVBQTBCO1NBQzVCOE0sVUFBTixHQUFtQjNHLFNBQW5CO1VBQ096UyxTQUFTc00sS0FBVCxDQUFQO0dBTDZCO2lCQU9ma0wsU0FBUytCLHVCQUFULEdBQW1DRCxTQUFuQztFQVBoQjtDQUZEOztBQzlCQTs7Ozs7Ozs7OztBQVVBLEFBS0E7Ozs7Ozs7O0FBUUEsSUFBSUUsV0FBVyxTQUFYQSxRQUFXLEdBQVcsRUFBMUI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBNkJBQSxTQUFTcGEsU0FBVCxDQUFtQnhCLElBQW5CLEdBQTBCLFlBQVcsRUFBckM7Ozs7Ozs7Ozs7QUFXQTRiLFNBQVNDLG1CQUFULEdBQStCLGdCQUEvQjs7Ozs7Ozs7Ozs7O0FBYUFELFNBQVNFLGlCQUFULEdBQTZCLFVBQVM3ZCxJQUFULEVBQWU7T0FDckN1RCxTQUFMLENBQWV4QixJQUFmLEdBQXNCL0IsS0FBS3VELFNBQUwsQ0FBZXhCLElBQXJDO09BQ0t3QixTQUFMLENBQWV1YSxjQUFmLEdBQWdDLElBQWhDO0NBRkY7Ozs7Ozs7QUFXQUgsU0FBU0ksZUFBVCxHQUEyQixVQUFTdlcsU0FBVCxFQUFpQjtNQUN0QyxDQUFDQSxTQUFMLEVBQWE7V0FDSixLQUFQOztNQUVFO1dBQ0ssQ0FBQyxDQUFDQSxVQUFPc1csY0FBaEI7R0FERixDQUVFLE9BQU9sWixDQUFQLEVBQVU7O1dBRUgsS0FBUDs7Q0FSSjs7Ozs7Ozs7Ozs7Ozs7O0FBMEJBLElBQUlvWixVQUFVLFNBQVZBLE9BQVUsQ0FBU3ZlLEVBQVQsRUFBYTtNQUNyQjJTLE9BQU9wUCxNQUFNTyxTQUFOLENBQWdCc0ssS0FBaEIsQ0FBc0JwSyxJQUF0QixDQUEyQm1FLFNBQTNCLEVBQXNDLENBQXRDLENBQVg7U0FDTyxZQUFXOzs7UUFHWnFXLFVBQVU3TCxLQUFLdkUsS0FBTCxFQUFkO1lBQ1ExSyxJQUFSLENBQWEwUCxLQUFiLENBQW1Cb0wsT0FBbkIsRUFBNEJyVyxTQUE1QjtXQUNPbkksR0FBR29ULEtBQUgsQ0FBUyxJQUFULEVBQWVvTCxPQUFmLENBQVA7R0FMRjtDQUZGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTJEQSxJQUFJQyxxQkFBcUIsU0FBckJBLGtCQUFxQixDQUFTQyxRQUFULEVBQW1CL1osV0FBbkIsRUFBZ0M7Ozs7OztPQU1sRGdhLE1BQUwsR0FBY0YsbUJBQW1CRyxNQUFuQixDQUEwQkMsT0FBeEM7Ozs7Ozs7T0FPS0MsT0FBTCxHQUFldmYsU0FBZjs7Ozs7O09BTUttTSxPQUFMLEdBQWUsSUFBZjs7Ozs7OztPQU9LcVQsZ0JBQUwsR0FBd0IsSUFBeEI7Ozs7OztPQU1LQyxVQUFMLEdBQWtCLEtBQWxCOztNQUVJUCxtQkFBbUJRLHlCQUFuQixHQUErQyxDQUFuRCxFQUFzRDs7Ozs7Ozs7Ozs7U0FXL0NDLHFCQUFMLEdBQTZCLENBQTdCO0dBWEYsTUFZTyxJQUFJVCxtQkFBbUJRLHlCQUFuQixLQUFpRCxDQUFyRCxFQUF3RDs7Ozs7Ozs7O1NBU3hERSxzQkFBTCxHQUE4QixLQUE5Qjs7O01BR0U7UUFDRWpNLE9BQU8sSUFBWDthQUNTbFAsSUFBVCxDQUNFVyxXQURGLEVBQ2UsVUFBU29GLEtBQVQsRUFBZ0I7V0FDdEJxVixRQUFMLENBQWNYLG1CQUFtQkcsTUFBbkIsQ0FBMEJTLFNBQXhDLEVBQW1EdFYsS0FBbkQ7S0FGSixFQUdLLFVBQVN1VixNQUFULEVBQWlCO1dBQ2JGLFFBQUwsQ0FBY1gsbUJBQW1CRyxNQUFuQixDQUEwQlcsUUFBeEMsRUFBa0RELE1BQWxEO0tBSko7R0FGRixDQVFFLE9BQU9uYSxDQUFQLEVBQVU7U0FDTGlhLFFBQUwsQ0FBY1gsbUJBQW1CRyxNQUFuQixDQUEwQlcsUUFBeEMsRUFBa0RwYSxDQUFsRDs7Q0FuRUo7Ozs7Ozs7Ozs7O0FBZ0ZBc1osbUJBQW1CUSx5QkFBbkIsR0FBK0MsQ0FBL0M7Ozs7Ozs7O0FBU0FSLG1CQUFtQkcsTUFBbkIsR0FBNEI7O1dBRWpCLENBRmlCOzs7V0FLakIsQ0FMaUI7OzthQVFmLENBUmU7OztZQVdoQjtDQVhaOzs7Ozs7Ozs7Ozs7OztBQTJCQUgsbUJBQW1CZSxjQUFuQixHQUFvQyxJQUFwQzs7Ozs7Ozs7QUFTQWYsbUJBQW1CZ0IsT0FBbkIsR0FBNkIsVUFBU0MsU0FBVCxFQUFvQjtTQUN4QyxJQUFJakIsa0JBQUosQ0FBdUIsVUFBU2dCLE9BQVQsRUFBa0I7WUFDcENDLFNBQVI7R0FERyxDQUFQO0NBREY7Ozs7Ozs7QUFZQWpCLG1CQUFtQmtCLE1BQW5CLEdBQTRCLFVBQVNDLFVBQVQsRUFBcUI7U0FDeEMsSUFBSW5CLGtCQUFKLENBQXVCLFVBQVNnQixPQUFULEVBQWtCRSxNQUFsQixFQUEwQjtXQUM3Q0MsVUFBUDtHQURHLENBQVA7Q0FERjs7Ozs7Ozs7QUFhQW5CLG1CQUFtQm9CLElBQW5CLEdBQTBCLFVBQVNDLFFBQVQsRUFBbUI7U0FDcEMsSUFBSXJCLGtCQUFKLENBQXVCLFVBQVNnQixPQUFULEVBQWtCRSxNQUFsQixFQUEwQjtRQUNoRCxDQUFDRyxTQUFTNWMsTUFBZCxFQUFzQjtjQUNaM0QsU0FBUjs7U0FFRyxJQUFJNEQsSUFBSSxDQUFSLEVBQVc0YyxPQUFoQixFQUEwQkEsVUFBVUQsU0FBUzNjLENBQVQsQ0FBcEMsRUFBa0RBLEdBQWxELEVBQXVEO2NBQzdDYixJQUFSLENBQWFtZCxPQUFiLEVBQXNCRSxNQUF0Qjs7R0FMQyxDQUFQO0NBREY7Ozs7Ozs7OztBQW1CQWxCLG1CQUFtQnVCLEdBQW5CLEdBQXlCLFVBQVNGLFFBQVQsRUFBbUI7U0FDbkMsSUFBSXJCLGtCQUFKLENBQXVCLFVBQVNnQixPQUFULEVBQWtCRSxNQUFsQixFQUEwQjtRQUNoRE0sWUFBWUgsU0FBUzVjLE1BQXpCO1FBQ0krSCxTQUFTLEVBQWI7O1FBRUksQ0FBQ2dWLFNBQUwsRUFBZ0I7Y0FDTmhWLE1BQVI7Ozs7UUFJRWlWLFlBQVksU0FBWkEsU0FBWSxDQUFTaFUsS0FBVCxFQUFnQm5DLEtBQWhCLEVBQXVCOzthQUU5Qm1DLEtBQVAsSUFBZ0JuQyxLQUFoQjtVQUNJa1csY0FBYyxDQUFsQixFQUFxQjtnQkFDWGhWLE1BQVI7O0tBSko7O1FBUUlrVixXQUFXLFNBQVhBLFFBQVcsQ0FBU2IsTUFBVCxFQUFpQjthQUN2QkEsTUFBUDtLQURGOztTQUlLLElBQUluYyxJQUFJLENBQVIsRUFBVzRjLE9BQWhCLEVBQTBCQSxVQUFVRCxTQUFTM2MsQ0FBVCxDQUFwQyxFQUFrREEsR0FBbEQsRUFBdUQ7Y0FDN0NiLElBQVIsQ0FBYWljLFFBQVEyQixTQUFSLEVBQW1CL2MsQ0FBbkIsQ0FBYixFQUFvQ2dkLFFBQXBDOztHQXRCQyxDQUFQO0NBREY7Ozs7Ozs7OztBQW9DQTFCLG1CQUFtQjJCLGNBQW5CLEdBQW9DLFVBQVNOLFFBQVQsRUFBbUI7U0FDOUMsSUFBSXJCLGtCQUFKLENBQXVCLFVBQVNnQixPQUFULEVBQWtCRSxNQUFsQixFQUEwQjtRQUNoRFUsV0FBV1AsU0FBUzVjLE1BQXhCO1FBQ0lvZCxVQUFVLEVBQWQ7O1FBRUksQ0FBQ0QsUUFBTCxFQUFlO2NBQ0w5Z0IsU0FBUjs7OztRQUlFMmdCLFlBQVksU0FBWkEsU0FBWSxDQUFTblcsS0FBVCxFQUFnQjtjQUN0QkEsS0FBUjtLQURGOztRQUlJb1csV0FBVyxTQUFYQSxRQUFXLENBQVNqVSxLQUFULEVBQWdCb1QsTUFBaEIsRUFBd0I7O2NBRTdCcFQsS0FBUixJQUFpQm9ULE1BQWpCO1VBQ0llLGFBQWEsQ0FBakIsRUFBb0I7ZUFDWEMsT0FBUDs7S0FKSjs7U0FRSyxJQUFJbmQsSUFBSSxDQUFSLEVBQVc0YyxPQUFoQixFQUEwQkEsVUFBVUQsU0FBUzNjLENBQVQsQ0FBcEMsRUFBa0RBLEdBQWxELEVBQXVEO2NBQzdDYixJQUFSLENBQWE0ZCxTQUFiLEVBQXdCM0IsUUFBUTRCLFFBQVIsRUFBa0JoZCxDQUFsQixDQUF4Qjs7R0F0QkMsQ0FBUDtDQURGOzs7Ozs7Ozs7Ozs7Ozs7OztBQTRDQXNiLG1CQUFtQjNhLFNBQW5CLENBQTZCeEIsSUFBN0IsR0FBb0MsVUFBU2llLGVBQVQsRUFBMEJDLGNBQTFCLEVBQTBDN2IsV0FBMUMsRUFBdUQ7U0FDbEYsS0FBSzhiLGdCQUFMLENBQ0x6ZSxXQUFXdWUsZUFBWCxJQUE4QkEsZUFBOUIsR0FBZ0QsSUFEM0MsRUFFTHZlLFdBQVd3ZSxjQUFYLElBQTZCQSxjQUE3QixHQUE4QyxJQUZ6QyxFQUdMN2IsV0FISyxDQUFQO0NBREY7QUFNQXVaLFNBQVNFLGlCQUFULENBQTJCSyxrQkFBM0I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBd0JBQSxtQkFBbUIzYSxTQUFuQixDQUE2QjRjLFVBQTdCLEdBQTBDLFVBQVNDLFVBQVQsRUFBcUJoYyxXQUFyQixFQUFrQztNQUN0RUQsV0FBVyxTQUFYQSxRQUFXLEdBQVc7UUFDcEI7O2lCQUVTVixJQUFYLENBQWdCVyxXQUFoQjtLQUZGLENBR0UsT0FBTzBMLEdBQVAsRUFBWTt5QkFDT3VRLGdCQUFuQixDQUFvQzVjLElBQXBDLENBQXlDLElBQXpDLEVBQStDcU0sR0FBL0M7O0dBTEo7O09BU0t3USxpQkFBTCxDQUF1QjtXQUNkLElBRGM7Z0JBRVRuYyxRQUZTO2lCQUdSQTtHQUhmO1NBS08sSUFBUDtDQWZGOzs7Ozs7Ozs7Ozs7Ozs7QUFnQ0ErWixtQkFBbUIzYSxTQUFuQixDQUE2QmdkLFNBQTdCLEdBQXlDLFVBQVNDLFVBQVQsRUFBcUJwYyxXQUFyQixFQUFrQztTQUNsRSxLQUFLOGIsZ0JBQUwsQ0FBc0IsSUFBdEIsRUFBNEJNLFVBQTVCLEVBQXdDcGMsV0FBeEMsQ0FBUDtDQURGOzs7OztBQU9BOFosbUJBQW1CM2EsU0FBbkIsQ0FBNkJrZCxLQUE3QixHQUFxQ3ZDLG1CQUFtQjNhLFNBQW5CLENBQTZCZ2QsU0FBbEU7Ozs7Ozs7Ozs7Ozs7O0FBZUFyQyxtQkFBbUIzYSxTQUFuQixDQUE2Qm1kLE1BQTdCLEdBQXNDLFVBQVNDLFdBQVQsRUFBc0I7TUFDdEQsS0FBS3ZDLE1BQUwsS0FBZ0JGLG1CQUFtQkcsTUFBbkIsQ0FBMEJDLE9BQTlDLEVBQXVEO1VBQy9DcGEsR0FBTixDQUFVLFlBQVc7VUFDZjRMLE1BQU0sSUFBSW9PLG1CQUFtQjBDLGlCQUF2QixDQUF5Q0QsV0FBekMsQ0FBVjtVQUNJRSxxQkFBSixHQUE0QixJQUE1QjtXQUNLQyxlQUFMLENBQXFCaFIsR0FBckI7S0FIRixFQUlHLElBSkg7O0NBRko7Ozs7Ozs7O0FBaUJBb08sbUJBQW1CM2EsU0FBbkIsQ0FBNkJ1ZCxlQUE3QixHQUErQyxVQUFTaFIsR0FBVCxFQUFjO01BQ3ZELEtBQUtzTyxNQUFMLEtBQWdCRixtQkFBbUJHLE1BQW5CLENBQTBCQyxPQUE5QyxFQUF1RDtRQUNqRCxLQUFLblQsT0FBVCxFQUFrQjs7V0FFWEEsT0FBTCxDQUFhNFYsWUFBYixDQUEwQixJQUExQixFQUFnQ2pSLEdBQWhDO0tBRkYsTUFHTztXQUNBK08sUUFBTCxDQUFjWCxtQkFBbUJHLE1BQW5CLENBQTBCVyxRQUF4QyxFQUFrRGxQLEdBQWxEOzs7Q0FOTjs7Ozs7Ozs7Ozs7O0FBc0JBb08sbUJBQW1CM2EsU0FBbkIsQ0FBNkJ3ZCxZQUE3QixHQUE0QyxVQUFTQyxZQUFULEVBQXVCbFIsR0FBdkIsRUFBNEI7TUFDbEUsQ0FBQyxLQUFLME8sZ0JBQVYsRUFBNEI7OztNQUd4QnlDLGFBQWEsQ0FBakI7TUFDSUMsYUFBYSxDQUFDLENBQWxCOzs7O09BSUssSUFBSXRlLElBQUksQ0FBUixFQUFXdWUsS0FBaEIsRUFBd0JBLFFBQVEsS0FBSzNDLGdCQUFMLENBQXNCNWIsQ0FBdEIsQ0FBaEMsRUFBMkRBLEdBQTNELEVBQWdFO1FBQzFEeUksUUFBUThWLE1BQU05VixLQUFsQjtRQUNJQSxLQUFKLEVBQVc7O1VBRUxBLFVBQVUyVixZQUFkLEVBQTRCO3FCQUNicGUsQ0FBYjs7VUFFRXNlLGNBQWMsQ0FBZCxJQUFtQkQsYUFBYSxDQUFwQyxFQUF1Qzs7Ozs7Ozs7TUFRdkNDLGNBQWMsQ0FBbEIsRUFBcUI7UUFDZixLQUFLOUMsTUFBTCxLQUFnQkYsbUJBQW1CRyxNQUFuQixDQUEwQkMsT0FBMUMsSUFBcUQyQyxlQUFlLENBQXhFLEVBQTJFO1dBQ3BFSCxlQUFMLENBQXFCaFIsR0FBckI7S0FERixNQUVPO1VBQ0RzUixnQkFBZ0IsS0FBSzVDLGdCQUFMLENBQXNCaGIsTUFBdEIsQ0FBNkIwZCxVQUE3QixFQUF5QyxDQUF6QyxFQUE0QyxDQUE1QyxDQUFwQjtXQUNLRyxnQkFBTCxDQUNFRCxhQURGLEVBQ2lCbEQsbUJBQW1CRyxNQUFuQixDQUEwQlcsUUFEM0MsRUFDcURsUCxHQURyRDs7O0NBN0JOOzs7Ozs7Ozs7OztBQTZDQW9PLG1CQUFtQjNhLFNBQW5CLENBQTZCK2MsaUJBQTdCLEdBQWlELFVBQVNjLGFBQVQsRUFBd0I7TUFDbkUsQ0FBQyxDQUFDLEtBQUs1QyxnQkFBTixJQUEwQixDQUFDLEtBQUtBLGdCQUFMLENBQXNCN2IsTUFBbEQsTUFDRCxLQUFLeWIsTUFBTCxLQUFnQkYsbUJBQW1CRyxNQUFuQixDQUEwQlMsU0FBMUMsSUFDRCxLQUFLVixNQUFMLEtBQWdCRixtQkFBbUJHLE1BQW5CLENBQTBCVyxRQUZ4QyxDQUFKLEVBRXVEO1NBQ2hEc0Msa0JBQUw7O01BRUUsQ0FBQyxLQUFLOUMsZ0JBQVYsRUFBNEI7U0FDckJBLGdCQUFMLEdBQXdCLEVBQXhCOztPQUVHQSxnQkFBTCxDQUFzQnJiLElBQXRCLENBQTJCaWUsYUFBM0I7Q0FURjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZ0NBbEQsbUJBQW1CM2EsU0FBbkIsQ0FBNkIyYyxnQkFBN0IsR0FBZ0QsVUFDaERxQixXQURnRCxFQUNuQ2YsVUFEbUMsRUFDdkJwYyxXQUR1QixFQUNWOztNQUVoQ2dkLGdCQUFnQjtXQUNYLElBRFc7aUJBRUwsSUFGSztnQkFHTjtHQUhkOztnQkFNYy9WLEtBQWQsR0FBc0IsSUFBSTZTLGtCQUFKLENBQXVCLFVBQVNnQixPQUFULEVBQWtCRSxNQUFsQixFQUEwQjs7a0JBRXZEbUMsV0FBZCxHQUE0QkEsY0FBYyxVQUFTL1gsS0FBVCxFQUFnQjtVQUNwRDtZQUNFZ1ksU0FBU0QsWUFBWTlkLElBQVosQ0FBaUJXLFdBQWpCLEVBQThCb0YsS0FBOUIsQ0FBYjtnQkFDUWdZLE1BQVI7T0FGRixDQUdFLE9BQU8xUixHQUFQLEVBQVk7ZUFDTEEsR0FBUDs7S0FMd0IsR0FPeEJvUCxPQVBKOzs7a0JBVWNzQixVQUFkLEdBQTJCQSxhQUFhLFVBQVN6QixNQUFULEVBQWlCO1VBQ25EO1lBQ0V5QyxTQUFTaEIsV0FBVy9jLElBQVgsQ0FBZ0JXLFdBQWhCLEVBQTZCMmEsTUFBN0IsQ0FBYjtZQUNJLENBQUM3ZCxNQUFNc2dCLE1BQU4sQ0FBRCxJQUFrQnpDLE9BQU84QixxQkFBN0IsRUFBb0Q7O2lCQUUzQzlCLE1BQVA7U0FGRixNQUdPO2tCQUNHeUMsTUFBUjs7T0FOSixDQVFFLE9BQU8xUixHQUFQLEVBQVk7ZUFDTEEsR0FBUDs7S0FWdUIsR0FZdkJzUCxNQVpKO0dBWm9CLENBQXRCOztnQkEyQmMvVCxLQUFkLENBQW9CRixPQUFwQixHQUE4QixJQUE5QjtPQUNLbVYsaUJBQUw7a0RBQ29EYyxhQURwRDtTQUVPQSxjQUFjL1YsS0FBckI7Q0F2Q0Y7Ozs7Ozs7O0FBaURBNlMsbUJBQW1CM2EsU0FBbkIsQ0FBNkJrZSxrQkFBN0IsR0FBa0QsVUFBU2pZLEtBQVQsRUFBZ0I7TUFDNUQsS0FBSzRVLE1BQUwsS0FBZ0JGLG1CQUFtQkcsTUFBbkIsQ0FBMEJxRCxPQUE5QyxFQUF1RDtVQUMvQyxJQUFJNWlCLEtBQUosQ0FBVSxvQ0FBVixDQUFOOztPQUVHc2YsTUFBTCxHQUFjRixtQkFBbUJHLE1BQW5CLENBQTBCQyxPQUF4QztPQUNLTyxRQUFMLENBQWNYLG1CQUFtQkcsTUFBbkIsQ0FBMEJTLFNBQXhDLEVBQW1EdFYsS0FBbkQ7Q0FMRjs7Ozs7Ozs7QUFlQTBVLG1CQUFtQjNhLFNBQW5CLENBQTZCb2UsaUJBQTdCLEdBQWlELFVBQVM1QyxNQUFULEVBQWlCO01BQzVELEtBQUtYLE1BQUwsS0FBZ0JGLG1CQUFtQkcsTUFBbkIsQ0FBMEJxRCxPQUE5QyxFQUF1RDtVQUMvQyxJQUFJNWlCLEtBQUosQ0FBVSxvQ0FBVixDQUFOOztPQUVHc2YsTUFBTCxHQUFjRixtQkFBbUJHLE1BQW5CLENBQTBCQyxPQUF4QztPQUNLTyxRQUFMLENBQWNYLG1CQUFtQkcsTUFBbkIsQ0FBMEJXLFFBQXhDLEVBQWtERCxNQUFsRDtDQUxGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBMEJBYixtQkFBbUIzYSxTQUFuQixDQUE2QnNiLFFBQTdCLEdBQXdDLFVBQVMrQyxLQUFULEVBQWdCNVksQ0FBaEIsRUFBbUI7TUFDckQsS0FBS29WLE1BQUwsS0FBZ0JGLG1CQUFtQkcsTUFBbkIsQ0FBMEJDLE9BQTlDLEVBQXVEOzs7O01BSW5ELFNBQVN0VixDQUFiLEVBQWdCO1lBQ05rVixtQkFBbUJHLE1BQW5CLENBQTBCVyxRQUFsQztRQUNJLElBQUlsVixTQUFKLENBQWMsNkNBQWQsQ0FBSjtHQUZGLE1BSU8sSUFBSTZULFNBQVNJLGVBQVQsQ0FBeUIvVSxDQUF6QixDQUFKLEVBQWlDO2dDQUNSQSxDQUE5QjtTQUNLb1YsTUFBTCxHQUFjRixtQkFBbUJHLE1BQW5CLENBQTBCcUQsT0FBeEM7TUFDRTNmLElBQUYsQ0FBTyxLQUFLMGYsa0JBQVosRUFBZ0MsS0FBS0UsaUJBQXJDLEVBQXdELElBQXhEOztHQUhLLE1BTUEsSUFBSS9mLFNBQVNvSCxDQUFULENBQUosRUFBaUI7UUFDbEI7VUFDRWpILE9BQU9pSCxFQUFFakgsSUFBYjtVQUNJTixXQUFXTSxJQUFYLENBQUosRUFBc0I7YUFDZjhmLFFBQUwsQ0FBYzdZLENBQWQsRUFBaUJqSCxJQUFqQjs7O0tBSEosQ0FNRSxPQUFPNkMsQ0FBUCxFQUFVO2NBQ0ZzWixtQkFBbUJHLE1BQW5CLENBQTBCVyxRQUFsQztVQUNJcGEsQ0FBSjs7OztPQUlDMlosT0FBTCxHQUFldlYsQ0FBZjtPQUNLb1YsTUFBTCxHQUFjd0QsS0FBZDtPQUNLTixrQkFBTDs7TUFFSU0sVUFBVTFELG1CQUFtQkcsTUFBbkIsQ0FBMEJXLFFBQXBDLElBQWdELENBQUNoVyxFQUFFNlgscUJBQXZELEVBQThFO3VCQUN6RGlCLHNCQUFuQixDQUEwQyxJQUExQyxFQUFnRDlZLENBQWhEOztDQWpDSjs7Ozs7Ozs7Ozs7Ozs7OztBQW9EQWtWLG1CQUFtQjNhLFNBQW5CLENBQTZCc2UsUUFBN0IsR0FBd0MsVUFBU0UsUUFBVCxFQUFtQmhnQixJQUFuQixFQUF5QjtPQUMxRHFjLE1BQUwsR0FBY0YsbUJBQW1CRyxNQUFuQixDQUEwQnFELE9BQXhDO01BQ0lsQyxVQUFVLElBQWQ7TUFDSXdDLFNBQVMsS0FBYjs7TUFFSTlDLFVBQVUsU0FBVkEsT0FBVSxDQUFTMVYsS0FBVCxFQUFnQjtRQUN4QixDQUFDd1ksTUFBTCxFQUFhO2VBQ0YsSUFBVDtjQUNRUCxrQkFBUixDQUEyQmpZLEtBQTNCOztHQUhKOztNQU9JNFYsU0FBUyxTQUFUQSxNQUFTLENBQVNMLE1BQVQsRUFBaUI7UUFDeEIsQ0FBQ2lELE1BQUwsRUFBYTtlQUNGLElBQVQ7Y0FDUUwsaUJBQVIsQ0FBMEI1QyxNQUExQjs7R0FISjs7TUFPSTtTQUNHdGIsSUFBTCxDQUFVc2UsUUFBVixFQUFvQjdDLE9BQXBCLEVBQTZCRSxNQUE3QjtHQURGLENBRUUsT0FBT3hhLENBQVAsRUFBVTtXQUNIQSxDQUFQOztDQXRCSjs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBMkNBc1osbUJBQW1CM2EsU0FBbkIsQ0FBNkIrZCxrQkFBN0IsR0FBa0QsWUFBVztNQUN2RCxDQUFDLEtBQUs3QyxVQUFWLEVBQXNCO1NBQ2ZBLFVBQUwsR0FBa0IsSUFBbEI7VUFDTXZhLEdBQU4sQ0FBVSxLQUFLK2QsaUJBQWYsRUFBa0MsSUFBbEM7O0NBSEo7Ozs7Ozs7QUFhQS9ELG1CQUFtQjNhLFNBQW5CLENBQTZCMGUsaUJBQTdCLEdBQWlELFlBQVc7U0FDbkQsS0FBS3pELGdCQUFMLElBQXlCLEtBQUtBLGdCQUFMLENBQXNCN2IsTUFBdEQsRUFBOEQ7UUFDeER1ZixVQUFVLEtBQUsxRCxnQkFBbkI7U0FDS0EsZ0JBQUwsR0FBd0IsRUFBeEI7O1NBRUssSUFBSTViLElBQUksQ0FBYixFQUFnQkEsSUFBSXNmLFFBQVF2ZixNQUE1QixFQUFvQ0MsR0FBcEMsRUFBeUM7V0FDbEN5ZSxnQkFBTCxDQUFzQmEsUUFBUXRmLENBQVIsQ0FBdEIsRUFBa0MsS0FBS3diLE1BQXZDLEVBQStDLEtBQUtHLE9BQXBEOzs7T0FHQ0UsVUFBTCxHQUFrQixLQUFsQjtDQVRGOzs7Ozs7Ozs7Ozs7O0FBd0JBUCxtQkFBbUIzYSxTQUFuQixDQUE2QjhkLGdCQUE3QixHQUFnRCxVQUNoREQsYUFEZ0QsRUFDakNRLEtBRGlDLEVBQzFCSixNQUQwQixFQUNsQjtNQUN4QkksVUFBVTFELG1CQUFtQkcsTUFBbkIsQ0FBMEJTLFNBQXhDLEVBQW1EO2tCQUNuQ3lDLFdBQWQsQ0FBMEJDLE1BQTFCO0dBREYsTUFFTztTQUNBVyx5QkFBTDtrQkFDYzNCLFVBQWQsQ0FBeUJnQixNQUF6Qjs7Q0FOSjs7Ozs7Ozs7O0FBa0JBdEQsbUJBQW1CM2EsU0FBbkIsQ0FBNkI0ZSx5QkFBN0IsR0FBeUQsWUFBVztNQUM5RGhKLENBQUo7TUFDSStFLG1CQUFtQlEseUJBQW5CLEdBQStDLENBQW5ELEVBQXNEO1NBQy9DdkYsSUFBSSxJQUFULEVBQWVBLEtBQUtBLEVBQUV3RixxQkFBdEIsRUFBNkN4RixJQUFJQSxFQUFFaE8sT0FBbkQsRUFBNEQ7bUJBQzdDZ08sRUFBRXdGLHFCQUFmO1FBQ0VBLHFCQUFGLEdBQTBCLENBQTFCOztHQUhKLE1BS08sSUFBSVQsbUJBQW1CUSx5QkFBbkIsS0FBaUQsQ0FBckQsRUFBd0Q7U0FDeER2RixJQUFJLElBQVQsRUFBZUEsS0FBS0EsRUFBRXlGLHNCQUF0QixFQUE4Q3pGLElBQUlBLEVBQUVoTyxPQUFwRCxFQUE2RDtRQUN6RHlULHNCQUFGLEdBQTJCLEtBQTNCOzs7Q0FUTjs7Ozs7Ozs7Ozs7OztBQTBCQVYsbUJBQW1CNEQsc0JBQW5CLEdBQTRDLFVBQVN0QyxPQUFULEVBQWtCVCxNQUFsQixFQUEwQjtNQUNoRWIsbUJBQW1CUSx5QkFBbkIsR0FBK0MsQ0FBbkQsRUFBc0Q7WUFDNUNDLHFCQUFSLEdBQWdDeUQsV0FBVyxZQUFXO3lCQUNqQy9CLGdCQUFuQixDQUFvQzVjLElBQXBDLENBQXlDLElBQXpDLEVBQStDc2IsTUFBL0M7S0FEOEIsRUFFN0JiLG1CQUFtQlEseUJBRlUsQ0FBaEM7R0FERixNQUtPLElBQUlSLG1CQUFtQlEseUJBQW5CLEtBQWlELENBQXJELEVBQXdEO1lBQ3JERSxzQkFBUixHQUFpQyxJQUFqQztVQUNNMWEsR0FBTixDQUFVLFlBQVc7VUFDZnNiLFFBQVFaLHNCQUFaLEVBQW9DOzJCQUNmeUIsZ0JBQW5CLENBQW9DNWMsSUFBcEMsQ0FBeUMsSUFBekMsRUFBK0NzYixNQUEvQzs7S0FGSjs7Q0FSSjs7Ozs7Ozs7QUF1QkFiLG1CQUFtQm1DLGdCQUFuQixHQUFzQ3ZjLE1BQU1DLGNBQTVDOzs7Ozs7Ozs7Ozs7OztBQWVBbWEsbUJBQW1CbUUsNEJBQW5CLEdBQWtELFVBQVMvUSxPQUFULEVBQWtCO3FCQUMvQytPLGdCQUFuQixHQUFzQy9PLE9BQXRDO0NBREY7Ozs7Ozs7Ozs7QUFjQTRNLG1CQUFtQjBDLGlCQUFuQjs7O2tCQUNjRCxXQUFaLEVBQXlCOzs7K0dBQ2hCQSxXQURnQjs7UUFHbEJBLFdBQUosRUFBaUI7WUFDVnZhLE9BQUwsR0FBZXVhLFdBQWY7Ozs7OztFQUw4QzdoQixLQUFyRDs7O0FBV0FvZixtQkFBbUIwQyxpQkFBbkIsQ0FBcUNyZCxTQUFyQyxDQUErQzdELElBQS9DLEdBQXNELFFBQXREOztBQ3A3QkE7Ozs7Ozs7QUFNQSxTQUFTNGlCLFFBQVQsQ0FBa0I3aUIsRUFBbEIsRUFBc0I4aUIsS0FBdEIsRUFBNkI7UUFDckIsU0FBU0MsU0FBVCxHQUFxQjtNQUN2QnBRLE9BQU94SyxTQUFYO2lCQUNlNGEsU0FBZjtZQUNVM2hCLEVBQVYsR0FBZXVoQixXQUFXLFlBQVc7TUFDakN2UCxLQUFILENBQVMsSUFBVCxFQUFlVCxJQUFmO0dBRGMsRUFFWm1RLEtBRlksQ0FBZjtFQUhEOzs7Ozs7QUFZRCxTQUFTRSxjQUFULENBQXdCRCxTQUF4QixFQUFtQztjQUNyQkEsVUFBVTNoQixFQUF2Qjs7O0FDbEJELElBQU02aEIsUUFBUSxtRkFBZDs7Ozs7OztBQU9BLFNBQVNDLG1CQUFULENBQTZCckosT0FBN0IsRUFBc0M7UUFDOUI7U0FDQ0EsUUFBUSxDQUFSLENBREQ7VUFFRUEsUUFBUSxDQUFSLENBRkY7UUFHQUEsUUFBUSxDQUFSLENBSEE7Z0JBSVFBLFFBQVEsQ0FBUixDQUpSO2tCQUtVQSxRQUFRLENBQVIsQ0FMVjtZQU1JQSxRQUFRLENBQVI7RUFOWDs7Ozs7Ozs7QUFlRCxTQUFTc0osb0JBQVQsQ0FBOEJDLE1BQTlCLEVBQXNDO0tBQ2pDQyxRQUFRLEVBQVo7TUFDSyxJQUFJbGdCLElBQUksQ0FBYixFQUFnQkEsSUFBSWlnQixPQUFPbGdCLE1BQTNCLEVBQW1DQyxHQUFuQyxFQUF3QztNQUNuQ21nQixPQUFLL2dCLFFBQUwsQ0FBYzZnQixPQUFPamdCLENBQVAsQ0FBZCxDQUFKLEVBQThCO1lBQ3BCb2dCLE9BQU9ILE9BQU9qZ0IsQ0FBUCxDQUFQLENBQVQ7R0FERCxNQUVPO09BQ0ZxZ0IsVUFBVUMseUJBQXlCTCxPQUFPamdCLENBQVAsRUFBVXVnQixPQUFuQyxDQUFkO09BQ0lOLE9BQU9qZ0IsQ0FBUCxFQUFVd2dCLE1BQWQsRUFBc0I7ZUFDVkYseUJBQXlCLFFBQVFELE9BQWpDLElBQTRDLEdBQXZEOzthQUVTRCxPQUFPSCxPQUFPamdCLENBQVAsRUFBVXlnQixNQUFqQixXQUErQkosT0FBL0IsT0FBVjtPQUNJSixPQUFPamdCLENBQVAsRUFBVTBnQixRQUFkLEVBQXdCO1FBQ25CLENBQUNULE9BQU9qZ0IsQ0FBUCxFQUFVb2IsT0FBZixFQUF3QjtlQUNia0YseUJBQXlCRCxPQUF6QixDQUFWOztlQUVVLEdBQVg7O1lBRVFBLE9BQVQ7OztRQUdLLElBQUlNLE1BQUosQ0FBVyxNQUFNQywwQkFBMEJWLEtBQTFCLENBQU4sR0FBeUMsR0FBcEQsQ0FBUDs7Ozs7Ozs7QUFRRCxTQUFTSSx3QkFBVCxDQUFrQ0MsT0FBbEMsRUFBMkM7Z0JBQzdCQSxPQUFiOzs7Ozs7OztBQVFELFNBQVNILE1BQVQsQ0FBZ0JyakIsR0FBaEIsRUFBcUI7UUFDYkEsSUFBSW9KLE9BQUosQ0FBWSw0QkFBWixFQUEwQyxNQUExQyxDQUFQOzs7Ozs7OztBQVFELFNBQVN5YSx5QkFBVCxDQUFtQ1YsS0FBbkMsRUFBMEM7S0FDckMsTUFBTWpaLElBQU4sQ0FBV2laLEtBQVgsQ0FBSixFQUF1QjtXQUNiLEdBQVQ7RUFERCxNQUVPO1dBQ0csTUFBVDs7UUFFTUEsS0FBUDs7Ozs7Ozs7OztBQVVELEFBQU8sU0FBU3pZLE9BQVQsQ0FBZW9aLGFBQWYsRUFBOEI7S0FDaEMsQ0FBQ1YsT0FBSy9nQixRQUFMLENBQWN5aEIsYUFBZCxDQUFMLEVBQW1DO1NBQzNCQSxhQUFQOzs7S0FHS0MsUUFBUUQsYUFBZDtLQUNJRSxlQUFlLENBQW5CO0tBQ01kLFNBQVMsRUFBZjtLQUNJZSxXQUFXLEVBQWY7S0FDSWpZLFFBQVEsQ0FBWjs7S0FFSTJOLFVBQVVvSixNQUFNbUIsSUFBTixDQUFXSCxLQUFYLENBQWQ7UUFDT3BLLE9BQVAsRUFBZ0I7TUFDVDVTLE9BQU9pYyxvQkFBb0JySixPQUFwQixDQUFiOzthQUVXb0ssTUFBTTdWLEtBQU4sQ0FBWWxDLEtBQVosRUFBbUIyTixRQUFRM04sS0FBM0IsQ0FBWDtVQUNRMk4sUUFBUTNOLEtBQVIsR0FBZ0JqRixLQUFLeVEsS0FBTCxDQUFXeFUsTUFBbkM7U0FDT1EsSUFBUCxDQUFZeWdCLFFBQVo7O1NBRU96Z0IsSUFBUCxDQUFZO1NBQ0x1RCxLQUFLaEgsSUFBTCxHQUFZZ0gsS0FBS2hILElBQWpCLEdBQXdCLEtBQUtpa0IsY0FEeEI7WUFFRkQsTUFBTS9YLEtBQU4sS0FBZ0IrWCxNQUFNL1gsS0FBTixNQUFpQmpGLEtBQUsyYyxNQUZwQztXQUdIM2MsS0FBSzJjLE1BQUwsSUFBZSxFQUhaO1lBSUYzYyxLQUFLb2QsWUFBTCxJQUFxQnBkLEtBQUtxZCxjQUExQixJQUE0QyxTQUoxQztXQUtIcmQsS0FBS3NkLFFBQUwsS0FBa0IsR0FBbEIsSUFBeUJ0ZCxLQUFLc2QsUUFBTCxLQUFrQixHQUx4QzthQU1EdGQsS0FBS3NkLFFBQUwsS0FBa0IsR0FBbEIsSUFBeUJ0ZCxLQUFLc2QsUUFBTCxLQUFrQjtHQU50RDs7WUFTVXRCLE1BQU1tQixJQUFOLENBQVdILEtBQVgsQ0FBVjs7O0tBR0cvWCxRQUFRK1gsTUFBTS9nQixNQUFsQixFQUEwQjtTQUNsQlEsSUFBUCxDQUFZdWdCLE1BQU16VCxNQUFOLENBQWF0RSxLQUFiLENBQVo7O1FBRU1rWCxNQUFQOzs7Ozs7Ozs7O0FBVUQsQUFBTyxTQUFTb0IsT0FBVCxDQUFpQlIsYUFBakIsRUFBZ0M7UUFDL0JiLHFCQUFxQnZZLFFBQU1vWixhQUFOLENBQXJCLENBQVA7Ozs7Ozs7Ozs7O0FBV0QsQUFBTyxTQUFTUyxXQUFULENBQXFCVCxhQUFyQixFQUFvQzlVLElBQXBDLEVBQTBDO0tBQzFDakksT0FBTyxFQUFiO0tBQ01tYyxTQUFTeFksUUFBTW9aLGFBQU4sQ0FBZjtLQUNNdE0sUUFBUXhJLEtBQUt3SSxLQUFMLENBQVd5TCxxQkFBcUJDLE1BQXJCLENBQVgsQ0FBZDs7S0FFSSxDQUFDMUwsS0FBTCxFQUFZO1NBQ0osSUFBUDs7O0tBR0dnTixhQUFhLENBQWpCO01BQ0ssSUFBSXZoQixJQUFJLENBQWIsRUFBZ0JBLElBQUlpZ0IsT0FBT2xnQixNQUEzQixFQUFtQ0MsR0FBbkMsRUFBd0M7TUFDbkMsQ0FBQ21nQixPQUFLL2dCLFFBQUwsQ0FBYzZnQixPQUFPamdCLENBQVAsQ0FBZCxDQUFMLEVBQStCO09BQzFCNEcsUUFBUTJOLE1BQU1nTixZQUFOLENBQVo7T0FDSXBCLE9BQUs3aEIsS0FBTCxDQUFXc0ksS0FBWCxDQUFKLEVBQXVCO1FBQ2xCcVosT0FBT2pnQixDQUFQLEVBQVV3Z0IsTUFBZCxFQUFzQjthQUNiNVosTUFBTXpCLEtBQU4sQ0FBWSxHQUFaLENBQVI7O1NBRUk4YSxPQUFPamdCLENBQVAsRUFBVWxELElBQWYsSUFBdUI4SixLQUF2Qjs7OztRQUlJOUMsSUFBUDs7O0lDaktLMGQ7Ozs7Ozs7O2dCQVFPelYsSUFBWixFQUFrQjJDLE9BQWxCLEVBQTJCOzs7TUFDdEIsQ0FBQ25RLGdCQUFnQndOLElBQWhCLENBQUwsRUFBNEI7U0FDckIsSUFBSTdQLEtBQUosQ0FBVSwyQkFBVixDQUFOOztNQUVHLENBQUMyQyxXQUFXNlAsT0FBWCxDQUFMLEVBQTBCO1NBQ25CLElBQUl4UyxLQUFKLENBQVUsa0NBQVYsQ0FBTjs7Ozs7Ozs7O09BU0l3UyxPQUFMLEdBQWVBLE9BQWY7Ozs7Ozs7T0FPSzNDLElBQUwsR0FBWUEsSUFBWjs7Ozs7Ozs7Ozs7O3FDQVFrQjtPQUNkLENBQUMsS0FBSzBWLFdBQVYsRUFBdUI7UUFDbEJ4QixTQUFTeFksUUFBTSxLQUFLc0UsSUFBWCxDQUFiO1FBQ0ltVSxRQUFRbUIsUUFBUXBCLE1BQVIsQ0FBWjtTQUNLd0IsV0FBTCxHQUFtQjtpQkFBQTs7S0FBbkI7O1VBS00sS0FBS0EsV0FBWjs7Ozs7Ozs7Ozs7O2dDQVNhMVYsTUFBTTtPQUNmM00sU0FBUyxLQUFLMk0sSUFBZCxDQUFKLEVBQXlCO1dBQ2pCdVYsWUFBWSxLQUFLSSxnQkFBTCxHQUF3QnpCLE1BQXBDLEVBQTRDbFUsSUFBNUMsQ0FBUDs7VUFFTSxFQUFQOzs7Ozs7Ozs7OytCQU9ZO1VBQ0wsS0FBSzJDLE9BQVo7Ozs7Ozs7Ozs7NEJBT1M7VUFDRixLQUFLM0MsSUFBWjs7Ozs7Ozs7Ozs7OEJBUVduRixPQUFPO09BQ2RtRixPQUFPLEtBQUtBLElBQWhCOztPQUVJbE4sV0FBV2tOLElBQVgsQ0FBSixFQUFzQjtXQUNkQSxLQUFLbkYsS0FBTCxDQUFQOztPQUVHeEgsU0FBUzJNLElBQVQsQ0FBSixFQUFvQjtXQUNaLEtBQUsyVixnQkFBTCxHQUF3QnhCLEtBQS9COztPQUVHblUsZ0JBQWdCNFUsTUFBcEIsRUFBNEI7V0FDcEIvWixNQUFNVyxNQUFOLENBQWF3RSxJQUFiLElBQXFCLENBQUMsQ0FBN0I7OztVQUdNLEtBQVA7Ozs7OztJQ2pHSTRWOzs7Ozs7O3NCQU1TOzs7Ozs7Ozs7OztRQVNSQyxLQUFMLEdBQWEsSUFBYjs7Ozs7Ozs7UUFRS0MsU0FBTCxHQUFpQixLQUFqQjs7Ozs7Ozs7Ozs7OzsyQkFRUUMsU0FBUztPQUNiLEtBQUtELFNBQVQsRUFBb0I7U0FDZEQsS0FBTCxHQUFhRSxPQUFiOztVQUVNLElBQVA7Ozs7Ozs7Ozs7K0JBT1k7UUFDUEYsS0FBTCxHQUFhLElBQWI7VUFDTyxJQUFQOzs7Ozs7Ozs7O29DQU9pQjtRQUNaRyxVQUFMOzs7Ozs7Ozs7Ozs2QkFRVTtVQUNILEtBQUtILEtBQVo7Ozs7Ozs7Ozs7Z0NBT2E7VUFDTixLQUFLQyxTQUFaOzs7Ozs7Ozs7OytCQU9ZQSxXQUFXO09BQ25CLENBQUNBLFNBQUwsRUFBZ0I7U0FDVkUsVUFBTDs7UUFFSUYsU0FBTCxHQUFpQkEsU0FBakI7Ozs7RUFoRnNCcGQ7O0lDR2xCdWQ7Ozs7Ozs7Ozs7bUJBU1M7Ozs7Ozs7Ozs7UUFRUi9qQixFQUFMLEdBQVUsTUFBS2drQixPQUFMLENBQWFua0IsUUFBYixDQUFWOzs7Ozs7Ozs7UUFTS29rQixLQUFMLEdBQWEsSUFBYjs7Ozs7Ozs7Ozs7OzZCQU9VO1dBQ0ZDLEdBQVIsQ0FBWSxhQUFhLElBQWIsR0FBb0IsWUFBaEM7Ozs7Ozs7Ozs7Ozs7O3FDQVdrQjtXQUNWQSxHQUFSLENBQVksYUFBYSxJQUFiLEdBQW9CLG9CQUFoQzs7Ozs7Ozs7Ozs7MENBUXVCcFcsTUFBTTtVQUN0QkEsSUFBUDs7Ozs7Ozs7Ozs7MkNBUXdCaVQsT0FBTztVQUN4QkEsS0FBUDs7Ozs7Ozs7Ozs7K0JBUVk7V0FDSm1ELEdBQVIsQ0FBWSxhQUFhLElBQWIsR0FBb0IsY0FBaEM7Ozs7Ozs7Ozs7O29DQVFpQjs7V0FFVEEsR0FBUixDQUFZLGFBQWEsSUFBYixHQUFvQixXQUFoQzs7Ozs7Ozs7Ozs7OztrQ0FVZUMsVUFBVTtVQUNsQjdjLElBQVAsQ0FBWTZjLFFBQVosRUFBc0IzWSxPQUF0QixDQUE4QixlQUFPO1FBQ2hDMlksU0FBU0MsR0FBVCxFQUFjQyxXQUFsQixFQUErQjtnQkFDbkJDLG1CQUFYLENBQStCSCxTQUFTQyxHQUFULEVBQWNDLFdBQTdDOztJQUZGO1VBS09oSCxtQkFBbUJnQixPQUFuQixFQUFQOzs7Ozs7Ozs7Ozs7O21DQVVnQjtVQUNUaEIsbUJBQW1CZ0IsT0FBbkIsRUFBUDs7Ozs7Ozs7Ozs7Ozt1QkFVSThGLFVBQVU7OztXQUNORCxHQUFSLENBQVksYUFBYSxJQUFiLEdBQW9CLFFBQWhDOztPQUVJSyxjQUFjLEVBQWxCOztVQUVPamQsSUFBUCxDQUFZNmMsUUFBWixFQUFzQjNZLE9BQXRCLENBQThCLGVBQU87UUFDaENnWixVQUFVTCxTQUFTQyxHQUFULENBQWQ7UUFDSUssV0FBV0QsUUFBUUUsSUFBUixDQUFhLE9BQUsxa0IsRUFBbEIsQ0FBZjtnQkFDWXNDLElBQVosQ0FBaUJtaUIsUUFBakI7SUFIRDs7VUFNT3BILG1CQUFtQnVCLEdBQW5CLENBQXVCMkYsV0FBdkIsQ0FBUDs7Ozs7Ozs7OzswQkFPTztVQUNBLEtBQUt2a0IsRUFBWjs7Ozs7Ozs7Ozs7Ozs7OztzQ0FhbUI7V0FDWGtrQixHQUFSLENBQVksYUFBYSxJQUFiLEdBQW9CLHFCQUFoQzs7Ozs7Ozs7Ozs2QkFPVTtVQUNILEtBQUtELEtBQVo7Ozs7Ozs7Ozs7Ozs7Ozt5QkFZTTtXQUNFQyxHQUFSLENBQVksYUFBYSxJQUFiLEdBQW9CLFFBQWhDO1VBQ083RyxtQkFBbUJnQixPQUFuQixFQUFQOzs7Ozs7Ozs7Ozs7MEJBU09yZSxJQUFJO1VBQ0osWUFBWUEsRUFBbkI7Ozs7Ozs7Ozs7d0JBT0tBLElBQUk7UUFDSkEsRUFBTCxHQUFVQSxFQUFWOzs7Ozs7Ozs7OzJCQU9RaWtCLE9BQU87UUFDVkEsS0FBTCxHQUFhQSxLQUFiOzs7Ozs7Ozs7NkJBTVU7VUFDSCxLQUFLamtCLEVBQVo7Ozs7RUFoTm1CMGpCOzs7Ozs7Ozs7QUEwTnJCSyxPQUFPN0csZUFBUCxHQUF5QixVQUFTdlcsU0FBVCxFQUFpQjtRQUNsQ0EscUJBQWtCb2QsTUFBekI7Q0FERDs7SUMxTk1ZOzs7Ozs7Ozs7a0JBUU8za0IsRUFBWixFQUFnQjs7Ozs7TUFHWCxDQUFDQSxFQUFMLEVBQVM7U0FDRixJQUFJL0IsS0FBSixDQUFVLDBFQUFWLENBQU47Ozs7Ozs7OztRQVNJb21CLFdBQUwsR0FBbUIsSUFBbkI7Ozs7Ozs7O1FBUUtPLFlBQUwsR0FBb0IsSUFBcEI7Ozs7Ozs7OztRQVNLclYsT0FBTCxHQUFlLElBQWY7Ozs7Ozs7O1FBUUt2UCxFQUFMLEdBQVVBLEVBQVY7Ozs7Ozs7O1FBUUs2a0IsWUFBTCxHQUFvQixJQUFwQjs7UUFFS0QsWUFBTCxHQUFvQixNQUFLRSxRQUFMLENBQWNILFFBQVFJLE9BQXRCLENBQXBCO1FBQ0tDLDBCQUFMO1FBQ0tYLFdBQUwsR0FBbUIsTUFBS08sWUFBeEI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs2QkFhVUssVUFBVUMsYUFBYTtPQUM3QjFhLFFBQVEsS0FBS29hLFlBQWpCOztPQUVJdGtCLGdCQUFnQjRrQixXQUFoQixDQUFKLEVBQWtDO1lBQ3pCLEtBQUtKLFFBQUwsQ0FBY0csUUFBZCxDQUFSO1FBQ0l6YSxLQUFKLEVBQVc7b0JBQ0tBLEtBQWY7S0FERCxNQUVPO2FBQ0UsS0FBSzJhLFdBQUwsQ0FBaUJGLFFBQWpCLENBQVI7VUFDS0csVUFBTCxDQUFnQjVhLEtBQWhCLEVBQXVCLElBQXZCOztXQUVNQSxLQUFQLEVBQWMwYSxXQUFkOzs7T0FHRzNWLFVBQVUsS0FBSzhWLFVBQUwsRUFBZDs7T0FFSTlWLFdBQVcvRSxLQUFmLEVBQXNCO1dBQ2QrRSxPQUFQLEVBQWdCL0UsS0FBaEI7OztVQUdNQSxLQUFQOzs7Ozs7Ozs7Ozs4QkFRV3lhLFVBQVU7T0FDakJ6YSxRQUFRaE4sUUFBUUUsUUFBUixDQUFpQmlILGFBQWpCLENBQStCLEtBQS9CLENBQVo7U0FDTTJKLFlBQU4sQ0FBbUIsSUFBbkIsRUFBeUIsS0FBSzBWLE9BQUwsQ0FBYWlCLFFBQWIsQ0FBekI7VUFDT3phLEtBQVA7Ozs7Ozs7Ozs7OzJCQVFReWEsVUFBVTtVQUNYem5CLFFBQVFFLFFBQVIsQ0FBaUI0bkIsY0FBakIsQ0FBZ0MsS0FBS3RCLE9BQUwsQ0FBYWlCLFFBQWIsQ0FBaEMsQ0FBUDs7Ozs7Ozs7Ozs7OytCQVNZO09BQ1IsS0FBSzFWLE9BQVQsRUFBa0I7V0FDVixLQUFLQSxPQUFaOztRQUVJQSxPQUFMLEdBQWUvUixRQUFRRSxRQUFSLENBQWlCNG5CLGNBQWpCLENBQWdDLEtBQUt0bEIsRUFBckMsQ0FBZjtVQUNPLEtBQUt1UCxPQUFaOzs7Ozs7Ozs7OzBCQU9PO1VBQ0EsS0FBS3ZQLEVBQVo7Ozs7Ozs7Ozs7O29DQVFpQjtVQUNWLEtBQUs2a0IsWUFBWjs7Ozs7Ozs7Ozs7OzBCQVNPSSxVQUFVO1VBQ1YsS0FBS2psQixFQUFMLEdBQVUsR0FBVixHQUFnQmlsQixRQUF2Qjs7Ozs7Ozs7Ozs7OytDQVM0QjtPQUN4QjFWLFVBQVUsS0FBSzhWLFVBQUwsRUFBZDtPQUNJOVYsV0FBVyxDQUFDLEtBQUtxVixZQUFyQixFQUFtQztRQUM5QjdOLFdBQVd2WixRQUFRRSxRQUFSLENBQWlCc1osc0JBQWpCLEVBQWY7V0FDT3pILFFBQVF1SCxVQUFmLEVBQTJCO2NBQ2pCOVIsV0FBVCxDQUFxQnVLLFFBQVF1SCxVQUE3Qjs7U0FFSThOLFlBQUwsR0FBb0IsS0FBS1csVUFBTCxDQUFnQlosUUFBUUksT0FBeEIsRUFBaUNoTyxRQUFqQyxDQUFwQjtTQUNLcU8sVUFBTCxDQUFnQixJQUFoQixFQUFzQixLQUFLUixZQUEzQjs7Ozs7Ozs7Ozs7d0JBUUk1a0IsSUFBSTtRQUNKQSxFQUFMLEdBQVVBLEVBQVY7Ozs7Ozs7Ozs7O2tDQVFlNmtCLGNBQWM7UUFDeEJBLFlBQUwsR0FBb0JBLFlBQXBCOzs7Ozs7Ozs7Ozt1QkFRSUksVUFBVTtPQUNWTyxPQUFPLEtBQUtuQixXQUFoQjtPQUNJb0IsS0FBSyxLQUFLWCxRQUFMLENBQWNHLFFBQWQsQ0FBVDtPQUNJLENBQUNRLEVBQUwsRUFBUztTQUNILEtBQUtiLFlBQVY7O1FBRUlQLFdBQUwsR0FBbUJvQixFQUFuQjtVQUNPLEtBQUtMLFVBQUwsQ0FBZ0JJLElBQWhCLEVBQXNCQyxFQUF0QixFQUEwQm5HLFVBQTFCLENBQXFDLFlBQU07UUFDN0NrRyxRQUFRQSxTQUFTQyxFQUFyQixFQUF5QjtrQkFDWEQsSUFBYjs7SUFGSyxDQUFQOzs7Ozs7Ozs7O3lCQVdNUCxVQUFVO09BQ1p6YSxRQUFRLEtBQUtzYSxRQUFMLENBQWNHLFFBQWQsQ0FBWjtPQUNJemEsS0FBSixFQUFXO2lCQUNHQSxLQUFiOzs7Ozs7Ozs7OzZCQU9TO1VBQ0gsS0FBS3hLLEVBQVo7Ozs7Ozs7Ozs7Ozs7NkJBVVV3bEIsTUFBTUMsSUFBSTtPQUNoQlosZUFBZSxLQUFLQSxZQUFMLElBQXFCRixRQUFRZSxpQkFBaEQ7VUFDT3JJLG1CQUFtQmdCLE9BQW5CLENBQTJCd0csYUFBYWppQixJQUFiLENBQWtCLElBQWxCLEVBQXdCNGlCLElBQXhCLEVBQThCQyxFQUE5QixDQUEzQixDQUFQOzs7O0VBNU9vQmpmOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9RdEJtZSxRQUFRSSxPQUFSLEdBQWtCLFNBQWxCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTBCQUosUUFBUWUsaUJBQVIsR0FBNEIsVUFBU0YsSUFBVCxFQUFlQyxFQUFmLEVBQW1CO0tBQzFDRCxJQUFKLEVBQVU7T0FDSjVnQixLQUFMLENBQVdDLE9BQVgsR0FBcUIsTUFBckI7T0FDSzZRLFNBQUwsQ0FBZXRLLE1BQWYsQ0FBc0IsU0FBdEI7O0tBRUdxYSxFQUFKLEVBQVE7S0FDSjdnQixLQUFILENBQVNDLE9BQVQsR0FBbUIsT0FBbkI7S0FDRzZRLFNBQUgsQ0FBYXZKLEdBQWIsQ0FBaUIsU0FBakI7O0NBUEY7O0lDdlJNd1o7Ozs7Ozs7O2dCQU9TOzs7Ozs7Ozs7O1FBUVJDLFlBQUwsR0FBb0IsSUFBcEI7Ozs7Ozs7UUFPS0MsVUFBTCxHQUFrQixJQUFsQjs7Ozs7Ozs7UUFRS0Msb0JBQUwsR0FBNEIsSUFBNUI7Ozs7Ozs7O1FBUUtsWSxRQUFMLEdBQWdCLEVBQWhCOzs7Ozs7OztRQVFLbVkseUJBQUwsR0FBaUM1WCxNQUFNSSxnQ0FBTixFQUFqQzs7Ozs7Ozs7UUFRS3lYLG9DQUFMLEdBQTRDLElBQTVDOzs7Ozs7OztRQVFLQyxZQUFMLEdBQW9Cem9CLFFBQVFFLFFBQVIsQ0FBaUJ1bUIsS0FBckM7Ozs7Ozs7O1FBUUtpQyxZQUFMLEdBQW9CLDJEQUFwQjs7Ozs7Ozs7UUFRS0MsOEJBQUwsR0FBc0MsS0FBdEM7Ozs7Ozs7O1FBUUtDLFlBQUwsR0FBb0IsZ0RBQXBCOzs7Ozs7OztRQVFLQyxlQUFMLEdBQXVCLGVBQXZCOzs7Ozs7Ozs7Ozs7Ozs7UUFlS0MsZ0NBQUwsR0FBeUMsdUJBQXVCOW9CLFFBQVFDLE1BQVIsQ0FBZXNSLE9BQS9FOzs7Ozs7Ozs7UUFTS3dYLG1CQUFMLEdBQTJCLEtBQTNCOzs7Ozs7OztRQVFLQyxlQUFMLEdBQXVCLElBQXZCOzs7Ozs7Ozs7UUFTS0Msa0JBQUwsR0FBMEIsQ0FBMUI7Ozs7Ozs7OztRQVNLQyxpQkFBTCxHQUF5QixDQUF6Qjs7Ozs7OztRQU9LQyxZQUFMLEdBQW9CLElBQXBCOzs7Ozs7OztRQVFLQyxNQUFMLEdBQWMsRUFBZDs7Ozs7Ozs7UUFRS0MsT0FBTCxHQUFlLEVBQWY7Ozs7Ozs7Ozs7UUFVS0MsZ0JBQUwsR0FBd0IsS0FBeEI7Ozs7Ozs7O1FBUUszQyxRQUFMLEdBQWdCLEVBQWhCOzs7Ozs7Ozs7O1FBVUs0QyxvQkFBTCxHQUE0QixJQUE1Qjs7UUFFS0MsaUJBQUwsR0FBeUIsSUFBSTVTLFlBQUosRUFBekI7O1FBRUs0UyxpQkFBTCxDQUF1QjdhLEdBQXZCLENBQ0N3SCxHQUFHblcsUUFBUUMsTUFBWCxFQUFtQixRQUFuQixFQUE2QmdrQixTQUFTLE1BQUt3RixTQUFMLENBQWVoakIsSUFBZixPQUFULEVBQW9DLEdBQXBDLENBQTdCLENBREQsRUFFQzBQLEdBQUduVyxRQUFRQyxNQUFYLEVBQW1CLE1BQW5CLEVBQTJCLE1BQUt5cEIsT0FBTCxDQUFhampCLElBQWIsT0FBM0IsQ0FGRCxFQUdDMFAsR0FBR25XLFFBQVFDLE1BQVgsRUFBbUIsVUFBbkIsRUFBK0IsTUFBSzBwQixXQUFMLENBQWlCbGpCLElBQWpCLE9BQS9CLENBSEQ7O1FBTUswUCxFQUFMLENBQVEsZUFBUixFQUF5QixNQUFLeVQsZ0JBQTlCO1FBQ0t6VCxFQUFMLENBQVEsZ0JBQVIsRUFBMEIsTUFBSzBULGlCQUEvQjtRQUNLMVQsRUFBTCxDQUFRLGdCQUFSLEVBQTBCLE1BQUsyVCx3QkFBL0IsRUFBeUQsSUFBekQ7UUFDSzNULEVBQUwsQ0FBUSxjQUFSLEVBQXdCLE1BQUs0VCxzQkFBN0I7O1FBRUtDLGVBQUwsQ0FBcUIsTUFBS3BCLFlBQTFCO1FBQ0txQixlQUFMLENBQXFCLE1BQUt2QixZQUExQjs7UUFFS3dCLDBCQUFMOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7NEJBc0JTZCxRQUFROzs7T0FDYixDQUFDemtCLE1BQU1DLE9BQU4sQ0FBY3drQixNQUFkLENBQUwsRUFBNEI7YUFDbEIsQ0FBQ0EsTUFBRCxDQUFUOztVQUVNcGIsT0FBUCxDQUFlLFVBQUNxWCxLQUFELEVBQVc7UUFDckIsRUFBRUEsaUJBQWlCVSxLQUFuQixDQUFKLEVBQStCO2FBQ3RCLElBQUlBLEtBQUosQ0FBVVYsTUFBTS9VLElBQWhCLEVBQXNCK1UsTUFBTXBTLE9BQTVCLENBQVI7O1dBRUltVyxNQUFMLENBQVl0a0IsSUFBWixDQUFpQnVnQixLQUFqQjtJQUpEO1VBTU8sSUFBUDs7Ozs7Ozs7Ozs7Ozs7OEJBV1dzQixVQUFVOzs7T0FDakIsQ0FBQ2hpQixNQUFNQyxPQUFOLENBQWMraEIsUUFBZCxDQUFMLEVBQThCO2VBQ2xCLENBQUNBLFFBQUQsQ0FBWDs7WUFFUTNZLE9BQVQsQ0FBaUIsVUFBQ2daLE9BQUQsRUFBYTtRQUN6QnJqQixTQUFTcWpCLE9BQVQsQ0FBSixFQUF1QjtlQUNaLElBQUlHLE9BQUosQ0FBWUgsT0FBWixDQUFWOztXQUVJTCxRQUFMLENBQWNLLFFBQVFtRCxLQUFSLEVBQWQsSUFBaUNuRCxPQUFqQztJQUpEO1VBTU8sSUFBUDs7Ozs7Ozs7Ozs7OEJBUVc5YSxLQUFLO09BQ1ZpRixNQUFNUixNQUFNeVosUUFBTixDQUFlbGUsR0FBZixDQUFaOztPQUVJLENBQUNpRixHQUFMLEVBQVU7V0FDRixLQUFQOzs7T0FHS2IsT0FBT0ssTUFBTVcsVUFBTixDQUFpQnBGLEdBQWpCLENBQWI7O09BRUksQ0FBQyxLQUFLbWUsaUJBQUwsQ0FBdUJsWixJQUFJckMsV0FBSixFQUF2QixDQUFMLEVBQWdEO1lBQ3ZDNFgsR0FBUixDQUFZLHNCQUFaO1dBQ08sS0FBUDs7T0FFRyxDQUFDLEtBQUs0RCxlQUFMLENBQXFCaGEsSUFBckIsQ0FBTCxFQUFpQztZQUN4Qm9XLEdBQVIsQ0FBWSx1Q0FBWjtXQUNPLEtBQVA7OztPQUdHdlYsSUFBSWpCLE9BQUosTUFBaUJTLE1BQU00WixvQkFBTixDQUEyQmphLElBQTNCLENBQXJCLEVBQXVEO1dBQy9DLEtBQVA7O09BRUcsQ0FBQyxLQUFLa2EsU0FBTCxDQUFlbGEsSUFBZixDQUFMLEVBQTJCO1lBQ2xCb1csR0FBUixDQUFZLGtCQUFrQnBXLElBQTlCO1dBQ08sS0FBUDs7O1VBR00sSUFBUDs7Ozs7Ozs7OztzQ0FPbUI7OztVQUNaeEcsSUFBUCxDQUFZLEtBQUt1ZixPQUFqQixFQUEwQnJiLE9BQTFCLENBQWtDLFVBQUNzQyxJQUFELEVBQVU7UUFDdkNBLFNBQVMsT0FBSytYLFVBQWxCLEVBQThCO1lBQ3hCRCxZQUFMLENBQWtCOUIsVUFBbEI7S0FERCxNQUVPO1lBQ0RtRSxZQUFMLENBQWtCbmEsSUFBbEI7O0lBSkY7Ozs7Ozs7Ozs7O3VDQWNvQkEsTUFBTStVLE9BQU87T0FDN0IsQ0FBQyxLQUFLMkQsZUFBTixJQUF5QjFZLFNBQVMsS0FBSytYLFVBQTNDLEVBQXVEO1lBQzlDM0IsR0FBUixDQUFZLDRDQUFaO1dBQ08sS0FBSzBCLFlBQVo7OztPQUdHc0MsU0FBUyxLQUFLckIsT0FBTCxDQUFhL1ksSUFBYixDQUFiO09BQ0ksQ0FBQ29hLE1BQUwsRUFBYTtRQUNSelgsVUFBVW9TLE1BQU1zRixVQUFOLEVBQWQ7UUFDSTFYLFlBQVlzVCxNQUFaLElBQXNCQSxPQUFPN0csZUFBUCxDQUF1QnpNLFFBQVEvTixTQUEvQixDQUExQixFQUFxRTtjQUMzRCxJQUFJK04sT0FBSixFQUFUO0tBREQsTUFFTztjQUNHQSxRQUFRb1MsS0FBUixLQUFrQixJQUFJa0IsTUFBSixFQUEzQjs7WUFFT0csR0FBUixDQUFZLHdCQUF3QnBXLElBQXhCLEdBQStCLEtBQS9CLEdBQXVDb2EsTUFBdkMsR0FBZ0QsR0FBNUQ7O1VBRU1BLE1BQVA7Ozs7Ozs7OztvQ0FNaUI7T0FDYixLQUFLdEMsWUFBVCxFQUF1QjtTQUNqQnFDLFlBQUwsQ0FBa0IsS0FBS3BDLFVBQXZCOztRQUVJdUMsaUJBQUw7UUFDS0MsaUJBQUwsQ0FBdUJwWSxjQUF2QjtRQUNLcVksaUJBQUwsQ0FBdUJyWSxjQUF2QjtRQUNLK1csaUJBQUwsQ0FBdUJ1QixrQkFBdkI7Ozs7Ozs7Ozs7Ozs2QkFTVTtVQUNILEtBQUtDLFFBQUwsQ0FBY3JhLE1BQU1zYSxxQkFBTixFQUFkLEVBQTZDLElBQTdDLENBQVA7Ozs7Ozs7Ozs7Ozs4QkFTVzNhLE1BQU00YSxvQkFBb0I7OztPQUNqQyxLQUFLOUMsWUFBTCxJQUFxQixLQUFLQSxZQUFMLENBQWtCK0MsZ0JBQWxCLEVBQXpCLEVBQStEO1NBQ3pEbkMsZUFBTCxHQUF1Qm5KLG1CQUFtQmtCLE1BQW5CLENBQTBCLElBQUlsQixtQkFBbUIwQyxpQkFBdkIsQ0FBeUMsNEJBQXpDLENBQTFCLENBQXZCO1dBQ08sS0FBS3lHLGVBQVo7OztPQUdHM0QsUUFBUSxLQUFLbUYsU0FBTCxDQUFlbGEsSUFBZixDQUFaO09BQ0ksQ0FBQytVLEtBQUwsRUFBWTtTQUNOMkQsZUFBTCxHQUF1Qm5KLG1CQUFtQmtCLE1BQW5CLENBQTBCLElBQUlsQixtQkFBbUIwQyxpQkFBdkIsQ0FBeUMsa0JBQWtCalMsSUFBM0QsQ0FBMUIsQ0FBdkI7V0FDTyxLQUFLMFksZUFBWjs7O1dBR090QyxHQUFSLENBQVksa0JBQWtCcFcsSUFBbEIsR0FBeUIsR0FBckM7O1FBRUs4YSxvQkFBTDtRQUNLckMsbUJBQUwsR0FBMkIsSUFBM0I7O09BRUlzQyxhQUFhLEtBQUtDLG9CQUFMLENBQTBCaGIsSUFBMUIsRUFBZ0MrVSxLQUFoQyxDQUFqQjs7VUFFT2dHLFdBQVdFLElBQVgsQ0FBZ0JqYixJQUFoQixFQUNMNU0sSUFESyxDQUNBLFlBQU07UUFDUCxPQUFLMGtCLFlBQVQsRUFBdUI7WUFDakJBLFlBQUwsQ0FBa0JvRCxVQUFsQjs7V0FFSUMsdUJBQUwsQ0FBNkJuYixJQUE3QixFQUFtQythLFVBQW5DLEVBQStDSCxrQkFBL0M7V0FDS1Esd0JBQUwsQ0FDQ0wsVUFERCxFQUVDLE9BQUsxRSxRQUZOLEVBR0MsT0FBS2dGLGFBQUwsQ0FBbUJ0RyxLQUFuQixFQUEwQi9VLElBQTFCLENBSEQ7SUFOSyxFQVlMNU0sSUFaSyxDQVlBO1dBQU0ybkIsV0FBV08sY0FBWCxDQUEwQixPQUFLakYsUUFBL0IsQ0FBTjtJQVpBLEVBYUxqakIsSUFiSyxDQWFBO1dBQU0ybkIsV0FBV1EsSUFBWCxDQUFnQixPQUFLbEYsUUFBckIsQ0FBTjtJQWJBLEVBY0xqakIsSUFkSyxDQWNBO1dBQU0ybkIsV0FBV1MsZUFBWCxDQUEyQixPQUFLbkYsUUFBaEMsQ0FBTjtJQWRBLEVBZUxqakIsSUFmSyxDQWVBO1dBQU0sT0FBS3FvQiwrQkFBTCxFQUFOO0lBZkEsRUFnQkxyb0IsSUFoQkssQ0FnQkE7V0FBTSxPQUFLc29CLGdDQUFMLEVBQU47SUFoQkEsRUFpQkx0b0IsSUFqQkssQ0FpQkE7V0FBTSxPQUFLdW9CLGlCQUFMLENBQXVCM2IsSUFBdkIsRUFBNkIrYSxVQUE3QixDQUFOO0lBakJBLEVBa0JMM25CLElBbEJLLENBa0JBO1dBQU0sT0FBS3dtQiwwQkFBTCxFQUFOO0lBbEJBLEVBbUJMOUgsS0FuQkssQ0FtQkMsVUFBQzFCLE1BQUQsRUFBWTtXQUNicUksbUJBQUwsR0FBMkIsS0FBM0I7V0FDS21ELG9CQUFMLENBQTBCNWIsSUFBMUIsRUFBZ0MrYSxVQUFoQyxFQUE0QzNLLE1BQTVDO1VBQ01BLE1BQU47SUF0QkssQ0FBUDs7Ozs7Ozs7Ozs7O2dDQWdDYTJFLE9BQU8vVSxNQUFNO1VBQ25CK1UsTUFBTXNHLGFBQU4sQ0FBb0IsS0FBS1EsWUFBTCxDQUFrQjdiLElBQWxCLENBQXBCLENBQVA7Ozs7Ozs7Ozs7OztvQ0FTaUJBLE1BQU0rYSxZQUFZO2NBQ3hCZSxRQUFYOztPQUVJLEtBQUtoRSxZQUFMLElBQXFCLENBQUMsS0FBS0EsWUFBTCxDQUFrQmlFLFdBQWxCLEVBQTFCLEVBQTJEO1FBQ3RELEtBQUtqRSxZQUFMLEtBQXNCaUQsVUFBMUIsRUFBc0M7VUFDaENaLFlBQUwsQ0FBa0IsS0FBS3BDLFVBQXZCOzs7O1FBSUdBLFVBQUwsR0FBa0IvWCxJQUFsQjtRQUNLOFgsWUFBTCxHQUFvQmlELFVBQXBCO1FBQ0s5Qyx5QkFBTCxHQUFpQzVYLE1BQU1JLGdDQUFOLEVBQWpDO1FBQ0tzWSxPQUFMLENBQWEvWSxJQUFiLElBQXFCK2EsVUFBckI7UUFDS3RDLG1CQUFMLEdBQTJCLEtBQTNCO1FBQ0tDLGVBQUwsR0FBdUIsSUFBdkI7V0FDUXNELG1CQUFSLEdBQThCLElBQTlCO1dBQ1FDLHlCQUFSLEdBQW9DLElBQXBDO1dBQ1E3RixHQUFSLENBQVksaUJBQVo7Ozs7Ozs7Ozs7Ozs7NEJBVVNwVyxNQUFNO1VBQ1IsS0FBSzZiLFlBQUwsQ0FBa0I3YixJQUFsQixDQUFQO1FBQ0ssSUFBSS9MLElBQUksQ0FBYixFQUFnQkEsSUFBSSxLQUFLNmtCLE1BQUwsQ0FBWTlrQixNQUFoQyxFQUF3Q0MsR0FBeEMsRUFBNkM7UUFDeEM4Z0IsUUFBUSxLQUFLK0QsTUFBTCxDQUFZN2tCLENBQVosQ0FBWjtRQUNJOGdCLE1BQU1tSCxXQUFOLENBQWtCbGMsSUFBbEIsQ0FBSixFQUE2QjtZQUNyQitVLEtBQVA7Ozs7VUFJSyxJQUFQOzs7Ozs7Ozs7OzRDQU95QjtVQUNsQixLQUFLaUQsb0JBQVo7Ozs7Ozs7Ozs7Z0NBT2E7VUFDTixLQUFLbFksUUFBWjs7Ozs7Ozs7OztvQ0FPaUI7VUFDVixLQUFLcVksWUFBWjs7Ozs7Ozs7OztvQ0FPaUI7VUFDVixLQUFLQyxZQUFaOzs7Ozs7Ozs7O3NEQU9tQztVQUM1QixLQUFLQyw4QkFBWjs7Ozs7Ozs7OztvQ0FPaUI7VUFDVixLQUFLQyxZQUFaOzs7Ozs7Ozs7O3VDQU9vQjtVQUNiLEtBQUtDLGVBQVo7Ozs7Ozs7Ozs7Ozs7K0JBVVl2WSxNQUFNO09BQ2QsS0FBS21jLGlDQUFMLEVBQUosRUFBOEM7V0FDdEM5YixNQUFNK2IsOEJBQU4sQ0FBcUNwYyxJQUFyQyxDQUFQO1dBQ09LLE1BQU0rYiw4QkFBTixDQUFxQ3BjLEtBQUtzQixNQUFMLENBQVksS0FBS3hCLFFBQUwsQ0FBYzlMLE1BQTFCLENBQXJDLENBQVA7OztVQUdNcU0sTUFBTVUscUJBQU4sQ0FBNEJmLElBQTVCLENBQVA7VUFDT0ssTUFBTVUscUJBQU4sQ0FBNEJmLEtBQUtzQixNQUFMLENBQVksS0FBS3hCLFFBQUwsQ0FBYzlMLE1BQTFCLENBQTVCLENBQVA7Ozs7Ozs7Ozs7NENBT3lCO1VBQ2xCLEtBQUtpbEIsb0JBQVo7Ozs7Ozs7Ozs7Ozs7dUNBVW9CalosTUFBTSthLFlBQVkzWixPQUFPOzs7V0FDckNnVixHQUFSLENBQVksMkJBQTJCMkUsVUFBM0IsR0FBd0MsS0FBeEMsR0FBZ0QzWixLQUFoRCxHQUF3RCxHQUFwRTtRQUNLMkUsSUFBTCxDQUFVLGlCQUFWLEVBQTZCO2dCQUFBOzBCQUFBOztJQUE3QjtPQUtJLENBQUMxRixNQUFNNFosb0JBQU4sQ0FBMkJqYSxJQUEzQixDQUFMLEVBQXVDO1FBQ2xDLEtBQUt5WSxtQkFBTCxJQUE0QixLQUFLQyxlQUFyQyxFQUFzRDtVQUNoREEsZUFBTCxDQUFxQmxILFVBQXJCLENBQWdDO2FBQU0sT0FBSzJJLFlBQUwsQ0FBa0JuYSxJQUFsQixDQUFOO01BQWhDLEVBQStELElBQS9EO0tBREQsTUFFTztVQUNEbWEsWUFBTCxDQUFrQm5hLElBQWxCOzs7Ozs7Ozs7Ozs7OEJBU1M7VUFDSixLQUFLOFksTUFBTCxDQUFZOWtCLE1BQVosR0FBcUIsQ0FBNUI7Ozs7Ozs7Ozs7Ozs7b0NBVWlCb0gsVUFBVTtVQUNwQkEsYUFBYTFMLFFBQVFDLE1BQVIsQ0FBZWdJLFFBQWYsQ0FBd0J5RCxRQUE1Qzs7Ozs7Ozs7Ozs7O2tDQVNlNEUsTUFBTTtVQUNkQSxLQUFLN08sT0FBTCxDQUFhLEtBQUsyTyxRQUFsQixNQUFnQyxDQUF2Qzs7Ozs7Ozs7Ozs7OytDQVM0QjtPQUN4Qm1ULFFBQVF2akIsUUFBUUMsTUFBUixDQUFlc1IsT0FBZixDQUF1QmdTLEtBQW5DO09BQ0ksQ0FBQ0EsS0FBTCxFQUFZOzs7Ozs7Ozs7OztPQVdSb0osU0FBUyxLQUFiO09BQ0lDLDJCQUEyQixTQUEzQkEsd0JBQTJCLEdBQVc7WUFDakMxc0IsUUFBUixDQUFpQnFYLG1CQUFqQixDQUFxQyxRQUFyQyxFQUErQ3FWLHdCQUEvQyxFQUF5RSxLQUF6RTtRQUNJLENBQUNELE1BQUwsRUFBYTthQUNKMXNCLE1BQVIsQ0FBZTRzQixRQUFmLENBQXdCdEosTUFBTXVKLFVBQTlCLEVBQTBDdkosTUFBTXdKLFNBQWhEO2NBQ1MsSUFBVDs7SUFKRjtTQU9Nbm5CLFFBQU4sQ0FBZWduQix3QkFBZjtXQUNRMXNCLFFBQVIsQ0FBaUIrRyxnQkFBakIsQ0FBa0MsUUFBbEMsRUFBNEMybEIsd0JBQTVDLEVBQXNFLEtBQXRFOzs7Ozs7Ozs7O3dEQU9xQztPQUNqQyxLQUFLOUQsZ0NBQVQsRUFBMkM7U0FDckNrRSx3QkFBTCxHQUFnQ2h0QixRQUFRQyxNQUFSLENBQWVzUixPQUFmLENBQXVCMGIsaUJBQXZEO1lBQ1FodEIsTUFBUixDQUFlc1IsT0FBZixDQUF1QjBiLGlCQUF2QixHQUEyQyxRQUEzQzs7Ozs7Ozs7Ozs7O2lDQVNhMWhCLE1BQU02RyxPQUFPO09BQ3ZCLENBQUMsS0FBSzhhLFdBQUwsQ0FBaUIzaEIsSUFBakIsQ0FBTCxFQUE2Qjs7OztXQUlyQitnQixtQkFBUixHQUE4QmxhLE1BQU1rYSxtQkFBcEM7V0FDUUMseUJBQVIsR0FBb0NuYSxNQUFNbWEseUJBQTFDOztPQUVJWSxpQkFBaUIsS0FBckI7T0FDSTtTQUNFbkMsUUFBTCxDQUFjcmEsTUFBTVcsVUFBTixDQUFpQi9GLElBQWpCLENBQWQsRUFBc0MsS0FBdEMsRUFBNkM2RyxLQUE3QztJQURELENBRUUsT0FBT1gsR0FBUCxFQUFZOztxQkFFSSxJQUFqQjs7O09BR0csQ0FBQzBiLGNBQUwsRUFBcUI7VUFDZEMsY0FBTjs7Ozs7Ozs7Ozs7Ozs7OytDQVkyQjs7O09BQ3hCLGVBQWUsT0FBT250QixPQUFPb3RCLGNBQWpDLEVBQWlEO1dBQ3pDQyxlQUFQLEdBQXlCcnRCLE9BQU9vdEIsY0FBaEM7O1dBRU9BLGNBQVAsR0FBd0IsaUJBQVM7WUFDM0JoWCxJQUFMLENBQVUsY0FBVixFQUEwQmpFLEtBQTFCO1NBQ0lBLFNBQVNBLE1BQU1zSyxnQkFBbkIsRUFBcUM7YUFDN0IsSUFBUDs7S0FIRjs7O1dBUU8yUSxjQUFQLENBQXNCRSxXQUF0QixHQUFvQyxJQUFwQzs7Ozs7Ozs7Ozt3REFPb0M7T0FDL0J2aUIsT0FBT2hMLFFBQVFDLE1BQVIsQ0FBZWdJLFFBQWYsQ0FBd0IrQyxJQUFyQztPQUNJQSxJQUFKLEVBQVU7UUFDTHdpQixnQkFBZ0J4dEIsUUFBUUUsUUFBUixDQUFpQjRuQixjQUFqQixDQUFnQzljLEtBQUt4SixTQUFMLENBQWUsQ0FBZixDQUFoQyxDQUFwQjtRQUNJZ3NCLGFBQUosRUFBbUI7Z0NBQ2M3YyxNQUFNOGMsYUFBTixDQUFvQkQsYUFBcEIsQ0FEZDtTQUNYeGMsVUFEVyx3QkFDWEEsVUFEVztTQUNDQyxTQURELHdCQUNDQSxTQUREOzthQUVWaFIsTUFBUixDQUFlNHNCLFFBQWYsQ0FBd0I3YixVQUF4QixFQUFvQ0MsU0FBcEM7Ozs7Ozs7Ozs7Ozt3REFTbUM7T0FDakMsS0FBSzZYLGdDQUFMLElBQXlDLEtBQUtrRSx3QkFBbEQsRUFBNEU7WUFDbkUvc0IsTUFBUixDQUFlc1IsT0FBZixDQUF1QjBiLGlCQUF2QixHQUEyQyxLQUFLRCx3QkFBaEQ7Ozs7Ozs7Ozs7Ozs7OztnREFZNEIxYyxNQUFNNlksY0FBY25lLE1BQU07T0FDbkRtZSxpQkFBaUJ4WSxNQUFNVSxxQkFBTixDQUE0QmYsSUFBNUIsQ0FBckIsRUFBd0Q7V0FDaEQ2WSxlQUFlbmUsSUFBdEI7O1VBRU1tZSxZQUFQOzs7Ozs7Ozs7O29EQU9pQztPQUM3Qm5lLE9BQU9oTCxRQUFRQyxNQUFSLENBQWVnSSxRQUFmLENBQXdCK0MsSUFBbkM7T0FDSXdpQixnQkFBZ0J4dEIsUUFBUUUsUUFBUixDQUFpQjRuQixjQUFqQixDQUFnQzljLEtBQUt4SixTQUFMLENBQWUsQ0FBZixDQUFoQyxDQUFwQjtPQUNJZ3NCLGFBQUosRUFBbUI7Z0NBQ2M3YyxNQUFNOGMsYUFBTixDQUFvQkQsYUFBcEIsQ0FEZDtRQUNYeGMsVUFEVyx5QkFDWEEsVUFEVztRQUNDQyxTQURELHlCQUNDQSxTQUREOztTQUVieWMscUNBQUwsQ0FBMkN6YyxTQUEzQyxFQUFzREQsVUFBdEQ7Ozs7Ozs7Ozs7Ozs7OzJCQVdPVixNQUFNNGEsb0JBQW9CeUMsV0FBVztPQUN6QyxDQUFDaGQsTUFBTWlkLHVCQUFOLEVBQUwsRUFBc0M7VUFDL0IsSUFBSW50QixLQUFKLENBQVUsc0VBQVYsQ0FBTjs7Ozs7T0FLRzZQLFNBQVMsS0FBSytYLFVBQWxCLEVBQThCO3lCQUNSLElBQXJCOzs7UUFHSWhTLElBQUwsQ0FBVSxnQkFBVixFQUE0QjtXQUNwQnNYLFNBRG9CO1VBRXJCcmQsSUFGcUI7b0JBR1gsQ0FBQyxDQUFDNGE7SUFIbkI7O1VBTU8sS0FBS2xDLGVBQVo7Ozs7Ozs7Ozs7OztvQ0FTaUI1VyxPQUFPO09BQ3BCcFMsUUFBUXNzQixtQkFBWixFQUFpQztVQUMxQnVCLElBQU4sR0FBYTd0QixRQUFRc3NCLG1CQUFyQjs7Ozs7Ozs7Ozs7OzsyQ0FVdUJsYSxPQUFPO09BQzNCLEtBQUs0VyxlQUFULEVBQTBCO1FBQ3JCLEtBQUtBLGVBQUwsQ0FBcUIxWSxJQUFyQixLQUE4QjhCLE1BQU05QixJQUF4QyxFQUE4QzthQUNyQ29XLEdBQVIsQ0FBWSxZQUFaOzs7OztRQUtHclEsSUFBTCxDQUFVLGNBQVYsRUFBMEJqRSxLQUExQjs7UUFFS2lFLElBQUwsQ0FBVSxlQUFWLEVBQTJCO1VBQ3BCakUsTUFBTXliLElBRGM7VUFFcEJ6YixNQUFNOUIsSUFGYztvQkFHVjhCLE1BQU0wYjtJQUh2Qjs7Ozs7Ozs7Ozs7O3lDQWFzQjFiLE9BQU87T0FDekIyYixPQUFPOXRCLE9BQU9xdEIsZUFBbEI7T0FDSVMsUUFBUSxDQUFDQSxLQUFLUixXQUFkLElBQTZCUSxNQUFqQyxFQUF5QztVQUNsQ1gsY0FBTjs7Ozs7Ozs7Ozs7OztzQ0FVa0JoYixPQUFPO09BQ3RCQSxNQUFNNGIsTUFBTixJQUFnQjViLE1BQU02YixPQUF0QixJQUFpQzdiLE1BQU04YixPQUF2QyxJQUFrRDliLE1BQU0rYixRQUF4RCxJQUFvRS9iLE1BQU04SCxNQUE5RSxFQUFzRjtZQUM3RXdNLEdBQVIsQ0FBWSxpRUFBWjs7O1FBR0kwSCxjQUFMLENBQW9CaGMsTUFBTXlJLGNBQU4sQ0FBcUJ0UCxJQUF6QyxFQUErQzZHLEtBQS9DOzs7Ozs7Ozs7Ozs7dUNBU29CQSxPQUFPO09BQ3ZCeWIsT0FBT3piLE1BQU15SSxjQUFqQjtPQUNJZ1QsS0FBS1EsTUFBTCxLQUFnQixLQUFwQixFQUEyQjtZQUNsQjNILEdBQVIsQ0FBWSwwQkFBWjs7O1NBR0s0RixtQkFBTixHQUE0QnVCLElBQTVCO09BQ01TLGlCQUFpQiwyREFBdkI7T0FDSXhWLE1BQU05WSxRQUFRRSxRQUFSLENBQWlCcXVCLGFBQXZCLEVBQXNDRCxjQUF0QyxDQUFKLEVBQTJEO1VBQ3BEL0IseUJBQU4sR0FBa0N2c0IsUUFBUUUsUUFBUixDQUFpQnF1QixhQUFuRDtJQURELE1BRU87VUFDQWhDLHlCQUFOLEdBQWtDc0IsS0FBS1csYUFBTCxDQUFtQkYsY0FBbkIsQ0FBbEM7O1FBRUlGLGNBQUwsQ0FBb0JQLEtBQUtZLE1BQXpCLEVBQWlDcmMsS0FBakM7Ozs7Ozs7Ozs7Ozs0QkFTUzs7O1FBQ0prWCxnQkFBTCxHQUF3QixJQUF4QjtjQUNXLFlBQU07OztXQUdYQSxnQkFBTCxHQUF3QixLQUF4QjtJQUhELEVBSUcsQ0FKSDs7UUFNS29GLG1DQUFMOzs7Ozs7Ozs7Ozs7Ozs7OEJBWVd0YyxPQUFPO09BQ2QsS0FBS2tYLGdCQUFULEVBQTJCOzs7OztPQUt2QjNZLE1BQU00WixvQkFBTixDQUEyQixLQUFLaEMseUJBQWhDLENBQUosRUFBZ0U7U0FDMURtRyxtQ0FBTDs7OztPQUlHbkwsUUFBUW5SLE1BQU1tUixLQUFsQjs7T0FFSSxDQUFDQSxLQUFMLEVBQVk7UUFDUHZqQixRQUFRQyxNQUFSLENBQWVnSSxRQUFmLENBQXdCK0MsSUFBNUIsRUFBa0M7Ozs7O1NBSzdCLEtBQUttZSxZQUFMLElBQXFCLENBQUN4WSxNQUFNNFosb0JBQU4sQ0FBMkIsS0FBS3BCLFlBQWhDLENBQTFCLEVBQXlFO1dBQ25Fd0YsVUFBTDs7OztVQUlJRCxtQ0FBTDtLQVZELE1BV087VUFDREMsVUFBTDs7Ozs7T0FLRXBMLE1BQU1xTCxLQUFWLEVBQWlCO1lBQ1JsSSxHQUFSLENBQVksNEJBQTRCbkQsTUFBTWpULElBQWxDLEdBQXlDLEdBQXJEO1NBQ0s0WSxpQkFBTCxHQUF5QjNGLE1BQU13SixTQUEvQjtTQUNLOUQsa0JBQUwsR0FBMEIxRixNQUFNdUosVUFBaEM7UUFDSSxDQUFDLEtBQUtoRSxnQ0FBVixFQUE0QztVQUN0QytGLDBCQUFMOztTQUVJN0QsUUFBTCxDQUFjekgsTUFBTWpULElBQXBCLEVBQTBCLElBQTFCOzs7Ozs7Ozs7Ozs7OEJBU1U7T0FDUCxLQUFLa1ksb0NBQVQsRUFBK0M7U0FDekNrRixxQ0FBTCxDQUEyQzF0QixRQUFRQyxNQUFSLENBQWU2dUIsV0FBMUQsRUFBdUU5dUIsUUFBUUMsTUFBUixDQUFlOHVCLFdBQXRGOzs7Ozs7Ozs7Ozs7O21DQVVlM2MsT0FBTzs7O1FBQ2xCNGMsbUNBQUw7UUFDS3hHLG9DQUFMLEdBQTRDLEtBQTVDO2NBQ1d4b0IsUUFBUUUsUUFBUixDQUFpQnFILGVBQTVCLEVBQTZDLEtBQUtzaEIsZUFBbEQ7O09BRUlvRyxxQkFBcUI7VUFDbEI3YyxNQUFNeWIsSUFEWTtVQUVsQnpiLE1BQU05QjtJQUZiOztRQUtLMFksZUFBTCxHQUF1QixLQUFLa0csV0FBTCxDQUFpQjljLE1BQU05QixJQUF2QixFQUE2QjhCLE1BQU0wYixjQUFuQyxFQUNyQjFMLEtBRHFCLENBQ2YsVUFBQzFCLE1BQUQsRUFBWTt1QkFDQ2hQLEtBQW5CLEdBQTJCZ1AsTUFBM0I7VUFDTUEsTUFBTjtJQUhxQixFQUtyQm9CLFVBTHFCLENBS1YsWUFBTTtRQUNiLENBQUMsT0FBS2tILGVBQVYsRUFBMkI7bUJBQ1pocEIsUUFBUUUsUUFBUixDQUFpQnFILGVBQS9CLEVBQWdELE9BQUtzaEIsZUFBckQ7WUFDS3NHLG1DQUFMO1lBQ0szRyxvQ0FBTCxHQUE0QyxJQUE1Qzs7V0FFSW5TLElBQUwsQ0FBVSxhQUFWLEVBQXlCNFksa0JBQXpCO0lBWHFCLENBQXZCOztRQWNLakcsZUFBTCxDQUFxQjFZLElBQXJCLEdBQTRCOEIsTUFBTTlCLElBQWxDOzs7Ozs7Ozs7OzsyQkFRUUEsTUFBTTs7O09BQ1YrVSxRQUFRLEtBQUttRixTQUFMLENBQWVsYSxJQUFmLENBQVo7T0FDSSxDQUFDK1UsS0FBTCxFQUFZO1dBQ0p4RixtQkFBbUJrQixNQUFuQixDQUEwQixJQUFJbEIsbUJBQW1CMEMsaUJBQXZCLENBQXlDLGtCQUFrQmpTLElBQTNELENBQTFCLENBQVA7OztXQUdPb1csR0FBUixDQUFZLGtCQUFrQnBXLElBQWxCLEdBQXlCLEdBQXJDOztPQUVJK2EsYUFBYSxLQUFLQyxvQkFBTCxDQUEwQmhiLElBQTFCLEVBQWdDK1UsS0FBaEMsQ0FBakI7O1VBRU9nRyxXQUFXRSxJQUFYLENBQWdCamIsSUFBaEIsRUFDTDVNLElBREssQ0FDQTtXQUFNLFFBQUsybEIsT0FBTCxDQUFhL1ksSUFBYixJQUFxQithLFVBQTNCO0lBREEsRUFFTGpKLEtBRkssQ0FFQyxVQUFDMUIsTUFBRCxFQUFZO1lBQ2J3TCxvQkFBTCxDQUEwQjViLElBQTFCLEVBQWdDK2EsVUFBaEMsRUFBNEMzSyxNQUE1QztVQUNNQSxNQUFOO0lBSkssQ0FBUDs7Ozs7Ozs7Ozs7OzBDQWN1QnBRLE1BQU0rYSxZQUFZSCxvQkFBb0I7T0FDekR6RSxRQUFRNEUsV0FBVytELFFBQVgsRUFBWjtPQUNJLENBQUN6ckIsU0FBUzhpQixLQUFULENBQUwsRUFBc0I7WUFDYixLQUFLNEksZUFBTCxFQUFSOztPQUVHbEcsZUFBZWtDLFdBQVdpRSx1QkFBWCxDQUFtQ2hmLElBQW5DLENBQW5CO09BQ01pZixlQUFlO1VBQ2R6c0IsZ0JBQWdCOUMsUUFBUXNzQixtQkFBeEIsQ0FEYztjQUFBOzhCQUFBO2dCQUlSLENBSlE7ZUFLVCxDQUxTO1dBTWI7SUFOUjtPQVFJcEIsa0JBQUosRUFBd0I7aUJBQ1Y2QixTQUFiLEdBQXlCLEtBQUs3RCxpQkFBOUI7aUJBQ2E0RCxVQUFiLEdBQTBCLEtBQUs3RCxrQkFBL0I7O09BRUtqZSxPQUFPLElBQUlvRCxHQUFKLENBQVFrQyxJQUFSLEVBQWNKLE9BQWQsRUFBYjtrQkFDZSxLQUFLc2YsNkJBQUwsQ0FBbUNsZixJQUFuQyxFQUF5QzZZLFlBQXpDLEVBQXVEbmUsSUFBdkQsQ0FBZjtRQUNLeWtCLGNBQUwsQ0FBb0JoSixLQUFwQixFQUEyQjBDLFlBQTNCLEVBQXlDa0MsV0FBV3FFLHdCQUFYLENBQW9DSCxZQUFwQyxDQUF6QyxFQUE0RnJFLGtCQUE1RjtRQUNLL0IsWUFBTCxHQUFvQkEsWUFBcEI7Ozs7Ozs7Ozs7OzsyQ0FTd0JrQyxZQUFZMUUsVUFBVWdKLFFBQVE7VUFDL0M3bEIsSUFBUCxDQUFZNmMsUUFBWixFQUFzQjNZLE9BQXRCLENBQThCLFVBQUN4TCxFQUFELEVBQVE7UUFDakNvdEIsaUJBQWlCdkUsV0FBV3dFLGlCQUFYLENBQTZCcnRCLEVBQTdCLEVBQWlDbXRCLE1BQWpDLENBQXJCO2FBQ1NudEIsRUFBVCxFQUFhdWxCLFVBQWIsQ0FBd0JzRCxXQUFXbEIsS0FBWCxFQUF4QixFQUE0Q3lGLGNBQTVDO1lBQ1FsSixHQUFSLENBQVksYUFBYTJFLFdBQVdsQixLQUFYLEVBQWIsR0FBa0MsMkJBQWxDLEdBQ1gsR0FEVyxHQUNMeEQsU0FBU25rQixFQUFULENBREssR0FDVSxLQURWLElBQ21CTSxnQkFBZ0I4c0IsY0FBaEIsSUFBa0MsS0FBbEMsR0FBMEMsT0FEN0QsSUFDd0UsR0FEcEY7SUFIRDs7Ozs7Ozs7OytCQVdZO1dBQ0ozdkIsTUFBUixDQUFlZ0ksUUFBZixDQUF3QjZuQixNQUF4Qjs7Ozs7Ozs7Ozs7OEJBUVd6SyxPQUFPO1VBQ1hsaEIsTUFBTXlKLE1BQU4sQ0FBYSxLQUFLd2IsTUFBbEIsRUFBMEIvRCxLQUExQixDQUFQOzs7Ozs7Ozs7OytCQU9ZL1UsTUFBTTs7O09BQ2RvYSxTQUFTLEtBQUtyQixPQUFMLENBQWEvWSxJQUFiLENBQWI7T0FDSW9hLE1BQUosRUFBWTtXQUNKNWdCLElBQVAsQ0FBWSxLQUFLNmMsUUFBakIsRUFBMkIzWSxPQUEzQixDQUFtQyxVQUFDK2hCLFNBQUQ7WUFBZSxRQUFLcEosUUFBTCxDQUFjb0osU0FBZCxFQUF5Qm5pQixNQUF6QixDQUFnQzhjLE9BQU9QLEtBQVAsRUFBaEMsQ0FBZjtLQUFuQztXQUNPNkYsT0FBUDtXQUNPLEtBQUszRyxPQUFMLENBQWEvWSxJQUFiLENBQVA7Ozs7Ozs7Ozs7Ozt3REFTb0N5YyxXQUFXRCxZQUFZO09BQ3hEdkosUUFBUXZqQixRQUFRQyxNQUFSLENBQWVzUixPQUFmLENBQXVCZ1MsS0FBbkM7T0FDSUEsU0FBU0EsTUFBTXFMLEtBQW5CLEVBQTBCO2VBQ2EsQ0FBQzdCLFNBQUQsRUFBWUQsVUFBWixDQURiO1VBQ2xCQyxTQURrQjtVQUNERCxVQURDOztZQUVqQjdzQixNQUFSLENBQWVzUixPQUFmLENBQXVCMGUsWUFBdkIsQ0FBb0MxTSxLQUFwQyxFQUEyQyxJQUEzQyxFQUFpRCxJQUFqRDs7Ozs7Ozs7Ozs7MENBUXNCK0Usc0JBQXNCO1FBQ3hDQSxvQkFBTCxHQUE0QkEsb0JBQTVCOzs7Ozs7Ozs7OzhCQU9XbFksVUFBVTtRQUNoQkEsUUFBTCxHQUFnQk8sTUFBTXVmLHVCQUFOLENBQThCOWYsUUFBOUIsQ0FBaEI7Ozs7Ozs7Ozs7a0NBT2VxWSxjQUFjO1FBQ3hCQSxZQUFMLEdBQW9CQSxZQUFwQjs7Ozs7Ozs7OztrQ0FPZUMsY0FBYztRQUN4QkEsWUFBTCxHQUFvQkEsWUFBcEI7T0FDSSxLQUFLbUMsaUJBQVQsRUFBNEI7U0FDdEJBLGlCQUFMLENBQXVCcFksY0FBdkI7O1FBRUlvWSxpQkFBTCxHQUF5QmxSLFNBQVN6WixRQUFULEVBQW1CLFFBQW5CLEVBQTZCLEtBQUt3b0IsWUFBbEMsRUFBZ0QsS0FBS3lILG9CQUFMLENBQTBCMXBCLElBQTFCLENBQStCLElBQS9CLENBQWhELEVBQXNGLEtBQUs2aEIsb0JBQTNGLENBQXpCOzs7Ozs7Ozs7O29EQU9pQ0ssZ0NBQWdDO1FBQzVEQSw4QkFBTCxHQUFzQ0EsOEJBQXRDOzs7Ozs7Ozs7O2tDQU9lQyxjQUFjO1FBQ3hCQSxZQUFMLEdBQW9CQSxZQUFwQjtPQUNJLEtBQUtrQyxpQkFBVCxFQUE0QjtTQUN0QkEsaUJBQUwsQ0FBdUJyWSxjQUF2Qjs7UUFFSXFZLGlCQUFMLEdBQXlCblIsU0FBU3paLFFBQVQsRUFBbUIsT0FBbkIsRUFBNEIsS0FBSzBvQixZQUFqQyxFQUErQyxLQUFLd0gsbUJBQUwsQ0FBeUIzcEIsSUFBekIsQ0FBOEIsSUFBOUIsQ0FBL0MsRUFBb0YsS0FBSzZoQixvQkFBekYsQ0FBekI7Ozs7Ozs7Ozs7cUNBT2tCTyxpQkFBaUI7UUFDOUJBLGVBQUwsR0FBdUJBLGVBQXZCOzs7Ozs7Ozs7OzBDQU91QlUsc0JBQXNCO1FBQ3hDQSxvQkFBTCxHQUE0QkEsb0JBQTVCOzs7Ozs7Ozs7O3lDQU9zQjtPQUNsQixLQUFLUCxlQUFULEVBQTBCO1NBQ3BCQSxlQUFMLENBQXFCM0csTUFBckIsQ0FBNEIsMkJBQTVCO1NBQ0syRyxlQUFMLEdBQXVCLElBQXZCOzs7Ozs7Ozs7Ozs7OztxREFXaUM7OztPQUM5QnpGLFFBQVF2akIsUUFBUUMsTUFBUixDQUFlc1IsT0FBZixDQUF1QmdTLEtBQW5DO09BQ0ksQ0FBQ0EsS0FBTCxFQUFZOzs7O09BSVJ3SixZQUFZeEosTUFBTXdKLFNBQXRCO09BQ0lELGFBQWF2SixNQUFNdUosVUFBdkI7O09BRUl1RCxPQUFPLFNBQVBBLElBQU8sR0FBTTtRQUNaLFFBQUs5RyxvQkFBVCxFQUErQjthQUN0QnRwQixNQUFSLENBQWU0c0IsUUFBZixDQUF3QkMsVUFBeEIsRUFBb0NDLFNBQXBDOztJQUZGOztVQU1PLElBQUlsTixrQkFBSixDQUF1QixVQUFDZ0IsT0FBRDtXQUFhd1AsU0FBUzVxQixNQUFNRyxRQUFOLENBQWU7WUFBTXlxQixTQUFTeFAsU0FBZjtLQUFmLENBQXRCO0lBQXZCLENBQVA7Ozs7Ozs7Ozs7Ozs7O2lDQVdjNEYsT0FBT25XLE1BQU1pVCxPQUFPMkgsb0JBQW9CO09BQ2xEQSxrQkFBSixFQUF3QjtZQUNmanJCLE1BQVIsQ0FBZXNSLE9BQWYsQ0FBdUIwZSxZQUF2QixDQUFvQzFNLEtBQXBDLEVBQTJDa0QsS0FBM0MsRUFBa0RuVyxJQUFsRDtJQURELE1BRU87WUFDRXJRLE1BQVIsQ0FBZXNSLE9BQWYsQ0FBdUJDLFNBQXZCLENBQWlDK1IsS0FBakMsRUFBd0NrRCxLQUF4QyxFQUErQ25XLElBQS9DOzs7T0FHR2dnQixZQUFZdHdCLFFBQVFFLFFBQVIsQ0FBaUJzdUIsYUFBakIsQ0FBK0IsT0FBL0IsQ0FBaEI7T0FDSThCLFNBQUosRUFBZTtjQUNKalgsU0FBVixHQUFzQm9OLEtBQXRCO0lBREQsTUFFTztZQUNFdm1CLFFBQVIsQ0FBaUJ1bUIsS0FBakIsR0FBeUJBLEtBQXpCOzs7OztFQXZyQ2U3VDs7SUNSWjJkOzs7Ozs7Ozs7Ozs7Ozs7Ozs7dUNBV3VCQyxZQUFZO09BQ25DQyxVQUFVLEVBQWQ7T0FDSSxDQUFDRCxVQUFMLEVBQWlCO1dBQ1RDLE9BQVA7O09BRUdDLFFBQVFGLFdBQVc5bUIsS0FBWCxDQUFpQixNQUFqQixDQUFaO1FBQ0ssSUFBSW5GLElBQUksQ0FBYixFQUFnQkEsSUFBSW1zQixNQUFNcHNCLE1BQTFCLEVBQWtDQyxHQUFsQyxFQUF1QztRQUNsQytJLFFBQVFvakIsTUFBTW5zQixDQUFOLEVBQVM5QyxPQUFULENBQWlCLElBQWpCLENBQVo7UUFDSTZMLFFBQVEsQ0FBWixFQUFlO1NBQ1ZqTSxPQUFPcXZCLE1BQU1uc0IsQ0FBTixFQUFTL0MsU0FBVCxDQUFtQixDQUFuQixFQUFzQjhMLEtBQXRCLENBQVg7U0FDSW5DLFFBQVF1bEIsTUFBTW5zQixDQUFOLEVBQVMvQyxTQUFULENBQW1COEwsUUFBUSxDQUEzQixDQUFaO2FBQ1F4SSxJQUFSLENBQWE7WUFDTnpELElBRE07YUFFTDhKO01BRlI7OztVQU1Lc2xCLE9BQVA7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7MEJBZ0JjdmtCLEtBQUttaUIsUUFBUXNDLE1BQU1DLGFBQWFDLFlBQVlDLGFBQWFDLFVBQVVDLHFCQUFxQjtTQUNoRzlrQixPQUFPLEVBQWI7WUFDU21pQixVQUFVLEtBQW5COztPQUVJNEMsVUFBVSxJQUFJQyxjQUFKLEVBQWQ7T0FDSUMscUJBQXFCLENBQXpCOztPQUVJaFEsVUFBVSxJQUFJaVEsa0JBQUosQ0FBWSxVQUFTdlEsT0FBVCxFQUFrQkUsTUFBbEIsRUFBMEI7WUFDM0NzUSxNQUFSLEdBQWlCLFlBQVc7U0FDdkJKLFFBQVFLLE9BQVosRUFBcUI7Y0FDWkMsT0FBUjs7O2FBR09OLE9BQVI7S0FMRDtZQU9RcG9CLGtCQUFSLEdBQTZCLFlBQVc7U0FDbkNzb0Isc0JBQXNCQSxxQkFBcUIsQ0FBM0MsSUFBZ0QsTUFBTUYsUUFBUU8sVUFBbEUsRUFBOEU7Y0FDckVDLHFCQUFSLEdBQWdDLElBQWhDOzswQkFFb0JSLFFBQVFPLFVBQTdCO0tBSkQ7WUFNUUQsT0FBUixHQUFrQixZQUFXO1NBQ3hCeHBCLFVBQVUsZUFBZDtTQUNJa3BCLFFBQVFRLHFCQUFaLEVBQW1DO2dCQUN4QixnQ0FBVjs7U0FFRy9mLFFBQVEsSUFBSWpSLEtBQUosQ0FBVXNILE9BQVYsQ0FBWjtXQUNNa3BCLE9BQU4sR0FBZ0JBLE9BQWhCO1lBQ092ZixLQUFQO0tBUEQ7SUFkYSxFQXVCWHdRLFNBdkJXLENBdUJELFVBQVN4QixNQUFULEVBQWlCO1lBQ3JCZ1IsS0FBUjtVQUNNaFIsTUFBTjtJQXpCYSxFQTBCWG9CLFVBMUJXLENBMEJBLFlBQVc7aUJBQ1g2UCxPQUFiO0lBM0JhLENBQWQ7O1NBOEJNLElBQUl2akIsR0FBSixDQUFRbEMsR0FBUixDQUFOOztPQUVJMmtCLFVBQUosRUFBZ0I7UUFDWGUseUJBQUosQ0FBOEJmLFVBQTlCLEVBQTBDdHZCLFFBQTFDOzs7U0FHSzJLLElBQUkzSyxRQUFKLEVBQU47O1dBRVFxRyxJQUFSLENBQWF5bUIsTUFBYixFQUFxQm5pQixHQUFyQixFQUEwQixDQUFDNmtCLFFBQTNCOztPQUVJQyxtQkFBSixFQUF5QjtZQUNoQmEsZUFBUixHQUEwQixJQUExQjs7O09BR0dqQixXQUFKLEVBQWlCO2dCQUNKcGtCLEtBQVosR0FBb0J3QixPQUFwQixDQUE0QixVQUFTM00sSUFBVCxFQUFlO2FBQ2xDeXdCLGdCQUFSLENBQXlCendCLElBQXpCLEVBQStCdXZCLFlBQVlyaUIsTUFBWixDQUFtQmxOLElBQW5CLEVBQXlCbVAsSUFBekIsQ0FBOEIsSUFBOUIsQ0FBL0I7S0FERDs7O1dBS091aEIsSUFBUixDQUFhbHZCLE1BQU04dEIsSUFBTixJQUFjQSxJQUFkLEdBQXFCLElBQWxDOztPQUVJN3RCLGdCQUFnQmd1QixXQUFoQixDQUFKLEVBQWtDO1FBQzdCYSxVQUFVNU4sV0FBVyxZQUFXO2FBQzNCMUIsTUFBUixDQUFlLGlCQUFmO0tBRGEsRUFFWHlPLFdBRlcsQ0FBZDs7O1VBS00zUCxPQUFQOzs7Ozs7QUNqSEY7Ozs7O0lBSU02UTs7Ozs7Ozs7Ozs7QUFRTkEsT0FBT0MsY0FBUCxHQUF3QixxQkFBeEI7Ozs7Ozs7QUFPQUQsT0FBT0UsYUFBUCxHQUF1QixlQUF2Qjs7Ozs7OztBQU9BRixPQUFPRyxlQUFQLEdBQXlCLGlCQUF6Qjs7Ozs7OztBQU9BSCxPQUFPSSw2QkFBUCxHQUF1QyxnQ0FBdkM7O0FDakNBOzs7Ozs7OztJQU9NQzs7Ozs7Ozs7Ozs7Ozs7Ozt1Q0FTdUI7T0FDdkJDLFlBQVlELEdBQUdyeUIsT0FBSCxDQUFXQyxNQUFYLENBQWtCcXlCLFNBQWxDO09BQ0lBLFNBQUosRUFBZTtRQUNWQyxZQUFZRCxVQUFVQyxTQUExQjtRQUNJQSxTQUFKLEVBQWU7WUFDUEEsU0FBUDs7O1VBR0ssRUFBUDs7Ozs7Ozs7Ozs7Ozs7c0NBVzBCO09BQ3RCRCxZQUFZRCxHQUFHcnlCLE9BQUgsQ0FBV0MsTUFBWCxDQUFrQnF5QixTQUFsQztPQUNJQSxTQUFKLEVBQWU7UUFDVkUsV0FBV0YsVUFBVUUsUUFBekI7UUFDSUEsUUFBSixFQUFjO1lBQ05BLFFBQVA7OztVQUdLLEVBQVA7Ozs7Ozs7Ozs7Ozs7Z0NBVW9CbHhCLEtBQUs7VUFDbEIrd0IsR0FBR0csUUFBSCxDQUFZL3dCLE9BQVosQ0FBb0JILEdBQXBCLE1BQTZCLENBQUMsQ0FBckM7Ozs7Ozs7Ozs7Ozs7aUNBVXFCQSxLQUFLO1VBQ25CK3dCLEdBQUdFLFNBQUgsQ0FBYTl3QixPQUFiLENBQXFCSCxHQUFyQixNQUE4QixDQUFDLENBQXRDOzs7Ozs7Ozs7OztrQ0FRbUQ7T0FBL0JpeEIsU0FBK0IsdUVBQW5CLEVBQW1CO09BQWZDLFFBQWUsdUVBQUosRUFBSTs7Ozs7OztNQU1oREQsU0FBSCxHQUFlQSxTQUFmOzs7Ozs7O01BT0dDLFFBQUgsR0FBY0EsUUFBZDs7Ozs7OztNQU9HQyxLQUFILEdBQVdKLEdBQUdLLGFBQUgsQ0FBaUIsS0FBakIsQ0FBWDs7Ozs7OztNQU9HQyxLQUFILEdBQVdOLEdBQUdLLGFBQUgsQ0FBaUIsS0FBakIsQ0FBWDs7Ozs7OztNQU9HRSxPQUFILEdBQWFQLEdBQUdRLGNBQUgsQ0FBa0IsT0FBbEIsS0FBOEJSLEdBQUdRLGNBQUgsQ0FBa0IsS0FBbEIsQ0FBM0M7Ozs7Ozs7TUFPR0MsSUFBSCxHQUFVVCxHQUFHUSxjQUFILENBQWtCLFNBQWxCLEtBQWdDUixHQUFHUSxjQUFILENBQWtCLE1BQWxCLENBQTFDOzs7Ozs7O01BT0dFLE1BQUgsR0FBWVYsR0FBR1EsY0FBSCxDQUFrQixNQUFsQixDQUFaOzs7Ozs7O01BT0dHLFVBQUgsR0FBZ0JYLEdBQUdTLElBQUgsSUFBV1QsR0FBR1UsTUFBOUI7Ozs7Ozs7TUFPR0UsUUFBSCxHQUFjLENBQUNaLEdBQUdRLGNBQUgsQ0FBa0IsUUFBbEIsS0FBK0JSLEdBQUdRLGNBQUgsQ0FBa0IsT0FBbEIsQ0FBaEMsS0FBK0QsQ0FBQ1IsR0FBR08sT0FBbkUsSUFBOEUsQ0FBQ1AsR0FBR1UsTUFBaEc7Ozs7Ozs7TUFPR0csUUFBSCxHQUFjYixHQUFHUSxjQUFILENBQWtCLFFBQWxCLEtBQStCLEVBQUVSLEdBQUdZLFFBQUgsSUFBZVosR0FBR08sT0FBbEIsSUFBNkJQLEdBQUdVLE1BQWxDLENBQTdDOzs7Ozs7O01BT0dJLFNBQUgsR0FBZWQsR0FBR1EsY0FBSCxDQUFrQixTQUFsQixDQUFmOzs7Ozs7Ozs7Ozs7O0FBU0ZSLEdBQUdyeUIsT0FBSCxHQUFhO1NBQ0pDO0NBRFQ7O0FBSUFveUIsR0FBR2UsYUFBSCxDQUFpQmYsR0FBR2dCLGtCQUFILEVBQWpCLEVBQTBDaEIsR0FBR2lCLGlCQUFILEVBQTFDOztJQ3ZKTUM7Ozs7Ozs7OzswQkFRUzs7Ozs7Ozs7O1FBT1JuTixTQUFMLEdBQWlCLElBQWpCOzs7Ozs7Ozs7OztRQVdLb04sV0FBTCxHQUFtQjthQUNSLE1BRFE7dUJBRUU7R0FGckI7Ozs7Ozs7O1FBV0tDLFVBQUwsR0FBa0JGLGNBQWNHLEdBQWhDOzs7Ozs7OztRQVFLekMsT0FBTCxHQUFlLElBQWY7Ozs7Ozs7O1FBUUtVLE9BQUwsR0FBZSxLQUFmOzs7Ozs7Ozs7Ozs7O2dEQVE2QmdDLFFBQVE7T0FDakMsQ0FBQyxLQUFLQyx5QkFBTCxDQUErQkQsTUFBL0IsQ0FBTCxFQUE2QztRQUN4Q2ppQixRQUFRLElBQUlqUixLQUFKLENBQVV1eEIsT0FBT0MsY0FBakIsQ0FBWjtVQUNNNEIsYUFBTixHQUFzQixJQUF0QjtVQUNNQyxVQUFOLEdBQW1CSCxNQUFuQjtVQUNNamlCLEtBQU47Ozs7Ozs7Ozs7MENBT3NCcEIsTUFBTTtPQUN6QjZZLGVBQWUsS0FBSzRLLGNBQUwsRUFBbkI7T0FDSTVLLGdCQUFnQkEsaUJBQWlCN1ksSUFBckMsRUFBMkM7V0FDbkM2WSxZQUFQOztVQUVNN1ksSUFBUDs7Ozs7Ozs7OzJDQU13QmlULE9BQU87Ozs7T0FJM0JBLE1BQU1xTCxLQUFOLElBQWVyTCxNQUFNc0ssSUFBckIsSUFBNkJ0SyxNQUFNNEYsWUFBTixLQUF1QjVGLE1BQU1qVCxJQUE5RCxFQUFvRTtXQUM1RCxJQUFQOztVQUVNaVQsS0FBUDs7Ozs7Ozs7Ozs7O2lDQVNjalQsTUFBTTtPQUNoQmEsTUFBTSxJQUFJL0MsR0FBSixDQUFRa0MsSUFBUixDQUFWOztPQUVJMGpCLFdBQUosQ0FBZ0JoMEIsUUFBUUMsTUFBUixDQUFlZ0ksUUFBZixDQUF3QnlELFFBQXhDO09BQ0l1b0IsV0FBSixDQUFnQmowQixRQUFRQyxNQUFSLENBQWVnSSxRQUFmLENBQXdCQyxRQUF4Qzs7T0FFSWxJLFFBQVFDLE1BQVIsQ0FBZWdJLFFBQWYsQ0FBd0I0RCxJQUE1QixFQUFrQztRQUM3QnFvQixPQUFKLENBQVlsMEIsUUFBUUMsTUFBUixDQUFlZ0ksUUFBZixDQUF3QjRELElBQXBDOzs7T0FHR3dtQixHQUFHVyxVQUFILElBQWlCLEtBQUtTLFVBQUwsS0FBb0JGLGNBQWNHLEdBQXZELEVBQTREO1dBQ3BEdmlCLElBQUlnakIsVUFBSixHQUFpQjV5QixRQUFqQixFQUFQOzs7VUFHTTRQLElBQUk1UCxRQUFKLEVBQVA7Ozs7Ozs7Ozs7bUNBT2dCO1VBQ1QsS0FBS2l5QixXQUFaOzs7Ozs7Ozs7O2tDQU9lO1VBQ1IsS0FBS0MsVUFBWjs7Ozs7Ozs7OzttQ0FPZ0I7T0FDWnhDLFVBQVUsS0FBS21ELFVBQUwsRUFBZDtPQUNJbkQsT0FBSixFQUFhO1FBQ1JvRCxjQUFjcEQsUUFBUW9ELFdBQTFCO1FBQ0lDLGNBQWMsS0FBS0Msa0NBQUwsQ0FBd0N0RCxPQUF4QyxDQUFsQjtRQUNJcUQsV0FBSixFQUFpQjttQkFDRkEsV0FBZDs7UUFFR2pDLEdBQUdXLFVBQUgsSUFBaUIsS0FBS1MsVUFBTCxLQUFvQkYsY0FBY0csR0FBdkQsRUFBNEQ7bUJBQzdDLElBQUl0bEIsR0FBSixDQUFRaW1CLFdBQVIsRUFBcUJHLFlBQXJCLEdBQW9DanpCLFFBQXBDLEVBQWQ7O1dBRU1vUCxNQUFNVyxVQUFOLENBQWlCK2lCLFdBQWpCLENBQVA7O1VBRU0sSUFBUDs7Ozs7Ozs7OzsrQkFPWTtVQUNMLEtBQUtwRCxPQUFaOzs7Ozs7Ozs7OytCQU9ZO1VBQ0wsS0FBS1UsT0FBWjs7Ozs7Ozs7Ozs7NENBUXlCbUMsWUFBWTtVQUM5QkEsY0FBYyxHQUFkLElBQXFCQSxjQUFjLEdBQTFDOzs7Ozs7Ozs7dUJBTUl4akIsTUFBTTs7O09BQ0o2VixRQUFRLEtBQUtzTyxRQUFMLEVBQWQ7T0FDSTN4QixnQkFBZ0JxakIsS0FBaEIsQ0FBSixFQUE0QjtXQUNwQnRHLG1CQUFtQmdCLE9BQW5CLENBQTJCc0YsS0FBM0IsQ0FBUDs7T0FFR3dLLE9BQU8sSUFBWDtPQUNJOEMsYUFBYSxLQUFLQSxVQUF0QjtPQUNNaEQsVUFBVSxJQUFJcmtCLFFBQUosRUFBaEI7VUFDT3RDLElBQVAsQ0FBWSxLQUFLMHBCLFdBQWpCLEVBQThCeGxCLE9BQTlCLENBQXNDO1dBQVV5aUIsUUFBUTloQixHQUFSLENBQVkrbEIsTUFBWixFQUFvQixPQUFLbEIsV0FBTCxDQUFpQmtCLE1BQWpCLENBQXBCLENBQVY7SUFBdEM7T0FDSTEwQixRQUFRc3NCLG1CQUFaLEVBQWlDO1dBQ3pCLElBQUlxSSxRQUFKLENBQWEzMEIsUUFBUXNzQixtQkFBckIsQ0FBUDtTQUNLc0ksNkJBQUwsQ0FBbUNqRSxJQUFuQztpQkFDYTRDLGNBQWNzQixJQUEzQjtRQUNJeEMsR0FBR1csVUFBUCxFQUFtQjthQUNWcmtCLEdBQVIsQ0FBWSxlQUFaLEVBQTZCLEtBQTdCOzs7T0FHSTBsQixjQUFjLEtBQUtTLGNBQUwsQ0FBb0J4a0IsSUFBcEIsQ0FBcEI7VUFDT2lnQixLQUNMVSxPQURLLENBQ0dvRCxXQURILEVBQ2dCWixVQURoQixFQUM0QjlDLElBRDVCLEVBQ2tDRixPQURsQyxFQUMyQyxJQUQzQyxFQUNpRCxLQUFLa0IsT0FEdEQsRUFFTGp1QixJQUZLLENBRUEsZUFBTztXQUNQcXhCLFVBQUwsQ0FBZ0JDLEdBQWhCO1dBQ0tDLDZCQUFMLENBQW1DRCxJQUFJckIsTUFBdkM7UUFDSUYsZUFBZUYsY0FBY0csR0FBN0IsSUFBb0MsT0FBS3JILFdBQUwsRUFBeEMsRUFBNEQ7WUFDdEQ2SSxRQUFMLENBQWNGLElBQUlHLFlBQWxCOztRQUVHZCxXQUFKLEdBQWtCQSxXQUFsQjtXQUNPVyxJQUFJRyxZQUFYO0lBVEssRUFXTC9TLEtBWEssQ0FXQyxVQUFDMUIsTUFBRCxFQUFZO1lBQ1ZBLE9BQU8zWSxPQUFmO1VBQ01pcUIsT0FBT0csZUFBWjthQUNRUixPQUFQLEdBQWlCLElBQWpCOztVQUVJSyxPQUFPRSxhQUFaO2FBQ1FrRCxZQUFQLEdBQXNCLElBQXRCOztVQUVJcEQsT0FBT0ksNkJBQVo7YUFDUWdELFlBQVAsR0FBc0IsSUFBdEI7YUFDT0MsMkJBQVAsR0FBcUMsSUFBckM7OztVQUdJM1UsTUFBTjtJQXhCSyxDQUFQOzs7Ozs7Ozs7Ozs7Z0RBa0M2QmlRLE1BQU07T0FDN0J6VyxTQUFTbGEsUUFBUXVzQix5QkFBdkI7T0FDSXJTLFVBQVVBLE9BQU83WSxJQUFyQixFQUEyQjtTQUNyQjBYLE1BQUwsQ0FBWW1CLE9BQU83WSxJQUFuQixFQUF5QjZZLE9BQU8vTyxLQUFoQzs7Ozs7Ozs7Ozs7Ozs7Ozs7O3FEQWVpQzhsQixTQUFTO09BQ3ZDcUQsY0FBY3JELFFBQVFxRSxXQUExQjtPQUNJaEIsV0FBSixFQUFpQjtXQUNUQSxXQUFQOztVQUVNckQsUUFBUXNFLGlCQUFSLENBQTBCaEMsY0FBY2lDLG9CQUF4QyxDQUFQOzs7Ozs7Ozs7O2lDQU9jaEMsYUFBYTtRQUN0QkEsV0FBTCxHQUFtQkEsV0FBbkI7Ozs7Ozs7Ozs7Z0NBT2FDLFlBQVk7UUFDcEJBLFVBQUwsR0FBa0JBLFdBQVdqcEIsV0FBWCxFQUFsQjs7Ozs7Ozs7Ozs2QkFPVXltQixTQUFTO1FBQ2RBLE9BQUwsR0FBZUEsT0FBZjs7Ozs7Ozs7Ozs2QkFPVVUsU0FBUztRQUNkQSxPQUFMLEdBQWVBLE9BQWY7Ozs7RUFoUzBCcEw7Ozs7Ozs7Ozs7QUEyUzVCZ04sY0FBY0csR0FBZCxHQUFvQixLQUFwQjs7Ozs7Ozs7QUFRQUgsY0FBY3NCLElBQWQsR0FBcUIsTUFBckI7Ozs7Ozs7O0FBUUF0QixjQUFjaUMsb0JBQWQsR0FBcUMsZUFBckM7O0lDNVRNQzs7Ozs7Ozs7O3VCQVFTOzs7Ozs7Ozs7Ozs7UUFVUkMsYUFBTCxHQUFxQixPQUFyQjs7Ozs7Ozs7Ozs7NkJBTVU7O1FBRUxDLHNCQUFMO1FBQ0tDLGFBQUwsR0FBcUIsSUFBckI7Ozs7Ozs7Ozs7O29EQVFpQ3pjLFlBQVk7T0FDekMsQ0FBQyxLQUFLMGMsZUFBVixFQUEyQjtTQUNyQkEsZUFBTCxHQUF1QjcxQixRQUFRRSxRQUFSLENBQWlCaUgsYUFBakIsQ0FBK0IsTUFBL0IsQ0FBdkI7OztRQUdJMnVCLDhCQUFMLENBQW9DM2MsVUFBcEMsRUFBZ0QsS0FBSzBjLGVBQXJEOztRQUVLQSxlQUFMLENBQXFCeGMsU0FBckIsR0FBaUNGLFVBQWpDOzs7Ozs7Ozs7Ozs7MkNBU3dCNGMsVUFBVTtPQUM5QkMsbUJBQW1CbGQsTUFBTWlkLFFBQU4sRUFBZ0JOLFdBQVd0ZSxTQUFYLENBQXFCOGUsZUFBckMsQ0FBdkI7T0FDSUQsZ0JBQUosRUFBc0I7U0FDaEJKLGFBQUwsQ0FBbUI5d0IsSUFBbkIsQ0FBd0JpeEIsUUFBeEI7O09BRUdBLFNBQVN2ekIsRUFBYixFQUFpQjtRQUNaMHpCLGFBQWFsMkIsUUFBUUUsUUFBUixDQUFpQjRuQixjQUFqQixDQUFnQ2lPLFNBQVN2ekIsRUFBekMsQ0FBakI7UUFDSTB6QixVQUFKLEVBQWdCO2dCQUNKcHRCLFVBQVgsQ0FBc0JxdEIsWUFBdEIsQ0FBbUNKLFFBQW5DLEVBQTZDRyxXQUFXRSxXQUF4RDs7OztXQUlNbDJCLFFBQVIsQ0FBaUJ1SSxJQUFqQixDQUFzQmpCLFdBQXRCLENBQWtDdXVCLFFBQWxDOzs7Ozs7Ozs7O3NEQU9tQztPQUMvQk0sY0FBYyxLQUFLUixlQUFMLENBQXFCckgsYUFBckIsQ0FBbUMsTUFBbkMsQ0FBbEI7T0FDSSxDQUFDeHVCLFFBQVFFLFFBQVIsQ0FBaUJ5d0IsSUFBakIsQ0FBc0JudUIsRUFBM0IsRUFBK0I7WUFDdEJ0QyxRQUFSLENBQWlCeXdCLElBQWpCLENBQXNCbnVCLEVBQXRCLEdBQTJCLG1CQUFtQkgsUUFBOUM7O09BRUdnMEIsV0FBSixFQUFpQjtnQkFDSjd6QixFQUFaLEdBQWlCeEMsUUFBUUUsUUFBUixDQUFpQnl3QixJQUFqQixDQUFzQm51QixFQUF2Qzs7Ozs7Ozs7OztpREFPNkI2akIsU0FBU25aLE1BQU07YUFDbkNtWixRQUFRM2IsT0FBUixDQUFnQixjQUFoQixFQUFnQyxRQUFoQyxDQUFWO2FBQ1UyYixRQUFRM2IsT0FBUixDQUFnQixlQUFoQixFQUFpQyxTQUFqQyxDQUFWO1FBQ0syTyxTQUFMLEdBQWlCZ04sT0FBakI7T0FDSWlRLGNBQWNwcEIsS0FBS3NoQixhQUFMLENBQW1CLE9BQW5CLENBQWxCO09BQ0k4SCxXQUFKLEVBQWlCO1VBQ1ZDLG1CQUFOLENBQTBCcnBCLElBQTFCO1VBQ01zcEIsa0JBQU4sQ0FBeUJGLFdBQXpCLEVBQXNDcHBCLElBQXRDOzs7Ozs7Ozs7O29DQU9nQjtRQUNadXBCLG9CQUFMOzs7Ozs7Ozs7O3lDQU9zQjtPQUNsQixLQUFLYixhQUFULEVBQXdCO1NBQ2xCQSxhQUFMLENBQW1CNW5CLE9BQW5CLENBQTJCLFVBQUM1RyxLQUFEO1lBQVdrVCxhQUFhbFQsS0FBYixDQUFYO0tBQTNCOzs7Ozs7Ozs7O2tDQU9jdWYsVUFBVTs7O09BQ3JCK1AseUJBQXlCLEtBQUtDLHlCQUFMLENBQzVCMVksV0FBVzZJLG1CQURpQixFQUNJMk8sV0FBV3RlLFNBQVgsQ0FBcUJtSCxPQUR6QixFQUU1Qm1YLFdBQVd0ZSxTQUFYLENBQXFCeWYsZ0JBRk8sRUFFV25CLFdBQVd0ZSxTQUFYLENBQXFCMGYsZ0JBRmhDLENBQTdCOztVQUlPSCx1QkFBdUJoekIsSUFBdkIsQ0FBNEI7c0lBQTRCaWpCLFFBQTVCO0lBQTVCLENBQVA7Ozs7Ozs7OztpQ0FNY0EsVUFBVTs7O1FBQ25CaVAsYUFBTCxHQUFxQixFQUFyQjtPQUNJa0Isd0JBQXdCLEtBQUtILHlCQUFMLENBQzNCalksaUJBQWlCcVksa0JBRFUsRUFDVXRCLFdBQVd0ZSxTQUFYLENBQXFCMEgsTUFEL0IsRUFFM0I0VyxXQUFXdGUsU0FBWCxDQUFxQjhlLGVBRk0sRUFFV1IsV0FBV3RlLFNBQVgsQ0FBcUI2ZixlQUZoQyxFQUczQixLQUFLQyx3QkFBTCxDQUE4Qnh3QixJQUE5QixDQUFtQyxJQUFuQyxDQUgyQixDQUE1Qjs7VUFLT3F3QixzQkFBc0JwekIsSUFBdEIsQ0FBMkI7cUlBQTJCaWpCLFFBQTNCO0lBQTNCLENBQVA7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs0Q0FrQnlCdVEsYUFBYWhnQixVQUFVaWdCLG1CQUFtQkMsbUJBQW1CQyxzQkFBc0I7OztPQUN4R0MsVUFBVSxLQUFLQyx3QkFBTCxDQUE4QnJnQixRQUE5QixDQUFkO09BQ0lzZ0IsbUJBQW1CLEtBQUtDLGlCQUFMLENBQXVCTixpQkFBdkIsQ0FBdkI7T0FDSU8sa0JBQWtCLEtBQUtELGlCQUFMLENBQXVCTCxpQkFBdkIsQ0FBdEI7OzttQkFHZ0JwcEIsT0FBaEIsQ0FBd0IsVUFBQzJwQixRQUFELEVBQWM7UUFDakNDLGNBQWMsT0FBS0MsZUFBTCxDQUFxQkYsUUFBckIsQ0FBbEI7UUFDSUMsV0FBSixFQUFpQjtnQkFDTEUsdUJBQVgsQ0FBbUNGLFdBQW5DLElBQWtELElBQWxEOztJQUhGOztPQU9JRyxPQUFPL2UsZUFBWDtXQUNRaEwsT0FBUixDQUFnQixVQUFDMnBCLFFBQUQsRUFBYztRQUN6QkMsY0FBYyxPQUFLQyxlQUFMLENBQXFCRixRQUFyQixDQUFsQjs7UUFFSSxDQUFDbEMsV0FBV3FDLHVCQUFYLENBQW1DRixXQUFuQyxDQUFMLEVBQXNEO1VBQ2hEcHdCLFdBQUwsQ0FBaUJtd0IsUUFBakI7OztRQUdHQyxlQUFlOWUsTUFBTTZlLFFBQU4sRUFBZ0JQLGlCQUFoQixDQUFuQixFQUF1RDtnQkFDM0NVLHVCQUFYLENBQW1DRixXQUFuQyxJQUFrRCxJQUFsRDs7SUFSRjs7VUFZTyxJQUFJL1gsa0JBQUosQ0FBdUIsVUFBQ2dCLE9BQUQsRUFBYTtnQkFDOUJrWCxJQUFaLEVBQWtCLFlBQU07c0JBQ04vcEIsT0FBakIsQ0FBeUIsVUFBQzJwQixRQUFEO2FBQWNyZCxhQUFhcWQsUUFBYixDQUFkO01BQXpCOztLQURELEVBR0dOLG9CQUhIO0lBRE0sQ0FBUDs7Ozs7Ozs7O3VCQVdJMVEsVUFBVTs7O1VBQ1B2Siw0R0FBV3VKLFFBQVgsRUFBcUJqakIsSUFBckIsQ0FBMEIsWUFBTTtVQUNoQzZ5QixtQkFBTixDQUEwQnIyQixTQUFTcUgsZUFBbkM7VUFDTWl2QixrQkFBTixDQUF5QixPQUFLWCxlQUE5QixFQUErQzMxQixTQUFTcUgsZUFBeEQ7SUFGTSxDQUFQOzs7Ozs7Ozs7Ozs7a0NBWWVvd0IsVUFBVTtVQUNsQkEsU0FBU24xQixFQUFULElBQWVtMUIsU0FBU3BzQixJQUF4QixJQUFnQ29zQixTQUFTcndCLEdBQXpDLElBQWdELEVBQXZEOzs7Ozs7Ozs7b0NBTWlCeW9CLFdBQVc7T0FDeEIvSSxVQUFVLEtBQUs2TyxlQUFMLENBQXFCckgsYUFBckIsQ0FBbUMsTUFBTXVCLFNBQXpDLENBQWQ7T0FDSS9JLE9BQUosRUFBYTtRQUNSSSxlQUFlSixRQUFRd0gsYUFBUixDQUFzQixNQUFNdUIsU0FBTixHQUFrQixHQUFsQixHQUF3QjVJLFFBQVFJLE9BQXRELENBQW5CO1FBQ0lILFlBQUosRUFBa0I7WUFDVkEsYUFBYS9OLFNBQXBCOztXQUVNMk4sUUFBUTNOLFNBQWYsQ0FMWTs7Ozs7Ozs7Ozs7cUNBYUs7VUFDWCxLQUFLcWMsYUFBWjs7Ozs7Ozs7O3VCQU1JcGxCLE1BQU07OztVQUNIOE0sNEdBQVc5TSxJQUFYLEVBQ0w1TSxJQURLLENBQ0EsbUJBQVc7V0FDWHMwQixpQ0FBTCxDQUF1QzNSLE9BQXZDO1dBQ0s0UiwrQkFBTDtXQUNLQyxpQ0FBTDtRQUNJN0YsR0FBR1MsSUFBUCxFQUFhO1lBQ1BxRiwrQkFBTDs7V0FFTTlSLE9BQVA7SUFSSyxDQUFQOzs7Ozs7Ozs7OztvREFpQmlDOzs7T0FDN0JtUixtQkFBbUIsS0FBS0Qsd0JBQUwsQ0FBOEI5QixXQUFXdGUsU0FBWCxDQUFxQjhlLGVBQW5ELENBQXZCO29CQUNpQmpvQixPQUFqQixDQUF5QixVQUFDNUcsS0FBRDtXQUFXLE9BQUtneEIsMEJBQUwsQ0FBZ0NoeEIsS0FBaEMsQ0FBWDtJQUF6Qjs7Ozs7Ozs7Ozs2Q0FPMEJBLE9BQU87T0FDN0JBLE1BQU1tRSxJQUFWLEVBQWdCO1FBQ1h3cUIsV0FBVy8xQixRQUFRRSxRQUFSLENBQWlCaUgsYUFBakIsQ0FBK0JDLE1BQU1nVCxPQUFyQyxDQUFmO1VBQ003TyxJQUFOLEdBQWEsSUFBSTZDLEdBQUosQ0FBUWhILE1BQU1tRSxJQUFkLEVBQW9CNG9CLFVBQXBCLEdBQWlDNXlCLFFBQWpDLEVBQWI7VUFDTWkxQixrQkFBTixDQUF5QnB2QixLQUF6QixFQUFnQzJ1QixRQUFoQztVQUNNanRCLFVBQU4sQ0FBaUJ1dkIsWUFBakIsQ0FBOEJ0QyxRQUE5QixFQUF3QzN1QixLQUF4QztVQUNNaVQsUUFBTixHQUFpQixJQUFqQjs7Ozs7Ozs7Ozs7OzJDQVN1Qm5ELFVBQVU7VUFDM0J2UyxNQUFNTyxTQUFOLENBQWdCc0ssS0FBaEIsQ0FBc0JwSyxJQUF0QixDQUEyQixLQUFLeXdCLGVBQUwsQ0FBcUJyYSxnQkFBckIsQ0FBc0N0RSxRQUF0QyxDQUEzQixDQUFQOzs7Ozs7Ozs7OztvQ0FRaUJBLFVBQVU7VUFDcEJ2UyxNQUFNTyxTQUFOLENBQWdCc0ssS0FBaEIsQ0FBc0JwSyxJQUF0QixDQUEyQnBGLFFBQVFFLFFBQVIsQ0FBaUJzYixnQkFBakIsQ0FBa0N0RSxRQUFsQyxDQUEzQixDQUFQOzs7Ozs7Ozs7MkNBTXdCO1FBQ25CMmUsZUFBTCxHQUF1QixJQUF2Qjs7Ozs7Ozs7O29EQU1pQztPQUM3QnBQLFFBQVEsS0FBS29QLGVBQUwsQ0FBcUJySCxhQUFyQixDQUFtQyxLQUFLa0gsYUFBeEMsQ0FBWjtPQUNJalAsS0FBSixFQUFXO1NBQ0w2UixRQUFMLENBQWM3UixNQUFNOFIsV0FBTixDQUFrQmxjLElBQWxCLEVBQWQ7Ozs7Ozs7Ozs7O21DQVFlcVosZUFBZTtRQUMxQkEsYUFBTCxHQUFxQkEsYUFBckI7Ozs7RUFsVHVCbkM7Ozs7Ozs7Ozs7QUE2VHpCa0MsV0FBV3RlLFNBQVgsR0FBdUI7VUFDYiwwQkFEYTttQkFFSixzQ0FGSTttQkFHSixzQ0FISTtTQUlkLGdEQUpjO2tCQUtMLHdFQUxLO2tCQU1MO0NBTmxCOzs7Ozs7OztBQWVBc2UsV0FBV3FDLHVCQUFYLEdBQXFDLEVBQXJDOztJQy9VTVU7Ozs7Ozs7b0NBTVM7Ozs7Ozs7Ozs7UUFRUkMsR0FBTCxHQUFXLElBQVg7Ozs7Ozs7OztRQVNLQyxXQUFMLEdBQW1CLElBQW5COzs7Ozs7Ozs7OzsyQkFNUTtPQUNKLENBQUN2MUIsVUFBVSxLQUFLdTFCLFdBQWYsQ0FBTCxFQUFrQztVQUMzQixJQUFJajRCLEtBQUosQ0FBVSwrQ0FDZix1REFEZSxHQUVmLG9DQUZLLENBQU47OztPQUtHLENBQUMsS0FBS2k0QixXQUFMLENBQWlCQyxZQUFqQixDQUE4QkMsZUFBZWhLLEtBQTdDLENBQUwsRUFBMEQ7WUFDakRsSSxHQUFSLENBQVkscURBQ1gsZ0VBRFcsR0FFWCxnREFGRDs7OztPQU1HLEtBQUsrUixHQUFULEVBQWM7VUFDUCxJQUFJaDRCLEtBQUosQ0FBVSxvQ0FBVixDQUFOOzs7V0FHT2ltQixHQUFSLENBQVksd0NBQVo7O1FBRUsrUixHQUFMLEdBQVcsSUFBSXRRLEtBQUosRUFBWDtRQUNLMFEsZUFBTDtRQUNLQyxpQkFBTDtRQUNLQyxpQkFBTDtRQUNLQyxxQkFBTDtRQUNLQyx3QkFBTDtRQUNLQyw2QkFBTDtRQUNLQyxjQUFMOzs7Ozs7Ozs7O29DQU9pQjtPQUNiLEtBQUtWLEdBQVQsRUFBYztTQUNSQSxHQUFMLENBQVN6SSxPQUFUOzs7Ozs7Ozs7OzsyQkFRTztVQUNELEtBQUt5SSxHQUFaOzs7Ozs7Ozs7O21DQU9nQjtVQUNULEtBQUtDLFdBQVo7Ozs7Ozs7OztvQ0FNaUI7OztPQUNiVSxpQkFBaUIseUJBQXJCO1FBQ0tDLHdCQUFMLENBQThCRCxjQUE5QixFQUE4Q3ByQixPQUE5QyxDQUFzRCxVQUFDMUMsSUFBRDtXQUFVLE9BQUtndUIsb0JBQUwsQ0FBMEJodUIsSUFBMUIsQ0FBVjtJQUF0RDtPQUNJLENBQUMsS0FBS210QixHQUFMLENBQVNjLFNBQVQsRUFBTCxFQUEyQjtTQUNyQmQsR0FBTCxDQUFTZSxTQUFULENBQW1CLElBQUl6VCxLQUFKLENBQVUsSUFBVixFQUFnQjBQLFVBQWhCLENBQW5CO1lBQ1EvTyxHQUFSLENBQVksbURBQVo7Ozs7Ozs7Ozs7c0NBT2tCOzs7T0FDZitTLG1CQUFtQixNQUFNYixlQUFlNVIsT0FBckIsR0FBK0IsR0FBdEQ7UUFDS3FTLHdCQUFMLENBQThCSSxnQkFBOUIsRUFBZ0R6ckIsT0FBaEQsQ0FBd0QsVUFBQzByQixjQUFELEVBQW9CO1dBQ3RFQyxnQ0FBTCxDQUFzQ0QsY0FBdEM7V0FDS2pCLEdBQUwsQ0FBU21CLFdBQVQsQ0FBcUJGLGVBQWVsM0IsRUFBcEM7SUFGRDs7Ozs7Ozs7O21DQVNnQjtPQUNaLEtBQUtrMkIsV0FBTCxDQUFpQkMsWUFBakIsQ0FBOEJDLGVBQWVpQixRQUE3QyxDQUFKLEVBQTREO1NBQ3REcEIsR0FBTCxDQUFTb0IsUUFBVDs7Ozs7Ozs7Ozs7O3VDQVNtQnZ1QixNQUFNO09BQ3RCK1osUUFBUSxJQUFJVSxLQUFKLENBQVUsS0FBSytULHdCQUFMLENBQThCeHVCLElBQTlCLENBQVYsRUFBK0MsS0FBS3l1QiwyQkFBTCxDQUFpQ3p1QixJQUFqQyxDQUEvQyxDQUFaO1FBQ0ttdEIsR0FBTCxDQUFTZSxTQUFULENBQW1CblUsS0FBbkI7V0FDUXFCLEdBQVIsQ0FBWSx5QkFBeUJyQixNQUFNMlUsT0FBTixFQUFyQzs7Ozs7Ozs7Ozs7OENBUTJCMXVCLE1BQU07T0FDN0IySCxVQUFVM0gsS0FBSzJ1QixZQUFMLENBQWtCLE1BQWxCLENBQWQ7T0FDSW4zQixnQkFBZ0JtUSxPQUFoQixDQUFKLEVBQThCO2NBQ25COUosT0FBTyt3QixlQUFQLENBQXVCam5CLE9BQXZCLENBQVY7O1VBRU1BLE9BQVA7Ozs7Ozs7Ozs7OzJDQVF3QjNILE1BQU07T0FDMUJnRixPQUFPaEYsS0FBSzJ1QixZQUFMLENBQWtCLE1BQWxCLENBQVg7T0FDSW4zQixnQkFBZ0J3TixJQUFoQixDQUFKLEVBQTJCO1FBQ3RCQSxLQUFLN08sT0FBTCxDQUFhLFFBQWIsTUFBMkIsQ0FBL0IsRUFBa0M7WUFDMUIsSUFBSXlqQixNQUFKLENBQVc1VSxLQUFLOU8sU0FBTCxDQUFlLENBQWYsQ0FBWCxDQUFQOzs7VUFHSzhPLElBQVA7Ozs7Ozs7OztzQ0FNbUI7T0FDZkYsV0FBVyxLQUFLc29CLFdBQUwsQ0FBaUJ1QixZQUFqQixDQUE4QnJCLGVBQWV4b0IsUUFBN0MsQ0FBZjtPQUNJdE4sZ0JBQWdCc04sUUFBaEIsQ0FBSixFQUErQjtTQUN6QnFvQixHQUFMLENBQVMwQixXQUFULENBQXFCL3BCLFFBQXJCO1lBQ1FzVyxHQUFSLENBQVksNkJBQTZCdFcsUUFBekM7Ozs7Ozs7Ozs7OzBDQVFzQjtPQUNuQndZLGVBQWUsS0FBSzhQLFdBQUwsQ0FBaUJ1QixZQUFqQixDQUE4QnJCLGVBQWVoUSxZQUE3QyxDQUFuQjtPQUNJOWxCLGdCQUFnQjhsQixZQUFoQixDQUFKLEVBQW1DO1NBQzdCNlAsR0FBTCxDQUFTek8sZUFBVCxDQUF5QnBCLFlBQXpCO1lBQ1FsQyxHQUFSLENBQVksaUNBQWlDa0MsWUFBN0M7Ozs7Ozs7Ozs7OzZDQVF5QjtPQUN0QkMsa0JBQWtCLEtBQUs2UCxXQUFMLENBQWlCdUIsWUFBakIsQ0FBOEJyQixlQUFlL1AsZUFBN0MsQ0FBdEI7T0FDSS9sQixnQkFBZ0IrbEIsZUFBaEIsQ0FBSixFQUFzQztTQUNoQzRQLEdBQUwsQ0FBUzJCLGtCQUFULENBQTRCdlIsZUFBNUI7WUFDUW5DLEdBQVIsQ0FBWSxxQ0FBcUNtQyxlQUFqRDs7Ozs7Ozs7Ozs7a0RBUThCO09BQzNCVSx1QkFBdUIsS0FBS21QLFdBQUwsQ0FBaUJ1QixZQUFqQixDQUE4QnJCLGVBQWVyUCxvQkFBN0MsQ0FBM0I7T0FDSXptQixnQkFBZ0J5bUIsb0JBQWhCLENBQUosRUFBMkM7UUFDdENBLHlCQUF5QixPQUE3QixFQUFzQztVQUNoQ2tQLEdBQUwsQ0FBUzRCLHVCQUFULENBQWlDLEtBQWpDO0tBREQsTUFFTztVQUNENUIsR0FBTCxDQUFTNEIsdUJBQVQsQ0FBaUMsSUFBakM7O1lBRU8zVCxHQUFSLENBQVksMENBQTBDNkMsb0JBQXREOzs7Ozs7Ozs7Ozs7MkNBU3VCclMsVUFBVTtVQUMzQnZTLE1BQU1PLFNBQU4sQ0FBZ0JzSyxLQUFoQixDQUFzQnBLLElBQXRCLENBQTJCcEYsUUFBUUUsUUFBUixDQUFpQnNiLGdCQUFqQixDQUFrQ3RFLFFBQWxDLENBQTNCLENBQVA7Ozs7Ozs7Ozs7OzttREFTZ0NuRixTQUFTO09BQ3JDLENBQUNBLFFBQVF2UCxFQUFULElBQWV1UCxZQUFZL1IsUUFBUUUsUUFBUixDQUFpQnl3QixJQUFoRCxFQUFzRDtZQUM3Q251QixFQUFSLEdBQWEsbUJBQW1CSCxRQUFoQzs7Ozs7Ozs7Ozs7aUNBUWFxMkIsYUFBYTtRQUN0QkEsV0FBTCxHQUFtQkEsV0FBbkI7Ozs7RUF6T29DMXZCOztBQ0p0Qzs7OztBQUlBLElBQUlzeEIsdUJBQXVCLElBQUk5Qix1QkFBSixFQUEzQjs7QUFFQXg0QixRQUFRRSxRQUFSLENBQWlCK0csZ0JBQWpCLENBQWtDLGtCQUFsQyxFQUFzRCxZQUFXO3VCQUMzQ3N6QixjQUFyQixDQUFvQ3Y2QixRQUFRRSxRQUFSLENBQWlCeXdCLElBQXJEO3VCQUNxQjZKLE1BQXJCO0NBRkQ7O0FDWEE7OztBQUdBLGNBQWUsZ0JBQWY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OyJ9"} \ No newline at end of file diff --git a/examples/amd/index.html b/examples/amd/index.html index 7e791fd..7e512ca 100644 --- a/examples/amd/index.html +++ b/examples/amd/index.html @@ -31,6 +31,7 @@ }); requirejs(['senna/src/senna'], function(senna) { + console.log('Senna version:', senna.version); var app = new senna.App(); app.setBasePath('/examples/amd'); app.addSurfaces(['header', 'content', 'footer', 'indexOnlySurface']); diff --git a/examples/blog/js/spa.js b/examples/blog/js/spa.js index f9d73ef..f446d39 100644 --- a/examples/blog/js/spa.js +++ b/examples/blog/js/spa.js @@ -6,6 +6,8 @@ document.addEventListener('DOMContentLoaded', function() { Creates a new Senna app ========================================================================== */ + console.log('Senna version:', senna.version); + var app = new senna.App(); app.setBasePath('/examples/blog'); app.addSurfaces('posts'); diff --git a/gulpfile.js b/gulpfile.js index ce9ca9f..f378609 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -6,9 +6,11 @@ var gulp = require('gulp'); var header = require('gulp-header'); var jsdoc = require('gulp-jsdoc3'); var metal = require('gulp-metal'); +var pkg = require('./package.json'); var rename = require('gulp-rename'); var runSequence = require('run-sequence'); var stripDebug = require('gulp-strip-debug'); +var template = require('gulp-template'); // Metal ----------------------------------------------------------------------- @@ -161,10 +163,18 @@ gulp.task('docs', function() { })); }); +gulp.task('version', function() { + return gulp.src('build/**/*.js') + .pipe(template({ + version: pkg.version + })) + .pipe(gulp.dest('build')); +}); + // Runner ---------------------------------------------------------------------- gulp.task('default', function(done) { - runSequence('clean', 'css', 'build:globals', 'uglify', 'build:amd', 'banner', 'clean:debug', 'clean:debug:globals', 'clean:debug:amd', done); + runSequence('clean', 'css', 'build:globals', 'uglify', 'build:amd', 'banner', 'clean:debug', 'clean:debug:globals', 'clean:debug:amd', 'version', done); }); gulp.task('server', ['default'], function() { diff --git a/package.json b/package.json index c5eb0d5..3c31c04 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "gulp-metal": "^1.0.0", "gulp-rename": "^1.2.2", "gulp-strip-debug": "^1.1.0", + "gulp-template": "^4.0.0", "metal-tools-build-rollup": "^2.0.6", "run-sequence": "^1.1.5", "sinon": "1.17.7" diff --git a/src/senna.js b/src/senna.js index a19599a..1f0e5d1 100644 --- a/src/senna.js +++ b/src/senna.js @@ -7,6 +7,7 @@ import HtmlScreen from './screen/HtmlScreen'; import RequestScreen from './screen/RequestScreen'; import Route from './route/Route'; import Screen from './screen/Screen'; +import version from './version'; export default App; -export { dataAttributeHandler, utils, App, HtmlScreen, Route, RequestScreen, Screen }; \ No newline at end of file +export { dataAttributeHandler, utils, App, HtmlScreen, Route, RequestScreen, Screen, version }; \ No newline at end of file diff --git a/src/version.js b/src/version.js new file mode 100644 index 0000000..bf27362 --- /dev/null +++ b/src/version.js @@ -0,0 +1,4 @@ +/** + * @returns String current senna version + */ +export default '<%= version %>'; \ No newline at end of file