@jsverse/transloco 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/CHANGELOG.md +1005 -0
  2. package/LICENSE +22 -0
  3. package/README.md +44 -0
  4. package/esm2022/index.mjs +20 -0
  5. package/esm2022/jsverse-transloco.mjs +5 -0
  6. package/esm2022/lib/browser-lang.mjs +28 -0
  7. package/esm2022/lib/get-fallbacks-loaders.mjs +13 -0
  8. package/esm2022/lib/helpers.mjs +104 -0
  9. package/esm2022/lib/lang-resolver.mjs +54 -0
  10. package/esm2022/lib/loader-component.component.mjs +21 -0
  11. package/esm2022/lib/resolve-loader.mjs +13 -0
  12. package/esm2022/lib/scope-resolver.mjs +24 -0
  13. package/esm2022/lib/shared.mjs +73 -0
  14. package/esm2022/lib/template-handler.mjs +28 -0
  15. package/esm2022/lib/transloco-fallback-strategy.mjs +26 -0
  16. package/esm2022/lib/transloco-lang.mjs +3 -0
  17. package/esm2022/lib/transloco-loading-template.mjs +3 -0
  18. package/esm2022/lib/transloco-missing-handler.mjs +18 -0
  19. package/esm2022/lib/transloco-scope.mjs +3 -0
  20. package/esm2022/lib/transloco-testing.module.mjs +76 -0
  21. package/esm2022/lib/transloco.config.mjs +37 -0
  22. package/esm2022/lib/transloco.directive.mjs +169 -0
  23. package/esm2022/lib/transloco.interceptor.mjs +17 -0
  24. package/esm2022/lib/transloco.loader.mjs +13 -0
  25. package/esm2022/lib/transloco.module.mjs +18 -0
  26. package/esm2022/lib/transloco.pipe.mjs +97 -0
  27. package/esm2022/lib/transloco.providers.mjs +92 -0
  28. package/esm2022/lib/transloco.service.mjs +579 -0
  29. package/esm2022/lib/transloco.transpiler.mjs +145 -0
  30. package/esm2022/lib/types.mjs +2 -0
  31. package/fesm2022/jsverse-transloco.mjs +1580 -0
  32. package/fesm2022/jsverse-transloco.mjs.map +1 -0
  33. package/index.d.ts +19 -0
  34. package/lib/browser-lang.d.ts +8 -0
  35. package/lib/get-fallbacks-loaders.d.ts +14 -0
  36. package/lib/helpers.d.ts +21 -0
  37. package/lib/lang-resolver.d.ts +32 -0
  38. package/lib/loader-component.component.d.ts +6 -0
  39. package/lib/resolve-loader.d.ts +10 -0
  40. package/lib/scope-resolver.d.ts +12 -0
  41. package/lib/shared.d.ts +17 -0
  42. package/lib/template-handler.d.ts +9 -0
  43. package/lib/transloco-fallback-strategy.d.ts +14 -0
  44. package/lib/transloco-lang.d.ts +2 -0
  45. package/lib/transloco-loading-template.d.ts +3 -0
  46. package/lib/transloco-missing-handler.d.ts +16 -0
  47. package/lib/transloco-scope.d.ts +3 -0
  48. package/lib/transloco-testing.module.d.ts +27 -0
  49. package/lib/transloco.config.d.ts +27 -0
  50. package/lib/transloco.directive.d.ts +50 -0
  51. package/lib/transloco.interceptor.d.ts +14 -0
  52. package/lib/transloco.loader.d.ts +15 -0
  53. package/lib/transloco.module.d.ts +8 -0
  54. package/lib/transloco.pipe.d.ts +23 -0
  55. package/lib/transloco.providers.d.ts +30 -0
  56. package/lib/transloco.service.d.ts +199 -0
  57. package/lib/transloco.transpiler.d.ts +58 -0
  58. package/lib/types.d.ts +45 -0
  59. package/package.json +54 -0
  60. package/schematics/src/assets/i18n/en.json +1 -0
  61. package/schematics/src/collection.json +59 -0
  62. package/schematics/src/component/index.d.ts +2 -0
  63. package/schematics/src/component/index.js +21 -0
  64. package/schematics/src/component/index.js.map +1 -0
  65. package/schematics/src/join/index.d.ts +3 -0
  66. package/schematics/src/join/index.js +79 -0
  67. package/schematics/src/join/index.js.map +1 -0
  68. package/schematics/src/join/schema.d.ts +28 -0
  69. package/schematics/src/join/schema.js +3 -0
  70. package/schematics/src/join/schema.js.map +1 -0
  71. package/schematics/src/join/schema.json +43 -0
  72. package/schematics/src/keys-manager/index.d.ts +5 -0
  73. package/schematics/src/keys-manager/index.js +97 -0
  74. package/schematics/src/keys-manager/index.js.map +1 -0
  75. package/schematics/src/keys-manager/schema.d.ts +19 -0
  76. package/schematics/src/keys-manager/schema.js +3 -0
  77. package/schematics/src/keys-manager/schema.js.map +1 -0
  78. package/schematics/src/keys-manager/schema.json +33 -0
  79. package/schematics/src/migrate/index.d.ts +3 -0
  80. package/schematics/src/migrate/index.js +21 -0
  81. package/schematics/src/migrate/index.js.map +1 -0
  82. package/schematics/src/migrate/ngx-translate-migration.d.ts +3 -0
  83. package/schematics/src/migrate/ngx-translate-migration.js +169 -0
  84. package/schematics/src/migrate/ngx-translate-migration.js.map +1 -0
  85. package/schematics/src/migrate/schema.d.ts +10 -0
  86. package/schematics/src/migrate/schema.js +3 -0
  87. package/schematics/src/migrate/schema.js.map +1 -0
  88. package/schematics/src/migrate/schema.json +23 -0
  89. package/schematics/src/ng-add/files/transloco-loader/transloco-loader.__ts__ +12 -0
  90. package/schematics/src/ng-add/files/transloco-module/transloco-root.module.__ts__ +24 -0
  91. package/schematics/src/ng-add/generators/http-loader.gen.d.ts +4 -0
  92. package/schematics/src/ng-add/generators/http-loader.gen.js +15 -0
  93. package/schematics/src/ng-add/generators/http-loader.gen.js.map +1 -0
  94. package/schematics/src/ng-add/generators/root-module.gen.d.ts +9 -0
  95. package/schematics/src/ng-add/generators/root-module.gen.js +31 -0
  96. package/schematics/src/ng-add/generators/root-module.gen.js.map +1 -0
  97. package/schematics/src/ng-add/generators/translation-files.gen.d.ts +4 -0
  98. package/schematics/src/ng-add/generators/translation-files.gen.js +23 -0
  99. package/schematics/src/ng-add/generators/translation-files.gen.js.map +1 -0
  100. package/schematics/src/ng-add/index.d.ts +3 -0
  101. package/schematics/src/ng-add/index.js +103 -0
  102. package/schematics/src/ng-add/index.js.map +1 -0
  103. package/schematics/src/ng-add/schema.d.ts +42 -0
  104. package/schematics/src/ng-add/schema.js +14 -0
  105. package/schematics/src/ng-add/schema.js.map +1 -0
  106. package/schematics/src/ng-add/schema.json +53 -0
  107. package/schematics/src/ng-migrate/index.d.ts +3 -0
  108. package/schematics/src/ng-migrate/index.js +14 -0
  109. package/schematics/src/ng-migrate/index.js.map +1 -0
  110. package/schematics/src/ng-migrate/ng-migrate.d.ts +5 -0
  111. package/schematics/src/ng-migrate/ng-migrate.js +106 -0
  112. package/schematics/src/ng-migrate/ng-migrate.js.map +1 -0
  113. package/schematics/src/ng-migrate/schema.d.ts +14 -0
  114. package/schematics/src/ng-migrate/schema.js +3 -0
  115. package/schematics/src/ng-migrate/schema.js.map +1 -0
  116. package/schematics/src/ng-migrate/schema.json +27 -0
  117. package/schematics/src/schematics.consts.d.ts +4 -0
  118. package/schematics/src/schematics.consts.js +8 -0
  119. package/schematics/src/schematics.consts.js.map +1 -0
  120. package/schematics/src/scope/index.d.ts +3 -0
  121. package/schematics/src/scope/index.js +101 -0
  122. package/schematics/src/scope/index.js.map +1 -0
  123. package/schematics/src/scope/schema.d.ts +28 -0
  124. package/schematics/src/scope/schema.js +3 -0
  125. package/schematics/src/scope/schema.js.map +1 -0
  126. package/schematics/src/scope/schema.json +84 -0
  127. package/schematics/src/split/index.d.ts +3 -0
  128. package/schematics/src/split/index.js +66 -0
  129. package/schematics/src/split/index.js.map +1 -0
  130. package/schematics/src/split/schema.d.ts +20 -0
  131. package/schematics/src/split/schema.js +3 -0
  132. package/schematics/src/split/schema.js.map +1 -0
  133. package/schematics/src/split/schema.json +35 -0
  134. package/schematics/src/types.d.ts +5 -0
  135. package/schematics/src/types.js +10 -0
  136. package/schematics/src/types.js.map +1 -0
  137. package/schematics/src/upgrade/index.d.ts +3 -0
  138. package/schematics/src/upgrade/index.js +19 -0
  139. package/schematics/src/upgrade/index.js.map +1 -0
  140. package/schematics/src/upgrade/schema.d.ts +6 -0
  141. package/schematics/src/upgrade/schema.js +3 -0
  142. package/schematics/src/upgrade/schema.js.map +1 -0
  143. package/schematics/src/upgrade/schema.json +16 -0
  144. package/schematics/src/upgrade/v2.d.ts +1 -0
  145. package/schematics/src/upgrade/v2.js +89 -0
  146. package/schematics/src/upgrade/v2.js.map +1 -0
  147. package/schematics/src/utils/array.d.ts +3 -0
  148. package/schematics/src/utils/array.js +12 -0
  149. package/schematics/src/utils/array.js.map +1 -0
  150. package/schematics/src/utils/config.d.ts +2 -0
  151. package/schematics/src/utils/config.js +13 -0
  152. package/schematics/src/utils/config.js.map +1 -0
  153. package/schematics/src/utils/find-module.d.ts +23 -0
  154. package/schematics/src/utils/find-module.js +110 -0
  155. package/schematics/src/utils/find-module.js.map +1 -0
  156. package/schematics/src/utils/package.d.ts +5 -0
  157. package/schematics/src/utils/package.js +19 -0
  158. package/schematics/src/utils/package.js.map +1 -0
  159. package/schematics/src/utils/projects.d.ts +8 -0
  160. package/schematics/src/utils/projects.js +56 -0
  161. package/schematics/src/utils/projects.js.map +1 -0
  162. package/schematics/src/utils/translations.d.ts +7 -0
  163. package/schematics/src/utils/translations.js +31 -0
  164. package/schematics/src/utils/translations.js.map +1 -0
  165. package/schematics/src/utils/transloco.d.ts +24 -0
  166. package/schematics/src/utils/transloco.js +93 -0
  167. package/schematics/src/utils/transloco.js.map +1 -0
