@ngx-i18nsupport/ngx-i18nsupport-lib
Version:
A Typescript library to work with Angular generated i18n files (xliff, xmb)
360 lines • 41 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { AbstractMessageParser } from './abstract-message-parser';
import { DOMUtilities } from './dom-utilities';
import { TagMapping } from './tag-mapping';
import { ParsedMessagePartType } from './parsed-message-part';
/**
* Created by roobm on 10.05.2017.
* A message parser for XMB
*/
export class XmbMessageParser extends AbstractMessageParser {
/**
* 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)
*/
processStartElement(elementNode, message) {
/** @type {?} */
const tagName = elementNode.tagName;
if (tagName === 'ph') {
// There are 4 different usages of ph element:
// 1. placeholders are like <ph name="INTERPOLATION"><ex>INTERPOLATION</ex></ph>
// or <ph name="INTERPOLATION_1"><ex>INTERPOLATION_1</ex></ph>
// 2. start tags:
// <ph name="START_LINK"><ex><a></ex></ph>
// 3. empty tags:
// <ph name="TAG_IMG"><ex><img></ex></ph>
// 4. ICU:
// <ph name="ICU"><ex>ICU</ex></ph>
/** @type {?} */
const name = elementNode.getAttribute('name');
if (!name) {
return true; // should not happen
}
if (name.startsWith('INTERPOLATION')) {
/** @type {?} */
const index = this.parsePlaceholderIndexFromName(name);
message.addPlaceholder(index, null);
return false; // ignore children
}
else if (name.startsWith('START_')) {
/** @type {?} */
const tag = this.parseTagnameFromPhElement(elementNode);
/** @type {?} */
const idcounter = this.parseIdCountFromName(name);
if (tag) {
message.addStartTag(tag, idcounter);
}
return false; // ignore children
}
else if (name.startsWith('CLOSE_')) {
/** @type {?} */
const tag = this.parseTagnameFromPhElement(elementNode);
if (tag) {
message.addEndTag(tag);
}
return false; // ignore children
}
else if (new TagMapping().isEmptyTagPlaceholderName(name)) {
/** @type {?} */
const emptyTagName = new TagMapping().getTagnameFromEmptyTagPlaceholderName(name);
/** @type {?} */
const idcounter = this.parseIdCountFromName(name);
message.addEmptyTag(emptyTagName, idcounter);
return false; // ignore children
}
else if (name.startsWith('ICU')) {
/** @type {?} */
const index = this.parseICUMessageIndexFromName(name);
message.addICUMessageRef(index, null);
return false; // ignore children
}
}
else if (tagName === 'source') {
// ignore source
return false;
}
return true;
}
/**
* Return the ICU message content of the node, if it is an ICU Message.
* @protected
* @param {?} node node
* @return {?} message or null, if it is no ICU Message.
*/
getICUMessageText(node) {
/** @type {?} */
const children = node.childNodes;
if (children.length === 0) {
return null;
}
/** @type {?} */
let firstChild = null;
// find first child that is no source element.
/** @type {?} */
let i;
for (i = 0; i < children.length; i++) {
/** @type {?} */
const child = children.item(i);
if (child.nodeType !== child.ELEMENT_NODE || ((/** @type {?} */ (child))).tagName !== 'source') {
firstChild = child;
break;
}
}
if (firstChild && firstChild.nodeType === firstChild.TEXT_NODE) {
if (this.isICUMessageStart(firstChild.textContent)) {
/** @type {?} */
const messageText = DOMUtilities.getXMLContent((/** @type {?} */ (node)));
if (i > 0) {
// drop <source> elements
/** @type {?} */
const reSource = new RegExp('<source[^>]*>.*</source>', 'g');
return messageText.replace(reSource, '');
}
else {
return messageText;
}
}
else {
return null;
}
}
else {
return null;
}
}
/**
* 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 {?}
*/
processEndElement(elementNode, message) {
}
/**
* Parse id attribute of x element as placeholder index.
* id can be "INTERPOLATION" or "INTERPOLATION_n"
* @private
* @param {?} name name
* @return {?} id as number
*/
parsePlaceholderIndexFromName(name) {
/** @type {?} */
let indexString = '';
if (name === 'INTERPOLATION') {
indexString = '0';
}
else {
indexString = name.substring('INTERPOLATION_'.length);
}
return Number.parseInt(indexString, 10);
}
/**
* Parse id attribute of x element as ICU message ref index.
* id can be "ICU" or "ICU_n"
* @private
* @param {?} name name
* @return {?} id as number
*/
parseICUMessageIndexFromName(name) {
/** @type {?} */
let indexString = '';
if (name === 'ICU') {
indexString = '0';
}
else {
indexString = name.substring('ICU_'.length);
}
return Number.parseInt(indexString, 10);
}
/**
* Parse the tag name from a ph element.
* It contained in the <ex> subelements value and enclosed in <>.
* Example: <ph name="START_BOLD_TEXT"><ex><b></ex></ph>
* @private
* @param {?} phElement phElement
* @return {?}
*/
parseTagnameFromPhElement(phElement) {
/** @type {?} */
const exElement = DOMUtilities.getFirstElementByTagName(phElement, 'ex');
if (exElement) {
/** @type {?} */
const value = DOMUtilities.getPCDATA(exElement);
if (!value || !value.startsWith('<') || !value.endsWith('>')) {
// oops
return null;
}
if (value.charAt(1) === '/') {
return value.substring(2, value.length - 1);
}
else {
return value.substring(1, value.length - 1);
}
}
else {
return null;
}
}
/**
* @protected
* @param {?} message
* @param {?} rootElem
* @return {?}
*/
addXmlRepresentationToRoot(message, rootElem) {
message.parts().forEach((/**
* @param {?} part
* @return {?}
*/
(part) => {
/** @type {?} */
const child = this.createXmlRepresentationOfPart(part, rootElem);
if (child) {
rootElem.appendChild(child);
}
}));
}
/**
* @protected
* @param {?} part
* @param {?} rootElem
* @return {?}
*/
createXmlRepresentationOfPart(part, rootElem) {
switch (part.type) {
case ParsedMessagePartType.TEXT:
return this.createXmlRepresentationOfTextPart((/** @type {?} */ (part)), rootElem);
case ParsedMessagePartType.START_TAG:
return this.createXmlRepresentationOfStartTagPart(((/** @type {?} */ (part))), rootElem);
case ParsedMessagePartType.END_TAG:
return this.createXmlRepresentationOfEndTagPart(((/** @type {?} */ (part))), rootElem);
case ParsedMessagePartType.EMPTY_TAG:
return this.createXmlRepresentationOfEmptyTagPart(((/** @type {?} */ (part))), rootElem);
case ParsedMessagePartType.PLACEHOLDER:
return this.createXmlRepresentationOfPlaceholderPart(((/** @type {?} */ (part))), rootElem);
case ParsedMessagePartType.ICU_MESSAGE_REF:
return this.createXmlRepresentationOfICUMessageRefPart(((/** @type {?} */ (part))), rootElem);
}
}
/**
* the xml used for start tag in the message.
* Returns an <ph>-Element with attribute name and subelement ex
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @return {?}
*/
createXmlRepresentationOfStartTagPart(part, rootElem) {
/** @type {?} */
const phElem = rootElem.ownerDocument.createElement('ph');
/** @type {?} */
const tagMapping = new TagMapping();
/** @type {?} */
const nameAttrib = tagMapping.getStartTagPlaceholderName(part.tagName(), part.idCounter());
phElem.setAttribute('name', nameAttrib);
/** @type {?} */
const exElem = rootElem.ownerDocument.createElement('ex');
exElem.appendChild(rootElem.ownerDocument.createTextNode('<' + part.tagName() + '>'));
phElem.appendChild(exElem);
return phElem;
}
/**
* the xml used for end tag in the message.
* Returns an <ph>-Element with attribute name and subelement ex
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @return {?}
*/
createXmlRepresentationOfEndTagPart(part, rootElem) {
/** @type {?} */
const phElem = rootElem.ownerDocument.createElement('ph');
/** @type {?} */
const tagMapping = new TagMapping();
/** @type {?} */
const nameAttrib = tagMapping.getCloseTagPlaceholderName(part.tagName());
phElem.setAttribute('name', nameAttrib);
/** @type {?} */
const exElem = rootElem.ownerDocument.createElement('ex');
exElem.appendChild(rootElem.ownerDocument.createTextNode('</' + part.tagName() + '>'));
phElem.appendChild(exElem);
return phElem;
}
/**
* the xml used for empty tag in the message.
* Returns an <ph>-Element with attribute name and subelement ex
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @return {?}
*/
createXmlRepresentationOfEmptyTagPart(part, rootElem) {
/** @type {?} */
const phElem = rootElem.ownerDocument.createElement('ph');
/** @type {?} */
const tagMapping = new TagMapping();
/** @type {?} */
const nameAttrib = tagMapping.getEmptyTagPlaceholderName(part.tagName(), part.idCounter());
phElem.setAttribute('name', nameAttrib);
/** @type {?} */
const exElem = rootElem.ownerDocument.createElement('ex');
exElem.appendChild(rootElem.ownerDocument.createTextNode('<' + part.tagName() + '>'));
phElem.appendChild(exElem);
return phElem;
}
/**
* the xml used for placeholder in the message.
* Returns an <ph>-Element with attribute name and subelement ex
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @return {?}
*/
createXmlRepresentationOfPlaceholderPart(part, rootElem) {
/** @type {?} */
const phElem = rootElem.ownerDocument.createElement('ph');
/** @type {?} */
let nameAttrib = 'INTERPOLATION';
if (part.index() > 0) {
nameAttrib = 'INTERPOLATION_' + part.index().toString(10);
}
phElem.setAttribute('name', nameAttrib);
/** @type {?} */
const exElem = rootElem.ownerDocument.createElement('ex');
exElem.appendChild(rootElem.ownerDocument.createTextNode(nameAttrib));
phElem.appendChild(exElem);
return phElem;
}
/**
* the xml used for icu message refs in the message.
* @protected
* @param {?} part part
* @param {?} rootElem rootElem
* @return {?}
*/
createXmlRepresentationOfICUMessageRefPart(part, rootElem) {
/** @type {?} */
const phElem = rootElem.ownerDocument.createElement('ph');
/** @type {?} */
let nameAttrib = 'ICU';
if (part.index() > 0) {
nameAttrib = 'ICU_' + part.index().toString(10);
}
phElem.setAttribute('name', nameAttrib);
/** @type {?} */
const exElem = rootElem.ownerDocument.createElement('ex');
exElem.appendChild(rootElem.ownerDocument.createTextNode(nameAttrib));
phElem.appendChild(exElem);
return phElem;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieG1iLW1lc3NhZ2UtcGFyc2VyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5neC1pMThuc3VwcG9ydC9uZ3gtaTE4bnN1cHBvcnQtbGliLyIsInNvdXJjZXMiOlsiaW1wbC94bWItbWVzc2FnZS1wYXJzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBRWhFLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUk3QyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBR3pDLE9BQU8sRUFBb0IscUJBQXFCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQzs7Ozs7QUFNL0UsTUFBTSxPQUFPLGdCQUFpQixTQUFRLHFCQUFxQjs7Ozs7Ozs7O0lBUzdDLG1CQUFtQixDQUFDLFdBQW9CLEVBQUUsT0FBc0I7O2NBQ2hFLE9BQU8sR0FBRyxXQUFXLENBQUMsT0FBTztRQUNuQyxJQUFJLE9BQU8sS0FBSyxJQUFJLEVBQUU7Ozs7Ozs7Ozs7O2tCQVVaLElBQUksR0FBRyxXQUFXLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQztZQUM3QyxJQUFJLENBQUMsSUFBSSxFQUFFO2dCQUNQLE9BQU8sSUFBSSxDQUFDLENBQUMsb0JBQW9CO2FBQ3BDO1lBQ0QsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLGVBQWUsQ0FBQyxFQUFFOztzQkFDNUIsS0FBSyxHQUFHLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxJQUFJLENBQUM7Z0JBQ3RELE9BQU8sQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUNwQyxPQUFPLEtBQUssQ0FBQyxDQUFDLGtCQUFrQjthQUNuQztpQkFBTSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUU7O3NCQUM1QixHQUFHLEdBQUcsSUFBSSxDQUFDLHlCQUF5QixDQUFDLFdBQVcsQ0FBQzs7c0JBQ2pE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ekQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDM0IsT0FBTyxNQUFNLENBQUM7SUFDbEIsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtBYnN0cmFjdE1lc3NhZ2VQYXJzZXJ9IGZyb20gJy4vYWJzdHJhY3QtbWVzc2FnZS1wYXJzZXInO1xyXG5pbXBvcnQge1BhcnNlZE1lc3NhZ2V9IGZyb20gJy4vcGFyc2VkLW1lc3NhZ2UnO1xyXG5pbXBvcnQge0RPTVV0aWxpdGllc30gZnJvbSAnLi9kb20tdXRpbGl0aWVzJztcclxuaW1wb3J0IHtQYXJzZWRNZXNzYWdlUGFydFN0YXJ0VGFnfSBmcm9tICcuL3BhcnNlZC1tZXNzYWdlLXBhcnQtc3RhcnQtdGFnJztcclxuaW1wb3J0IHtQYXJzZWRNZXNzYWdlUGFydEVuZFRhZ30gZnJvbSAnLi9wYXJzZWQtbWVzc2FnZS1wYXJ0LWVuZC10YWcnO1xyXG5pbXBvcnQge1BhcnNlZE1lc3NhZ2VQYXJ0UGxhY2Vob2xkZXJ9IGZyb20gJy4vcGFyc2VkLW1lc3NhZ2UtcGFydC1wbGFjZWhvbGRlcic7XHJcbmltcG9ydCB7VGFnTWFwcGluZ30gZnJvbSAnLi90YWctbWFwcGluZyc7XHJcbmltcG9ydCB7UGFyc2VkTWVzc2FnZVBhcnRFbXB0eVRhZ30gZnJvbSAnLi9wYXJzZWQtbWVzc2FnZS1wYXJ0LWVtcHR5LXRhZyc7XHJcbmltcG9ydCB7UGFyc2VkTWVzc2FnZVBhcnRJQ1VNZXNzYWdlUmVmfSBmcm9tICcuL3BhcnNlZC1tZXNzYWdlLXBhcnQtaWN1LW1lc3NhZ2UtcmVmJztcclxuaW1wb3J0IHtQYXJzZWRNZXNzYWdlUGFydCwgUGFyc2VkTWVzc2FnZVBhcnRUeXBlfSBmcm9tICcuL3BhcnNlZC1tZXNzYWdlLXBhcnQnO1xyXG5pbXBvcnQge1BhcnNlZE1lc3NhZ2VQYXJ0VGV4dH0gZnJvbSAnLi9wYXJzZWQtbWVzc2FnZS1wYXJ0LXRleHQnO1xyXG4vKipcclxuICogQ3JlYXRlZCBieSByb29ibSBvbiAxMC4wNS4yMDE3LlxyXG4gKiBBIG1lc3NhZ2UgcGFyc2VyIGZvciBYTUJcclxuICovXHJcbmV4cG9ydCBjbGFzcyBYbWJNZXNzYWdlUGFyc2VyIGV4dGVuZHMgQWJzdHJhY3RNZXNzYWdlUGFyc2VyIHtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEhhbmRsZSB0aGlzIGVsZW1lbnQgbm9kZS5cclxuICAgICAqIFRoaXMgaXMgY2FsbGVkIGJlZm9yZSB0aGUgY2hpbGRyZW4gYXJlIGRvbmUuXHJcbiAgICAgKiBAcGFyYW0gZWxlbWVudE5vZGUgZWxlbWVudE5vZGVcclxuICAgICAqIEBwYXJhbSBtZXNzYWdlIG1lc3NhZ2UgdG8gYmUgYWx0ZXJlZFxyXG4gICAgICogQHJldHVybiB0cnVlLCBpZiBjaGlsZHJlbiBzaG91bGQgYmUgcHJvY2Vzc2VkIHRvbywgZmFsc2Ugb3RoZXJ3aXNlIChjaGlsZHJlbiBpZ25vcmVkIHRoZW4pXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBwcm9jZXNzU3RhcnRFbGVtZW50KGVsZW1lbnROb2RlOiBFbGVtZW50LCBtZXNzYWdlOiBQYXJzZWRNZXNzYWdlKTogYm9vbGVhbiB7XHJcbiAgICAgICAgY29uc3QgdGFnTmFtZSA9IGVsZW1lbnROb2RlLnRhZ05hbWU7XHJcbiAgICAgICAgaWYgKHRhZ05hbWUgPT09ICdwaCcpIHtcclxuICAgICAgICAgICAgLy8gVGhlcmUgYXJlIDQgZGlmZmVyZW50IHVzYWdlcyBvZiBwaCBlbGVtZW50OlxyXG4gICAgICAgICAgICAvLyAxLiBwbGFjZWhvbGRlcnMgYXJlIGxpa2UgPHBoIG5hbWU9XCJJTlRFUlBPTEFUSU9OXCI+PGV4PklOVEVSUE9MQVRJT048L2V4PjwvcGg+XHJcbiAgICAgICAgICAgIC8vIG9yIDxwaCBuYW1lPVwiSU5URVJQT0xBVElPTl8xXCI+PGV4PklOVEVSUE9MQVRJT05fMTwvZXg+PC9waD5cclxuICAgICAgICAgICAgLy8gMi4gc3RhcnQgdGFnczpcclxuICAgICAgICAgICAgLy8gPHBoIG5hbWU9XCJTVEFSVF9MSU5LXCI+PGV4PiZsdDthJmd0OzwvZXg+PC9waD5cclxuICAgICAgICAgICAgLy8gMy4gZW1wdHkgdGFnczpcclxuICAgICAgICAgICAgLy8gPHBoIG5hbWU9XCJUQUdfSU1HXCI+PGV4PiZsdDtpbWcmZ3Q7PC9leD48L3BoPlxyXG4gICAgICAgICAgICAvLyA0LiBJQ1U6XHJcbiAgICAgICAgICAgIC8vIDxwaCBuYW1lPVwiSUNVXCI+PGV4PklDVTwvZXg+PC9waD5cclxuICAgICAgICAgICAgY29uc3QgbmFtZSA9IGVsZW1lbnROb2RlLmdldEF0dHJpYnV0ZSgnbmFtZScpO1xyXG4gICAgICAgICAgICBpZiAoIW5hbWUpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOyAvLyBzaG91bGQgbm90IGhhcHBlblxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChuYW1lLnN0YXJ0c1dpdGgoJ0lOVEVSUE9MQVRJT04nKSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnBhcnNlUGxhY2Vob2xkZXJJbmRleEZyb21OYW1lKG5hbWUpO1xyXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5hZGRQbGFjZWhvbGRlcihpbmRleCwgbnVsbCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7IC8vIGlnbm9yZSBjaGlsZHJlblxyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG5hbWUuc3RhcnRzV2l0aCgnU1RBUlRfJykpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHRhZyA9IHRoaXMucGFyc2VUYWduYW1lRnJvbVBoRWxlbWVudChlbGVtZW50Tm9kZSk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpZGNvdW50ZXIgPSB0aGlzLnBhcnNlSWRDb3VudEZyb21OYW1lKG5hbWUpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRhZykge1xyXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuYWRkU3RhcnRUYWcodGFnLCBpZGNvdW50ZXIpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBpZ25vcmUgY2hpbGRyZW5cclxuICAgICAgICAgICAgfSBlbHNlIGlmIChuYW1lLnN0YXJ0c1dpdGgoJ0NMT1NFXycpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB0YWcgPSB0aGlzLnBhcnNlVGFnbmFtZUZyb21QaEVsZW1lbnQoZWxlbWVudE5vZGUpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRhZykge1xyXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuYWRkRW5kVGFnKHRhZyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7IC8vIGlnbm9yZSBjaGlsZHJlblxyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG5ldyBUYWdNYXBwaW5nKCkuaXNFbXB0eVRhZ1BsYWNlaG9sZGVyTmFtZShuYW1lKSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZW1wdHlUYWdOYW1lID0gbmV3IFRhZ01hcHBpbmcoKS5nZXRUYWduYW1lRnJvbUVtcHR5VGFnUGxhY2Vob2xkZXJOYW1lKG5hbWUpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaWRjb3VudGVyID0gdGhpcy5wYXJzZUlkQ291bnRGcm9tTmFtZShuYW1lKTtcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuYWRkRW1wdHlUYWcoZW1wdHlUYWdOYW1lLCBpZGNvdW50ZXIpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBpZ25vcmUgY2hpbGRyZW5cclxuICAgICAgICAgICAgfSBlbHNlIGlmIChuYW1lLnN0YXJ0c1dpdGgoJ0lDVScpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMucGFyc2VJQ1VNZXNzYWdlSW5kZXhGcm9tTmFtZShuYW1lKTtcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuYWRkSUNVTWVzc2FnZVJlZihpbmRleCwgbnVsbCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7IC8vIGlnbm9yZSBjaGlsZHJlblxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIGlmICh0YWdOYW1lID09PSAnc291cmNlJykge1xyXG4gICAgICAgICAgICAvLyBpZ25vcmUgc291cmNlXHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm4gdGhlIElDVSBtZXNzYWdlIGNvbnRlbnQgb2YgdGhlIG5vZGUsIGlmIGl0IGlzIGFuIElDVSBNZXNzYWdlLlxyXG4gICAgICogQHBhcmFtIG5vZGUgbm9kZVxyXG4gICAgICogQHJldHVybiBtZXNzYWdlIG9yIG51bGwsIGlmIGl0IGlzIG5vIElDVSBNZXNzYWdlLlxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgZ2V0SUNVTWVzc2FnZVRleHQobm9kZTogTm9kZSk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgY2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXM7XHJcbiAgICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgbGV0IGZpcnN0Q2hpbGQgPSBudWxsO1xyXG4gICAgICAgIC8vIGZpbmQgZmlyc3QgY2hpbGQgdGhhdCBpcyBubyBzb3VyY2UgZWxlbWVudC5cclxuICAgICAgICBsZXQgaTtcclxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgY29uc3QgY2hpbGQgPSBjaGlsZHJlbi5pdGVtKGkpO1xyXG4gICAgICAgICAgICBpZiAoY2hpbGQubm9kZVR5cGUgIT09IGNoaWxkLkVMRU1FTlRfTk9ERSB8fCAoPEVsZW1lbnQ+IGNoaWxkKS50YWdOYW1lICE9PSAnc291cmNlJykge1xyXG4gICAgICAgICAgICAgICAgZmlyc3RDaGlsZCA9IGNoaWxkO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGZpcnN0Q2hpbGQgJiYgZmlyc3RDaGlsZC5ub2RlVHlwZSA9PT0gZmlyc3RDaGlsZC5URVhUX05PREUpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNJQ1VNZXNzYWdlU3RhcnQoZmlyc3RDaGlsZC50ZXh0Q29udGVudCkpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2VUZXh0ID0gRE9NVXRpbGl0aWVzLmdldFhNTENvbnRlbnQoPEVsZW1lbnQ+IG5vZGUpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGkgPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gZHJvcCA8c291cmNlPiBlbGVtZW50c1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlU291cmNlOiBSZWdFeHAgPSBuZXcgUmVnRXhwKCc8c291cmNlW14+XSo+Lio8L3NvdXJjZT4nLCAnZycpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlVGV4dC5yZXBsYWNlKHJlU291cmNlLCAnJyk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlVGV4dDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGFuZGxlIGVuZCBvZiB0aGlzIGVsZW1lbnQgbm9kZS5cclxuICAgICAqIFRoaXMgaXMgY2FsbGVkIGFmdGVyIGFsbCBjaGlsZHJlbiBhcmUgcHJvY2Vzc2VkLlxyXG4gICAgICogQHBhcmFtIGVsZW1lbnROb2RlIGVsZW1lbnROb2RlXHJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBtZXNzYWdlIHRvIGJlIGFsdGVyZWRcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHByb2Nlc3NFbmRFbGVtZW50KGVsZW1lbnROb2RlOiBFbGVtZW50LCBtZXNzYWdlOiBQYXJzZWRNZXNzYWdlKSB7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQYXJzZSBpZCBhdHRyaWJ1dGUgb2YgeCBlbGVtZW50IGFzIHBsYWNlaG9sZGVyIGluZGV4LlxyXG4gICAgICogaWQgY2FuIGJlIFwiSU5URVJQT0xBVElPTlwiIG9yIFwiSU5URVJQT0xBVElPTl9uXCJcclxuICAgICAqIEBwYXJhbSBuYW1lIG5hbWVcclxuICAgICAqIEByZXR1cm4gaWQgYXMgbnVtYmVyXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcGFyc2VQbGFjZWhvbGRlckluZGV4RnJvbU5hbWUobmFtZTogc3RyaW5nKTogbnVtYmVyIHtcclxuICAgICAgICBsZXQgaW5kZXhTdHJpbmcgPSAnJztcclxuXHJcbiAgICAgICAgaWYgKG5hbWUgPT09ICdJTlRFUlBPTEFUSU9OJykge1xyXG4gICAgICAgICAgICBpbmRleFN0cmluZyA9ICcwJztcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBpbmRleFN0cmluZyA9IG5hbWUuc3Vic3RyaW5nKCdJTlRFUlBPTEFUSU9OXycubGVuZ3RoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIE51bWJlci5wYXJzZUludChpbmRleFN0cmluZywgMTApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFyc2UgaWQgYXR0cmlidXRlIG9mIHggZWxlbWVudCBhcyBJQ1UgbWVzc2FnZSByZWYgaW5kZXguXHJcbiAgICAgKiBpZCBjYW4gYmUgXCJJQ1VcIiBvciBcIklDVV9uXCJcclxuICAgICAqIEBwYXJhbSBuYW1lIG5hbWVcclxuICAgICAqIEByZXR1cm4gaWQgYXMgbnVtYmVyXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcGFyc2VJQ1VNZXNzYWdlSW5kZXhGcm9tTmFtZShuYW1lOiBzdHJpbmcpOiBudW1iZXIge1xyXG4gICAgICAgIGxldCBpbmRleFN0cmluZyA9ICcnO1xyXG5cclxuICAgICAgICBpZiAobmFtZSA9PT0gJ0lDVScpIHtcclxuICAgICAgICAgICAgaW5kZXhTdHJpbmcgPSAnMCc7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaW5kZXhTdHJpbmcgPSBuYW1lLnN1YnN0cmluZygnSUNVXycubGVuZ3RoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIE51bWJlci5wYXJzZUludChpbmRleFN0cmluZywgMTApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFyc2UgdGhlIHRhZyBuYW1lIGZyb20gYSBwaCBlbGVtZW50LlxyXG4gICAgICogSXQgY29udGFpbmVkIGluIHRoZSA8ZXg+IHN1YmVsZW1lbnRzIHZhbHVlIGFuZCBlbmNsb3NlZCBpbiA8Pi5cclxuICAgICAqIEV4YW1wbGU6IDxwaCBuYW1lPVwiU1RBUlRfQk9MRF9URVhUXCI+PGV4PiZsdDtiJmd0OzwvZXg+PC9waD5cclxuICAgICAqIEBwYXJhbSBwaEVsZW1lbnQgcGhFbGVtZW50XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcGFyc2VUYWduYW1lRnJvbVBoRWxlbWVudChwaEVsZW1lbnQ6IEVsZW1lbnQpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGV4RWxlbWVudCA9IERPTVV0aWxpdGllcy5nZXRGaXJzdEVsZW1lbnRCeVRhZ05hbWUocGhFbGVtZW50LCAnZXgnKTtcclxuICAgICAgICBpZiAoZXhFbGVtZW50KSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gRE9NVXRpbGl0aWVzLmdldFBDREFUQShleEVsZW1lbnQpO1xyXG4gICAgICAgICAgICBpZiAoIXZhbHVlIHx8ICF2YWx1ZS5zdGFydHNXaXRoKCc8JykgfHwgIXZhbHVlLmVuZHNXaXRoKCc+JykpIHtcclxuICAgICAgICAgICAgICAgIC8vIG9vcHNcclxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh2YWx1ZS5jaGFyQXQoMSkgPT09ICcvJykge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLnN1YnN0cmluZygyLCB2YWx1ZS5sZW5ndGggLSAxKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5zdWJzdHJpbmcoMSwgdmFsdWUubGVuZ3RoIC0gMSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJvdGVjdGVkIGFkZFhtbFJlcHJlc2VudGF0aW9uVG9Sb290KG1lc3NhZ2U6IFBhcnNlZE1lc3NhZ2UsIHJvb3RFbGVtOiBFbGVtZW50KSB7XHJcbiAgICAgICAgbWVzc2FnZS5wYXJ0cygpLmZvckVhY2goKHBhcnQpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgY2hpbGQgPSB0aGlzLmNyZWF0ZVhtbFJlcHJlc2VudGF0aW9uT2ZQYXJ0KHBhcnQsIHJvb3RFbGVtKTtcclxuICAgICAgICAgICAgaWYgKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICByb290RWxlbS5hcHBlbmRDaGlsZChjaGlsZCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcm90ZWN0ZWQgY3JlYXRlWG1sUmVwcmVzZW50YXRpb25PZlBhcnQocGFydDogUGFyc2VkTWVzc2FnZVBhcnQsIHJvb3RFbGVtOiBFbGVtZW50KTogTm9kZSB7XHJcbiAgICAgICAgc3dpdGNoIChwYXJ0LnR5cGUpIHtcclxuICAgICAgICAgICAgY2FzZSBQYXJzZWRNZXNzYWdlUGFydFR5cGUuVEVYVDpcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVhtbFJlcHJlc2VudGF0aW9uT2ZUZXh0UGFydCg8UGFyc2VkTWVzc2FnZVBhcnRUZXh0PiBwYXJ0LCByb290RWxlbSk7XHJcbiAgICAgICAgICAgIGNhc2UgUGFyc2VkTWVzc2FnZVBhcnRUeXBlLlNUQVJUX1RBRzpcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVhtbFJlcHJlc2VudGF0aW9uT2ZTdGFydFRhZ1BhcnQoKDxQYXJzZWRNZXNzYWdlUGFydFN0YXJ0VGFnPnBhcnQpLCByb290RWxlbSk7XHJcbiAgICAgICAgICAgIGNhc2UgUGFyc2VkTWVzc2FnZVBhcnRUeXBlLkVORF9UQUc6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVYbWxSZXByZXNlbnRhdGlvbk9mRW5kVGFnUGFydCgoPFBhcnNlZE1lc3NhZ2VQYXJ0RW5kVGFnPnBhcnQpLCByb290RWxlbSk7XHJcbiAgICAgICAgICAgIGNhc2UgUGFyc2VkTWVzc2FnZVBhcnRUeXBlLkVNUFRZX1RBRzpcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVhtbFJlcHJlc2VudGF0aW9uT2ZFbXB0eVRhZ1BhcnQoKDxQYXJzZWRNZXNzYWdlUGFydEVtcHR5VGFnPnBhcnQpLCByb290RWxlbSk7XHJcbiAgICAgICAgICAgIGNhc2UgUGFyc2VkTWVzc2FnZVBhcnRUeXBlLlBMQUNFSE9MREVSOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlWG1sUmVwcmVzZW50YXRpb25PZlBsYWNlaG9sZGVyUGFydCgoPFBhcnNlZE1lc3NhZ2VQYXJ0UGxhY2Vob2xkZXI+cGFydCksIHJvb3RFbGVtKTtcclxuICAgICAgICAgICAgY2FzZSBQYXJzZWRNZXNzYWdlUGFydFR5cGUuSUNVX01FU1NBR0VfUkVGOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlWG1sUmVwcmVzZW50YXRpb25PZklDVU1lc3NhZ2VSZWZQYXJ0KCg8UGFyc2VkTWVzc2FnZVBhcnRJQ1VNZXNzYWdlUmVmPnBhcnQpLCByb290RWxlbSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogdGhlIHhtbCB1c2VkIGZvciBzdGFydCB0YWcgaW4gdGhlIG1lc3NhZ2UuXHJcbiAgICAgKiBSZXR1cm5zIGFuIDxwaD4tRWxlbWVudCB3aXRoIGF0dHJpYnV0ZSBuYW1lIGFuZCBzdWJlbGVtZW50IGV4XHJcbiAgICAgKiBAcGFyYW0gcGFydCBwYXJ0XHJcbiAgICAgKiBAcGFyYW0gcm9vdEVsZW0gcm9vdEVsZW1cclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGNyZWF0ZVhtbFJlcHJlc2VudGF0aW9uT2ZTdGFydFRhZ1BhcnQocGFydDogUGFyc2VkTWVzc2FnZVBhcnRTdGFydFRhZywgcm9vdEVsZW06IEVsZW1lbnQpOiBOb2RlIHtcclxuICAgICAgICBjb25zdCBwaEVsZW0gPSByb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3BoJyk7XHJcbiAgICAgICAgY29uc3QgdGFnTWFwcGluZyA9IG5ldyBUYWdNYXBwaW5nKCk7XHJcbiAgICAgICAgY29uc3QgbmFtZUF0dHJpYiA9IHRhZ01hcHBpbmcuZ2V0U3RhcnRUYWdQbGFjZWhvbGRlck5hbWUocGFydC50YWdOYW1lKCksIHBhcnQuaWRDb3VudGVyKCkpO1xyXG4gICAgICAgIHBoRWxlbS5zZXRBdHRyaWJ1dGUoJ25hbWUnLCBuYW1lQXR0cmliKTtcclxuICAgICAgICBjb25zdCBleEVsZW0gPSByb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2V4Jyk7XHJcbiAgICAgICAgZXhFbGVtLmFwcGVuZENoaWxkKHJvb3RFbGVtLm93bmVyRG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJzwnICsgcGFydC50YWdOYW1lKCkgKyAnPicpKTtcclxuICAgICAgICBwaEVsZW0uYXBwZW5kQ2hpbGQoZXhFbGVtKTtcclxuICAgICAgICByZXR1cm4gcGhFbGVtO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogdGhlIHhtbCB1c2VkIGZvciBlbmQgdGFnIGluIHRoZSBtZXNzYWdlLlxyXG4gICAgICogUmV0dXJucyBhbiA8cGg+LUVsZW1lbnQgd2l0aCBhdHRyaWJ1dGUgbmFtZSBhbmQgc3ViZWxlbWVudCBleFxyXG4gICAgICogQHBhcmFtIHBhcnQgcGFydFxyXG4gICAgICogQHBhcmFtIHJvb3RFbGVtIHJvb3RFbGVtXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBjcmVhdGVYbWxSZXByZXNlbnRhdGlvbk9mRW5kVGFnUGFydChwYXJ0OiBQYXJzZWRNZXNzYWdlUGFydEVuZFRhZywgcm9vdEVsZW06IEVsZW1lbnQpOiBOb2RlIHtcclxuICAgICAgICBjb25zdCBwaEVsZW0gPSByb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3BoJyk7XHJcbiAgICAgICAgY29uc3QgdGFnTWFwcGluZyA9IG5ldyBUYWdNYXBwaW5nKCk7XHJcbiAgICAgICAgY29uc3QgbmFtZUF0dHJpYiA9IHRhZ01hcHBpbmcuZ2V0Q2xvc2VUYWdQbGFjZWhvbGRlck5hbWUocGFydC50YWdOYW1lKCkpO1xyXG4gICAgICAgIHBoRWxlbS5zZXRBdHRyaWJ1dGUoJ25hbWUnLCBuYW1lQXR0cmliKTtcclxuICAgICAgICBjb25zdCBleEVsZW0gPSByb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2V4Jyk7XHJcbiAgICAgICAgZXhFbGVtLmFwcGVuZENoaWxkKHJvb3RFbGVtLm93bmVyRG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJzwvJyArIHBhcnQudGFnTmFtZSgpICsgJz4nKSk7XHJcbiAgICAgICAgcGhFbGVtLmFwcGVuZENoaWxkKGV4RWxlbSk7XHJcbiAgICAgICAgcmV0dXJuIHBoRWxlbTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHRoZSB4bWwgdXNlZCBmb3IgZW1wdHkgdGFnIGluIHRoZSBtZXNzYWdlLlxyXG4gICAgICogUmV0dXJucyBhbiA8cGg+LUVsZW1lbnQgd2l0aCBhdHRyaWJ1dGUgbmFtZSBhbmQgc3ViZWxlbWVudCBleFxyXG4gICAgICogQHBhcmFtIHBhcnQgcGFydFxyXG4gICAgICogQHBhcmFtIHJvb3RFbGVtIHJvb3RFbGVtXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBjcmVhdGVYbWxSZXByZXNlbnRhdGlvbk9mRW1wdHlUYWdQYXJ0KHBhcnQ6IFBhcnNlZE1lc3NhZ2VQYXJ0RW1wdHlUYWcsIHJvb3RFbGVtOiBFbGVtZW50KTogTm9kZSB7XHJcbiAgICAgICAgY29uc3QgcGhFbGVtID0gcm9vdEVsZW0ub3duZXJEb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwaCcpO1xyXG4gICAgICAgIGNvbnN0IHRhZ01hcHBpbmcgPSBuZXcgVGFnTWFwcGluZygpO1xyXG4gICAgICAgIGNvbnN0IG5hbWVBdHRyaWIgPSB0YWdNYXBwaW5nLmdldEVtcHR5VGFnUGxhY2Vob2xkZXJOYW1lKHBhcnQudGFnTmFtZSgpLCBwYXJ0LmlkQ291bnRlcigpKTtcclxuICAgICAgICBwaEVsZW0uc2V0QXR0cmlidXRlKCduYW1lJywgbmFtZUF0dHJpYik7XHJcbiAgICAgICAgY29uc3QgZXhFbGVtID0gcm9vdEVsZW0ub3duZXJEb2N1bWVudC5jcmVhdGVFbGVtZW50KCdleCcpO1xyXG4gICAgICAgIGV4RWxlbS5hcHBlbmRDaGlsZChyb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCc8JyArIHBhcnQudGFnTmFtZSgpICsgJz4nKSk7XHJcbiAgICAgICAgcGhFbGVtLmFwcGVuZENoaWxkKGV4RWxlbSk7XHJcbiAgICAgICAgcmV0dXJuIHBoRWxlbTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHRoZSB4bWwgdXNlZCBmb3IgcGxhY2Vob2xkZXIgaW4gdGhlIG1lc3NhZ2UuXHJcbiAgICAgKiBSZXR1cm5zIGFuIDxwaD4tRWxlbWVudCB3aXRoIGF0dHJpYnV0ZSBuYW1lIGFuZCBzdWJlbGVtZW50IGV4XHJcbiAgICAgKiBAcGFyYW0gcGFydCBwYXJ0XHJcbiAgICAgKiBAcGFyYW0gcm9vdEVsZW0gcm9vdEVsZW1cclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGNyZWF0ZVhtbFJlcHJlc2VudGF0aW9uT2ZQbGFjZWhvbGRlclBhcnQocGFydDogUGFyc2VkTWVzc2FnZVBhcnRQbGFjZWhvbGRlciwgcm9vdEVsZW06IEVsZW1lbnQpOiBOb2RlIHtcclxuICAgICAgICBjb25zdCBwaEVsZW0gPSByb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3BoJyk7XHJcbiAgICAgICAgbGV0IG5hbWVBdHRyaWIgPSAnSU5URVJQT0xBVElPTic7XHJcbiAgICAgICAgaWYgKHBhcnQuaW5kZXgoKSA+IDApIHtcclxuICAgICAgICAgICAgbmFtZUF0dHJpYiA9ICdJTlRFUlBPTEFUSU9OXycgKyBwYXJ0LmluZGV4KCkudG9TdHJpbmcoMTApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBwaEVsZW0uc2V0QXR0cmlidXRlKCduYW1lJywgbmFtZUF0dHJpYik7XHJcbiAgICAgICAgY29uc3QgZXhFbGVtID0gcm9vdEVsZW0ub3duZXJEb2N1bWVudC5jcmVhdGVFbGVtZW50KCdleCcpO1xyXG4gICAgICAgIGV4RWxlbS5hcHBlbmRDaGlsZChyb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5hbWVBdHRyaWIpKTtcclxuICAgICAgICBwaEVsZW0uYXBwZW5kQ2hpbGQoZXhFbGVtKTtcclxuICAgICAgICByZXR1cm4gcGhFbGVtO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogdGhlIHhtbCB1c2VkIGZvciBpY3UgbWVzc2FnZSByZWZzIGluIHRoZSBtZXNzYWdlLlxyXG4gICAgICogQHBhcmFtIHBhcnQgcGFydFxyXG4gICAgICogQHBhcmFtIHJvb3RFbGVtIHJvb3RFbGVtXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBjcmVhdGVYbWxSZXByZXNlbnRhdGlvbk9mSUNVTWVzc2FnZVJlZlBhcnQocGFydDogUGFyc2VkTWVzc2FnZVBhcnRJQ1VNZXNzYWdlUmVmLCByb290RWxlbTogRWxlbWVudCk6IE5vZGUge1xyXG4gICAgICAgIGNvbnN0IHBoRWxlbSA9IHJvb3RFbGVtLm93bmVyRG9jdW1lbnQuY3JlYXRlRWxlbWVudCgncGgnKTtcclxuICAgICAgICBsZXQgbmFtZUF0dHJpYiA9ICdJQ1UnO1xyXG4gICAgICAgIGlmIChwYXJ0LmluZGV4KCkgPiAwKSB7XHJcbiAgICAgICAgICAgIG5hbWVBdHRyaWIgPSAnSUNVXycgKyBwYXJ0LmluZGV4KCkudG9TdHJpbmcoMTApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBwaEVsZW0uc2V0QXR0cmlidXRlKCduYW1lJywgbmFtZUF0dHJpYik7XHJcbiAgICAgICAgY29uc3QgZXhFbGVtID0gcm9vdEVsZW0ub3duZXJEb2N1bWVudC5jcmVhdGVFbGVtZW50KCdleCcpO1xyXG4gICAgICAgIGV4RWxlbS5hcHBlbmRDaGlsZChyb290RWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5hbWVBdHRyaWIpKTtcclxuICAgICAgICBwaEVsZW0uYXBwZW5kQ2hpbGQoZXhFbGVtKTtcclxuICAgICAgICByZXR1cm4gcGhFbGVtO1xyXG4gICAgfVxyXG59XHJcbiJdfQ==