UNPKG

@ngx-i18nsupport/ngx-i18nsupport-lib

Version:

A Typescript library to work with Angular generated i18n files (xliff, xmb)

732 lines 71.9 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { ParsedMessagePartType } from './parsed-message-part'; import { ParsedMessagePartText } from './parsed-message-part-text'; import { ParsedMessagePartPlaceholder } from './parsed-message-part-placeholder'; import { ParsedMessagePartStartTag } from './parsed-message-part-start-tag'; import { ParsedMessagePartEndTag } from './parsed-message-part-end-tag'; import { DOMUtilities } from './dom-utilities'; import { format, isNullOrUndefined } from 'util'; import { ParsedMessagePartICUMessage } from './parsed-message-part-icu-message'; import { ParsedMessagePartICUMessageRef } from './parsed-message-part-icu-message-ref'; import { ParsedMessagePartEmptyTag } from './parsed-message-part-empty-tag'; /** * Created by martin on 05.05.2017. * A message text read from a translation file. * Can contain placeholders, tags, text. * This class is a representation independent of the concrete format. */ export class ParsedMessage { /** * @param {?} parser * @param {?} sourceMessage */ constructor(parser, sourceMessage) { this._parser = parser; this.sourceMessage = sourceMessage; this._parts = []; } /** * Get the parser (for tests only, not part of API) * @return {?} parser */ getParser() { return this._parser; } /** * Create a new normalized message as a translation of this one. * @throws an error if normalized string is not well formed. * Throws an error too, if this is an ICU message. * @param {?} normalizedString the translation in normalized form. * If the message is an ICUMessage (getICUMessage returns a value), use translateICUMessage instead. * @return {?} */ translate(normalizedString) { if (isNullOrUndefined(this.getICUMessage())) { return this._parser.parseNormalizedString((/** @type {?} */ (normalizedString)), this); } else { throw new Error(format('cannot translate ICU message with simple string, use translateICUMessage() instead ("%s", "%s")', normalizedString, this.asNativeString())); } } /** * Create a new normalized icu message as a translation of this one. * @throws an error if normalized string is not well formed. * Throws an error too, if this is not an ICU message. * @param {?} icuTranslation the translation, this is the translation of the ICU message, * which is not a string, but a collections of the translations of the different categories. * The message must be an ICUMessage (getICUMessage returns a value) * @return {?} */ translateICUMessage(icuTranslation) { /** @type {?} */ const icuMessage = this.getICUMessage(); if (isNullOrUndefined(icuMessage)) { throw new Error(format('this is not an ICU message, use translate() instead ("%s", "%s")', icuTranslation, this.asNativeString())); } else { /** @type {?} */ const translatedICUMessage = icuMessage.translate(icuTranslation); return this._parser.parseICUMessage(translatedICUMessage.asNativeString(), this); } } /** * Create a new normalized message from a native xml string as a translation of this one. * @param {?} nativeString xml string in the format of the underlying file format. * Throws an error if native string is not acceptable. * @return {?} */ translateNativeString(nativeString) { return this._parser.createNormalizedMessageFromXMLString(nativeString, this); } /** * normalized message as string. * @param {?=} displayFormat optional way to determine the exact syntax. * Allowed formats are defined as constants NORMALIZATION_FORMAT... * @return {?} */ asDisplayString(displayFormat) { return this._parts.map((/** * @param {?} part * @return {?} */ (part) => part.asDisplayString(displayFormat))).join(''); } /** * Returns the message content as format dependent native string. * Includes all format specific markup like <ph id="INTERPOLATION" ../> .. * @return {?} */ asNativeString() { if (isNullOrUndefined(this.getICUMessage())) { return DOMUtilities.getXMLContent(this._xmlRepresentation); } else { return this.getICUMessage().asNativeString(); } } /** * Validate the message. * @return {?} null, if ok, error object otherwise. */ validate() { /** @type {?} */ let hasErrors = false; /** @type {?} */ const errors = {}; /** @type {?} */ let e; e = this.checkPlaceholderAdded(); if (!isNullOrUndefined(e)) { errors.placeholderAdded = e; hasErrors = true; } e = this.checkICUMessageRefRemoved(); if (!isNullOrUndefined(e)) { errors.icuMessageRefRemoved = e; hasErrors = true; } e = this.checkICUMessageRefAdded(); if (!isNullOrUndefined(e)) { errors.icuMessageRefAdded = e; hasErrors = true; } return hasErrors ? errors : null; } /** * Validate the message, check for warnings only. * A warning shows, that the message is acceptable, but misses something. * E.g. if you remove a placeholder or a special tag from the original message, this generates a warning. * @return {?} null, if no warning, warnings as error object otherwise. */ validateWarnings() { /** @type {?} */ let hasWarnings = false; /** @type {?} */ const warnings = {}; /** @type {?} */ let w; w = this.checkPlaceholderRemoved(); if (!isNullOrUndefined(w)) { warnings.placeholderRemoved = w; hasWarnings = true; } w = this.checkTagRemoved(); if (!isNullOrUndefined(w)) { warnings.tagRemoved = w; hasWarnings = true; } w = this.checkTagAdded(); if (!isNullOrUndefined(w)) { warnings.tagAdded = w; hasWarnings = true; } return hasWarnings ? warnings : null; } /** * Test wether this message is an ICU message. * @return {?} true, if it is an ICU message. */ isICUMessage() { return this._parts.length === 1 && this._parts[0].type === ParsedMessagePartType.ICU_MESSAGE; } /** * Test wether this message contains an ICU message reference. * ICU message references are something like <x ID="ICU"../>. * @return {?} true, if there is an ICU message reference in the message. */ containsICUMessageRef() { return this._parts.findIndex((/** * @param {?} part * @return {?} */ part => part.type === ParsedMessagePartType.ICU_MESSAGE_REF)) >= 0; } /** * If this message is an ICU message, returns its structure. * Otherwise this method returns null. * @return {?} ICUMessage or null. */ getICUMessage() { if (this._parts.length === 1 && this._parts[0].type === ParsedMessagePartType.ICU_MESSAGE) { /** @type {?} */ const icuPart = (/** @type {?} */ (this._parts[0])); return icuPart.getICUMessage(); } else { return null; } } /** * Check for added placeholder. * @private * @return {?} null or message, if fulfilled. */ checkPlaceholderAdded() { /** @type {?} */ let e = null; /** @type {?} */ const suspiciousIndexes = []; if (this.sourceMessage) { /** @type {?} */ const sourcePlaceholders = this.sourceMessage.allPlaceholders(); /** @type {?} */ const myPlaceholders = this.allPlaceholders(); myPlaceholders.forEach((/** * @param {?} index * @return {?} */ (index) => { if (!sourcePlaceholders.has(index)) { suspiciousIndexes.push(index); } })); } if (suspiciousIndexes.length === 1) { e = 'added placeholder ' + suspiciousIndexes[0] + ', which is not in original message'; } else if (suspiciousIndexes.length > 1) { /** @type {?} */ let allSuspiciousIndexes = ''; /** @type {?} */ let first = true; suspiciousIndexes.forEach((/** * @param {?} index * @return {?} */ (index) => { if (!first) { allSuspiciousIndexes = allSuspiciousIndexes + ', '; } allSuspiciousIndexes = allSuspiciousIndexes + index; first = false; })); e = 'added placeholders ' + allSuspiciousIndexes + ', which are not in original message'; } return e; } /** * Check for removed placeholder. * @private * @return {?} null or message, if fulfilled. */ checkPlaceholderRemoved() { /** @type {?} */ let w = null; /** @type {?} */ const suspiciousIndexes = []; if (this.sourceMessage) { /** @type {?} */ const sourcePlaceholders = this.sourceMessage.allPlaceholders(); /** @type {?} */ const myPlaceholders = this.allPlaceholders(); sourcePlaceholders.forEach((/** * @param {?} index * @return {?} */ (index) => { if (!myPlaceholders.has(index)) { suspiciousIndexes.push(index); } })); } if (suspiciousIndexes.length === 1) { w = 'removed placeholder ' + suspiciousIndexes[0] + ' from original message'; } else if (suspiciousIndexes.length > 1) { /** @type {?} */ let allSuspiciousIndexes = ''; /** @type {?} */ let first = true; suspiciousIndexes.forEach((/** * @param {?} index * @return {?} */ (index) => { if (!first) { allSuspiciousIndexes = allSuspiciousIndexes + ', '; } allSuspiciousIndexes = allSuspiciousIndexes + index; first = false; })); w = 'removed placeholders ' + allSuspiciousIndexes + ' from original message'; } return w; } /** * Check for added ICU Message Refs. * @private * @return {?} null or message, if fulfilled. */ checkICUMessageRefAdded() { /** @type {?} */ let e = null; /** @type {?} */ const suspiciousIndexes = []; if (this.sourceMessage) { /** @type {?} */ const sourceICURefs = this.sourceMessage.allICUMessageRefs(); /** @type {?} */ const myICURefs = this.allICUMessageRefs(); myICURefs.forEach((/** * @param {?} index * @return {?} */ (index) => { if (!sourceICURefs.has(index)) { suspiciousIndexes.push(index); } })); } if (suspiciousIndexes.length === 1) { e = 'added ICU message reference ' + suspiciousIndexes[0] + ', which is not in original message'; } else if (suspiciousIndexes.length > 1) { /** @type {?} */ let allSuspiciousIndexes = ''; /** @type {?} */ let first = true; suspiciousIndexes.forEach((/** * @param {?} index * @return {?} */ (index) => { if (!first) { allSuspiciousIndexes = allSuspiciousIndexes + ', '; } allSuspiciousIndexes = allSuspiciousIndexes + index; first = false; })); e = 'added ICU message references ' + allSuspiciousIndexes + ', which are not in original message'; } return e; } /** * Check for removed ICU Message Refs. * @private * @return {?} null or message, if fulfilled. */ checkICUMessageRefRemoved() { /** @type {?} */ let e = null; /** @type {?} */ const suspiciousIndexes = []; if (this.sourceMessage) { /** @type {?} */ const sourceICURefs = this.sourceMessage.allICUMessageRefs(); /** @type {?} */ const myICURefs = this.allICUMessageRefs(); sourceICURefs.forEach((/** * @param {?} index * @return {?} */ (index) => { if (!myICURefs.has(index)) { suspiciousIndexes.push(index); } })); } if (suspiciousIndexes.length === 1) { e = 'removed ICU message reference ' + suspiciousIndexes[0] + ' from original message'; } else if (suspiciousIndexes.length > 1) { /** @type {?} */ let allSuspiciousIndexes = ''; /** @type {?} */ let first = true; suspiciousIndexes.forEach((/** * @param {?} index * @return {?} */ (index) => { if (!first) { allSuspiciousIndexes = allSuspiciousIndexes + ', '; } allSuspiciousIndexes = allSuspiciousIndexes + index; first = false; })); e = 'removed ICU message references ' + allSuspiciousIndexes + ' from original message'; } return e; } /** * Get all indexes of placeholders used in the message. * @private * @return {?} */ allPlaceholders() { /** @type {?} */ const result = new Set(); this.parts().forEach((/** * @param {?} part * @return {?} */ (part) => { if (part.type === ParsedMessagePartType.PLACEHOLDER) { /** @type {?} */ const index = ((/** @type {?} */ (part))).index(); result.add(index); } })); return result; } /** * Return the disp-Attribute of placeholder * @param {?} index index of placeholder * @return {?} disp or null */ getPlaceholderDisp(index) { /** @type {?} */ let placeHolder = null; this.parts().forEach((/** * @param {?} part * @return {?} */ (part) => { if (part.type === ParsedMessagePartType.PLACEHOLDER) { /** @type {?} */ const phPart = (/** @type {?} */ (part)); if (phPart.index() === index) { placeHolder = phPart; } } })); return placeHolder ? placeHolder.disp() : null; } /** * Get all indexes of ICU message refs used in the message. * @private * @return {?} */ allICUMessageRefs() { /** @type {?} */ const result = new Set(); this.parts().forEach((/** * @param {?} part * @return {?} */ (part) => { if (part.type === ParsedMessagePartType.ICU_MESSAGE_REF) { /** @type {?} */ const index = ((/** @type {?} */ (part))).index(); result.add(index); } })); return result; } /** * Return the disp-Attribute of icu message ref * @param {?} index of ref * @return {?} disp or null */ getICUMessageRefDisp(index) { /** @type {?} */ let icuMessageRefPart = null; this.parts().forEach((/** * @param {?} part * @return {?} */ (part) => { if (part.type === ParsedMessagePartType.ICU_MESSAGE_REF) { /** @type {?} */ const refPart = (/** @type {?} */ (part)); if (refPart.index() === index) { icuMessageRefPart = refPart; } } })); return icuMessageRefPart ? icuMessageRefPart.disp() : null; } /** * Check for added tags. * @private * @return {?} null or message, if fulfilled. */ checkTagAdded() { /** @type {?} */ let e = null; /** @type {?} */ const suspiciousTags = []; if (this.sourceMessage) { /** @type {?} */ const sourceTags = this.sourceMessage.allTags(); /** @type {?} */ const myTags = this.allTags(); myTags.forEach((/** * @param {?} tagName * @return {?} */ (tagName) => { if (!sourceTags.has(tagName)) { suspiciousTags.push(tagName); } })); } if (suspiciousTags.length === 1) { e = 'added tag <' + suspiciousTags[0] + '>, which is not in original message'; } else if (suspiciousTags.length > 1) { /** @type {?} */ let allSuspiciousTags = ''; /** @type {?} */ let first = true; suspiciousTags.forEach((/** * @param {?} tag * @return {?} */ (tag) => { if (!first) { allSuspiciousTags = allSuspiciousTags + ', '; } allSuspiciousTags = allSuspiciousTags + '<' + tag + '>'; first = false; })); e = 'added tags ' + allSuspiciousTags + ', which are not in original message'; } return e; } /** * Check for removed tags. * @private * @return {?} null or message, if fulfilled. */ checkTagRemoved() { /** @type {?} */ let w = null; /** @type {?} */ const suspiciousTags = []; if (this.sourceMessage) { /** @type {?} */ const sourceTags = this.sourceMessage.allTags(); /** @type {?} */ const myTags = this.allTags(); sourceTags.forEach((/** * @param {?} tagName * @return {?} */ (tagName) => { if (!myTags.has(tagName)) { suspiciousTags.push(tagName); } })); } if (suspiciousTags.length === 1) { w = 'removed tag <' + suspiciousTags[0] + '> from original message'; } else if (suspiciousTags.length > 1) { /** @type {?} */ let allSuspiciousTags = ''; /** @type {?} */ let first = true; suspiciousTags.forEach((/** * @param {?} tag * @return {?} */ (tag) => { if (!first) { allSuspiciousTags = allSuspiciousTags + ', '; } allSuspiciousTags = allSuspiciousTags + '<' + tag + '>'; first = false; })); w = 'removed tags ' + allSuspiciousTags + ' from original message'; } return w; } /** * Get all tag names used in the message. * @private * @return {?} */ allTags() { /** @type {?} */ const result = new Set(); this.parts().forEach((/** * @param {?} part * @return {?} */ (part) => { if (part.type === ParsedMessagePartType.START_TAG || part.type === ParsedMessagePartType.EMPTY_TAG) { /** @type {?} */ const tagName = ((/** @type {?} */ (part))).tagName(); result.add(tagName); } })); return result; } /** * @return {?} */ parts() { return this._parts; } /** * @param {?} xmlRepresentation * @return {?} */ setXmlRepresentation(xmlRepresentation) { this._xmlRepresentation = xmlRepresentation; } /** * @param {?} text * @return {?} */ addText(text) { this._parts.push(new ParsedMessagePartText(text)); } /** * @param {?} index * @param {?} disp * @return {?} */ addPlaceholder(index, disp) { this._parts.push(new ParsedMessagePartPlaceholder(index, disp)); } /** * @param {?} tagname * @param {?} idcounter * @return {?} */ addStartTag(tagname, idcounter) { this._parts.push(new ParsedMessagePartStartTag(tagname, idcounter)); } /** * @param {?} tagname * @return {?} */ addEndTag(tagname) { // check if well formed /** @type {?} */ const openTag = this.calculateOpenTagName(); if (!openTag || openTag !== tagname) { // oops, not well formed throw new Error(format('unexpected close tag %s (currently open is %s, native xml is "%s")', tagname, openTag, this.asNativeString())); } this._parts.push(new ParsedMessagePartEndTag(tagname)); } /** * @param {?} tagname * @param {?} idcounter * @return {?} */ addEmptyTag(tagname, idcounter) { this._parts.push(new ParsedMessagePartEmptyTag(tagname, idcounter)); } /** * @param {?} index * @param {?} disp * @return {?} */ addICUMessageRef(index, disp) { this._parts.push(new ParsedMessagePartICUMessageRef(index, disp)); } /** * @param {?} text * @return {?} */ addICUMessage(text) { this._parts.push(new ParsedMessagePartICUMessage(text, this._parser)); } /** * Determine, wether there is an open tag, that is not closed. * Returns the latest one or null, if there is no open tag. * @private * @return {?} */ calculateOpenTagName() { /** @type {?} */ const openTags = []; this._parts.forEach((/** * @param {?} part * @return {?} */ (part) => { switch (part.type) { case ParsedMessagePartType.START_TAG: openTags.push(((/** @type {?} */ (part))).tagName()); break; case ParsedMessagePartType.END_TAG: /** @type {?} */ const tagName = ((/** @type {?} */ (part))).tagName(); if (openTags.length === 0 || openTags[openTags.length - 1] !== tagName) { // oops, not well formed /** @type {?} */ const openTag = (openTags.length === 0) ? 'nothing' : openTags[openTags.length - 1]; throw new Error(format('unexpected close tag %s (currently open is %s, native xml is "%s")', tagName, openTag, this.asNativeString())); } openTags.pop(); } })); return openTags.length === 0 ? null : openTags[openTags.length - 1]; } } if (false) { /** * Parser that created this message (determines the native format). * @type {?} * @private */ ParsedMessage.prototype._parser; /** * The message where this one stems from as translation. * Optional, set only for messages created by calling translate. * @type {?} * @private */ ParsedMessage.prototype.sourceMessage; /** * The parts of the message. * @type {?} * @private */ ParsedMessage.prototype._parts; /** * messages xml representation. * @type {?} * @private */ ParsedMessage.prototype._xmlRepresentation; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VkLW1lc3NhZ2UuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9Abmd4LWkxOG5zdXBwb3J0L25neC1pMThuc3VwcG9ydC1saWIvIiwic291cmNlcyI6WyJpbXBsL3BhcnNlZC1tZXNzYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQW9CLHFCQUFxQixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDL0UsT0FBTyxFQUFDLHFCQUFxQixFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFDakUsT0FBTyxFQUFDLDRCQUE0QixFQUFDLE1BQU0sbUNBQW1DLENBQUM7QUFDL0UsT0FBTyxFQUFDLHlCQUF5QixFQUFDLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFDLHVCQUF1QixFQUFDLE1BQU0sK0JBQStCLENBQUM7QUFFdEUsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRTdDLE9BQU8sRUFBQyxNQUFNLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFFL0MsT0FBTyxFQUFDLDJCQUEyQixFQUFDLE1BQU0sbUNBQW1DLENBQUM7QUFDOUUsT0FBTyxFQUFDLDhCQUE4QixFQUFDLE1BQU0sdUNBQXVDLENBQUM7QUFFckYsT0FBTyxFQUFDLHlCQUF5QixFQUFDLE1BQU0saUNBQWlDLENBQUM7Ozs7Ozs7QUFPMUUsTUFBTSxPQUFPLGFBQWE7Ozs7O0lBdUJ0QixZQUFZLE1BQXNCLEVBQUUsYUFBNEI7UUFDNUQsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7UUFDdEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7UUFDbkMsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUM7SUFDckIsQ0FBQzs7Ozs7SUFNRCxTQUFTO1FBQ0wsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3hCLENBQUM7Ozs7Ozs7OztJQVNELFNBQVMsQ0FBQyxnQkFBd0I7UUFDOUIsSUFBSSxpQkFBaUIs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QUMsQ0FBQyxDQUFDO3FCQUNqRDtvQkFDRCxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUM7YUFDdEI7UUFDTCxDQUFDLEVBQUMsQ0FBQztRQUNILE9BQU8sUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDeEUsQ0FBQztDQUNKOzs7Ozs7O0lBOWdCRyxnQ0FBZ0M7Ozs7Ozs7SUFNaEMsc0NBQXFDOzs7Ozs7SUFLckMsK0JBQW9DOzs7Ozs7SUFLcEMsMkNBQW9DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtQYXJzZWRNZXNzYWdlUGFydCwgUGFyc2VkTWVzc2FnZVBhcnRUeXBlfSBmcm9tICcuL3BhcnNlZC1tZXNzYWdlLXBhcnQnO1xyXG5pbXBvcnQge1BhcnNlZE1lc3NhZ2VQYXJ0VGV4dH0gZnJvbSAnLi9wYXJzZWQtbWVzc2FnZS1wYXJ0LXRleHQnO1xyXG5pbXBvcnQge1BhcnNlZE1lc3NhZ2VQYXJ0UGxhY2Vob2xkZXJ9IGZyb20gJy4vcGFyc2VkLW1lc3NhZ2UtcGFydC1wbGFjZWhvbGRlcic7XHJcbmltcG9ydCB7UGFyc2VkTWVzc2FnZVBhcnRTdGFydFRhZ30gZnJvbSAnLi9wYXJzZWQtbWVzc2FnZS1wYXJ0LXN0YXJ0LXRhZyc7XHJcbmltcG9ydCB7UGFyc2VkTWVzc2FnZVBhcnRFbmRUYWd9IGZyb20gJy4vcGFyc2VkLW1lc3NhZ2UtcGFydC1lbmQtdGFnJztcclxuaW1wb3J0IHtJTm9ybWFsaXplZE1lc3NhZ2UsIFZhbGlkYXRpb25FcnJvcnN9IGZyb20gJy4uL2FwaS9pLW5vcm1hbGl6ZWQtbWVzc2FnZSc7XHJcbmltcG9ydCB7RE9NVXRpbGl0aWVzfSBmcm9tICcuL2RvbS11dGlsaXRpZXMnO1xyXG5pbXBvcnQge0lNZXNzYWdlUGFyc2VyfSBmcm9tICcuL2ktbWVzc2FnZS1wYXJzZXInO1xyXG5pbXBvcnQge2Zvcm1hdCwgaXNOdWxsT3JVbmRlZmluZWR9IGZyb20gJ3V0aWwnO1xyXG5pbXBvcnQge0lJQ1VNZXNzYWdlLCBJSUNVTWVzc2FnZVRyYW5zbGF0aW9ufSBmcm9tICcuLi9hcGkvaS1pY3UtbWVzc2FnZSc7XHJcbmltcG9ydCB7UGFyc2VkTWVzc2FnZVBhcnRJQ1VNZXNzYWdlfSBmcm9tICcuL3BhcnNlZC1tZXNzYWdlLXBhcnQtaWN1LW1lc3NhZ2UnO1xyXG5pbXBvcnQge1BhcnNlZE1lc3NhZ2VQYXJ0SUNVTWVzc2FnZVJlZn0gZnJvbSAnLi9wYXJzZWQtbWVzc2FnZS1wYXJ0LWljdS1tZXNzYWdlLXJlZic7XHJcbmltcG9ydCB7SUNVTWVzc2FnZX0gZnJvbSAnLi9pY3UtbWVzc2FnZSc7XHJcbmltcG9ydCB7UGFyc2VkTWVzc2FnZVBhcnRFbXB0eVRhZ30gZnJvbSAnLi9wYXJzZWQtbWVzc2FnZS1wYXJ0LWVtcHR5LXRhZyc7XHJcbi8qKlxyXG4gKiBDcmVhdGVkIGJ5IG1hcnRpbiBvbiAwNS4wNS4yMDE3LlxyXG4gKiBBIG1lc3NhZ2UgdGV4dCByZWFkIGZyb20gYSB0cmFuc2xhdGlvbiBmaWxlLlxyXG4gKiBDYW4gY29udGFpbiBwbGFjZWhvbGRlcnMsIHRhZ3MsIHRleHQuXHJcbiAqIFRoaXMgY2xhc3MgaXMgYSByZXByZXNlbnRhdGlvbiBpbmRlcGVuZGVudCBvZiB0aGUgY29uY3JldGUgZm9ybWF0LlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFBhcnNlZE1lc3NhZ2UgaW1wbGVtZW50cyBJTm9ybWFsaXplZE1lc3NhZ2Uge1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFyc2VyIHRoYXQgY3JlYXRlZCB0aGlzIG1lc3NhZ2UgKGRldGVybWluZXMgdGhlIG5hdGl2ZSBmb3JtYXQpLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIF9wYXJzZXI6IElNZXNzYWdlUGFyc2VyO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIG1lc3NhZ2Ugd2hlcmUgdGhpcyBvbmUgc3RlbXMgZnJvbSBhcyB0cmFuc2xhdGlvbi5cclxuICAgICAqIE9wdGlvbmFsLCBzZXQgb25seSBmb3IgbWVzc2FnZXMgY3JlYXRlZCBieSBjYWxsaW5nIHRyYW5zbGF0ZS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBzb3VyY2VNZXNzYWdlOiBQYXJzZWRNZXNzYWdlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIHBhcnRzIG9mIHRoZSBtZXNzYWdlLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIF9wYXJ0czogUGFyc2VkTWVzc2FnZVBhcnRbXTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIG1lc3NhZ2VzIHhtbCByZXByZXNlbnRhdGlvbi5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBfeG1sUmVwcmVzZW50YXRpb246IEVsZW1lbnQ7XHJcblxyXG4gICAgY29uc3RydWN0b3IocGFyc2VyOiBJTWVzc2FnZVBhcnNlciwgc291cmNlTWVzc2FnZTogUGFyc2VkTWVzc2FnZSkge1xyXG4gICAgICAgIHRoaXMuX3BhcnNlciA9IHBhcnNlcjtcclxuICAgICAgICB0aGlzLnNvdXJjZU1lc3NhZ2UgPSBzb3VyY2VNZXNzYWdlO1xyXG4gICAgICAgIHRoaXMuX3BhcnRzID0gW107XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXQgdGhlIHBhcnNlciAoZm9yIHRlc3RzIG9ubHksIG5vdCBwYXJ0IG9mIEFQSSlcclxuICAgICAqIEByZXR1cm4gcGFyc2VyXHJcbiAgICAgKi9cclxuICAgIGdldFBhcnNlcigpOiBJTWVzc2FnZVBhcnNlciB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BhcnNlcjtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZSBhIG5ldyBub3JtYWxpemVkIG1lc3NhZ2UgYXMgYSB0cmFuc2xhdGlvbiBvZiB0aGlzIG9uZS5cclxuICAgICAqIEBwYXJhbSBub3JtYWxpemVkU3RyaW5nIHRoZSB0cmFuc2xhdGlvbiBpbiBub3JtYWxpemVkIGZvcm0uXHJcbiAgICAgKiBJZiB0aGUgbWVzc2FnZSBpcyBhbiBJQ1VNZXNzYWdlIChnZXRJQ1VNZXNzYWdlIHJldHVybnMgYSB2YWx1ZSksIHVzZSB0cmFuc2xhdGVJQ1VNZXNzYWdlIGluc3RlYWQuXHJcbiAgICAgKiBAdGhyb3dzIGFuIGVycm9yIGlmIG5vcm1hbGl6ZWQgc3RyaW5nIGlzIG5vdCB3ZWxsIGZvcm1lZC5cclxuICAgICAqIFRocm93cyBhbiBlcnJvciB0b28sIGlmIHRoaXMgaXMgYW4gSUNVIG1lc3NhZ2UuXHJcbiAgICAgKi9cclxuICAgIHRyYW5zbGF0ZShub3JtYWxpemVkU3RyaW5nOiBzdHJpbmcpOiBJTm9ybWFsaXplZE1lc3NhZ2Uge1xyXG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZCh0aGlzLmdldElDVU1lc3NhZ2UoKSkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BhcnNlci5wYXJzZU5vcm1hbGl6ZWRTdHJpbmcoPHN0cmluZz4gbm9ybWFsaXplZFN0cmluZywgdGhpcyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGZvcm1hdCgnY2Fubm90IHRyYW5zbGF0ZSBJQ1UgbWVzc2FnZSB3aXRoIHNpbXBsZSBzdHJpbmcsIHVzZSB0cmFuc2xhdGVJQ1VNZXNzYWdlKCkgaW5zdGVhZCAoXCIlc1wiLCBcIiVzXCIpJyxcclxuICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRTdHJpbmcsIHRoaXMuYXNOYXRpdmVTdHJpbmcoKSkpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZSBhIG5ldyBub3JtYWxpemVkIGljdSBtZXNzYWdlIGFzIGEgdHJhbnNsYXRpb24gb2YgdGhpcyBvbmUuXHJcbiAgICAgKiBAcGFyYW0gaWN1VHJhbnNsYXRpb24gdGhlIHRyYW5zbGF0aW9uLCB0aGlzIGlzIHRoZSB0cmFuc2xhdGlvbiBvZiB0aGUgSUNVIG1lc3NhZ2UsXHJcbiAgICAgKiB3aGljaCBpcyBub3QgYSBzdHJpbmcsIGJ1dCBhIGNvbGxlY3Rpb25zIG9mIHRoZSB0cmFuc2xhdGlvbnMgb2YgdGhlIGRpZmZlcmVudCBjYXRlZ29yaWVzLlxyXG4gICAgICogVGhlIG1lc3NhZ2UgbXVzdCBiZSBhbiBJQ1VNZXNzYWdlIChnZXRJQ1VNZXNzYWdlIHJldHVybnMgYSB2YWx1ZSlcclxuICAgICAqIEB0aHJvd3MgYW4gZXJyb3IgaWYgbm9ybWFsaXplZCBzdHJpbmcgaXMgbm90IHdlbGwgZm9ybWVkLlxyXG4gICAgICogVGhyb3dzIGFuIGVycm9yIHRvbywgaWYgdGhpcyBpcyBub3QgYW4gSUNVIG1lc3NhZ2UuXHJcbiAgICAgKi9cclxuICAgIHRyYW5zbGF0ZUlDVU1lc3NhZ2UoaWN1VHJhbnNsYXRpb246IElJQ1VNZXNzYWdlVHJhbnNsYXRpb24pOiBJTm9ybWFsaXplZE1lc3NhZ2Uge1xyXG4gICAgICAgIGNvbnN0IGljdU1lc3NhZ2U6IElJQ1VNZXNzYWdlID0gdGhpcy5nZXRJQ1VNZXNzYWdlKCk7XHJcbiAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWZpbmVkKGljdU1lc3NhZ2UpKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihmb3JtYXQoJ3RoaXMgaXMgbm90IGFuIElDVSBtZXNzYWdlLCB1c2UgdHJhbnNsYXRlKCkgaW5zdGVhZCAoXCIlc1wiLCBcIiVzXCIpJyxcclxuICAgICAgICAgICAgICAgIGljdVRyYW5zbGF0aW9uLCAgdGhpcy5hc05hdGl2ZVN0cmluZygpKSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc3QgdHJhbnNsYXRlZElDVU1lc3NhZ2U6IElJQ1VNZXNzYWdlID0gaWN1TWVzc2FnZS50cmFuc2xhdGUoaWN1VHJhbnNsYXRpb24pO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fcGFyc2VyLnBhcnNlSUNVTWVzc2FnZSh0cmFuc2xhdGVkSUNVTWVzc2FnZS5hc05hdGl2ZVN0cmluZygpLCB0aGlzKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGUgYSBuZXcgbm9ybWFsaXplZCBtZXNzYWdlIGZyb20gYSBuYXRpdmUgeG1sIHN0cmluZyBhcyBhIHRyYW5zbGF0aW9uIG9mIHRoaXMgb25lLlxyXG4gICAgICogQHBhcmFtIG5hdGl2ZVN0cmluZyB4bWwgc3RyaW5nIGluIHRoZSBmb3JtYXQgb2YgdGhlIHVuZGVybHlpbmcgZmlsZSBmb3JtYXQuXHJcbiAgICAgKiBUaHJvd3MgYW4gZXJyb3IgaWYgbmF0aXZlIHN0cmluZyBpcyBub3QgYWNjZXB0YWJsZS5cclxuICAgICAqL1xyXG4gICAgdHJhbnNsYXRlTmF0aXZlU3RyaW5nKG5hdGl2ZVN0cmluZzogc3RyaW5nKTogSU5vcm1hbGl6ZWRNZXNzYWdlIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fcGFyc2VyLmNyZWF0ZU5vcm1hbGl6ZWRNZXNzYWdlRnJvbVhNTFN0cmluZyhuYXRpdmVTdHJpbmcsIHRoaXMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogbm9ybWFsaXplZCBtZXNzYWdlIGFzIHN0cmluZy5cclxuICAgICAqIEBwYXJhbSBkaXNwbGF5Rm9ybWF0IG9wdGlvbmFsIHdheSB0byBkZXRlcm1pbmUgdGhlIGV4YWN0IHN5bnRheC5cclxuICAgICAqIEFsbG93ZWQgZm9ybWF0cyBhcmUgZGVmaW5lZCBhcyBjb25zdGFudHMgTk9STUFMSVpBVElPTl9GT1JNQVQuLi5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGFzRGlzcGxheVN0cmluZyhkaXNwbGF5Rm9ybWF0Pzogc3RyaW5nKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BhcnRzLm1hcCgocGFydCkgPT4gcGFydC5hc0Rpc3BsYXlTdHJpbmcoZGlzcGxheUZvcm1hdCkpLmpvaW4oJycpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgbWVzc2FnZSBjb250ZW50IGFzIGZvcm1hdCBkZXBlbmRlbnQgbmF0aXZlIHN0cmluZy5cclxuICAgICAqIEluY2x1ZGVzIGFsbCBmb3JtYXQgc3BlY2lmaWMgbWFya3VwIGxpa2UgPHBoIGlkPVwiSU5URVJQT0xBVElPTlwiIC4uLz4gLi5cclxuICAgICAqL1xyXG4gICAgYXNOYXRpdmVTdHJpbmcoKTogc3RyaW5nIHtcclxuICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZmluZWQodGhpcy5nZXRJQ1VNZXNzYWdlKCkpKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBET01VdGlsaXRpZXMuZ2V0WE1MQ29udGVudCh0aGlzLl94bWxSZXByZXNlbnRhdGlvbik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SUNVTWVzc2FnZSgpLmFzTmF0aXZlU3RyaW5nKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmFsaWRhdGUgdGhlIG1lc3NhZ2UuXHJcbiAgICAgKiBAcmV0dXJuIG51bGwsIGlmIG9rLCBlcnJvciBvYmplY3Qgb3RoZXJ3aXNlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdmFsaWRhdGUoKTogVmFsaWRhdGlvbkVycm9ycyB8IG51bGwge1xyXG4gICAgICAgIGxldCBoYXNFcnJvcnMgPSBmYWxzZTtcclxuICAgICAgICBjb25zdCBlcnJvcnM6IFZhbGlkYXRpb25FcnJvcnMgPSB7fTtcclxuICAgICAgICBsZXQgZTtcclxuICAgICAgICBlID0gdGhpcy5jaGVja1BsYWNlaG9sZGVyQWRkZWQoKTtcclxuICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKGUpKSB7XHJcbiAgICAgICAgICAgIGVycm9ycy5wbGFjZWhvbGRlckFkZGVkID0