@ngx-i18nsupport/ngx-i18nsupport-lib
Version:
A Typescript library to work with Angular generated i18n files (xliff, xmb)
493 lines • 47.4 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import * as tslib_1 from "tslib";
import { AbstractMessageParser } from './abstract-message-parser';
import { ParsedMessagePartType } from './parsed-message-part';
import { TagMapping } from './tag-mapping';
/**
* Created by roobm on 10.05.2017.
* A message parser for XLIFF 2.0
*/
var /**
* Created by roobm on 10.05.2017.
* A message parser for XLIFF 2.0
*/
Xliff2MessageParser = /** @class */ (function (_super) {
tslib_1.__extends(Xliff2MessageParser, _super);
function Xliff2MessageParser() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Handle this element node.
* This is called before the children are done.
* @param elementNode elementNode
* @param message message to be altered
* @return true, if children should be processed too, false otherwise (children ignored then)
*/
/**
* Handle this element node.
* This is called before the children are done.
* @protected
* @param {?} elementNode elementNode
* @param {?} message message to be altered
* @return {?} true, if children should be processed too, false otherwise (children ignored then)
*/
Xliff2MessageParser.prototype.processStartElement = /**
* Handle this element node.
* This is called before the children are done.
* @protected
* @param {?} elementNode elementNode
* @param {?} message message to be altered
* @return {?} true, if children should be processed too, false otherwise (children ignored then)
*/
function (elementNode, message) {
/** @type {?} */
var tagName = elementNode.tagName;
if (tagName === 'ph') {
// placeholder are like <ph id="0" equiv="INTERPOLATION" disp="{{number()}}"/>
// They contain the id and also a name (number in the example)
// TODO make some use of the name (but it is not available in XLIFF 1.2)
// ICU message are handled with the same tag
// Before 4.3.2 they did not have an equiv and disp (Bug #17344):
// e.g. <ph id="0"/>
// Beginning with 4.3.2 they do have an equiv ICU and disp:
// e.g. <ph id="0" equiv="ICU" disp="{count, plural, =0 {...} =1 {...} other {...}}"/>
// and empty tags have equiv other then INTERPOLATION:
// e.g. <ph id="3" equiv="TAG_IMG" type="image" disp="<img/>"/>
// or <ph equiv="LINE_BREAK" type="lb" disp="<br/>"/>
/** @type {?} */
var isInterpolation = false;
/** @type {?} */
var isICU = false;
/** @type {?} */
var isEmptyTag = false;
/** @type {?} */
var equiv = elementNode.getAttribute('equiv');
/** @type {?} */
var disp = elementNode.getAttribute('disp');
/** @type {?} */
var indexString = null;
/** @type {?} */
var index = 0;
/** @type {?} */
var emptyTagName = null;
if (!equiv) {
// old ICU syntax, fixed with #17344
isICU = true;
indexString = elementNode.getAttribute('id');
index = Number.parseInt(indexString, 10);
}
else if (equiv.startsWith('ICU')) {
// new ICU syntax, fixed with #17344
isICU = true;
if (equiv === 'ICU') {
indexString = '0';
}
else {
indexString = equiv.substring('ICU_'.length);
}
index = Number.parseInt(indexString, 10);
}
else if (equiv.startsWith('INTERPOLATION')) {
isInterpolation = true;
if (equiv === 'INTERPOLATION') {
indexString = '0';
}
else {
indexString = equiv.substring('INTERPOLATION_'.length);
}
index = Number.parseInt(indexString, 10);
}
else if (new TagMapping().isEmptyTagPlaceholderName(equiv)) {
isEmptyTag = true;
emptyTagName = new TagMapping().getTagnameFromEmptyTagPlaceholderName(equiv);
}
else {
return true;
}
if (isInterpolation) {
message.addPlaceholder(index, disp);
}
else if (isICU) {
message.addICUMessageRef(index, disp);
}
else if (isEmptyTag) {
message.addEmptyTag(emptyTagName, this.parseIdCountFromName(equiv));
}
}
else if (tagName === 'pc') {
// pc example: <pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt"
// dispStart="<b>" dispEnd="</b>">IMPORTANT</pc>
/** @type {?} */
var embeddedTagName = this.tagNameFromPCElement(elementNode);
if (embeddedTagName) {
message.addStartTag(embeddedTagName, this.parseIdCountFromName(elementNode.getAttribute('equivStart')));
}
}
return true;
};
/**
* Handle end of this element node.
* This is called after all children are processed.
* @param elementNode elementNode
* @param message message to be altered
*/
/**
* Handle end of this element node.
* This is called after all children are processed.
* @protected
* @param {?} elementNode elementNode
* @param {?} message message to be altered
* @return {?}
*/
Xliff2MessageParser.prototype.processEndElement = /**
* Handle end of this element node.
* This is called after all children are processed.
* @protected
* @param {?} elementNode elementNode
* @param {?} message message to be altered
* @return {?}
*/
function (elementNode, message) {
/** @type {?} */
var tagName = elementNode.tagName;
if (tagName === 'pc') {
// pc example: <pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt"
// dispStart="<b>" dispEnd="</b>">IMPORTANT</pc>
/** @type {?} */
var embeddedTagName = this.tagNameFromPCElement(elementNode);
if (embeddedTagName) {
message.addEndTag(embeddedTagName);
}
return;
}
};
/**
* @private
* @param {?} pcNode
* @return {?}
*/
Xliff2MessageParser.prototype.tagNameFromPCElement = /**
* @private
* @param {?} pcNode
* @return {?}
*/
function (pcNode) {
/** @type {?} */
var dispStart = pcNode.getAttribute('dispStart');
if (dispStart.startsWith('<')) {
dispStart = dispStart.substring(1);
}
if (dispStart.endsWith('>')) {
dispStart = dispStart.substring(0, dispStart.length - 1);
}
return dispStart;
};
/**
* reimplemented here, because XLIFF 2.0 uses a deeper xml model.
* So we cannot simply replace the message parts by xml parts.
* @param message message
* @param rootElem rootElem
*/
/**
* reimplemented here, because XLIFF 2.0 uses a deeper xml model.
* So we cannot simply replace the message parts by xml parts.
* @protected
* @param {?} message message
* @param {?} rootElem rootElem
* @return {?}
*/
Xliff2MessageParser.prototype.addXmlRepresentationToRoot = /**
* reimplemented here, because XLIFF 2.0 uses a deeper xml model.
* So we cannot simply replace the message parts by xml parts.
* @protected
* @param {?} message message
* @param {?} rootElem rootElem
* @return {?}
*/
function (message, rootElem) {
var _this = this;
/** @type {?} */
var stack = [{ element: rootElem, tagName: 'root' }];
/** @type {?} */
var id = 0;
message.parts().forEach((/**
* @param {?} part
* @return {?}
*/
function (part) {
switch (part.type) {
case ParsedMessagePartType.TEXT:
stack[stack.length - 1].element.appendChild(_this.createXmlRepresentationOfTextPart((/** @type {?} */ (part)), rootElem));
break;
case ParsedMessagePartType.PLACEHOLDER:
stack[stack.length - 1].element.appendChild(_this.createXmlRepresentationOfPlaceholderPart((/** @type {?} */ (part)), rootElem, id++));
break;
case ParsedMessagePartType.ICU_MESSAGE_REF:
stack[stack.length - 1].element.appendChild(_this.createXmlRepresentationOfICUMessageRefPart((/** @type {?} */ (part)), rootElem));
break;
case ParsedMessagePartType.START_TAG:
/** @type {?} */
var newTagElem = _this.createXmlRepresentationOfStartTagPart((/** @type {?} */ (part)), rootElem, id++);
stack[stack.length - 1].element.appendChild(newTagElem);
stack.push({ element: (/** @type {?} */ (newTagElem)), tagName: ((/** @type {?} */ (part))).tagName() });
break;
case ParsedMessagePartType.END_TAG:
/** @type {?} */
var closeTagName = ((/** @type {?} */ (part))).tagName();
if (stack.length <= 1 || stack[stack.length - 1].tagName !== closeTagName) {
// oops, not well formed
throw new Error('unexpected close tag ' + closeTagName);
}
stack.pop();
break;
case ParsedMessagePartType.EMPTY_TAG:
/** @type {?} */
var emptyTagElem = _this.createXmlRepresentationOfEmptyTagPart((/** @type {?} */ (part)), rootElem, id++);
stack[stack.length - 1].element.appendChild(emptyTagElem);
break;
}
}));
if (stack.length !== 1) {
// oops, not well closed tags
throw new Error('missing close tag ' + stack[stack.length - 1].tagName);
}
};
/**
* the xml used for start tag in the message.
* Returns an empty pc-Element.
* e.g. <pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">
* Text content will be added later.
* @param part part
* @param rootElem rootElem
* @param id id number in xliff2
*/
/**
* the xml used for start tag in the message.
* Returns an empty pc-Element.
* e.g. <pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">
* Text content will be added later.
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @param {?} id id number in xliff2
* @return {?}
*/
Xliff2MessageParser.prototype.createXmlRepresentationOfStartTagPart = /**
* the xml used for start tag in the message.
* Returns an empty pc-Element.
* e.g. <pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">
* Text content will be added later.
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @param {?} id id number in xliff2
* @return {?}
*/
function (part, rootElem, id) {
/** @type {?} */
var tagMapping = new TagMapping();
/** @type {?} */
var pcElem = rootElem.ownerDocument.createElement('pc');
/** @type {?} */
var tagName = part.tagName();
/** @type {?} */
var equivStart = tagMapping.getStartTagPlaceholderName(tagName, part.idCounter());
/** @type {?} */
var equivEnd = tagMapping.getCloseTagPlaceholderName(tagName);
/** @type {?} */
var dispStart = '<' + tagName + '>';
/** @type {?} */
var dispEnd = '</' + tagName + '>';
pcElem.setAttribute('id', id.toString(10));
pcElem.setAttribute('equivStart', equivStart);
pcElem.setAttribute('equivEnd', equivEnd);
pcElem.setAttribute('type', this.getTypeForTag(tagName));
pcElem.setAttribute('dispStart', dispStart);
pcElem.setAttribute('dispEnd', dispEnd);
return pcElem;
};
/**
* the xml used for end tag in the message.
* Not used here, because content is child of start tag.
* @param part part
* @param rootElem rootElem
*/
/**
* the xml used for end tag in the message.
* Not used here, because content is child of start tag.
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @return {?}
*/
Xliff2MessageParser.prototype.createXmlRepresentationOfEndTagPart = /**
* the xml used for end tag in the message.
* Not used here, because content is child of start tag.
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @return {?}
*/
function (part, rootElem) {
// not used
return null;
};
/**
* the xml used for empty tag in the message.
* Returns an empty ph-Element.
* e.g. <ph id="3" equiv="TAG_IMG" type="image" disp="<img/>"/>
* @param part part
* @param rootElem rootElem
* @param id id number in xliff2
*/
/**
* the xml used for empty tag in the message.
* Returns an empty ph-Element.
* e.g. <ph id="3" equiv="TAG_IMG" type="image" disp="<img/>"/>
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @param {?} id id number in xliff2
* @return {?}
*/
Xliff2MessageParser.prototype.createXmlRepresentationOfEmptyTagPart = /**
* the xml used for empty tag in the message.
* Returns an empty ph-Element.
* e.g. <ph id="3" equiv="TAG_IMG" type="image" disp="<img/>"/>
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @param {?} id id number in xliff2
* @return {?}
*/
function (part, rootElem, id) {
/** @type {?} */
var tagMapping = new TagMapping();
/** @type {?} */
var phElem = rootElem.ownerDocument.createElement('ph');
/** @type {?} */
var tagName = part.tagName();
/** @type {?} */
var equiv = tagMapping.getEmptyTagPlaceholderName(tagName, part.idCounter());
/** @type {?} */
var disp = '<' + tagName + '/>';
phElem.setAttribute('id', id.toString(10));
phElem.setAttribute('equiv', equiv);
phElem.setAttribute('type', this.getTypeForTag(tagName));
phElem.setAttribute('disp', disp);
return phElem;
};
/**
* @private
* @param {?} tag
* @return {?}
*/
Xliff2MessageParser.prototype.getTypeForTag = /**
* @private
* @param {?} tag
* @return {?}
*/
function (tag) {
switch (tag.toLowerCase()) {
case 'br':
case 'b':
case 'i':
case 'u':
return 'fmt';
case 'img':
return 'image';
case 'a':
return 'link';
default:
return 'other';
}
};
/**
* the xml used for placeholder in the message.
* Returns e.g. <ph id="1" equiv="INTERPOLATION_1" disp="{{total()}}"/>
* @param part part
* @param rootElem rootElem
* @param id id number in xliff2
*/
/**
* the xml used for placeholder in the message.
* Returns e.g. <ph id="1" equiv="INTERPOLATION_1" disp="{{total()}}"/>
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @param {?} id id number in xliff2
* @return {?}
*/
Xliff2MessageParser.prototype.createXmlRepresentationOfPlaceholderPart = /**
* the xml used for placeholder in the message.
* Returns e.g. <ph id="1" equiv="INTERPOLATION_1" disp="{{total()}}"/>
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @param {?} id id number in xliff2
* @return {?}
*/
function (part, rootElem, id) {
/** @type {?} */
var phElem = rootElem.ownerDocument.createElement('ph');
/** @type {?} */
var equivAttrib = 'INTERPOLATION';
if (part.index() > 0) {
equivAttrib = 'INTERPOLATION_' + part.index().toString(10);
}
phElem.setAttribute('id', id.toString(10));
phElem.setAttribute('equiv', equivAttrib);
/** @type {?} */
var disp = part.disp();
if (disp) {
phElem.setAttribute('disp', disp);
}
return phElem;
};
/**
* the xml used for icu message refs in the message.
* @param part part
* @param rootElem rootElem
*/
/**
* the xml used for icu message refs in the message.
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @return {?}
*/
Xliff2MessageParser.prototype.createXmlRepresentationOfICUMessageRefPart = /**
* the xml used for icu message refs in the message.
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @return {?}
*/
function (part, rootElem) {
/** @type {?} */
var phElem = rootElem.ownerDocument.createElement('ph');
/** @type {?} */
var equivAttrib = 'ICU';
if (part.index() > 0) {
equivAttrib = 'ICU_' + part.index().toString(10);
}
phElem.setAttribute('id', part.index().toString(10));
phElem.setAttribute('equiv', equivAttrib);
/** @type {?} */
var disp = part.disp();
if (disp) {
phElem.setAttribute('disp', disp);
}
return phElem;
};
return Xliff2MessageParser;
}(AbstractMessageParser));
/**
* Created by roobm on 10.05.2017.
* A message parser for XLIFF 2.0
*/
export { Xliff2MessageParser };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieGxpZmYyLW1lc3NhZ2UtcGFyc2VyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5neC1pMThuc3VwcG9ydC9uZ3gtaTE4bnN1cHBvcnQtbGliLyIsInNvdXJjZXMiOlsiaW1wbC94bGlmZjItbWVzc2FnZS1wYXJzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQU1oRSxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDOzs7OztBQU96Qzs7Ozs7SUFBeUMsK0NBQXFCO0lBQTlEOztJQStRQSxDQUFDO0lBN1FHOzs7Ozs7T0FNRzs7Ozs7Ozs7O0lBQ08saURBQW1COzs7Ozs7OztJQUE3QixVQUE4QixXQUFvQixFQUFFLE9BQXNCOztZQUNoRSxPQUFPLEdBQUcsV0FBVyxDQUFDLE9BQU87UUFDbkMsSUFBSSxPQUFPLEtBQUssSUFBSSxFQUFFOzs7Ozs7Ozs7Ozs7O2dCQVlkLGVBQWUsR0FBRyxLQUFLOztnQkFDdkIsS0FBSyxHQUFHLEtBQUs7O2dCQUNiLFVBQVUsR0FBRyxLQUFLOztnQkFDaEIsS0FBSyxHQUFHLFdBQVcsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDOztnQkFDekMsSUFBSSxHQUFHLFdBQVcsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDOztnQkFDekMsV0FBVyxHQUFHLElBQUk7O2dCQUNsQixLQUFLLEdBQUcsQ0FBQzs7Z0JBQ1QsWUFBWSxHQUFHLElBQUk7WUFDdkIsSUFBSSxDQUFDLEtBQUssRUFBRTtnQkFDUixvQ0FBb0M7Z0JBQ3BDLEtBQUssR0FBRyxJQUFJLENBQUM7Z0JBQ2IsV0FBVyxHQUFHLFdBQVcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzdDLEtBQUssR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQzthQUM1QztpQkFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQ2hDLG9DQUFvQztnQkFDcEMsS0FBSyxHQUFHLElBQUksQ0FBQztnQkFDYixJQUFJLEtBQUssS0FBSyxLQUFLLEVBQUU7b0JBQ2pCLFdBQVcsR0FBRyxHQUFHLENBQUM7aUJBQ3JCO3FCQUFNO29CQUNILFdBQVcsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztpQkFDaEQ7Z0JBQ0QsS0FBSyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2FBQzVDO2lCQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsRUFBRTtnQkFDMUMsZUFBZSxHQUFHLElBQUksQ0FBQztnQkFDdkIsSUFBSSxLQUFLLEtBQUssZUFBZSxFQUFFO29CQUMzQixXQUFXLEdBQUcsR0FBRyxDQUFDO2lCQUNyQjtxQkFBTTtvQkFDSCxXQUFXLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztpQkFDMUQ7Z0JBQ0QsS0FBSyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2FBQzVDO2lCQUFNLElBQUksSUFBSSxVQUFVLEVBQUUsQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDMUQsVUFBVSxHQUFHLElBQUksQ0FBQztnQkFDbEIsWUFBWSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUMscUNBQXFDLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDaEY7aUJBQU07Z0JBQ0gsT0FBTyxJQUFJLENBQUM7YUFDZjtZQUNELElBQUksZUFBZSxFQUFFO2dCQUNqQixPQUFPLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQzthQUN2QztpQkFBTSxJQUFJLEtBQUssRUFBRTtnQkFDZCxPQUFPLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO2FBQ3pDO2lCQUFNLElBQUksVUFBVSxFQUFFO2dCQUNuQixPQUFPLENBQUMsV0FBVyxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsb0JBQW9CLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQzthQUN2RTtTQUNKO2FBQU0sSUFBSSxPQUFPLEtBQUssSUFBSSxFQUFFOzs7O2dCQUduQixlQUFlLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFdBQVcsQ0FBQztZQUM5RCxJQUFJLGVBQWUsRUFBRTtnQkFDakIsT0FBTyxDQUFDLFdBQVcsQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQzNHO1NBQ0o7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQ7Ozs7O09BS0c7Ozs7Ozs7OztJQUNPLCtDQUFpQjs7Ozs7Ozs7SUFBM0IsVUFBNEIsV0FBb0IsRUFBRSxPQUFzQjs7WUFDOUQsT0FBTyxHQUFHLFdBQVcsQ0FBQyxPQUFPO1FBQ25DLElBQUksT0FBTyxLQUFLLElBQUksRUFBRTs7OztnQkFHWixlQUFlLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFdBQVcsQ0FBQztZQUM5RCxJQUFJLGVBQWUsRUFBRTtnQkFDakIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQzthQUN0QztZQUNELE9BQU87U0FDVjtJQUNMLENBQUM7Ozs7OztJQUVPLGtEQUFvQjs7Ozs7SUFBNUIsVUFBNkIsTUFBZTs7WUFDcEMsU0FBUyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDO1FBQ2hELElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUMzQixTQUFTLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN0QztRQUNELElBQUksU0FBUyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUN6QixTQUFTLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztTQUM1RDtRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ3JCLENBQUM7SUFFRDs7Ozs7T0FLRzs7Ozs7Ozs7O0lBQ08sd0RBQTBCOzs7Ozs7OztJQUFwQyxVQUFxQyxPQUFzQixFQUFFLFFBQWlCO1FBQTlFLGlCQXdDQzs7WUF2Q1MsS0FBSyxHQUFHLENBQUMsRUFBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUMsQ0FBQzs7WUFDaEQsRUFBRSxHQUFHLENBQUM7UUFDVixPQUFPLENBQUMsS0FBSyxFQUFFLENBQUMsT0FBTzs7OztRQUFDLFVBQUMsSUFBSTtZQUN6QixRQUFRLElBQUksQ0FBQyxJQUFJLEVBQUU7Z0JBQ2YsS0FBSyxxQkFBcUIsQ0FBQyxJQUFJO29CQUMzQixLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUN2QyxLQUFJLENBQUMsaUNBQWlDLENBQUMsbUJBQXdCLElBQUksRUFBQSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7b0JBQ3BGLE1BQU07Z0JBQ1YsS0FBSyxxQkFBcUIsQ0FBQyxXQUFXO29CQUNsQyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUN2QyxLQUFJLENBQUMsd0NBQXdDLENBQUMsbUJBQStCLElBQUksRUFBQSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7b0JBQ3hHLE1BQU07Z0JBQ1YsS0FBSyxxQkFBcUIsQ0FBQyxlQUFlO29CQUN0QyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUN2QyxLQUFJLENBQUMsMENBQTBDLENBQUMsbUJBQWlDLElBQUksRUFBQSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7b0JBQ3RHLE1BQU07Z0JBQ1YsS0FBSyxxQkFBcUIsQ0FBQyxTQUFTOzt3QkFDMUIsVUFBVSxHQUFHLEtBQUksQ0FBQyxxQ0FBcUMsQ0FBQyxtQkFBNEIsSUFBSSxFQUFBLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxDQUFDO29CQUMvRyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO29CQUN4RCxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUMsT0FBTyxFQUFFLG1CQUFVLFVBQVUsRUFBQSxFQUFFLE9BQU8sRUFBRSxDQUFDLG1CQUE0QixJQUFJLEVBQUEsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFDLENBQUMsQ0FBQztvQkFDbkcsTUFBTTtnQkFDVixLQUFLLHFCQUFxQixDQUFDLE9BQU87O3dCQUN4QixZQUFZLEdBQUcsQ0FBQyxtQkFBMEIsSUFBSSxFQUFBLENBQUMsQ0FBQyxPQUFPLEVBQUU7b0JBQy9ELElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsT0FBTyxLQUFLLFlBQVksRUFBRTt3QkFDdkUsd0JBQXdCO3dCQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixHQUFHLFlBQVksQ0FBQyxDQUFDO3FCQUMzRDtvQkFDRCxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7b0JBQ1osTUFBTTtnQkFDVixLQUFLLHFCQUFxQixDQUFDLFNBQVM7O3dCQUMxQixZQUFZLEdBQUcsS0FBSSxDQUFDLHFDQUFxQyxDQUFDLG1CQUE0QixJQUFJLEVBQUEsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUM7b0JBQ2pILEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBQzFELE1BQU07YUFDYjtRQUNMLENBQUMsRUFBQyxDQUFDO1FBQ0gsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUNwQiw2QkFBNkI7WUFDN0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUMzRTtJQUNMLENBQUM7SUFFRDs7Ozs7Ozs7T0FRRzs7Ozs7Ozs7Ozs7O0lBQ08sbUVBQXFDOzs7Ozs7Ozs7OztJQUEvQyxVQUFnRCxJQUErQixFQUFFLFFBQWlCLEVBQUUsRUFBVTs7WUFDcEcsVUFBVSxHQUFHLElBQUksVUFBVSxFQUFFOztZQUM3QixNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDOztZQUNuRCxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRTs7WUFDeEIsVUFBVSxHQUFHLFVBQVUsQ0FBQywwQkFBMEIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDOztZQUM3RSxRQUFRLEdBQUcsVUFBVSxDQUFDLDBCQUEwQixDQUFDLE9BQU8sQ0FBQzs7WUFDekQsU0FBUyxHQUFHLEdBQUcsR0FBRyxPQUFPLEdBQUcsR0FBRzs7WUFDL0IsT0FBTyxHQUFHLElBQUksR0FBRyxPQUFPLEdBQUcsR0FBRztRQUNwQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0MsTUFBTSxDQUFDLFlBQVksQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDOUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDMUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sQ0FBQyxZQUFZLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3hDLE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7Ozs7T0FLRzs7Ozs7Ozs7O0lBQ08saUVBQW1DOzs7Ozs7OztJQUE3QyxVQUE4QyxJQUE2QixFQUFFLFFBQWlCO1FBQzFGLFdBQVc7UUFDWCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRzs7Ozs7Ozs7Ozs7SUFDTyxtRUFBcUM7Ozs7Ozs7Ozs7SUFBL0MsVUFBZ0QsSUFBK0IsRUFBRSxRQUFpQixFQUFFLEVBQVU7O1lBQ3BHLFVBQVUsR0FBRyxJQUFJLFVBQVUsRUFBRTs7WUFDN0IsTUFBTSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQzs7WUFDbkQsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUU7O1lBQ3hCLEtBQUssR0FBRyxVQUFVLENBQUMsMEJBQTBCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQzs7WUFDeEUsSUFBSSxHQUFHLEdBQUcsR0FBRyxPQUFPLEdBQUcsSUFBSTtRQUNqQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0MsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDcEMsTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2xDLE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7Ozs7OztJQUVPLDJDQUFhOzs7OztJQUFyQixVQUFzQixHQUFXO1FBQzdCLFFBQVEsR0FBRyxDQUFDLFdBQVcsRUFBRSxFQUFFO1lBQ3ZCLEtBQUssSUFBSSxDQUFDO1lBQ1YsS0FBSyxHQUFHLENBQUM7WUFDVCxLQUFLLEdBQUcsQ0FBQztZQUNULEtBQUssR0FBRztnQkFDSixPQUFPLEtBQUssQ0FBQztZQUNqQixLQUFLLEtBQUs7Z0JBQ04sT0FBTyxPQUFPLENBQUM7WUFDbkIsS0FBSyxHQUFHO2dCQUNKLE9BQU8sTUFBTSxDQUFDO1lBQ2xCO2dCQUNJLE9BQU8sT0FBTyxDQUFDO1NBQ3RCO0lBQ0wsQ0FBQztJQUVEOzs7Ozs7T0FNRzs7Ozs7Ozs7OztJQUNPLHNFQUF3Qzs7Ozs7Ozs7O0lBQWxELFVBQW1ELElBQWtDLEVBQUUsUUFBaUIsRUFBRSxFQUFVOztZQUMxRyxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDOztZQUNyRCxXQUFXLEdBQUcsZUFBZTtRQUNqQyxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLEVBQUU7WUFDbEIsV0FBVyxHQUFHLGdCQUFnQixHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDOUQ7UUFDRCxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0MsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUM7O1lBQ3BDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQ3hCLElBQUksSUFBSSxFQUFFO1lBQ04sTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDckM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNsQixDQUFDO0lBRUQ7Ozs7T0FJRzs7Ozs7Ozs7SUFDTyx3RUFBMEM7Ozs7Ozs7SUFBcEQsVUFBcUQsSUFBb0MsRUFBRSxRQUFpQjs7WUFDbEcsTUFBTSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQzs7WUFDckQsV0FBVyxHQUFHLEtBQUs7UUFDdkIsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO1lBQ2xCLFdBQVcsR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUNwRDtRQUNELE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNyRCxNQUFNLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQzs7WUFDcEMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUU7UUFDeEIsSUFBSSxJQUFJLEVBQUU7WUFDTixNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztTQUNyQztRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7SUFFTCwwQkFBQztBQUFELENBQUMsQUEvUUQsQ0FBeUMscUJBQXFCLEdBK1E3RCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7QWJzdHJhY3RNZXNzYWdlUGFyc2VyfSBmcm9tICcuL2Fic3RyYWN0LW1lc3NhZ2UtcGFyc2VyJztcclxuaW1wb3J0IHtQYXJzZWRNZXNzYWdlfSBmcm9tICcuL3BhcnNlZC1tZXNzYWdlJztcclxuaW1wb3J0IHtQYXJzZWRNZXNzYWdlUGFydFN0YXJ0VGFnfSBmcm9tICcuL3BhcnNlZC1tZXNzYWdlLXBhcnQtc3RhcnQtdGFnJztcclxuaW1wb3J0IHtQYXJzZWRNZXNzYWdlUGFydEVuZFRhZ30gZnJvbSAnLi9wYXJzZWQtbWVzc2FnZS1wYXJ0LWVuZC10YWcnO1xyXG5pbXBvcnQge1BhcnNlZE1lc3NhZ2VQYXJ0UGxhY2Vob2xkZXJ9IGZyb20gJy4vcGFyc2VkLW1lc3NhZ2UtcGFydC1wbGFjZWhvbGRlcic7XHJcbmltcG9ydCB7UGFyc2VkTWVzc2FnZVBhcnRUZXh0fSBmcm9tICcuL3BhcnNlZC1tZXNzYWdlLXBhcnQtdGV4dCc7XHJcbmltcG9ydCB7UGFyc2VkTWVzc2FnZVBhcnRUeXBlfSBmcm9tICcuL3BhcnNlZC1tZXNzYWdlLXBhcnQnO1xyXG5pbXBvcnQge1RhZ01hcHBpbmd9IGZyb20gJy4vdGFnLW1hcHBpbmcnO1xyXG5pbXBvcnQge1BhcnNlZE1lc3NhZ2VQYXJ0RW1wdHlUYWd9IGZyb20gJy4vcGFyc2VkLW1lc3NhZ2UtcGFydC1lbXB0eS10YWcnO1xyXG5pbXBvcnQge1BhcnNlZE1lc3NhZ2VQYXJ0SUNVTWVzc2FnZVJlZn0gZnJvbSAnLi9wYXJzZWQtbWVzc2FnZS1wYXJ0LWljdS1tZXNzYWdlLXJlZic7XHJcbi8qKlxyXG4gKiBDcmVhdGVkIGJ5IHJvb2JtIG9uIDEwLjA1LjIwMTcuXHJcbiAqIEEgbWVzc2FnZSBwYXJzZXIgZm9yIFhMSUZGIDIuMFxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFhsaWZmMk1lc3NhZ2VQYXJzZXIgZXh0ZW5kcyBBYnN0cmFjdE1lc3NhZ2VQYXJzZXIge1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGFuZGxlIHRoaXMgZWxlbWVudCBub2RlLlxyXG4gICAgICogVGhpcyBpcyBjYWxsZWQgYmVmb3JlIHRoZSBjaGlsZHJlbiBhcmUgZG9uZS5cclxuICAgICAqIEBwYXJhbSBlbGVtZW50Tm9kZSBlbGVtZW50Tm9kZVxyXG4gICAgICogQHBhcmFtIG1lc3NhZ2UgbWVzc2FnZSB0byBiZSBhbHRlcmVkXHJcbiAgICAgKiBAcmV0dXJuIHRydWUsIGlmIGNoaWxkcmVuIHNob3VsZCBiZSBwcm9jZXNzZWQgdG9vLCBmYWxzZSBvdGhlcndpc2UgKGNoaWxkcmVuIGlnbm9yZWQgdGhlbilcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHByb2Nlc3NTdGFydEVsZW1lbnQoZWxlbWVudE5vZGU6IEVsZW1lbnQsIG1lc3NhZ2U6IFBhcnNlZE1lc3NhZ2UpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCB0YWdOYW1lID0gZWxlbWVudE5vZGUudGFnTmFtZTtcclxuICAgICAgICBpZiAodGFnTmFtZSA9PT0gJ3BoJykge1xyXG4gICAgICAgICAgICAvLyBwbGFjZWhvbGRlciBhcmUgbGlrZSA8cGggaWQ9XCIwXCIgZXF1aXY9XCJJTlRFUlBPTEFUSU9OXCIgZGlzcD1cInt7bnVtYmVyKCl9fVwiLz5cclxuICAgICAgICAgICAgLy8gVGhleSBjb250YWluIHRoZSBpZCBhbmQgYWxzbyBhIG5hbWUgKG51bWJlciBpbiB0aGUgZXhhbXBsZSlcclxuICAgICAgICAgICAgLy8gVE9ETyBtYWtlIHNvbWUgdXNlIG9mIHRoZSBuYW1lIChidXQgaXQgaXMgbm90IGF2YWlsYWJsZSBpbiBYTElGRiAxLjIpXHJcbiAgICAgICAgICAgIC8vIElDVSBtZXNzYWdlIGFyZSBoYW5kbGVkIHdpdGggdGhlIHNhbWUgdGFnXHJcbiAgICAgICAgICAgIC8vIEJlZm9yZSA0LjMuMiB0aGV5IGRpZCBub3QgaGF2ZSBhbiBlcXVpdiBhbmQgZGlzcCAoQnVnICMxNzM0NCk6XHJcbiAgICAgICAgICAgIC8vIGUuZy4gPHBoIGlkPVwiMFwiLz5cclxuICAgICAgICAgICAgLy8gQmVnaW5uaW5nIHdpdGggNC4zLjIgdGhleSBkbyBoYXZlIGFuIGVxdWl2IElDVSBhbmQgZGlzcDpcclxuICAgICAgICAgICAgLy8gZS5nLiA8cGggaWQ9XCIwXCIgZXF1aXY9XCJJQ1VcIiBkaXNwPVwie2NvdW50LCBwbHVyYWwsID0wIHsuLi59ID0xIHsuLi59IG90aGVyIHsuLi59fVwiLz5cclxuICAgICAgICAgICAgLy8gYW5kIGVtcHR5IHRhZ3MgaGF2ZSBlcXVpdiBvdGhlciB0aGVuIElOVEVSUE9MQVRJT046XHJcbiAgICAgICAgICAgIC8vIGUuZy4gPHBoIGlkPVwiM1wiIGVxdWl2PVwiVEFHX0lNR1wiIHR5cGU9XCJpbWFnZVwiIGRpc3A9XCImbHQ7aW1nLz5cIi8+XHJcbiAgICAgICAgICAgIC8vIG9yIDxwaCBlcXVpdj1cIkxJTkVfQlJFQUtcIiB0eXBlPVwibGJcIiBkaXNwPVwiJmx0O2JyLz5cIi8+XHJcbiAgICAgICAgICAgIGxldCBpc0ludGVycG9sYXRpb24gPSBmYWxzZTtcclxuICAgICAgICAgICAgbGV0IGlzSUNVID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGxldCBpc0VtcHR5VGFnID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGNvbnN0IGVxdWl2ID0gZWxlbWVudE5vZGUuZ2V0QXR0cmlidXRlKCdlcXVpdicpO1xyXG4gICAgICAgICAgICBjb25zdCBkaXNwID0gZWxlbWVudE5vZGUuZ2V0QXR0cmlidXRlKCdkaXNwJyk7XHJcbiAgICAgICAgICAgIGxldCBpbmRleFN0cmluZyA9IG51bGw7XHJcbiAgICAgICAgICAgIGxldCBpbmRleCA9IDA7XHJcbiAgICAgICAgICAgIGxldCBlbXB0eVRhZ05hbWUgPSBudWxsO1xyXG4gICAgICAgICAgICBpZiAoIWVxdWl2KSB7XHJcbiAgICAgICAgICAgICAgICAvLyBvbGQgSUNVIHN5bnRheCwgZml4ZWQgd2l0aCAjMTczNDRcclxuICAgICAgICAgICAgICAgIGlzSUNVID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIGluZGV4U3RyaW5nID0gZWxlbWVudE5vZGUuZ2V0QXR0cmlidXRlKCdpZCcpO1xyXG4gICAgICAgICAgICAgICAgaW5kZXggPSBOdW1iZXIucGFyc2VJbnQoaW5kZXhTdHJpbmcsIDEwKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChlcXVpdi5zdGFydHNXaXRoKCdJQ1UnKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gbmV3IElDVSBzeW50YXgsIGZpeGVkIHdpdGggIzE3MzQ0XHJcbiAgICAgICAgICAgICAgICBpc0lDVSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICBpZiAoZXF1aXYgPT09ICdJQ1UnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaW5kZXhTdHJpbmcgPSAnMCc7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGluZGV4U3RyaW5nID0gZXF1aXYuc3Vic3RyaW5nKCdJQ1VfJy5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaW5kZXggPSBOdW1iZXIucGFyc2VJbnQoaW5kZXhTdHJpbmcsIDEwKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChlcXVpdi5zdGFydHNXaXRoKCdJTlRFUlBPTEFUSU9OJykpIHtcclxuICAgICAgICAgICAgICAgIGlzSW50ZXJwb2xhdGlvbiA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICBpZiAoZXF1aXYgPT09ICdJTlRFUlBPTEFUSU9OJykge1xyXG4gICAgICAgICAgICAgICAgICAgIGluZGV4U3RyaW5nID0gJzAnO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpbmRleFN0cmluZyA9IGVxdWl2LnN1YnN0cmluZygnSU5URVJQT0xBVElPTl8nLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpbmRleCA9IE51bWJlci5wYXJzZUludChpbmRleFN0cmluZywgMTApO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG5ldyBUYWdNYXBwaW5nKCkuaXNFbXB0eVRhZ1BsYWNlaG9sZGVyTmFtZShlcXVpdikpIHtcclxuICAgICAgICAgICAgICAgIGlzRW1wdHlUYWcgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgZW1wdHlUYWdOYW1lID0gbmV3IFRhZ01hcHBpbmcoKS5nZXRUYWduYW1lRnJvbUVtcHR5VGFnUGxhY2Vob2xkZXJOYW1lKGVxdWl2KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChpc0ludGVycG9sYXRpb24pIHtcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuYWRkUGxhY2Vob2xkZXIoaW5kZXgsIGRpc3ApO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzSUNVKSB7XHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmFkZElDVU1lc3NhZ2VSZWYoaW5kZXgsIGRpc3ApO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzRW1wdHlUYWcpIHtcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuYWRkRW1wdHlUYWcoZW1wdHlUYWdOYW1lLCB0aGlzLnBhcnNlSWRDb3VudEZyb21OYW1lKGVxdWl2KSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2UgaWYgKHRhZ05hbWUgPT09ICdwYycpIHtcclxuICAgICAgICAgICAgLy8gcGMgZXhhbXBsZTogPHBjIGlkPVwiMFwiIGVxdWl2U3RhcnQ9XCJTVEFSVF9CT0xEX1RFWFRcIiBlcXVpdkVuZD1cIkNMT1NFX0JPTERfVEVYVFwiIHR5cGU9XCJmbXRcIlxyXG4gICAgICAgICAgICAvLyBkaXNwU3RhcnQ9XCImbHQ7YiZndDtcIiBkaXNwRW5kPVwiJmx0Oy9iJmd0O1wiPklNUE9SVEFOVDwvcGM+XHJcbiAgICAgICAgICAgIGNvbnN0IGVtYmVkZGVkVGFnTmFtZSA9IHRoaXMudGFnTmFtZUZyb21QQ0VsZW1lbnQoZWxlbWVudE5vZGUpO1xyXG4gICAgICAgICAgICBpZiAoZW1iZWRkZWRUYWdOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmFkZFN0YXJ0VGFnKGVtYmVkZGVkVGFnTmFtZSwgdGhpcy5wYXJzZUlkQ291bnRGcm9tTmFtZShlbGVtZW50Tm9kZS5nZXRBdHRyaWJ1dGUoJ2VxdWl2U3RhcnQnKSkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGFuZGxlIGVuZCBvZiB0aGlzIGVsZW1lbnQgbm9kZS5cclxuICAgICAqIFRoaXMgaXMgY2FsbGVkIGFmdGVyIGFsbCBjaGlsZHJlbiBhcmUgcHJvY2Vzc2VkLlxyXG4gICAgICogQHBhcmFtIGVsZW1lbnROb2RlIGVsZW1lbnROb2RlXHJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBtZXNzYWdlIHRvIGJlIGFsdGVyZWRcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHByb2Nlc3NFbmRFbGVtZW50KGVsZW1lbnROb2RlOiBFbGVtZW50LCBtZXNzYWdlOiBQYXJzZWRNZXNzYWdlKSB7XHJcbiAgICAgICAgY29uc3QgdGFnTmFtZSA9IGVsZW1lbnROb2RlLnRhZ05hbWU7XHJcbiAgICAgICAgaWYgKHRhZ05hbWUgPT09ICdwYycpIHtcclxuICAgICAgICAgICAgLy8gcGMgZXhhbXBsZTogPHBjIGlkPVwiMFwiIGVxdWl2U3RhcnQ9XCJTVEFSVF9CT0xEX1RFWFRcIiBlcXVpdkVuZD1cIkNMT1NFX0JPTERfVEVYVFwiIHR5cGU9XCJmbXRcIlxyXG4gICAgICAgICAgICAvLyBkaXNwU3RhcnQ9XCImbHQ7YiZndDtcIiBkaXNwRW5kPVwiJmx0Oy9iJmd0O1wiPklNUE9SVEFOVDwvcGM+XHJcbiAgICAgICAgICAgIGNvbnN0IGVtYmVkZGVkVGFnTmFtZSA9IHRoaXMudGFnTmFtZUZyb21QQ0VsZW1lbnQoZWxlbWVudE5vZGUpO1xyXG4gICAgICAgICAgICBpZiAoZW1iZWRkZWRUYWdOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmFkZEVuZFRhZyhlbWJlZGRlZFRhZ05hbWUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSB0YWdOYW1lRnJvbVBDRWxlbWVudChwY05vZGU6IEVsZW1lbnQpOiBzdHJpbmcge1xyXG4gICAgICAgIGxldCBkaXNwU3RhcnQgPSBwY05vZGUuZ2V0QXR0cmlidXRlKCdkaXNwU3RhcnQnKTtcclxuICAgICAgICBpZiAoZGlzcFN0YXJ0LnN0YXJ0c1dpdGgoJzwnKSkge1xyXG4gICAgICAgICAgICBkaXNwU3RhcnQgPSBkaXNwU3RhcnQuc3Vic3RyaW5nKDEpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoZGlzcFN0YXJ0LmVuZHNXaXRoKCc+JykpIHtcclxuICAgICAgICAgICAgZGlzcFN0YXJ0ID0gZGlzcFN0YXJ0LnN1YnN0cmluZygwLCBkaXNwU3RhcnQubGVuZ3RoIC0gMSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBkaXNwU3RhcnQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiByZWltcGxlbWVudGVkIGhlcmUsIGJlY2F1c2UgWExJRkYgMi4wIHVzZXMgYSBkZWVwZXIgeG1sIG1vZGVsLlxyXG4gICAgICogU28gd2UgY2Fubm90IHNpbXBseSByZXBsYWNlIHRoZSBtZXNzYWdlIHBhcnRzIGJ5IHhtbCBwYXJ0cy5cclxuICAgICAqIEBwYXJhbSBtZXNzYWdlIG1lc3NhZ2VcclxuICAgICAqIEBwYXJhbSByb290RWxlbSByb290RWxlbVxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgYWRkWG1sUmVwcmVzZW50YXRpb25Ub1Jvb3QobWVzc2FnZTogUGFyc2VkTWVzc2FnZSwgcm9vdEVsZW06IEVsZW1lbnQpIHtcclxuICAgICAgICBjb25zdCBzdGFjayA9IFt7ZWxlbWVudDogcm9vdEVsZW0sIHRhZ05hbWU6ICdyb290J31dO1xyXG4gICAgICAgIGxldCBpZCA9IDA7XHJcbiAgICAgICAgbWVzc2FnZS5wYXJ0cygpLmZvckVhY2goKHBhcnQpID0+IHtcclxuICAgICAgICAgICAgc3dpdGNoIChwYXJ0LnR5cGUpIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgUGFyc2VkTWVzc2FnZVBhcnRUeXBlLlRFWFQ6XHJcbiAgICAgICAgICAgICAgICAgICAgc3RhY2tbc3RhY2subGVuZ3RoIC0gMV0uZWxlbWVudC5hcHBlbmRDaGlsZChcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVYbWxSZXByZXNlbnRhdGlvbk9mVGV4dFBhcnQoPFBhcnNlZE1lc3NhZ2VQYXJ0VGV4dD4gcGFydCwgcm9vdEVsZW0pKTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgUGFyc2VkTWVzc2FnZVBhcnRUeXBlLlBMQUNFSE9MREVSOlxyXG4gICAgICAgICAgICAgICAgICAgIHN0YWNrW3N0YWNrLmxlbmd0aCAtIDFdLmVsZW1lbnQuYXBwZW5kQ2hpbGQoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlWG1sUmVwcmVzZW50YXRpb25PZlBsYWNlaG9sZGVyUGFydCg8UGFyc2VkTWVzc2FnZVBhcnRQbGFjZWhvbGRlcj4gcGFydCwgcm9vdEVsZW0sIGlkKyspKTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgUGFyc2VkTWVzc2FnZVBhcnRUeXBlLklDVV9NRVNTQUdFX1JFRjpcclxuICAgICAgICAgICAgICAgICAgICBzdGFja1tzdGFjay5sZW5ndGggLSAxXS5lbGVtZW50LmFwcGVuZENoaWxkKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZVhtbFJlcHJlc2VudGF0aW9uT2ZJQ1VNZXNzYWdlUmVmUGFydCg8UGFyc2VkTWVzc2FnZVBhcnRJQ1VNZXNzYWdlUmVmPiBwYXJ0LCByb290RWxlbSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBQYXJzZWRNZXNzYWdlUGFydFR5cGUuU1RBUlRfVEFHOlxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld1RhZ0VsZW0gPSB0aGlzLmNyZWF0ZVhtbFJlcHJlc2VudGF0aW9uT2ZTdGFydFRhZ1BhcnQoPFBhcnNlZE1lc3NhZ2VQYXJ0U3RhcnRUYWc+IHBhcnQsIHJvb3RFbGVtLCBpZCsrKTtcclxuICAgICAgICAgICAgICAgICAgICBzdGFja1tzdGFjay5sZW5ndGggLSAxXS5lbGVtZW50LmFwcGVuZENoaWxkKG5ld1RhZ0VsZW0pO1xyXG4gICAgICAgICAgICAgICAgICAgIHN0YWNrLnB1c2goe2VsZW1lbnQ6IDxFbGVtZW50PiBuZXdUYWdFbGVtLCB0YWdOYW1lOiAoPFBhcnNlZE1lc3NhZ2VQYXJ0U3RhcnRUYWc+IHBhcnQpLnRhZ05hbWUoKX0pO1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBQYXJzZWRNZXNzYWdlUGFydFR5cGUuRU5EX1RBRzpcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjbG9zZVRhZ05hbWUgPSAoPFBhcnNlZE1lc3NhZ2VQYXJ0RW5kVGFnPiBwYXJ0KS50YWdOYW1lKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA8PSAxIHx8IHN0YWNrW3N0YWNrLmxlbmd0aCAtIDFdLnRhZ05hbWUgIT09IGNsb3NlVGFnTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBvb3BzLCBub3Qgd2VsbCBmb3JtZWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bmV4cGVjdGVkIGNsb3NlIHRhZyAnICsgY2xvc2VUYWdOYW1lKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgc3RhY2sucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIFBhcnNlZE1lc3NhZ2VQYXJ0VHlwZS5FTVBUWV9UQUc6XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW1wdHlUYWdFbGVtID0gdGhpcy5jcmVhdGVYbWxSZXByZXNlbnRhdGlvbk9mRW1wdHlUYWdQYXJ0KDxQYXJzZWRNZXNzYWdlUGFydEVtcHR5VGFnPiBwYXJ0LCByb290RWxlbSwgaWQrKyk7XHJcbiAgICAgICAgICAgICAgICAgICAgc3RhY2tbc3RhY2subGVuZ3RoIC0gMV0uZWxlbWVudC5hcHBlbmRDaGlsZChlbXB0eVRhZ0VsZW0pO1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCAhPT0gMSkge1xyXG4gICAgICAgICAgICAvLyBvb3BzLCBub3Qgd2VsbCBjbG9zZWQgdGFnc1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgY2xvc2UgdGFnICcgKyBzdGFja1tzdGFjay5sZW5ndGggLSAxXS50YWdOYW1lKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiB0aGUgeG1sIHVzZWQgZm9yIHN0YXJ0IHRhZyBpbiB0aGUgbWVzc2FnZS5cclxuICAgICAqIFJldHVybnMgYW4gZW1wdHkgcGMtRWxlbWVudC5cclxuICAgICAqIGUuZy4gPHBjIGlkPVwiMFwiIGVxdWl2U3RhcnQ9XCJTVEFSVF9CT0xEX1RFWFRcIiBlcXVpdkVuZD1cIkNMT1NFX0JPTERfVEVYVFwiIHR5cGU9XCJmbXRcIiBkaXNwU3RhcnQ9XCImbHQ7YiZndDtcIiBkaXNwRW5kPVwiJmx0Oy9iJmd0O1wiPlxyXG4gICAgICogVGV4dCBjb250ZW50IHdpbGwgYmUgYWRkZWQgbGF0ZXIuXHJcbiAgICAgKiBAcGFyYW0gcGFydCBwYXJ0XHJcbiAgICAgKiBAcGFyYW0gcm9vdEVsZW0gcm9vdEVsZW1cclxuICAgICAqIEBwYXJhbSBpZCBpZCBudW1iZXIgaW4geGxpZmYyXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBjcmVhdGVYbWxSZXByZXNlbnRhdGlvbk9mU3RhcnRUYWdQYXJ0KHBhcnQ6IFBhcnNlZE1lc3NhZ2VQYXJ0U3RhcnRUYWcsIHJvb3RFbGVtOiBFbGVtZW50LCBpZDogbnVtYmVyKTogTm9kZSB7XHJcbiAgICAgICAgY29uc3QgdGFnTWFwcGluZyA9IG5ldyBUYWdNYXBwaW5nKCk7XHJcbiAgICAgICAgY29uc3QgcGNFbGVtID0gcm9vdEVsZW0ub3duZXJEb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwYycpO1xyXG4gICAgICAgIGNvbnN0IHRhZ05hbWUgPSBwYXJ0LnRhZ05hbWUoKTtcclxuICAgICAgICBjb25zdCBlcXVpdlN0YXJ0ID0gdGFnTWFwcGluZy5nZXRTdGFydFRhZ1BsYWNlaG9sZGVyTmFtZSh0YWdOYW1lLCBwYXJ0LmlkQ291bnRlcigpKTtcclxuICAgICAgICBjb25zdCBlcXVpdkVuZCA9IHRhZ01hcHBpbmcuZ2V0Q2xvc2VUYWdQbGFjZWhvbGRlck5hbWUodGFnTmFtZSk7XHJcbiAgICAgICAgY29uc3QgZGlzcFN0YXJ0ID0gJzwnICsgdGFnTmFtZSArICc+JztcclxuICAgICAgICBjb25zdCBkaXNwRW5kID0gJzwvJyArIHRhZ05hbWUgKyAnPic7XHJcbiAgICAgICAgcGNFbGVtLnNldEF0dHJpYnV0ZSgnaWQnLCBpZC50b1N0cmluZygxMCkpO1xyXG4gICAgICAgIHBjRWxlbS5zZXRBdHRyaWJ1dGUoJ2VxdWl2U3RhcnQnLCBlcXVpdlN0YXJ0KTtcclxuICAgICAgICBwY0VsZW0uc2V0QXR0cmlidXRlKCdlcXVpdkVuZCcsIGVxdWl2RW5kKTtcclxuICAgICAgICBwY0VsZW0uc2V0QXR0cmlidXRlKCd0eXBlJywgdGhpcy5nZXRUeXBlRm9yVGFnKHRhZ05hbWUpKTtcclxuICAgICAgICBwY0VsZW0uc2V0QXR0cmlidXRlKCdkaXNwU3RhcnQnLCBkaXNwU3RhcnQpO1xyXG4gICAgICAgIHBjRWxlbS5zZXRBdHRyaWJ1dGUoJ2Rpc3BFbmQnLCBkaXNwRW5kKTtcclxuICAgICAgICByZXR1cm4gcGNFbGVtO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogdGhlIHhtbCB1c2VkIGZvciBlbmQgdGFnIGluIHRoZSBtZXNzYWdlLlxyXG4gICAgICogTm90IHVzZWQgaGVyZSwgYmVjYXVzZSBjb250ZW50IGlzIGNoaWxkIG9mIHN0YXJ0IHRhZy5cclxuICAgICAqIEBwYXJhbSBwYXJ0IHBhcnRcclxuICAgICAqIEBwYXJhbSByb290RWxlbSByb290RWxlbVxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgY3JlYXRlWG1sUmVwcmVzZW50YXRpb25PZkVuZFRhZ1BhcnQocGFydDogUGFyc2VkTWVzc2FnZVBhcnRFbmRUYWcsIHJvb3RFbGVtOiBFbGVtZW50KTogTm9kZSB7XHJcbiAgICAgICAgLy8gbm90IHVzZWRcclxuICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHRoZSB4bWwgdXNlZCBmb3IgZW1wdHkgdGFnIGluIHRoZSBtZXNzYWdlLlxyXG4gICAgICogUmV0dXJucyBhbiBlbXB0eSBwaC1FbGVtZW50LlxyXG4gICAgICogZS5nLiA8cGggaWQ9XCIzXCIgZXF1aXY9XCJUQUdfSU1HXCIgdHlwZT1cImltYWdlXCIgZGlzcD1cIiZsdDtpbWcvPlwiLz5cclxuICAgICAqIEBwYXJhbSBwYXJ0IHBhcnRcclxuICAgICAqIEBwYXJhbSByb290RWxlbSByb290RWxlbVxyXG4gICAgICogQHBhcmFtIGlkIGlkIG51bWJlciBpbiB4bGlmZjJcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGNyZWF0ZVhtbFJlcHJlc2VudGF0aW9uT2ZFbXB0eVRhZ1BhcnQocGFydDogUGFyc2VkTWVzc2FnZVBhcnRFbXB0eVRhZywgcm9vdEVsZW06IEVsZW1lbnQsIGlkOiBudW1iZXIpOiBOb2RlIHtcclxuICAgICAgICBjb25zdCB0YWdNYXBwaW5nID0gbmV3IFRhZ01hcHBpbmcoKTtcclxuICAgICAgICBjb25zdCBwaEVsZW0gPSByb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3BoJyk7XHJcbiAgICAgICAgY29uc3QgdGFnTmFtZSA9IHBhcnQudGFnTmFtZSgpO1xyXG4gICAgICAgIGNvbnN0IGVxdWl2ID0gdGFnTWFwcGluZy5nZXRFbXB0eVRhZ1BsYWNlaG9sZGVyTmFtZSh0YWdOYW1lLCBwYXJ0LmlkQ291bnRlcigpKTtcclxuICAgICAgICBjb25zdCBkaXNwID0gJzwnICsgdGFnTmFtZSArICcvPic7XHJcbiAgICAgICAgcGhFbGVtLnNldEF0dHJpYnV0ZSgnaWQnLCBpZC50b1N0cmluZygxMCkpO1xyXG4gICAgICAgIHBoRWxlbS5zZXRBdHRyaWJ1dGUoJ2VxdWl2JywgZXF1aXYpO1xyXG4gICAgICAgIHBoRWxlbS5zZXRBdHRyaWJ1dGUoJ3R5cGUnLCB0aGlzLmdldFR5cGVGb3JUYWcodGFnTmFtZSkpO1xyXG4gICAgICAgIHBoRWxlbS5zZXRBdHRyaWJ1dGUoJ2Rpc3AnLCBkaXNwKTtcclxuICAgICAgICByZXR1cm4gcGhFbGVtO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0VHlwZUZvclRhZyh0YWc6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgc3dpdGNoICh0YWcudG9Mb3dlckNhc2UoKSkge1xyXG4gICAgICAgICAgICBjYXNlICdicic6XHJcbiAgICAgICAgICAgIGNhc2UgJ2InOlxyXG4gICAgICAgICAgICBjYXNlICdpJzpcclxuICAgICAgICAgICAgY2FzZSAndSc6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2ZtdCc7XHJcbiAgICAgICAgICAgIGNhc2UgJ2ltZyc6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2ltYWdlJztcclxuICAgICAgICAgICAgY2FzZSAnYSc6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2xpbmsnO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICdvdGhlcic7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogdGhlIHhtbCB1c2VkIGZvciBwbGFjZWhvbGRlciBpbiB0aGUgbWVzc2FnZS5cclxuICAgICAqIFJldHVybnMgZS5nLiA8cGggaWQ9XCIxXCIgZXF1aXY9XCJJTlRFUlBPTEFUSU9OXzFcIiBkaXNwPVwie3t0b3RhbCgpfX1cIi8+XHJcbiAgICAgKiBAcGFyYW0gcGFydCBwYXJ0XHJcbiAgICAgKiBAcGFyYW0gcm9vdEVsZW0gcm9vdEVsZW1cclxuICAgICAqIEBwYXJhbSBpZCBpZCBudW1iZXIgaW4geGxpZmYyXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBjcmVhdGVYbWxSZXByZXNlbnRhdGlvbk9mUGxhY2Vob2xkZXJQYXJ0KHBhcnQ6IFBhcnNlZE1lc3NhZ2VQYXJ0UGxhY2Vob2xkZXIsIHJvb3RFbGVtOiBFbGVtZW50LCBpZDogbnVtYmVyKTogTm9kZSB7XHJcbiAgICAgICAgY29uc3QgcGhFbGVtID0gcm9vdEVsZW0ub3duZXJEb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwaCcpO1xyXG4gICAgICAgIGxldCBlcXVpdkF0dHJpYiA9ICdJTlRFUlBPTEFUSU9OJztcclxuICAgICAgICBpZiAocGFydC5pbmRleCgpID4gMCkge1xyXG4gICAgICAgICAgICBlcXVpdkF0dHJpYiA9ICdJTlRFUlBPTEFUSU9OXycgKyBwYXJ0LmluZGV4KCkudG9TdHJpbmcoMTApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBwaEVsZW0uc2V0QXR0cmlidXRlKCdpZCcsIGlkLnRvU3RyaW5nKDEwKSk7XHJcbiAgICAgICAgcGhFbGVtLnNldEF0dHJpYnV0ZSgnZXF1aXYnLCBlcXVpdkF0dHJpYik7XHJcbiAgICAgICAgY29uc3QgZGlzcCA9IHBhcnQuZGlzcCgpO1xyXG4gICAgICAgIGlmIChkaXNwKSB7XHJcbiAgICAgICAgICAgIHBoRWxlbS5zZXRBdHRyaWJ1dGUoJ2Rpc3AnLCBkaXNwKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHBoRWxlbTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHRoZSB4bWwgdXNlZCBmb3IgaWN1IG1lc3NhZ2UgcmVmcyBpbiB0aGUgbWVzc2FnZS5cclxuICAgICAqIEBwYXJhbSBwYXJ0IHBhcnRcclxuICAgICAqIEBwYXJhbSByb290RWxlbSByb290RWxlbVxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgY3JlYXRlWG1sUmVwcmVzZW50YXRpb25PZklDVU1lc3NhZ2VSZWZQYXJ0KHBhcnQ6IFBhcnNlZE1lc3NhZ2VQYXJ0SUNVTWVzc2FnZVJlZiwgcm9vdEVsZW06IEVsZW1lbnQpOiBOb2RlIHtcclxuICAgICAgICBjb25zdCBwaEVsZW0gPSByb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3BoJyk7XHJcbiAgICAgICAgbGV0IGVxdWl2QXR0cmliID0gJ0lDVSc7XHJcbiAgICAgICAgaWYgKHBhcnQuaW5kZXgoKSA+IDApIHtcclxuICAgICAgICAgICAgZXF1aXZBdHRyaWIgPSAnSUNVXycgKyBwYXJ0LmluZGV4KCkudG9TdHJpbmcoMTApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBwaEVsZW0uc2V0QXR0cmlidXRlKCdpZCcsIHBhcnQuaW5kZXgoKS50b1N0cmluZygxMCkpO1xyXG4gICAgICAgIHBoRWxlbS5zZXRBdHRyaWJ1dGUoJ2VxdWl2JywgZXF1aXZBdHRyaWIpO1xyXG4gICAgICAgIGNvbnN0IGRpc3AgPSBwYXJ0LmRpc3AoKTtcclxuICAgICAgICBpZiAoZGlzcCkge1xyXG4gICAgICAgICAgICBwaEVsZW0uc2V0QXR0cmlidXRlKCdkaXNwJywgZGlzcCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBwaEVsZW07XHJcbiAgICB9XHJcblxyXG59XHJcbiJdfQ==