UNPKG

angular-l10n

Version:

Angular library to translate texts, dates and numbers

200 lines 26.8 kB
import { Injectable, Inject } from '@angular/core'; import { BehaviorSubject, merge, concat } from 'rxjs'; import { L10N_CONFIG, L10N_LOCALE } from '../models/l10n-config'; import { formatLanguage, getSchema, getValue, mergeDeep } from '../models/utils'; import * as i0 from "@angular/core"; import * as i1 from "./l10n-cache"; import * as i2 from "./l10n-storage"; import * as i3 from "./l10n-locale-resolver"; import * as i4 from "./l10n-translation-fallback"; import * as i5 from "./l10n-translation-loader"; import * as i6 from "./l10n-translation-handler"; import * as i7 from "./l10n-missing-translation-handler"; export class L10nTranslationService { constructor(config, locale, cache, storage, resolveLocale, translationFallback, translationLoader, translationHandler, missingTranslationHandler) { this.config = config; this.locale = locale; this.cache = cache; this.storage = storage; this.resolveLocale = resolveLocale; this.translationFallback = translationFallback; this.translationLoader = translationLoader; this.translationHandler = translationHandler; this.missingTranslationHandler = missingTranslationHandler; /** * The translation data: {language: {key: value}} */ this.data = {}; this.translation = new BehaviorSubject(this.locale); this.error = new BehaviorSubject(null); } /** * Gets the current locale. */ getLocale() { return this.locale; } /** * Changes the current locale and load the translation data. * @param locale The new locale */ async setLocale(locale) { await this.loadTranslations(this.config.providers, locale); } /** * Fired every time the translation data has been loaded. Returns the locale. */ onChange() { return this.translation.asObservable(); } /** * Fired when the translation data could not been loaded. Returns the error. */ onError() { return this.error.asObservable(); } /** * Translates a key or an array of keys. * @param keys The key or an array of keys to be translated * @param params Optional parameters contained in the key * @param language The current language * @return The translated value or an object: {key: value} */ translate(keys, params, language = this.locale.language) { language = formatLanguage(language, this.config.format); if (Array.isArray(keys)) { const data = {}; for (const key of keys) { data[key] = this.translate(key, params, language); } return data; } const value = getValue(keys, this.data[language], this.config.keySeparator); return value ? this.translationHandler.parseValue(keys, params, value) : this.missingTranslationHandler.handle(keys, value, params); } /** * Checks if a translation exists. * @param key The key to be tested * @param language The current language */ has(key, language = this.locale.language) { language = formatLanguage(language, this.config.format); return getValue(key, this.data[language], this.config.keySeparator) !== null; } /** * Gets the language direction. */ getLanguageDirection(language = this.locale.language) { const schema = getSchema(this.config.schema, language, this.config.format); return schema ? schema.dir : undefined; } /** * Gets available languages. */ getAvailableLanguages() { const languages = this.config.schema.map(item => formatLanguage(item.locale.language, this.config.format)); return languages; } /** * Initializes the service * @param providers An array of L10nProvider */ async init(providers = this.config.providers) { let locale = null; // Tries to get locale from storage. if (locale == null) { locale = await this.storage.read(); } // Tries resolved locale. if (locale == null) { locale = await this.resolveLocale.get(); } // Uses default locale. if (locale == null) { locale = this.config.defaultLocale; } // Loads translation data. await this.loadTranslations(providers, locale); } /** * Can be called at every translation change. * @param providers An array of L10nProvider * @param locale The current locale */ async loadTranslations(providers = this.config.providers, locale = this.locale) { const language = formatLanguage(locale.language, this.config.format); return new Promise((resolve) => { concat(...this.getTranslation(providers, language)).subscribe({ next: (data) => this.addData(data, language), error: (error) => { this.handleError(error); resolve(); }, complete: () => { this.releaseTranslation(locale); resolve(); } }); }); } /** * Can be called to add translation data. * @param data The translation data {key: value} * @param language The language to add data */ addData(data, language) { this.data[language] = this.data[language] !== undefined ? mergeDeep(this.data[language], data) : data; } /** * Adds providers to configuration * @param providers The providers of the translations data */ addProviders(providers) { providers.forEach(provider => { if (!this.config.providers.find(p => p.name === provider.name)) { this.config.providers.push(provider); } }); } getTranslation(providers, language) { const lazyLoaders = []; let loaders = []; for (const provider of providers) { if (this.config.fallback) { loaders = loaders.concat(this.translationFallback.get(language, provider)); } else { if (this.config.cache) { lazyLoaders.push(this.cache.read(`${provider.name}-${language}`, this.translationLoader.get(language, provider))); } else { lazyLoaders.push(this.translationLoader.get(language, provider)); } } } loaders.push(merge(...lazyLoaders)); return loaders; } handleError(error) { this.error.next(error); } releaseTranslation(locale) { Object.assign(this.locale, locale); this.translation.next(this.locale); this.storage.write(this.locale); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: L10nTranslationService, deps: [{ token: L10N_CONFIG }, { token: L10N_LOCALE }, { token: i1.L10nCache }, { token: i2.L10nStorage }, { token: i3.L10nLocaleResolver }, { token: i4.L10nTranslationFallback }, { token: i5.L10nTranslationLoader }, { token: i6.L10nTranslationHandler }, { token: i7.L10nMissingTranslationHandler }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: L10nTranslationService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: L10nTranslationService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [L10N_CONFIG] }] }, { type: undefined, decorators: [{ type: Inject, args: [L10N_LOCALE] }] }, { type: i1.L10nCache }, { type: i2.L10nStorage }, { type: i3.L10nLocaleResolver }, { type: i4.L10nTranslationFallback }, { type: i5.L10nTranslationLoader }, { type: i6.L10nTranslationHandler }, { type: i7.L10nMissingTranslationHandler }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibDEwbi10cmFuc2xhdGlvbi5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci1sMTBuL3NyYy9saWIvc2VydmljZXMvbDEwbi10cmFuc2xhdGlvbi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFZLE1BQU0sZUFBZSxDQUFDO0FBQzdELE9BQU8sRUFBYyxlQUFlLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUdsRSxPQUFPLEVBQUUsV0FBVyxFQUFjLFdBQVcsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzdFLE9BQU8sRUFBRSxjQUFjLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7Ozs7O0FBU25FLE1BQU0sT0FBTyxzQkFBc0I7SUFXN0MsWUFDaUMsTUFBa0IsRUFDbEIsTUFBa0IsRUFDdkMsS0FBZ0IsRUFDaEIsT0FBb0IsRUFDcEIsYUFBaUMsRUFDakMsbUJBQTRDLEVBQzVDLGlCQUF3QyxFQUN4QyxrQkFBMEMsRUFDMUMseUJBQXdEO1FBUm5DLFdBQU0sR0FBTixNQUFNLENBQVk7UUFDbEIsV0FBTSxHQUFOLE1BQU0sQ0FBWTtRQUN2QyxVQUFLLEdBQUwsS0FBSyxDQUFXO1FBQ2hCLFlBQU8sR0FBUCxPQUFPLENBQWE7UUFDcEIsa0JBQWEsR0FBYixhQUFhLENBQW9CO1FBQ2pDLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBeUI7UUFDNUMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUF1QjtRQUN4Qyx1QkFBa0IsR0FBbEIsa0JBQWtCLENBQXdCO1FBQzFDLDhCQUF5QixHQUF6Qix5QkFBeUIsQ0FBK0I7UUFsQnBFOztXQUVHO1FBQ0ksU0FBSSxHQUEyQixFQUFFLENBQUM7UUFFakMsZ0JBQVcsR0FBRyxJQUFJLGVBQWUsQ0FB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Q0FBQztJQUNwQyxDQUFDOzhHQTlNc0Isc0JBQXNCLGtCQVlqQyxXQUFXLGFBQ1gsV0FBVztrSEFiQSxzQkFBc0I7OzJGQUF0QixzQkFBc0I7a0JBQWhELFVBQVU7OzBCQVlGLE1BQU07MkJBQUMsV0FBVzs7MEJBQ2xCLE1BQU07MkJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIEluamVjdCwgT3B0aW9uYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgQmVoYXZpb3JTdWJqZWN0LCBtZXJnZSwgY29uY2F0IH0gZnJvbSAncnhqcyc7XHJcblxyXG5pbXBvcnQgeyBMMTBuTG9jYWxlLCBMMTBuUHJvdmlkZXIgfSBmcm9tICcuLi9tb2RlbHMvdHlwZXMnO1xyXG5pbXBvcnQgeyBMMTBOX0NPTkZJRywgTDEwbkNvbmZpZywgTDEwTl9MT0NBTEUgfSBmcm9tICcuLi9tb2RlbHMvbDEwbi1jb25maWcnO1xyXG5pbXBvcnQgeyBmb3JtYXRMYW5ndWFnZSwgZ2V0U2NoZW1hLCBnZXRWYWx1ZSwgbWVyZ2VEZWVwIH0gZnJvbSAnLi4vbW9kZWxzL3V0aWxzJztcclxuaW1wb3J0IHsgTDEwbkNhY2hlIH0gZnJvbSAnLi9sMTBuLWNhY2hlJztcclxuaW1wb3J0IHsgTDEwblN0b3JhZ2UgfSBmcm9tICcuL2wxMG4tc3RvcmFnZSc7XHJcbmltcG9ydCB7IEwxMG5Mb2NhbGVSZXNvbHZlciB9IGZyb20gJy4vbDEwbi1sb2NhbGUtcmVzb2x2ZXInO1xyXG5pbXBvcnQgeyBMMTBuVHJhbnNsYXRpb25GYWxsYmFjayB9IGZyb20gJy4vbDEwbi10cmFuc2xhdGlvbi1mYWxsYmFjayc7XHJcbmltcG9ydCB7IEwxMG5UcmFuc2xhdGlvbkxvYWRlciB9IGZyb20gJy4vbDEwbi10cmFuc2xhdGlvbi1sb2FkZXInO1xyXG5pbXBvcnQgeyBMMTBuVHJhbnNsYXRpb25IYW5kbGVyIH0gZnJvbSAnLi9sMTBuLXRyYW5zbGF0aW9uLWhhbmRsZXInO1xyXG5pbXBvcnQgeyBMMTBuTWlzc2luZ1RyYW5zbGF0aW9uSGFuZGxlciB9IGZyb20gJy4vbDEwbi1taXNzaW5nLXRyYW5zbGF0aW9uLWhhbmRsZXInO1xyXG5cclxuQEluamVjdGFibGUoKSBleHBvcnQgY2xhc3MgTDEwblRyYW5zbGF0aW9uU2VydmljZSB7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgdHJhbnNsYXRpb24gZGF0YToge2xhbmd1YWdlOiB7a2V5OiB2YWx1ZX19XHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBkYXRhOiB7IFtrZXk6IHN0cmluZ106IGFueSB9ID0ge307XHJcblxyXG4gICAgcHJpdmF0ZSB0cmFuc2xhdGlvbiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8TDEwbkxvY2FsZT4odGhpcy5sb2NhbGUpO1xyXG5cclxuICAgIHByaXZhdGUgZXJyb3IgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGFueT4obnVsbCk7XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgQEluamVjdChMMTBOX0NPTkZJRykgcHJpdmF0ZSBjb25maWc6IEwxMG5Db25maWcsXHJcbiAgICAgICAgQEluamVjdChMMTBOX0xPQ0FMRSkgcHJpdmF0ZSBsb2NhbGU6IEwxMG5Mb2NhbGUsXHJcbiAgICAgICAgcHJpdmF0ZSBjYWNoZTogTDEwbkNhY2hlLFxyXG4gICAgICAgIHByaXZhdGUgc3RvcmFnZTogTDEwblN0b3JhZ2UsXHJcbiAgICAgICAgcHJpdmF0ZSByZXNvbHZlTG9jYWxlOiBMMTBuTG9jYWxlUmVzb2x2ZXIsXHJcbiAgICAgICAgcHJpdmF0ZSB0cmFuc2xhdGlvbkZhbGxiYWNrOiBMMTBuVHJhbnNsYXRpb25GYWxsYmFjayxcclxuICAgICAgICBwcml2YXRlIHRyYW5zbGF0aW9uTG9hZGVyOiBMMTBuVHJhbnNsYXRpb25Mb2FkZXIsXHJcbiAgICAgICAgcHJpdmF0ZSB0cmFuc2xhdGlvbkhhbmRsZXI6IEwxMG5UcmFuc2xhdGlvbkhhbmRsZXIsXHJcbiAgICAgICAgcHJpdmF0ZSBtaXNzaW5nVHJhbnNsYXRpb25IYW5kbGVyOiBMMTBuTWlzc2luZ1RyYW5zbGF0aW9uSGFuZGxlclxyXG4gICAgKSB7IH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldHMgdGhlIGN1cnJlbnQgbG9jYWxlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0TG9jYWxlKCk6IEwxMG5Mb2NhbGUge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoYW5nZXMgdGhlIGN1cnJlbnQgbG9jYWxlIGFuZCBsb2FkIHRoZSB0cmFuc2xhdGlvbiBkYXRhLlxyXG4gICAgICogQHBhcmFtIGxvY2FsZSBUaGUgbmV3IGxvY2FsZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYXN5bmMgc2V0TG9jYWxlKGxvY2FsZTogTDEwbkxvY2FsZSk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGF3YWl0IHRoaXMubG9hZFRyYW5zbGF0aW9ucyh0aGlzLmNvbmZpZy5wcm92aWRlcnMsIGxvY2FsZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGaXJlZCBldmVyeSB0aW1lIHRoZSB0cmFuc2xhdGlvbiBkYXRhIGhhcyBiZWVuIGxvYWRlZC4gUmV0dXJucyB0aGUgbG9jYWxlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25DaGFuZ2UoKTogT2JzZXJ2YWJsZTxMMTBuTG9jYWxlPiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRpb24uYXNPYnNlcnZhYmxlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGaXJlZCB3aGVuIHRoZSB0cmFuc2xhdGlvbiBkYXRhIGNvdWxkIG5vdCBiZWVuIGxvYWRlZC4gUmV0dXJucyB0aGUgZXJyb3IuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvbkVycm9yKCk6IE9ic2VydmFibGU8YW55PiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3IuYXNPYnNlcnZhYmxlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUcmFuc2xhdGVzIGEga2V5IG9yIGFuIGFycmF5IG9mIGtleXMuXHJcbiAgICAgKiBAcGFyYW0ga2V5cyBUaGUga2V5IG9yIGFuIGFycmF5IG9mIGtleXMgdG8gYmUgdHJhbnNsYXRlZFxyXG4gICAgICogQHBhcmFtIHBhcmFtcyBPcHRpb25hbCBwYXJhbWV0ZXJzIGNvbnRhaW5lZCBpbiB0aGUga2V5XHJcbiAgICAgKiBAcGFyYW0gbGFuZ3VhZ2UgVGhlIGN1cnJlbnQgbGFuZ3VhZ2VcclxuICAgICAqIEByZXR1cm4gVGhlIHRyYW5zbGF0ZWQgdmFsdWUgb3IgYW4gb2JqZWN0OiB7a2V5OiB2YWx1ZX1cclxuICAgICAqL1xyXG4gICAgcHVibGljIHRyYW5zbGF0ZShcclxuICAgICAgICBrZXlzOiBzdHJpbmcgfCBzdHJpbmdbXSxcclxuICAgICAgICBwYXJhbXM/OiBhbnksXHJcbiAgICAgICAgbGFuZ3VhZ2UgPSB0aGlzLmxvY2FsZS5sYW5ndWFnZVxyXG4gICAgKTogc3RyaW5nIHwgYW55IHtcclxuICAgICAgICBsYW5ndWFnZSA9IGZvcm1hdExhbmd1YWdlKGxhbmd1YWdlLCB0aGlzLmNvbmZpZy5mb3JtYXQpO1xyXG5cclxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShrZXlzKSkge1xyXG4gICAgICAgICAgICBjb25zdCBkYXRhOiB7IFtrZXk6IHN0cmluZ106IGFueSB9ID0ge307XHJcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcclxuICAgICAgICAgICAgICAgIGRhdGFba2V5XSA9IHRoaXMudHJhbnNsYXRlKGtleSwgcGFyYW1zLCBsYW5ndWFnZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGRhdGE7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCB2YWx1ZSA9IGdldFZhbHVlKGtleXMsIHRoaXMuZGF0YVtsYW5ndWFnZV0sIHRoaXMuY29uZmlnLmtleVNlcGFyYXRvcik7XHJcblxyXG4gICAgICAgIHJldHVybiB2YWx1ZSA/IHRoaXMudHJhbnNsYXRpb25IYW5kbGVyLnBhcnNlVmFsdWUoa2V5cywgcGFyYW1zLCB2YWx1ZSkgOiB0aGlzLm1pc3NpbmdUcmFuc2xhdGlvbkhhbmRsZXIuaGFuZGxlKGtleXMsIHZhbHVlLCBwYXJhbXMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2hlY2tzIGlmIGEgdHJhbnNsYXRpb24gZXhpc3RzLlxyXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIGJlIHRlc3RlZFxyXG4gICAgICogQHBhcmFtIGxhbmd1YWdlIFRoZSBjdXJyZW50IGxhbmd1YWdlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBoYXMoa2V5OiBzdHJpbmcsIGxhbmd1YWdlID0gdGhpcy5sb2NhbGUubGFuZ3VhZ2UpOiBib29sZWFuIHtcclxuICAgICAgICBsYW5ndWFnZSA9IGZvcm1hdExhbmd1YWdlKGxhbmd1YWdlLCB0aGlzLmNvbmZpZy5mb3JtYXQpO1xyXG5cclxuICAgICAgICByZXR1cm4gZ2V0VmFsdWUoa2V5LCB0aGlzLmRhdGFbbGFuZ3VhZ2VdLCB0aGlzLmNvbmZpZy5rZXlTZXBhcmF0b3IpICE9PSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgbGFuZ3VhZ2UgZGlyZWN0aW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0TGFuZ3VhZ2VEaXJlY3Rpb24obGFuZ3VhZ2UgPSB0aGlzLmxvY2FsZS5sYW5ndWFnZSk6ICdsdHInIHwgJ3J0bCcgfCB1bmRlZmluZWQge1xyXG4gICAgICAgIGNvbnN0IHNjaGVtYSA9IGdldFNjaGVtYSh0aGlzLmNvbmZpZy5zY2hlbWEsIGxhbmd1YWdlLCB0aGlzLmNvbmZpZy5mb3JtYXQpO1xyXG4gICAgICAgIHJldHVybiBzY2hlbWEgPyBzY2hlbWEuZGlyIDogdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyBhdmFpbGFibGUgbGFuZ3VhZ2VzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0QXZhaWxhYmxlTGFuZ3VhZ2VzKCk6IHN0cmluZ1tdIHtcclxuICAgICAgICBjb25zdCBsYW5ndWFnZXMgPSB0aGlzLmNvbmZpZy5zY2hlbWEubWFwKGl0ZW0gPT4gZm9ybWF0TGFuZ3VhZ2UoaXRlbS5sb2NhbGUubGFuZ3VhZ2UsIHRoaXMuY29uZmlnLmZvcm1hdCkpO1xyXG4gICAgICAgIHJldHVybiBsYW5ndWFnZXM7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgc2VydmljZVxyXG4gICAgICogQHBhcmFtIHByb3ZpZGVycyBBbiBhcnJheSBvZiBMMTBuUHJvdmlkZXJcclxuICAgICAqL1xyXG4gICAgcHVibGljIGFzeW5jIGluaXQocHJvdmlkZXJzOiBMMTBuUHJvdmlkZXJbXSA9IHRoaXMuY29uZmlnLnByb3ZpZGVycyk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGxldCBsb2NhbGU6IEwxMG5Mb2NhbGUgfCBudWxsID0gbnVsbDtcclxuXHJcbiAgICAgICAgLy8gVHJpZXMgdG8gZ2V0IGxvY2FsZSBmcm9tIHN0b3JhZ2UuXHJcbiAgICAgICAgaWYgKGxvY2FsZSA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIGxvY2FsZSA9IGF3YWl0IHRoaXMuc3RvcmFnZS5yZWFkKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIFRyaWVzIHJlc29sdmVkIGxvY2FsZS5cclxuICAgICAgICBpZiAobG9jYWxlID09IG51bGwpIHtcclxuICAgICAgICAgICAgbG9jYWxlID0gYXdhaXQgdGhpcy5yZXNvbHZlTG9jYWxlLmdldCgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBVc2VzIGRlZmF1bHQgbG9jYWxlLlxyXG4gICAgICAgIGlmIChsb2NhbGUgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICBsb2NhbGUgPSB0aGlzLmNvbmZpZy5kZWZhdWx0TG9jYWxlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gTG9hZHMgdHJhbnNsYXRpb24gZGF0YS5cclxuICAgICAgICBhd2FpdCB0aGlzLmxvYWRUcmFuc2xhdGlvbnMocHJvdmlkZXJzLCBsb2NhbGUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FuIGJlIGNhbGxlZCBhdCBldmVyeSB0cmFuc2xhdGlvbiBjaGFuZ2UuXHJcbiAgICAgKiBAcGFyYW0gcHJvdmlkZXJzIEFuIGFycmF5IG9mIEwxMG5Qcm92aWRlclxyXG4gICAgICogQHBhcmFtIGxvY2FsZSBUaGUgY3VycmVudCBsb2NhbGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGFzeW5jIGxvYWRUcmFuc2xhdGlvbnMocHJvdmlkZXJzOiBMMTBuUHJvdmlkZXJbXSA9IHRoaXMuY29uZmlnLnByb3ZpZGVycywgbG9jYWxlID0gdGhpcy5sb2NhbGUpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBjb25zdCBsYW5ndWFnZSA9IGZvcm1hdExhbmd1YWdlKGxvY2FsZS5sYW5ndWFnZSwgdGhpcy5jb25maWcuZm9ybWF0KTtcclxuXHJcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbmNhdCguLi50aGlzLmdldFRyYW5zbGF0aW9uKHByb3ZpZGVycywgbGFuZ3VhZ2UpKS5zdWJzY3JpYmUoe1xyXG4gICAgICAgICAgICAgICAgbmV4dDogKGRhdGEpID0+IHRoaXMuYWRkRGF0YShkYXRhLCBsYW5ndWFnZSksXHJcbiAgICAgICAgICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVFcnJvcihlcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWxlYXNlVHJhbnNsYXRpb24obG9jYWxlKTtcclxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FuIGJlIGNhbGxlZCB0byBhZGQgdHJhbnNsYXRpb24gZGF0YS5cclxuICAgICAqIEBwYXJhbSBkYXRhIFRoZSB0cmFuc2xhdGlvbiBkYXRhIHtrZXk6IHZhbHVlfVxyXG4gICAgICogQHBhcmFtIGxhbmd1YWdlIFRoZSBsYW5ndWFnZSB0byBhZGQgZGF0YVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYWRkRGF0YShkYXRhOiB7IFtrZXk6IHN0cmluZ106IGFueSB9LCBsYW5ndWFnZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5kYXRhW2xhbmd1YWdlXSA9IHRoaXMuZGF0YVtsYW5ndWFnZV0gIT09IHVuZGVmaW5lZFxyXG4gICAgICAgICAgICA/IG1lcmdlRGVlcCh0aGlzLmRhdGFbbGFuZ3VhZ2VdLCBkYXRhKVxyXG4gICAgICAgICAgICA6IGRhdGE7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBZGRzIHByb3ZpZGVycyB0byBjb25maWd1cmF0aW9uXHJcbiAgICAgKiBAcGFyYW0gcHJvdmlkZXJzIFRoZSBwcm92aWRlcnMgb2YgdGhlIHRyYW5zbGF0aW9ucyBkYXRhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhZGRQcm92aWRlcnMocHJvdmlkZXJzOiBMMTBuUHJvdmlkZXJbXSk6IHZvaWQge1xyXG4gICAgICAgIHByb3ZpZGVycy5mb3JFYWNoKHByb3ZpZGVyID0+IHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5wcm92aWRlcnMuZmluZChwID0+IHAubmFtZSA9PT0gcHJvdmlkZXIubmFtZSkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLnByb3ZpZGVycy5wdXNoKHByb3ZpZGVyKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0VHJhbnNsYXRpb24ocHJvdmlkZXJzOiBMMTBuUHJvdmlkZXJbXSwgbGFuZ3VhZ2U6IHN0cmluZyk6IE9ic2VydmFibGU8YW55PltdIHtcclxuICAgICAgICBjb25zdCBsYXp5TG9hZGVyczogT2JzZXJ2YWJsZTxhbnk+W10gPSBbXTtcclxuICAgICAgICBsZXQgbG9hZGVyczogT2JzZXJ2YWJsZTxhbnk+W10gPSBbXTtcclxuXHJcbiAgICAgICAgZm9yIChjb25zdCBwcm92aWRlciBvZiBwcm92aWRlcnMpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmZhbGxiYWNrKSB7XHJcbiAgICAgICAgICAgICAgICBsb2FkZXJzID0gbG9hZGVycy5jb25jYXQodGhpcy50cmFuc2xhdGlvbkZhbGxiYWNrLmdldChsYW5ndWFnZSwgcHJvdmlkZXIpKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5jYWNoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxhenlMb2FkZXJzLnB1c2goXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FjaGUucmVhZChgJHtwcm92aWRlci5uYW1lfS0ke2xhbmd1YWdlfWAsIHRoaXMudHJhbnNsYXRpb25Mb2FkZXIuZ2V0KGxhbmd1YWdlLCBwcm92aWRlcikpXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGF6eUxvYWRlcnMucHVzaCh0aGlzLnRyYW5zbGF0aW9uTG9hZGVyLmdldChsYW5ndWFnZSwgcHJvdmlkZXIpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBsb2FkZXJzLnB1c2gobWVyZ2UoLi4ubGF6eUxvYWRlcnMpKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGxvYWRlcnM7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBoYW5kbGVFcnJvcihlcnJvcjogYW55KTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5lcnJvci5uZXh0KGVycm9yKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHJlbGVhc2VUcmFuc2xhdGlvbihsb2NhbGU6IEwxMG5Mb2NhbGUpOiB2b2lkIHtcclxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMubG9jYWxlLCBsb2NhbGUpO1xyXG4gICAgICAgIHRoaXMudHJhbnNsYXRpb24ubmV4dCh0aGlzLmxvY2FsZSk7XHJcbiAgICAgICAgdGhpcy5zdG9yYWdlLndyaXRlKHRoaXMubG9jYWxlKTtcclxuICAgIH1cclxuXHJcbn1cclxuIl19