UNPKG

@singleton-i18n/angular-client

Version:

Singleton client code for Angular 10.

256 lines 33.7 kB
import { __awaiter } from "tslib"; /* * Copyright 2019-2021 VMware, Inc. * SPDX-License-Identifier: EPL-2.0 */ import { Injectable } from '@angular/core'; import { EventEmitter } from '@angular/core'; import { LocaleService } from './locale.service'; import { I18nLoader } from '../loader'; import { mergeObject, assign, deprecatedWarn } from '../util'; import { concat, Observable, forkJoin, of } from 'rxjs'; import { share, switchMap, take, catchError } from 'rxjs/operators'; import { getNameSpace, VIPConfigFactory } from '../config'; import { I18nContext } from './i18n.context'; export class VIPService { constructor(localeService, i18nContext, currentLoader) { this.localeService = localeService; this.i18nContext = i18nContext; this.currentLoader = currentLoader; this.pending = false; this.configs = []; this.availableLocales = []; this._onLocaleChange = new EventEmitter(); this._i18nScope = []; this._localeData = {}; } get onLocaleChange() { return this._onLocaleChange; } get localeData() { return this._localeData; } get i18nScope() { return this._i18nScope; } /** * Loading the i18n data at app module or root of lazy module. * @param config For root module or lazy load mdule. */ initData(config) { return __awaiter(this, void 0, void 0, function* () { this.subscribeLocaleSubject(); this.registerComponent(config, true); this.initLocale(config); yield this.loadLocaleData(); }); } /** * Init locale by config passed from root module for compatibility. * Will be removed in v9. * @param config */ initLocale(config) { if (config.locale || config.language || config.region) { console.warn('Set language and region by configuration is deprecated, will be removed in v9. ' + 'Please use LocaleService.init instead.'); if (config.language && config.region) { this.localeService.init(config.language, config.region); } else if (config.locale) { this.localeService.init(config.locale); } } } /** * Subscrible the locale changed event from view layer. * For live UI translation update. */ subscribeLocaleSubject() { if (!this.localeSubscription) { this.localeSubscription = this.localeService.userLocaleChanged .subscribe(() => { this.loadLocaleData(); }); } } /** * Specifically, for the feature module which will be imported * to root module or lazy load module. This method should be invoked * in the constructor of feature module. * @param config * @param isMain */ registerComponent(config, isMain = false) { this.subscribeLocaleSubject(); config = VIPConfigFactory(config, this.i18nContext); this.mainConfig = isMain ? config : this.mainConfig; this.configs.push(config); this.updateI18nScope(config); if (config.sourceBundles || config.sourceBundle) { if (config.sourceBundle) { deprecatedWarn('The sourceBundle option in i18n config', 'v10', 'sourceBundles'); } const bundle = config.sourceBundles ? this.resetBundle(config.sourceBundles) : config.sourceBundle; this.processBundle(bundle, this.localeService.defaultLocale.languageCode, config); } } /** * Tentative solution, if translation bundle is mounted. * no longer to consider i18n scope which defined in * feature module configuration. * @param config */ updateI18nScope(config) { if (config.i18nScope && !config.translationBundles) { this._i18nScope = this._i18nScope.concat(config.i18nScope) .filter((elem, index, self) => { return index === self.indexOf(elem); }); } } /** * If the locale is processed or source locale, skip. */ loadLocaleData() { return __awaiter(this, void 0, void 0, function* () { const language = this.localeService.getCurrentLanguage(); const region = this.localeService.getCurrentRegion(); const locale = this.localeService.getCurrentLocale(); if (!this.localeService.isSourceLocale && this.availableLocales.indexOf(locale) === -1 && this.i18nContext.i18nEnabled !== false) { yield this.getLocaleData(language, region, locale) .toPromise(); } this.releaseLocale(locale); }); } getLocaleData(language, region, locale) { const sequencesOfRequest = []; let loadingLocaleData; for (const config of this.configs) { // Bypass sending HTTP call to get translation. // Using local bundle instead. // Using language to map local bundle. // Using locale to store the translation. if (config.translationBundles) { const standardLanguageTag = this.localeService.normalizeLanguageCode(language); const bundle = config.translationBundles[language] || config.translationBundles[standardLanguageTag]; if (bundle) { this.processBundle(bundle, locale, config); } } else { sequencesOfRequest.push(this.currentLoader .getLocaleData(config, language, region) .pipe(share(), catchError((err) => { console.error(`Can't fetch locale data.`, config, err); return of(undefined); }))); } } // No HTTP call required. // Resource of current locale is available. if (sequencesOfRequest.length < 1) { this.availableLocales.push(locale); return of([]); } loadingLocaleData = forkJoin(sequencesOfRequest); this.loadingLocaleData = { data: loadingLocaleData.pipe(take(1), share()), locale: locale }; // FIFO this.pending = true; this.loadingLocaleData.data.subscribe((res) => { this.storeResource(res, this._localeData, locale); this.availableLocales.push(locale); this.pending = false; }, (err) => { this.pending = false; }); return loadingLocaleData; } resetBundle(sourceBundles) { if (Array.isArray(sourceBundles)) { return assign({}, sourceBundles); } return undefined; } processBundle(bundle, locale, config) { const formattedBundle = { 'messages': {} }; const namespace = getNameSpace(config); formattedBundle.messages[namespace] = bundle; this.storeResource([formattedBundle], this._localeData, locale); } storeResource(res, localedata, locale) { if (res) { const supplemental = {}; localedata[locale] = localedata[locale] || {}; res.forEach((element) => { if (element) { if (element.messages) { localedata[locale].messages = mergeObject(localedata[locale].messages, element.messages); } if (element.categories) { localedata[locale].categories = mergeObject(localedata[locale].categories, element.categories); if (element.categories.supplemental) { Object.assign(supplemental, element.categories.supplemental); } } } }); if (localedata[locale].categories) { localedata[locale].categories.supplemental = supplemental; } } } /** * current represents current available locale to cover the initial status. * since in some situation, the 'onLocaleChange' haven't be register always, * or there is no event at time. */ get current() { if (this.pending) { const locale = this.loadingLocaleData.locale; return Observable.create((observer) => { const onComplete = () => { observer.next(locale); observer.complete(); }; this.loadingLocaleData.data.subscribe((res) => { onComplete(); }, onComplete); }); } else { return of(this.localeService.getCurrentLocale()); } } /** * stream of 'available' locale. */ get stream() { return concat(this.current, this.onLocaleChange.pipe(switchMap((locale) => { return of(locale); }))); } releaseLocale(locale) { this.onLocaleChange.emit(locale); } registerSourceBundles(sourceBundles, config) { if (sourceBundles) { const bundle = this.resetBundle(sourceBundles); this.processBundle(bundle, this.localeService.defaultLocale.languageCode, config); } } } VIPService.decorators = [ { type: Injectable } ]; VIPService.ctorParameters = () => [ { type: LocaleService }, { type: I18nContext }, { type: I18nLoader } ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlwLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiL2hvbWUvcmxpZ2VuZy9Qcm9qZWN0cy9EZXZvcHMvQ2xpZW50X0FuZ3VsYXJfR2l0SHViX05wbWpzL3ZpcC9jaS9wdWIyb3JnL0NsaWVudF9Bbmd1bGFyX0dpdEh1Yl9OcG1qcy9zaW5nbGV0b24vcHJvamVjdHMvYW5ndWxhci1jbGllbnQvIiwic291cmNlcyI6WyJzcmMvc2VydmljZXMvdmlwLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRztBQUNILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDakQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN2QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDOUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFZLEVBQUUsRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDaEYsT0FBTyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BFLE9BQU8sRUFBYSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFdEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBYTdDLE1BQU0sT0FBTyxVQUFVO0lBV25CLFlBQ2MsYUFBNEIsRUFDNUIsV0FBd0IsRUFDM0IsYUFBeUI7UUFGdEIsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFDNUIsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDM0Isa0JBQWEsR0FBYixhQUFhLENBQVk7UUFaNUIsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUVoQixZQUFPLEdBQWdCLEVBQUUsQ0FBQztRQUMxQixxQkFBZ0IsR0FBa0IsRUFBRSxDQUFDO1FBRXJDLG9CQUFlLEdBQXlCLElBQUksWUFBWSxFQUFVLENBQUM7UUFDbkUsZUFBVSxHQUFrQixFQUFFLENBQUM7UUFDL0IsZ0JBQVcsR0FBUSxFQUFFLENBQUM7SUFNMUIsQ0FBQztJQUVMLElBQUksY0FBYztRQUNkLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQztJQUNoQyxDQUFDO0lBRUQsSUFBSSxVQUFVO1FBQ1YsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO0lBQzVCLENBQUM7SUFFRCxJQUFJLFNBQVM7UUFDVCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDM0IsQ0FBQztJQUVEOzs7T0FHRztJQUNVLFFBQVEsQ0FBQyxNQUFpQjs7WUFDbkMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNyQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3hCLE1BQU0sSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ2hDLENBQUM7S0FBQTtJQUVEOzs7O09BSUc7SUFDSyxVQUFVLENBQUMsTUFBaUI7UUFDaEMsSUFBSyxNQUFNLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxRQUFRLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRztZQUNyRCxPQUFPLENBQUMsSUFBSSxDQUNSLGlGQUFpRjtnQkFDakYsd0NBQXdDLENBQUMsQ0FBQztZQUM5QyxJQUFLLE1BQU0sQ0FBQyxRQUFRLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRztnQkFDcEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDM0Q7aUJBQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxFQUFFO2dCQUN0QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDMUM7U0FDSjtJQUNMLENBQUM7SUFDRDs7O09BR0c7SUFDSSxzQkFBc0I7UUFDekIsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUMxQixJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxpQkFBaUI7aUJBQ3pELFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNwRDtJQUNMLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxpQkFBaUIsQ0FBQyxNQUFpQixFQUFFLFNBQWtCLEtBQUs7UUFDL0QsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDOUIsTUFBTSxHQUFHLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztRQUNwRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzdCLElBQUksTUFBTSxDQUFDLGFBQWEsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFO1lBQzdDLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRTtnQkFDckIsY0FBYyxDQUFDLHdDQUF3QyxFQUFFLEtBQUssRUFBRSxlQUFlLENBQUMsQ0FBQTthQUNuRjtZQUNELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDO1lBQ25HLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUNyQixJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUM7U0FDOUQ7SUFDTCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxlQUFlLENBQUMsTUFBaUI7UUFDckMsSUFBSSxNQUFNLENBQUMsU0FBUyxJQUFJLENBQUMsTUFBTSxDQUFDLGtCQUFrQixFQUFFO1lBQ2hELElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQztpQkFDckQsTUFBTSxDQUFFLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsRUFBRTtnQkFDM0IsT0FBTyxLQUFLLEtBQUssSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN4QyxDQUFDLENBQUMsQ0FBQztTQUNWO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ1UsY0FBYzs7WUFDdkIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQ3pELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUNyRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDckQsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYztnQkFDbEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7bUJBQ3pDLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxLQUFLLEtBQUssRUFDM0M7Z0JBQ0UsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDO3FCQUM3QyxTQUFTLEVBQUUsQ0FBQzthQUNwQjtZQUNELElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0IsQ0FBQztLQUFBO0lBRU8sYUFBYSxDQUFDLFFBQWdCLEVBQUUsTUFBYyxFQUFFLE1BQWM7UUFDbEUsTUFBTSxrQkFBa0IsR0FBMkIsRUFBRSxDQUFDO1FBQ3RELElBQUksaUJBQWtDLENBQUM7UUFDdkMsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQy9CLCtDQUErQztZQUMvQyw4QkFBOEI7WUFDOUIsc0NBQXNDO1lBQ3RDLHlDQUF5QztZQUN6QyxJQUFJLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRTtnQkFDM0IsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLHFCQUFxQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUMvRSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsUUFBUSxDQUFDLElBQUksTUFBTSxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLENBQUM7Z0JBQ3JHLElBQUksTUFBTSxFQUFFO29CQUNSLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztpQkFDOUM7YUFDSjtpQkFBTTtnQkFDSCxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWE7cUJBQ3JDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQztxQkFDdkMsSUFBSSxDQUFDLEtBQUssRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO29CQUM5QixPQUFPLENBQUMsS0FBSyxDQUFDLDBCQUEwQixFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztvQkFDdkQsT0FBTyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3pCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNaO1NBQ0o7UUFFRCx5QkFBeUI7UUFDekIsMkNBQTJDO1FBQzNDLElBQUksa0JBQWtCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUMvQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ25DLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ2pCO1FBRUQsaUJBQWlCLEdBQUcsUUFBUSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLGlCQUFpQixHQUFHO1lBQ3JCLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxJQUFJLENBQ3hCLElBQUksQ0FBQyxDQUFDLENBQUMsRUFDUCxLQUFLLEVBQUUsQ0FDVixFQUFFLE1BQU0sRUFBRSxNQUFNO1NBQ3BCLENBQUM7UUFFRixPQUFPO1FBQ1AsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDcEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFlLEVBQUUsRUFBRTtZQUN0RCxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ2xELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbkMsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDekIsQ0FBQyxFQUFFLENBQUMsR0FBUSxFQUFFLEVBQUU7WUFDWixJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztRQUN6QixDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8saUJBQWlCLENBQUM7SUFDN0IsQ0FBQztJQUVPLFdBQVcsQ0FBQyxhQUFrQjtRQUNsQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDOUIsT0FBTyxNQUFNLENBQUMsRUFBRSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1NBQ3BDO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDckIsQ0FBQztJQUVPLGFBQWEsQ0FBQyxNQUFXLEVBQUUsTUFBYyxFQUFFLE1BQWlCO1FBQ2hFLE1BQU0sZUFBZSxHQUFHLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQzNDLE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN0QyxlQUFlLENBQUMsUUFBZ0IsQ0FBQyxTQUFTLENBQUMsR0FBRyxNQUFNLENBQUM7UUFDdEQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxFQUNoQyxJQUFJLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFTyxhQUFhLENBQUMsR0FBUSxFQUFFLFVBQWUsRUFBRSxNQUFjO1FBQzNELElBQUksR0FBRyxFQUFFO1lBQ0wsTUFBTSxZQUFZLEdBQVcsRUFBRSxDQUFDO1lBQ2hDLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFZLEVBQUUsRUFBRTtnQkFDekIsSUFBSSxPQUFPLEVBQUU7b0JBQ1QsSUFBSSxPQUFPLENBQUMsUUFBUSxFQUFFO3dCQUNsQixVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUTs0QkFDdkIsV0FBVyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO3FCQUNsRTtvQkFDRCxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7d0JBQ3BCLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxVQUFVOzRCQUN6QixXQUFXLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7d0JBQ25FLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxZQUFZLEVBQUU7NEJBQ2pDLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7eUJBQ2hFO3FCQUNKO2lCQUNKO1lBQ0wsQ0FBQyxDQUFDLENBQUM7WUFDSCxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxVQUFVLEVBQUU7Z0JBQy9CLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxVQUFVLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQzthQUM3RDtTQUNKO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxJQUFJLE9BQU87UUFDUCxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDZCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDO1lBQzdDLE9BQU8sVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFFBQTBCLEVBQUUsRUFBRTtnQkFDcEQsTUFBTSxVQUFVLEdBQUcsR0FBRyxFQUFFO29CQUNwQixRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUN0QixRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ3hCLENBQUMsQ0FBQztnQkFDRixJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEdBQWUsRUFBRSxFQUFFO29CQUN0RCxVQUFVLEVBQUUsQ0FBQztnQkFDakIsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQ25CLENBQUMsQ0FBQyxDQUFDO1NBQ047YUFBTTtZQUNILE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO1NBQ3BEO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxNQUFNO1FBQ04sT0FBTyxNQUFNLENBQ1QsSUFBSSxDQUFDLE9BQU8sRUFDWixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FDcEIsU0FBUyxDQUFDLENBQUMsTUFBYyxFQUFFLEVBQUU7WUFDekIsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEIsQ0FBQyxDQUFDLENBQ0wsQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUVPLGFBQWEsQ0FBQyxNQUFjO1FBQ2hDLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFTSxxQkFBcUIsQ0FBQyxhQUFtQyxFQUFFLE1BQWlCO1FBQy9FLElBQUksYUFBYSxFQUFFO1lBQ2YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUMvQyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFDckIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQzlEO0lBQ0wsQ0FBQzs7O1lBcFFKLFVBQVU7OztZQW5CRixhQUFhO1lBT2IsV0FBVztZQU5YLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IDIwMTktMjAyMSBWTXdhcmUsIEluYy5cbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBFUEwtMi4wXG4gKi9cbmltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTG9jYWxlU2VydmljZSB9IGZyb20gJy4vbG9jYWxlLnNlcnZpY2UnO1xuaW1wb3J0IHsgSTE4bkxvYWRlciB9IGZyb20gJy4uL2xvYWRlcic7XG5pbXBvcnQgeyBtZXJnZU9iamVjdCwgYXNzaWduLCBkZXByZWNhdGVkV2FybiB9IGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHsgY29uY2F0LCBPYnNlcnZhYmxlLCBmb3JrSm9pbiwgT2JzZXJ2ZXIsIG9mLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHNoYXJlLCBzd2l0Y2hNYXAsIHRha2UsIGNhdGNoRXJyb3IgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBWSVBDb25maWcsIGdldE5hbWVTcGFjZSwgVklQQ29uZmlnRmFjdG9yeSB9IGZyb20gJy4uL2NvbmZpZyc7XG5pbXBvcnQgeyBzb3VyY2VCdW5kbGVPYmplY3QgfSBmcm9tICcuL2wxMG4uc2VydmljZSc7XG5pbXBvcnQgeyBJMThuQ29udGV4dCB9IGZyb20gJy4vaTE4bi5jb250ZXh0JztcblxuZXhwb3J0IGludGVyZmFjZSBMb2NhbGVEYXRhIHtcbiAgICBjYXRlZ29yaWVzOiBPYmplY3Q7XG4gICAgbWVzc2FnZXM6IHsgW2tleTogc3RyaW5nXTogYW55IH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9hZGluZ0xvY2FsZURhdGEge1xuICAgIGxvY2FsZTogc3RyaW5nO1xuICAgIGRhdGE6IE9ic2VydmFibGU8YW55Pjtcbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFZJUFNlcnZpY2Uge1xuICAgIHB1YmxpYyBtYWluQ29uZmlnOiBWSVBDb25maWc7XG4gICAgcHJpdmF0ZSBwZW5kaW5nID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBsb2FkaW5nTG9jYWxlRGF0YTogTG9hZGluZ0xvY2FsZURhdGE7XG4gICAgcHJpdmF0ZSBjb25maWdzOiBWSVBDb25maWdbXSA9IFtdO1xuICAgIHByaXZhdGUgYXZhaWxhYmxlTG9jYWxlczogQXJyYXk8c3RyaW5nPiA9IFtdO1xuICAgIHByaXZhdGUgbG9jYWxlU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG4gICAgcHJpdmF0ZSBfb25Mb2NhbGVDaGFuZ2U6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG4gICAgcHJpdmF0ZSBfaTE4blNjb3BlOiBBcnJheTxzdHJpbmc+ID0gW107XG4gICAgcHJpdmF0ZSBfbG9jYWxlRGF0YTogYW55ID0ge307XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJvdGVjdGVkIGxvY2FsZVNlcnZpY2U6IExvY2FsZVNlcnZpY2UsXG4gICAgICAgIHByb3RlY3RlZCBpMThuQ29udGV4dDogSTE4bkNvbnRleHQsXG4gICAgICAgIHB1YmxpYyBjdXJyZW50TG9hZGVyOiBJMThuTG9hZGVyXG4gICAgKSB7IH1cblxuICAgIGdldCBvbkxvY2FsZUNoYW5nZSgpOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vbkxvY2FsZUNoYW5nZTtcbiAgICB9XG5cbiAgICBnZXQgbG9jYWxlRGF0YSgpOiBhbnkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbG9jYWxlRGF0YTtcbiAgICB9XG5cbiAgICBnZXQgaTE4blNjb3BlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faTE4blNjb3BlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRpbmcgdGhlIGkxOG4gZGF0YSBhdCBhcHAgbW9kdWxlIG9yIHJvb3Qgb2YgbGF6eSBtb2R1bGUuXG4gICAgICogQHBhcmFtIGNvbmZpZyBGb3Igcm9vdCBtb2R1bGUgb3IgbGF6eSBsb2FkIG1kdWxlLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBpbml0RGF0YShjb25maWc6IFZJUENvbmZpZyk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHRoaXMuc3Vic2NyaWJlTG9jYWxlU3ViamVjdCgpO1xuICAgICAgICB0aGlzLnJlZ2lzdGVyQ29tcG9uZW50KGNvbmZpZywgdHJ1ZSk7XG4gICAgICAgIHRoaXMuaW5pdExvY2FsZShjb25maWcpO1xuICAgICAgICBhd2FpdCB0aGlzLmxvYWRMb2NhbGVEYXRhKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdCBsb2NhbGUgYnkgY29uZmlnIHBhc3NlZCBmcm9tIHJvb3QgbW9kdWxlIGZvciBjb21wYXRpYmlsaXR5LlxuICAgICAqIFdpbGwgYmUgcmVtb3ZlZCBpbiB2OS5cbiAgICAgKiBAcGFyYW0gY29uZmlnXG4gICAgICovXG4gICAgcHJpdmF0ZSBpbml0TG9jYWxlKGNvbmZpZzogVklQQ29uZmlnKSB7XG4gICAgICAgIGlmICggY29uZmlnLmxvY2FsZSB8fCBjb25maWcubGFuZ3VhZ2UgfHwgY29uZmlnLnJlZ2lvbiApIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICAnU2V0IGxhbmd1YWdlIGFuZCByZWdpb24gYnkgY29uZmlndXJhdGlvbiBpcyBkZXByZWNhdGVkLCB3aWxsIGJlIHJlbW92ZWQgaW4gdjkuICcgK1xuICAgICAgICAgICAgICAgICdQbGVhc2UgdXNlIExvY2FsZVNlcnZpY2UuaW5pdCBpbnN0ZWFkLicpO1xuICAgICAgICAgICAgaWYgKCBjb25maWcubGFuZ3VhZ2UgJiYgY29uZmlnLnJlZ2lvbiApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsZVNlcnZpY2UuaW5pdChjb25maWcubGFuZ3VhZ2UsIGNvbmZpZy5yZWdpb24pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjb25maWcubG9jYWxlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2NhbGVTZXJ2aWNlLmluaXQoY29uZmlnLmxvY2FsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJsZSB0aGUgbG9jYWxlIGNoYW5nZWQgZXZlbnQgZnJvbSB2aWV3IGxheWVyLlxuICAgICAqIEZvciBsaXZlIFVJIHRyYW5zbGF0aW9uIHVwZGF0ZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgc3Vic2NyaWJlTG9jYWxlU3ViamVjdCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmxvY2FsZVN1YnNjcmlwdGlvbikge1xuICAgICAgICAgICAgdGhpcy5sb2NhbGVTdWJzY3JpcHRpb24gPSB0aGlzLmxvY2FsZVNlcnZpY2UudXNlckxvY2FsZUNoYW5nZWRcbiAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHsgdGhpcy5sb2FkTG9jYWxlRGF0YSgpOyB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNwZWNpZmljYWxseSwgZm9yIHRoZSBmZWF0dXJlIG1vZHVsZSB3aGljaCB3aWxsIGJlIGltcG9ydGVkXG4gICAgICogdG8gcm9vdCBtb2R1bGUgb3IgbGF6eSBsb2FkIG1vZHVsZS4gVGhpcyBtZXRob2Qgc2hvdWxkIGJlIGludm9rZWRcbiAgICAgKiBpbiB0aGUgY29uc3RydWN0b3Igb2YgZmVhdHVyZSBtb2R1bGUuXG4gICAgICogQHBhcmFtIGNvbmZpZ1xuICAgICAqIEBwYXJhbSBpc01haW5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVnaXN0ZXJDb21wb25lbnQoY29uZmlnOiBWSVBDb25maWcsIGlzTWFpbjogYm9vbGVhbiA9IGZhbHNlKSB7XG4gICAgICAgIHRoaXMuc3Vic2NyaWJlTG9jYWxlU3ViamVjdCgpO1xuICAgICAgICBjb25maWcgPSBWSVBDb25maWdGYWN0b3J5KGNvbmZpZywgdGhpcy5pMThuQ29udGV4dCk7XG4gICAgICAgIHRoaXMubWFpbkNvbmZpZyA9IGlzTWFpbiA/IGNvbmZpZyA6IHRoaXMubWFpbkNvbmZpZztcbiAgICAgICAgdGhpcy5jb25maWdzLnB1c2goY29uZmlnKTtcbiAgICAgICAgdGhpcy51cGRhdGVJMThuU2NvcGUoY29uZmlnKTtcbiAgICAgICAgaWYgKGNvbmZpZy5zb3VyY2VCdW5kbGVzIHx8IGNvbmZpZy5zb3VyY2VCdW5kbGUpIHtcbiAgICAgICAgICAgIGlmIChjb25maWcuc291cmNlQnVuZGxlKSB7XG4gICAgICAgICAgICAgICAgZGVwcmVjYXRlZFdhcm4oJ1RoZSBzb3VyY2VCdW5kbGUgb3B0aW9uIGluIGkxOG4gY29uZmlnJywgJ3YxMCcsICdzb3VyY2VCdW5kbGVzJylcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGJ1bmRsZSA9IGNvbmZpZy5zb3VyY2VCdW5kbGVzID8gdGhpcy5yZXNldEJ1bmRsZShjb25maWcuc291cmNlQnVuZGxlcykgOiBjb25maWcuc291cmNlQnVuZGxlO1xuICAgICAgICAgICAgdGhpcy5wcm9jZXNzQnVuZGxlKGJ1bmRsZSxcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsZVNlcnZpY2UuZGVmYXVsdExvY2FsZS5sYW5ndWFnZUNvZGUsIGNvbmZpZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZW50YXRpdmUgc29sdXRpb24sIGlmIHRyYW5zbGF0aW9uIGJ1bmRsZSBpcyBtb3VudGVkLlxuICAgICAqIG5vIGxvbmdlciB0byBjb25zaWRlciBpMThuIHNjb3BlIHdoaWNoIGRlZmluZWQgaW5cbiAgICAgKiBmZWF0dXJlIG1vZHVsZSBjb25maWd1cmF0aW9uLlxuICAgICAqIEBwYXJhbSBjb25maWdcbiAgICAgKi9cbiAgICBwcml2YXRlIHVwZGF0ZUkxOG5TY29wZShjb25maWc6IFZJUENvbmZpZykge1xuICAgICAgICBpZiAoY29uZmlnLmkxOG5TY29wZSAmJiAhY29uZmlnLnRyYW5zbGF0aW9uQnVuZGxlcykge1xuICAgICAgICAgICAgdGhpcy5faTE4blNjb3BlID0gdGhpcy5faTE4blNjb3BlLmNvbmNhdChjb25maWcuaTE4blNjb3BlKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoIChlbGVtLCBpbmRleCwgc2VsZikgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5kZXggPT09IHNlbGYuaW5kZXhPZihlbGVtKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIElmIHRoZSBsb2NhbGUgaXMgcHJvY2Vzc2VkIG9yIHNvdXJjZSBsb2NhbGUsIHNraXAuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGxvYWRMb2NhbGVEYXRhKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIGNvbnN0IGxhbmd1YWdlID0gdGhpcy5sb2NhbGVTZXJ2aWNlLmdldEN1cnJlbnRMYW5ndWFnZSgpO1xuICAgICAgICBjb25zdCByZWdpb24gPSB0aGlzLmxvY2FsZVNlcnZpY2UuZ2V0Q3VycmVudFJlZ2lvbigpO1xuICAgICAgICBjb25zdCBsb2NhbGUgPSB0aGlzLmxvY2FsZVNlcnZpY2UuZ2V0Q3VycmVudExvY2FsZSgpO1xuICAgICAgICBpZiAoIXRoaXMubG9jYWxlU2VydmljZS5pc1NvdXJjZUxvY2FsZSAmJlxuICAgICAgICAgICAgdGhpcy5hdmFpbGFibGVMb2NhbGVzLmluZGV4T2YobG9jYWxlKSA9PT0gLTFcbiAgICAgICAgICAgICYmIHRoaXMuaTE4bkNvbnRleHQuaTE4bkVuYWJsZWQgIT09IGZhbHNlXG4gICAgICAgICkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5nZXRMb2NhbGVEYXRhKGxhbmd1YWdlLCByZWdpb24sIGxvY2FsZSlcbiAgICAgICAgICAgICAgICAudG9Qcm9taXNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWxlYXNlTG9jYWxlKGxvY2FsZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRMb2NhbGVEYXRhKGxhbmd1YWdlOiBzdHJpbmcsIHJlZ2lvbjogc3RyaW5nLCBsb2NhbGU6IHN0cmluZyk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgICAgIGNvbnN0IHNlcXVlbmNlc09mUmVxdWVzdDogQXJyYXk8T2JzZXJ2YWJsZTxhbnk+PiA9IFtdO1xuICAgICAgICBsZXQgbG9hZGluZ0xvY2FsZURhdGE6IE9ic2VydmFibGU8YW55PjtcbiAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5jb25maWdzKSB7XG4gICAgICAgICAgICAvLyBCeXBhc3Mgc2VuZGluZyBIVFRQIGNhbGwgdG8gZ2V0IHRyYW5zbGF0aW9uLlxuICAgICAgICAgICAgLy8gVXNpbmcgbG9jYWwgYnVuZGxlIGluc3RlYWQuXG4gICAgICAgICAgICAvLyBVc2luZyBsYW5ndWFnZSB0byBtYXAgbG9jYWwgYnVuZGxlLlxuICAgICAgICAgICAgLy8gVXNpbmcgbG9jYWxlIHRvIHN0b3JlIHRoZSB0cmFuc2xhdGlvbi5cbiAgICAgICAgICAgIGlmIChjb25maWcudHJhbnNsYXRpb25CdW5kbGVzKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RhbmRhcmRMYW5ndWFnZVRhZyA9IHRoaXMubG9jYWxlU2VydmljZS5ub3JtYWxpemVMYW5ndWFnZUNvZGUobGFuZ3VhZ2UpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGJ1bmRsZSA9IGNvbmZpZy50cmFuc2xhdGlvbkJ1bmRsZXNbbGFuZ3VhZ2VdIHx8IGNvbmZpZy50cmFuc2xhdGlvbkJ1bmRsZXNbc3RhbmRhcmRMYW5ndWFnZVRhZ107XG4gICAgICAgICAgICAgICAgaWYgKGJ1bmRsZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NCdW5kbGUoYnVuZGxlLCBsb2NhbGUsIGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZXF1ZW5jZXNPZlJlcXVlc3QucHVzaCh0aGlzLmN1cnJlbnRMb2FkZXJcbiAgICAgICAgICAgICAgICAgICAgLmdldExvY2FsZURhdGEoY29uZmlnLCBsYW5ndWFnZSwgcmVnaW9uKVxuICAgICAgICAgICAgICAgICAgICAucGlwZShzaGFyZSgpLCBjYXRjaEVycm9yKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYENhbid0IGZldGNoIGxvY2FsZSBkYXRhLmAsIGNvbmZpZywgZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvZih1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICB9KSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gTm8gSFRUUCBjYWxsIHJlcXVpcmVkLlxuICAgICAgICAvLyBSZXNvdXJjZSBvZiBjdXJyZW50IGxvY2FsZSBpcyBhdmFpbGFibGUuXG4gICAgICAgIGlmIChzZXF1ZW5jZXNPZlJlcXVlc3QubGVuZ3RoIDwgMSkge1xuICAgICAgICAgICAgdGhpcy5hdmFpbGFibGVMb2NhbGVzLnB1c2gobG9jYWxlKTtcbiAgICAgICAgICAgIHJldHVybiBvZihbXSk7XG4gICAgICAgIH1cblxuICAgICAgICBsb2FkaW5nTG9jYWxlRGF0YSA9IGZvcmtKb2luKHNlcXVlbmNlc09mUmVxdWVzdCk7XG4gICAgICAgIHRoaXMubG9hZGluZ0xvY2FsZURhdGEgPSB7XG4gICAgICAgICAgICBkYXRhOiBsb2FkaW5nTG9jYWxlRGF0YS5waXBlKFxuICAgICAgICAgICAgICAgIHRha2UoMSksXG4gICAgICAgICAgICAgICAgc2hhcmUoKVxuICAgICAgICAgICAgKSwgbG9jYWxlOiBsb2NhbGVcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBGSUZPXG4gICAgICAgIHRoaXMucGVuZGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMubG9hZGluZ0xvY2FsZURhdGEuZGF0YS5zdWJzY3JpYmUoKHJlczogTG9jYWxlRGF0YSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdG9yZVJlc291cmNlKHJlcywgdGhpcy5fbG9jYWxlRGF0YSwgbG9jYWxlKTtcbiAgICAgICAgICAgIHRoaXMuYXZhaWxhYmxlTG9jYWxlcy5wdXNoKGxvY2FsZSk7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmcgPSBmYWxzZTtcbiAgICAgICAgfSwgKGVycjogYW55KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmcgPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBsb2FkaW5nTG9jYWxlRGF0YTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlc2V0QnVuZGxlKHNvdXJjZUJ1bmRsZXM6IGFueSkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShzb3VyY2VCdW5kbGVzKSkge1xuICAgICAgICAgICAgcmV0dXJuIGFzc2lnbih7fSwgc291cmNlQnVuZGxlcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NCdW5kbGUoYnVuZGxlOiBhbnksIGxvY2FsZTogc3RyaW5nLCBjb25maWc6IFZJUENvbmZpZykge1xuICAgICAgICBjb25zdCBmb3JtYXR0ZWRCdW5kbGUgPSB7ICdtZXNzYWdlcyc6IHt9IH07XG4gICAgICAgIGNvbnN0IG5hbWVzcGFjZSA9IGdldE5hbWVTcGFjZShjb25maWcpO1xuICAgICAgICAoZm9ybWF0dGVkQnVuZGxlLm1lc3NhZ2VzIGFzIGFueSlbbmFtZXNwYWNlXSA9IGJ1bmRsZTtcbiAgICAgICAgdGhpcy5zdG9yZVJlc291cmNlKFtmb3JtYXR0ZWRCdW5kbGVdLFxuICAgICAgICAgICAgdGhpcy5fbG9jYWxlRGF0YSwgbG9jYWxlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3JlUmVzb3VyY2UocmVzOiBhbnksIGxvY2FsZWRhdGE6IGFueSwgbG9jYWxlOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKHJlcykge1xuICAgICAgICAgICAgY29uc3Qgc3VwcGxlbWVudGFsOiBPYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGxvY2FsZWRhdGFbbG9jYWxlXSA9IGxvY2FsZWRhdGFbbG9jYWxlXSB8fCB7fTtcbiAgICAgICAgICAgIHJlcy5mb3JFYWNoKChlbGVtZW50OiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5tZXNzYWdlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxlZGF0YVtsb2NhbGVdLm1lc3NhZ2VzID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZU9iamVjdChsb2NhbGVkYXRhW2xvY2FsZV0ubWVzc2FnZXMsIGVsZW1lbnQubWVzc2FnZXMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmNhdGVnb3JpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsZWRhdGFbbG9jYWxlXS5jYXRlZ29yaWVzID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZU9iamVjdChsb2NhbGVkYXRhW2xvY2FsZV0uY2F0ZWdvcmllcywgZWxlbWVudC5jYXRlZ29yaWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmNhdGVnb3JpZXMuc3VwcGxlbWVudGFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihzdXBwbGVtZW50YWwsIGVsZW1lbnQuY2F0ZWdvcmllcy5zdXBwbGVtZW50YWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAobG9jYWxlZGF0YVtsb2NhbGVdLmNhdGVnb3JpZXMpIHtcbiAgICAgICAgICAgICAgICBsb2NhbGVkYXRhW2xvY2FsZV0uY2F0ZWdvcmllcy5zdXBwbGVtZW50YWwgPSBzdXBwbGVtZW50YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBjdXJyZW50IHJlcHJlc2VudHMgY3VycmVudCBhdmFpbGFibGUgbG9jYWxlIHRvIGNvdmVyIHRoZSBpbml0aWFsIHN0YXR1cy5cbiAgICAgKiBzaW5jZSBpbiBzb21lIHNpdHVhdGlvbiwgdGhlICdvbkxvY2FsZUNoYW5nZScgaGF2ZW4ndCBiZSByZWdpc3RlciBhbHdheXMsXG4gICAgICogb3IgdGhlcmUgaXMgbm8gZXZlbnQgYXQgdGltZS5cbiAgICAgKi9cbiAgICBnZXQgY3VycmVudCgpOiBPYnNlcnZhYmxlPHN0cmluZyB8IGFueT4ge1xuICAgICAgICBpZiAodGhpcy5wZW5kaW5nKSB7XG4gICAgICAgICAgICBjb25zdCBsb2NhbGUgPSB0aGlzLmxvYWRpbmdMb2NhbGVEYXRhLmxvY2FsZTtcbiAgICAgICAgICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZSgob2JzZXJ2ZXI6IE9ic2VydmVyPHN0cmluZz4pID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBvbkNvbXBsZXRlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KGxvY2FsZSk7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRpbmdMb2NhbGVEYXRhLmRhdGEuc3Vic2NyaWJlKChyZXM6IExvY2FsZURhdGEpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgb25Db21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgIH0sIG9uQ29tcGxldGUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gb2YodGhpcy5sb2NhbGVTZXJ2aWNlLmdldEN1cnJlbnRMb2NhbGUoKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBzdHJlYW0gb2YgJ2F2YWlsYWJsZScgbG9jYWxlLlxuICAgICAqL1xuICAgIGdldCBzdHJlYW0oKTogT2JzZXJ2YWJsZTxzdHJpbmcgfCBhbnk+IHtcbiAgICAgICAgcmV0dXJuIGNvbmNhdChcbiAgICAgICAgICAgIHRoaXMuY3VycmVudCxcbiAgICAgICAgICAgIHRoaXMub25Mb2NhbGVDaGFuZ2UucGlwZShcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKGxvY2FsZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvZihsb2NhbGUpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbGVhc2VMb2NhbGUobG9jYWxlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5vbkxvY2FsZUNoYW5nZS5lbWl0KGxvY2FsZSk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlZ2lzdGVyU291cmNlQnVuZGxlcyhzb3VyY2VCdW5kbGVzOiBzb3VyY2VCdW5kbGVPYmplY3RbXSwgY29uZmlnOiBWSVBDb25maWcpIHtcbiAgICAgICAgaWYgKHNvdXJjZUJ1bmRsZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGJ1bmRsZSA9IHRoaXMucmVzZXRCdW5kbGUoc291cmNlQnVuZGxlcyk7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NCdW5kbGUoYnVuZGxlLFxuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxlU2VydmljZS5kZWZhdWx0TG9jYWxlLmxhbmd1YWdlQ29kZSwgY29uZmlnKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiJdfQ==