@angular/router 16.0.0-next.4 → 16.0.0-next.6

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 (94) hide show
  1. package/esm2022/src/apply_redirects.mjs +112 -0
  2. package/{esm2020 → esm2022}/src/components/empty_outlet.mjs +4 -4
  3. package/esm2022/src/create_url_tree.mjs +418 -0
  4. package/{esm2020 → esm2022}/src/directives/router_link.mjs +4 -4
  5. package/{esm2020 → esm2022}/src/directives/router_link_active.mjs +4 -4
  6. package/esm2022/src/directives/router_outlet.mjs +336 -0
  7. package/esm2022/src/index.mjs +30 -0
  8. package/esm2022/src/navigation_transition.mjs +397 -0
  9. package/esm2022/src/operators/activate_routes.mjs +192 -0
  10. package/{esm2020 → esm2022}/src/operators/check_guards.mjs +1 -1
  11. package/esm2022/src/operators/recognize.mjs +16 -0
  12. package/{esm2020 → esm2022}/src/page_title_strategy.mjs +7 -7
  13. package/esm2022/src/provide_router.mjs +507 -0
  14. package/esm2022/src/recognize.mjs +360 -0
  15. package/{esm2020 → esm2022}/src/route_reuse_strategy.mjs +7 -7
  16. package/esm2022/src/router.mjs +724 -0
  17. package/esm2022/src/router_config.mjs +18 -0
  18. package/esm2022/src/router_config_loader.mjs +132 -0
  19. package/esm2022/src/router_module.mjs +220 -0
  20. package/{esm2020 → esm2022}/src/router_outlet_context.mjs +4 -4
  21. package/esm2022/src/router_preloader.mjs +167 -0
  22. package/{esm2020 → esm2022}/src/router_scroller.mjs +4 -4
  23. package/esm2022/src/router_state.mjs +408 -0
  24. package/{esm2020 → esm2022}/src/url_handling_strategy.mjs +7 -7
  25. package/esm2022/src/url_tree.mjs +642 -0
  26. package/esm2022/src/utils/navigations.mjs +42 -0
  27. package/esm2022/src/utils/type_guards.mjs +54 -0
  28. package/{esm2020 → esm2022}/src/version.mjs +1 -1
  29. package/{esm2020 → esm2022}/testing/src/router_testing_harness.mjs +7 -7
  30. package/{esm2020 → esm2022}/testing/src/router_testing_module.mjs +10 -10
  31. package/{fesm2020 → fesm2022}/router.mjs +799 -787
  32. package/fesm2022/router.mjs.map +1 -0
  33. package/{fesm2020 → fesm2022}/testing.mjs +16 -16
  34. package/{fesm2020 → fesm2022}/testing.mjs.map +1 -1
  35. package/{fesm2020 → fesm2022}/upgrade.mjs +1 -1
  36. package/index.d.ts +92 -5
  37. package/package.json +14 -24
  38. package/testing/index.d.ts +1 -1
  39. package/upgrade/index.d.ts +1 -1
  40. package/esm2020/src/apply_redirects.mjs +0 -331
  41. package/esm2020/src/create_url_tree.mjs +0 -417
  42. package/esm2020/src/directives/router_outlet.mjs +0 -259
  43. package/esm2020/src/index.mjs +0 -30
  44. package/esm2020/src/navigation_transition.mjs +0 -399
  45. package/esm2020/src/operators/activate_routes.mjs +0 -177
  46. package/esm2020/src/operators/apply_redirects.mjs +0 -14
  47. package/esm2020/src/operators/recognize.mjs +0 -14
  48. package/esm2020/src/provide_router.mjs +0 -477
  49. package/esm2020/src/recognize.mjs +0 -270
  50. package/esm2020/src/router.mjs +0 -710
  51. package/esm2020/src/router_config.mjs +0 -19
  52. package/esm2020/src/router_config_loader.mjs +0 -131
  53. package/esm2020/src/router_module.mjs +0 -216
  54. package/esm2020/src/router_preloader.mjs +0 -167
  55. package/esm2020/src/router_state.mjs +0 -409
  56. package/esm2020/src/url_tree.mjs +0 -631
  57. package/esm2020/src/utils/navigations.mjs +0 -42
  58. package/esm2020/src/utils/type_guards.mjs +0 -54
  59. package/fesm2015/router.mjs +0 -7001
  60. package/fesm2015/router.mjs.map +0 -1
  61. package/fesm2015/testing.mjs +0 -270
  62. package/fesm2015/testing.mjs.map +0 -1
  63. package/fesm2015/upgrade.mjs +0 -146
  64. package/fesm2015/upgrade.mjs.map +0 -1
  65. package/fesm2020/router.mjs.map +0 -1
  66. /package/{esm2020 → esm2022}/index.mjs +0 -0
  67. /package/{esm2020 → esm2022}/public_api.mjs +0 -0
  68. /package/{esm2020 → esm2022}/router.mjs +0 -0
  69. /package/{esm2020 → esm2022}/src/create_router_state.mjs +0 -0
  70. /package/{esm2020 → esm2022}/src/errors.mjs +0 -0
  71. /package/{esm2020 → esm2022}/src/events.mjs +0 -0
  72. /package/{esm2020 → esm2022}/src/models.mjs +0 -0
  73. /package/{esm2020 → esm2022}/src/models_deprecated.mjs +0 -0
  74. /package/{esm2020 → esm2022}/src/navigation_canceling_error.mjs +0 -0
  75. /package/{esm2020 → esm2022}/src/operators/prioritized_guard_value.mjs +0 -0
  76. /package/{esm2020 → esm2022}/src/operators/resolve_data.mjs +0 -0
  77. /package/{esm2020 → esm2022}/src/operators/switch_tap.mjs +0 -0
  78. /package/{esm2020 → esm2022}/src/private_export.mjs +0 -0
  79. /package/{esm2020 → esm2022}/src/shared.mjs +0 -0
  80. /package/{esm2020 → esm2022}/src/utils/collection.mjs +0 -0
  81. /package/{esm2020 → esm2022}/src/utils/config.mjs +0 -0
  82. /package/{esm2020 → esm2022}/src/utils/config_matching.mjs +0 -0
  83. /package/{esm2020 → esm2022}/src/utils/functional_guards.mjs +0 -0
  84. /package/{esm2020 → esm2022}/src/utils/preactivation.mjs +0 -0
  85. /package/{esm2020 → esm2022}/src/utils/tree.mjs +0 -0
  86. /package/{esm2020 → esm2022}/testing/index.mjs +0 -0
  87. /package/{esm2020 → esm2022}/testing/public_api.mjs +0 -0
  88. /package/{esm2020 → esm2022}/testing/src/testing.mjs +0 -0
  89. /package/{esm2020 → esm2022}/testing/testing.mjs +0 -0
  90. /package/{esm2020 → esm2022}/upgrade/index.mjs +0 -0
  91. /package/{esm2020 → esm2022}/upgrade/public_api.mjs +0 -0
  92. /package/{esm2020 → esm2022}/upgrade/src/upgrade.mjs +0 -0
  93. /package/{esm2020 → esm2022}/upgrade/upgrade.mjs +0 -0
  94. /package/{fesm2020 → fesm2022}/upgrade.mjs.map +0 -0
