@magic-xpa/utils
Version:
magic utils package
533 lines (532 loc) • 53.2 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
import { NString, List, ApplicationException, StringBuilder, NChar, NNumber } from "@magic-xpa/mscorelib";
import { XMLConstants } from "../XMLConstants";
var XmlParser = /** @class */ (function () {
/// <summary>
///
/// </summary>
/// <param name="data"></param>
function XmlParser(data) {
if (data === void 0) { data = NString.Empty; }
this._currIndex = 0;
this._xmLdata = "";
this._history = new List();
this.setXMLdata(data);
this.setCurrIndex(0);
}
/// <summary> parse a string according to a set of delimiters and return the result in a vector</summary>
/// <param name="str">the String which need be parted </param>
/// <param name="delimiter">the delimiter which part different parts of str </param>
/// <param name="isMagicXML">is needed tokenizer working on Magic XML, so the "=" sign will be delited in the end of every first token </param>
/// <returns> tmpVector dynamically array, which consist tokens in every element, every token is String </returns>
/**
* @param {?} str
* @param {?} delimiter
* @param {?=} isMagicXML
* @return {?}
*/
XmlParser.getTokens = /**
* @param {?} str
* @param {?} delimiter
* @param {?=} isMagicXML
* @return {?}
*/
function (str, delimiter, isMagicXML) {
if (isMagicXML === void 0) { isMagicXML = true; }
/** @type {?} */
var tokensVec = new List();
/** @type {?} */
var token = null;
if (isMagicXML) {
str = str.trim();
}
/** @type {?} */
var strTok = str.split(delimiter.charAt(0));
for (var i = 0; i < strTok.length; i = i + 1) {
// Split in C# creates a last empty string token if the source string ends with
// the delimiter or if the string is empty (as opposed to Java that will ignore it)
// therefore we have to break this loop if such case occurs.
if (isMagicXML && i === strTok.length - 1 && strTok.length % 2 === 1) {
break;
}
token = strTok[i];
if (isMagicXML) {
// the 1st token in the pair comes with "=", remove it.
if (i % 2 === 0) {
token = token.trim();
if (token.endsWith("=")) {
token = token.substr(0, token.length - 1);
}
}
else if (token === "")
token = " ";
}
if (token === null)
throw new ApplicationException("in ClientManager.Instance.XMLParser.getTokens() null token value");
tokensVec.push(token);
}
return tokensVec;
};
/**
* @param {?} str
* @return {?}
*/
XmlParser.unescape = /**
* @param {?} str
* @return {?}
*/
function (str) {
/** @type {?} */
var unescapedString = new StringBuilder(str.length);
for (var i = 0; i < str.length; i++) {
if (str[i] !== '\\') {
unescapedString.Append(str[i]);
continue;
}
switch (str[++i]) {
case 'q':
unescapedString.Append('\"');
break;
case 'o':
unescapedString.Append('\'');
break;
case 'l':
unescapedString.Append('<');
break;
case 'g':
unescapedString.Append('>');
break;
case 'e':
unescapedString.Append('=');
break;
case 'r':
unescapedString.Append('\r');
break;
case 'n':
unescapedString.Append('\n');
break;
default:
unescapedString.Append(str[i]);
break;
}
}
return (unescapedString.ToString());
};
/**
* @param {?} str
* @return {?}
*/
XmlParser.escape = /**
* @param {?} str
* @return {?}
*/
function (str) {
/** @type {?} */
var escapedString = new StringBuilder(str.length * 2);
for (var i = 0; i < str.length; i++) {
switch (str[i]) {
case '\\':
escapedString.Append("\\\\");
break;
case '"':
escapedString.Append("\\q");
break;
case '\'':
escapedString.Append("\\o");
break;
case '<':
escapedString.Append("\\l");
break;
case '>':
escapedString.Append("\\g");
break;
case '=':
escapedString.Append("\\e");
break;
case '\r':
escapedString.Append("\r");
break;
case '\n':
escapedString.Append("\n");
break;
default:
escapedString.Append(str[i]);
break;
}
}
return (escapedString.ToString());
};
/// <summary>
/// here we only need to take care of "&" so that Sax parser will be able to handle url
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
/**
* @param {?} str
* @return {?}
*/
XmlParser.escapeUrl = /**
* @param {?} str
* @return {?}
*/
function (str) {
return NString.Replace(str, "&", "&");
};
/// <summary>get next tag name from current index in XML string</summary>
/// <returns> next tag name </returns>
/**
* @return {?}
*/
XmlParser.prototype.getNextTag = /**
* @return {?}
*/
function () {
if (this._xmLdata.length - this._currIndex <= 1) {
return null; // end of XML string
}
for (var tmpIndx = this._currIndex + 1; tmpIndx < this._xmLdata.length; tmpIndx++) {
/** @type {?} */
var tmpChar = this._xmLdata[tmpIndx];
// a letter starts an element and ends with " ". "/" starts an element closing and ends with '>'.
if (NChar.IsLetter(tmpChar) || tmpChar === '/') {
/** @type {?} */
var endOfTag = NString.IndexOfAny(this._xmLdata, XmlParser.endOfNameChar, tmpIndx, this._xmLdata.length - tmpIndx);
if (endOfTag === -1)
return null;
else
return this._xmLdata.substr(tmpIndx, endOfTag - tmpIndx);
}
}
return null;
};
/// <summary>Substring of XMLstring</summary>
/// <returns> substring of XML string -from currIndex to endContext </returns>
/**
* @param {?} endContext
* @return {?}
*/
XmlParser.prototype.getXMLsubstring = /**
* @param {?} endContext
* @return {?}
*/
function (endContext) {
return this._xmLdata.substr(this._currIndex, endContext - this._currIndex);
};
/// <summary>get current element value</summary>
/// <returns> element's value </returns>
/**
* @return {?}
*/
XmlParser.prototype.GetCurrentElementValue = /**
* @return {?}
*/
function () {
this.setCurrIndex2EndOfTag();
/** @type {?} */
var endContext = this.getXMLdata().indexOf(XMLConstants.TAG_OPEN, this.getCurrIndex());
/** @type {?} */
var value = this.getXMLsubstring(endContext);
this.setCurrIndex2EndOfTag();
return value;
};
/// <summary>set current index (on parsing time) to the end of current tag</summary>
/**
* @return {?}
*/
XmlParser.prototype.setCurrIndex2EndOfTag = /**
* @return {?}
*/
function () {
this._currIndex = this._xmLdata.indexOf(XMLConstants.TAG_CLOSE, this._currIndex) + 1;
};
/// <summary>get int from string at parsing time</summary>
/**
* @param {?} valueStr
* @return {?}
*/
XmlParser.getInt = /**
* @param {?} valueStr
* @return {?}
*/
function (valueStr) {
return NNumber.Parse(valueStr.trim());
};
/// <summary>get boolean from string at parsing time</summary>
/**
* @param {?} valueStr
* @return {?}
*/
XmlParser.getBoolean = /**
* @param {?} valueStr
* @return {?}
*/
function (valueStr) {
return valueStr[0] === '1';
};
/// <summary>get/set functions 4 XMLstring & currIndex, for parser</summary>
/**
* @return {?}
*/
XmlParser.prototype.getCurrIndex = /**
* @return {?}
*/
function () {
return this._currIndex;
};
/**
* @return {?}
*/
XmlParser.prototype.getXMLdata = /**
* @return {?}
*/
function () {
return this._xmLdata;
};
/**
* @param {?} add
* @return {?}
*/
XmlParser.prototype.add2CurrIndex = /**
* @param {?} add
* @return {?}
*/
function (add) {
this._currIndex = this._currIndex + add;
};
/**
* @param {?} index
* @return {?}
*/
XmlParser.prototype.setCurrIndex = /**
* @param {?} index
* @return {?}
*/
function (index) {
this._currIndex = index;
};
/**
* @param {?} data
* @return {?}
*/
XmlParser.prototype.setXMLdata = /**
* @param {?} data
* @return {?}
*/
function (data) {
if (data !== null)
this._xmLdata = data.trim();
else {
this._xmLdata = null;
this.setCurrIndex(0);
}
};
/// <summary>
/// prepare the parser to read from the newXmlString
/// </summary>
/// <param name="newXmlString"></param>
/**
* @param {?} newXmlString
* @return {?}
*/
XmlParser.prototype.PrepareFormReadString = /**
* @param {?} newXmlString
* @return {?}
*/
function (newXmlString) {
this.setXMLdata(newXmlString);
this.setCurrIndex(0);
};
/// <summary> push the current parsing information into the history stack</summary>
/**
* @return {?}
*/
XmlParser.prototype.push = /**
* @return {?}
*/
function () {
this._history.push(this._currIndex);
this._history.push(this._xmLdata);
};
/// <summary> restore the previous parsing information from the history stack</summary>
/**
* @return {?}
*/
XmlParser.prototype.pop = /**
* @return {?}
*/
function () {
/** @type {?} */
var count = this._history.length;
this._xmLdata = /** @type {?} */ (this._history.get_Item(count - 1));
this._currIndex = /** @type {?} */ (this._history.get_Item(count - 2));
this._history.SetSize(count - 2);
};
/// <summary>gets a table cache xml and set the xmlparser data and index accordingly</summary>
/**
* @param {?} data
* @return {?}
*/
XmlParser.prototype.loadTableCacheData = /**
* @param {?} data
* @return {?}
*/
function (data) {
this.setXMLdata(data);
this.setCurrIndex(0);
};
/// <summary>
/// Reads the XML from the element at the current position until the end of
/// the element, returning the contents as a string. This allows deferring the
/// processing of an element until the time is right to do so.<br/>
/// The returned string contains the element tag itself. For example:<br/>
/// - Assuming that the current element is 'element1', with 2 'innerElement' elements, the
/// resulting string will look like this:<br/>
/// <element1>
/// <innerelement/>
/// <innerelement/>
/// </element1>
///
/// This makes the result valid for processing by this XML parser.
/// </summary>
/// <returns></returns>
/**
* @return {?}
*/
XmlParser.prototype.ReadToEndOfCurrentElement = /**
* @return {?}
*/
function () {
/** @type {?} */
var currentTag = this.getNextTag();
/** @type {?} */
var currentTagIndex = this._xmLdata.indexOf(XMLConstants.TAG_OPEN + currentTag, this.getCurrIndex());
/** @type {?} */
var nextOpenTagIndex = this._xmLdata.indexOf(XMLConstants.TAG_OPEN, currentTagIndex + 1);
if (nextOpenTagIndex === -1)
nextOpenTagIndex = this._xmLdata.length;
/** @type {?} */
var elementEndIndex = NString.IndexOf(this._xmLdata, XMLConstants.TAG_TERM, this.getCurrIndex(), nextOpenTagIndex - this.getCurrIndex());
if (elementEndIndex === -1)
// close tag was not found in range - we have inner elements, look for the full close tag
elementEndIndex = this._xmLdata.indexOf("/" + currentTag, this.getCurrIndex()) + currentTag.length + XMLConstants.TAG_TERM.length;
else
elementEndIndex = elementEndIndex + XMLConstants.TAG_TERM.length;
/** @type {?} */
var elementBlock = this.getXMLsubstring(elementEndIndex);
// Move the parser to the end of the element block.
this.setCurrIndex(elementEndIndex);
return elementBlock;
};
/**
* @return {?}
*/
XmlParser.prototype.ReadContentOfCurrentElement = /**
* @return {?}
*/
function () {
/** @type {?} */
var currentTag = this.getNextTag();
/** @type {?} */
var elementEndIndex = this._xmLdata.indexOf("</" + currentTag + ">", this.getCurrIndex());
if (elementEndIndex === -1)
// Can't find the end of the current element - either XML is faulty or the element is empty.
return NString.Empty;
// Move to the end of the opening tag
this.setCurrIndex2EndOfTag();
/** @type {?} */
var elementBlock = this.getXMLsubstring(elementEndIndex);
// Move the parser to the end of the element block.
this.setCurrIndex(elementEndIndex);
this.setCurrIndex2EndOfTag();
return elementBlock;
};
/**
* @param {?=} headCharCount
* @param {?=} tailCharCount
* @return {?}
*/
XmlParser.prototype.toString = /**
* @param {?=} headCharCount
* @param {?=} tailCharCount
* @return {?}
*/
function (headCharCount, tailCharCount) {
if (arguments.length === 0) {
return this.ToString_0();
}
return this.ToString_1(headCharCount, tailCharCount);
};
/**
* @return {?}
*/
XmlParser.prototype.ToString_0 = /**
* @return {?}
*/
function () {
return this.toString(20, 50);
};
/**
* @param {?} headCharCount
* @param {?} tailCharCount
* @return {?}
*/
XmlParser.prototype.ToString_1 = /**
* @param {?} headCharCount
* @param {?} tailCharCount
* @return {?}
*/
function (headCharCount, tailCharCount) {
/** @type {?} */
var markerPosition = Math.min(this._currIndex, this._xmLdata.length);
/** @type {?} */
var segmentStartIndex = Math.max(0, markerPosition - headCharCount);
/** @type {?} */
var segmentEndIndex = Math.min(this._xmLdata.length, markerPosition + tailCharCount);
/** @type {?} */
var headLength = markerPosition - segmentStartIndex;
/** @type {?} */
var tailLength = segmentEndIndex - markerPosition;
/** @type {?} */
var segment = new StringBuilder();
if (segmentStartIndex > 0)
segment.Append("...");
if (headLength > 0)
segment.Append(this._xmLdata, segmentStartIndex, headLength);
segment.Append("|-{").Append(this._currIndex).Append("}-|");
if (tailLength > 0)
segment.Append(this._xmLdata, this._currIndex, tailLength);
if (segmentEndIndex < this._xmLdata.length)
segment.Append("...");
return segment.ToString();
};
/**
* @return {?}
*/
XmlParser.prototype.SkipXMLElement = /**
* @return {?}
*/
function () {
/** @type {?} */
var endContext = this.getXMLdata().indexOf(XMLConstants.TAG_TERM, this.getCurrIndex());
if (endContext !== -1 && endContext < this.getXMLdata().length) {
this.setCurrIndex2EndOfTag();
}
};
XmlParser.endOfNameChar = [' ', '>'];
return XmlParser;
}());
export { XmlParser };
if (false) {
/** @type {?} */
XmlParser.endOfNameChar;
/** @type {?} */
XmlParser.prototype._currIndex;
/** @type {?} */
XmlParser.prototype._xmLdata;
/** @type {?} */
XmlParser.prototype._history;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiWG1sUGFyc2VyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG1hZ2ljLXhwYS91dGlscy8iLCJzb3VyY2VzIjpbInNyYy9YbWwvWG1sUGFyc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxvQkFBb0IsRUFBRSxhQUFhLEVBQWMsS0FBSyxFQUFFLE9BQU8sRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQ3BILE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQzs7SUFVM0MsYUFBYTtJQUNiLEdBQUc7SUFDSCxjQUFjO0lBQ2QsK0JBQStCO0lBQy9CLG1CQUFZLElBQTRCO1FBQTVCLHFCQUFBLEVBQUEsT0FBZSxPQUFPLENBQUMsS0FBSzswQkFSWCxDQUFDO3dCQUNILEVBQUU7d0JBQ2EsSUFBSSxJQUFJLEVBQUU7UUFPbEQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QixJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQ3RCO0lBRUQseUdBQXlHO0lBQ3pHLDhEQUE4RDtJQUM5RCxvRkFBb0Y7SUFDcEYsK0lBQStJO0lBQy9JLGtIQUFrSDs7Ozs7OztJQUMzRyxtQkFBUzs7Ozs7O0lBQWhCLFVBQWlCLEdBQVcsRUFBRSxTQUFpQixFQUFFLFVBQTBCO1FBQTFCLDJCQUFBLEVBQUEsaUJBQTBCOztRQUN6RSxJQUFJLFNBQVMsR0FBaUIsSUFBSSxJQUFJLEVBQVUsQ0FBQzs7UUFDakQsSUFBSSxLQUFLLEdBQVcsSUFBSSxDQUFDO1FBRXpCLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFDZixHQUFHLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1NBQ2xCOztRQUVELElBQUksTUFBTSxHQUFhLEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRXRE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LFlBQVksRUFBRSxDQUFDLENBQUM7UUFDL0YsRUFBRSxDQUFDLENBQUMsVUFBVSxLQUFLLENBQUMsQ0FBQyxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUMvRCxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztTQUM5QjtLQUNGOzhCQTlad0MsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDO29CQUxyRDs7U0FJYSxTQUFTIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtOU3RyaW5nLCBMaXN0LCBBcHBsaWNhdGlvbkV4Y2VwdGlvbiwgU3RyaW5nQnVpbGRlciwgRGljdGlvbmFyeSwgTkNoYXIsIE5OdW1iZXJ9IGZyb20gXCJAbWFnaWMteHBhL21zY29yZWxpYlwiO1xyXG5pbXBvcnQge1hNTENvbnN0YW50c30gZnJvbSBcIi4uL1hNTENvbnN0YW50c1wiO1xyXG5cclxuLy8vIDxzdW1tYXJ5PiBhIGhlbHBlciBjbGFzcyBmb3IgdGhlIHBhcnNpbmcgb2YgdGhlIFhNTDwvc3VtbWFyeT5cclxuZXhwb3J0IGNsYXNzIFhtbFBhcnNlciB7XHJcbiAgcHJpdmF0ZSBzdGF0aWMgZW5kT2ZOYW1lQ2hhcjogc3RyaW5nW10gPSBbJyAnLCAnPiddO1xyXG5cclxuICBwcml2YXRlIF9jdXJySW5kZXg6IG51bWJlciA9IDA7XHJcbiAgcHJpdmF0ZSBfeG1MZGF0YTogc3RyaW5nID0gXCJcIjtcclxuICBwcml2YXRlIF9oaXN0b3J5OiBMaXN0PG51bWJlciB8IHN0cmluZz4gPSBuZXcgTGlzdCgpOyAvLyBJbiBvcmRlciB0byBhbGxvdyByZWN1cnNpdmUgcGFyc2luZyB3ZSBzYXZlIHByZXYgZGF0YVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJkYXRhXCI+PC9wYXJhbT5cclxuICBjb25zdHJ1Y3RvcihkYXRhOiBzdHJpbmcgPSBOU3RyaW5nLkVtcHR5KSB7XHJcbiAgICB0aGlzLnNldFhNTGRhdGEoZGF0YSk7XHJcbiAgICB0aGlzLnNldEN1cnJJbmRleCgwKTtcclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT4gcGFyc2UgYSBzdHJpbmcgYWNjb3JkaW5nIHRvIGEgc2V0IG9mIGRlbGltaXRlcnMgYW5kIHJldHVybiB0aGUgcmVzdWx0IGluIGEgdmVjdG9yPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cInN0clwiPnRoZSBTdHJpbmcgd2hpY2ggbmVlZCBiZSBwYXJ0ZWQgPC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJkZWxpbWl0ZXJcIj50aGUgZGVsaW1pdGVyIHdoaWNoIHBhcnQgZGlmZmVyZW50IHBhcnRzIG9mIHN0ciA8L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cImlzTWFnaWNYTUxcIj5pcyBuZWVkZWQgdG9rZW5pemVyIHdvcmtpbmcgb24gTWFnaWMgWE1MLCBzbyB0aGUgXCI9XCIgc2lnbiB3aWxsIGJlIGRlbGl0ZWQgaW4gdGhlIGVuZCBvZiBldmVyeSBmaXJzdCB0b2tlbiA8L3BhcmFtPlxyXG4gIC8vLyA8cmV0dXJucz4gdG1wVmVjdG9yIGR5bmFtaWNhbGx5IGFycmF5LCB3aGljaCBjb25zaXN0IHRva2VucyBpbiBldmVyeSBlbGVtZW50LCBldmVyeSB0b2tlbiBpcyBTdHJpbmcgPC9yZXR1cm5zPlxyXG4gIHN0YXRpYyBnZXRUb2tlbnMoc3RyOiBzdHJpbmcsIGRlbGltaXRlcjogc3RyaW5nLCBpc01hZ2ljWE1MOiBib29sZWFuID0gdHJ1ZSk6IExpc3Q8c3RyaW5nPiB7XHJcbiAgICBsZXQgdG9rZW5zVmVjOiBMaXN0PHN0cmluZz4gPSBuZXcgTGlzdDxzdHJpbmc+KCk7XHJcbiAgICBsZXQgdG9rZW46IHN0cmluZyA9IG51bGw7XHJcblxyXG4gICAgaWYgKGlzTWFnaWNYTUwpIHtcclxuICAgICAgc3RyID0gc3RyLnRyaW0oKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgc3RyVG9rOiBzdHJpbmdbXSA9IHN0ci5zcGxpdChkZWxpbWl0ZXIuY2hhckF0KDApKTtcclxuXHJcbiAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgc3RyVG9rLmxlbmd0aDsgaSA9IGkgKyAxKSB7XHJcbiAgICAgIC8vIFNwbGl0IGluIEMjIGNyZWF0ZXMgYSBsYXN0IGVtcHR5IHN0cmluZyB0b2tlbiBpZiB0aGUgc291cmNlIHN0cmluZyBlbmRzIHdpdGhcclxuICAgICAgLy8gdGhlIGRlbGltaXRlciBvciBpZiB0aGUgc3RyaW5nIGlzIGVtcHR5IChhcyBvcHBvc2VkIHRvIEphdmEgdGhhdCB3aWxsIGlnbm9yZSBpdClcclxuICAgICAgLy8gdGhlcmVmb3JlIHdlIGhhdmUgdG8gYnJlYWsgdGhpcyBsb29wIGlmIHN1Y2ggY2FzZSBvY2N1cnMuXHJcbiAgICAgIGlmIChpc01hZ2ljWE1MICYmIGkgPT09IHN0clRvay5sZW5ndGggLSAxICYmIHN0clRvay5sZW5ndGggJSAyID09PSAxKSB7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRva2VuID0gc3RyVG9rW2ldO1xyXG4gICAgICBpZiAoaXNNYWdpY1hNTCkge1xyXG4gICAgICAgIC8vIHRoZSAxc3QgdG9rZW4gaW4gdGhlIHBhaXIgY29tZXMgd2l0aCBcIj1cIiwgcmVtb3ZlIGl0LlxyXG4gICAgICAgIGlmIChpICUgMiA9PT0gMCkge1xyXG4gICAgICAgICAgdG9rZW4gPSB0b2tlbi50cmltKCk7XHJcbiAgICAgICAgICBpZiAodG9rZW4uZW5kc1dpdGgoXCI9XCIpKSB7XHJcbiAgICAgICAgICAgIHRva2VuID0gdG9rZW4uc3Vic3RyKDAsIHRva2VuLmxlbmd0aCAtIDEpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICAvLyAybmQgdG9rZW4gaW4gdGhlIHBhaXIgY2FuIGJlIGFuIGVtcHR5IHN0cmluZywgaW4gdGhhdCBjYXNlIHNldCBpdCB0byBcIiBcIi5cclxuICAgICAgICBlbHNlIGlmICh0b2tlbiA9PT0gXCJcIilcclxuICAgICAgICAgIHRva2VuID0gXCIgXCI7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICh0b2tlbiA9PT0gbnVsbClcclxuICAgICAgICB0aHJvdyBuZXcgQXBwbGljYXRpb25FeGNlcHRpb24oXCJpbiBDbGllbnRNYW5hZ2VyLkluc3RhbmNlLlhNTFBhcnNlci5nZXRUb2tlbnMoKSBudWxsIHRva2VuIHZhbHVlXCIpO1xyXG5cclxuICAgICAgdG9rZW5zVmVjLnB1c2godG9rZW4pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0b2tlbnNWZWM7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+dW5zY2FwZSBmcm9tOlxyXG4gIC8vLyB7XCImYW1wO1wiLFxcXFwsIFxccSwgXFxvLCBcXGwsIFxcZywgXFxlLCBcXFxcciwgXFxcXG59LCB0bzpcclxuICAvLy8ge1wiJlwiLCAgICAgXFwsICBcIiwgICcsICA8LCAgPiwgID0sICBcXHIsICBcXG59XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwic3RyXCI+U3RyaW5nIHRvIGJlIGNvbnZlcnRlZDwvcGFyYW0+XHJcbiAgLy8vIDxyZXR1cm5zPnVuZXNjYXBlZCBzdHJpbmc8L3JldHVybnM+XHJcbiAgcHVibGljIHN0YXRpYyB1bmVzY2FwZShzdHI6IHN0cmluZyk6IHN0cmluZ1xyXG4gIHtcclxuICAgIGxldCB1bmVzY2FwZWRTdHJpbmc6IFN0cmluZ0J1aWxkZXIgPSBuZXcgU3RyaW5nQnVpbGRlcihzdHIubGVuZ3RoKTtcclxuXHJcbiAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGlmIChzdHJbaV0gIT09ICdcXFxcJykge1xyXG4gICAgICAgIHVuZXNjYXBlZFN0cmluZy5BcHBlbmQoc3RyW2ldKTtcclxuICAgICAgICBjb250aW51ZTtcclxuICAgICAgfVxyXG5cclxuICAgICAgc3dpdGNoIChzdHJbKytpXSkge1xyXG4gICAgICAgIGNhc2UgJ3EnOlxyXG4gICAgICAgICAgdW5lc2NhcGVkU3RyaW5nLkFwcGVuZCgnXFxcIicpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgY2FzZSAnbyc6XHJcbiAgICAgICAgICB1bmVzY2FwZWRTdHJpbmcuQXBwZW5kKCdcXCcnKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJ2wnOlxyXG4gICAgICAgICAgdW5lc2NhcGVkU3RyaW5nLkFwcGVuZCgnPCcpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgY2FzZSAnZyc6XHJcbiAgICAgICAgICB1bmVzY2FwZWRTdHJpbmcuQXBwZW5kKCc+Jyk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICdlJzpcclxuICAgICAgICAgIHVuZXNjYXBlZFN0cmluZy5BcHBlbmQoJz0nKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJ3InOlxyXG4gICAgICAgICAgdW5lc2NhcGVkU3RyaW5nLkFwcGVuZCgnXFxyJyk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICduJzpcclxuICAgICAgICAgIHVuZXNjYXBlZFN0cmluZy5BcHBlbmQoJ1xcbicpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgIHVuZXNjYXBlZFN0cmluZy5BcHBlbmQoc3RyW2ldKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gKHVuZXNjYXBlZFN0cmluZy5Ub1N0cmluZygpKTtcclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5lc2NhcGUgZnJvbTpcclxuICAvLy8ge1xcLCAgXCIsICAnLCAgPCwgICA+LCAgPSwgIFxcciwgIFxcbn0sIHRvOlxyXG4gIC8vLyB7XFxcXCwgXFxxLCBcXDAsIFxcbCwgIFxcZywgXFxlLCBcXFxcciwgXFxcXG59XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwic3RyXCI+U3RyaW5nIHRvIGJlIGNvbnZlcnRlZDwvcGFyYW0+XHJcbiAgLy8vIDxyZXR1cm5zPmVzY2FwZWQgc3RyaW5nPC9yZXR1cm5zPlxyXG4gIHB1YmxpYyBzdGF0aWMgZXNjYXBlKHN0cjogc3RyaW5nKTogc3RyaW5nXHJcbiAge1xyXG4gICAgbGV0IGVzY2FwZWRTdHJpbmc6IFN0cmluZ0J1aWxkZXIgPSBuZXcgU3RyaW5nQnVpbGRlcihzdHIubGVuZ3RoICogMik7XHJcblxyXG4gICAgZm9yIChsZXQgaTogbnVtYmVyID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xyXG4gICAgICBzd2l0Y2ggKHN0cltpXSkge1xyXG4gICAgICAgIGNhc2UgJ1xcXFwnOlxyXG4gICAgICAgICAgZXNjYXBlZFN0cmluZy5BcHBlbmQoXCJcXFxcXFxcXFwiKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJ1wiJzpcclxuICAgICAgICAgIGVzY2FwZWRTdHJpbmcuQXBwZW5kKFwiXFxcXHFcIik7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICdcXCcnOlxyXG4gICAgICAgICAgZXNjYXBlZFN0cmluZy5BcHBlbmQoXCJcXFxcb1wiKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJzwnOlxyXG4gICAgICAgICAgZXNjYXBlZFN0cmluZy5BcHBlbmQoXCJcXFxcbFwiKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJz4nOlxyXG4gICAgICAgICAgZXNjYXBlZFN0cmluZy5BcHBlbmQoXCJcXFxcZ1wiKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJz0nOlxyXG4gICAgICAgICAgZXNjYXBlZFN0cmluZy5BcHBlbmQoXCJcXFxcZVwiKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJ1xccic6XHJcbiAgICAgICAgICBlc2NhcGVkU3RyaW5nLkFwcGVuZChcIlxcclwiKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJ1xcbic6XHJcbiAgICAgICAgICBlc2NhcGVkU3RyaW5nLkFwcGVuZChcIlxcblwiKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICBlc2NhcGVkU3RyaW5nLkFwcGVuZChzdHJbaV0pO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gKGVzY2FwZWRTdHJpbmcuVG9TdHJpbmcoKSk7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIGhlcmUgd2Ugb25seSBuZWVkIHRvIHRha2UgY2FyZSBvZiBcIiZcIiBzbyB0aGF0IFNheCBwYXJzZXIgd2lsbCBiZSBhYmxlIHRvIGhhbmRsZSB1cmxcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cInN0clwiPjwvcGFyYW0+XHJcbiAgLy8vIDxyZXR1cm5zPjwvcmV0dXJucz5cclxuICBzdGF0aWMgZXNjYXBlVXJsKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIHJldHVybiBOU3RyaW5nLlJlcGxhY2Uoc3RyLCBcIiZcIiwgXCImYW1wO1wiKTtcclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5nZXQgbmV4dCB0YWcgbmFtZSBmcm9tIGN1cnJlbnQgaW5kZXggaW4gWE1MIHN0cmluZzwvc3VtbWFyeT5cclxuICAvLy8gPHJldHVybnM+IG5leHQgdGFnIG5hbWUgPC9yZXR1cm5zPlxyXG4gIGdldE5leHRUYWcoKTogc3RyaW5nIHtcclxuICAgIGlmICh0aGlzLl94bUxkYXRhLmxlbmd0aCAtIHRoaXMuX2N1cnJJbmRleCA8PSAxKSB7XHJcbiAgICAgIHJldHVybiBudWxsOyAgLy8gZW5kIG9mIFhNTCBzdHJpbmdcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGxldCB0bXBJbmR4OiBudW1iZXIgPSB0aGlzLl9jdXJySW5kZXggKyAxOyB0bXBJbmR4IDwgdGhpcy5feG1MZGF0YS5sZW5ndGg7IHRtcEluZHgrKykge1xyXG4gICAgICBsZXQgdG1wQ2hhcjogc3RyaW5nID0gdGhpcy5feG1MZGF0YVt0bXBJbmR4XTtcclxuXHJcbiAgICAgIC8vIGEgbGV0dGVyIHN0YXJ0cyBhbiBlbGVtZW50IGFuZCBlbmRzIHdpdGggXCIgXCIuIFwiL1wiIHN0YXJ0cyBhbiBlbGVtZW50IGNsb3NpbmcgYW5kIGVuZHMgd2l0aCAnPicuXHJcbiAgICAgIGlmIChOQ2hhci5Jc0xldHRlcih0bXBDaGFyKSB8fCB0bXBDaGFyID09PSAnLycpIHtcclxuICAgICAgICBsZXQgZW5kT2ZUYWc6IG51bWJlciA9IE5TdHJpbmcuSW5kZXhPZkFueSh0aGlzLl94bUxkYXRhLCBYbWxQYXJzZXIuZW5kT2ZOYW1lQ2hhciwgdG1wSW5keCwgdGhpcy5feG1MZGF0YS5sZW5ndGggLSB0bXBJbmR4KTtcclxuXHJcbiAgICAgICAgaWYgKGVuZE9mVGFnID09PSAtMSlcclxuICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgIHJldHVybiB0aGlzLl94bUxkYXRhLnN1YnN0cih0bXBJbmR4LCBlbmRPZlRhZyAtIHRtcEluZHgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+U3Vic3RyaW5nIG9mIFhNTHN0cmluZzwvc3VtbWFyeT5cclxuICAvLy8gPHJldHVybnM+IHN1YnN0cmluZyBvZiBYTUwgc3RyaW5nIC1mcm9tIGN1cnJJbmRleCB0byBlbmRDb250ZXh0IDwvcmV0dXJucz5cclxuICBnZXRYTUxzdWJzdHJpbmcoZW5kQ29udGV4dDogbnVtYmVyKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLl94bUxkYXRhLnN1YnN0cih0aGlzLl9jdXJySW5kZXgsIGVuZENvbnRleHQgLSB0aGlzLl9jdXJySW5kZXgpO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PmdldCBjdXJyZW50IGVsZW1lbnQgdmFsdWU8L3N1bW1hcnk+XHJcbiAgLy8vIDxyZXR1cm5zPiBlbGVtZW50J3MgdmFsdWUgPC9yZXR1cm5zPlxyXG4gIEdldEN1cnJlbnRFbGVtZW50VmFsdWUoKTogc3RyaW5nIHtcclxuICAgIHRoaXMuc2V0Q3VyckluZGV4MkVuZE9mVGFnKCk7XHJcbiAgICBsZXQgZW5kQ29udGV4dDogbnVtYmVyID0gdGhpcy5nZXRYTUxkYXRhKCkuaW5kZXhPZihYTUxDb25zdGFudHMuVEFHX09QRU4sIHRoaXMuZ2V0Q3VyckluZGV4KCkpO1xyXG4gICAgLy8gcmVhZCB2YWx1ZSBvZiB4bWwgZWxlbWVudFxyXG4gICAgbGV0IHZhbHVlOiBzdHJpbmcgPSB0aGlzLmdldFhNTHN1YnN0cmluZyhlbmRDb250ZXh0KTtcclxuICAgIHRoaXMuc2V0Q3VyckluZGV4MkVuZE9mVGFnKCk7XHJcbiAgICByZXR1cm4gdmFsdWU7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+c2V0IGN1cnJlbnQgaW5kZXggKG9uIHBhcnNpbmcgdGltZSkgdG8gdGhlIGVuZCBvZiBjdXJyZW50IHRhZzwvc3VtbWFyeT5cclxuICBzZXRDdXJySW5kZXgyRW5kT2ZUYWcoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9jdXJySW5kZXggPSB0aGlzLl94bUxkYXRhLmluZGV4T2YoWE1MQ29uc3RhbnRzLlRBR19DTE9TRSwgdGhpcy5fY3VyckluZGV4KSArIDE7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+Z2V0IGludCBmcm9tIHN0cmluZyBhdCBwYXJzaW5nIHRpbWU8L3N1bW1hcnk+XHJcbiAgc3RhdGljIGdldEludCh2YWx1ZVN0cjogc3RyaW5nKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBOTnVtYmVyLlBhcnNlKHZhbHVlU3RyLnRyaW0oKSk7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+Z2V0IGJvb2xlYW4gZnJvbSBzdHJpbmcgYXQgcGFyc2luZyB0aW1lPC9zdW1tYXJ5PlxyXG4gIHN0YXRpYyBnZXRCb29sZWFuKHZhbHVlU3RyOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB2YWx1ZVN0clswXSA9PT0gJzEnO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PmdldC9zZXQgZnVuY3Rpb25zIDQgWE1Mc3RyaW5nICYgY3VyckluZGV4LCBmb3IgcGFyc2VyPC9zdW1tYXJ5PlxyXG4gIGdldEN1cnJJbmRleCgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX2N1cnJJbmRleDtcclxuICB9XHJcblxyXG4gIGdldFhNTGRhdGEoKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLl94bUxkYXRhO1xyXG4gIH1cclxuXHJcbiAgYWRkMkN1cnJJbmRleChhZGQ6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5fY3VyckluZGV4ID0gdGhpcy5fY3VyckluZGV4ICsgYWRkO1xyXG4gIH1cclxuXHJcbiAgc2V0Q3VyckluZGV4KGluZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMuX2N1cnJJbmRleCA9IGluZGV4O1xyXG4gIH1cclxuXHJcbiAgc2V0WE1MZGF0YShkYXRhOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmIChkYXRhICE9PSBudWxsKVxyXG4gICAgICB0aGlzLl94bUxkYXRhID0gZGF0YS50cmltKCk7XHJcbiAgICBlbHNlIHtcclxuICAgICAgdGhpcy5feG1MZGF0YSA9IG51bGw7XHJcbiAgICAgIHRoaXMuc2V0Q3VyckluZGV4KDApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyBwcmVwYXJlIHRoZSBwYXJzZXIgdG8gcmVhZCBmcm9tIHRoZSBuZXdYbWxTdHJpbmdcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm5ld1htbFN0cmluZ1wiPjwvcGFyYW0+XHJcbiAgUHJlcGFyZUZvcm1SZWFkU3RyaW5nKG5ld1htbFN0cmluZzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLnNldFhNTGRhdGEobmV3WG1sU3RyaW5nKTtcclxuICAgIHRoaXMuc2V0Q3VyckluZGV4KDApO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PiBwdXNoIHRoZSBjdXJyZW50IHBhcnNpbmcgaW5mb3JtYXRpb24gaW50byB0aGUgaGlzdG9yeSBzdGFjazwvc3VtbWFyeT5cclxuICBwdXNoKCk6IHZvaWQge1xyXG4gICAgdGhpcy5faGlzdG9yeS5wdXNoKHRoaXMuX2N1cnJJbmRleCk7XHJcbiAgICB0aGlzLl9oaXN0b3J5LnB1c2godGhpcy5feG1MZGF0YSk7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+IHJlc3RvcmUgdGhlIHByZXZpb3VzIHBhcnNpbmcgaW5mb3JtYXRpb24gZnJvbSB0aGUgaGlzdG9yeSBzdGFjazwvc3VtbWFyeT5cclxuICBwb3AoKTogdm9pZCB7XHJcbiAgICBsZXQgY291bnQ6IG51bWJlciA9IHRoaXMuX2hpc3RvcnkubGVuZ3RoO1xyXG5cclxuICAgIHRoaXMuX3htTGRhdGEgPSA8c3RyaW5nPnRoaXMuX2hpc3RvcnkuZ2V0X0l0ZW0oY291bnQgLSAxKTtcclxuICAgIHRoaXMuX2N1cnJJbmRleCA9IDxudW1iZXI+dGhpcy5faGlzdG9yeS5nZXRfSXRlbShjb3VudCAtIDIpO1xyXG5cclxuICAgIHRoaXMuX2hpc3RvcnkuU2V0U2l6ZShjb3VudCAtIDIpO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PmdldHMgYSB0YWJsZSBjYWNoZSB4bWwgYW5kIHNldCB0aGUgeG1scGFyc2VyIGRhdGEgYW5kIGluZGV4IGFjY29yZGluZ2x5PC9zdW1tYXJ5PlxyXG4gIGxvYWRUYWJsZUNhY2hlRGF0YShkYXRhOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuc2V0WE1MZGF0YShkYXRhKTtcclxuICAgIHRoaXMuc2V0Q3VyckluZGV4KDApO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyBSZWFkcyB0aGUgWE1MIGZyb20gdGhlIGVsZW1lbnQgYXQgdGhlIGN1cnJlbnQgcG9zaXRpb24gdW50aWwgdGhlIGVuZCBvZlxyXG4gIC8vLyB0aGUgZWxlbWVudCwgcmV0dXJuaW5nIHRoZSBjb250ZW50cyBhcyBhIHN0cmluZy4gVGhpcyBhbGxvd3MgZGVmZXJyaW5nIHRoZVxyXG4gIC8vLyBwcm9jZXNzaW5nIG9mIGFuIGVsZW1lbnQgdW50aWwgdGhlIHRpbWUgaXMgcmlnaHQgdG8gZG8gc28uPGJyLz5cclxuICAvLy8gVGhlIHJldHVybmVkIHN0cmluZyBjb250YWlucyB0aGUgZWxlbWVudCB0YWcgaXRzZWxmLiBGb3IgZXhhbXBsZTo8YnIvPlxyXG4gIC8vLyAtIEFzc3VtaW5nIHRoYXQgdGhlIGN1cnJlbnQgZWxlbWVudCBpcyAnZWxlbWVudDEnLCB3aXRoIDIgJ2lubmVyRWxlbWVudCcgZWxlbWVudHMsIHRoZVxyXG4gIC8vLyByZXN1bHRpbmcgc3RyaW5nIHdpbGwgbG9vayBsaWtlIHRoaXM6PGJyLz5cclxuICAvLy8gPGVsZW1lbnQxPlxyXG4gIC8vLyAgIDxpbm5lcmVsZW1lbnQvPlxyXG4gIC8vLyAgIDxpbm5lcmVsZW1lbnQvPlxyXG4gIC8vLyA8L2VsZW1lbnQxPlxyXG4gIC8vL1xyXG4gIC8vLyBUaGlzIG1ha2VzIHRoZSByZXN1bHQgdmFsaWQgZm9yIHByb2Nlc3NpbmcgYnkgdGhpcyBYTUwgcGFyc2VyLlxyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxyZXR1cm5zPjwvcmV0dXJucz5cclxuICBSZWFkVG9FbmRPZkN1cnJlbnRFbGVtZW50KCk6IHN0cmluZyB7XHJcbiAgICAvLyBHZXQgdGhlIGN1cnJlbnQgdGFnIGFjY29yZGluZyB0byB0aGUgdmFsdWUgb2YgX2N1cnJJbmRleC5cclxuICAgIGxldCBjdXJyZW50VGFnOiBzdHJpbmcgPSB0aGlzLmdldE5leHRUYWcoKTtcclxuICAgIGxldCBjdXJyZW50VGFnSW5kZXg6IG51bWJlciA9IHRoaXMuX3htTGRhdGEuaW5kZXhPZihYTUxDb25zdGFudHMuVEFHX09QRU4gKyBjdXJyZW50VGFnLCB0aGlzLmdldEN1cnJJbmRleCgpKTtcclxuXHJcbiAgICAvLyBGaW5kIHRoZSBlbmQgb2YgdGhlIGVsZW1lbnQncyBibG9jayBpbiB0aGUgWE1MLlxyXG4gICAgLy8gZmluZCBuZXh0IG9wZW4gdGFnXHJcbiAgICBsZXQgbmV4dE9wZW5UYWdJbmRleDogbnVtYmVyID0gdGhpcy5feG1MZGF0YS5pbmRleE9mKFhNTENvbnN0YW50cy5UQUdfT1BFTiwgY3VycmVudFRhZ0luZGV4ICsgMSk7XHJcbiAgICBpZiAobmV4dE9wZW5UYWdJbmRleCA9PT0gLTEpXHJcbiAgICAgIG5leHRPcGVuVGFnSW5kZXggPSB0aGlzLl94bUxkYXRhLmxlbmd0aDtcclxuXHJcbiAgICAvLyBmaW5kIGEgY2xvc2UgdGFnIEJFRk9SRSB0aGUgbmV4dCBvcGVuIHRhZ1xyXG4gICAgbGV0IGVsZW1lbnRFbmRJbmRleDogbnVtYmVyID0gTlN0cmluZy5JbmRleE9mKHRoaXMuX3htTGRhdGEsIFhNTENvbnN0YW50cy5UQUdfVEVSTSwgdGhpcy5nZXRDdXJySW5kZXgoKSwgbmV4dE9wZW5UYWdJbmRleCAtIHRoaXMuZ2V0Q3VyckluZGV4KCkpO1xyXG4gICAgaWYgKGVsZW1lbnRFbmRJbmRleCA9PT0gLTEpXHJcbiAgICAvLyBjbG9zZSB0YWcgd2FzIG5vdCBmb3VuZCBpbiByYW5nZSAtIHdlIGhhdmUgaW5uZXIgZWxlbWVudHMsIGxvb2sgZm9yIHRoZSBmdWxsIGNsb3NlIHRhZ1xyXG4gICAgICBlbGVtZW50RW5kSW5kZXggPSB0aGlzLl94bUxkYXRhLmluZGV4T2YoXCIvXCIgKyBjdXJyZW50VGFnLCB0aGlzLmdldEN1cnJJbmRleCgpKSArIGN1cnJlbnRUYWcubGVuZ3RoICsgWE1MQ29uc3RhbnRzLlRBR19URVJNLmxlbmd0aDtcclxuICAgIGVsc2VcclxuICAgICAgZWxlbWVudEVuZEluZGV4ID0gZWxlbWVudEVuZEluZGV4ICsgWE1MQ29uc3RhbnRzLlRBR19URVJNLmxlbmd0aDtcclxuXHJcbiAgICAvLyBDb3B5IHRoZSBlbGVtZW50IGRhdGEgc28gaXQgY2FuIGJlIHJldHVybmVkLlxyXG4gICAgbGV0IGVsZW1lbnRCbG9jazogc3RyaW5nID0gdGhpcy5nZXRYTUxzdWJzdHJpbmcoZWxlbWVudEVuZEluZGV4KTtcclxuXHJcbiAgICAvLyBNb3ZlIHRoZSBwYXJzZXIgdG8gdGhlIGVuZCBvZiB0aGUgZWxlbWVudCBibG9jay5cclxuICAgIHRoaXMuc2V0Q3VyckluZGV4KGVsZW1lbnRFbmRJbmRleCk7XHJcblxyXG4gICAgcmV0dXJuIGVsZW1lbnRCbG9jaztcclxuICB9XHJcblxyXG4gIFJlYWRDb250ZW50T2ZDdXJyZW50RWxlbWVudCgpOiBzdHJpbmcge1xyXG4gICAgLy8gR2V0IHRoZSBjdXJyZW50IHRhZyBhY2NvcmRpbmcgdG8gdGhlIHZhbHVlIG9mIF9jdXJySW5kZXguXHJcbiAgICBsZXQgY3VycmVudFRhZzogc3RyaW5nID0gdGhpcy5nZXROZXh0VGFnKCk7XHJcblxyXG4gICAgLy8gRmluZCB0aGUgZW5kIG9mIHRoZSBlbGVtZW50J3MgYmxvY2sgaW4gdGhlIFhNTC5cclxuICAgIGxldCBlbGVtZW50RW5kSW5kZXg6IG51bWJlciA9IHRoaXMuX3htTGRhdGEuaW5kZXhPZihcIjwvXCIgKyBjdXJyZW50VGFnICsgXCI+XCIsIHRoaXMuZ2V0Q3VyckluZGV4KCkpO1xyXG5cclxuICAgIGlmIChlbGVtZW50RW5kSW5kZXggPT09IC0xKVxyXG4gICAgICAvLyBDYW4ndCBmaW5kIHRoZSBlbmQgb2YgdGhlIGN1cnJlbnQgZWxlbWVudCAtIGVpdGhlciBYTUwgaXMgZmF1bHR5IG9yIHRoZSBlbGVtZW50IGlzIGVtcHR5LlxyXG4gICAgICByZXR1cm4gTlN0cmluZy5FbXB0eTtcclxuXHJcbiAgICAvLyBNb3ZlIHRvIHRoZSBlbmQgb2YgdGhlIG9wZW5pbmcgdGFnXHJcbiAgICB0aGlzLnNldEN1cnJJbmRleDJFbmRPZlRhZygpO1xyXG5cclxuICAgIC8vIENvcHkgdGhlIGNvbnRlbnQgb2YgdGhlIGVsZW1lbnQgKGZyb20gdGhlIGVuZCBvZiB0aGUgb3BlbmluZyB0YWcgdG8gdGhlIGJlZ2lubmluZyBvZiB0aGUgY2xvc2luZyB0YWcpLlxyXG4gICAgbGV0IGVsZW1lbnRCbG9jazogc3RyaW5nID0gdGhpcy5nZXRYTUxzdWJzdHJpbmcoZWxlbWVudEVuZEluZGV4KTtcclxuXHJcbiAgICAvLyBNb3ZlIHRoZSBwYXJzZXIgdG8gdGhlIGVuZCBvZiB0aGUgZWxlbWVudCBibG9jay5cclxuICAgIHRoaXMuc2V0Q3VyckluZGV4KGVsZW1lbnRFbmRJbmRleCk7XHJcbiAgICB0aGlzLnNldEN1cnJJbmRleDJFbmRPZlRhZygpO1xyXG5cclxuICAgIHJldHVybiBlbGVtZW50QmxvY2s7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIEdlbmVyYXRlcyBhIHN0cmluZyB0aGF0IHZpc3VhbGl6ZXMgdGhlIFhNTCBwYXJzZXIgc3RhdGUgKGUuZy4gZm9yIGRlYnVnIHdhdGNoIGxpc3QuKTxici8+XHJcbiAgLy8vIFRoZSBtZXRob2Qgd2lsbCBzaG93IHRoZSBYTUwgZGF0YSwgdHJpbW1pbmcgaXQgdG8gMjAgY2hhcmFjdGVycyBiZWZvcmUgdGhlXHJcbiAgLy8vIGN1cnJlbnQgcG9zaXRpb24gKF9jdXJySW5kZXgpIGFuZCB1cCB0byA1MCBjaGFyYWN0ZXJzIGFmdGVyIHRoZSBjdXJyZW50IHBvc2l0aW9uLlxyXG4gIC8vLyBUaGUgY3VycmVudCBwb3NpdGlvbiBpdHNlbGYgd2lsbCBiZSBtYXJrZWQgd2l0aCBhIG1hcmtlciB0aGF0IGxvb2tzIGxpa2U6XHJcbiAgLy8vIHwte2N1cnJlbnQgaW5kZXh9LXwgPGJyLz5cclxuICAvLy8gVGhlIG1hcmtlciB3aWxsIGJlIHBsYWNlZCBpbW1lZGlhdGVseSBiZWZvcmUgX3htbERhdGFbX2N1cnJJbmRleF0uXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJoZWFkQ2hhckNvdW50XCI+TnVtYmVyIG9mIGNoYXJhY3RlcnMgdG8gc2hvdyBiZWZvcmUgdGhlIGN1cnJlbnQgcG9zaXRpb24gbWFya2VyLjwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwidGFpbENoYXJDb3VudFwiPk51bWJlciBvZiBjaGFyYWN0ZXJzIHRvIHNob3cgYWZ0ZXIgdGhlIGN1cnJlbnQgcG9zaXRpb24gbWFya2VyLjwvcGFyYW0+XHJcbiAgLy8vIDxyZXR1cm5zPjwvcmV0dXJucz5cclxuICB0b1N0cmluZygpOiBzdHJpbmc7XHJcbiAgdG9TdHJpbmcoaGVhZENoYXJDb3VudDogbnVtYmVyLCB0YWlsQ2hhckNvdW50OiBudW1iZXIpOiBzdHJpbmc7XHJcbiAgdG9TdHJpbmcoaGVhZENoYXJDb3VudD86IG51bWJlciwgdGFpbENoYXJDb3VudD86IG51bWJlcik6IHN0cmluZyB7XHJcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5Ub1N0cmluZ18wKCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5Ub1N0cmluZ18xKGhlYWRDaGFyQ291bnQsIHRhaWxDaGFyQ291bnQpO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyBHZW5lcmF0ZXMgYSBzdHJpbmcgdGhhdCB2aXN1YWxpemVzIHRoZSBYTUwgcGFyc2VyIHN0YXRlIChlLmcuIGZvciBkZWJ1ZyB3YXRjaCBsaXN0Lik8YnIvPlxyXG4gIC8vLyBUaGUgbWV0aG9kIHdpbGwgc2hvdyB0aGUgWE1MIGRhdGEsIHRyaW1taW5nIGl0IHRvIDIwIGNoYXJhY3RlcnMgYmVmb3JlIHRoZVxyXG4gIC8vLyBjdXJyZW50IHBvc2l0aW9uIChfY3VyckluZGV4KSBhbmQgdXAgdG8gNTAgY2hhcmFjdGVycyBhZnRlciB0aGUgY3VycmVudCBwb3NpdGlvbi5cclxuICAvLy8gVGhlIGN1cnJlbnQgcG9