@@ -0,0 +1,579 @@
1
+ import { Inject, Injectable, Optional } from '@angular/core';
2
+ import { BehaviorSubject, catchError, combineLatest, EMPTY, forkJoin, from, map, of, retry, shareReplay, Subject, switchMap, tap, } from 'rxjs';
3
+ import { DefaultLoader, TRANSLOCO_LOADER, } from './transloco.loader';
4
+ import { TRANSLOCO_TRANSPILER, } from './transloco.transpiler';
5
+ import { flatten, isEmpty, isNil, isScopeArray, isScopeObject, isString, size, toCamelCase, unflatten, } from './helpers';
6
+ import { TRANSLOCO_CONFIG } from './transloco.config';
7
+ import { TRANSLOCO_MISSING_HANDLER, } from './transloco-missing-handler';
8
+ import { TRANSLOCO_INTERCEPTOR, } from './transloco.interceptor';
9
+ import { TRANSLOCO_FALLBACK_STRATEGY, } from './transloco-fallback-strategy';
10
+ import { getEventPayload, getLangFromScope, getScopeFromLang, resolveInlineLoader, } from './shared';
11
+ import { getFallbacksLoaders } from './get-fallbacks-loaders';
12
+ import { resolveLoader } from './resolve-loader';
13
+ import * as i0 from "@angular/core";
14
+ let service;
15
+ export function translate(key, params = {}, lang) {
16
+ return service.translate(key, params, lang);
17
+ }
18
+ export function translateObject(key, params = {}, lang) {
19
+ return service.translateObject(key, params, lang);
20
+ }
21
+ export class TranslocoService {
22
+ loader;
23
+ parser;
24
+ missingHandler;
25
+ interceptor;
26
+ fallbackStrategy;
27
+ langChanges$;
28
+ subscription = null;
29
+ translations = new Map();
30
+ cache = new Map();
31
+ firstFallbackLang;
32
+ defaultLang = '';
33
+ availableLangs = [];
34
+ isResolvedMissingOnce = false;
35
+ lang;
36
+ failedLangs = new Set();
37
+ events = new Subject();
38
+ events$ = this.events.asObservable();
39
+ config;
40
+ constructor(loader, parser, missingHandler, interceptor, userConfig, fallbackStrategy) {
41
+ this.loader = loader;
42
+ this.parser = parser;
43
+ this.missingHandler = missingHandler;
44
+ this.interceptor = interceptor;
45
+ this.fallbackStrategy = fallbackStrategy;
46
+ if (!this.loader) {
47
+ this.loader = new DefaultLoader(this.translations);
48
+ }
49
+ service = this;
50
+ this.config = JSON.parse(JSON.stringify(userConfig));
51
+ this.setAvailableLangs(this.config.availableLangs || []);
52
+ this.setFallbackLangForMissingTranslation(this.config);
53
+ this.setDefaultLang(this.config.defaultLang);
54
+ this.lang = new BehaviorSubject(this.getDefaultLang());
55
+ // Don't use distinctUntilChanged as we need the ability to update
56
+ // the value when using setTranslation or setTranslationKeys
57
+ this.langChanges$ = this.lang.asObservable();
58
+ /**
59
+ * When we have a failure, we want to define the next language that succeeded as the active
60
+ */
61
+ this.subscription = this.events$.subscribe((e) => {
62
+ if (e.type === 'translationLoadSuccess' && e.wasFailure) {
63
+ this.setActiveLang(e.payload.langName);
64
+ }
65
+ });
66
+ }
67
+ getDefaultLang() {
68
+ return this.defaultLang;
69
+ }
70
+ setDefaultLang(lang) {
71
+ this.defaultLang = lang;
72
+ }
73
+ getActiveLang() {
74
+ return this.lang.getValue();
75
+ }
76
+ setActiveLang(lang) {
77
+ this.parser.onLangChanged?.(lang);
78
+ this.lang.next(lang);
79
+ this.events.next({
80
+ type: 'langChanged',
81
+ payload: getEventPayload(lang),
82
+ });
83
+ return this;
84
+ }
85
+ setAvailableLangs(langs) {
86
+ this.availableLangs = langs;
87
+ }
88
+ /**
89
+ * Gets the available languages.
90
+ *
91
+ * @returns
92
+ * An array of the available languages. Can be either a `string[]` or a `{ id: string; label: string }[]`
93
+ * depending on how the available languages are set in your module.
94
+ */
95
+ getAvailableLangs() {
96
+ return this.availableLangs;
97
+ }
98
+ load(path, options = {}) {
99
+ const cached = this.cache.get(path);
100
+ if (cached) {
101
+ return cached;
102
+ }
103
+ let loadTranslation;
104
+ const isScope = this._isLangScoped(path);
105
+ let scope;
106
+ if (isScope) {
107
+ scope = getScopeFromLang(path);
108
+ }
109
+ const loadersOptions = {
110
+ path,
111
+ mainLoader: this.loader,
112
+ inlineLoader: options.inlineLoader,
113
+ data: isScope ? { scope: scope } : undefined,
114
+ };
115
+ if (this.useFallbackTranslation(path)) {
116
+ // if the path is scope the fallback should be `scope/fallbackLang`;
117
+ const fallback = isScope
118
+ ? `${scope}/${this.firstFallbackLang}`
119
+ : this.firstFallbackLang;
120
+ const loaders = getFallbacksLoaders({
121
+ ...loadersOptions,
122
+ fallbackPath: fallback,
123
+ });
124
+ loadTranslation = forkJoin(loaders);
125
+ }
126
+ else {
127
+ const loader = resolveLoader(loadersOptions);
128
+ loadTranslation = from(loader);
129
+ }
130
+ const load$ = loadTranslation.pipe(retry(this.config.failedRetries), tap((translation) => {
131
+ if (Array.isArray(translation)) {
132
+ translation.forEach((t) => {
133
+ this.handleSuccess(t.lang, t.translation);
134
+ // Save the fallback in cache so we'll not create a redundant request
135
+ if (t.lang !== path) {
136
+ this.cache.set(t.lang, of({}));
137
+ }
138
+ });
139
+ return;
140
+ }
141
+ this.handleSuccess(path, translation);
142
+ }), catchError((error) => {
143
+ if (!this.config.prodMode) {
144
+ console.error(`Error while trying to load "${path}"`, error);
145
+ }
146
+ return this.handleFailure(path, options);
147
+ }), shareReplay(1));
148
+ this.cache.set(path, load$);
149
+ return load$;
150
+ }
151
+ /**
152
+ * Gets the instant translated value of a key
153
+ *
154
+ * @example
155
+ *
156
+ * translate<string>('hello')
157
+ * translate('hello', { value: 'value' })
158
+ * translate<string[]>(['hello', 'key'])
159
+ * translate('hello', { }, 'en')
160
+ * translate('scope.someKey', { }, 'en')
161
+ */
162
+ translate(key, params = {}, lang = this.getActiveLang()) {
163
+ if (!key)
164
+ return key;
165
+ const { scope, resolveLang } = this.resolveLangAndScope(lang);
166
+ if (Array.isArray(key)) {
167
+ return key.map((k) => this.translate(scope ? `${scope}.${k}` : k, params, resolveLang));
168
+ }
169
+ key = scope ? `${scope}.${key}` : key;
170
+ const translation = this.getTranslation(resolveLang);
171
+ const value = translation[key];
172
+ if (!value) {
173
+ return this._handleMissingKey(key, value, params);
174
+ }
175
+ return this.parser.transpile({
176
+ value, params, translation, key
177
+ });
178
+ }
179
+ /**
180
+ * Gets the translated value of a key as observable
181
+ *
182
+ * @example
183
+ *
184
+ * selectTranslate<string>('hello').subscribe(value => ...)
185
+ * selectTranslate<string>('hello', {}, 'es').subscribe(value => ...)
186
+ * selectTranslate<string>('hello', {}, 'todos').subscribe(value => ...)
187
+ * selectTranslate<string>('hello', {}, { scope: 'todos' }).subscribe(value => ...)
188
+ *
189
+ */
190
+ selectTranslate(key, params, lang, _isObject = false) {
191
+ let inlineLoader;
192
+ const load = (lang, options) => this.load(lang, options).pipe(map(() => _isObject
193
+ ? this.translateObject(key, params, lang)
194
+ : this.translate(key, params, lang)));
195
+ if (isNil(lang)) {
196
+ return this.langChanges$.pipe(switchMap((lang) => load(lang)));
197
+ }
198
+ if (isScopeArray(lang) || isScopeObject(lang)) {
199
+ // it's a scope object.
200
+ const providerScope = Array.isArray(lang) ? lang[0] : lang;
201
+ lang = providerScope.scope;
202
+ inlineLoader = resolveInlineLoader(providerScope, providerScope.scope);
203
+ }
204
+ lang = lang;
205
+ if (this.isLang(lang) || this.isScopeWithLang(lang)) {
206
+ return load(lang);
207
+ }
208
+ // it's a scope
209
+ const scope = lang;
210
+ return this.langChanges$.pipe(switchMap((lang) => load(`${scope}/${lang}`, { inlineLoader })));
211
+ }
212
+ /**
213
+ * Whether the scope with lang
214
+ *
215
+ * @example
216
+ *
217
+ * todos/en => true
218
+ * todos => false
219
+ */
220
+ isScopeWithLang(lang) {
221
+ return this.isLang(getLangFromScope(lang));
222
+ }
223
+ translateObject(key, params = {}, lang = this.getActiveLang()) {
224
+ if (isString(key) || Array.isArray(key)) {
225
+ const { resolveLang, scope } = this.resolveLangAndScope(lang);
226
+ if (Array.isArray(key)) {
227
+ return key.map((k) => this.translateObject(scope ? `${scope}.${k}` : k, params, resolveLang));
228
+ }
229
+ const translation = this.getTranslation(resolveLang);
230
+ key = scope ? `${scope}.${key}` : key;
231
+ const value = unflatten(this.getObjectByKey(translation, key));
232
+ /* If an empty object was returned we want to try and translate the key as a string and not an object */
233
+ return isEmpty(value)
234
+ ? this.translate(key, params, lang)
235
+ : this.parser.transpile({ value, params: params, translation, key });
236
+ }
237
+ const translations = [];
238
+ for (const [_key, _params] of this.getEntries(key)) {
239
+ translations.push(this.translateObject(_key, _params, lang));
240
+ }
241
+ return translations;
242
+ }
243
+ selectTranslateObject(key, params, lang) {
244
+ if (isString(key) || Array.isArray(key)) {
245
+ return this.selectTranslate(key, params, lang, true);
246
+ }
247
+ const [[firstKey, firstParams], ...rest] = this.getEntries(key);
248
+ /* In order to avoid subscribing multiple times to the load language event by calling selectTranslateObject for each pair,
249
+ * we listen to when the first key has been translated (the language is loaded) and translate the rest synchronously */
250
+ return this.selectTranslateObject(firstKey, firstParams, lang).pipe(map((value) => {
251
+ const translations = [value];
252
+ for (const [_key, _params] of rest) {
253
+ translations.push(this.translateObject(_key, _params, lang));
254
+ }
255
+ return translations;
256
+ }));
257
+ }
258
+ getTranslation(langOrScope) {
259
+ if (langOrScope) {
260
+ if (this.isLang(langOrScope)) {
261
+ return this.translations.get(langOrScope) || {};
262
+ }
263
+ else {
264
+ // This is a scope, build the scope value from the translation object
265
+ const { scope, resolveLang } = this.resolveLangAndScope(langOrScope);
266
+ const translation = this.translations.get(resolveLang) || {};
267
+ return this.getObjectByKey(translation, scope);
268
+ }
269
+ }
270
+ return this.translations;
271
+ }
272
+ /**
273
+ * Gets an object of translations for a given language
274
+ *
275
+ * @example
276
+ *
277
+ * selectTranslation().subscribe() - will return the current lang translation
278
+ * selectTranslation('es').subscribe()
279
+ * selectTranslation('admin-page').subscribe() - will return the current lang scope translation
280
+ * selectTranslation('admin-page/es').subscribe()
281
+ */
282
+ selectTranslation(lang) {
283
+ let language$ = this.langChanges$;
284
+ if (lang) {
285
+ const scopeLangSpecified = getLangFromScope(lang) !== lang;
286
+ if (this.isLang(lang) || scopeLangSpecified) {
287
+ language$ = of(lang);
288
+ }
289
+ else {
290
+ language$ = this.langChanges$.pipe(map((currentLang) => `${lang}/${currentLang}`));
291
+ }
292
+ }
293
+ return language$.pipe(switchMap((language) => this.load(language).pipe(map(() => this.getTranslation(language)))));
294
+ }
295
+ /**
296
+ * Sets or merge a given translation object to current lang
297
+ *
298
+ * @example
299
+ *
300
+ * setTranslation({ ... })
301
+ * setTranslation({ ... }, 'en')
302
+ * setTranslation({ ... }, 'es', { merge: false } )
303
+ * setTranslation({ ... }, 'todos/en', { merge: false } )
304
+ */
305
+ setTranslation(translation, lang = this.getActiveLang(), options = {}) {
306
+ const defaults = { merge: true, emitChange: true };
307
+ const mergedOptions = { ...defaults, ...options };
308
+ const scope = getScopeFromLang(lang);
309
+ /**
310
+ * If this isn't a scope we use the whole translation as is
311
+ * otherwise we need to flat the scope and use it
312
+ */
313
+ let flattenScopeOrTranslation = translation;
314
+ // Merged the scoped language into the active language
315
+ if (scope) {
316
+ const key = this.getMappedScope(scope);
317
+ flattenScopeOrTranslation = flatten({ [key]: translation });
318
+ }
319
+ const currentLang = scope ? getLangFromScope(lang) : lang;
320
+ const mergedTranslation = {
321
+ ...(mergedOptions.merge && this.getTranslation(currentLang)),
322
+ ...flattenScopeOrTranslation,
323
+ };
324
+ const flattenTranslation = this.config.flatten.aot
325
+ ? mergedTranslation
326
+ : flatten(mergedTranslation);
327
+ const withHook = this.interceptor.preSaveTranslation(flattenTranslation, currentLang);
328
+ this.translations.set(currentLang, withHook);
329
+ mergedOptions.emitChange && this.setActiveLang(this.getActiveLang());
330
+ }
331
+ /**
332
+ * Sets translation key with given value
333
+ *
334
+ * @example
335
+ *
336
+ * setTranslationKey('key', 'value')
337
+ * setTranslationKey('key.nested', 'value')
338
+ * setTranslationKey('key.nested', 'value', 'en')
339
+ * setTranslationKey('key.nested', 'value', 'en', { emitChange: false } )
340
+ */
341
+ setTranslationKey(key, value, options = {}) {
342
+ const lang = options.lang || this.getActiveLang();
343
+ const withHook = this.interceptor.preSaveTranslationKey(key, value, lang);
344
+ const newValue = {
345
+ [key]: withHook,
346
+ };
347
+ this.setTranslation(newValue, lang, { ...options, merge: true });
348
+ }
349
+ /**
350
+ * Sets the fallback lang for the currently active language
351
+ * @param fallbackLang
352
+ */
353
+ setFallbackLangForMissingTranslation({ fallbackLang, }) {
354
+ const lang = Array.isArray(fallbackLang) ? fallbackLang[0] : fallbackLang;
355
+ if (fallbackLang && this.useFallbackTranslation(lang)) {
356
+ this.firstFallbackLang = lang;
357
+ }
358
+ }
359
+ /**
360
+ * @internal
361
+ */
362
+ _handleMissingKey(key, value, params) {
363
+ if (this.config.missingHandler.allowEmpty && value === '') {
364
+ return '';
365
+ }
366
+ if (!this.isResolvedMissingOnce && this.useFallbackTranslation()) {
367
+ // We need to set it to true to prevent a loop
368
+ this.isResolvedMissingOnce = true;
369
+ const fallbackValue = this.translate(key, params, this.firstFallbackLang);
370
+ this.isResolvedMissingOnce = false;
371
+ return fallbackValue;
372
+ }
373
+ return this.missingHandler.handle(key, this.getMissingHandlerData(), params);
374
+ }
375
+ /**
376
+ * @internal
377
+ */
378
+ _isLangScoped(lang) {
379
+ return this.getAvailableLangsIds().indexOf(lang) === -1;
380
+ }
381
+ /**
382
+ * Checks if a given string is one of the specified available languages.
383
+ * @returns
384
+ * True if the given string is an available language.
385
+ * False if the given string is not an available language.
386
+ */
387
+ isLang(lang) {
388
+ return this.getAvailableLangsIds().indexOf(lang) !== -1;
389
+ }
390
+ /**
391
+ * @internal
392
+ *
393
+ * We always want to make sure the global lang is loaded
394
+ * before loading the scope since you can access both via the pipe/directive.
395
+ */
396
+ _loadDependencies(path, inlineLoader) {
397
+ const mainLang = getLangFromScope(path);
398
+ if (this._isLangScoped(path) && !this.isLoadedTranslation(mainLang)) {
399
+ return combineLatest([
400
+ this.load(mainLang),
401
+ this.load(path, { inlineLoader }),
402
+ ]);
403
+ }
404
+ return this.load(path, { inlineLoader });
405
+ }
406
+ /**
407
+ * @internal
408
+ */
409
+ _completeScopeWithLang(langOrScope) {
410
+ if (this._isLangScoped(langOrScope) &&
411
+ !this.isLang(getLangFromScope(langOrScope))) {
412
+ return `${langOrScope}/${this.getActiveLang()}`;
413
+ }
414
+ return langOrScope;
415
+ }
416
+ /**
417
+ * @internal
418
+ */
419
+ _setScopeAlias(scope, alias) {
420
+ if (!this.config.scopeMapping) {
421
+ this.config.scopeMapping = {};
422
+ }
423
+ this.config.scopeMapping[scope] = alias;
424
+ }
425
+ ngOnDestroy() {
426
+ if (this.subscription) {
427
+ this.subscription.unsubscribe();
428
+ // Caretaker note: it's important to clean up references to subscriptions since they save the `next`
429
+ // callback within its `destination` property, preventing classes from being GC'd.
430
+ this.subscription = null;
431
+ }
432
+ // Caretaker note: since this is the root provider, it'll be destroyed when the `NgModuleRef.destroy()` is run.
433
+ // Cached values capture `this`, thus leading to a circular reference and preventing the `TranslocoService` from
434
+ // being GC'd. This would lead to a memory leak when server-side rendering is used since the service is created
435
+ // and destroyed per each HTTP request, but any service is not getting GC'd.
436
+ this.cache.clear();
437
+ }
438
+ isLoadedTranslation(lang) {
439
+ return size(this.getTranslation(lang));
440
+ }
441
+ getAvailableLangsIds() {
442
+ const first = this.getAvailableLangs()[0];
443
+ if (isString(first)) {
444
+ return this.getAvailableLangs();
445
+ }
446
+ return this.getAvailableLangs().map((l) => l.id);
447
+ }
448
+ getMissingHandlerData() {
449
+ return {
450
+ ...this.config,
451
+ activeLang: this.getActiveLang(),
452
+ availableLangs: this.availableLangs,
453
+ defaultLang: this.defaultLang,
454
+ };
455
+ }
456
+ /**
457
+ * Use a fallback translation set for missing keys of the primary language
458
+ * This is unrelated to the fallback language (which changes the active language)
459
+ */
460
+ useFallbackTranslation(lang) {
461
+ return (this.config.missingHandler.useFallbackTranslation &&
462
+ lang !== this.firstFallbackLang);
463
+ }
464
+ handleSuccess(lang, translation) {
465
+ this.setTranslation(translation, lang, { emitChange: false });
466
+ this.events.next({
467
+ wasFailure: !!this.failedLangs.size,
468
+ type: 'translationLoadSuccess',
469
+ payload: getEventPayload(lang),
470
+ });
471
+ this.failedLangs.forEach((l) => this.cache.delete(l));
472
+ this.failedLangs.clear();
473
+ }
474
+ handleFailure(lang, loadOptions) {
475
+ // When starting to load a first choice language, initialize
476
+ // the failed counter and resolve the fallback langs.
477
+ if (isNil(loadOptions.failedCounter)) {
478
+ loadOptions.failedCounter = 0;
479
+ if (!loadOptions.fallbackLangs) {
480
+ loadOptions.fallbackLangs = this.fallbackStrategy.getNextLangs(lang);
481
+ }
482
+ }
483
+ const splitted = lang.split('/');
484
+ const fallbacks = loadOptions.fallbackLangs;
485
+ const nextLang = fallbacks[loadOptions.failedCounter];
486
+ this.failedLangs.add(lang);
487
+ // This handles the case where a loaded fallback language is requested again
488
+ if (this.cache.has(nextLang)) {
489
+ this.handleSuccess(nextLang, this.getTranslation(nextLang));
490
+ return EMPTY;
491
+ }
492
+ const isFallbackLang = nextLang === splitted[splitted.length - 1];
493
+ if (!nextLang || isFallbackLang) {
494
+ let msg = `Unable to load translation and all the fallback languages`;
495
+ if (splitted.length > 1) {
496
+ msg += `, did you misspelled the scope name?`;
497
+ }
498
+ throw new Error(msg);
499
+ }
500
+ let resolveLang = nextLang;
501
+ // if it's scoped lang
502
+ if (splitted.length > 1) {
503
+ // We need to resolve it to:
504
+ // todos/langNotExists => todos/nextLang
505
+ splitted[splitted.length - 1] = nextLang;
506
+ resolveLang = splitted.join('/');
507
+ }
508
+ loadOptions.failedCounter++;
509
+ this.events.next({
510
+ type: 'translationLoadFailure',
511
+ payload: getEventPayload(lang),
512
+ });
513
+ return this.load(resolveLang, loadOptions);
514
+ }
515
+ getMappedScope(scope) {
516
+ const { scopeMapping = {} } = this.config;
517
+ return scopeMapping[scope] || toCamelCase(scope);
518
+ }
519
+ /**
520
+ * If lang is scope we need to check the following cases:
521
+ * todos/es => in this case we should take `es` as lang
522
+ * todos => in this case we should set the active lang as lang
523
+ */
524
+ resolveLangAndScope(lang) {
525
+ let resolveLang = lang;
526
+ let scope;
527
+ if (this._isLangScoped(lang)) {
528
+ // en for example
529
+ const langFromScope = getLangFromScope(lang);
530
+ // en is lang
531
+ const hasLang = this.isLang(langFromScope);
532
+ // take en
533
+ resolveLang = hasLang ? langFromScope : this.getActiveLang();
534
+ // find the scope
535
+ scope = this.getMappedScope(hasLang ? getScopeFromLang(lang) : lang);
536
+ }
537
+ return { scope, resolveLang };
538
+ }
539
+ getObjectByKey(translation, key) {
540
+ const result = {};
541
+ const prefix = `${key}.`;
542
+ for (const currentKey in translation) {
543
+ if (currentKey.startsWith(prefix)) {
544
+ result[currentKey.replace(prefix, '')] = translation[currentKey];
545
+ }
546
+ }
547
+ return result;
548
+ }
549
+ getEntries(key) {
550
+ return key instanceof Map ? key.entries() : Object.entries(key);
551
+ }
552
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: TranslocoService, deps: [{ token: TRANSLOCO_LOADER, optional: true }, { token: TRANSLOCO_TRANSPILER }, { token: TRANSLOCO_MISSING_HANDLER }, { token: TRANSLOCO_INTERCEPTOR }, { token: TRANSLOCO_CONFIG }, { token: TRANSLOCO_FALLBACK_STRATEGY }], target: i0.ɵɵFactoryTarget.Injectable });
553
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: TranslocoService, providedIn: 'root' });
554
+ }
555
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: TranslocoService, decorators: [{
556
+ type: Injectable,
557
+ args: [{ providedIn: 'root' }]
558
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
559
+ type: Optional
560
+ }, {
561
+ type: Inject,
562
+ args: [TRANSLOCO_LOADER]
563
+ }] }, { type: undefined, decorators: [{
564
+ type: Inject,
565
+ args: [TRANSLOCO_TRANSPILER]
566
+ }] }, { type: undefined, decorators: [{
567
+ type: Inject,
568
+ args: [TRANSLOCO_MISSING_HANDLER]
569
+ }] }, { type: undefined, decorators: [{
570
+ type: Inject,
571
+ args: [TRANSLOCO_INTERCEPTOR]
572
+ }] }, { type: undefined, decorators: [{
573
+ type: Inject,
574
+ args: [TRANSLOCO_CONFIG]
575
+ }] }, { type: undefined, decorators: [{
576
+ type: Inject,
577
+ args: [TRANSLOCO_FALLBACK_STRATEGY]
578
+ }] }] });
579
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsb2NvLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL3RyYW5zbG9jby9zcmMvbGliL3RyYW5zbG9jby5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFhLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4RSxPQUFPLEVBQ0wsZUFBZSxFQUNmLFVBQVUsRUFDVixhQUFhLEVBQ2IsS0FBSyxFQUNMLFFBQVEsRUFDUixJQUFJLEVBQ0osR0FBRyxFQUVILEVBQUUsRUFDRixLQUFLLEVBQ0wsV0FBVyxFQUNYLE9BQU8sRUFFUCxTQUFTLEVBQ1QsR0FBRyxHQUNKLE1BQU0sTUFBTSxDQUFDO0FBRWQsT0FBTyxFQUNMLGFBQWEsRUFDYixnQkFBZ0IsR0FFakIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQ0wsb0JBQW9CLEdBRXJCLE1BQU0sd0JBQXdCLENBQUM7QUFjaEMsT0FBTyxFQUNMLE9BQU8sRUFDUCxPQUFPLEVBQ1AsS0FBSyxFQUNMLFlBQVksRUFDWixhQUFhLEVBQ2IsUUFBUSxFQUNSLElBQUksRUFDSixXQUFXLEVBQ1gsU0FBUyxHQUNWLE1BQU0sV0FBVyxDQUFDO0FBQ25CLE9BQU8sRUFBRSxnQkFBZ0IsRUFBbUIsTUFBTSxvQkFBb0IsQ0FBQztBQUN2RSxPQUFPLEVBQ0wseUJBQXlCLEdBRzFCLE1BQU0sNkJBQTZCLENBQUM7QUFDckMsT0FBTyxFQUNMLHFCQUFxQixHQUV0QixNQUFNLHlCQUF5QixDQUFDO0FBQ2pDLE9BQU8sRUFDTCwyQkFBMkIsR0FFNUIsTUFBTSwrQkFBK0IsQ0FBQztBQUN2QyxPQUFPLEVBQ0wsZUFBZSxFQUNmLGdCQUFnQixFQUNoQixnQkFBZ0IsRUFDaEIsbUJBQW1CLEdBQ3BCLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzlELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQzs7QUFFakQsSUFBSSxPQUF5QixDQUFDO0FBRTlCLE1BQU0sVUFBVSxTQUFTLENBQ3ZCLEdBQW9CLEVBQ3BCLFNBQWtCLEVBQUUsRUFDcEIsSUFBYTtJQUViLE9BQU8sT0FBTyxDQUFDLFNBQVMsQ0FBSSxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ2pELENBQUM7QUFFRCxNQUFNLFVBQVUsZUFBZSxDQUM3QixHQUFvQixFQUNwQixTQUFrQixFQUFFLEVBQ3BCLElBQWE7SUFFYixPQUFPLE9BQU8sQ0FBQyxlQUFlLENBQUksR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztBQUN2RCxDQUFDO0FBR0QsTUFBTSxPQUFPLGdCQUFnQjtJQW9CcUI7SUFDUjtJQUU5QjtJQUMrQjtJQUcvQjtJQTFCVixZQUFZLENBQXFCO0lBRXpCLFlBQVksR0FBd0IsSUFBSSxDQUFDO0lBQ3pDLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBdUIsQ0FBQztJQUM5QyxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQW1DLENBQUM7SUFDbkQsaUJBQWlCLENBQXFCO0lBQ3RDLFdBQVcsR0FBRyxFQUFFLENBQUM7SUFDakIsY0FBYyxHQUFtQixFQUFFLENBQUM7SUFDcEMscUJBQXFCLEdBQUcsS0FBSyxDQUFDO0lBQzlCLElBQUksQ0FBMEI7SUFDOUIsV0FBVyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDaEMsTUFBTSxHQUFHLElBQUksT0FBTyxFQUFtQixDQUFDO0lBRWhELE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzVCLE1BQU0sQ0FFYjtJQUVGLFlBQ2dELE1BQXVCLEVBQy9CLE1BQTJCLEVBRXpELGNBQXVDLEVBQ1IsV0FBaUMsRUFDOUMsVUFBMkIsRUFFN0MsZ0JBQTJDO1FBUEwsV0FBTSxHQUFOLE1BQU0sQ0FBaUI7UUFDL0IsV0FBTSxHQUFOLE1BQU0sQ0FBcUI7UUFFekQsbUJBQWMsR0FBZCxjQUFjLENBQXlCO1FBQ1IsZ0JBQVcsR0FBWCxXQUFXLENBQXNCO1FBR2hFLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBMkI7UUFFbkQsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDaEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLGFBQWEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDcEQ7UUFDRCxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ2YsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUVyRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLElBQUksRUFBRSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLG9DQUFvQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2RCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDN0MsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLGVBQWUsQ0FBUyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUMvRCxrRUFBa0U7UUFDbEUsNERBQTREO1FBQzVELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUU3Qzs7V0FFRztRQUNILElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUMvQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssd0JBQXdCLElBQUksQ0FBQyxDQUFDLFVBQVUsRUFBRTtnQkFDdkQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ3hDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsY0FBYztRQUNaLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUMxQixDQUFDO0lBRUQsY0FBYyxDQUFDLElBQVk7UUFDekIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7SUFDMUIsQ0FBQztJQUVELGFBQWE7UUFDWCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVELGFBQWEsQ0FBQyxJQUFZO1FBQ3hCLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDZixJQUFJLEVBQUUsYUFBYTtZQUNuQixPQUFPLEVBQUUsZUFBZSxDQUFDLElBQUksQ0FBQztTQUMvQixDQUFDLENBQUM7UUFDSCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxLQUFxQjtRQUNyQyxJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQztJQUM5QixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsaUJBQWlCO1FBQ2YsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDO0lBQzdCLENBQUM7SUFFRCxJQUFJLENBQUMsSUFBWSxFQUFFLFVBQXVCLEVBQUU7UUFDMUMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEMsSUFBSSxNQUFNLEVBQUU7WUFDVixPQUFPLE1BQU0sQ0FBQztTQUNmO1FBRUQsSUFBSSxlQUVILENBQUM7UUFDRixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pDLElBQUksS0FBYSxDQUFDO1FBQ2xCLElBQUksT0FBTyxFQUFFO1lBQ1gsS0FBSyxHQUFHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ2hDO1FBRUQsTUFBTSxjQUFjLEdBQUc7WUFDckIsSUFBSTtZQUNKLFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTTtZQUN2QixZQUFZLEVBQUUsT0FBTyxDQUFDLFlBQVk7WUFDbEMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsS0FBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVM7U0FDOUMsQ0FBQztRQUVGLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ3JDLG9FQUFvRTtZQUNwRSxNQUFNLFFBQVEsR0FBRyxPQUFPO2dCQUN0QixDQUFDLENBQUMsR0FBRyxLQUFNLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUN2QyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDO1lBRTNCLE1BQU0sT0FBTyxHQUFHLG1CQUFtQixDQUFDO2dCQUNsQyxHQUFHLGNBQWM7Z0JBQ2pCLFlBQVksRUFBRSxRQUFTO2FBQ3hCLENBQUMsQ0FBQztZQUNILGVBQWUsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDckM7YUFBTTtZQUNMLE1BQU0sTUFBTSxHQUFHLGFBQWEsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM3QyxlQUFlLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ2hDO1FBRUQsTUFBTSxLQUFLLEdBQUcsZUFBZSxDQUFDLElBQUksQ0FDaEMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEVBQ2hDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFO1lBQ2xCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBRTtnQkFDOUIsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO29CQUN4QixJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDO29CQUMxQyxxRUFBcUU7b0JBQ3JFLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLEVBQUU7d0JBQ25CLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7cUJBQ2hDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUNILE9BQU87YUFDUjtZQUNELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3hDLENBQUMsQ0FBQyxFQUNGLFVBQVUsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTtnQkFDekIsT0FBTyxDQUFDLEtBQUssQ0FBQywrQkFBK0IsSUFBSSxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7YUFDOUQ7WUFFRCxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzNDLENBQUMsQ0FBQyxFQUNGLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FDZixDQUFDO1FBRUYsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRTVCLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSCxTQUFTLENBQ1AsR0FBb0IsRUFDcEIsU0FBa0IsRUFBRSxFQUNwQixJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRTtRQUUzQixJQUFJLENBQUMsR0FBRztZQUFFLE9BQU8sR0FBVSxDQUFDO1FBRTVCLE1BQU0sRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTlELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUN0QixPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUNuQixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQzFELENBQUM7U0FDVjtRQUVELEdBQUcsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxJQUFJLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFFdEMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNyRCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFL0IsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNWLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7U0FDbkQ7UUFFRCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDO1lBQzNCLEtBQUssRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLEdBQUc7U0FDaEMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSCxlQUFlLENBQ2IsR0FBb0IsRUFDcEIsTUFBZ0IsRUFDaEIsSUFBaUQsRUFDakQsU0FBUyxHQUFHLEtBQUs7UUFFakIsSUFBSSxZQUFzQyxDQUFDO1FBQzNDLE1BQU0sSUFBSSxHQUFHLENBQUMsSUFBWSxFQUFFLE9BQXFCLEVBQUUsRUFBRSxDQUNuRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQzNCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FDUCxTQUFTO1lBQ1AsQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUM7WUFDekMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FDdEMsQ0FDRixDQUFDO1FBQ0osSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDZixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoRTtRQUVELElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLGFBQWEsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUM3Qyx1QkFBdUI7WUFDdkIsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDM0QsSUFBSSxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUM7WUFDM0IsWUFBWSxHQUFHLG1CQUFtQixDQUFDLGFBQWEsRUFBRSxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDeEU7UUFFRCxJQUFJLEdBQUcsSUFBYyxDQUFDO1FBQ3RCLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ25ELE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ25CO1FBQ0QsZUFBZTtRQUNmLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQztRQUNuQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUMzQixTQUFTLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssSUFBSSxJQUFJLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FDaEUsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ssZUFBZSxDQUFDLElBQVk7UUFDbEMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQXNCRCxlQUFlLENBQ2IsR0FBMEIsRUFDMUIsU0FBeUIsRUFBRSxFQUMzQixJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRTtRQUUzQixJQUFJLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQ3ZDLE1BQU0sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzlELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRTtnQkFDdEIsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FDbkIsSUFBSSxDQUFDLGVBQWUsQ0FDbEIsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUMzQixNQUFPLEVBQ1AsV0FBVyxDQUNaLENBQ0ssQ0FBQzthQUNWO1lBRUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNyRCxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBRXRDLE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQy9ELHdHQUF3RztZQUN4RyxPQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUM7Z0JBQ25CLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxNQUFPLEVBQUUsSUFBSSxDQUFDO2dCQUNwQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU8sRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFDLENBQUMsQ0FBQztTQUN2RTtRQUVELE1BQU0sWUFBWSxHQUFRLEVBQUUsQ0FBQztRQUM3QixLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUNsRCxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1NBQzlEO1FBRUQsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQztJQXNCRCxxQkFBcUIsQ0FDbkIsR0FBMEIsRUFDMUIsTUFBdUIsRUFDdkIsSUFBYTtRQUViLElBQUksUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDdkMsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFJLEdBQUcsRUFBRSxNQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQzFEO1FBRUQsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVoRTsrSEFDdUg7UUFDdkgsT0FBTyxJQUFJLENBQUMscUJBQXFCLENBQUksUUFBUSxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQ3BFLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ1osTUFBTSxZQUFZLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM3QixLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFO2dCQUNsQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUksSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO2FBQ2pFO1lBRUQsT0FBTyxZQUFZLENBQUM7UUFDdEIsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUNKLENBQUM7SUFhRCxjQUFjLENBQUMsV0FBb0I7UUFDakMsSUFBSSxXQUFXLEVBQUU7WUFDZixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUU7Z0JBQzVCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO2FBQ2pEO2lCQUFNO2dCQUNMLHFFQUFxRTtnQkFDckUsTUFBTSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ3JFLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFFN0QsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsQ0FBQzthQUNoRDtTQUNGO1FBRUQsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSCxpQkFBaUIsQ0FBQyxJQUFhO1FBQzdCLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDbEMsSUFBSSxJQUFJLEVBQUU7WUFDUixNQUFNLGtCQUFrQixHQUFHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQztZQUMzRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksa0JBQWtCLEVBQUU7Z0JBQzNDLFNBQVMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDdEI7aUJBQU07Z0JBQ0wsU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUNoQyxHQUFHLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLEdBQUcsSUFBSSxJQUFJLFdBQVcsRUFBRSxDQUFDLENBQy9DLENBQUM7YUFDSDtTQUNGO1FBRUQsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUNuQixTQUFTLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQ25FLENBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSCxjQUFjLENBQ1osV0FBd0IsRUFDeEIsSUFBSSxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsRUFDM0IsVUFBaUMsRUFBRTtRQUVuQyxNQUFNLFFBQVEsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO1FBQ25ELE1BQU0sYUFBYSxHQUFHLEVBQUUsR0FBRyxRQUFRLEVBQUUsR0FBRyxPQUFPLEVBQUUsQ0FBQztRQUNsRCxNQUFNLEtBQUssR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVyQzs7O1dBR0c7UUFDSCxJQUFJLHlCQUF5QixHQUFHLFdBQVcsQ0FBQztRQUU1QyxzREFBc0Q7UUFDdEQsSUFBSSxLQUFLLEVBQUU7WUFDVCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3ZDLHlCQUF5QixHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztTQUM3RDtRQUVELE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUUxRCxNQUFNLGlCQUFpQixHQUFHO1lBQ3hCLEdBQUcsQ0FBQyxhQUFhLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDNUQsR0FBRyx5QkFBeUI7U0FDN0IsQ0FBQztRQUVGLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFRLENBQUMsR0FBRztZQUNqRCxDQUFDLENBQUMsaUJBQWlCO1lBQ25CLENBQUMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUMvQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUNsRCxrQkFBa0IsRUFDbEIsV0FBVyxDQUNaLENBQUM7UUFDRixJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDN0MsYUFBYSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSCxpQkFBaUIsQ0FDZixHQUFXLEVBQ1gsS0FBYSxFQUNiLFVBQWdELEVBQUU7UUFFbEQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDbEQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzFFLE1BQU0sUUFBUSxHQUFHO1lBQ2YsQ0FBQyxHQUFHLENBQUMsRUFBRSxRQUFRO1NBQ2hCLENBQUM7UUFFRixJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxHQUFHLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsb0NBQW9DLENBQUMsRUFDbkMsWUFBWSxHQUMwQjtRQUN0QyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQztRQUMxRSxJQUFJLFlBQVksSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDckQsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUssQ0FBQztTQUNoQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILGlCQUFpQixDQUFDLEdBQVcsRUFBRSxLQUFVLEVBQUUsTUFBZ0I7UUFDekQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWUsQ0FBQyxVQUFVLElBQUksS0FBSyxLQUFLLEVBQUUsRUFBRTtZQUMxRCxPQUFPLEVBQUUsQ0FBQztTQUNYO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsSUFBSSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsRUFBRTtZQUNoRSw4Q0FBOEM7WUFDOUMsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQztZQUNsQyxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUNsQyxHQUFHLEVBQ0gsTUFBTSxFQUNOLElBQUksQ0FBQyxpQkFBa0IsQ0FDeEIsQ0FBQztZQUNGLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxLQUFLLENBQUM7WUFFbkMsT0FBTyxhQUFhLENBQUM7U0FDdEI7UUFFRCxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUMvQixHQUFHLEVBQ0gsSUFBSSxDQUFDLHFCQUFxQixFQUFFLEVBQzVCLE1BQU0sQ0FDUCxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0gsYUFBYSxDQUFDLElBQVk7UUFDeEIsT0FBTyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsTUFBTSxDQUFDLElBQVk7UUFDakIsT0FBTyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsaUJBQWlCLENBQ2YsSUFBWSxFQUNaLFlBQTJCO1FBRTNCLE1BQU0sUUFBUSxHQUFHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXhDLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsRUFBRTtZQUNuRSxPQUFPLGFBQWEsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7Z0JBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsWUFBWSxFQUFFLENBQUM7YUFDbEMsQ0FBQyxDQUFDO1NBQ0o7UUFDRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxzQkFBc0IsQ0FBQyxXQUFtQjtRQUN4QyxJQUNFLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDO1lBQy9CLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUMzQztZQUNBLE9BQU8sR0FBRyxXQUFXLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUM7U0FDakQ7UUFDRCxPQUFPLFdBQVcsQ0FBQztJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxjQUFjLENBQUMsS0FBYSxFQUFFLEtBQWE7UUFDekMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFO1lBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQztTQUMvQjtRQUNELElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUMxQyxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNyQixJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ2hDLG9HQUFvRztZQUNwRyxrRkFBa0Y7WUFDbEYsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7U0FDMUI7UUFDRCwrR0FBK0c7UUFDL0csZ0hBQWdIO1FBQ2hILCtHQUErRztRQUMvRyw0RUFBNEU7UUFDNUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRU8sbUJBQW1CLENBQUMsSUFBWTtRQUN0QyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVPLG9CQUFvQjtRQUMxQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUUxQyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUNuQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsRUFBYyxDQUFDO1NBQzdDO1FBRUQsT0FBUSxJQUFJLENBQUMsaUJBQWlCLEVBQXVCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekUsQ0FBQztJQUVPLHFCQUFxQjtRQUMzQixPQUFPO1lBQ0wsR0FBRyxJQUFJLENBQUMsTUFBTTtZQUNkLFVBQVUsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFO1lBQ2hDLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYztZQUNuQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7U0FDOUIsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSyxzQkFBc0IsQ0FBQyxJQUFhO1FBQzFDLE9BQU8sQ0FDTCxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWUsQ0FBQyxzQkFBc0I7WUFDbEQsSUFBSSxLQUFLLElBQUksQ0FBQyxpQkFBaUIsQ0FDaEMsQ0FBQztJQUNKLENBQUM7SUFFTyxhQUFhLENBQUMsSUFBWSxFQUFFLFdBQXdCO1FBQzFELElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxFQUFFLElBQUksRUFBRSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1lBQ2YsVUFBVSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUk7WUFDbkMsSUFBSSxFQUFFLHdCQUF3QjtZQUM5QixPQUFPLEVBQUUsZUFBZSxDQUFDLElBQUksQ0FBQztTQUMvQixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFTyxhQUFhLENBQUMsSUFBWSxFQUFFLFdBQXdCO1FBQzFELDREQUE0RDtRQUM1RCxxREFBcUQ7UUFDckQsSUFBSSxLQUFLLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQ3BDLFdBQVcsQ0FBQyxhQUFhLEdBQUcsQ0FBQyxDQUFDO1lBRTlCLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxFQUFFO2dCQUM5QixXQUFXLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDdEU7U0FDRjtRQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDakMsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLGFBQWEsQ0FBQztRQUM1QyxNQUFNLFFBQVEsR0FBRyxTQUFVLENBQUMsV0FBVyxDQUFDLGFBQWMsQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTNCLDRFQUE0RTtRQUM1RSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQzVCLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztZQUM1RCxPQUFPLEtBQUssQ0FBQztTQUNkO1FBRUQsTUFBTSxjQUFjLEdBQUcsUUFBUSxLQUFLLFFBQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRWxFLElBQUksQ0FBQyxRQUFRLElBQUksY0FBYyxFQUFFO1lBQy9CLElBQUksR0FBRyxHQUFHLDJEQUEyRCxDQUFDO1lBQ3RFLElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ3ZCLEdBQUcsSUFBSSxzQ0FBc0MsQ0FBQzthQUMvQztZQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDdEI7UUFFRCxJQUFJLFdBQVcsR0FBRyxRQUFRLENBQUM7UUFDM0Isc0JBQXNCO1FBQ3RCLElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDdkIsNEJBQTRCO1lBQzVCLHdDQUF3QztZQUN4QyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUM7WUFDekMsV0FBVyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDbEM7UUFFRCxXQUFXLENBQUMsYUFBYyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDZixJQUFJLEVBQUUsd0JBQXdCO1lBQzlCLE9BQU8sRUFBRSxlQUFlLENBQUMsSUFBSSxDQUFDO1NBQy9CLENBQUMsQ0FBQztRQUVILE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVPLGNBQWMsQ0FBQyxLQUFhO1FBQ2xDLE1BQU0sRUFBRSxZQUFZLEdBQUcsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMxQyxPQUFPLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxtQkFBbUIsQ0FBQyxJQUFZO1FBQ3RDLElBQUksV0FBVyxHQUFHLElBQUksQ0FBQztRQUN2QixJQUFJLEtBQUssQ0FBQztRQUVWLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUM1QixpQkFBaUI7WUFDakIsTUFBTSxhQUFhLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDN0MsYUFBYTtZQUNiLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDM0MsVUFBVTtZQUNWLFdBQVcsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzdELGlCQUFpQjtZQUNqQixLQUFLLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN0RTtRQUVELE9BQU8sRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLENBQUM7SUFDaEMsQ0FBQztJQUVPLGNBQWMsQ0FBQyxXQUF3QixFQUFFLEdBQVk7UUFDM0QsTUFBTSxNQUFNLEdBQWdCLEVBQUUsQ0FBQztRQUMvQixNQUFNLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBRXpCLEtBQUssTUFBTSxVQUFVLElBQUksV0FBVyxFQUFFO1lBQ3BDLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDakMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ2xFO1NBQ0Y7UUFFRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sVUFBVSxDQUFDLEdBQW1DO1FBQ3BELE9BQU8sR0FBRyxZQUFZLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7dUdBdnVCVSxnQkFBZ0Isa0JBb0JMLGdCQUFnQiw2QkFDNUIsb0JBQW9CLGFBQ3BCLHlCQUF5QixhQUV6QixxQkFBcUIsYUFDckIsZ0JBQWdCLGFBQ2hCLDJCQUEyQjsyR0ExQjFCLGdCQUFnQixjQURILE1BQU07OzJGQUNuQixnQkFBZ0I7a0JBRDVCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOzswQkFxQjdCLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsZ0JBQWdCOzswQkFDbkMsTUFBTTsyQkFBQyxvQkFBb0I7OzBCQUMzQixNQUFNOzJCQUFDLHlCQUF5Qjs7MEJBRWhDLE1BQU07MkJBQUMscUJBQXFCOzswQkFDNUIsTUFBTTsyQkFBQyxnQkFBZ0I7OzBCQUN2QixNQUFNOzJCQUFDLDJCQUEyQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgT25EZXN0cm95LCBPcHRpb25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQmVoYXZpb3JTdWJqZWN0LFxuICBjYXRjaEVycm9yLFxuICBjb21iaW5lTGF0ZXN0LFxuICBFTVBUWSxcbiAgZm9ya0pvaW4sXG4gIGZyb20sXG4gIG1hcCxcbiAgT2JzZXJ2YWJsZSxcbiAgb2YsXG4gIHJldHJ5LFxuICBzaGFyZVJlcGxheSxcbiAgU3ViamVjdCxcbiAgU3Vic2NyaXB0aW9uLFxuICBzd2l0Y2hNYXAsXG4gIHRhcCxcbn0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7XG4gIERlZmF1bHRMb2FkZXIsXG4gIFRSQU5TTE9DT19MT0FERVIsXG4gIFRyYW5zbG9jb0xvYWRlcixcbn0gZnJvbSAnLi90cmFuc2xvY28ubG9hZGVyJztcbmltcG9ydCB7XG4gIFRSQU5TTE9DT19UUkFOU1BJTEVSLFxuICBUcmFuc2xvY29UcmFuc3BpbGVyLFxufSBmcm9tICcuL3RyYW5zbG9jby50cmFuc3BpbGVyJztcbmltcG9ydCB7XG4gIEF2YWlsYWJsZUxhbmdzLFxuICBIYXNoTWFwLFxuICBJbmxpbmVMb2FkZXIsXG4gIExhbmdEZWZpbml0aW9uLFxuICBMb2FkT3B0aW9ucyxcbiAgU2V0VHJhbnNsYXRpb25PcHRpb25zLFxuICBUcmFuc2xhdGVPYmplY3RQYXJhbXMsXG4gIFRyYW5zbGF0ZVBhcmFtcyxcbiAgVHJhbnNsYXRpb24sXG4gIFRyYW5zbG9jb0V2ZW50cyxcbiAgVHJhbnNsb2NvU2NvcGUsXG59IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHtcbiAgZmxhdHRlbixcbiAgaXNFbXB0eSxcbiAgaXNOaWwsXG4gIGlzU2NvcGVBcnJheSxcbiAgaXNTY29wZU9iamVjdCxcbiAgaXNTdHJpbmcsXG4gIHNpemUsXG4gIHRvQ2FtZWxDYXNlLFxuICB1bmZsYXR0ZW4sXG59IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQgeyBUUkFOU0xPQ09fQ09ORklHLCBUcmFuc2xvY29Db25maWcgfSBmcm9tICcuL3RyYW5zbG9jby5jb25maWcnO1xuaW1wb3J0IHtcbiAgVFJBTlNMT0NPX01JU1NJTkdfSEFORExFUixcbiAgVHJhbnNsb2NvTWlzc2luZ0hhbmRsZXIsXG4gIFRyYW5zbG9jb01pc3NpbmdIYW5kbGVyRGF0YSxcbn0gZnJvbSAnLi90cmFuc2xvY28tbWlzc2luZy1oYW5kbGVyJztcbmltcG9ydCB7XG4gIFRSQU5TTE9DT19JTlRFUkNFUFRPUixcbiAgVHJhbnNsb2NvSW50ZXJjZXB0b3IsXG59IGZyb20gJy4vdHJhbnNsb2NvLmludGVyY2VwdG9yJztcbmltcG9ydCB7XG4gIFRSQU5TTE9DT19GQUxMQkFDS19TVFJBVEVHWSxcbiAgVHJhbnNsb2NvRmFsbGJhY2tTdHJhdGVneSxcbn0gZnJvbSAnLi90cmFuc2xvY28tZmFsbGJhY2stc3RyYXRlZ3knO1xuaW1wb3J0IHtcbiAgZ2V0RXZlbnRQYXlsb2FkLFxuICBnZXRMYW5nRnJvbVNjb3BlLFxuICBnZXRTY29wZUZyb21MYW5nLFxuICByZXNvbHZlSW5saW5lTG9hZGVyLFxufSBmcm9tICcuL3NoYXJlZCc7XG5pbXBvcnQgeyBnZXRGYWxsYmFja3NMb2FkZXJzIH0gZnJvbSAnLi9nZXQtZmFsbGJhY2tzLWxvYWRlcnMnO1xuaW1wb3J0IHsgcmVzb2x2ZUxvYWRlciB9IGZyb20gJy4vcmVzb2x2ZS1sb2FkZXInO1xuXG5sZXQgc2VydmljZTogVHJhbnNsb2NvU2VydmljZTtcblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zbGF0ZTxUID0gc3RyaW5nPihcbiAga2V5OiBUcmFuc2xhdGVQYXJhbXMsXG4gIHBhcmFtczogSGFzaE1hcCA9IHt9LFxuICBsYW5nPzogc3RyaW5nXG4pOiBUIHtcbiAgcmV0dXJuIHNlcnZpY2UudHJhbnNsYXRlPFQ+KGtleSwgcGFyYW1zLCBsYW5nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zbGF0ZU9iamVjdDxUPihcbiAga2V5OiBUcmFuc2xhdGVQYXJhbXMsXG4gIHBhcmFtczogSGFzaE1hcCA9IHt9LFxuICBsYW5nPzogc3RyaW5nXG4pOiBUIHwgVFtdIHtcbiAgcmV0dXJuIHNlcnZpY2UudHJhbnNsYXRlT2JqZWN0PFQ+KGtleSwgcGFyYW1zLCBsYW5nKTtcbn1cblxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBUcmFuc2xvY29TZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgbGFuZ0NoYW5nZXMkOiBPYnNlcnZhYmxlPHN0cmluZz47XG5cbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHRyYW5zbGF0aW9ucyA9IG5ldyBNYXA8c3RyaW5nLCBUcmFuc2xhdGlvbj4oKTtcbiAgcHJpdmF0ZSBjYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBPYnNlcnZhYmxlPFRyYW5zbGF0aW9uPj4oKTtcbiAgcHJpdmF0ZSBmaXJzdEZhbGxiYWNrTGFuZzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIGRlZmF1bHRMYW5nID0gJyc7XG4gIHByaXZhdGUgYXZhaWxhYmxlTGFuZ3M6IEF2YWlsYWJsZUxhbmdzID0gW107XG4gIHByaXZhdGUgaXNSZXNvbHZlZE1pc3NpbmdPbmNlID0gZmFsc2U7XG4gIHByaXZhdGUgbGFuZzogQmVoYXZpb3JTdWJqZWN0PHN0cmluZz47XG4gIHByaXZhdGUgZmFpbGVkTGFuZ3MgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgcHJpdmF0ZSBldmVudHMgPSBuZXcgU3ViamVjdDxUcmFuc2xvY29FdmVudHM+KCk7XG5cbiAgZXZlbnRzJCA9IHRoaXMuZXZlbnRzLmFzT2JzZXJ2YWJsZSgpO1xuICByZWFkb25seSBjb25maWc6IFRyYW5zbG9jb0NvbmZpZyAmIHtcbiAgICBzY29wZU1hcHBpbmc/OiBIYXNoTWFwPHN0cmluZz47XG4gIH07XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChUUkFOU0xPQ09fTE9BREVSKSBwcml2YXRlIGxvYWRlcjogVHJhbnNsb2NvTG9hZGVyLFxuICAgIEBJbmplY3QoVFJBTlNMT0NPX1RSQU5TUElMRVIpIHByaXZhdGUgcGFyc2VyOiBUcmFuc2xvY29UcmFuc3BpbGVyLFxuICAgIEBJbmplY3QoVFJBTlNMT0NPX01JU1NJTkdfSEFORExFUilcbiAgICBwcml2YXRlIG1pc3NpbmdIYW5kbGVyOiBUcmFuc2xvY29NaXNzaW5nSGFuZGxlcixcbiAgICBASW5qZWN0KFRSQU5TTE9DT19JTlRFUkNFUFRPUikgcHJpdmF0ZSBpbnRlcmNlcHRvcjogVHJhbnNsb2NvSW50ZXJjZXB0b3IsXG4gICAgQEluamVjdChUUkFOU0xPQ09fQ09ORklHKSB1c2VyQ29uZmlnOiBUcmFuc2xvY29Db25maWcsXG4gICAgQEluamVjdChUUkFOU0xPQ09fRkFMTEJBQ0tfU1RSQVRFR1kpXG4gICAgcHJpdmF0ZSBmYWxsYmFja1N0cmF0ZWd5OiBUcmFuc2xvY29GYWxsYmFja1N0cmF0ZWd5XG4gICkge1xuICAgIGlmICghdGhpcy5sb2FkZXIpIHtcbiAgICAgIHRoaXMubG9hZGVyID0gbmV3IERlZmF1bHRMb2FkZXIodGhpcy50cmFuc2xhdGlvbnMpO1xuICAgIH1cbiAgICBzZXJ2aWNlID0gdGhpcztcbiAgICB0aGlzLmNvbmZpZyA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodXNlckNvbmZpZykpO1xuXG4gICAgdGhpcy5zZXRBdmFpbGFibGVMYW5ncyh0aGlzLmNvbmZpZy5hdmFpbGFibGVMYW5ncyB8fCBbXSk7XG4gICAgdGhpcy5zZXRGYWxsYmFja0xhbmdGb3JNaXNzaW5nVHJhbnNsYXRpb24odGhpcy5jb25maWcpO1xuICAgIHRoaXMuc2V0RGVmYXVsdExhbmcodGhpcy5jb25maWcuZGVmYXVsdExhbmcpO1xuICAgIHRoaXMubGFuZyA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nPih0aGlzLmdldERlZmF1bHRMYW5nKCkpO1xuICAgIC8vIERvbid0IHVzZSBkaXN0aW5jdFVudGlsQ2hhbmdlZCBhcyB3ZSBuZWVkIHRoZSBhYmlsaXR5IHRvIHVwZGF0ZVxuICAgIC8vIHRoZSB2YWx1ZSB3aGVuIHVzaW5nIHNldFRyYW5zbGF0aW9uIG9yIHNldFRyYW5zbGF0aW9uS2V5c1xuICAgIHRoaXMubGFuZ0NoYW5nZXMkID0gdGhpcy5sYW5nLmFzT2JzZXJ2YWJsZSgpO1xuXG4gICAgLyoqXG4gICAgICogV2hlbiB3ZSBoYXZlIGEgZmFpbHVyZSwgd2Ugd2FudCB0byBkZWZpbmUgdGhlIG5leHQgbGFuZ3VhZ2UgdGhhdCBzdWNjZWVkZWQgYXMgdGhlIGFjdGl2ZVxuICAgICAqL1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uID0gdGhpcy5ldmVudHMkLnN1YnNjcmliZSgoZSkgPT4ge1xuICAgICAgaWYgKGUudHlwZSA9PT0gJ3RyYW5zbGF0aW9uTG9hZFN1Y2Nlc3MnICYmIGUud2FzRmFpbHVyZSkge1xuICAgICAgICB0aGlzLnNldEFjdGl2ZUxhbmcoZS5wYXlsb2FkLmxhbmdOYW1lKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGdldERlZmF1bHRMYW5nKCkge1xuICAgIHJldHVybiB0aGlzLmRlZmF1bHRMYW5nO1xuICB9XG5cbiAgc2V0RGVmYXVsdExhbmcobGFuZzogc3RyaW5nKSB7XG4gICAgdGhpcy5kZWZhdWx0TGFuZyA9IGxhbmc7XG4gIH1cblxuICBnZXRBY3RpdmVMYW5nKCkge1xuICAgIHJldHVybiB0aGlzLmxhbmcuZ2V0VmFsdWUoKTtcbiAgfVxuXG4gIHNldEFjdGl2ZUxhbmcobGFuZzogc3RyaW5nKSB7XG4gICAgdGhpcy5wYXJzZXIub25MYW5nQ2hhbmdlZD8uKGxhbmcpO1xuICAgIHRoaXMubGFuZy5uZXh0KGxhbmcpO1xuICAgIHRoaXMuZXZlbnRzLm5leHQoe1xuICAgICAgdHlwZTogJ2xhbmdDaGFuZ2VkJyxcbiAgICAgIHBheWxvYWQ6IGdldEV2ZW50UGF5bG9hZChsYW5nKSxcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldEF2YWlsYWJsZUxhbmdzKGxhbmdzOiBBdmFpbGFibGVMYW5ncykge1xuICAgIHRoaXMuYXZhaWxhYmxlTGFuZ3MgPSBsYW5ncztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBhdmFpbGFibGUgbGFuZ3VhZ2VzLlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKiBBbiBhcnJheSBvZiB0aGUgYXZhaWxhYmxlIGxhbmd1YWdlcy4gQ2FuIGJlIGVpdGhlciBhIGBzdHJpbmdbXWAgb3IgYSBgeyBpZDogc3RyaW5nOyBsYWJlbDogc3RyaW5nIH1bXWBcbiAgICogZGVwZW5kaW5nIG9uIGhvdyB0aGUgYXZhaWxhYmxlIGxhbmd1YWdlcyBhcmUgc2V0IGluIHlvdXIgbW9kdWxlLlxuICAgKi9cbiAgZ2V0QXZhaWxhYmxlTGFuZ3MoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXZhaWxhYmxlTGFuZ3M7XG4gIH1cblxuICBsb2FkKHBhdGg6IHN0cmluZywgb3B0aW9uczogTG9hZE9wdGlvbnMgPSB7fSk6IE9ic2VydmFibGU8VHJhbnNsYXRpb24+IHtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLmNhY2hlLmdldChwYXRoKTtcbiAgICBpZiAoY2FjaGVkKSB7XG4gICAgICByZXR1cm4gY2FjaGVkO1xuICAgIH1cblxuICAgIGxldCBsb2FkVHJhbnNsYXRpb246IE9ic2VydmFibGU8XG4gICAgICBUcmFuc2xhdGlvbiB8IHsgdHJhbnNsYXRpb246IFRyYW5zbGF0aW9uOyBsYW5nOiBzdHJpbmcgfVtdXG4gICAgPjtcbiAgICBjb25zdCBpc1Njb3BlID0gdGhpcy5faXNMYW5nU2NvcGVkKHBhdGgpO1xuICAgIGxldCBzY29wZTogc3RyaW5nO1xuICAgIGlmIChpc1Njb3BlKSB7XG4gICAgICBzY29wZSA9IGdldFNjb3BlRnJvbUxhbmcocGF0aCk7XG4gICAgfVxuXG4gICAgY29uc3QgbG9hZGVyc09wdGlvbnMgPSB7XG4gICAgICBwYXRoLFxuICAgICAgbWFpbkxvYWRlcjogdGhpcy5sb2FkZXIsXG4gICAgICBpbmxpbmVMb2FkZXI6IG9wdGlvbnMuaW5saW5lTG9hZGVyLFxuICAgICAgZGF0YTogaXNTY29wZSA/IHsgc2NvcGU6IHNjb3BlISB9IDogdW5kZWZpbmVkLFxuICAgIH07XG5cbiAgICBpZiAodGhpcy51c2VGYWxsYmFja1RyYW5zbGF0aW9uKHBhdGgpKSB7XG4gICAgICAvLyBpZiB0aGUgcGF0aCBpcyBzY29wZSB0aGUgZmFsbGJhY2sgc2hvdWxkIGJlIGBzY29wZS9mYWxsYmFja0xhbmdgO1xuICAgICAgY29uc3QgZmFsbGJhY2sgPSBpc1Njb3BlXG4gICAgICAgID8gYCR7c2NvcGUhfS8ke3RoaXMuZmlyc3RGYWxsYmFja0xhbmd9YFxuICAgICAgICA6IHRoaXMuZmlyc3RGYWxsYmFja0xhbmc7XG5cbiAgICAgIGNvbnN0IGxvYWRlcnMgPSBnZXRGYWxsYmFja3NMb2FkZXJzKHtcbiAgICAgICAgLi4ubG9hZGVyc09wdGlvbnMsXG4gICAgICAgIGZhbGxiYWNrUGF0aDogZmFsbGJhY2shLFxuICAgICAgfSk7XG4gICAgICBsb2FkVHJhbnNsYXRpb24gPSBmb3JrSm9pbihsb2FkZXJzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgbG9hZGVyID0gcmVzb2x2ZUxvYWRlcihsb2FkZXJzT3B0aW9ucyk7XG4gICAgICBsb2FkVHJhbnNsYXRpb24gPSBmcm9tKGxvYWRlcik7XG4gICAgfVxuXG4gICAgY29uc3QgbG9hZCQgPSBsb2FkVHJhbnNsYXRpb24ucGlwZShcbiAgICAgIHJldHJ5KHRoaXMuY29uZmlnLmZhaWxlZFJldHJpZXMpLFxuICAgICAgdGFwKCh0cmFuc2xhdGlvbikgPT4ge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh0cmFuc2xhdGlvbikpIHtcbiAgICAgICAgICB0cmFuc2xhdGlvbi5mb3JFYWNoKCh0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVN1Y2Nlc3ModC5sYW5nLCB0LnRyYW5zbGF0aW9uKTtcbiAgICAgICAgICAgIC8vIFNhdmUgdGhlIGZhbGxiYWNrIGluIGNhY2hlIHNvIHdlJ2xsIG5vdCBjcmVhdGUgYSByZWR1bmRhbnQgcmVxdWVzdFxuICAgICAgICAgICAgaWYgKHQubGFuZyAhPT0gcGF0aCkge1xuICAgICAgICAgICAgICB0aGlzLmNhY2hlLnNldCh0LmxhbmcsIG9mKHt9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaGFuZGxlU3VjY2VzcyhwYXRoLCB0cmFuc2xhdGlvbik7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoKGVycm9yKSA9PiB7XG4gICAgICAgIGlmICghdGhpcy5jb25maWcucHJvZE1vZGUpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciB3aGlsZSB0cnlpbmcgdG8gbG9hZCBcIiR7cGF0aH1cImAsIGVycm9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmhhbmRsZUZhaWx1cmUocGF0aCwgb3B0aW9ucyk7XG4gICAgICB9KSxcbiAgICAgIHNoYXJlUmVwbGF5KDEpXG4gICAgKTtcblxuICAgIHRoaXMuY2FjaGUuc2V0KHBhdGgsIGxvYWQkKTtcblxuICAgIHJldHVybiBsb2FkJDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBpbnN0YW50IHRyYW5zbGF0ZWQgdmFsdWUgb2YgYSBrZXlcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogdHJhbnNsYXRlPHN0cmluZz4oJ2hlbGxvJylcbiAgICogdHJhbnNsYXRlKCdoZWxsbycsIHsgdmFsdWU6ICd2YWx1ZScgfSlcbiAgICogdHJhbnNsYXRlPHN0cmluZ1tdPihbJ2hlbGxvJywgJ2tleSddKVxuICAgKiB0cmFuc2xhdGUoJ2hlbGxvJywgeyB9LCAnZW4nKVxuICAgKiB0cmFuc2xhdGUoJ3Njb3BlLnNvbWVLZXknLCB7IH0sICdlbicpXG4gICAqL1xuICB0cmFuc2xhdGU8VCA9IHN0cmluZz4oXG4gICAga2V5OiBUcmFuc2xhdGVQYXJhbXMsXG4gICAgcGFyYW1zOiBIYXNoTWFwID0ge30sXG4gICAgbGFuZyA9IHRoaXMuZ2V0QWN0aXZlTGFuZygpXG4gICk6IFQge1xuICAgIGlmICgha2V5KSByZXR1cm4ga2V5IGFzIGFueTtcblxuICAgIGNvbnN0IHsgc2NvcGUsIHJlc29sdmVMYW5nIH0gPSB0aGlzLnJlc29sdmVMYW5nQW5kU2NvcGUobGFuZyk7XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShrZXkpKSB7XG4gICAgICByZXR1cm4ga2V5Lm1hcCgoaykgPT5cbiAgICAgICAgdGhpcy50cmFuc2xhdGUoc2NvcGUgPyBgJHtzY29wZX0uJHtrfWAgOiBrLCBwYXJhbXMsIHJlc29sdmVMYW5nKVxuICAgICAgKSBhcyBhbnk7XG4gICAgfVxuXG4gICAga2V5ID0gc2NvcGUgPyBgJHtzY29wZX0uJHtrZXl9YCA6IGtleTtcblxuICAgIGNvbnN0IHRyYW5zbGF0aW9uID0gdGhpcy5nZXRUcmFuc2xhdGlvbihyZXNvbHZlTGFuZyk7XG4gICAgY29uc3QgdmFsdWUgPSB0cmFuc2xhdGlvbltrZXldO1xuXG4gICAgaWYgKCF2YWx1ZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2hhbmRsZU1pc3NpbmdLZXkoa2V5LCB2YWx1ZSwgcGFyYW1zKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5wYXJzZXIudHJhbnNwaWxlKHtcbiAgICAgIHZhbHVlLCBwYXJhbXMsIHRyYW5zbGF0aW9uLCBrZXlcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSB0cmFuc2xhdGVkIHZhbHVlIG9mIGEga2V5IGFzIG9ic2VydmFibGVcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogc2VsZWN0VHJhbnNsYXRlPHN0cmluZz4oJ2hlbGxvJykuc3Vic2NyaWJlKHZhbHVlID0+IC4uLilcbiAgICogc2VsZWN0VHJhbnNsYXRlPHN0cmluZz4oJ2hlbGxvJywge30sICdlcycpLnN1YnNjcmliZSh2YWx1ZSA9PiAuLi4pXG4gICAqIHNlbGVjdFRyYW5zbGF0ZTxzdHJpbmc+KCdoZWxsbycsIHt9LCAndG9kb3MnKS5zdWJzY3JpYmUodmFsdWUgPT4gLi4uKVxuICAgKiBzZWxlY3RUcmFuc2xhdGU8c3RyaW5nPignaGVsbG8nLCB7fSwgeyBzY29wZTogJ3RvZG9zJyB9KS5zdWJzY3JpYmUodmFsdWUgPT4gLi4uKVxuICAgKlxuICAgKi9cbiAgc2VsZWN0VHJhbnNsYXRlPFQgPSBhbnk+KFxuICAgIGtleTogVHJhbnNsYXRlUGFyYW1zLFxuICAgIHBhcmFtcz86IEhhc2hNYXAsXG4gICAgbGFuZz86IHN0cmluZyB8IFRyYW5zbG9jb1Njb3BlIHwgVHJhbnNsb2NvU2NvcGVbXSxcbiAgICBfaXNPYmplY3QgPSBmYWxzZVxuICApOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICBsZXQgaW5saW5lTG9hZGVyOiBJbmxpbmVMb2FkZXIgfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgbG9hZCA9IChsYW5nOiBzdHJpbmcsIG9wdGlvbnM/OiBMb2FkT3B0aW9ucykgPT5cbiAgICAgIHRoaXMubG9hZChsYW5nLCBvcHRpb25zKS5waXBlKFxuICAgICAgICBtYXAoKCkgPT5cbiAgICAgICAgICBfaXNPYmplY3RcbiAgICAgICAgICAgID8gdGhpcy50cmFuc2xhdGVPYmplY3Qoa2V5LCBwYXJhbXMsIGxhbmcpXG4gICAgICAgICAgICA6IHRoaXMudHJhbnNsYXRlKGtleSwgcGFyYW1zLCBsYW5nKVxuICAgICAgICApXG4gICAgICApO1xuICAgIGlmIChpc05pbChsYW5nKSkge1xuICAgICAgcmV0dXJuIHRoaXMubGFuZ0NoYW5nZXMkLnBpcGUoc3dpdGNoTWFwKChsYW5nKSA9PiBsb2FkKGxhbmcpKSk7XG4gICAgfVxuXG4gICAgaWYgKGlzU2NvcGVBcnJheShsYW5nKSB8fCBpc1Njb3BlT2JqZWN0KGxhbmcpKSB7XG4gICAgICAvLyBpdCdzIGEgc2NvcGUgb2JqZWN0LlxuICAgICAgY29uc3QgcHJvdmlkZXJTY29wZSA9IEFycmF5LmlzQXJyYXkobGFuZykgPyBsYW5nWzBdIDogbGFuZztcbiAgICAgIGxhbmcgPSBwcm92aWRlclNjb3BlLnNjb3BlO1xuICAgICAgaW5saW5lTG9hZGVyID0gcmVzb2x2ZUlubGluZUxvYWRlcihwcm92aWRlclNjb3BlLCBwcm92aWRlclNjb3BlLnNjb3BlKTtcbiAgICB9XG5cbiAgICBsYW5nID0gbGFuZyBhcyBzdHJpbmc7XG4gICAgaWYgKHRoaXMuaXNMYW5nKGxhbmcpIHx8IHRoaXMuaXNTY29wZVdpdGhMYW5nKGxhbmcpKSB7XG4gICAgICByZXR1cm4gbG9hZChsYW5nKTtcbiAgICB9XG4gICAgLy8gaXQncyBhIHNjb3BlXG4gICAgY29uc3Qgc2NvcGUgPSBsYW5nO1xuICAgIHJldHVybiB0aGlzLmxhbmdDaGFuZ2VzJC5waXBlKFxuICAgICAgc3dpdGNoTWFwKChsYW5nKSA9PiBsb2FkKGAke3Njb3BlfS8ke2xhbmd9YCwgeyBpbmxpbmVMb2FkZXIgfSkpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBzY29wZSB3aXRoIGxhbmdcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogdG9kb3MvZW4gPT4gdHJ1ZVxuICAgKiB0b2RvcyA9PiBmYWxzZVxuICAgKi9cbiAgcHJpdmF0ZSBpc1Njb3BlV2l0aExhbmcobGFuZzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNMYW5nKGdldExhbmdGcm9tU2NvcGUobGFuZykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zbGF0ZSB0aGUgZ2l2ZW4gcGF0aCB0aGF0IHJldHVybnMgYW4gb2JqZWN0XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIHNlcnZpY2UudHJhbnNsYXRlT2JqZWN0KCdwYXRoLnRvLm9iamVjdCcsIHsnc3VicGF0aCc6IHsgdmFsdWU6ICdzb21lVmFsdWUnfX0pID0+IHJldHVybnMgdHJhbnNsYXRlZCBvYmplY3RcbiAgICpcbiAgICovXG4gIHRyYW5zbGF0ZU9iamVjdDxUID0gYW55PihrZXk6IHN0cmluZywgcGFyYW1zPzogSGFzaE1hcCwgbGFuZz86IHN0cmluZyk6IFQ7XG4gIHRyYW5zbGF0ZU9iamVjdDxUID0gYW55PihrZXk6IHN0cmluZ1tdLCBwYXJhbXM/OiBIYXNoTWFwLCBsYW5nPzogc3RyaW5nKTogVFtdO1xuICB0cmFuc2xhdGVPYmplY3Q8VCA9IGFueT4oXG4gICAga2V5OiBUcmFuc2xhdGVQYXJhbXMsXG4gICAgcGFyYW1zPzogSGFzaE1hcCxcbiAgICBsYW5nPzogc3RyaW5nXG4gICk6IFQgfCBUW107XG4gIHRyYW5zbGF0ZU9iamVjdDxUID0gYW55PihcbiAgICBrZXk6IEhhc2hNYXAgfCBNYXA8c3RyaW5nLCBIYXNoTWFwPixcbiAgICBwYXJhbXM/OiBudWxsLFxuICAgIGxhbmc/OiBzdHJpbmdcbiAgKTogVFtdO1xuICB0cmFuc2xhdGVPYmplY3Q8VCA9IGFueT4oXG4gICAga2V5OiBUcmFuc2xhdGVPYmplY3RQYXJhbXMsXG4gICAgcGFyYW1zOiBIYXNoTWFwIHwgbnVsbCA9IHt9LFxuICAgIGxhbmcgPSB0aGlzLmdldEFjdGl2ZUxhbmcoKVxuICApOiBUIHwgVFtdIHtcbiAgICBpZiAoaXNTdHJpbmcoa2V5KSB8fCBBcnJheS5pc0FycmF5KGtleSkpIHtcbiAgICAgIGNvbnN0IHsgcmVzb2x2ZUxhbmcsIHNjb3BlIH0gPSB0aGlzLnJlc29sdmVMYW5nQW5kU2NvcGUobGFuZyk7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShrZXkpKSB7XG4gICAgICAgIHJldHVybiBrZXkubWFwKChrKSA9PlxuICAgICAgICAgIHRoaXMudHJhbnNsYXRlT2JqZWN0KFxuICAgICAgICAgICAgc2NvcGUgPyBgJHtzY29wZX0uJHtrfWAgOiBrLFxuICAgICAgICAgICAgcGFyYW1zISxcbiAgICAgICAgICAgIHJlc29sdmVMYW5nXG4gICAgICAgICAgKVxuICAgICAgICApIGFzIGFueTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdHJhbnNsYXRpb24gPSB0aGlzLmdldFRyYW5zbGF0aW9uKHJlc29sdmVMYW5nKTtcbiAgICAgIGtleSA9IHNjb3BlID8gYCR7c2NvcGV9LiR7a2V5fWAgOiBrZXk7XG5cbiAgICAgIGNvbnN0IHZhbHVlID0gdW5mbGF0dGVuKHRoaXMuZ2V0T2JqZWN0QnlLZXkodHJhbnNsYXRpb24sIGtleSkpO1xuICAgICAgLyogSWYgYW4gZW1wdHkgb2JqZWN0IHdhcyByZXR1cm5lZCB3ZSB3YW50IHRvIHRyeSBhbmQgdHJhbnNsYXRlIHRoZSBrZXkgYXMgYSBzdHJpbmcgYW5kIG5vdCBhbiBvYmplY3QgKi9cbiAgICAgIHJldHVybiBpc0VtcHR5KHZhbHVlKVxuICAgICAgICA/IHRoaXMudHJhbnNsYXRlKGtleSwgcGFyYW1zISwgbGFuZylcbiAgICAgICAgOiB0aGlzLnBhcnNlci50cmFuc3BpbGUoe3ZhbHVlLCBwYXJhbXM6IHBhcmFtcyEsIHRyYW5zbGF0aW9uLCBrZXl9KTtcbiAgICB9XG5cbiAgICBjb25zdCB0cmFuc2xhdGlvbnM6IFRbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgW19rZXksIF9wYXJhbXNdIG9mIHRoaXMuZ2V0RW50cmllcyhrZXkpKSB7XG4gICAgICB0cmFuc2xhdGlvbnMucHVzaCh0aGlzLnRyYW5zbGF0ZU9iamVjdChfa2V5LCBfcGFyYW1zLCBsYW5nKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyYW5zbGF0aW9ucztcbiAgfVxuXG4gIHNlbGVjdFRyYW5zbGF0ZU9iamVjdDxUID0gYW55PihcbiAgICBrZXk6IHN0cmluZyxcbiAgICBwYXJhbXM/OiBIYXNoTWFwLFxuICAgIGxhbmc/OiBzdHJpbmdcbiAgKTogT2JzZXJ2YWJsZTxUPjtcbiAgc2VsZWN0VHJhbnNsYXRlT2JqZWN0PFQgPSBhbnk+KFxuICAgIGtleTogc3RyaW5nW10sXG4gICAgcGFyYW1zPzogSGFzaE1hcCxcbiAgICBsYW5nPzogc3RyaW5nXG4gICk6IE9ic2VydmFibGU8VFtdPjtcbiAgc2VsZWN0VHJhbnNsYXRlT2JqZWN0PFQgPSBhbnk+KFxuICAgIGtleTogVHJhbnNsYXRlUGFyYW1zLFxuICAgIHBhcmFtcz86IEhhc2hNYXAsXG4gICAgbGFuZz86IHN0cmluZ1xuICApOiBPYnNlcnZhYmxlPFQ+IHwgT2JzZXJ2YWJsZTxUW10+O1xuICBzZWxlY3RUcmFuc2xhdGVPYmplY3Q8VCA9IGFueT4oXG4gICAga2V5OiBIYXNoTWFwIHwgTWFwPHN0cmluZywgSGFzaE1hcD4sXG4gICAgcGFyYW1zPzogbnVsbCxcbiAgICBsYW5nPzogc3RyaW5nXG4gICk6IE9ic2VydmFibGU8VFtdPjtcbiAgc2VsZWN0VHJhbnNsYXRlT2JqZWN0PFQgPSBhbnk+KFxuICAgIGtleTogVHJhbnNsYXRlT2JqZWN0UGFyYW1zLFxuICAgIHBhcmFtcz86IEhhc2hNYXAgfCBudWxsLFxuICAgIGxhbmc/OiBzdHJpbmdcbiAgKTogT2JzZXJ2YWJsZTxUPiB8IE9ic2VydmFibGU8VFtdPiB7XG4gICAgaWYgKGlzU3RyaW5nKGtleSkgfHwgQXJyYXkuaXNBcnJheShrZXkpKSB7XG4gICAgICByZXR1cm4gdGhpcy5zZWxlY3RUcmFuc2xhdGU8VD4oa2V5LCBwYXJhbXMhLCBsYW5nLCB0cnVlKTtcbiAgICB9XG5cbiAgICBjb25zdCBbW2ZpcnN0S2V5LCBmaXJzdFBhcmFtc10sIC4uLnJlc3RdID0gdGhpcy5nZXRFbnRyaWVzKGtleSk7XG5cbiAgICAvKiBJbiBvcmRlciB0byBhdm9pZCBzdWJzY3JpYmluZyBtdWx0aXBsZSB0aW1lcyB0byB0aGUgbG9hZCBsYW5ndWFnZSBldmVudCBieSBjYWxsaW5nIHNlbGVjdFRyYW5zbGF0ZU9iamVjdCBmb3IgZWFjaCBwYWlyLFxuICAgICAqIHdlIGxpc3RlbiB0byB3aGVuIHRoZSBmaXJzdCBrZXkgaGFzIGJlZW4gdHJhbnNsYXRlZCAodGhlIGxhbmd1YWdlIGlzIGxvYWRlZCkgYW5kIHRyYW5zbGF0ZSB0aGUgcmVzdCBzeW5jaHJvbm91c2x5ICovXG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0VHJhbnNsYXRlT2JqZWN0PFQ+KGZpcnN0S2V5LCBmaXJzdFBhcmFtcywgbGFuZykucGlwZShcbiAgICAgIG1hcCgodmFsdWUpID0+IHtcbiAgICAgICAgY29uc3QgdHJhbnNsYXRpb25zID0gW3ZhbHVlXTtcbiAgICAgICAgZm9yIChjb25zdCBbX2tleSwgX3BhcmFtc10gb2YgcmVzdCkge1xuICAgICAgICAgIHRyYW5zbGF0aW9ucy5wdXNoKHRoaXMudHJhbnNsYXRlT2JqZWN0PFQ+KF9rZXksIF9wYXJhbXMsIGxhbmcpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cmFuc2xhdGlvbnM7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBhbiBvYmplY3Qgb2YgdHJhbnNsYXRpb25zIGZvciBhIGdpdmVuIGxhbmd1YWdlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIGdldFRyYW5zbGF0aW9uKClcbiAgICogZ2V0VHJhbnNsYXRpb24oJ2VuJylcbiAgICogZ2V0VHJhbnNsYXRpb24oJ2FkbWluLXBhZ2UvZW4nKVxuICAgKi9cbiAgZ2V0VHJhbnNsYXRpb24oKTogTWFwPHN0cmluZywgVHJhbnNsYXRpb24+O1xuICBnZXRUcmFuc2xhdGlvbihsYW5nT3JTY29wZTogc3RyaW5nKTogVHJhbnNsYXRpb247XG4gIGdldFRyYW5zbGF0aW9uKGxhbmdPclNjb3BlPzogc3RyaW5nKTogTWFwPHN0cmluZywgVHJhbnNsYXRpb24+IHwgVHJhbnNsYXRpb24ge1xuICAgIGlmIChsYW5nT3JTY29wZSkge1xuICAgICAgaWYgKHRoaXMuaXNMYW5nKGxhbmdPclNjb3BlKSkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGlvbnMuZ2V0KGxhbmdPclNjb3BlKSB8fCB7fTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRoaXMgaXMgYSBzY29wZSwgYnVpbGQgdGhlIHNjb3BlIHZhbHVlIGZyb20gdGhlIHRyYW5zbGF0aW9uIG9iamVjdFxuICAgICAgICBjb25zdCB7IHNjb3BlLCByZXNvbHZlTGFuZyB9ID0gdGhpcy5yZXNvbHZlTGFuZ0FuZFNjb3BlKGxhbmdPclNjb3BlKTtcbiAgICAgICAgY29uc3QgdHJhbnNsYXRpb24gPSB0aGlzLnRyYW5zbGF0aW9ucy5nZXQocmVzb2x2ZUxhbmcpIHx8IHt9O1xuXG4gICAgICAgIHJldHVybiB0aGlzLmdldE9iamVjdEJ5S2V5KHRyYW5zbGF0aW9uLCBzY29wZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudHJhbnNsYXRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgYW4gb2JqZWN0IG9mIHRyYW5zbGF0aW9ucyBmb3IgYSBnaXZlbiBsYW5ndWFnZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiBzZWxlY3RUcmFuc2xhdGlvbigpLnN1YnNjcmliZSgpIC0gd2lsbCByZXR1cm4gdGhlIGN1cnJlbnQgbGFuZyB0cmFuc2xhdGlvblxuICAgKiBzZWxlY3RUcmFuc2xhdGlvbignZXMnKS5zdWJzY3JpYmUoKVxuICAgKiBzZWxlY3RUcmFuc2xhdGlvbignYWRtaW4tcGFnZScpLnN1YnNjcmliZSgpIC0gd2lsbCByZXR1cm4gdGhlIGN1cnJlbnQgbGFuZyBzY29wZSB0cmFuc2xhdGlvblxuICAgKiBzZWxlY3RUcmFuc2xhdGlvbignYWRtaW4tcGFnZS9lcycpLnN1YnNjcmliZSgpXG4gICAqL1xuICBzZWxlY3RUcmFuc2xhdGlvbihsYW5nPzogc3RyaW5nKTogT2JzZXJ2YWJsZTxUcmFuc2xhdGlvbj4ge1xuICAgIGxldCBsYW5ndWFnZSQgPSB0aGlzLmxhbmdDaGFuZ2VzJDtcbiAgICBpZiAobGFuZykge1xuICAgICAgY29uc3Qgc2NvcGVMYW5nU3BlY2lmaWVkID0gZ2V0TGFuZ0Zyb21TY29wZShsYW5nKSAhPT0gbGFuZztcbiAgICAgIGlmICh0aGlzLmlzTGFuZyhsYW5nKSB8fCBzY29wZUxhbmdTcGVjaWZpZWQpIHtcbiAgICAgICAgbGFuZ3VhZ2UkID0gb2YobGFuZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsYW5ndWFnZSQgPSB0aGlzLmxhbmdDaGFuZ2VzJC5waXBlKFxuICAgICAgICAgIG1hcCgoY3VycmVudExhbmcpID0+IGAke2xhbmd9LyR7Y3VycmVudExhbmd9YClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGFuZ3VhZ2UkLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKGxhbmd1YWdlKSA9PlxuICAgICAgICB0aGlzLmxvYWQobGFuZ3VhZ2UpLnBpcGUobWFwKCgpID0+IHRoaXMuZ2V0VHJhbnNsYXRpb24obGFuZ3VhZ2UpKSlcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgb3IgbWVyZ2UgYSBnaXZlbiB0cmFuc2xhdGlvbiBvYmplY3QgdG8gY3VycmVudCBsYW5nXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIHNldFRyYW5zbGF0aW9uKHsgLi4uIH0pXG4gICAqIHNldFRyYW5zbGF0aW9uKHsgLi4uIH0sICdlbicpXG4gICAqIHNldFRyYW5zbGF0aW9uKHsgLi4uIH0sICdlcycsIHsgbWVyZ2U6IGZhbHNlIH0gKVxuICAgKiBzZXRUcmFuc2xhdGlvbih7IC4uLiB9LCAndG9kb3MvZW4nLCB7IG1lcmdlOiBmYWxzZSB9IClcbiAgICovXG4gIHNldFRyYW5zbGF0aW9uKFxuICAgIHRyYW5zbGF0aW9uOiBUcmFuc2xhdGlvbixcbiAgICBsYW5nID0gdGhpcy5nZXRBY3RpdmVMYW5nKCksXG4gICAgb3B0aW9uczogU2V0VHJhbnNsYXRpb25PcHRpb25zID0ge31cbiAgKSB7XG4gICAgY29uc3QgZGVmYXVsdHMgPSB7IG1lcmdlOiB0cnVlLCBlbWl0Q2hhbmdlOiB0cnVlIH07XG4gICAgY29uc3QgbWVyZ2VkT3B0aW9ucyA9IHsgLi4uZGVmYXVsdHMsIC4uLm9wdGlvbnMgfTtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlRnJvbUxhbmcobGFuZyk7XG5cbiAgICAvKipcbiAgICAgKiBJZiB0aGlzIGlzbid0IGEgc2NvcGUgd2UgdXNlIHRoZSB3aG9sZSB0cmFuc2xhdGlvbiBhcyBpc1xuICAgICAqIG90aGVyd2lzZSB3ZSBuZWVkIHRvIGZsYXQgdGhlIHNjb3BlIGFuZCB1c2UgaXRcbiAgICAgKi9cbiAgICBsZXQgZmxhdHRlblNjb3BlT3JUcmFuc2xhdGlvbiA9IHRyYW5zbGF0aW9uO1xuXG4gICAgLy8gTWVyZ2VkIHRoZSBzY29wZWQgbGFuZ3VhZ2UgaW50byB0aGUgYWN0aXZlIGxhbmd1YWdlXG4gICAgaWYgKHNjb3BlKSB7XG4gICAgICBjb25zdCBrZXkgPSB0aGlzLmdldE1hcHBlZFNjb3BlKHNjb3BlKTtcbiAgICAgIGZsYXR0ZW5TY29wZU9yVHJhbnNsYXRpb24gPSBmbGF0dGVuKHsgW2tleV06IHRyYW5zbGF0aW9uIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRMYW5nID0gc2NvcGUgPyBnZXRMYW5nRnJvbVNjb3BlKGxhbmcpIDogbGFuZztcblxuICAgIGNvbnN0IG1lcmdlZFRyYW5zbGF0aW9uID0ge1xuICAgICAgLi4uKG1lcmdlZE9wdGlvbnMubWVyZ2UgJiYgdGhpcy5nZXRUcmFuc2xhdGlvbihjdXJyZW50TGFuZykpLFxuICAgICAgLi4uZmxhdHRlblNjb3BlT3JUcmFuc2xhdGlvbixcbiAgICB9O1xuXG4gICAgY29uc3QgZmxhdHRlblRyYW5zbGF0aW9uID0gdGhpcy5jb25maWcuZmxhdHRlbiEuYW90XG4gICAgICA/IG1lcmdlZFRyYW5zbGF0aW9uXG4gICAgICA6IGZsYXR0ZW4obWVyZ2VkVHJhbnNsYXRpb24pO1xuICAgIGNvbnN0IHdpdGhIb29rID0gdGhpcy5pbnRlcmNlcHRvci5wcmVTYXZlVHJhbnNsYXRpb24oXG4gICAgICBmbGF0dGVuVHJhbnNsYXRpb24sXG4gICAgICBjdXJyZW50TGFuZ1xuICAgICk7XG4gICAgdGhpcy50cmFuc2xhdGlvbnMuc2V0KGN1cnJlbnRMYW5nLCB3aXRoSG9vayk7XG4gICAgbWVyZ2VkT3B0aW9ucy5lbWl0Q2hhbmdlICYmIHRoaXMuc2V0QWN0aXZlTGFuZyh0aGlzLmdldEFjdGl2ZUxhbmcoKSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0cmFuc2xhdGlvbiBrZXkgd2l0aCBnaXZlbiB2YWx1ZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiBzZXRUcmFuc2xhdGlvbktleSgna2V5JywgJ3ZhbHVlJylcbiAgICogc2V0VHJhbnNsYXRpb25LZXkoJ2tleS5uZXN0ZWQnLCAndmFsdWUnKVxuICAgKiBzZXRUcmFuc2xhdGlvbktleSgna2V5Lm5lc3RlZCcsICd2YWx1ZScsICdlbicpXG4gICAqIHNldFRyYW5zbGF0aW9uS2V5KCdrZXkubmVzdGVkJywgJ3ZhbHVlJywgJ2VuJywgeyBlbWl0Q2hhbmdlOiBmYWxzZSB9IClcbiAgICovXG4gIHNldFRyYW5zbGF0aW9uS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBzdHJpbmcsXG4gICAgb3B0aW9uczogT21pdDxTZXRUcmFuc2xhdGlvbk9wdGlvbnMsICdtZXJnZSc+ID0ge31cbiAgKSB7XG4gICAgY29uc3QgbGFuZyA9IG9wdGlvbnMubGFuZyB8fCB0aGlzLmdldEFjdGl2ZUxhbmcoKTtcbiAgICBjb25zdCB3aXRoSG9vayA9IHRoaXMuaW50ZXJjZXB0b3IucHJlU2F2ZVRyYW5zbGF0aW9uS2V5KGtleSwgdmFsdWUsIGxhbmcpO1xuICAgIGNvbnN0IG5ld1ZhbHVlID0ge1xuICAgICAgW2tleV06IHdpdGhIb29rLFxuICAgIH07XG5cbiAgICB0aGlzLnNldFRyYW5zbGF0aW9uKG5ld1ZhbHVlLCBsYW5nLCB7IC4uLm9wdGlvbnMsIG1lcmdlOiB0cnVlIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGZhbGxiYWNrIGxhbmcgZm9yIHRoZSBjdXJyZW50bHkgYWN0aXZlIGxhbmd1YWdlXG4gICAqIEBwYXJhbSBmYWxsYmFja0xhbmdcbiAgICovXG4gIHNldEZhbGxiYWNrTGFuZ0Zvck1pc3NpbmdUcmFuc2xhdGlvbih7XG4gICAgZmFsbGJhY2tMYW5nLFxuICB9OiBQaWNrPFRyYW5zbG9jb0NvbmZpZywgJ2ZhbGxiYWNrTGFuZyc+KSB7XG4gICAgY29uc3QgbGFuZyA9IEFycmF5LmlzQXJyYXkoZmFsbGJhY2tMYW5nKSA/IGZhbGxiYWNrTGFuZ1swXSA6IGZhbGxiYWNrTGFuZztcbiAgICBpZiAoZmFsbGJhY2tMYW5nICYmIHRoaXMudXNlRmFsbGJhY2tUcmFuc2xhdGlvbihsYW5nKSkge1xuICAgICAgdGhpcy5maXJzdEZhbGxiYWNrTGFuZyA9IGxhbmchO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIF9oYW5kbGVNaXNzaW5nS2V5KGtleTogc3RyaW5nLCB2YWx1ZTogYW55LCBwYXJhbXM/OiBIYXNoTWFwKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLm1pc3NpbmdIYW5kbGVyIS5hbGxvd0VtcHR5ICYmIHZhbHVlID09PSAnJykge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5pc1Jlc29sdmVkTWlzc2luZ09uY2UgJiYgdGhpcy51c2VGYWxsYmFja1RyYW5zbGF0aW9uKCkpIHtcbiAgICAgIC8vIFdlIG5lZWQgdG8gc2V0IGl0IHRvIHRydWUgdG8gcHJldmVudCBhIGxvb3BcbiAgICAgIHRoaXMuaXNSZXNvbHZlZE1pc3NpbmdPbmNlID0gdHJ1ZTtcbiAgICAgIGNvbnN0IGZhbGxiYWNrVmFsdWUgPSB0aGlzLnRyYW5zbGF0ZShcbiAgICAgICAga2V5LFxuICAgICAgICBwYXJhbXMsXG4gICAgICAgIHRoaXMuZmlyc3RGYWxsYmFja0xhbmchXG4gICAgICApO1xuICAgICAgdGhpcy5pc1Jlc29sdmVkTWlzc2luZ09uY2UgPSBmYWxzZTtcblxuICAgICAgcmV0dXJuIGZhbGxiYWNrVmFsdWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMubWlzc2luZ0hhbmRsZXIuaGFuZGxlKFxuICAgICAga2V5LFxuICAgICAgdGhpcy5nZXRNaXNzaW5nSGFuZGxlckRhdGEoKSxcbiAgICAgIHBhcmFtc1xuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBfaXNMYW5nU2NvcGVkKGxhbmc6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmdldEF2YWlsYWJsZUxhbmdzSWRzKCkuaW5kZXhPZihsYW5nKSA9PT0gLTE7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgZ2l2ZW4gc3RyaW5nIGlzIG9uZSBvZiB0aGUgc3BlY2lmaWVkIGF2YWlsYWJsZSBsYW5ndWFnZXMuXG4gICAqIEByZXR1cm5zXG4gICAqIFRydWUgaWYgdGhlIGdpdmVuIHN0cmluZyBpcyBhbiBhdmFpbGFibGUgbGFuZ3VhZ2UuXG4gICAqIEZhbHNlIGlmIHRoZSBnaXZlbiBzdHJpbmcgaXMgbm90IGFuIGF2YWlsYWJsZSBsYW5ndWFnZS5cbiAgICovXG4gIGlzTGFuZyhsYW5nOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5nZXRBdmFpbGFibGVMYW5nc0lkcygpLmluZGV4T2YobGFuZykgIT09IC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKlxuICAgKiBXZSBhbHdheXMgd2FudCB0byBtYWtlIHN1cmUgdGhlIGdsb2JhbCBsYW5nIGlzIGxvYWRlZFxuICAgKiBiZWZvcmUgbG9hZGluZyB0aGUgc2NvcGUgc2luY2UgeW91IGNhbiBhY2Nlc3MgYm90aCB2aWEgdGhlIHBpcGUvZGlyZWN0aXZlLlxuICAgKi9cbiAgX2xvYWREZXBlbmRlbmNpZXMoXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIGlubGluZUxvYWRlcj86IElubGluZUxvYWRlclxuICApOiBPYnNlcnZhYmxlPFRyYW5zbGF0aW9uIHwgVHJhbnNsYXRpb25bXT4ge1xuICAgIGNvbnN0IG1haW5MYW5nID0gZ2V0TGFuZ0Zyb21TY29wZShwYXRoKTtcblxuICAgIGlmICh0aGlzLl9pc0xhbmdTY29wZWQocGF0aCkgJiYgIXRoaXMuaXNMb2FkZWRUcmFuc2xhdGlvbihtYWluTGFuZykpIHtcbiAgICAgIHJldHVybiBjb21iaW5lTGF0ZXN0KFtcbiAgICAgICAgdGhpcy5sb2FkKG1haW5MYW5nKSxcbiAgICAgICAgdGhpcy5sb2FkKHBhdGgsIHsgaW5saW5lTG9hZGVyIH0pLFxuICAgICAgXSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmxvYWQocGF0aCwgeyBpbmxpbmVMb2FkZXIgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBfY29tcGxldGVTY29wZVdpdGhMYW5nKGxhbmdPclNjb3BlOiBzdHJpbmcpIHtcbiAgICBpZiAoXG4gICAgICB0aGlzLl9pc0xhbmdTY29wZWQobGFuZ09yU2NvcGUpICYmXG4gICAgICAhdGhpcy5pc0xhbmcoZ2V0TGFuZ0Zyb21TY29wZShsYW5nT3JTY29wZSkpXG4gICAgKSB7XG4gICAgICByZXR1cm4gYCR7bGFuZ09yU2NvcGV9LyR7dGhpcy5nZXRBY3RpdmVMYW5nKCl9YDtcbiAgICB9XG4gICAgcmV0dXJuIGxhbmdPclNjb3BlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgX3NldFNjb3BlQWxpYXMoc2NvcGU6IHN0cmluZywgYWxpYXM6IHN0cmluZykge1xuICAgIGlmICghdGhpcy5jb25maWcuc2NvcGVNYXBwaW5nKSB7XG4gICAgICB0aGlzLmNvbmZpZy5zY29wZU1hcHBpbmcgPSB7fTtcbiAgICB9XG4gICAgdGhpcy5jb25maWcuc2NvcGVNYXBwaW5nW3Njb3BlXSA9IGFsaWFzO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMuc3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgLy8gQ2FyZXRha2VyIG5vdGU6IGl0J3MgaW1wb3J0YW50IHRvIGNsZWFuIHVwIHJlZmVyZW5jZXMgdG8gc3Vic2NyaXB0aW9ucyBzaW5jZSB0aGV5IHNhdmUgdGhlIGBuZXh0YFxuICAgICAgLy8gY2FsbGJhY2sgd2l0aGluIGl0cyBgZGVzdGluYXRpb25gIHByb3BlcnR5LCBwcmV2ZW50aW5nIGNsYXNzZXMgZnJvbSBiZWluZyBHQydkLlxuICAgICAgdGhpcy5zdWJzY3JpcHRpb24gPSBudWxsO1xuICAgIH1cbiAgICAvLyBDYXJldGFrZXIgbm90ZTogc2luY2UgdGhpcyBpcyB0aGUgcm9vdCBwcm92aWRlciwgaXQnbGwgYmUgZGVzdHJveWVkIHdoZW4gdGhlIGBOZ01vZHVsZVJlZi5kZXN0cm95KClgIGlzIHJ1bi5cbiAgICAvLyBDYWNoZWQgdmFsdWVzIGNhcHR1cmUgYHRoaXNgLCB0aHVzIGxlYWRpbmcgdG8gYSBjaXJjdWxhciByZWZlcmVuY2UgYW5kIHByZXZlbnRpbmcgdGhlIGBUcmFuc2xvY29TZXJ2aWNlYCBmcm9tXG4gICAgLy8gYmVpbmcgR0MnZC4gVGhpcyB3b3VsZCBsZWFkIHRvIGEgbWVtb3J5IGxlYWsgd2hlbiBzZXJ2ZXItc2lkZSByZW5kZXJpbmcgaXMgdXNlZCBzaW5jZSB0aGUgc2VydmljZSBpcyBjcmVhdGVkXG4gICAgLy8gYW5kIGRlc3Ryb3llZCBwZXIgZWFjaCBIVFRQIHJlcXVlc3QsIGJ1dCBhbnkgc2VydmljZSBpcyBub3QgZ2V0dGluZyBHQydkLlxuICAgIHRoaXMuY2FjaGUuY2xlYXIoKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNMb2FkZWRUcmFuc2xhdGlvbihsYW5nOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gc2l6ZSh0aGlzLmdldFRyYW5zbGF0aW9uKGxhbmcpKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QXZhaWxhYmxlTGFuZ3NJZHMoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGZpcnN0ID0gdGhpcy5nZXRBdmFpbGFibGVMYW5ncygpWzBdO1xuXG4gICAgaWYgKGlzU3RyaW5nKGZpcnN0KSkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0QXZhaWxhYmxlTGFuZ3MoKSBhcyBzdHJpbmdbXTtcbiAgICB9XG5cbiAgICByZXR1cm4gKHRoaXMuZ2V0QXZhaWxhYmxlTGFuZ3MoKSBhcyBMYW5nRGVmaW5pdGlvbltdKS5tYXAoKGwpID0+IGwuaWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRNaXNzaW5nSGFuZGxlckRhdGEoKTogVHJhbnNsb2NvTWlzc2luZ0hhbmRsZXJEYXRhIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4udGhpcy5jb25maWcsXG4gICAgICBhY3RpdmVMYW5nOiB0aGlzLmdldEFjdGl2ZUxhbmcoKSxcbiAgICAgIGF2YWlsYWJsZUxhbmdzOiB0aGlzLmF2YWlsYWJsZUxhbmdzLFxuICAgICAgZGVmYXVsdExhbmc6IHRoaXMuZGVmYXVsdExhbmcsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2UgYSBmYWxsYmFjayB0cmFuc2xhdGlvbiBzZXQgZm9yIG1pc3Npbmcga2V5cyBvZiB0aGUgcHJpbWFyeSBsYW5ndWFnZVxuICAgKiBUaGlzIGlzIHVucmVsYXRlZCB0byB0aGUgZmFsbGJhY2sgbGFuZ3VhZ2UgKHdoaWNoIGNoYW5nZXMgdGhlIGFjdGl2ZSBsYW5ndWFnZSlcbiAgICovXG4gIHByaXZhdGUgdXNlRmFsbGJhY2tUcmFuc2xhdGlvbihsYW5nPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuY29uZmlnLm1pc3NpbmdIYW5kbGVyIS51c2VGYWxsYmFja1RyYW5zbGF0aW9uICYmXG4gICAgICBsYW5nICE9PSB0aGlzLmZpcnN0RmFsbGJhY2tMYW5nXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlU3VjY2VzcyhsYW5nOiBzdHJpbmcsIHRyYW5zbGF0aW9uOiBUcmFuc2xhdGlvbikge1xuICAgIHRoaXMuc2V0VHJhbnNsYXRpb24odHJhbnNsYXRpb24sIGxhbmcsIHsgZW1pdENoYW5nZTogZmFsc2UgfSk7XG4gICAgdGhpcy5ldmVudHMubmV4dCh7XG4gICAgICB3YXNGYWlsdXJlOiAhIXRoaXMuZmFpbGVkTGFuZ3Muc2l6ZSxcbiAgICAgIHR5cGU6ICd0cmFuc2xhdGlvbkxvYWRTdWNjZXNzJyxcbiAgICAgIHBheWxvYWQ6IGdldEV2ZW50UGF5bG9hZChsYW5nKSxcbiAgICB9KTtcbiAgICB0aGlzLmZhaWxlZExhbmdzLmZvckVhY2goKGwpID0+IHRoaXMuY2FjaGUuZGVsZXRlKGwpKTtcbiAgICB0aGlzLmZhaWxlZExhbmdzLmNsZWFyKCk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUZhaWx1cmUobGFuZzogc3RyaW5nLCBsb2FkT3B0aW9uczogTG9hZE9wdGlvbnMpIHtcbiAgICAvLyBXaGVuIHN0YXJ0aW5nIHRvIGxvYWQgYSBmaXJzdCBjaG9pY2UgbGFuZ3VhZ2UsIGluaXRpYWxpemVcbiAgICAvLyB0aGUgZmFpbGVkIGNvdW50ZXIgYW5kIHJlc29sdmUgdGhlIGZhbGxiYWNrIGxhbmdzLlxuICAgIGlmIChpc05pbChsb2FkT3B0aW9ucy5mYWlsZWRDb3VudGVyKSkge1xuICAgICAgbG9hZE9wdGlvbnMuZmFpbGVkQ291bnRlciA9IDA7XG5cbiAgICAgIGlmICghbG9hZE9wdGlvbnMuZmFsbGJhY2tMYW5ncykge1xuICAgICAgICBsb2FkT3B0aW9ucy5mYWxsYmFja0xhbmdzID0gdGhpcy5mYWxsYmFja1N0cmF0ZWd5LmdldE5leHRMYW5ncyhsYW5nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBzcGxpdHRlZCA9IGxhbmcuc3BsaXQoJy8nKTtcbiAgICBjb25zdCBmYWxsYmFja3MgPSBsb2FkT3B0aW9ucy5mYWxsYmFja0xhbmdzO1xuICAgIGNvbnN0IG5leHRMYW5nID0gZmFsbGJhY2tzIVtsb2FkT3B0aW9ucy5mYWlsZWRDb3VudGVyIV07XG4gICAgdGhpcy5mYWlsZWRMYW5ncy5hZGQobGFuZyk7XG5cbiAgICAvLyBUaGlzIGhhbmRsZXMgdGhlIGNhc2Ugd2hlcmUgYSBsb2FkZWQgZmFsbGJhY2sgbGFuZ3VhZ2UgaXMgcmVxdWVzdGVkIGFnYWluXG4gICAgaWYgKHRoaXMuY2FjaGUuaGFzKG5leHRMYW5nKSkge1xuICAgICAgdGhpcy5oYW5kbGVTdWNjZXNzKG5leHRMYW5nLCB0aGlzLmdldFRyYW5zbGF0aW9uKG5leHRMYW5nKSk7XG4gICAgICByZXR1cm4gRU1QVFk7XG4gICAgfVxuXG4gICAgY29uc3QgaXNGYWxsYmFja0xhbmcgPSBuZXh0TGFuZyA9PT0gc3BsaXR0ZWRbc3BsaXR0ZWQubGVuZ3RoIC0gMV07XG5cbiAgICBpZiAoIW5leHRMYW5nIHx8IGlzRmFsbGJhY2tMYW5nKSB7XG4gICAgICBsZXQgbXNnID0gYFVuYWJsZSB0byBsb2FkIHRyYW5zbGF0aW9uIGFuZCBhbGwgdGhlIGZhbGxiYWNrIGxhbmd1YWdlc2A7XG4gICAgICBpZiAoc3BsaXR0ZWQubGVuZ3RoID4gMSkge1xuICAgICAgICBtc2cgKz0gYCwgZGlkIHlvdSBtaXNzcGVsbGVkIHRoZSBzY29wZSBuYW1lP2A7XG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgIH1cblxuICAgIGxldCByZXNvbHZlTGFuZyA9IG5leHRMYW5nO1xuICAgIC8vIGlmIGl0J3Mgc2NvcGVkIGxhbmdcbiAgICBpZiAoc3BsaXR0ZWQubGVuZ3RoID4gMSkge1xuICAgICAgLy8gV2UgbmVlZCB0byByZXNvbHZlIGl0IHRvOlxuICAgICAgLy8gdG9kb3MvbGFuZ05vdEV4aXN0cyA9PiB0b2Rvcy9uZXh0TGFuZ1xuICAgICAgc3BsaXR0ZWRbc3BsaXR0ZWQubGVuZ3RoIC0gMV0gPSBuZXh0TGFuZztcbiAgICAgIHJlc29sdmVMYW5nID0gc3BsaXR0ZWQuam9pbignLycpO1xuICAgIH1cblxuICAgIGxvYWRPcHRpb25zLmZhaWxlZENvdW50ZXIhKys7XG4gICAgdGhpcy5ldmVudHMubmV4dCh7XG4gICAgICB0eXBlOiAndHJhbnNsYXRpb25Mb2FkRmFpbHVyZScsXG4gICAgICBwYXlsb2FkOiBnZXRFdmVudFBheWxvYWQobGFuZyksXG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcy5sb2FkKHJlc29sdmVMYW5nLCBsb2FkT3B0aW9ucyk7XG4gIH1cblxuICBwcml2YXRlIGdldE1hcHBlZFNjb3BlKHNjb3BlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHsgc2NvcGVNYXBwaW5nID0ge30gfSA9IHRoaXMuY29uZmlnO1xuICAgIHJldHVybiBzY29wZU1hcHBpbmdbc2NvcGVdIHx8IHRvQ2FtZWxDYXNlKHNjb3BlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiBsYW5nIGlzIHNjb3BlIHdlIG5lZWQgdG8gY2hlY2sgdGhlIGZvbGxvd2luZyBjYXNlczpcbiAgICogdG9kb3MvZXMgPT4gaW4gdGhpcyBjYXNlIHdlIHNob3VsZCB0YWtlIGBlc2AgYXMgbGFuZ1xuICAgKiB0b2RvcyA9PiBpbiB0aGlzIGNhc2Ugd2Ugc2hvdWxkIHNldCB0aGUgYWN0aXZlIGxhbmcgYXMgbGFuZ1xuICAgKi9cbiAgcHJpdmF0ZSByZXNvbHZlTGFuZ0FuZFNjb3BlKGxhbmc6IHN0cmluZykge1xuICAgIGxldCByZXNvbHZlTGFuZyA9IGxhbmc7XG4gICAgbGV0IHNjb3BlO1xuXG4gICAgaWYgKHRoaXMuX2lzTGFuZ1Njb3BlZChsYW5nKSkge1xuICAgICAgLy8gZW4gZm9yIGV4YW1wbGVcbiAgICAgIGNvbnN0IGxhbmdGcm9tU2NvcGUgPSBnZXRMYW5nRnJvbVNjb3BlKGxhbmcpO1xuICAgICAgLy8gZW4gaXMgbGFuZ1xuICAgICAgY29uc3QgaGFzTGFuZyA9IHRoaXMuaXNMYW5nKGxhbmdGcm9tU2NvcGUpO1xuICAgICAgLy8gdGFrZSBlblxuICAgICAgcmVzb2x2ZUxhbmcgPSBoYXNMYW5nID8gbGFuZ0Zyb21TY29wZSA6IHRoaXMuZ2V0QWN0aXZlTGFuZygpO1xuICAgICAgLy8gZmluZCB0aGUgc2NvcGVcbiAgICAgIHNjb3BlID0gdGhpcy5nZXRNYXBwZWRTY29wZShoYXNMYW5nID8gZ2V0U2NvcGVGcm9tTGFuZyhsYW5nKSA6IGxhbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB7IHNjb3BlLCByZXNvbHZlTGFuZyB9O1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRPYmplY3RCeUtleSh0cmFuc2xhdGlvbjogVHJhbnNsYXRpb24sIGtleT86IHN0cmluZykge1xuICAgIGNvbnN0IHJlc3VsdDogVHJhbnNsYXRpb24gPSB7fTtcbiAgICBjb25zdCBwcmVmaXggPSBgJHtrZXl9LmA7XG5cbiAgICBmb3IgKGNvbnN0IGN1cnJlbnRLZXkgaW4gdHJhbnNsYXRpb24pIHtcbiAgICAgIGlmIChjdXJyZW50S2V5LnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgICByZXN1bHRbY3VycmVudEtleS5yZXBsYWNlKHByZWZpeCwgJycpXSA9IHRyYW5zbGF0aW9uW2N1cnJlbnRLZXldO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwcml2YXRlIGdldEVudHJpZXMoa2V5OiBIYXNoTWFwIHwgTWFwPHN0cmluZywgSGFzaE1hcD4pIHtcbiAgICByZXR1cm4ga2V5IGluc3RhbmNlb2YgTWFwID8ga2V5LmVudHJpZXMoKSA6IE9iamVjdC5lbnRyaWVzKGtleSk7XG4gIH1cbn1cbiJdfQ==