@@ -0,0 +1,724 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.io/license
7
+ */
8
+ import { Location } from '@angular/common';
9
+ import { inject, Injectable, NgZone, ɵConsole as Console, ɵInitialRenderPendingTasks as InitialRenderPendingTasks, ɵRuntimeError as RuntimeError } from '@angular/core';
10
+ import { createSegmentGroupFromRoute, createUrlTreeFromSegmentGroup } from './create_url_tree';
11
+ import { INPUT_BINDER } from './directives/router_outlet';
12
+ import { IMPERATIVE_NAVIGATION } from './events';
13
+ import { NavigationTransitions } from './navigation_transition';
14
+ import { TitleStrategy } from './page_title_strategy';
15
+ import { RouteReuseStrategy } from './route_reuse_strategy';
16
+ import { ROUTER_CONFIGURATION } from './router_config';
17
+ import { ROUTES } from './router_config_loader';
18
+ import { createEmptyState } from './router_state';
19
+ import { UrlHandlingStrategy } from './url_handling_strategy';
20
+ import { containsTree, isUrlTree, UrlSerializer, UrlTree } from './url_tree';
21
+ import { standardizeConfig, validateConfig } from './utils/config';
22
+ import { afterNextNavigation } from './utils/navigations';
23
+ import * as i0 from "@angular/core";
24
+ function defaultErrorHandler(error) {
25
+ throw error;
26
+ }
27
+ function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
28
+ return urlSerializer.parse('/');
29
+ }
30
+ /**
31
+ * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`
32
+ * (exact = true).
33
+ */
34
+ export const exactMatchOptions = {
35
+ paths: 'exact',
36
+ fragment: 'ignored',
37
+ matrixParams: 'ignored',
38
+ queryParams: 'exact'
39
+ };
40
+ /**
41
+ * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false`
42
+ * (exact = false).
43
+ */
44
+ export const subsetMatchOptions = {
45
+ paths: 'subset',
46
+ fragment: 'ignored',
47
+ matrixParams: 'ignored',
48
+ queryParams: 'subset'
49
+ };
50
+ /**
51
+ * @description
52
+ *
53
+ * A service that provides navigation among views and URL manipulation capabilities.
54
+ *
55
+ * @see `Route`.
56
+ * @see [Routing and Navigation Guide](guide/router).
57
+ *
58
+ * @ngModule RouterModule
59
+ *
60
+ * @publicApi
61
+ */
62
+ class Router {
63
+ // TODO(b/260747083): This should not exist and navigationId should be private in
64
+ // `NavigationTransitions`
65
+ get navigationId() {
66
+ return this.navigationTransitions.navigationId;
67
+ }
68
+ /**
69
+ * The ɵrouterPageId of whatever page is currently active in the browser history. This is
70
+ * important for computing the target page id for new navigations because we need to ensure each
71
+ * page id in the browser history is 1 more than the previous entry.
72
+ */
73
+ get browserPageId() {
74
+ return this.location.getState()?.ɵrouterPageId;
75
+ }
76
+ /**
77
+ * An event stream for routing events.
78
+ */
79
+ get events() {
80
+ // TODO(atscott): This _should_ be events.asObservable(). However, this change requires internal
81
+ // cleanup: tests are doing `(route.events as Subject<Event>).next(...)`. This isn't
82
+ // allowed/supported but we still have to fix these or file bugs against the teams before making
83
+ // the change.
84
+ return this.navigationTransitions.events;
85
+ }
86
+ constructor() {
87
+ this.disposed = false;
88
+ /**
89
+ * The id of the currently active page in the router.
90
+ * Updated to the transition's target id on a successful navigation.
91
+ *
92
+ * This is used to track what page the router last activated. When an attempted navigation fails,
93
+ * the router can then use this to compute how to restore the state back to the previously active
94
+ * page.
95
+ */
96
+ this.currentPageId = 0;
97
+ this.console = inject(Console);
98
+ this.isNgZoneEnabled = false;
99
+ this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
100
+ this.pendingTasks = inject(InitialRenderPendingTasks);
101
+ /**
102
+ * A handler for navigation errors in this NgModule.
103
+ *
104
+ * @deprecated Subscribe to the `Router` events and watch for `NavigationError` instead.
105
+ * `provideRouter` has the `withNavigationErrorHandler` feature to make this easier.
106
+ * @see `withNavigationErrorHandler`
107
+ */
108
+ this.errorHandler = this.options.errorHandler || defaultErrorHandler;
109
+ /**
110
+ * A handler for errors thrown by `Router.parseUrl(url)`
111
+ * when `url` contains an invalid character.
112
+ * The most common case is a `%` sign
113
+ * that's not encoded and is not part of a percent encoded sequence.
114
+ *
115
+ * @deprecated URI parsing errors should be handled in the `UrlSerializer`.
116
+ *
117
+ * @see `RouterModule`
118
+ */
119
+ this.malformedUriErrorHandler = this.options.malformedUriErrorHandler || defaultMalformedUriErrorHandler;
120
+ /**
121
+ * True if at least one navigation event has occurred,
122
+ * false otherwise.
123
+ */
124
+ this.navigated = false;
125
+ this.lastSuccessfulId = -1;
126
+ /**
127
+ * A strategy for extracting and merging URLs.
128
+ * Used for AngularJS to Angular migrations.
129
+ *
130
+ * @deprecated Configure using `providers` instead:
131
+ * `{provide: UrlHandlingStrategy, useClass: MyStrategy}`.
132
+ */
133
+ this.urlHandlingStrategy = inject(UrlHandlingStrategy);
134
+ /**
135
+ * A strategy for re-using routes.
136
+ *
137
+ * @deprecated Configure using `providers` instead:
138
+ * `{provide: RouteReuseStrategy, useClass: MyStrategy}`.
139
+ */
140
+ this.routeReuseStrategy = inject(RouteReuseStrategy);
141
+ /**
142
+ * A strategy for setting the title based on the `routerState`.
143
+ *
144
+ * @deprecated Configure using `providers` instead:
145
+ * `{provide: TitleStrategy, useClass: MyStrategy}`.
146
+ */
147
+ this.titleStrategy = inject(TitleStrategy);
148
+ /**
149
+ * How to handle a navigation request to the current URL.
150
+ *
151
+ *
152
+ * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
153
+ * @see `withRouterConfig`
154
+ * @see `provideRouter`
155
+ * @see `RouterModule`
156
+ */
157
+ this.onSameUrlNavigation = this.options.onSameUrlNavigation || 'ignore';
158
+ /**
159
+ * How to merge parameters, data, resolved data, and title from parent to child
160
+ * routes. One of:
161
+ *
162
+ * - `'emptyOnly'` : Inherit parent parameters, data, and resolved data
163
+ * for path-less or component-less routes.
164
+ * - `'always'` : Inherit parent parameters, data, and resolved data
165
+ * for all child routes.
166
+ *
167
+ * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
168
+ * @see `withRouterConfig`
169
+ * @see `provideRouter`
170
+ * @see `RouterModule`
171
+ */
172
+ this.paramsInheritanceStrategy = this.options.paramsInheritanceStrategy || 'emptyOnly';
173
+ /**
174
+ * Determines when the router updates the browser URL.
175
+ * By default (`"deferred"`), updates the browser URL after navigation has finished.
176
+ * Set to `'eager'` to update the browser URL at the beginning of navigation.
177
+ * You can choose to update early so that, if navigation fails,
178
+ * you can show an error message with the URL that failed.
179
+ *
180
+ * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
181
+ * @see `withRouterConfig`
182
+ * @see `provideRouter`
183
+ * @see `RouterModule`
184
+ */
185
+ this.urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
186
+ /**
187
+ * Configures how the Router attempts to restore state when a navigation is cancelled.
188
+ *
189
+ * 'replace' - Always uses `location.replaceState` to set the browser state to the state of the
190
+ * router before the navigation started. This means that if the URL of the browser is updated
191
+ * _before_ the navigation is canceled, the Router will simply replace the item in history rather
192
+ * than trying to restore to the previous location in the session history. This happens most
193
+ * frequently with `urlUpdateStrategy: 'eager'` and navigations with the browser back/forward
194
+ * buttons.
195
+ *
196
+ * 'computed' - Will attempt to return to the same index in the session history that corresponds
197
+ * to the Angular route when the navigation gets cancelled. For example, if the browser back
198
+ * button is clicked and the navigation is cancelled, the Router will trigger a forward navigation
199
+ * and vice versa.
200
+ *
201
+ * Note: the 'computed' option is incompatible with any `UrlHandlingStrategy` which only
202
+ * handles a portion of the URL because the history restoration navigates to the previous place in
203
+ * the browser history rather than simply resetting a portion of the URL.
204
+ *
205
+ * The default value is `replace`.
206
+ *
207
+ * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
208
+ * @see `withRouterConfig`
209
+ * @see `provideRouter`
210
+ * @see `RouterModule`
211
+ */
212
+ this.canceledNavigationResolution = this.options.canceledNavigationResolution || 'replace';
213
+ this.config = inject(ROUTES, { optional: true })?.flat() ?? [];
214
+ this.navigationTransitions = inject(NavigationTransitions);
215
+ this.urlSerializer = inject(UrlSerializer);
216
+ this.location = inject(Location);
217
+ /**
218
+ * Indicates whether the the application has opted in to binding Router data to component inputs.
219
+ *
220
+ * This option is enabled by the `withComponentInputBinding` feature of `provideRouter` or
221
+ * `bindToComponentInputs` in the `ExtraOptions` of `RouterModule.forRoot`.
222
+ */
223
+ this.componentInputBindingEnabled = !!inject(INPUT_BINDER, { optional: true });
224
+ this.isNgZoneEnabled = inject(NgZone) instanceof NgZone && NgZone.isInAngularZone();
225
+ this.resetConfig(this.config);
226
+ this.currentUrlTree = new UrlTree();
227
+ this.rawUrlTree = this.currentUrlTree;
228
+ this.browserUrlTree = this.currentUrlTree;
229
+ this.routerState = createEmptyState(this.currentUrlTree, null);
230
+ this.navigationTransitions.setupNavigations(this).subscribe(t => {
231
+ this.lastSuccessfulId = t.id;
232
+ this.currentPageId = t.targetPageId;
233
+ }, e => {
234
+ this.console.warn(`Unhandled Navigation Error: ${e}`);
235
+ });
236
+ }
237
+ /** @internal */
238
+ resetRootComponentType(rootComponentType) {
239
+ // TODO: vsavkin router 4.0 should make the root component set to null
240
+ // this will simplify the lifecycle of the router.
241
+ this.routerState.root.component = rootComponentType;
242
+ this.navigationTransitions.rootComponentType = rootComponentType;
243
+ }
244
+ /**
245
+ * Sets up the location change listener and performs the initial navigation.
246
+ */
247
+ initialNavigation() {
248
+ this.setUpLocationChangeListener();
249
+ if (!this.navigationTransitions.hasRequestedNavigation) {
250
+ const state = this.location.getState();
251
+ this.navigateToSyncWithBrowser(this.location.path(true), IMPERATIVE_NAVIGATION, state);
252
+ }
253
+ }
254
+ /**
255
+ * Sets up the location change listener. This listener detects navigations triggered from outside
256
+ * the Router (the browser back/forward buttons, for example) and schedules a corresponding Router
257
+ * navigation so that the correct events, guards, etc. are triggered.
258
+ */
259
+ setUpLocationChangeListener() {
260
+ // Don't need to use Zone.wrap any more, because zone.js
261
+ // already patch onPopState, so location change callback will
262
+ // run into ngZone
263
+ if (!this.locationSubscription) {
264
+ this.locationSubscription = this.location.subscribe(event => {
265
+ const source = event['type'] === 'popstate' ? 'popstate' : 'hashchange';
266
+ if (source === 'popstate') {
267
+ // The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS
268
+ // hybrid apps.
269
+ setTimeout(() => {
270
+ this.navigateToSyncWithBrowser(event['url'], source, event.state);
271
+ }, 0);
272
+ }
273
+ });
274
+ }
275
+ }
276
+ /**
277
+ * Schedules a router navigation to synchronize Router state with the browser state.
278
+ *
279
+ * This is done as a response to a popstate event and the initial navigation. These
280
+ * two scenarios represent times when the browser URL/state has been updated and
281
+ * the Router needs to respond to ensure its internal state matches.
282
+ */
283
+ navigateToSyncWithBrowser(url, source, state) {
284
+ const extras = { replaceUrl: true };
285
+ // TODO: restoredState should always include the entire state, regardless
286
+ // of navigationId. This requires a breaking change to update the type on
287
+ // NavigationStart’s restoredState, which currently requires navigationId
288
+ // to always be present. The Router used to only restore history state if
289
+ // a navigationId was present.
290
+ // The stored navigationId is used by the RouterScroller to retrieve the scroll
291
+ // position for the page.
292
+ const restoredState = state?.navigationId ? state : null;
293
+ // Separate to NavigationStart.restoredState, we must also restore the state to
294
+ // history.state and generate a new navigationId, since it will be overwritten
295
+ if (state) {
296
+ const stateCopy = { ...state };
297
+ delete stateCopy.navigationId;
298
+ delete stateCopy.ɵrouterPageId;
299
+ if (Object.keys(stateCopy).length !== 0) {
300
+ extras.state = stateCopy;
301
+ }
302
+ }
303
+ const urlTree = this.parseUrl(url);
304
+ this.scheduleNavigation(urlTree, source, restoredState, extras);
305
+ }
306
+ /** The current URL. */
307
+ get url() {
308
+ return this.serializeUrl(this.currentUrlTree);
309
+ }
310
+ /**
311
+ * Returns the current `Navigation` object when the router is navigating,
312
+ * and `null` when idle.
313
+ */
314
+ getCurrentNavigation() {
315
+ return this.navigationTransitions.currentNavigation;
316
+ }
317
+ /**
318
+ * The `Navigation` object of the most recent navigation to succeed and `null` if there
319
+ * has not been a successful navigation yet.
320
+ */
321
+ get lastSuccessfulNavigation() {
322
+ return this.navigationTransitions.lastSuccessfulNavigation;
323
+ }
324
+ /**
325
+ * Resets the route configuration used for navigation and generating links.
326
+ *
327
+ * @param config The route array for the new configuration.
328
+ *
329
+ * @usageNotes
330
+ *
331
+ * ```
332
+ * router.resetConfig([
333
+ * { path: 'team/:id', component: TeamCmp, children: [
334
+ * { path: 'simple', component: SimpleCmp },
335
+ * { path: 'user/:name', component: UserCmp }
336
+ * ]}
337
+ * ]);
338
+ * ```
339
+ */
340
+ resetConfig(config) {
341
+ (typeof ngDevMode === 'undefined' || ngDevMode) && validateConfig(config);
342
+ this.config = config.map(standardizeConfig);
343
+ this.navigated = false;
344
+ this.lastSuccessfulId = -1;
345
+ }
346
+ /** @nodoc */
347
+ ngOnDestroy() {
348
+ this.dispose();
349
+ }
350
+ /** Disposes of the router. */
351
+ dispose() {
352
+ this.navigationTransitions.complete();
353
+ if (this.locationSubscription) {
354
+ this.locationSubscription.unsubscribe();
355
+ this.locationSubscription = undefined;
356
+ }
357
+ this.disposed = true;
358
+ }
359
+ /**
360
+ * Appends URL segments to the current URL tree to create a new URL tree.
361
+ *
362
+ * @param commands An array of URL fragments with which to construct the new URL tree.
363
+ * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
364
+ * segments, followed by the parameters for each segment.
365
+ * The fragments are applied to the current URL tree or the one provided in the `relativeTo`
366
+ * property of the options object, if supplied.
367
+ * @param navigationExtras Options that control the navigation strategy.
368
+ * @returns The new URL tree.
369
+ *
370
+ * @usageNotes
371
+ *
372
+ * ```
373
+ * // create /team/33/user/11
374
+ * router.createUrlTree(['/team', 33, 'user', 11]);
375
+ *
376
+ * // create /team/33;expand=true/user/11
377
+ * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
378
+ *
379
+ * // you can collapse static segments like this (this works only with the first passed-in value):
380
+ * router.createUrlTree(['/team/33/user', userId]);
381
+ *
382
+ * // If the first segment can contain slashes, and you do not want the router to split it,
383
+ * // you can do the following:
384
+ * router.createUrlTree([{segmentPath: '/one/two'}]);
385
+ *
386
+ * // create /team/33/(user/11//right:chat)
387
+ * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
388
+ *
389
+ * // remove the right secondary node
390
+ * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]);
391
+ *
392
+ * // assuming the current url is `/team/33/user/11` and the route points to `user/11`
393
+ *
394
+ * // navigate to /team/33/user/11/details
395
+ * router.createUrlTree(['details'], {relativeTo: route});
396
+ *
397
+ * // navigate to /team/33/user/22
398
+ * router.createUrlTree(['../22'], {relativeTo: route});
399
+ *
400
+ * // navigate to /team/44/user/22
401
+ * router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});
402
+ *
403
+ * Note that a value of `null` or `undefined` for `relativeTo` indicates that the
404
+ * tree should be created relative to the root.
405
+ * ```
406
+ */
407
+ createUrlTree(commands, navigationExtras = {}) {
408
+ const { relativeTo, queryParams, fragment, queryParamsHandling, preserveFragment } = navigationExtras;
409
+ const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
410
+ let q = null;
411
+ switch (queryParamsHandling) {
412
+ case 'merge':
413
+ q = { ...this.currentUrlTree.queryParams, ...queryParams };
414
+ break;
415
+ case 'preserve':
416
+ q = this.currentUrlTree.queryParams;
417
+ break;
418
+ default:
419
+ q = queryParams || null;
420
+ }
421
+ if (q !== null) {
422
+ q = this.removeEmptyProps(q);
423
+ }
424
+ let relativeToUrlSegmentGroup;
425
+ try {
426
+ const relativeToSnapshot = relativeTo ? relativeTo.snapshot : this.routerState.snapshot.root;
427
+ relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeToSnapshot);
428
+ }
429
+ catch (e) {
430
+ // This is strictly for backwards compatibility with tests that create
431
+ // invalid `ActivatedRoute` mocks.
432
+ // Note: the difference between having this fallback for invalid `ActivatedRoute` setups and
433
+ // just throwing is ~500 test failures. Fixing all of those tests by hand is not feasible at
434
+ // the moment.
435
+ if (typeof commands[0] !== 'string' || !commands[0].startsWith('/')) {
436
+ // Navigations that were absolute in the old way of creating UrlTrees
437
+ // would still work because they wouldn't attempt to match the
438
+ // segments in the `ActivatedRoute` to the `currentUrlTree` but
439
+ // instead just replace the root segment with the navigation result.
440
+ // Non-absolute navigations would fail to apply the commands because
441
+ // the logic could not find the segment to replace (so they'd act like there were no
442
+ // commands).
443
+ commands = [];
444
+ }
445
+ relativeToUrlSegmentGroup = this.currentUrlTree.root;
446
+ }
447
+ return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, q, f ?? null);
448
+ }
449
+ /**
450
+ * Navigates to a view using an absolute route path.
451
+ *
452
+ * @param url An absolute path for a defined route. The function does not apply any delta to the
453
+ * current URL.
454
+ * @param extras An object containing properties that modify the navigation strategy.
455
+ *
456
+ * @returns A Promise that resolves to 'true' when navigation succeeds,
457
+ * to 'false' when navigation fails, or is rejected on error.
458
+ *
459
+ * @usageNotes
460
+ *
461
+ * The following calls request navigation to an absolute path.
462
+ *
463
+ * ```
464
+ * router.navigateByUrl("/team/33/user/11");
465
+ *
466
+ * // Navigate without updating the URL
467
+ * router.navigateByUrl("/team/33/user/11", { skipLocationChange: true });
468
+ * ```
469
+ *
470
+ * @see [Routing and Navigation guide](guide/router)
471
+ *
472
+ */
473
+ navigateByUrl(url, extras = {
474
+ skipLocationChange: false
475
+ }) {
476
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
477
+ if (this.isNgZoneEnabled && !NgZone.isInAngularZone()) {
478
+ this.console.warn(`Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`);
479
+ }
480
+ }
481
+ const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
482
+ const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
483
+ return this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras);
484
+ }
485
+ /**
486
+ * Navigate based on the provided array of commands and a starting point.
487
+ * If no starting route is provided, the navigation is absolute.
488
+ *
489
+ * @param commands An array of URL fragments with which to construct the target URL.
490
+ * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
491
+ * segments, followed by the parameters for each segment.
492
+ * The fragments are applied to the current URL or the one provided in the `relativeTo` property
493
+ * of the options object, if supplied.
494
+ * @param extras An options object that determines how the URL should be constructed or
495
+ * interpreted.
496
+ *
497
+ * @returns A Promise that resolves to `true` when navigation succeeds, to `false` when navigation
498
+ * fails,
499
+ * or is rejected on error.
500
+ *
501
+ * @usageNotes
502
+ *
503
+ * The following calls request navigation to a dynamic route path relative to the current URL.
504
+ *
505
+ * ```
506
+ * router.navigate(['team', 33, 'user', 11], {relativeTo: route});
507
+ *
508
+ * // Navigate without updating the URL, overriding the default behavior
509
+ * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true});
510
+ * ```
511
+ *
512
+ * @see [Routing and Navigation guide](guide/router)
513
+ *
514
+ */
515
+ navigate(commands, extras = { skipLocationChange: false }) {
516
+ validateCommands(commands);
517
+ return this.navigateByUrl(this.createUrlTree(commands, extras), extras);
518
+ }
519
+ /** Serializes a `UrlTree` into a string */
520
+ serializeUrl(url) {
521
+ return this.urlSerializer.serialize(url);
522
+ }
523
+ /** Parses a string into a `UrlTree` */
524
+ parseUrl(url) {
525
+ let urlTree;
526
+ try {
527
+ urlTree = this.urlSerializer.parse(url);
528
+ }
529
+ catch (e) {
530
+ urlTree = this.malformedUriErrorHandler(e, this.urlSerializer, url);
531
+ }
532
+ return urlTree;
533
+ }
534
+ isActive(url, matchOptions) {
535
+ let options;
536
+ if (matchOptions === true) {
537
+ options = { ...exactMatchOptions };
538
+ }
539
+ else if (matchOptions === false) {
540
+ options = { ...subsetMatchOptions };
541
+ }
542
+ else {
543
+ options = matchOptions;
544
+ }
545
+ if (isUrlTree(url)) {
546
+ return containsTree(this.currentUrlTree, url, options);
547
+ }
548
+ const urlTree = this.parseUrl(url);
549
+ return containsTree(this.currentUrlTree, urlTree, options);
550
+ }
551
+ removeEmptyProps(params) {
552
+ return Object.keys(params).reduce((result, key) => {
553
+ const value = params[key];
554
+ if (value !== null && value !== undefined) {
555
+ result[key] = value;
556
+ }
557
+ return result;
558
+ }, {});
559
+ }
560
+ /** @internal */
561
+ scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
562
+ if (this.disposed) {
563
+ return Promise.resolve(false);
564
+ }
565
+ let resolve;
566
+ let reject;
567
+ let promise;
568
+ if (priorPromise) {
569
+ resolve = priorPromise.resolve;
570
+ reject = priorPromise.reject;
571
+ promise = priorPromise.promise;
572
+ }
573
+ else {
574
+ promise = new Promise((res, rej) => {
575
+ resolve = res;
576
+ reject = rej;
577
+ });
578
+ }
579
+ let targetPageId;
580
+ if (this.canceledNavigationResolution === 'computed') {
581
+ // If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of
582
+ // `ɵrouterPageId`. This is the case for something like a page refresh where we assign the
583
+ // target id to the previously set value for that page.
584
+ if (restoredState && restoredState.ɵrouterPageId) {
585
+ targetPageId = restoredState.ɵrouterPageId;
586
+ }
587
+ else {
588
+ // If we're replacing the URL or doing a silent navigation, we do not want to increment the
589
+ // page id because we aren't pushing a new entry to history.
590
+ if (extras.replaceUrl || extras.skipLocationChange) {
591
+ targetPageId = this.browserPageId ?? 0;
592
+ }
593
+ else {
594
+ targetPageId = (this.browserPageId ?? 0) + 1;
595
+ }
596
+ }
597
+ }
598
+ else {
599
+ // This is unused when `canceledNavigationResolution` is not computed.
600
+ targetPageId = 0;
601
+ }
602
+ // Indicate that the navigation is happening.
603
+ const taskId = this.pendingTasks.add();
604
+ afterNextNavigation(this, () => {
605
+ // Remove pending task in a microtask to allow for cancelled
606
+ // initial navigations and redirects within the same task.
607
+ Promise.resolve().then(() => this.pendingTasks.remove(taskId));
608
+ });
609
+ this.navigationTransitions.handleNavigationRequest({
610
+ targetPageId,
611
+ source,
612
+ restoredState,
613
+ currentUrlTree: this.currentUrlTree,
614
+ currentRawUrl: this.currentUrlTree,
615
+ rawUrl,
616
+ extras,
617
+ resolve,
618
+ reject,
619
+ promise,
620
+ currentSnapshot: this.routerState.snapshot,
621
+ currentRouterState: this.routerState
622
+ });
623
+ // Make sure that the error is propagated even though `processNavigations` catch
624
+ // handler does not rethrow
625
+ return promise.catch((e) => {
626
+ return Promise.reject(e);
627
+ });
628
+ }
629
+ /** @internal */
630
+ setBrowserUrl(url, transition) {
631
+ const path = this.urlSerializer.serialize(url);
632
+ const state = {
633
+ ...transition.extras.state,
634
+ ...this.generateNgRouterState(transition.id, transition.targetPageId)
635
+ };
636
+ if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {
637
+ this.location.replaceState(path, '', state);
638
+ }
639
+ else {
640
+ this.location.go(path, '', state);
641
+ }
642
+ }
643
+ /**
644
+ * Performs the necessary rollback action to restore the browser URL to the
645
+ * state before the transition.
646
+ * @internal
647
+ */
648
+ restoreHistory(transition, restoringFromCaughtError = false) {
649
+ if (this.canceledNavigationResolution === 'computed') {
650
+ const targetPagePosition = this.currentPageId - transition.targetPageId;
651
+ // The navigator change the location before triggered the browser event,
652
+ // so we need to go back to the current url if the navigation is canceled.
653
+ // Also, when navigation gets cancelled while using url update strategy eager, then we need to
654
+ // go back. Because, when `urlUpdateStrategy` is `eager`; `setBrowserUrl` method is called
655
+ // before any verification.
656
+ const browserUrlUpdateOccurred = (transition.source === 'popstate' || this.urlUpdateStrategy === 'eager' ||
657
+ this.currentUrlTree === this.getCurrentNavigation()?.finalUrl);
658
+ if (browserUrlUpdateOccurred && targetPagePosition !== 0) {
659
+ this.location.historyGo(targetPagePosition);
660
+ }
661
+ else if (this.currentUrlTree === this.getCurrentNavigation()?.finalUrl &&
662
+ targetPagePosition === 0) {
663
+ // We got to the activation stage (where currentUrlTree is set to the navigation's
664
+ // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
665
+ // We still need to reset the router state back to what it was when the navigation started.
666
+ this.resetState(transition);
667
+ // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
668
+ // Investigate if this can be done by running TGP.
669
+ this.browserUrlTree = transition.currentUrlTree;
670
+ this.resetUrlToCurrentUrlTree();
671
+ }
672
+ else {
673
+ // The browser URL and router state was not updated before the navigation cancelled so
674
+ // there's no restoration needed.
675
+ }
676
+ }
677
+ else if (this.canceledNavigationResolution === 'replace') {
678
+ // TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op
679
+ // for `deferred` navigations that haven't change the internal state yet because guards
680
+ // reject. For 'eager' navigations, it seems like we also really should reset the state
681
+ // because the navigation was cancelled. Investigate if this can be done by running TGP.
682
+ if (restoringFromCaughtError) {
683
+ this.resetState(transition);
684
+ }
685
+ this.resetUrlToCurrentUrlTree();
686
+ }
687
+ }
688
+ resetState(t) {
689
+ this.routerState = t.currentRouterState;
690
+ this.currentUrlTree = t.currentUrlTree;
691
+ // Note here that we use the urlHandlingStrategy to get the reset `rawUrlTree` because it may be
692
+ // configured to handle only part of the navigation URL. This means we would only want to reset
693
+ // the part of the navigation handled by the Angular router rather than the whole URL. In
694
+ // addition, the URLHandlingStrategy may be configured to specifically preserve parts of the URL
695
+ // when merging, such as the query params so they are not lost on a refresh.
696
+ this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl);
697
+ }
698
+ resetUrlToCurrentUrlTree() {
699
+ this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
700
+ }
701
+ generateNgRouterState(navigationId, routerPageId) {
702
+ if (this.canceledNavigationResolution === 'computed') {
703
+ return { navigationId, ɵrouterPageId: routerPageId };
704
+ }
705
+ return { navigationId };
706
+ }
707
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: Router, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
708
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: Router, providedIn: 'root' }); }
709
+ }
710
+ export { Router };
711
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: Router, decorators: [{
712
+ type: Injectable,
713
+ args: [{ providedIn: 'root' }]
714
+ }], ctorParameters: function () { return []; } });
715
+ function validateCommands(commands) {
716
+ for (let i = 0; i < commands.length; i++) {
717
+ const cmd = commands[i];
718
+ if (cmd == null) {
719
+ throw new RuntimeError(4008 /* RuntimeErrorCode.NULLISH_COMMAND */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
720
+ `The requested path contains ${cmd} segment at index ${i}`);
721
+ }
722
+ }
723
+ }
724
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvcm91dGVyL3NyYy9yb3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBUSxRQUFRLElBQUksT0FBTyxFQUFFLDBCQUEwQixJQUFJLHlCQUF5QixFQUFFLGFBQWEsSUFBSSxZQUFZLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFHNUssT0FBTyxFQUFDLDJCQUEyQixFQUFFLDZCQUE2QixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDN0YsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBRXhELE9BQU8sRUFBUSxxQkFBcUIsRUFBb0IsTUFBTSxVQUFVLENBQUM7QUFFekUsT0FBTyxFQUFxRCxxQkFBcUIsRUFBb0MsTUFBTSx5QkFBeUIsQ0FBQztBQUNySixPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFDLGtCQUFrQixFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFDMUQsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDckQsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQzlDLE9BQU8sRUFBQyxnQkFBZ0IsRUFBYyxNQUFNLGdCQUFnQixDQUFDO0FBRTdELE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLHlCQUF5QixDQUFDO0FBQzVELE9BQU8sRUFBQyxZQUFZLEVBQXdCLFNBQVMsRUFBbUIsYUFBYSxFQUFFLE9BQU8sRUFBQyxNQUFNLFlBQVksQ0FBQztBQUNsSCxPQUFPLEVBQUMsaUJBQWlCLEVBQUUsY0FBYyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDakUsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0scUJBQXFCLENBQUM7O0FBSXhELFNBQVMsbUJBQW1CLENBQUMsS0FBVTtJQUNyQyxNQUFNLEtBQUssQ0FBQztBQUNkLENBQUM7QUFFRCxTQUFTLCtCQUErQixDQUNwQyxLQUFlLEVBQUUsYUFBNEIsRUFBRSxHQUFXO0lBQzVELE9BQU8sYUFBYSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNsQyxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQXlCO0lBQ3JELEtBQUssRUFBRSxPQUFPO0lBQ2QsUUFBUSxFQUFFLFNBQVM7SUFDbkIsWUFBWSxFQUFFLFNBQVM7SUFDdkIsV0FBVyxFQUFFLE9BQU87Q0FDckIsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUF5QjtJQUN0RCxLQUFLLEVBQUUsUUFBUTtJQUNmLFFBQVEsRUFBRSxTQUFTO0lBQ25CLFlBQVksRUFBRSxTQUFTO0lBQ3ZCLFdBQVcsRUFBRSxRQUFRO0NBQ3RCLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQ2EsTUFBTTtJQTJEakIsaUZBQWlGO0lBQ2pGLDBCQUEwQjtJQUMxQixJQUFZLFlBQVk7UUFDdEIsT0FBTyxJQUFJLENBQUMscUJBQXFCLENBQUMsWUFBWSxDQUFDO0lBQ2pELENBQUM7SUFXRDs7OztPQUlHO0lBQ0gsSUFBWSxhQUFhO1FBQ3ZCLE9BQVEsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQTJCLEVBQUUsYUFBYSxDQUFDO0lBQzNFLENBQUM7SUFJRDs7T0FFRztJQUNILElBQVcsTUFBTTtRQUNmLGdHQUFnRztRQUNoRyxvRkFBb0Y7UUFDcEYsZ0dBQWdHO1FBQ2hHLGNBQWM7UUFDZCxPQUFPLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUM7SUFDM0MsQ0FBQztJQXFKRDtRQTNMUSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBU3pCOzs7Ozs7O1dBT0c7UUFDSyxrQkFBYSxHQUFXLENBQUMsQ0FBQztRQVMxQixZQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFCLG9CQUFlLEdBQVksS0FBSyxDQUFDO1FBaUJqQyxZQUFPLEdBQUcsTUFBTSxDQUFDLG9CQUFvQixFQUFFLEVBQUMsUUFBUSxFQUFFLElBQUksRUFBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRS9ELGlCQUFZLEdBQUcsTUFBTSxDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFFekQ7Ozs7OztXQU1HO1FBQ0gsaUJBQVksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksSUFBSSxtQkFBbUIsQ0FBQztRQUVoRTs7Ozs7Ozs7O1dBU0c7UUFDSCw2QkFBd0IsR0FDcEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyx3QkFBd0IsSUFBSSwrQkFBK0IsQ0FBQztRQUU3RTs7O1dBR0c7UUFDSCxjQUFTLEdBQVksS0FBSyxDQUFDO1FBQ25CLHFCQUFnQixHQUFXLENBQUMsQ0FBQyxDQUFDO1FBRXRDOzs7Ozs7V0FNRztRQUNILHdCQUFtQixHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBRWxEOzs7OztXQUtHO1FBQ0gsdUJBQWtCLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFFaEQ7Ozs7O1dBS0c7UUFDSCxrQkFBYSxHQUFtQixNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFdEQ7Ozs7Ozs7O1dBUUc7UUFDSCx3QkFBbUIsR0FBd0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsSUFBSSxRQUFRLENBQUM7UUFFeEY7Ozs7Ozs7Ozs7Ozs7V0FhRztRQUNILDhCQUF5QixHQUNyQixJQUFJLENBQUMsT0FBTyxDQUFDLHlCQUF5QixJQUFJLFdBQVcsQ0FBQztRQUUxRDs7Ozs7Ozs7Ozs7V0FXRztRQUNILHNCQUFpQixHQUF1QixJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixJQUFJLFVBQVUsQ0FBQztRQUVyRjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztXQXlCRztRQUNILGlDQUE0QixHQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLDRCQUE0QixJQUFJLFNBQVMsQ0FBQztRQUUzRCxXQUFNLEdBQVcsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUUvQywwQkFBcUIsR0FBRyxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUN0RCxrQkFBYSxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN0QyxhQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRTdDOzs7OztXQUtHO1FBQ00saUNBQTRCLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsRUFBQyxRQUFRLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQztRQUcvRSxJQUFJLENBQUMsZUFBZSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxNQUFNLElBQUksTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRXBGLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNwQyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUM7UUFDdEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBRTFDLElBQUksQ0FBQyxXQUFXLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUUvRCxJQUFJLENBQUMscUJBQXFCLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUN2RCxDQUFDLENBQUMsRUFBRTtZQUNGLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxhQUFhLEdBQUcsQ0FBQyxDQUFDLFlBQVksQ0FBQztRQUN0QyxDQUFDLEVBQ0QsQ0FBQyxDQUFDLEVBQUU7WUFDRixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQywrQkFBK0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN4RCxDQUFDLENBQUMsQ0FBQztJQUNULENBQUM7SUFFRCxnQkFBZ0I7SUFDaEIsc0JBQXNCLENBQUMsaUJBQTRCO1FBQ2pELHNFQUFzRTtRQUN0RSxrREFBa0Q7UUFDbEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLGlCQUFpQixDQUFDO1FBQ3BELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQztJQUNuRSxDQUFDO0lBRUQ7O09BRUc7SUFDSCxpQkFBaUI7UUFDZixJQUFJLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztRQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLHNCQUFzQixFQUFFO1lBQ3RELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFtQixDQUFDO1lBQ3hELElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxxQkFBcUIsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUN4RjtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsMkJBQTJCO1FBQ3pCLHdEQUF3RDtRQUN4RCw2REFBNkQ7UUFDN0Qsa0JBQWtCO1FBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUU7WUFDOUIsSUFBSSxDQUFDLG9CQUFvQixHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUMxRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQztnQkFDeEUsSUFBSSxNQUFNLEtBQUssVUFBVSxFQUFFO29CQUN6QixrRkFBa0Y7b0JBQ2xGLGVBQWU7b0JBQ2YsVUFBVSxDQUFDLEdBQUcsRUFBRTt3QkFDZCxJQUFJLENBQUMseUJBQXlCLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3JFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztpQkFDUDtZQUNILENBQUMsQ0FBQyxDQUFDO1NBQ0o7SUFDSCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0sseUJBQXlCLENBQzdCLEdBQVcsRUFBRSxNQUF5QixFQUFFLEtBQThCO1FBQ3hFLE1BQU0sTUFBTSxHQUFxQixFQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUMsQ0FBQztRQUVwRCx5RUFBeUU7UUFDekUseUVBQXlFO1FBQ3pFLHlFQUF5RTtRQUN6RSx5RUFBeUU7UUFDekUsOEJBQThCO1FBRTlCLCtFQUErRTtRQUMvRSx5QkFBeUI7UUFDekIsTUFBTSxhQUFhLEdBQUcsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFFekQsK0VBQStFO1FBQy9FLDhFQUE4RTtRQUM5RSxJQUFJLEtBQUssRUFBRTtZQUNULE1BQU0sU0FBUyxHQUFHLEVBQUMsR0FBRyxLQUFLLEVBQTJCLENBQUM7WUFDdkQsT0FBTyxTQUFTLENBQUMsWUFBWSxDQUFDO1lBQzlCLE9BQU8sU0FBUyxDQUFDLGFBQWEsQ0FBQztZQUMvQixJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDdkMsTUFBTSxDQUFDLEtBQUssR0FBRyxTQUFTLENBQUM7YUFDMUI7U0FDRjtRQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFFRCx1QkFBdUI7SUFDdkIsSUFBSSxHQUFHO1FBQ0wsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsb0JBQW9CO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLHFCQUFxQixDQUFDLGlCQUFpQixDQUFDO0lBQ3RELENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUFJLHdCQUF3QjtRQUMxQixPQUFPLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyx3QkFBd0IsQ0FBQztJQUM3RCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0gsV0FBVyxDQUFDLE1BQWM7UUFDeEIsQ0FBQyxPQUFPLFNBQVMsS0FBSyxXQUFXLElBQUksU0FBUyxDQUFDLElBQUksY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFFLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzVDLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBRUQsYUFBYTtJQUNiLFdBQVc7UUFDVCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDakIsQ0FBQztJQUVELDhCQUE4QjtJQUM5QixPQUFPO1FBQ0wsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3RDLElBQUksSUFBSSxDQUFDLG9CQUFvQixFQUFFO1lBQzdCLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN4QyxJQUFJLENBQUMsb0JBQW9CLEdBQUcsU0FBUyxDQUFDO1NBQ3ZDO1FBQ0QsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7SUFDdkIsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQStDRztJQUNILGFBQWEsQ0FBQyxRQUFlLEVBQUUsbUJBQXVDLEVBQUU7UUFDdEUsTUFBTSxFQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLG1CQUFtQixFQUFFLGdCQUFnQixFQUFDLEdBQzVFLGdCQUFnQixDQUFDO1FBQ3JCLE1BQU0sQ0FBQyxHQUFHLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO1FBQ3JFLElBQUksQ0FBQyxHQUFnQixJQUFJLENBQUM7UUFDMUIsUUFBUSxtQkFBbUIsRUFBRTtZQUMzQixLQUFLLE9BQU87Z0JBQ1YsQ0FBQyxHQUFHLEVBQUMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxHQUFHLFdBQVcsRUFBQyxDQUFDO2dCQUN6RCxNQUFNO1lBQ1IsS0FBSyxVQUFVO2dCQUNiLENBQUMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQztnQkFDcEMsTUFBTTtZQUNSO2dCQUNFLENBQUMsR0FBRyxXQUFXLElBQUksSUFBSSxDQUFDO1NBQzNCO1FBQ0QsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFO1lBQ2QsQ0FBQyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUM5QjtRQUVELElBQUkseUJBQW9ELENBQUM7UUFDekQsSUFBSTtZQUNGLE1BQU0sa0JBQWtCLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7WUFDN0YseUJBQXlCLEdBQUcsMkJBQTJCLENBQUMsa0JBQWtCLENBQUMsQ0FBQztTQUM3RTtRQUFDLE9BQU8sQ0FBVSxFQUFFO1lBQ25CLHNFQUFzRTtZQUN0RSxrQ0FBa0M7WUFDbEMsNEZBQTRGO1lBQzVGLDRGQUE0RjtZQUM1RixjQUFjO1lBQ2QsSUFBSSxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFO2dCQUNuRSxxRUFBcUU7Z0JBQ3JFLDhEQUE4RDtnQkFDOUQsK0RBQStEO2dCQUMvRCxvRUFBb0U7Z0JBQ3BFLG9FQUFvRTtnQkFDcEUsb0ZBQW9GO2dCQUNwRixhQUFhO2dCQUNiLFFBQVEsR0FBRyxFQUFFLENBQUM7YUFDZjtZQUNELHlCQUF5QixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDO1NBQ3REO1FBQ0QsT0FBTyw2QkFBNkIsQ0FBQyx5QkFBeUIsRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFFLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQztJQUMxRixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BdUJHO0lBQ0gsYUFBYSxDQUFDLEdBQW1CLEVBQUUsU0FBb0M7UUFDckUsa0JBQWtCLEVBQUUsS0FBSztLQUMxQjtRQUNDLElBQUksT0FBTyxTQUFTLEtBQUssV0FBVyxJQUFJLFNBQVMsRUFBRTtZQUNqRCxJQUFJLElBQUksQ0FBQyxlQUFlLElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxFQUFFLEVBQUU7Z0JBQ3JELElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUNiLG1GQUFtRixDQUFDLENBQUM7YUFDMUY7U0FDRjtRQUVELE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUU1RSxPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxVQUFVLEVBQUUscUJBQXFCLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2xGLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0E2Qkc7SUFDSCxRQUFRLENBQUMsUUFBZSxFQUFFLFNBQTJCLEVBQUMsa0JBQWtCLEVBQUUsS0FBSyxFQUFDO1FBRTlFLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzNCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMxRSxDQUFDO0lBRUQsMkNBQTJDO0lBQzNDLFlBQVksQ0FBQyxHQUFZO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVELHVDQUF1QztJQUN2QyxRQUFRLENBQUMsR0FBVztRQUNsQixJQUFJLE9BQWdCLENBQUM7UUFDckIsSUFBSTtZQUNGLE9BQU8sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUN6QztRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsT0FBTyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxDQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsQ0FBQztTQUNqRjtRQUNELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFvQkQsUUFBUSxDQUFDLEdBQW1CLEVBQUUsWUFBMEM7UUFDdEUsSUFBSSxPQUE2QixDQUFDO1FBQ2xDLElBQUksWUFBWSxLQUFLLElBQUksRUFBRTtZQUN6QixPQUFPLEdBQUcsRUFBQyxHQUFHLGlCQUFpQixFQUFDLENBQUM7U0FDbEM7YUFBTSxJQUFJLFlBQVksS0FBSyxLQUFLLEVBQUU7WUFDakMsT0FBTyxHQUFHLEVBQUMsR0FBRyxrQkFBa0IsRUFBQyxDQUFDO1NBQ25DO2FBQU07WUFDTCxPQUFPLEdBQUcsWUFBWSxDQUFDO1NBQ3hCO1FBQ0QsSUFBSSxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDbEIsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7U0FDeEQ7UUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ25DLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxNQUFjO1FBQ3JDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFjLEVBQUUsR0FBVyxFQUFFLEVBQUU7WUFDaEUsTUFBTSxLQUFLLEdBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQy9CLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFO2dCQUN6QyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDO2FBQ3JCO1lBQ0QsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ1QsQ0FBQztJQUVELGdCQUFnQjtJQUNoQixrQkFBa0IsQ0FDZCxNQUFlLEVBQUUsTUFBeUIsRUFBRSxhQUFpQyxFQUM3RSxNQUF3QixFQUN4QixZQUFxRTtRQUN2RSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDakIsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQy9CO1FBRUQsSUFBSSxPQUFZLENBQUM7UUFDakIsSUFBSSxNQUFXLENBQUM7UUFDaEIsSUFBSSxPQUF5QixDQUFDO1FBQzlCLElBQUksWUFBWSxFQUFFO1lBQ2hCLE9BQU8sR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDO1lBQy9CLE1BQU0sR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDO1lBQzdCLE9BQU8sR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDO1NBQ2hDO2FBQU07WUFDTCxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQVUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUU7Z0JBQzFDLE9BQU8sR0FBRyxHQUFHLENBQUM7Z0JBQ2QsTUFBTSxHQUFHLEdBQUcsQ0FBQztZQUNmLENBQUMsQ0FBQyxDQUFDO1NBQ0o7UUFFRCxJQUFJLFlBQW9CLENBQUM7UUFDekIsSUFBSSxJQUFJLENBQUMsNEJBQTRCLEtBQUssVUFBVSxFQUFFO1lBQ3BELHlGQUF5RjtZQUN6RiwwRkFBMEY7WUFDMUYsdURBQXVEO1lBQ3ZELElBQUksYUFBYSxJQUFJLGFBQWEsQ0FBQyxhQUFhLEVBQUU7Z0JBQ2hELFlBQVksR0FBRyxhQUFhLENBQUMsYUFBYSxDQUFDO2FBQzVDO2lCQUFNO2dCQUNMLDJGQUEyRjtnQkFDM0YsNERBQTREO2dCQUM1RCxJQUFJLE1BQU0sQ0FBQyxVQUFVLElBQUksTUFBTSxDQUFDLGtCQUFrQixFQUFFO29CQUNsRCxZQUFZLEdBQUcsSUFBSSxDQUFDLGFBQWEsSUFBSSxDQUFDLENBQUM7aUJBQ3hDO3FCQUFNO29CQUNMLFlBQVksR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2lCQUM5QzthQUNGO1NBQ0Y7YUFBTTtZQUNMLHNFQUFzRTtZQUN0RSxZQUFZLEdBQUcsQ0FBQyxDQUFDO1NBQ2xCO1FBRUQsNkNBQTZDO1FBQzdDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkMsbUJBQW1CLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRTtZQUM3Qiw0REFBNEQ7WUFDNUQsMERBQTBEO1lBQzFELE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUNqRSxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxxQkFBcUIsQ0FBQyx1QkFBdUIsQ0FBQztZQUNqRCxZQUFZO1lBQ1osTUFBTTtZQUNOLGFBQWE7WUFDYixjQUFjLEVBQUUsSUFBSSxDQUFDLGNBQWM7WUFDbkMsYUFBYSxFQUFFLElBQUksQ0FBQyxjQUFjO1lBQ2xDLE1BQU07WUFDTixNQUFNO1lBQ04sT0FBTztZQUNQLE1BQU07WUFDTixPQUFPO1lBQ1AsZUFBZSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUTtZQUMxQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsV0FBVztTQUNyQyxDQUFDLENBQUM7UUFFSCxnRkFBZ0Y7UUFDaEYsMkJBQTJCO1FBQzNCLE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQU0sRUFBRSxFQUFFO1lBQzlCLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxnQkFBZ0I7SUFDaEIsYUFBYSxDQUFDLEdBQVksRUFBRSxVQUFnQztRQUMxRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMvQyxNQUFNLEtBQUssR0FBRztZQUNaLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxLQUFLO1lBQzFCLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLFlBQVksQ0FBQztTQUN0RSxDQUFDO1FBQ0YsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRTtZQUM5RSxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQzdDO2FBQU07WUFDTCxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ25DO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxjQUFjLENBQUMsVUFBZ0MsRUFBRSx3QkFBd0IsR0FBRyxLQUFLO1FBQy9FLElBQUksSUFBSSxDQUFDLDRCQUE0QixLQUFLLFVBQVUsRUFBRTtZQUNwRCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxhQUFhLEdBQUcsVUFBVSxDQUFDLFlBQVksQ0FBQztZQUN4RSx3RUFBd0U7WUFDeEUsMEVBQTBFO1lBQzFFLDhGQUE4RjtZQUM5RiwwRkFBMEY7WUFDMUYsMkJBQTJCO1lBQzNCLE1BQU0sd0JBQXdCLEdBQzFCLENBQUMsVUFBVSxDQUFDLE1BQU0sS0FBSyxVQUFVLElBQUksSUFBSSxDQUFDLGlCQUFpQixLQUFLLE9BQU87Z0JBQ3RFLElBQUksQ0FBQyxjQUFjLEtBQUssSUFBSSxDQUFDLG9CQUFvQixFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDcEUsSUFBSSx3QkFBd0IsSUFBSSxrQkFBa0IsS0FBSyxDQUFDLEVBQUU7Z0JBQ3hELElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLENBQUM7YUFDN0M7aUJBQU0sSUFDSCxJQUFJLENBQUMsY0FBYyxLQUFLLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxFQUFFLFFBQVE7Z0JBQzdELGtCQUFrQixLQUFLLENBQUMsRUFBRTtnQkFDNUIsa0ZBQWtGO2dCQUNsRiwyRkFBMkY7Z0JBQzNGLDJGQUEyRjtnQkFDM0YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDNUIsdUZBQXVGO2dCQUN2RixrREFBa0Q7Z0JBQ2xELElBQUksQ0FBQyxjQUFjLEdBQUcsVUFBVSxDQUFDLGNBQWMsQ0FBQztnQkFDaEQsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7YUFDakM7aUJBQU07Z0JBQ0wsc0ZBQXNGO2dCQUN0RixpQ0FBaUM7YUFDbEM7U0FDRjthQUFNLElBQUksSUFBSSxDQUFDLDRCQUE0QixLQUFLLFNBQVMsRUFBRTtZQUMxRCw0RkFBNEY7WUFDNUYsdUZBQXVGO1lBQ3ZGLHVGQUF1RjtZQUN2Rix3RkFBd0Y7WUFDeEYsSUFBSSx3QkFBd0IsRUFBRTtnQkFDNUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUM3QjtZQUNELElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1NBQ2pDO0lBQ0gsQ0FBQztJQUVPLFVBQVUsQ0FBQyxDQUF1QjtRQUN2QyxJQUFtQyxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsa0JBQWtCLENBQUM7UUFDeEUsSUFBSSxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUMsY0FBYyxDQUFDO1FBQ3ZDLGdHQUFnRztRQUNoRywrRkFBK0Y7UUFDL0YseUZBQXlGO1FBQ3pGLGdHQUFnRztRQUNoRyw0RUFBNEU7UUFDNUUsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xGLENBQUM7SUFFTyx3QkFBd0I7UUFDOUIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQ3RCLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQ2pELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDN0UsQ0FBQztJQUVPLHFCQUFxQixDQUFDLFlBQW9CLEVBQUUsWUFBcUI7UUFDdkUsSUFBSSxJQUFJLENBQUMsNEJBQTRCLEtBQUssVUFBVSxFQUFFO1lBQ3BELE9BQU8sRUFBQyxZQUFZLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBQyxDQUFDO1NBQ3BEO1FBQ0QsT0FBTyxFQUFDLFlBQVksRUFBQyxDQUFDO0lBQ3hCLENBQUM7eUhBaHhCVSxNQUFNOzZIQUFOLE1BQU0sY0FETSxNQUFNOztTQUNsQixNQUFNO3NHQUFOLE1BQU07a0JBRGxCLFVBQVU7bUJBQUMsRUFBQyxVQUFVLEVBQUUsTUFBTSxFQUFDOztBQW94QmhDLFNBQVMsZ0JBQWdCLENBQUMsUUFBa0I7SUFDMUMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDeEMsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hCLElBQUksR0FBRyxJQUFJLElBQUksRUFBRTtZQUNmLE1BQU0sSUFBSSxZQUFZLDhDQUVsQixDQUFDLE9BQU8sU0FBUyxLQUFLLFdBQVcsSUFBSSxTQUFTLENBQUM7Z0JBQzNDLCtCQUErQixHQUFHLHFCQUFxQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ3JFO0tBQ0Y7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7TG9jYXRpb259IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge2luamVjdCwgSW5qZWN0YWJsZSwgTmdab25lLCBUeXBlLCDJtUNvbnNvbGUgYXMgQ29uc29sZSwgybVJbml0aWFsUmVuZGVyUGVuZGluZ1Rhc2tzIGFzIEluaXRpYWxSZW5kZXJQZW5kaW5nVGFza3MsIMm1UnVudGltZUVycm9yIGFzIFJ1bnRpbWVFcnJvcn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge09ic2VydmFibGUsIG9mLCBTdWJzY3JpcHRpb25MaWtlfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHtjcmVhdGVTZWdtZW50R3JvdXBGcm9tUm91dGUsIGNyZWF0ZVVybFRyZWVGcm9tU2VnbWVudEdyb3VwfSBmcm9tICcuL2NyZWF0ZV91cmxfdHJlZSc7XG5pbXBvcnQge0lOUFVUX0JJTkRFUn0gZnJvbSAnLi9kaXJlY3RpdmVzL3JvdXRlcl9vdXRsZXQnO1xuaW1wb3J0IHtSdW50aW1lRXJyb3JDb2RlfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQge0V2ZW50LCBJTVBFUkFUSVZFX05BVklHQVRJT04sIE5hdmlnYXRpb25UcmlnZ2VyfSBmcm9tICcuL2V2ZW50cyc7XG5pbXBvcnQge05hdmlnYXRpb25CZWhhdmlvck9wdGlvbnMsIE9uU2FtZVVybE5hdmlnYXRpb24sIFJvdXRlc30gZnJvbSAnLi9tb2RlbHMnO1xuaW1wb3J0IHtOYXZpZ2F0aW9uLCBOYXZpZ2F0aW9uRXh0cmFzLCBOYXZpZ2F0aW9uVHJhbnNpdGlvbiwgTmF2aWdhdGlvblRyYW5zaXRpb25zLCBSZXN0b3JlZFN0YXRlLCBVcmxDcmVhdGlvbk9wdGlvbnN9IGZyb20gJy4vbmF2aWdhdGlvbl90cmFuc2l0aW9uJztcbmltcG9ydCB7VGl0bGVTdHJhdGVneX0gZnJvbSAnLi9wYWdlX3RpdGxlX3N0cmF0ZWd5JztcbmltcG9ydCB7Um91dGVSZXVzZVN0cmF0ZWd5fSBmcm9tICcuL3JvdXRlX3JldXNlX3N0cmF0ZWd5JztcbmltcG9ydCB7Uk9VVEVSX0NPTkZJR1VSQVRJT059IGZyb20gJy4vcm91dGVyX2NvbmZpZyc7XG5pbXBvcnQge1JPVVRFU30gZnJvbSAnLi9yb3V0ZXJfY29uZmlnX2xvYWRlcic7XG5pbXBvcnQge2NyZWF0ZUVtcHR5U3RhdGUsIFJvdXRlclN0YXRlfSBmcm9tICcuL3JvdXRlcl9zdGF0ZSc7XG5pbXBvcnQge1BhcmFtc30gZnJvbSAnLi9zaGFyZWQnO1xuaW1wb3J0IHtVcmxIYW5kbGluZ1N0cmF0ZWd5fSBmcm9tICcuL3VybF9oYW5kbGluZ19zdHJhdGVneSc7XG5pbXBvcnQge2NvbnRhaW5zVHJlZSwgSXNBY3RpdmVNYXRjaE9wdGlvbnMsIGlzVXJsVHJlZSwgVXJsU2VnbWVudEdyb3VwLCBVcmxTZXJpYWxpemVyLCBVcmxUcmVlfSBmcm9tICcuL3VybF90cmVlJztcbmltcG9ydCB7c3RhbmRhcmRpemVDb25maWcsIHZhbGlkYXRlQ29uZmlnfSBmcm9tICcuL3V0aWxzL2NvbmZpZyc7XG5pbXBvcnQge2FmdGVyTmV4dE5hdmlnYXRpb259IGZyb20gJy4vdXRpbHMvbmF2aWdhdGlvbnMnO1xuXG5cblxuZnVuY3Rpb24gZGVmYXVsdEVycm9ySGFuZGxlcihlcnJvcjogYW55KTogYW55IHtcbiAgdGhyb3cgZXJyb3I7XG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRNYWxmb3JtZWRVcmlFcnJvckhhbmRsZXIoXG4gICAgZXJyb3I6IFVSSUVycm9yLCB1cmxTZXJpYWxpemVyOiBVcmxTZXJpYWxpemVyLCB1cmw6IHN0cmluZyk6IFVybFRyZWUge1xuICByZXR1cm4gdXJsU2VyaWFsaXplci5wYXJzZSgnLycpO1xufVxuXG4vKipcbiAqIFRoZSBlcXVpdmFsZW50IGBJc0FjdGl2ZU1hdGNoT3B0aW9uc2Agb3B0aW9ucyBmb3IgYFJvdXRlci5pc0FjdGl2ZWAgaXMgY2FsbGVkIHdpdGggYHRydWVgXG4gKiAoZXhhY3QgPSB0cnVlKS5cbiAqL1xuZXhwb3J0IGNvbnN0IGV4YWN0TWF0Y2hPcHRpb25zOiBJc0FjdGl2ZU1hdGNoT3B0aW9ucyA9IHtcbiAgcGF0aHM6ICdleGFjdCcsXG4gIGZyYWdtZW50OiAnaWdub3JlZCcsXG4gIG1hdHJpeFBhcmFtczogJ2lnbm9yZWQnLFxuICBxdWVyeVBhcmFtczogJ2V4YWN0J1xufTtcblxuLyoqXG4gKiBUaGUgZXF1aXZhbGVudCBgSXNBY3RpdmVNYXRjaE9wdGlvbnNgIG9wdGlvbnMgZm9yIGBSb3V0ZXIuaXNBY3RpdmVgIGlzIGNhbGxlZCB3aXRoIGBmYWxzZWBcbiAqIChleGFjdCA9IGZhbHNlKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHN1YnNldE1hdGNoT3B0aW9uczogSXNBY3RpdmVNYXRjaE9wdGlvbnMgPSB7XG4gIHBhdGhzOiAnc3Vic2V0JyxcbiAgZnJhZ21lbnQ6ICdpZ25vcmVkJyxcbiAgbWF0cml4UGFyYW1zOiAnaWdub3JlZCcsXG4gIHF1ZXJ5UGFyYW1zOiAnc3Vic2V0J1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqXG4gKiBBIHNlcnZpY2UgdGhhdCBwcm92aWRlcyBuYXZpZ2F0aW9uIGFtb25nIHZpZXdzIGFuZCBVUkwgbWFuaXB1bGF0aW9uIGNhcGFiaWxpdGllcy5cbiAqXG4gKiBAc2VlIGBSb3V0ZWAuXG4gKiBAc2VlIFtSb3V0aW5nIGFuZCBOYXZpZ2F0aW9uIEd1aWRlXShndWlkZS9yb3V0ZXIpLlxuICpcbiAqIEBuZ01vZHVsZSBSb3V0ZXJNb2R1bGVcbiAqXG4gKiBAcHVibGljQXBpXG4gKi9cbkBJbmplY3RhYmxlKHtwcm92aWRlZEluOiAncm9vdCd9KVxuZXhwb3J0IGNsYXNzIFJvdXRlciB7XG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIHRoZSBhY3RpdmF0ZWQgYFVybFRyZWVgIHRoYXQgdGhlIGBSb3V0ZXJgIGlzIGNvbmZpZ3VyZWQgdG8gaGFuZGxlICh0aHJvdWdoXG4gICAqIGBVcmxIYW5kbGluZ1N0cmF0ZWd5YCkuIFRoYXQgaXMsIGFmdGVyIHdlIGZpbmQgdGhlIHJvdXRlIGNvbmZpZyB0cmVlIHRoYXQgd2UncmUgZ29pbmcgdG9cbiAgICogYWN0aXZhdGUsIHJ1biBndWFyZHMsIGFuZCBhcmUganVzdCBhYm91dCB0byBhY3RpdmF0ZSB0aGUgcm91dGUsIHdlIHNldCB0aGUgY3VycmVudFVybFRyZWUuXG4gICAqXG4gICAqIFRoaXMgc2hvdWxkIG1hdGNoIHRoZSBgYnJvd3NlclVybFRyZWVgIHdoZW4gYSBuYXZpZ2F0aW9uIHN1Y2NlZWRzLiBJZiB0aGVcbiAgICogYFVybEhhbmRsaW5nU3RyYXRlZ3kuc2hvdWxkUHJvY2Vzc1VybGAgaXMgYGZhbHNlYCwgb25seSB0aGUgYGJyb3dzZXJVcmxUcmVlYCBpcyB1cGRhdGVkLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIGN1cnJlbnRVcmxUcmVlOiBVcmxUcmVlO1xuICAvKipcbiAgICogTWVhbnQgdG8gcmVwcmVzZW50IHRoZSBlbnRpcmUgYnJvd3NlciB1cmwgYWZ0ZXIgYSBzdWNjZXNzZnVsIG5hdmlnYXRpb24uIEluIHRoZSBsaWZlIG9mIGFcbiAgICogbmF2aWdhdGlvbiB0cmFuc2l0aW9uOlxuICAgKiAxLiBUaGUgcmF3VXJsIHJlcHJlc2VudHMgdGhlIGZ1bGwgVVJMIHRoYXQncyBiZWluZyBuYXZpZ2F0ZWQgdG9cbiAgICogMi4gV2UgYXBwbHkgcmVkaXJlY3RzLCB3aGljaCBtaWdodCBvbmx5IGFwcGx5IHRvIF9wYXJ0XyBvZiB0aGUgVVJMIChkdWUgdG9cbiAgICogYFVybEhhbmRsaW5nU3RyYXRlZ3lgKS5cbiAgICogMy4gUmlnaHQgYmVmb3JlIGFjdGl2YXRpb24gKGJlY2F1c2Ugd2UgYXNzdW1lIGFjdGl2YXRpb24gd2lsbCBzdWNjZWVkKSwgd2UgdXBkYXRlIHRoZVxuICAgKiByYXdVcmxUcmVlIHRvIGJlIGEgY29tYmluYXRpb24gb2YgdGhlIHVybEFmdGVyUmVkaXJlY3RzIChhZ2FpbiwgdGhpcyBtaWdodCBvbmx5IGFwcGx5IHRvIHBhcnRcbiAgICogb2YgdGhlIGluaXRpYWwgdXJsKSBhbmQgdGhlIHJhd1VybCBvZiB0aGUgdHJhbnNpdGlvbiAod2hpY2ggd2FzIHRoZSBvcmlnaW5hbCBuYXZpZ2F0aW9uIHVybCBpblxuICAgKiBpdHMgZnVsbCBmb3JtKS5cbiAgICogQGludGVybmFsXG4gICAqXG4gICAqIE5vdGUgdGhhdCB0aGlzIGlzIF9vbmx5XyBoZXJlIHRvIHN1cHBvcnQgYFVybEhhbmRsaW5nU3RyYXRlZ3kuZXh0cmFjdGAgYW5kXG4gICAqIGBVcmxIYW5kbGluZ1N0cmF0ZWd5LnNob3VsZFByb2Nlc3NVcmxgLiBJZiB0aG9zZSBkaWRuJ3QgZXhpc3QsIHdlIGNvdWxkIGdldCBieSB3aXRoXG4gICAqIGBjdXJyZW50VXJsVHJlZWAgYWxvbmUuIElmIGEgbmV3IFJvdXRlciB3ZXJlIHRvIGJlIHByb3ZpZGVkIChpLmUuIG9uZSB0aGF0IHdvcmtzIHdpdGggdGhlXG4gICAqIGJyb3dzZXIgbmF2aWdhdGlvbiBBUEkpLCB3ZSBzaG91bGQgdGhpbmsgYWJvdXQgd2hldGhlciB0aGlzIGNvbXBsZXhpdHkgc2hvdWxkIGJlIGNhcnJpZWQgb3Zlci5cbiAgICpcbiAgICogLSBleHRyYWN0OiBgcmF3VXJsVHJlZWAgaXMgbmVlZGVkIGJlY2F1c2UgYGV4dHJhY3RgIG1heSBvbmx5IHJldHVybiBwYXJ0XG4gICAqIG9mIHRoZSBuYXZpZ2F0aW9uIFVSTC4gVGh1cywgYGN1cnJlbnRVcmxUcmVlYCBtYXkgb25seSByZXByZXNlbnQgX3BhcnRfIG9mIHRoZSBicm93c2VyIFVSTC5cbiAgICogV2hlbiBhIG5hdmlnYXRpb24gZ2V0cyBjYW5jZWxsZWQgYW5kIHdlIG5lZWQgdG8gcmVzZXQgdGhlIFVSTCBvciBhIG5ldyBuYXZpZ2F0aW9uIG9jY3Vycywgd2VcbiAgICogbmVlZCB0byBrbm93IHRoZSBfd2hvbGVfIGJyb3dzZXIgVVJMLCBub3QganVzdCB0aGUgcGFydCBoYW5kbGVkIGJ5IFVybEhhbmRsaW5nU3RyYXRlZ3kuXG4gICAqIC0gc2hvdWxkUHJvY2Vzc1VybDogV2hlbiB0aGlzIHJldHVybnMgYGZhbHNlYCwgdGhlIHJvdXRlciBqdXN0IGlnbm9yZXMgdGhlIG5hdmlnYXRpb24gYnV0IHN0aWxsXG4gICAqIHVwZGF0ZXMgdGhlIGByYXdVcmxUcmVlYCB3aXRoIHRoZSBhc3N1bXB0aW9uIHRoYXQgdGhlIG5hdmlnYXRpb24gd2FzIGNhdXNlZCBieSB0aGUgbG9jYXRpb25cbiAgICogY2hhbmdlIGxpc3RlbmVyIGR1ZSB0byBhIFVSTCB1cGRhdGUgYnkgdGhlIEFuZ3VsYXJKUyByb3V0ZXIuIEluIHRoaXMgY2FzZSwgd2Ugc3RpbGwgbmVlZCB0b1xuICAgKiBrbm93IHdoYXQgdGhlIGJyb3dzZXIncyBVUkwgaXMgZm9yIGZ1dHVyZSBuYXZpZ2F0aW9ucy5cbiAgICpcbiAgICovXG4gIHJhd1VybFRyZWU6IFVybFRyZWU7XG4gIC8qKlxuICAgKiBNZWFudCB0byByZXByZXNlbnQgdGhlIHBhcnQgb2YgdGhlIGJyb3dzZXIgdXJsIHRoYXQgdGhlIGBSb3V0ZXJgIGlzIHNldCB1cCB0byBoYW5kbGUgKHZpYSB0aGVcbiAgICogYFVybEhhbmRsaW5nU3RyYXRlZ3lgKS4gVGhpcyB2YWx1ZSBpcyB1cGRhdGVkIGltbWVkaWF0ZWx5IGFmdGVyIHRoZSBicm93c2VyIHVybCBpcyB1cGRhdGVkIChvclxuICAgKiB0aGUgYnJvd3NlciB1cmwgdXBkYXRlIGlzIHNraXBwZWQgdmlhIGBza2lwTG9jYXRpb25DaGFuZ2VgKS4gV2l0aCB0aGF0LCBub3RlIHRoYXRcbiAgICogYGJyb3dzZXJVcmxUcmVlYCBfbWF5IG5vdF8gcmVmbGVjdCB0aGUgYWN0dWFsIGJyb3dzZXIgVVJMIGZvciB0d28gcmVhc29uczpcbiAgICpcbiAgICogMS4gYFVybEhhbmRsaW5nU3RyYXRlZ3lgIG9ubHkgaGFuZGxlcyBwYXJ0IG9mIHRoZSBVUkxcbiAgICogMi4gYHNraXBMb2NhdGlvbkNoYW5nZWAgZG9lcyBub3QgdXBkYXRlIHRoZSBicm93c2VyIHVybC5cbiAgICpcbiAgICogU28gdG8gcmVpdGVyYXRlLCBgYnJvd3NlclVybFRyZWVgIG9ubHkgcmVwcmVzZW50cyB0aGUgUm91dGVyJ3MgaW50ZXJuYWwgdW5kZXJzdGFuZGluZyBvZiB0aGVcbiAgICogY3VycmVudCByb3V0ZSwgZWl0aGVyIGJlZm9yZSBndWFyZHMgd2l0aCBgdXJsVXBkYXRlU3RyYXRlZ3kgPT09ICdlYWdlcidgIG9yIHJpZ2h0IGJlZm9yZVxuICAgKiBhY3RpdmF0aW9uIHdpdGggYCdkZWZlcnJlZCdgLlxuICAgKlxuICAgKiBUaGlzIHNob3VsZCBtYXRjaCB0aGUgYGN1cnJlbnRVcmxUcmVlYCB3aGVuIHRoZSBuYXZpZ2F0aW9uIHN1Y2NlZWRzLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIGJyb3dzZXJVcmxUcmVlOiBVcmxUcmVlO1xuICBwcml2YXRlIGRpc3Bvc2VkID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBsb2NhdGlvblN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbkxpa2U7XG4gIC8vIFRPRE8oYi8yNjA3NDcwODMpOiBUaGlzIHNob3VsZCBub3QgZXhpc3QgYW5kIG5hdmlnYXRpb25JZCBzaG91bGQgYmUgcHJpdmF0ZSBpblxuICAvLyBgTmF2aWdhdGlvblRyYW5zaXRpb25zYFxuICBwcml2YXRlIGdldCBuYXZpZ2F0aW9uSWQoKSB7XG4gICAgcmV0dXJuIHRoaXMubmF2aWdhdGlvblRyYW5zaXRpb25zLm5hdmlnYXRpb25JZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaWQgb2YgdGhlIGN1cnJlbnRseSBhY3RpdmUgcGFnZSBpbiB0aGUgcm91dGVyLlxuICAgKiBVcGRhdGVkIHRvIHRoZSB0cmFuc2l0aW9uJ3MgdGFyZ2V0IGlkIG9uIGEgc3VjY2Vzc2Z1bCBuYXZpZ2F0aW9uLlxuICAgKlxuICAgKiBUaGlzIGlzIHVzZWQgdG8gdHJhY2sgd2hhdCBwYWdlIHRoZSByb3V0ZXIgbGFzdCBhY3RpdmF0ZWQuIFdoZW4gYW4gYXR0ZW1wdGVkIG5hdmlnYXRpb24gZmFpbHMsXG4gICAqIHRoZSByb3V0ZXIgY2FuIHRoZW4gdXNlIHRoaXMgdG8gY29tcHV0ZSBob3cgdG8gcmVzdG9yZSB0aGUgc3RhdGUgYmFjayB0byB0aGUgcHJldmlvdXNseSBhY3RpdmVcbiAgICogcGFnZS5cbiAgICovXG4gIHByaXZhdGUgY3VycmVudFBhZ2VJZDogbnVtYmVyID0gMDtcbiAgLyoqXG4gICAqIFRoZSDJtXJvdXRlclBhZ2VJZCBvZiB3aGF0ZXZlciBwYWdlIGlzIGN1cnJlbnRseSBhY3RpdmUgaW4gdGhlIGJyb3dzZXIgaGlzdG9yeS4gVGhpcyBpc1xuICAgKiBpbXBvcnRhbnQgZm9yIGNvbXB1dGluZyB0aGUgdGFyZ2V0IHBhZ2UgaWQgZm9yIG5ldyBuYXZpZ2F0aW9ucyBiZWNhdXNlIHdlIG5lZWQgdG8gZW5zdXJlIGVhY2hcbiAgICogcGFnZSBpZCBpbiB0aGUgYnJvd3NlciBoaXN0b3J5IGlzIDEgbW9yZSB0aGFuIHRoZSBwcmV2aW91cyBlbnRyeS5cbiAgICovXG4gIHByaXZhdGUgZ2V0IGJyb3dzZXJQYWdlSWQoKTogbnVtYmVyfHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuICh0aGlzLmxvY2F0aW9uLmdldFN0YXRlKCkgYXMgUmVzdG9yZWRTdGF0ZSB8IG51bGwpPy7JtXJvdXRlclBhZ2VJZDtcbiAgfVxuICBwcml2YXRlIGNvbnNvbGUgPSBpbmplY3QoQ29uc29sZSk7XG4gIHByaXZhdGUgaXNOZ1pvbmVFbmFibGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEFuIGV2ZW50IHN0cmVhbSBmb3Igcm91dGluZyBldmVudHMuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGV2ZW50cygpOiBPYnNlcnZhYmxlPEV2ZW50PiB7XG4gICAgLy8gVE9ETyhhdHNjb3R0KTogVGhpcyBfc2hvdWxkXyBiZSBldmVudHMuYXNPYnNlcnZhYmxlKCkuIEhvd2V2ZXIsIHRoaXMgY2hhbmdlIHJlcXVpcmVzIGludGVybmFsXG4gICAgLy8gY2xlYW51cDogdGVzdHMgYXJlIGRvaW5nIGAocm91dGUuZXZlbnRzIGFzIFN1YmplY3Q8RXZlbnQ+KS5uZXh0KC4uLilgLiBUaGlzIGlzbid0XG4gICAgLy8gYWxsb3dlZC9zdXBwb3J0ZWQgYnV0IHdlIHN0aWxsIGhhdmUgdG8gZml4IHRoZXNlIG9yIGZpbGUgYnVncyBhZ2FpbnN0IHRoZSB0ZWFtcyBiZWZvcmUgbWFraW5nXG4gICAgLy8gdGhlIGNoYW5nZS5cbiAgICByZXR1cm4gdGhpcy5uYXZpZ2F0aW9uVHJhbnNpdGlvbnMuZXZlbnRzO1xuICB9XG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCBzdGF0ZSBvZiByb3V0aW5nIGluIHRoaXMgTmdNb2R1bGUuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcm91dGVyU3RhdGU6IFJvdXRlclN0YXRlO1xuXG4gIHByaXZhdGUgb3B0aW9ucyA9IGluamVjdChST1VURVJfQ09ORklHVVJBVElPTiwge29wdGlvbmFsOiB0cnVlfSkgfHwge307XG5cbiAgcHJpdmF0ZSBwZW5kaW5nVGFza3MgPSBpbmplY3QoSW5pdGlhbFJlbmRlclBlbmRpbmdUYXNrcyk7XG5cbiAgLyoqXG4gICAqIEEgaGFuZGxlciBmb3IgbmF2aWdhdGlvbiBlcnJvcnMgaW4gdGhpcyBOZ01vZHVsZS5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgU3Vic2NyaWJlIHRvIHRoZSBgUm91dGVyYCBldmVudHMgYW5kIHdhdGNoIGZvciBgTmF2aWdhdGlvbkVycm9yYCBpbnN0ZWFkLlxuICAgKiAgIGBwcm92aWRlUm91dGVyYCBoYXMgdGhlIGB3aXRoTmF2aWdhdGlvbkVycm9ySGFuZGxlcmAgZmVhdHVyZSB0byBtYWtlIHRoaXMgZWFzaWVyLlxuICAgKiBAc2VlIGB3aXRoTmF2aWdhdGlvbkVycm9ySGFuZGxlcmBcbiAgICovXG4gIGVycm9ySGFuZGxlciA9IHRoaXMub3B0aW9ucy5lcnJvckhhbmRsZXIgfHwgZGVmYXVsdEVycm9ySGFuZGxlcjtcblxuICAvKipcbiAgICogQSBoYW5kbGVyIGZvciBlcnJvcnMgdGhyb3duIGJ5IGBSb3V0ZXIucGFyc2VVcmwodXJsKWBcbiAgICogd2hlbiBgdXJsYCBjb250YWlucyBhbiBpbnZhbGlkIGNoYXJhY3Rlci5cbiAgICogVGhlIG1vc3QgY29tbW9uIGNhc2UgaXMgYSBgJWAgc2lnblxuICAgKiB0aGF0J3Mgbm90IGVuY29kZWQgYW5kIGlzIG5vdCBwYXJ0IG9mIGEgcGVyY2VudCBlbmNvZGVkIHNlcXVlbmNlLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBVUkkgcGFyc2luZyBlcnJvcnMgc2hvdWxkIGJlIGhhbmRsZWQgaW4gdGhlIGBVcmxTZXJpYWxpemVyYC5cbiAgICpcbiAgICogQHNlZSBgUm91dGVyTW9kdWxlYFxuICAgKi9cbiAgbWFsZm9ybWVkVXJpRXJyb3JIYW5kbGVyID1cbiAgICAgIHRoaXMub3B0aW9ucy5tYWxmb3JtZWRVcmlFcnJvckhhbmRsZXIgfHwgZGVmYXVsdE1hbGZvcm1lZFVyaUVycm9ySGFuZGxlcjtcblxuICAvKipcbiAgICogVHJ1ZSBpZiBhdCBsZWFzdCBvbmUgbmF2aWdhdGlvbiBldmVudCBoYXMgb2NjdXJyZWQsXG4gICAqIGZhbHNlIG90aGVyd2lzZS5cbiAgICovXG4gIG5hdmlnYXRlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBwcml2YXRlIGxhc3RTdWNjZXNzZnVsSWQ6IG51bWJlciA9IC0xO1xuXG4gIC8qKlxuICAgKiBBIHN0cmF0ZWd5IGZvciBleHRyYWN0aW5nIGFuZCBtZXJnaW5nIFVSTHMuXG4gICAqIFVzZWQgZm9yIEFuZ3VsYXJKUyB0byBBbmd1bGFyIG1pZ3JhdGlvbnMuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIENvbmZpZ3VyZSB1c2luZyBgcHJvdmlkZXJzYCBpbnN0ZWFkOlxuICAgKiAgIGB7cHJvdmlkZTogVXJsSGFuZGxpbmdTdHJhdGVneSwgdXNlQ2xhc3M6IE15U3RyYXRlZ3l9YC5cbiAgICovXG4gIHVybEhhbmRsaW5nU3RyYXRlZ3kgPSBpbmplY3QoVXJsSGFuZGxpbmdTdHJhdGVneSk7XG5cbiAgLyoqXG4gICAqIEEgc3RyYXRlZ3kgZm9yIHJlLXVzaW5nIHJvdXRlcy5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgQ29uZmlndXJlIHVzaW5nIGBwcm92aWRlcnNgIGluc3RlYWQ6XG4gICAqICAgYHtwcm92aWRlOiBSb3V0ZVJldXNlU3RyYXRlZ3ksIHVzZUNsYXNzOiBNeVN0cmF0ZWd5fWAuXG4gICAqL1xuICByb3V0ZVJldXNlU3RyYXRlZ3kgPSBpbmplY3QoUm91dGVSZXVzZVN0cmF0ZWd5KTtcblxuICAvKipcbiAgICogQSBzdHJhdGVneSBmb3Igc2V0dGluZyB0aGUgdGl0bGUgYmFzZWQgb24gdGhlIGByb3V0ZXJTdGF0ZWAuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIENvbmZpZ3VyZSB1c2luZyBgcHJvdmlkZXJzYCBpbnN0ZWFkOlxuICAgKiAgIGB7cHJvdmlkZTogVGl0bGVTdHJhdGVneSwgdXNlQ2xhc3M6IE15U3RyYXRlZ3l9YC5cbiAgICovXG4gIHRpdGxlU3RyYXRlZ3k/OiBUaXRsZVN0cmF0ZWd5ID0gaW5qZWN0KFRpdGxlU3RyYXRlZ3kpO1xuXG4gIC8qKlxuICAgKiBIb3cgdG8gaGFuZGxlIGEgbmF2aWdhdGlvbiByZXF1ZXN0IHRvIHRoZSBjdXJyZW50IFVSTC5cbiAgICpcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgQ29uZmlndXJlIHRoaXMgdGhyb3VnaCBgcHJvdmlkZVJvdXRlcmAgb3IgYFJvdXRlck1vZHVsZS5mb3JSb290YCBpbnN0ZWFkLlxuICAgKiBAc2VlIGB3aXRoUm91dGVyQ29uZmlnYFxuICAgKiBAc2VlIGBwcm92aWRlUm91dGVyYFxuICAgKiBAc2VlIGBSb3V0ZXJNb2R1bGVgXG4gICAqL1xuICBvblNhbWVVcmxOYXZpZ2F0aW9uOiBPblNhbWVVcmxOYXZpZ2F0aW9uID0gdGhpcy5vcHRpb25zLm9uU2FtZVVybE5hdmlnYXRpb24gfHwgJ2lnbm9yZSc7XG5cbiAgLyoqXG4gICAqIEhvdyB0byBtZXJnZSBwYXJhbWV0ZXJzLCBkYXRhLCByZXNvbHZlZCBkYXRhLCBhbmQgdGl0bGUgZnJvbSBwYXJlbnQgdG8gY2hpbGRcbiAgICogcm91dGVzLiBPbmUgb2Y6XG4gICAqXG4gICAqIC0gYCdlbXB0eU9ubHknYCA6IEluaGVyaXQgcGFyZW50IHBhcmFtZXRlcnMsIGRhdGEsIGFuZCByZXNvbHZlZCBkYXRhXG4gICAqIGZvciBwYXRoLWxlc3Mgb3IgY29tcG9uZW50LWxlc3Mgcm91dGVzLlxuICAgKiAtIGAnYWx3YXlzJ2AgOiBJbmhlcml0IHBhcmVudCBwYXJhbWV0ZXJzLCBkYXRhLCBhbmQgcmVzb2x2ZWQgZGF0YVxuICAgKiBmb3IgYWxsIGNoaWxkIHJvdXRlcy5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgQ29uZmlndXJlIHRoaXMgdGhyb3VnaCBgcHJvdmlkZVJvdXRlcmAgb3IgYFJvdXRlck1vZHVsZS5mb3JSb290YCBpbnN0ZWFkLlxuICAgKiBAc2VlIGB3aXRoUm91dGVyQ29uZmlnYFxuICAgKiBAc2VlIGBwcm92aWRlUm91dGVyYFxuICAgKiBAc2VlIGBSb3V0ZXJNb2R1bGVgXG4gICAqL1xuICBwYXJhbXNJbmhlcml0YW5jZVN0cmF0ZWd5OiAnZW1wdHlPbmx5J3wnYWx3YXlzJyA9XG4gICAgICB0aGlzLm9wdGlvbnMucGFyYW1zSW5oZXJpdGFuY2VTdHJhdGVneSB8fCAnZW1wdHlPbmx5JztcblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB3aGVuIHRoZSByb3V0ZXIgdXBkYXRlcyB0aGUgYnJvd3NlciBVUkwuXG4gICAqIEJ5IGRlZmF1bHQgKGBcImRlZmVycmVkXCJgKSwgdXBkYXRlcyB0aGUgYnJvd3NlciBVUkwgYWZ0ZXIgbmF2aWdhdGlvbiBoYXMgZmluaXNoZWQuXG4gICAqIFNldCB0byBgJ2VhZ2VyJ2AgdG8gdXBkYXRlIHRoZSBicm93c2VyIFVSTCBhdCB0aGUgYmVnaW5uaW5nIG9mIG5hdmlnYXRpb24uXG4gICAqIFlvdSBjYW4gY2hvb3NlIHRvIHVwZGF0ZSBlYXJseSBzbyB0aGF0LCBpZiBuYXZpZ2F0aW9uIGZhaWxzLFxuICAgKiB5b3UgY2FuIHNob3cgYW4gZXJyb3IgbWVzc2FnZSB3aXRoIHRoZSBVUkwgdGhhdCBmYWlsZWQuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIENvbmZpZ3VyZSB0aGlzIHRocm91Z2ggYHByb3ZpZGVSb3V0ZXJgIG9yIGBSb3V0ZXJNb2R1bGUuZm9yUm9vdGAgaW5zdGVhZC5cbiAgICogQHNlZSBgd2l0aFJvdXRlckNvbmZpZ2BcbiAgICogQHNlZSBgcHJvdmlkZVJvdXRlcmBcbiAgICogQHNlZSBgUm91dGVyTW9kdWxlYFxuICAgKi9cbiAgdXJsVXBkYXRlU3RyYXRlZ3k6ICdkZWZlcnJlZCd8J2VhZ2VyJyA9IHRoaXMub3B0aW9ucy51cmxVcGRhdGVTdHJhdGVneSB8fCAnZGVmZXJyZWQnO1xuXG4gIC8qKlxuICAgKiBDb25maWd1cmVzIGhvdyB0aGUgUm91dGVyIGF0dGVtcHRzIHRvIHJlc3RvcmUgc3RhdGUgd2hlbiBhIG5hdmlnYXRpb24gaXMgY2FuY2VsbGVkLlxuICAgKlxuICAgKiAncmVwbGFjZScgLSBBbHdheXMgdXNlcyBgbG9jYXRpb24ucmVwbGFjZVN0YXRlYCB0byBzZXQgdGhlIGJyb3dzZXIgc3RhdGUgdG8gdGhlIHN0YXRlIG9mIHRoZVxuICAgKiByb3V0ZXIgYmVmb3JlIHRoZSBuYXZpZ2F0aW9uIHN0YXJ0ZWQuIFRoaXMgbWVhbnMgdGhhdCBpZiB0aGUgVVJMIG9mIHRoZSBicm93c2VyIGlzIHVwZGF0ZWRcbiAgICogX2JlZm9yZV8gdGhlIG5hdmlnYXRpb24gaXMgY2FuY2VsZWQsIHRoZSBSb3V0ZXIgd2lsbCBzaW1wbHkgcmVwbGFjZSB0aGUgaXRlbSBpbiBoaXN0b3J5IHJhdGhlclxuICAgKiB0aGFuIHRyeWluZyB0byByZXN0b3JlIHRvIHRoZSBwcmV2aW91cyBsb2NhdGlvbiBpbiB0aGUgc2Vzc2lvbiBoaXN0b3J5LiBUaGlzIGhhcHBlbnMgbW9zdFxuICAgKiBmcmVxdWVudGx5IHdpdGggYHVybFVwZGF0ZVN0cmF0ZWd5OiAnZWFnZXInYCBhbmQgbmF2aWdhdGlvbnMgd2l0aCB0aGUgYnJvd3NlciBiYWNrL2ZvcndhcmRcbiAgICogYnV0dG9ucy5cbiAgICpcbiAgICogJ2NvbXB1dGVkJyAtIFdpbGwgYXR0ZW1wdCB0byByZXR1cm4gdG8gdGhlIHNhbWUgaW5kZXggaW4gdGhlIHNlc3Npb24gaGlzdG9yeSB0aGF0IGNvcnJlc3BvbmRzXG4gICAqIHRvIHRoZSBBbmd1bGFyIHJvdXRlIHdoZW4gdGhlIG5hdmlnYXRpb24gZ2V0cyBjYW5jZWxsZWQuIEZvciBleGFtcGxlLCBpZiB0aGUgYnJvd3NlciBiYWNrXG4gICAqIGJ1dHRvbiBpcyBjbGlja2VkIGFuZCB0aGUgbmF2aWdhdGlvbiBpcyBjYW5jZWxsZWQsIHRoZSBSb3V0ZXIgd2lsbCB0cmlnZ2VyIGEgZm9yd2FyZCBuYXZpZ2F0aW9uXG4gICAqIGFuZCB2aWNlIHZlcnNhLlxuICAgKlxuICAgKiBOb3RlOiB0aGUgJ2NvbXB1dGVkJyBvcHRpb24gaXMgaW5jb21wYXRpYmxlIHdpdGggYW55IGBVcmxIYW5kbGluZ1N0cmF0ZWd5YCB3aGljaCBvbmx5XG4gICAqIGhhbmRsZXMgYSBwb3J0aW9uIG9mIHRoZSBVUkwgYmVjYXVzZSB0aGUgaGlzdG9yeSByZXN0b3JhdGlvbiBuYXZpZ2F0ZXMgdG8gdGhlIHByZXZpb3VzIHBsYWNlIGluXG4gICAqIHRoZSBicm93c2VyIGhpc3RvcnkgcmF0aGVyIHRoYW4gc2ltcGx5IHJlc2V0dGluZyBhIHBvcnRpb24gb2YgdGhlIFVSTC5cbiAgICpcbiAgICogVGhlIGRlZmF1bHQgdmFsdWUgaXMgYHJlcGxhY2VgLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBDb25maWd1cmUgdGhpcyB0aHJvdWdoIGBwcm92aWRlUm91dGVyYCBvciBgUm91dGVyTW9kdWxlLmZvclJvb3RgIGluc3RlYWQuXG4gICAqIEBzZWUgYHdpdGhSb3V0ZXJDb25maWdgXG4gICAqIEBzZWUgYHByb3ZpZGVSb3V0ZXJgXG4gICAqIEBzZWUgYFJvdXRlck1vZHVsZWBcbiAgICovXG4gIGNhbmNlbGVkTmF2aWdhdGlvblJlc29sdXRpb246ICdyZXBsYWNlJ3wnY29tcHV0ZWQnID1cbiAgICAgIHRoaXMub3B0aW9ucy5jYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uIHx8ICdyZXBsYWNlJztcblxuICBjb25maWc6IFJvdXRlcyA9IGluamVjdChST1VURVMsIHtvcHRpb25hbDogdHJ1ZX0pPy5mbGF0KCkgPz8gW107XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuYXZpZ2F0aW9uVHJhbnNpdGlvbnMgPSBpbmplY3QoTmF2aWdhdGlvblRyYW5zaXRpb25zKTtcbiAgcHJpdmF0ZSByZWFkb25seSB1cmxTZXJpYWxpemVyID0gaW5qZWN0KFVybFNlcmlhbGl6ZXIpO1xuICBwcml2YXRlIHJlYWRvbmx5IGxvY2F0aW9uID0gaW5qZWN0KExvY2F0aW9uKTtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdGhlIHRoZSBhcHBsaWNhdGlvbiBoYXMgb3B0ZWQgaW4gdG8gYmluZGluZyBSb3V0ZXIgZGF0YSB0byBjb21wb25lbnQgaW5wdXRzLlxuICAgKlxuICAgKiBUaGlzIG9wdGlvbiBpcyBlbmFibGVkIGJ5IHRoZSBgd2l0aENvbXBvbmVudElucHV0QmluZGluZ2AgZmVhdHVyZSBvZiBgcHJvdmlkZVJvdXRlcmAgb3JcbiAgICogYGJpbmRUb0NvbXBvbmVudElucHV0c2AgaW4gdGhlIGBFeHRyYU9wdGlvbnNgIG9mIGBSb3V0ZXJNb2R1bGUuZm9yUm9vdGAuXG4gICAqL1xuICByZWFkb25seSBjb21wb25lbnRJbnB1dEJpbmRpbmdFbmFibGVkID0gISFpbmplY3QoSU5QVVRfQklOREVSLCB7b3B0aW9uYWw6IHRydWV9KTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmlzTmdab25lRW5hYmxlZCA9IGluamVjdChOZ1pvbmUpIGluc3RhbmNlb2YgTmdab25lICYmIE5nWm9uZS5pc0luQW5ndWxhclpvbmUoKTtcblxuICAgIHRoaXMucmVzZXRDb25maWcodGhpcy5jb25maWcpO1xuICAgIHRoaXMuY3VycmVudFVybFRyZWUgPSBuZXcgVXJsVHJlZSgpO1xuICAgIHRoaXMucmF3VXJsVHJlZSA9IHRoaXMuY3VycmVudFVybFRyZWU7XG4gICAgdGhpcy5icm93c2VyVXJsVHJlZSA9IHRoaXMuY3VycmVudFVybFRyZWU7XG5cbiAgICB0aGlzLnJvdXRlclN0YXRlID0gY3JlYXRlRW1wdHlTdGF0ZSh0aGlzLmN1cnJlbnRVcmxUcmVlLCBudWxsKTtcblxuICAgIHRoaXMubmF2aWdhdGlvblRyYW5zaXRpb25zLnNldHVwTmF2aWdhdGlvbnModGhpcykuc3Vic2NyaWJlKFxuICAgICAgICB0ID0+IHtcbiAgICAgICAgICB0aGlzLmxhc3RTdWNjZXNzZnVsSWQgPSB0LmlkO1xuICAgICAgICAgIHRoaXMuY3VycmVudFBhZ2VJZCA9IHQudGFyZ2V0UGFnZUlkO1xuICAgICAgICB9LFxuICAgICAgICBlID0+IHtcbiAgICAgICAgICB0aGlzLmNvbnNvbGUud2FybihgVW5oYW5kbGVkIE5hdmlnYXRpb24gRXJyb3I6ICR7ZX1gKTtcbiAgICAgICAgfSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHJlc2V0Um9vdENvbXBvbmVudFR5cGUocm9vdENvbXBvbmVudFR5cGU6IFR5cGU8YW55Pik6IHZvaWQge1xuICAgIC8vIFRPRE86IHZzYXZraW4gcm91dGVyIDQuMCBzaG91bGQgbWFrZSB0aGUgcm9vdCBjb21wb25lbnQgc2V0IHRvIG51bGxcbiAgICAvLyB0aGlzIHdpbGwgc2ltcGxpZnkgdGhlIGxpZmVjeWNsZSBvZiB0aGUgcm91dGVyLlxuICAgIHRoaXMucm91dGVyU3RhdGUucm9vdC5jb21wb25lbnQgPSByb290Q29tcG9uZW50VHlwZTtcbiAgICB0aGlzLm5hdmlnYXRpb25UcmFuc2l0aW9ucy5yb290Q29tcG9uZW50VHlwZSA9IHJvb3RDb21wb25lbnRUeXBlO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdXAgdGhlIGxvY2F0aW9uIGNoYW5nZSBsaXN0ZW5lciBhbmQgcGVyZm9ybXMgdGhlIGluaXRpYWwgbmF2aWdhdGlvbi5cbiAgICovXG4gIGluaXRpYWxOYXZpZ2F0aW9uKCk6IHZvaWQge1xuICAgIHRoaXMuc2V0VXBMb2NhdGlvbkNoYW5nZUxpc3RlbmVyKCk7XG4gICAgaWYgKCF0aGlzLm5hdmlnYXRpb25UcmFuc2l0aW9ucy5oYXNSZXF1ZXN0ZWROYXZpZ2F0aW9uKSB7XG4gICAgICBjb25zdCBzdGF0ZSA9IHRoaXMubG9jYXRpb24uZ2V0U3RhdGUoKSBhcyBSZXN0b3JlZFN0YXRlO1xuICAgICAgdGhpcy5uYXZpZ2F0ZVRvU3luY1dpdGhCcm93c2VyKHRoaXMubG9jYXRpb24ucGF0aCh0cnVlKSwgSU1QRVJBVElWRV9OQVZJR0FUSU9OLCBzdGF0ZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdXAgdGhlIGxvY2F0aW9uIGNoYW5nZSBsaXN0ZW5lci4gVGhpcyBsaXN0ZW5lciBkZXRlY3RzIG5hdmlnYXRpb25zIHRyaWdnZXJlZCBmcm9tIG91dHNpZGVcbiAgICogdGhlIFJvdXRlciAodGhlIGJyb3dzZXIgYmFjay9mb3J3YXJkIGJ1dHRvbnMsIGZvciBleGFtcGxlKSBhbmQgc2NoZWR1bGVzIGEgY29ycmVzcG9uZGluZyBSb3V0ZXJcbiAgICogbmF2aWdhdGlvbiBzbyB0aGF0IHRoZSBjb3JyZWN0IGV2ZW50cywgZ3VhcmRzLCBldGMuIGFyZSB0cmlnZ2VyZWQuXG4gICAqL1xuICBzZXRVcExvY2F0aW9uQ2hhbmdlTGlzdGVuZXIoKTogdm9pZCB7XG4gICAgLy8gRG9uJ3QgbmVlZCB0byB1c2UgWm9uZS53cmFwIGFueSBtb3JlLCBiZWNhdXNlIHpvbmUuanNcbiAgICAvLyBhbHJlYWR5IHBhdGNoIG9uUG9wU3RhdGUsIHNvIGxvY2F0aW9uIGNoYW5nZSBjYWxsYmFjayB3aWxsXG4gICAgLy8gcnVuIGludG8gbmdab25lXG4gICAgaWYgKCF0aGlzLmxvY2F0aW9uU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLmxvY2F0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5sb2NhdGlvbi5zdWJzY3JpYmUoZXZlbnQgPT4ge1xuICAgICAgICBjb25zdCBzb3VyY2UgPSBldmVudFsndHlwZSddID09PSAncG9wc3RhdGUnID8gJ3BvcHN0YXRlJyA6ICdoYXNoY2hhbmdlJztcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gJ3BvcHN0YXRlJykge1xuICAgICAgICAgIC8vIFRoZSBgc2V0VGltZW91dGAgd2FzIGFkZGVkIGluICMxMjE2MCBhbmQgaXMgbGlrZWx5IHRvIHN1cHBvcnQgQW5ndWxhci9Bbmd1bGFySlNcbiAgICAgICAgICAvLyBoeWJyaWQgYXBwcy5cbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMubmF2aWdhdGVUb1N5bmNXaXRoQnJvd3NlcihldmVudFsndXJsJ10hLCBzb3VyY2UsIGV2ZW50LnN0YXRlKTtcbiAgICAgICAgICB9LCAwKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNjaGVkdWxlcyBhIHJvdXRlciBuYXZpZ2F0aW9uIHRvIHN5bmNocm9uaXplIFJvdXRlciBzdGF0ZSB3aXRoIHRoZSBicm93c2VyIHN0YXRlLlxuICAgKlxuICAgKiBUaGlzIGlzIGRvbmUgYXMgYSByZXNwb25zZSB0byBhIHBvcHN0YXRlIGV2ZW50IGFuZCB0aGUgaW5pdGlhbCBuYXZpZ2F0aW9uLiBUaGVzZVxuICAgKiB0d28gc2NlbmFyaW9zIHJlcHJlc2VudCB0aW1lcyB3aGVuIHRoZSBicm93c2VyIFVSTC9zdGF0ZSBoYXMgYmVlbiB1cGRhdGVkIGFuZFxuICAgKiB0aGUgUm91dGVyIG5lZWRzIHRvIHJlc3BvbmQgdG8gZW5zdXJlIGl0cyBpbnRlcm5hbCBzdGF0ZSBtYXRjaGVzLlxuICAgKi9cbiAgcHJpdmF0ZSBuYXZpZ2F0ZVRvU3luY1dpdGhCcm93c2VyKFxuICAgICAgdXJsOiBzdHJpbmcsIHNvdXJjZTogTmF2aWdhdGlvblRyaWdnZXIsIHN0YXRlOiBSZXN0b3JlZFN0YXRlfHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IGV4dHJhczogTmF2aWdhdGlvbkV4dHJhcyA9IHtyZXBsYWNlVXJsOiB0cnVlfTtcblxuICAgIC8vIFRPRE86IHJlc3RvcmVkU3RhdGUgc2hvdWxkIGFsd2F5cyBpbmNsdWRlIHRoZSBlbnRpcmUgc3RhdGUsIHJlZ2FyZGxlc3NcbiAgICAvLyBvZiBuYXZpZ2F0aW9uSWQuIFRoaXMgcmVxdWlyZXMgYSBicmVha2luZyBjaGFuZ2UgdG8gdXBkYXRlIHRoZSB0eXBlIG9uXG4gICAgLy8gTmF2aWdhdGlvblN0YXJ04oCZcyByZXN0b3JlZFN0YXRlLCB3aGljaCBjdXJyZW50bHkgcmVxdWlyZXMgbmF2aWdhdGlvbklkXG4gICAgLy8gdG8gYWx3YXlzIGJlIHByZXNlbnQuIFRoZSBSb3V0ZXIgdXNlZCB0byBvbmx5IHJlc3RvcmUgaGlzdG9yeSBzdGF0ZSBpZlxuICAgIC8vIGEgbmF2aWdhdGlvbklkIHdhcyBwcmVzZW50LlxuXG4gICAgLy8gVGhlIHN0b3JlZCBuYXZpZ2F0aW9uSWQgaXMgdXNlZCBieSB0aGUgUm91dGVyU2Nyb2xsZXIgdG8gcmV0cmlldmUgdGhlIHNjcm9sbFxuICAgIC8vIHBvc2l0aW9uIGZvciB0aGUgcGFnZS5cbiAgICBjb25zdCByZXN0b3JlZFN0YXRlID0gc3RhdGU/Lm5hdmlnYXRpb25JZCA/IHN0YXRlIDogbnVsbDtcblxuICAgIC8vIFNlcGFyYXRlIHRvIE5hdmlnYXRpb25TdGFydC5yZXN0b3JlZFN0YXRlLCB3ZSBtdXN0IGFsc28gcmVzdG9yZSB0aGUgc3RhdGUgdG9cbiAgICAvLyBoaXN0b3J5LnN0YXRlIGFuZCBnZW5lcmF0ZSBhIG5ldyBuYXZpZ2F0aW9uSWQsIHNpbmNlIGl0IHdpbGwgYmUgb3ZlcndyaXR0ZW5cbiAgICBpZiAoc3RhdGUpIHtcbiAgICAgIGNvbnN0IHN0YXRlQ29weSA9IHsuLi5zdGF0ZX0gYXMgUGFydGlhbDxSZXN0b3JlZFN0YXRlPjtcbiAgICAgIGRlbGV0ZSBzdGF0ZUNvcHkubmF2aWdhdGlvbklkO1xuICAgICAgZGVsZXRlIHN0YXRlQ29weS7JtXJvdXRlclBhZ2VJZDtcbiAgICAgIGlmIChPYmplY3Qua2V5cyhzdGF0ZUNvcHkpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICBleHRyYXMuc3RhdGUgPSBzdGF0ZUNvcHk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdXJsVHJlZSA9IHRoaXMucGFyc2VVcmwodXJsKTtcbiAgICB0aGlzLnNjaGVkdWxlTmF2aWdhdGlvbih1cmxUcmVlLCBzb3VyY2UsIHJlc3RvcmVkU3RhdGUsIGV4dHJhcyk7XG4gIH1cblxuICAvKiogVGhlIGN1cnJlbnQgVVJMLiAqL1xuICBnZXQgdXJsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc2VyaWFsaXplVXJsKHRoaXMuY3VycmVudFVybFRyZWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgYE5hdmlnYXRpb25gIG9iamVjdCB3aGVuIHRoZSByb3V0ZXIgaXMgbmF2aWdhdGluZyxcbiAgICogYW5kIGBudWxsYCB3aGVuIGlkbGUuXG4gICAqL1xuICBnZXRDdXJyZW50TmF2aWdhdGlvbigpOiBOYXZpZ2F0aW9ufG51bGwge1xuICAgIHJldHVybiB0aGlzLm5hdmlnYXRpb25UcmFuc2l0aW9ucy5jdXJyZW50TmF2aWdhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYE5hdmlnYXRpb25gIG9iamVjdCBvZiB0aGUgbW9zdCByZWNlbnQgbmF2aWdhdGlvbiB0byBzdWNjZWVkIGFuZCBgbnVsbGAgaWYgdGhlcmVcbiAgICogICAgIGhhcyBub3QgYmVlbiBhIHN1Y2Nlc3NmdWwgbmF2aWdhdGlvbiB5ZXQuXG4gICAqL1xuICBnZXQgbGFzdFN1Y2Nlc3NmdWxOYXZpZ2F0aW9uKCk6IE5hdmlnYXRpb258bnVsbCB7XG4gICAgcmV0dXJuIHRoaXMubmF2aWdhdGlvblRyYW5zaXRpb25zLmxhc3RTdWNjZXNzZnVsTmF2aWdhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldHMgdGhlIHJvdXRlIGNvbmZpZ3VyYXRpb24gdXNlZCBmb3IgbmF2aWdhdGlvbiBhbmQgZ2VuZXJhdGluZyBsaW5rcy5cbiAgICpcbiAgICogQHBhcmFtIGNvbmZpZyBUaGUgcm91dGUgYXJyYXkgZm9yIHRoZSBuZXcgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogQHVzYWdlTm90ZXNcbiAgICpcbiAgICogYGBgXG4gICAqIHJvdXRlci5yZXNldENvbmZpZyhbXG4gICAqICB7IHBhdGg6ICd0ZWFtLzppZCcsIGNvbXBvbmVudDogVGVhbUNtcCwgY2hpbGRyZW46IFtcbiAgICogICAgeyBwYXRoOiAnc2ltcGxlJywgY29tcG9uZW50OiBTaW1wbGVDbXAgfSxcbiAgICogICAgeyBwYXRoOiAndXNlci86bmFtZScsIGNvbXBvbmVudDogVXNlckNtcCB9XG4gICAqICBdfVxuICAgKiBdKTtcbiAgICogYGBgXG4gICAqL1xuICByZXNldENvbmZpZyhjb25maWc6IFJvdXRlcyk6IHZvaWQge1xuICAgICh0eXBlb2YgbmdEZXZNb2RlID09PSAndW5kZWZpbmVkJyB8fCBuZ0Rldk1vZGUpICYmIHZhbGlkYXRlQ29uZmlnKGNvbmZpZyk7XG4gICAgdGhpcy5jb25maWcgPSBjb25maWcubWFwKHN0YW5kYXJkaXplQ29uZmlnKTtcbiAgICB0aGlzLm5hdmlnYXRlZCA9IGZhbHNlO1xuICAgIHRoaXMubGFzdFN1Y2Nlc3NmdWxJZCA9IC0xO1xuICB9XG5cbiAgLyoqIEBub2RvYyAqL1xuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmRpc3Bvc2UoKTtcbiAgfVxuXG4gIC8qKiBEaXNwb3NlcyBvZiB0aGUgcm91dGVyLiAqL1xuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMubmF2aWdhdGlvblRyYW5zaXRpb25zLmNvbXBsZXRlKCk7XG4gICAgaWYgKHRoaXMubG9jYXRpb25TdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMubG9jYXRpb25TdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgIHRoaXMubG9jYXRpb25TdWJzY3JpcHRpb24gPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZHMgVVJMIHNlZ21lbnRzIHRvIHRoZSBjdXJyZW50IFVSTCB0cmVlIHRvIGNyZWF0ZSBhIG5ldyBVUkwgdHJlZS5cbiAgICpcbiAgICogQHBhcmFtIGNvbW1hbmRzIEFuIGFycmF5IG9mIFVSTCBmcmFnbWVudHMgd2l0aCB3aGljaCB0byBjb25zdHJ1Y3QgdGhlIG5ldyBVUkwgdHJlZS5cbiAgICogSWYgdGhlIHBhdGggaXMgc3RhdGljLCBjYW4gYmUgdGhlIGxpdGVyYWwgVVJMIHN0cmluZy4gRm9yIGEgZHluYW1pYyBwYXRoLCBwYXNzIGFuIGFycmF5IG9mIHBhdGhcbiAgICogc2VnbWVudHMsIGZvbGxvd2VkIGJ5IHRoZSBwYXJhbWV0ZXJzIGZvciBlYWNoIHNlZ21lbnQuXG4gICAqIFRoZSBmcmFnbWVudHMgYXJlIGFwcGxpZWQgdG8gdGhlIGN1cnJlbnQgVVJMIHRyZWUgb3IgdGhlIG9uZSBwcm92aWRlZCAgaW4gdGhlIGByZWxhdGl2ZVRvYFxuICAgKiBwcm9wZXJ0eSBvZiB0aGUgb3B0aW9ucyBvYmplY3QsIGlmIHN1cHBsaWVkLlxuICAgKiBAcGFyYW0gbmF2aWdhdGlvbkV4dHJhcyBPcHRpb25zIHRoYXQgY29udHJvbCB0aGUgbmF2aWdhdGlvbiBzdHJhdGVneS5cbiAgICogQHJldHVybnMgVGhlIG5ldyBVUkwgdHJlZS5cbiAgICpcbiAgICogQHVzYWdlTm90ZXNcbiAgICpcbiAgICogYGBgXG4gICAqIC8vIGNyZWF0ZSAvdGVhbS8zMy91c2VyLzExXG4gICAqIHJvdXRlci5jcmVhdGVVcmxUcmVlKFsnL3RlYW0nLCAzMywgJ3VzZXInLCAxMV0pO1xuICAgKlxuICAgKiAvLyBjcmVhdGUgL3RlYW0vMzM7ZXhwYW5kPXRydWUvdXNlci8xMVxuICAgKiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbJy90ZWFtJywgMzMsIHtleHBhbmQ6IHRydWV9LCAndXNlcicsIDExXSk7XG4gICAqXG4gICAqIC8vIHlvdSBjYW4gY29sbGFwc2Ugc3RhdGljIHNlZ21lbnRzIGxpa2UgdGhpcyAodGhpcyB3b3JrcyBvbmx5IHdpdGggdGhlIGZpcnN0IHBhc3NlZC1pbiB2YWx1ZSk6XG4gICAqIHJvdXRlci5jcmVhdGVVcmxUcmVlKFsnL3RlYW0vMzMvdXNlcicsIHVzZXJJZF0pO1xuICAgKlxuICAgKiAvLyBJZiB0aGUgZmlyc3Qgc2VnbWVudCBjYW4gY29udGFpbiBzbGFzaGVzLCBhbmQgeW91IGRvIG5vdCB3YW50IHRoZSByb3V0ZXIgdG8gc3BsaXQgaXQsXG4gICAqIC8vIHlvdSBjYW4gZG8gdGhlIGZvbGxvd2luZzpcbiAgICogcm91dGVyLmNyZWF0ZVVybFRyZWUoW3tzZWdtZW50UGF0aDogJy9vbmUvdHdvJ31dKTtcbiAgICpcbiAgICogLy8gY3JlYXRlIC90ZWFtLzMzLyh1c2VyLzExLy9yaWdodDpjaGF0KVxuICAgKiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbJy90ZWFtJywgMzMsIHtvdXRsZXRzOiB7cHJpbWFyeTogJ3VzZXIvMTEnLCByaWdodDogJ2NoYXQnfX1dKTtcbiAgICpcbiAgICogLy8gcmVtb3ZlIHRoZSByaWdodCBzZWNvbmRhcnkgbm9kZVxuICAgKiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbJy90ZWFtJywgMzMsIHtvdXRsZXRzOiB7cHJpbWFyeTogJ3VzZXIvMTEnLCByaWdodDogbnVsbH19XSk7XG4gICAqXG4gICAqIC8vIGFzc3VtaW5nIHRoZSBjdXJyZW50IHVybCBpcyBgL3RlYW0vMzMvdXNlci8xMWAgYW5kIHRoZSByb3V0ZSBwb2ludHMgdG8gYHVzZXIvMTFgXG4gICAqXG4gICAqIC8vIG5hdmlnYXRlIHRvIC90ZWFtLzMzL3VzZXIvMTEvZGV0YWlsc1xuICAgKiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbJ2RldGFpbHMnXSwge3JlbGF0aXZlVG86IHJvdXRlfSk7XG4gICAqXG4gICAqIC8vIG5hdmlnYXRlIHRvIC90ZWFtLzMzL3VzZXIvMjJcbiAgICogcm91dGVyLmNyZWF0ZVVybFRyZWUoWycuLi8yMiddLCB7cmVsYXRpdmVUbzogcm91dGV9KTtcbiAgICpcbiAgICogLy8gbmF2aWdhdGUgdG8gL3RlYW0vNDQvdXNlci8yMlxuICAgKiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbJy4uLy4uL3RlYW0vNDQvdXNlci8yMiddLCB7cmVsYXRpdmVUbzogcm91dGV9KTtcbiAgICpcbiAgICogTm90ZSB0aGF0IGEgdmFsdWUgb2YgYG51bGxgIG9yIGB1bmRlZmluZWRgIGZvciBgcmVsYXRpdmVUb2AgaW5kaWNhdGVzIHRoYXQgdGhlXG4gICAqIHRyZWUgc2hvdWxkIGJlIGNyZWF0ZWQgcmVsYXRpdmUgdG8gdGhlIHJvb3QuXG4gICAqIGBgYFxuICAgKi9cbiAgY3JlYXRlVXJsVHJlZShjb21tYW5kczogYW55W10sIG5hdmlnYXRpb25FeHRyYXM6IFVybENyZWF0aW9uT3B0aW9ucyA9IHt9KTogVXJsVHJlZSB7XG4gICAgY29uc3Qge3JlbGF0aXZlVG8sIHF1ZXJ5UGFyYW1zLCBmcmFnbWVudCwgcXVlcnlQYXJhbXNIYW5kbGluZywgcHJlc2VydmVGcmFnbWVudH0gPVxuICAgICAgICBuYXZpZ2F0aW9uRXh0cmFzO1xuICAgIGNvbnN0IGYgPSBwcmVzZXJ2ZUZyYWdtZW50ID8gdGhpcy5jdXJyZW50VXJsVHJlZS5mcmFnbWVudCA6IGZyYWdtZW50O1xuICAgIGxldCBxOiBQYXJhbXN8bnVsbCA9IG51bGw7XG4gICAgc3dpdGNoIChxdWVyeVBhcmFtc0hhbmRsaW5nKSB7XG4gICAgICBjYXNlICdtZXJnZSc6XG4gICAgICAgIHEgPSB7Li4udGhpcy5jdXJyZW50VXJsVHJlZS5xdWVyeVBhcmFtcywgLi4ucXVlcnlQYXJhbXN9O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3ByZXNlcnZlJzpcbiAgICAgICAgcSA9IHRoaXMuY3VycmVudFVybFRyZWUucXVlcnlQYXJhbXM7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcSA9IHF1ZXJ5UGFyYW1zIHx8IG51bGw7XG4gICAgfVxuICAgIGlmIChxICE9PSBudWxsKSB7XG4gICAgICBxID0gdGhpcy5yZW1vdmVFbXB0eVByb3BzKHEpO1xuICAgIH1cblxuICAgIGxldCByZWxhdGl2ZVRvVXJsU2VnbWVudEdyb3VwOiBVcmxTZWdtZW50R3JvdXB8dW5kZWZpbmVkO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZWxhdGl2ZVRvU25hcHNob3QgPSByZWxhdGl2ZVRvID8gcmVsYXRpdmVUby5zbmFwc2hvdCA6IHRoaXMucm91dGVyU3RhdGUuc25hcHNob3Qucm9vdDtcbiAgICAgIHJlbGF0aXZlVG9VcmxTZWdtZW50R3JvdXAgPSBjcmVhdGVTZWdtZW50R3JvdXBGcm9tUm91dGUocmVsYXRpdmVUb1NuYXBzaG90KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAvLyBUaGlzIGlzIHN0cmljdGx5IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSB3aXRoIHRlc3RzIHRoYXQgY3JlYXRlXG4gICAgICAvLyBpbnZhbGlkIGBBY3RpdmF0ZWRSb3V0ZWAgbW9ja3MuXG4gICAgICAvLyBOb3RlOiB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGhhdmluZyB0aGlzIGZhbGxiYWNrIGZvciBpbnZhbGlkIGBBY3RpdmF0ZWRSb3V0ZWAgc2V0dXBzIGFuZFxuICAgICAgLy8ganVzdCB0aHJvd2luZyBpcyB+NTAwIHRlc3QgZmFpbHVyZXMuIEZpeGluZyBhbGwgb2YgdGhvc2UgdGVzdHMgYnkgaGFuZCBpcyBub3QgZmVhc2libGUgYXRcbiAgICAgIC8vIHRoZSBtb21lbnQuXG4gICAgICBpZiAodHlwZW9mIGNvbW1hbmRzWzBdICE9PSAnc3RyaW5nJyB8fCAhY29tbWFuZHNbMF0uc3RhcnRzV2l0aCgnLycpKSB7XG4gICAgICAgIC8vIE5hdmlnYXRpb25zIHRoYXQgd2VyZSBhYnNvbHV0ZSBpbiB0aGUgb2xkIHdheSBvZiBjcmVhdGluZyBVcmxUcmVlc1xuICAgICAgICAvLyB3b3VsZCBzdGlsbCB3b3JrIGJlY2F1c2UgdGhleSB3b3VsZG4ndCBhdHRlbXB0IHRvIG1hdGNoIHRoZVxuICAgICAgICAvLyBzZWdtZW50cyBpbiB0aGUgYEFjdGl2YXRlZFJvdXRlYCB0byB0aGUgYGN1cnJlbnRVcmxUcmVlYCBidXRcbiAgICAgICAgLy8gaW5zdGVhZCBqdXN0IHJlcGxhY2UgdGhlIHJvb3Qgc2VnbWVudCB3aXRoIHRoZSBuYXZpZ2F0aW9uIHJlc3VsdC5cbiAgICAgICAgLy8gTm9uLWFic29sdXRlIG5hdmlnYXRpb25zIHdvdWxkIGZhaWwgdG8gYXBwbHkgdGhlIGNvbW1hbmRzIGJlY2F1c2VcbiAgICAgICAgLy8gdGhlIGxvZ2ljIGNvdWxkIG5vdCBmaW5kIHRoZSBzZWdtZW50IHRvIHJlcGxhY2UgKHNvIHRoZXknZCBhY3QgbGlrZSB0aGVyZSB3ZXJlIG5vXG4gICAgICAgIC8vIGNvbW1hbmRzKS5cbiAgICAgICAgY29tbWFuZHMgPSBbXTtcbiAgICAgIH1cbiAgICAgIHJlbGF0aXZlVG9VcmxTZWdtZW50R3JvdXAgPSB0aGlzLmN1cnJlbnRVcmxUcmVlLnJvb3Q7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVVcmxUcmVlRnJvbVNlZ21lbnRHcm91cChyZWxhdGl2ZVRvVXJsU2VnbWVudEdyb3VwLCBjb21tYW5kcywgcSwgZiA/PyBudWxsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBOYXZpZ2F0ZXMgdG8gYSB2aWV3IHVzaW5nIGFuIGFic29sdXRlIHJvdXRlIHBhdGguXG4gICAqXG4gICAqIEBwYXJhbSB1cmwgQW4gYWJzb2x1dGUgcGF0aCBmb3IgYSBkZWZpbmVkIHJvdXRlLiBUaGUgZnVuY3Rpb24gZG9lcyBub3QgYXBwbHkgYW55IGRlbHRhIHRvIHRoZVxuICAgKiAgICAgY3VycmVudCBVUkwuXG4gICAqIEBwYXJhbSBleHRyYXMgQW4gb2JqZWN0IGNvbnRhaW5pbmcgcHJvcGVydGllcyB0aGF0IG1vZGlmeSB0aGUgbmF2aWdhdGlvbiBzdHJhdGVneS5cbiAgICpcbiAgICogQHJldHVybnMgQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gJ3RydWUnIHdoZW4gbmF2aWdhdGlvbiBzdWNjZWVkcyxcbiAgICogdG8gJ2ZhbHNlJyB3aGVuIG5hdmlnYXRpb24gZmFpbHMsIG9yIGlzIHJlamVjdGVkIG9uIGVycm9yLlxuICAgKlxuICAgKiBAdXNhZ2VOb3Rlc1xuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGNhbGxzIHJlcXVlc3QgbmF2aWdhdGlvbiB0byBhbiBhYnNvbHV0ZSBwYXRoLlxuICAgKlxuICAgKiBgYGBcbiAgICogcm91dGVyLm5hdmlnYXRlQnlVcmwoXCIvdGVhbS8zMy91c2VyLzExXCIpO1xuICAgKlxuICAgKiAvLyBOYXZpZ2F0ZSB3aXRob3V0IHVwZGF0aW5nIHRoZSBVUkxcbiAgICogcm91dGVyLm5hdmlnYXRlQnlVcmwoXCIvdGVhbS8zMy91c2VyLzExXCIsIHsgc2tpcExvY2F0aW9uQ2hhbmdlOiB0cnVlIH0pO1xuICAgKiBgYGBcbiAgICpcbiAgICogQHNlZSBbUm91dGluZyBhbmQgTmF2aWdhdGlvbiBndWlkZV0oZ3VpZGUvcm91dGVyKVxuICAgKlxuICAgKi9cbiAgbmF2aWdhdGVCeVVybCh1cmw6IHN0cmluZ3xVcmxUcmVlLCBleHRyYXM6IE5hdmlnYXRpb25CZWhhdmlvck9wdGlvbnMgPSB7XG4gICAgc2tpcExvY2F0aW9uQ2hhbmdlOiBmYWxzZVxuICB9KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKHR5cGVvZiBuZ0Rldk1vZGUgPT09ICd1bmRlZmluZWQnIHx8IG5nRGV2TW9kZSkge1xuICAgICAgaWYgKHRoaXMuaXNOZ1pvbmVFbmFibGVkICYmICFOZ1pvbmUuaXNJbkFuZ3VsYXJab25lKCkpIHtcbiAgICAgICAgdGhpcy5jb25zb2xlLndhcm4oXG4gICAgICAgICAgICBgTmF2aWdhdGlvbiB0cmlnZ2VyZWQgb3V0c2lkZSBBbmd1bGFyIHpvbmUsIGRpZCB5b3UgZm9yZ2V0IHRvIGNhbGwgJ25nWm9uZS5ydW4oKSc/YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdXJsVHJlZSA9IGlzVXJsVHJlZSh1cmwpID8gdXJsIDogdGhpcy5wYXJzZVVybCh1cmwpO1xuICAgIGNvbnN0IG1lcmdlZFRyZWUgPSB0aGlzLnVybEhhbmRsaW5nU3RyYXRlZ3kubWVyZ2UodXJsVHJlZSwgdGhpcy5yYXdVcmxUcmVlKTtcblxuICAgIHJldHVybiB0aGlzLnNjaGVkdWxlTmF2aWdhdGlvbihtZXJnZWRUcmVlLCBJTVBFUkFUSVZFX05BVklHQVRJT04sIG51bGwsIGV4dHJhcyk7XG4gIH1cblxuICAvKipcbiAgICogTmF2aWdhdGUgYmFzZWQgb24gdGhlIHByb3ZpZGVkIGFycmF5IG9mIGNvbW1hbmRzIGFuZCBhIHN0YXJ0aW5nIHBvaW50LlxuICAgKiBJZiBubyBzdGFydGluZyByb3V0ZSBpcyBwcm92aWRlZCwgdGhlIG5hdmlnYXRpb24gaXMgYWJzb2x1dGUuXG4gICAqXG4gICAqIEBwYXJhbSBjb21tYW5kcyBBbiBhcnJheSBvZiBVUkwgZnJhZ21lbnRzIHdpdGggd2hpY2ggdG8gY29uc3RydWN0IHRoZSB0YXJnZXQgVVJMLlxuICAgKiBJZiB0aGUgcGF0aCBpcyBzdGF0aWMsIGNhbiBiZSB0aGUgbGl0ZXJhbCBVUkwgc3RyaW5nLiBGb3IgYSBkeW5hbWljIHBhdGgsIHBhc3MgYW4gYXJyYXkgb2YgcGF0aFxuICAgKiBzZWdtZW50cywgZm9sbG93ZWQgYnkgdGhlIHBhcmFtZXRlcnMgZm9yIGVhY2ggc2VnbWVudC5cbiAgICogVGhlIGZyYWdtZW50cyBhcmUgYXBwbGllZCB0byB0aGUgY3VycmVudCBVUkwgb3IgdGhlIG9uZSBwcm92aWRlZCAgaW4gdGhlIGByZWxhdGl2ZVRvYCBwcm9wZXJ0eVxuICAgKiBvZiB0aGUgb3B0aW9ucyBvYmplY3QsIGlmIHN1cHBsaWVkLlxuICAgKiBAcGFyYW0gZXh0cmFzIEFuIG9wdGlvbnMgb2JqZWN0IHRoYXQgZGV0ZXJtaW5lcyBob3cgdGhlIFVSTCBzaG91bGQgYmUgY29uc3RydWN0ZWQgb3JcbiAgICogICAgIGludGVycHJldGVkLlxuICAgKlxuICAgKiBAcmV0dXJucyBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byBgdHJ1ZWAgd2hlbiBuYXZpZ2F0aW9uIHN1Y2NlZWRzLCB0byBgZmFsc2VgIHdoZW4gbmF2aWdhdGlvblxuICAgKiAgICAgZmFpbHMsXG4gICAqIG9yIGlzIHJlamVjdGVkIG9uIGVycm9yLlxuICAgKlxuICAgKiBAdXNhZ2VOb3Rlc1xuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGNhbGxzIHJlcXVlc3QgbmF2aWdhdGlvbiB0byBhIGR5bmFtaWMgcm91dGUgcGF0aCByZWxhdGl2ZSB0byB0aGUgY3VycmVudCBVUkwuXG4gICAqXG4gICAqIGBgYFxuICAgKiByb3V0ZXIubmF2aWdhdGUoWyd0ZWFtJywgMzMsICd1c2VyJywgMTFdLCB7cmVsYXRpdmVUbzogcm91dGV9KTtcbiAgICpcbiAgICogLy8gTmF2aWdhdGUgd2l0aG91dCB1cGRhdGluZyB0aGUgVVJMLCBvdmVycmlkaW5nIHRoZSBkZWZhdWx0IGJlaGF2aW9yXG4gICAqIHJvdXRlci5uYXZpZ2F0ZShbJ3RlYW0nLCAzMywgJ3VzZXInLCAxMV0sIHtyZWxhdGl2ZVRvOiByb3V0ZSwgc2tpcExvY2F0aW9uQ2hhbmdlOiB0cnVlfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAc2VlIFtSb3V0aW5nIGFuZCBOYXZpZ2F0aW9uIGd1aWRlXShndWlkZS9yb3V0ZXIpXG4gICAqXG4gICAqL1xuICBuYXZpZ2F0ZShjb21tYW5kczogYW55W10sIGV4dHJhczogTmF2aWdhdGlvbkV4dHJhcyA9IHtza2lwTG9jYXRpb25DaGFuZ2U6IGZhbHNlfSk6XG4gICAgICBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB2YWxpZGF0ZUNvbW1hbmRzKGNvbW1hbmRzKTtcbiAgICByZXR1cm4gdGhpcy5uYXZpZ2F0ZUJ5VXJsKHRoaXMuY3JlYXRlVXJsVHJlZShjb21tYW5kcywgZXh0cmFzKSwgZXh0cmFzKTtcbiAgfVxuXG4gIC8qKiBTZXJpYWxpemVzIGEgYFVybFRyZWVgIGludG8gYSBzdHJpbmcgKi9cbiAgc2VyaWFsaXplVXJsKHVybDogVXJsVHJlZSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMudXJsU2VyaWFsaXplci5zZXJpYWxpemUodXJsKTtcbiAgfVxuXG4gIC8qKiBQYXJzZXMgYSBzdHJpbmcgaW50byBhIGBVcmxUcmVlYCAqL1xuICBwYXJzZVVybCh1cmw6IHN0cmluZyk6IFVybFRyZWUge1xuICAgIGxldCB1cmxUcmVlOiBVcmxUcmVlO1xuICAgIHRyeSB7XG4gICAgICB1cmxUcmVlID0gdGhpcy51cmxTZXJpYWxpemVyLnBhcnNlKHVybCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdXJsVHJlZSA9IHRoaXMubWFsZm9ybWVkVXJpRXJyb3JIYW5kbGVyKGUgYXMgVVJJRXJyb3IsIHRoaXMudXJsU2VyaWFsaXplciwgdXJsKTtcbiAgICB9XG4gICAgcmV0dXJuIHVybFRyZWU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB3aGV0aGVyIHRoZSB1cmwgaXMgYWN0aXZhdGVkLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZFxuICAgKiBVc2UgYElzQWN0aXZlTWF0Y2hPcHRpb25zYCBpbnN0ZWFkLlxuICAgKlxuICAgKiAtIFRoZSBlcXVpdmFsZW50IGBJc0FjdGl2ZU1hdGNoT3B0aW9uc2AgZm9yIGB0cnVlYCBpc1xuICAgKiBge3BhdGhzOiAnZXhhY3QnLCBxdWVyeVBhcmFtczogJ2V4YWN0JywgZnJhZ21lbnQ6ICdpZ25vcmVkJywgbWF0cml4UGFyYW1zOiAnaWdub3JlZCd9YC5cbiAgICogLSBUaGUgZXF1aXZhbGVudCBmb3IgYGZhbHNlYCBpc1xuICAgKiBge3BhdGhzOiAnc3Vic2V0JywgcXVlcnlQYXJhbXM6ICdzdWJzZXQnLCBmcmFnbWVudDogJ2lnbm9yZWQnLCBtYXRyaXhQYXJhbXM6ICdpZ25vcmVkJ31gLlxuICAgKi9cbiAgaXNBY3RpdmUodXJsOiBzdHJpbmd8VXJsVHJlZSwgZXhhY3Q6IGJvb2xlYW4pOiBib29sZWFuO1xuICAvKipcbiAgICogUmV0dXJucyB3aGV0aGVyIHRoZSB1cmwgaXMgYWN0aXZhdGVkLlxuICAgKi9cbiAgaXNBY3RpdmUodXJsOiBzdHJpbmd8VXJsVHJlZSwgbWF0Y2hPcHRpb25zOiBJc0FjdGl2ZU1hdGNoT3B0aW9ucyk6IGJvb2xlYW47XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgaXNBY3RpdmUodXJsOiBzdHJpbmd8VXJsVHJlZSwgbWF0Y2hPcHRpb25zOiBib29sZWFufElzQWN0aXZlTWF0Y2hPcHRpb25zKTogYm9vbGVhbjtcbiAgaXNBY3RpdmUodXJsOiBzdHJpbmd8VXJsVHJlZSwgbWF0Y2hPcHRpb25zOiBib29sZWFufElzQWN0aXZlTWF0Y2hPcHRpb25zKTogYm9vbGVhbiB7XG4gICAgbGV0IG9wdGlvbnM6IElzQWN0aXZlTWF0Y2hPcHRpb25zO1xuICAgIGlmIChtYXRjaE9wdGlvbnMgPT09IHRydWUpIHtcbiAgICAgIG9wdGlvbnMgPSB7Li4uZXhhY3RNYXRjaE9wdGlvbnN9O1xuICAgIH0gZWxzZSBpZiAobWF0Y2hPcHRpb25zID09PSBmYWxzZSkge1xuICAgICAgb3B0aW9ucyA9IHsuLi5zdWJzZXRNYXRjaE9wdGlvbnN9O1xuICAgIH0gZWxzZSB7XG4gICAgICBvcHRpb25zID0gbWF0Y2hPcHRpb25zO1xuICAgIH1cbiAgICBpZiAoaXNVcmxUcmVlKHVybCkpIHtcbiAgICAgIHJldHVybiBjb250YWluc1RyZWUodGhpcy5jdXJyZW50VXJsVHJlZSwgdXJsLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBjb25zdCB1cmxUcmVlID0gdGhpcy5wYXJzZVVybCh1cmwpO1xuICAgIHJldHVybiBjb250YWluc1RyZWUodGhpcy5jdXJyZW50VXJsVHJlZSwgdXJsVHJlZSwgb3B0aW9ucyk7XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZUVtcHR5UHJvcHMocGFyYW1zOiBQYXJhbXMpOiBQYXJhbXMge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhwYXJhbXMpLnJlZHVjZSgocmVzdWx0OiBQYXJhbXMsIGtleTogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZTogYW55ID0gcGFyYW1zW2tleV07XG4gICAgICBpZiAodmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LCB7fSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHNjaGVkdWxlTmF2aWdhdGlvbihcbiAgICAgIHJhd1VybDogVXJsVHJlZSwgc291cmNlOiBOYXZpZ2F0aW9uVHJpZ2dlciwgcmVzdG9yZWRTdGF0ZTogUmVzdG9yZWRTdGF0ZXxudWxsLFxuICAgICAgZXh0cmFzOiBOYXZpZ2F0aW9uRXh0cmFzLFxuICAgICAgcHJpb3JQcm9taXNlPzoge3Jlc29sdmU6IGFueSwgcmVqZWN0OiBhbnksIHByb21pc2U6IFByb21pc2U8Ym9vbGVhbj59KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKHRoaXMuZGlzcG9zZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICAgIH1cblxuICAgIGxldCByZXNvbHZlOiBhbnk7XG4gICAgbGV0IHJlamVjdDogYW55O1xuICAgIGxldCBwcm9taXNlOiBQcm9taXNlPGJvb2xlYW4+O1xuICAgIGlmIChwcmlvclByb21pc2UpIHtcbiAgICAgIHJlc29sdmUgPSBwcmlvclByb21pc2UucmVzb2x2ZTtcbiAgICAgIHJlamVjdCA9IHByaW9yUHJvbWlzZS5yZWplY3Q7XG4gICAgICBwcm9taXNlID0gcHJpb3JQcm9taXNlLnByb21pc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb21pc2UgPSBuZXcgUHJvbWlzZTxib29sZWFuPigocmVzLCByZWopID0+IHtcbiAgICAgICAgcmVzb2x2ZSA9IHJlcztcbiAgICAgICAgcmVqZWN0ID0gcmVqO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgbGV0IHRhcmdldFBhZ2VJZDogbnVtYmVyO1xuICAgIGlmICh0aGlzLmNhbmNlbGVkTmF2aWdhdGlvblJlc29sdXRpb24gPT09ICdjb21wdXRlZCcpIHtcbiAgICAgIC8vIElmIHRoZSBgybVyb3V0ZXJQYWdlSWRgIGV4aXN0IGluIHRoZSBzdGF0ZSB0aGVuIGB0YXJnZXRwYWdlSWRgIHNob3VsZCBoYXZlIHRoZSB2YWx1ZSBvZlxuICAgICAgLy8gYMm1cm91dGVyUGFnZUlkYC4gVGhpcyBpcyB0aGUgY2FzZSBmb3Igc29tZXRoaW5nIGxpa2UgYSBwYWdlIHJlZnJlc2ggd2hlcmUgd2UgYXNzaWduIHRoZVxuICAgICAgLy8gdGFyZ2V0IGlkIHRvIHRoZSBwcmV2aW91c2x5IHNldCB2YWx1ZSBmb3IgdGhhdCBwYWdlLlxuICAgICAgaWYgKHJlc3RvcmVkU3RhdGUgJiYgcmVzdG9yZWRTdGF0ZS7JtXJvdXRlclBhZ2VJZCkge1xuICAgICAgICB0YXJnZXRQYWdlSWQgPSByZXN0b3JlZFN0YXRlLsm1cm91dGVyUGFnZUlkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSWYgd2UncmUgcmVwbGFjaW5nIHRoZSBVUkwgb3IgZG9pbmcgYSBzaWxlbnQgbmF2aWdhdGlvbiwgd2UgZG8gbm90IHdhbnQgdG8gaW5jcmVtZW50IHRoZVxuICAgICAgICAvLyBwYWdlIGlkIGJlY2F1c2Ugd2UgYXJlbid0IHB1c2hpbmcgYSBuZXcgZW50cnkgdG8gaGlzdG9yeS5cbiAgICAgICAgaWYgKGV4dHJhcy5yZXBsYWNlVXJsIHx8IGV4dHJhcy5za2lwTG9jYXRpb25DaGFuZ2UpIHtcbiAgICAgICAgICB0YXJnZXRQYWdlSWQgPSB0aGlzLmJyb3dzZXJQYWdlSWQgPz8gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0YXJnZXRQYWdlSWQgPSAodGhpcy5icm93c2VyUGFnZUlkID8/IDApICsgMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBUaGlzIGlzIHVudXNlZCB3aGVuIGBjYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uYCBpcyBub3QgY29tcHV0ZWQuXG4gICAgICB0YXJnZXRQYWdlSWQgPSAwO1xuICAgIH1cblxuICAgIC8vIEluZGljYXRlIHRoYXQgdGhlIG5hdmlnYXRpb24gaXMgaGFwcGVuaW5nLlxuICAgIGNvbnN0IHRhc2tJZCA9IHRoaXMucGVuZGluZ1Rhc2tzLmFkZCgpO1xuICAgIGFmdGVyTmV4dE5hdmlnYXRpb24odGhpcywgKCkgPT4ge1xuICAgICAgLy8gUmVtb3ZlIHBlbmRpbmcgdGFzayBpbiBhIG1pY3JvdGFzayB0byBhbGxvdyBmb3IgY2FuY2VsbGVkXG4gICAgICAvLyBpbml0aWFsIG5hdmlnYXRpb25zIGFuZCByZWRpcmVjdHMgd2l0aGluIHRoZSBzYW1lIHRhc2suXG4gICAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHRoaXMucGVuZGluZ1Rhc2tzLnJlbW92ZSh0YXNrSWQpKTtcbiAgICB9KTtcblxuICAgIHRoaXMubmF2aWdhdGlvblRyYW5zaXRpb25zLmhhbmRsZU5hdmlnYXRpb25SZXF1ZXN0KHtcbiAgICAgIHRhcmdldFBhZ2VJZCxcbiAgICAgIHNvdXJjZSxcbiAgICAgIHJlc3RvcmVkU3RhdGUsXG4gICAgICBjdXJyZW50VXJsVHJlZTogdGhpcy5jdXJyZW50VXJsVHJlZSxcbiAgICAgIGN1cnJlbnRSYXdVcmw6IHRoaXMuY3VycmVudFVybFRyZWUsXG4gICAgICByYXdVcmwsXG4gICAgICBleHRyYXMsXG4gICAgICByZXNvbHZlLFxuICAgICAgcmVqZWN0LFxuICAgICAgcHJvbWlzZSxcbiAgICAgIGN1cnJlbnRTbmFwc2hvdDogdGhpcy5yb3V0ZXJTdGF0ZS5zbmFwc2hvdCxcbiAgICAgIGN1cnJlbnRSb3V0ZXJTdGF0ZTogdGhpcy5yb3V0ZXJTdGF0ZVxuICAgIH0pO1xuXG4gICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGVycm9yIGlzIHByb3BhZ2F0ZWQgZXZlbiB0aG91Z2ggYHByb2Nlc3NOYXZpZ2F0aW9uc2AgY2F0Y2hcbiAgICAvLyBoYW5kbGVyIGRvZXMgbm90IHJldGhyb3dcbiAgICByZXR1cm4gcHJvbWlzZS5jYXRjaCgoZTogYW55KSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHNldEJyb3dzZXJVcmwodXJsOiBVcmxUcmVlLCB0cmFuc2l0aW9uOiBOYXZpZ2F0aW9uVHJhbnNpdGlvbikge1xuICAgIGNvbnN0IHBhdGggPSB0aGlzLnVybFNlcmlhbGl6ZXIuc2VyaWFsaXplKHVybCk7XG4gICAgY29uc3Qgc3RhdGUgPSB7XG4gICAgICAuLi50cmFuc2l0aW9uLmV4dHJhcy5zdGF0ZSxcbiAgICAgIC4uLnRoaXMuZ2VuZXJhdGVOZ1JvdXRlclN0YXRlKHRyYW5zaXRpb24uaWQsIHRyYW5zaXRpb24udGFyZ2V0UGFnZUlkKVxuICAgIH07XG4gICAgaWYgKHRoaXMubG9jYXRpb24uaXNDdXJyZW50UGF0aEVxdWFsVG8ocGF0aCkgfHwgISF0cmFuc2l0aW9uLmV4dHJhcy5yZXBsYWNlVXJsKSB7XG4gICAgICB0aGlzLmxvY2F0aW9uLnJlcGxhY2VTdGF0ZShwYXRoLCAnJywgc3RhdGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxvY2F0aW9uLmdvKHBhdGgsICcnLCBzdGF0ZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIHRoZSBuZWNlc3Nhcnkgcm9sbGJhY2sgYWN0aW9uIHRvIHJlc3RvcmUgdGhlIGJyb3dzZXIgVVJMIHRvIHRoZVxuICAgKiBzdGF0ZSBiZWZvcmUgdGhlIHRyYW5zaXRpb24uXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcmVzdG9yZUhpc3RvcnkodHJhbnNpdGlvbjogTmF2aWdhdGlvblRyYW5zaXRpb24sIHJlc3RvcmluZ0Zyb21DYXVnaHRFcnJvciA9IGZhbHNlKSB7XG4gICAgaWYgKHRoaXMuY2FuY2VsZWROYXZpZ2F0aW9uUmVzb2x1dGlvbiA9PT0gJ2NvbXB1dGVkJykge1xuICAgICAgY29uc3QgdGFyZ2V0UGFnZVBvc2l0aW9uID0gdGhpcy5jdXJyZW50UGFnZUlkIC0gdHJhbnNpdGlvbi50YXJnZXRQYWdlSWQ7XG4gICAgICAvLyBUaGUgbmF2aWdhdG9yIGNoYW5nZSB0aGUgbG9jYXRpb24gYmVmb3JlIHRyaWdnZXJlZCB0aGUgYnJvd3NlciBldmVudCxcbiAgICAgIC8vIHNvIHdlIG5lZWQgdG8gZ28gYmFjayB0byB0aGUgY3VycmVudCB1cmwgaWYgdGhlIG5hdmlnYXRpb24gaXMgY2FuY2VsZWQuXG4gICAgICAvLyBBbHNvLCB3aGVuIG5hdmlnYXRpb24gZ2V0cyBjYW5jZWxsZWQgd2hpbGUgdXNpbmcgdXJsIHVwZGF0ZSBzdHJhdGVneSBlYWdlciwgdGhlbiB3ZSBuZWVkIHRvXG4gICAgICAvLyBnbyBiYWNrLiBCZWNhdXNlLCB3aGVuIGB1cmxVcGRhdGVTdHJhdGVneWAgaXMgYGVhZ2VyYDsgYHNldEJyb3dzZXJVcmxgIG1ldGhvZCBpcyBjYWxsZWRcbiAgICAgIC8vIGJlZm9yZSBhbnkgdmVyaWZpY2F0aW9uLlxuICAgICAgY29uc3QgYnJvd3NlclVybFVwZGF0ZU9jY3VycmVkID1cbiAgICAgICAgICAodHJhbnNpdGlvbi5zb3VyY2UgPT09ICdwb3BzdGF0ZScgfHwgdGhpcy51cmxVcGRhdGVTdHJhdGVneSA9PT0gJ2VhZ2VyJyB8fFxuICAgICAgICAgICB0aGlzLmN1cnJlbnRVcmxUcmVlID09PSB0aGlzLmdldEN1cnJlbnROYXZpZ2F0aW9uKCk/LmZpbmFsVXJsKTtcbiAgICAgIGlmIChicm93c2VyVXJsVXBkYXRlT2NjdXJyZWQgJiYgdGFyZ2V0UGFnZVBvc2l0aW9uICE9PSAwKSB7XG4gICAgICAgIHRoaXMubG9jYXRpb24uaGlzdG9yeUdvKHRhcmdldFBhZ2VQb3NpdGlvbik7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgIHRoaXMuY3VycmVudFVybFRyZWUgPT09IHRoaXMuZ2V0Q3VycmVudE5hdmlnYXRpb24oKT8uZmluYWxVcmwgJiZcbiAgICAgICAgICB0YXJnZXRQYWdlUG9zaXRpb24gPT09IDApIHtcbiAgICAgICAgLy8gV2UgZ290IHRvIHRoZSBhY3RpdmF0aW9uIHN0YWdlICh3aGVyZSBjdXJyZW50VXJsVHJlZSBpcyBzZXQgdG8gdGhlIG5hdmlnYXRpb24nc1xuICAgICAgICAvLyBmaW5hbFVybCksIGJ1dCB3ZSB3ZXJlbid0IG1vdmluZyBhbnl3aGVyZSBpbiBoaXN0b3J5IChza2lwTG9jYXRpb25DaGFuZ2Ugb3IgcmVwbGFjZVVybCkuXG4gICAgICAgIC8vIFdlIHN0aWxsIG5lZWQgdG8gcmVzZXQgdGhlIHJvdXRlciBzdGF0ZSBiYWNrIHRvIHdoYXQgaXQgd2FzIHdoZW4gdGhlIG5hdmlnYXRpb24gc3RhcnRlZC5cbiAgICAgICAgdGhpcy5yZXNldFN0YXRlKHRyYW5zaXRpb24pO1xuICAgICAgICAvLyBUT0RPKGF0c2NvdHQpOiByZXNldHRpbmcgdGhlIGBicm93c2VyVXJsVHJlZWAgc2hvdWxkIHJlYWxseSBiZSBkb25lIGluIGByZXNldFN0YXRlYC5cbiAgICAgICAgLy8gSW52ZXN0aWdhdGUgaWYgdGhpcyBjYW4gYmUgZG9uZSBieSBydW5uaW5nIFRHUC5cbiAgICAgICAgdGhpcy5icm93c2VyVXJsVHJlZSA9IHRyYW5zaXRpb24uY3VycmVudFVybFRyZWU7XG4gICAgICAgIHRoaXMucmVzZXRVcmxUb0N1cnJlbnRVcmxUcmVlKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBUaGUgYnJvd3NlciBVUkwgYW5kIHJvdXRlciBzdGF0ZSB3YXMgbm90IHVwZGF0ZWQgYmVmb3JlIHRoZSBuYXZpZ2F0aW9uIGNhbmNlbGxlZCBzb1xuICAgICAgICAvLyB0aGVyZSdzIG5vIHJlc3RvcmF0aW9uIG5lZWRlZC5cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRoaXMuY2FuY2VsZWROYXZpZ2F0aW9uUmVzb2x1dGlvbiA9PT0gJ3JlcGxhY2UnKSB7XG4gICAgICAvLyBUT0RPKGF0c2NvdHQpOiBJdCBzZWVtcyBsaWtlIHdlIHNob3VsZCBfYWx3YXlzXyByZXNldCB0aGUgc3RhdGUgaGVyZS4gSXQgd291bGQgYmUgYSBuby1vcFxuICAgICAgLy8gZm9yIGBkZWZlcnJlZGAgbmF2aWdhdGlvbnMgdGhhdCBoYXZlbid0IGNoYW5nZSB0aGUgaW50ZXJuYWwgc3RhdGUgeWV0IGJlY2F1c2UgZ3VhcmRzXG4gICAgICAvLyByZWplY3QuIEZvciAnZWFnZXInIG5hdmlnYXRpb25zLCBpdCBzZWVtcyBsaWtlIHdlIGFsc28gcmVhbGx5IHNob3VsZCByZXNldCB0aGUgc3RhdGVcbiAgICAgIC8vIGJlY2F1c2UgdGhlIG5hdmlnYXRpb24gd2FzIGNhbmNlbGxlZC4gSW52ZXN0aWdhdGUgaWYgdGhpcyBjYW4gYmUgZG9uZSBieSBydW5uaW5nIFRHUC5cbiAgICAgIGlmIChyZXN0b3JpbmdGcm9tQ2F1Z2h0RXJyb3IpIHtcbiAgICAgICAgdGhpcy5yZXNldFN0YXRlKHRyYW5zaXRpb24pO1xuICAgICAgfVxuICAgICAgdGhpcy5yZXNldFVybFRvQ3VycmVudFVybFRyZWUoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlc2V0U3RhdGUodDogTmF2aWdhdGlvblRyYW5zaXRpb24pOiB2b2lkIHtcbiAgICAodGhpcyBhcyB7cm91dGVyU3RhdGU6IFJvdXRlclN0YXRlfSkucm91dGVyU3RhdGUgPSB0LmN1cnJlbnRSb3V0ZXJTdGF0ZTtcbiAgICB0aGlzLmN1cnJlbnRVcmxUcmVlID0gdC5jdXJyZW50VXJsVHJlZTtcbiAgICAvLyBOb3RlIGhlcmUgdGhhdCB3ZSB1c2UgdGhlIHVybEhhbmRsaW5nU3RyYXRlZ3kgdG8gZ2V0IHRoZSByZXNldCBgcmF3VXJsVHJlZWAgYmVjYXVzZSBpdCBtYXkgYmVcbiAgICAvLyBjb25maWd1cmVkIHRvIGhhbmRsZSBvbmx5IHBhcnQgb2YgdGhlIG5hdmlnYXRpb24gVVJMLiBUaGlzIG1lYW5zIHdlIHdvdWxkIG9ubHkgd2FudCB0byByZXNldFxuICAgIC8vIHRoZSBwYXJ0IG9mIHRoZSBuYXZpZ2F0aW9uIGhhbmRsZWQgYnkgdGhlIEFuZ3VsYXIgcm91dGVyIHJhdGhlciB0aGFuIHRoZSB3aG9sZSBVUkwuIEluXG4gICAgLy8gYWRkaXRpb24sIHRoZSBVUkxIYW5kbGluZ1N0cmF0ZWd5IG1heSBiZSBjb25maWd1cmVkIHRvIHNwZWNpZmljYWxseSBwcmVzZXJ2ZSBwYXJ0cyBvZiB0aGUgVVJMXG4gICAgLy8gd2hlbiBtZXJnaW5nLCBzdWNoIGFzIHRoZSBxdWVyeSBwYXJhbXMgc28gdGhleSBhcmUgbm90IGxvc3Qgb24gYSByZWZyZXNoLlxuICAgIHRoaXMucmF3VXJsVHJlZSA9IHRoaXMudXJsSGFuZGxpbmdTdHJhdGVneS5tZXJnZSh0aGlzLmN1cnJlbnRVcmxUcmVlLCB0LnJhd1VybCk7XG4gIH1cblxuICBwcml2YXRlIHJlc2V0VXJsVG9DdXJyZW50VXJsVHJlZSgpOiB2b2lkIHtcbiAgICB0aGlzLmxvY2F0aW9uLnJlcGxhY2VTdGF0ZShcbiAgICAgICAgdGhpcy51cmxTZXJpYWxpemVyLnNlcmlhbGl6ZSh0aGlzLnJhd1VybFRyZWUpLCAnJyxcbiAgICAgICAgdGhpcy5nZW5lcmF0ZU5nUm91dGVyU3RhdGUodGhpcy5sYXN0U3VjY2Vzc2Z1bElkLCB0aGlzLmN1cnJlbnRQYWdlSWQpKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2VuZXJhdGVOZ1JvdXRlclN0YXRlKG5hdmlnYXRpb25JZDogbnVtYmVyLCByb3V0ZXJQYWdlSWQ/OiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5jYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uID09PSAnY29tcHV0ZWQnKSB7XG4gICAgICByZXR1cm4ge25hdmlnYXRpb25JZCwgybVyb3V0ZXJQYWdlSWQ6IHJvdXRlclBhZ2VJZH07XG4gICAgfVxuICAgIHJldHVybiB7bmF2aWdhdGlvbklkfTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUNvbW1hbmRzKGNvbW1hbmRzOiBzdHJpbmdbXSk6IHZvaWQge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbW1hbmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgY21kID0gY29tbWFuZHNbaV07XG4gICAgaWYgKGNtZCA9PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yKFxuICAgICAgICAgIFJ1bnRpbWVFcnJvckNvZGUuTlVMTElTSF9DT01NQU5ELFxuICAgICAgICAgICh0eXBlb2YgbmdEZXZNb2RlID09PSAndW5kZWZpbmVkJyB8fCBuZ0Rldk1vZGUpICYmXG4gICAgICAgICAgICAgIGBUaGUgcmVxdWVzdGVkIHBhdGggY29udGFpbnMgJHtjbWR9IHNlZ21lbnQgYXQgaW5kZXggJHtpfWApO1xuICAgIH1cbiAgfVxufVxuIl19