@decaf-ts/for-angular 0.0.11 → 0.0.13

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 (85) hide show
  1. package/package.json +19 -91
  2. package/LICENSE.md +0 -659
  3. package/dist/lib/README.md +0 -92
  4. package/dist/lib/assets/i18n/en.json +0 -140
  5. package/dist/lib/assets/images/angular-logo.svg +0 -45
  6. package/dist/lib/assets/images/decaf-logo-black.svg +0 -22
  7. package/dist/lib/assets/images/decaf-logo-lw.svg +0 -50
  8. package/dist/lib/assets/images/decaf-logo-white.svg +0 -22
  9. package/dist/lib/assets/images/decaf-logo.svg +0 -54
  10. package/dist/lib/components/component-renderer/component-renderer.component.d.ts +0 -276
  11. package/dist/lib/components/crud-field/crud-field.component.d.ts +0 -445
  12. package/dist/lib/components/crud-form/constants.d.ts +0 -5
  13. package/dist/lib/components/crud-form/crud-form.component.d.ts +0 -102
  14. package/dist/lib/components/crud-form/types.d.ts +0 -17
  15. package/dist/lib/components/empty-state/empty-state.component.d.ts +0 -301
  16. package/dist/lib/components/fieldset/fieldset.component.d.ts +0 -199
  17. package/dist/lib/components/filter/filter.component.d.ts +0 -505
  18. package/dist/lib/components/for-angular-components.module.d.ts +0 -20
  19. package/dist/lib/components/index.d.ts +0 -16
  20. package/dist/lib/components/layout/layout.component.d.ts +0 -133
  21. package/dist/lib/components/list/constants.d.ts +0 -29
  22. package/dist/lib/components/list/list.component.d.ts +0 -849
  23. package/dist/lib/components/list-item/list-item.component.d.ts +0 -390
  24. package/dist/lib/components/model-renderer/model-renderer.component.d.ts +0 -96
  25. package/dist/lib/components/pagination/constants.d.ts +0 -7
  26. package/dist/lib/components/pagination/pagination.component.d.ts +0 -264
  27. package/dist/lib/components/searchbar/searchbar.component.d.ts +0 -407
  28. package/dist/lib/directives/collapsable.directive.d.ts +0 -8
  29. package/dist/lib/directives/index.d.ts +0 -1
  30. package/dist/lib/engine/DynamicModule.d.ts +0 -17
  31. package/dist/lib/engine/NgxBaseComponent.d.ts +0 -541
  32. package/dist/lib/engine/NgxCrudFormField.d.ts +0 -118
  33. package/dist/lib/engine/NgxFormService.d.ts +0 -167
  34. package/dist/lib/engine/NgxRenderingEngine.d.ts +0 -127
  35. package/dist/lib/engine/NgxRenderingEngine2.d.ts +0 -250
  36. package/dist/lib/engine/ValidatorFactory.d.ts +0 -15
  37. package/dist/lib/engine/constants.d.ts +0 -151
  38. package/dist/lib/engine/decorators.d.ts +0 -25
  39. package/dist/lib/engine/index.d.ts +0 -16
  40. package/dist/lib/engine/types.d.ts +0 -381
  41. package/dist/lib/esm2022/components/component-renderer/component-renderer.component.mjs +0 -313
  42. package/dist/lib/esm2022/components/crud-field/crud-field.component.mjs +0 -301
  43. package/dist/lib/esm2022/components/crud-form/constants.mjs +0 -14
  44. package/dist/lib/esm2022/components/crud-form/crud-form.component.mjs +0 -139
  45. package/dist/lib/esm2022/components/crud-form/types.mjs +0 -2
  46. package/dist/lib/esm2022/components/empty-state/empty-state.component.mjs +0 -348
  47. package/dist/lib/esm2022/components/fieldset/fieldset.component.mjs +0 -225
  48. package/dist/lib/esm2022/components/filter/filter.component.mjs +0 -689
  49. package/dist/lib/esm2022/components/for-angular-components.module.mjs +0 -71
  50. package/dist/lib/esm2022/components/index.mjs +0 -20
  51. package/dist/lib/esm2022/components/layout/layout.component.mjs +0 -176
  52. package/dist/lib/esm2022/components/list/constants.mjs +0 -6
  53. package/dist/lib/esm2022/components/list/list.component.mjs +0 -1236
  54. package/dist/lib/esm2022/components/list-item/list-item.component.mjs +0 -408
  55. package/dist/lib/esm2022/components/model-renderer/model-renderer.component.mjs +0 -138
  56. package/dist/lib/esm2022/components/pagination/constants.mjs +0 -2
  57. package/dist/lib/esm2022/components/pagination/pagination.component.mjs +0 -323
  58. package/dist/lib/esm2022/components/searchbar/searchbar.component.mjs +0 -493
  59. package/dist/lib/esm2022/decaf-ts-for-angular.mjs +0 -5
  60. package/dist/lib/esm2022/directives/collapsable.directive.mjs +0 -28
  61. package/dist/lib/esm2022/directives/index.mjs +0 -2
  62. package/dist/lib/esm2022/engine/DynamicModule.mjs +0 -18
  63. package/dist/lib/esm2022/engine/NgxBaseComponent.mjs +0 -539
  64. package/dist/lib/esm2022/engine/NgxCrudFormField.mjs +0 -125
  65. package/dist/lib/esm2022/engine/NgxFormService.mjs +0 -315
  66. package/dist/lib/esm2022/engine/NgxRenderingEngine.mjs +0 -192
  67. package/dist/lib/esm2022/engine/NgxRenderingEngine2.mjs +0 -332
  68. package/dist/lib/esm2022/engine/ValidatorFactory.mjs +0 -102
  69. package/dist/lib/esm2022/engine/constants.mjs +0 -160
  70. package/dist/lib/esm2022/engine/decorators.mjs +0 -38
  71. package/dist/lib/esm2022/engine/index.mjs +0 -17
  72. package/dist/lib/esm2022/engine/types.mjs +0 -4
  73. package/dist/lib/esm2022/for-angular.module.mjs +0 -118
  74. package/dist/lib/esm2022/helpers/index.mjs +0 -13
  75. package/dist/lib/esm2022/helpers/utils.mjs +0 -415
  76. package/dist/lib/esm2022/interfaces.mjs +0 -2
  77. package/dist/lib/esm2022/public-apis.mjs +0 -14
  78. package/dist/lib/fesm2022/decaf-ts-for-angular.mjs +0 -7109
  79. package/dist/lib/fesm2022/decaf-ts-for-angular.mjs.map +0 -1
  80. package/dist/lib/for-angular.module.d.ts +0 -45
  81. package/dist/lib/helpers/index.d.ts +0 -12
  82. package/dist/lib/helpers/utils.d.ts +0 -253
  83. package/dist/lib/index.d.ts +0 -5
  84. package/dist/lib/interfaces.d.ts +0 -28
  85. package/dist/lib/public-apis.d.ts +0 -13
@@ -1,539 +0,0 @@
1
- import { Input, Component, Inject, ViewChild, ElementRef, Output, EventEmitter, } from '@angular/core';
2
- import { getInjectablesRegistry, getLocaleFromClassName, stringToBoolean } from '../helpers/utils';
3
- import { Model } from '@decaf-ts/decorator-validation';
4
- import { InternalError, OperationKeys } from '@decaf-ts/db-decorators';
5
- import { BaseComponentProps } from './constants';
6
- import { NgxRenderingEngine2 } from './NgxRenderingEngine2';
7
- import { getLogger } from '../for-angular.module';
8
- import { Repository } from '@decaf-ts/core';
9
- import * as i0 from "@angular/core";
10
- /**
11
- * @description Base component class that provides common functionality for all Decaf components.
12
- * @summary The NgxBaseComponent serves as the foundation for all Decaf UI components, providing
13
- * shared functionality for localization, element references, and styling. This abstract class
14
- * implements common properties and methods that are used across the component library, ensuring
15
- * consistent behavior and reducing code duplication. Components that extend this class inherit
16
- * its capabilities for handling translations, accessing DOM elements, and applying custom styling.
17
- *
18
- * @template M - The model type that this component works with
19
- * @param {string} instance - The component instance token used for identification
20
- * @param {string} locale - The locale to be used for translations
21
- * @param {StringOrBoolean} translatable - Whether the component should be translated
22
- * @param {string} className - Additional CSS classes to apply to the component
23
- * @param {"ios" | "md" | undefined} mode - Component platform style
24
- *
25
- * @component NgxBaseComponent
26
- * @example
27
- * ```typescript
28
- * @Component({
29
- * selector: 'app-my-component',
30
- * templateUrl: './my-component.component.html',
31
- * styleUrls: ['./my-component.component.scss']
32
- * })
33
- * export class MyComponent extends NgxBaseComponent {
34
- * constructor(@Inject('instanceToken') instance: string) {
35
- * super(instance);
36
- * }
37
- *
38
- * ngOnInit() {
39
- * this.initialize();
40
- * // Component-specific initialization
41
- * }
42
- * }
43
- * ```
44
- * @mermaid
45
- * sequenceDiagram
46
- * participant App as Application
47
- * participant Comp as Component
48
- * participant Base as NgxBaseComponent
49
- * participant Engine as NgxRenderingEngine2
50
- *
51
- * App->>Comp: Create component
52
- * Comp->>Base: super(instance)
53
- * Base->>Base: Set componentName & componentLocale
54
- *
55
- * App->>Comp: Set @Input properties
56
- * Comp->>Base: ngOnChanges(changes)
57
- *
58
- * alt model changed
59
- * Base->>Base: getModel(model)
60
- * Base->>Engine: getDecorators(model, {})
61
- * Engine-->>Base: Return decorator metadata
62
- * Base->>Base: Configure mapper and item
63
- * Base->>Base: getLocale(translatable)
64
- * else locale/translatable changed
65
- * Base->>Base: getLocale(translatable)
66
- * end
67
- *
68
- * App->>Comp: ngOnInit()
69
- * Comp->>Base: initialize()
70
- * Base->>Base: Set initialized flag
71
- */
72
- export class NgxBaseComponent {
73
- /**
74
- * @description Creates an instance of NgxBaseComponent.
75
- * @summary Initializes a new instance of the base component with the provided instance token.
76
- * This constructor sets up the fundamental properties required by all Decaf components,
77
- * including the component name, locale settings, and logging capabilities. The instance
78
- * token is used for component identification and locale derivation.
79
- *
80
- * The constructor performs the following initialization steps:
81
- * 1. Sets the componentName from the provided instance token
82
- * 2. Derives the componentLocale from the class name using utility functions
83
- * 3. Initializes the logger instance for the component
84
- *
85
- * @param {string} instance - The component instance token used for identification
86
- *
87
- * @mermaid
88
- * sequenceDiagram
89
- * participant A as Angular
90
- * participant C as Component
91
- * participant B as NgxBaseComponent
92
- * participant U as Utils
93
- * participant L as Logger
94
- *
95
- * A->>C: new Component(instance)
96
- * C->>B: super(instance)
97
- * B->>B: Set componentName = instance
98
- * B->>U: getLocaleFromClassName(instance)
99
- * U-->>B: Return derived locale
100
- * B->>B: Set componentLocale
101
- * B->>L: getLogger(this)
102
- * L-->>B: Return logger instance
103
- * B->>B: Set logger
104
- *
105
- * @memberOf NgxBaseComponent
106
- */
107
- // eslint-disable-next-line @angular-eslint/prefer-inject
108
- constructor(instance) {
109
- this.instance = instance;
110
- /**
111
- * @description Dynamic properties configuration object.
112
- * @summary Contains key-value pairs of dynamic properties that can be applied to the component
113
- * at runtime. This flexible configuration object allows for dynamic property assignment without
114
- * requiring explicit input bindings for every possible configuration option. Properties from
115
- * this object are parsed and applied to the component instance through the parseProps method,
116
- * enabling customizable component behavior based on external configuration.
117
- *
118
- * @type {Record<string, unknown>}
119
- * @default {}
120
- * @memberOf NgxBaseComponent
121
- */
122
- this.props = {};
123
- /**
124
- * @description Configuration for list item rendering
125
- * @summary Defines how list items should be rendered in the component.
126
- * This property holds a configuration object that specifies the tag name
127
- * and other properties needed to render list items correctly. The tag property
128
- * identifies which component should be used to render each item in a list.
129
- * Additional properties can be included to customize the rendering behavior.
130
- *
131
- * @type {Record<string, unknown>}
132
- * @default {tag: ""}
133
- * @memberOf NgxBaseComponent
134
- */
135
- this.item = { tag: '' };
136
- /**
137
- * @description Primary key field name for the model.
138
- * @summary Specifies which field in the model should be used as the primary key.
139
- * This is typically used for identifying unique records in operations like update and delete.
140
- *
141
- * @type {string}
142
- * @default 'id'
143
- * @memberOf NgxBaseComponent
144
- */
145
- this.pk = 'id';
146
- /**
147
- * @description Available CRUD operations for this component.
148
- * @summary Defines which CRUD operations (Create, Read, Update, Delete) are available
149
- * for this component. This affects which operations can be performed on the data.
150
- *
151
- * @default [OperationKeys.READ]
152
- * @memberOf NgxBaseComponent
153
- */
154
- this.operations = [OperationKeys.READ];
155
- /**
156
- * @description Field mapping configuration.
157
- * @summary Defines how fields from the data model should be mapped to properties used by the component.
158
- * This allows for flexible data binding between the model and the component's display logic.
159
- *
160
- * @type {Record<string, string>}
161
- * @memberOf NgxBaseComponent
162
- */
163
- this.mapper = {};
164
- /**
165
- * @description Determines if the component should be translated.
166
- * @summary Controls whether the component's text content should be processed for translation.
167
- * When true, the component will attempt to translate text using the specified locale.
168
- * When false, text is displayed as-is without translation. This property accepts either
169
- * a boolean value or a string that can be converted to a boolean (e.g., 'true', 'false', '1', '0').
170
- *
171
- * @type {StringOrBoolean}
172
- * @default false
173
- * @memberOf NgxBaseComponent
174
- */
175
- this.translatable = true;
176
- /**
177
- * @description Additional CSS class names to apply to the component.
178
- * @summary Allows custom CSS classes to be added to the component's root element.
179
- * These classes are appended to any automatically generated classes based on other
180
- * component properties. Multiple classes can be provided as a space-separated string.
181
- * This provides a way to customize the component's appearance beyond the built-in styling options.
182
- *
183
- * @type {string}
184
- * @default ""
185
- * @memberOf NgxBaseComponent
186
- */
187
- this.className = '';
188
- /**
189
- * @description Component platform style.
190
- * @summary Controls the visual appearance of the component based on platform design guidelines.
191
- * The 'ios' mode follows iOS design patterns, while 'md' (Material Design) follows Android/Google
192
- * design patterns. This property affects various visual aspects such as animations, form elements,
193
- * and icons. Setting this property allows components to maintain platform-specific styling
194
- * for a more native look and feel.
195
- *
196
- * @type {("ios" | "md" | undefined)}
197
- * @default "md"
198
- * @memberOf NgxBaseComponent
199
- */
200
- this.mode = 'md';
201
- /**
202
- * @description Controls whether child components should be rendered
203
- * @summary Determines if child components should be rendered by the component.
204
- * This can be set to a boolean value or a string that can be converted to a boolean.
205
- * When true, child components defined in the model will be rendered. When false,
206
- * child components will be skipped. This provides control over the rendering depth.
207
- *
208
- * @type {string | StringOrBoolean}
209
- * @default true
210
- * @memberOf NgxBaseComponent
211
- */
212
- this.renderChild = true;
213
- /**
214
- * @description Flag indicating if the component has been initialized
215
- * @summary Tracks whether the component has completed its initialization process.
216
- * This flag is used to prevent duplicate initialization and to determine if
217
- * certain operations that require initialization can be performed.
218
- *
219
- * @type {boolean}
220
- * @default false
221
- */
222
- this.initialized = false;
223
- /**
224
- * @description Event emitter for custom renderer events.
225
- * @summary Emits custom events that occur within child components or the layout itself.
226
- * This allows parent components to listen for and respond to user interactions or
227
- * state changes within the grid layout. Events are passed up the component hierarchy
228
- * to enable coordinated behavior across the application.
229
- *
230
- * @type {EventEmitter<RendererCustomEvent>}
231
- * @memberOf NgxBaseComponent
232
- */
233
- this.listenEvent = new EventEmitter();
234
- /**
235
- * @description Reference to the rendering engine instance
236
- * @summary Provides access to the NgxRenderingEngine2 singleton instance,
237
- * which handles the rendering of components based on model definitions.
238
- * This engine is used to extract decorator metadata and render child components.
239
- *
240
- * @type {NgxRenderingEngine2}
241
- */
242
- this.renderingEngine = NgxRenderingEngine2.get();
243
- this.componentName = instance;
244
- this.componentLocale = getLocaleFromClassName(instance);
245
- this.logger = getLogger(this);
246
- this.getLocale(this.translatable);
247
- }
248
- /**
249
- * @description Getter for the repository instance.
250
- * @summary Provides a connection to the data layer for retrieving and manipulating data.
251
- * This method initializes the `_repository` property if it is not already set, ensuring
252
- * that a single instance of the repository is used throughout the component.
253
- *
254
- * The repository is used to perform CRUD operations on the data model, such as fetching data,
255
- * creating new items, updating existing items, and deleting items. It also provides methods
256
- * for querying and filtering data based on specific criteria.
257
- *
258
- * @returns {DecafRepository<Model>} The initialized repository instance.
259
- * @private
260
- * @memberOf NgxBaseComponent
261
- */
262
- get repository() {
263
- try {
264
- if (!this._repository) {
265
- const modelName = this.model.constructor.name;
266
- const constructor = Model.get(modelName);
267
- if (!constructor)
268
- throw new InternalError('Cannot find model. was it registered with @model?');
269
- this._repository = Repository.forModel(constructor);
270
- this.model = new constructor();
271
- }
272
- }
273
- catch (error) {
274
- throw new InternalError(error?.message || error);
275
- }
276
- return this._repository;
277
- }
278
- /**
279
- * @description Parses and applies properties from the props object to the component instance.
280
- * @summary This method iterates through the properties of the provided instance object
281
- * and applies any matching properties from the component's props configuration to the
282
- * component instance. This allows for dynamic property assignment based on configuration
283
- * stored in the props object, enabling flexible component customization without requiring
284
- * explicit property binding for every possible configuration option.
285
- *
286
- * The method performs a safe property assignment by checking if each key from the instance
287
- * exists in the props object before applying it. This prevents accidental property
288
- * overwriting and ensures only intended properties are modified.
289
- *
290
- * @param {KeyValue} instance - The component instance object to process
291
- * @return {void}
292
- *
293
- * @mermaid
294
- * sequenceDiagram
295
- * participant C as Component
296
- * participant B as NgxBaseComponent
297
- * participant P as Props Object
298
- *
299
- * C->>B: parseProps(instance)
300
- * B->>B: Get Object.keys(instance)
301
- * loop For each key in instance
302
- * B->>P: Check if key exists in this.props
303
- * alt Key exists in props
304
- * B->>B: Set this[key] = this.props[key]
305
- * else Key not in props
306
- * Note over B: Skip this key
307
- * end
308
- * end
309
- *
310
- * @protected
311
- * @memberOf NgxBaseComponent
312
- */
313
- parseProps(instance) {
314
- Object.keys(instance).forEach((key) => {
315
- if (Object.keys(this.props).includes(key))
316
- this[key] = this.props[key];
317
- });
318
- }
319
- /**
320
- * @description Handles changes to component inputs
321
- * @summary This Angular lifecycle hook is called when input properties change.
322
- * It responds to changes in the model, locale, or translatable properties by
323
- * updating the component's internal state accordingly. When the model changes,
324
- * it calls getModel to process the new model and getLocale to update the locale.
325
- * When locale or translatable properties change, it calls getLocale to update
326
- * the translation settings.
327
- *
328
- * @param {SimpleChanges} changes - Object containing changed properties
329
- * @return {void}
330
- */
331
- ngOnChanges(changes) {
332
- if (changes[BaseComponentProps.MODEL]) {
333
- const { currentValue } = changes[BaseComponentProps.MODEL];
334
- if (currentValue)
335
- this.getModel(currentValue);
336
- this.getLocale(this.translatable);
337
- }
338
- if (changes[BaseComponentProps.INITIALIZED] ||
339
- changes[BaseComponentProps.LOCALE] ||
340
- changes[BaseComponentProps.TRANSLATABLE])
341
- this.getLocale(this.translatable);
342
- }
343
- /**
344
- * @description Gets the appropriate locale string based on the translatable flag and available locales.
345
- * @summary Determines which locale string to use for translation based on the translatable flag
346
- * and available locale settings. This method first converts the translatable parameter to a boolean
347
- * using the stringToBoolean utility function. If translatable is false, it returns an empty string,
348
- * indicating no translation should be performed. If translatable is true, it checks for an explicitly
349
- * provided locale via the locale property. If no explicit locale is available, it falls back to the
350
- * componentLocale derived from the component's class name.
351
- *
352
- * @param {StringOrBoolean} translatable - Whether the component should be translated
353
- * @return {string} The locale string to use for translation, or empty string if not translatable
354
- *
355
- * @mermaid
356
- * sequenceDiagram
357
- * participant C as Component
358
- * participant N as NgxBaseComponent
359
- * participant S as StringUtils
360
- *
361
- * C->>N: getLocale(translatable)
362
- * N->>S: stringToBoolean(translatable)
363
- * S-->>N: Return boolean value
364
- * N->>N: Store in this.translatable
365
- * alt translatable is false
366
- * N-->>C: Return empty string
367
- * else translatable is true
368
- * alt this.locale is defined
369
- * N-->>C: Return this.locale
370
- * else this.locale is not defined
371
- * N-->>C: Return this.componentLocale
372
- * end
373
- * end
374
- */
375
- getLocale(translatable) {
376
- this.translatable = stringToBoolean(translatable);
377
- if (!this.translatable)
378
- return '';
379
- if (!this.locale)
380
- this.locale = this.componentLocale;
381
- return this.locale;
382
- }
383
- /**
384
- * @description Gets the route for the component
385
- * @summary Retrieves the route path for the component, generating one based on the model
386
- * if no route is explicitly set. This method checks if a route is already defined, and if not,
387
- * it creates a default route based on the model's constructor name. The generated route follows
388
- * the pattern '/model/{ModelName}'. This is useful for automatic routing in CRUD operations.
389
- *
390
- * @return {string} The route path for the component, or empty string if no route is available
391
- */
392
- getRoute() {
393
- if (!this.route && this.model instanceof Model)
394
- this.route = `/model/${this.model?.constructor.name}`;
395
- return this.route || '';
396
- }
397
- /**
398
- * @description Resolves and sets the component's model
399
- * @summary Processes the provided model parameter, which can be either a Model instance
400
- * or a string identifier. If a string is provided, it attempts to resolve the actual model
401
- * from the injectables registry. After resolving the model, it calls setModelDefinitions
402
- * to configure the component based on the model's metadata.
403
- *
404
- * @param {string | Model} model - The model instance or identifier string
405
- * @return {void}
406
- */
407
- getModel(model) {
408
- if (!(model instanceof Model))
409
- this.model = getInjectablesRegistry().get(model);
410
- this.setModelDefinitions(this.model);
411
- }
412
- /**
413
- * @description Configures component properties based on model metadata
414
- * @summary Extracts and applies configuration from the model's decorators to set up
415
- * the component. This method uses the rendering engine to retrieve decorator metadata
416
- * from the model, then configures the component's mapper and item properties accordingly.
417
- * It ensures the route is properly set and merges various properties from the model's
418
- * metadata into the component's configuration.
419
- *
420
- * @param {Model} model - The model to extract configuration from
421
- * @return {void}
422
- */
423
- setModelDefinitions(model) {
424
- if (model instanceof Model) {
425
- this.getRoute();
426
- this.model = model;
427
- const field = this.renderingEngine.getDecorators(this.model, {});
428
- const { props, item, children } = field;
429
- this.props = Object.assign(props || {}, { children: children || [] });
430
- if (item?.props?.['mapper'])
431
- this.mapper = item?.props['mapper'] || {};
432
- this.item = {
433
- tag: item?.tag || '',
434
- ...item?.props,
435
- ...(this.mapper ? { mapper: this.mapper } : {}),
436
- ...{ route: item?.props?.['route'] || this.route },
437
- };
438
- }
439
- }
440
- /**
441
- * @description Initializes the component
442
- * @summary Performs one-time initialization of the component. This method checks if
443
- * the component has already been initialized to prevent duplicate initialization.
444
- * When called for the first time, it sets the initialized flag to true and logs
445
- * an initialization message with the component name. This method is typically called
446
- * during the component's lifecycle setup.
447
- */
448
- initialize() {
449
- this.initialized = true;
450
- }
451
- /**
452
- * @description Handles custom events from child components.
453
- * @summary Receives events from child renderer components and forwards them to parent
454
- * components through the listenEvent output. This creates an event propagation chain
455
- * that allows events to bubble up through the component hierarchy, enabling coordinated
456
- * responses to user interactions across the layout structure.
457
- *
458
- * @param {RendererCustomEvent} event - The custom event from a child component
459
- * @return {void}
460
- *
461
- * @mermaid
462
- * sequenceDiagram
463
- * participant C as Child Component
464
- * participant L as NgxBaseComponent
465
- * participant P as Parent Component
466
- *
467
- * C->>L: Emit RendererCustomEvent
468
- * L->>L: handleEvent(event)
469
- * L->>P: listenEvent.emit(event)
470
- * Note over P: Handle event in parent
471
- *
472
- * @memberOf NgxBaseComponent
473
- */
474
- handleEvent(event) {
475
- this.listenEvent.emit(event);
476
- }
477
- /**
478
- * @description Tracks items in ngFor loops for optimal change detection.
479
- * @summary Provides a tracking function for Angular's *ngFor directive to optimize rendering
480
- * performance. This method generates unique identifiers for list items based on their index
481
- * and content, allowing Angular to efficiently track changes and minimize DOM manipulations
482
- * during list updates. The tracking function is essential for maintaining component state
483
- * and preventing unnecessary re-rendering of unchanged items.
484
- *
485
- * @param {number} index - The index of the item in the list
486
- * @param {KeyValue | string | number} item - The item data to track
487
- * @returns {string | number} A unique identifier for the item
488
- * @memberOf NgxBaseComponent
489
- */
490
- trackItemFn(index, item) {
491
- return `${index}-${item}`;
492
- }
493
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgxBaseComponent, deps: [{ token: 'instanceToken' }], target: i0.ɵɵFactoryTarget.Component }); }
494
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NgxBaseComponent, isStandalone: true, selector: "ng-component", inputs: { rendererId: "rendererId", model: "model", props: "props", item: "item", pk: "pk", route: "route", operations: "operations", uid: "uid", mapper: "mapper", locale: "locale", translatable: "translatable", className: "className", mode: "mode", renderChild: "renderChild" }, outputs: { listenEvent: "listenEvent" }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: '', isInline: true }); }
495
- }
496
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgxBaseComponent, decorators: [{
497
- type: Component,
498
- args: [{
499
- standalone: true,
500
- template: '',
501
- }]
502
- }], ctorParameters: () => [{ type: undefined, decorators: [{
503
- type: Inject,
504
- args: ['instanceToken']
505
- }] }], propDecorators: { component: [{
506
- type: ViewChild,
507
- args: ['component', { read: ElementRef, static: true }]
508
- }], rendererId: [{
509
- type: Input
510
- }], model: [{
511
- type: Input
512
- }], props: [{
513
- type: Input
514
- }], item: [{
515
- type: Input
516
- }], pk: [{
517
- type: Input
518
- }], route: [{
519
- type: Input
520
- }], operations: [{
521
- type: Input
522
- }], uid: [{
523
- type: Input
524
- }], mapper: [{
525
- type: Input
526
- }], locale: [{
527
- type: Input
528
- }], translatable: [{
529
- type: Input
530
- }], className: [{
531
- type: Input
532
- }], mode: [{
533
- type: Input
534
- }], renderChild: [{
535
- type: Input
536
- }], listenEvent: [{
537
- type: Output
538
- }] } });
539
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTmd4QmFzZUNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZW5naW5lL05neEJhc2VDb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLEtBQUssRUFDTCxTQUFTLEVBQ1QsTUFBTSxFQUNOLFNBQVMsRUFDVCxVQUFVLEVBR1YsTUFBTSxFQUNOLFlBQVksR0FDYixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLHNCQUFzQixFQUN0QixlQUFlLEVBQ2hCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3ZELE9BQU8sRUFFTCxhQUFhLEVBQ2IsYUFBYSxFQUNkLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2pELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUVsRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7O0FBRTVDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkRHO0FBS0gsTUFBTSxPQUFnQixnQkFBZ0I7SUFzU3BDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FpQ0c7SUFDSCx5REFBeUQ7SUFDekQsWUFBeUQsUUFBZ0I7UUFBaEIsYUFBUSxHQUFSLFFBQVEsQ0FBUTtRQWhRekU7Ozs7Ozs7Ozs7O1dBV0c7UUFFSCxVQUFLLEdBQTRCLEVBQUUsQ0FBQztRQUVwQzs7Ozs7Ozs7Ozs7V0FXRztRQUVILFNBQUksR0FBNEIsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUM7UUFFNUM7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ICBJbmplY3QsXG4gIFZpZXdDaGlsZCxcbiAgRWxlbWVudFJlZixcbiAgT25DaGFuZ2VzLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBPdXRwdXQsXG4gIEV2ZW50RW1pdHRlcixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBLZXlWYWx1ZSwgUmVuZGVyZXJDdXN0b21FdmVudCwgU3RyaW5nT3JCb29sZWFuIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge1xuICBnZXRJbmplY3RhYmxlc1JlZ2lzdHJ5LFxuICBnZXRMb2NhbGVGcm9tQ2xhc3NOYW1lLFxuICBzdHJpbmdUb0Jvb2xlYW5cbn0gZnJvbSAnLi4vaGVscGVycy91dGlscyc7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gJ0BkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvbic7XG5pbXBvcnQge1xuICBDcnVkT3BlcmF0aW9ucyxcbiAgSW50ZXJuYWxFcnJvcixcbiAgT3BlcmF0aW9uS2V5c1xufSBmcm9tICdAZGVjYWYtdHMvZGItZGVjb3JhdG9ycyc7XG5pbXBvcnQgeyBCYXNlQ29tcG9uZW50UHJvcHMgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBOZ3hSZW5kZXJpbmdFbmdpbmUyIH0gZnJvbSAnLi9OZ3hSZW5kZXJpbmdFbmdpbmUyJztcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJ0BkZWNhZi10cy9sb2dnaW5nJztcbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gJy4uL2Zvci1hbmd1bGFyLm1vZHVsZSc7XG5pbXBvcnQgeyBEZWNhZlJlcG9zaXRvcnkgfSBmcm9tICcuLi9jb21wb25lbnRzL2xpc3QvY29uc3RhbnRzJztcbmltcG9ydCB7IFJlcG9zaXRvcnkgfSBmcm9tICdAZGVjYWYtdHMvY29yZSc7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEJhc2UgY29tcG9uZW50IGNsYXNzIHRoYXQgcHJvdmlkZXMgY29tbW9uIGZ1bmN0aW9uYWxpdHkgZm9yIGFsbCBEZWNhZiBjb21wb25lbnRzLlxuICogQHN1bW1hcnkgVGhlIE5neEJhc2VDb21wb25lbnQgc2VydmVzIGFzIHRoZSBmb3VuZGF0aW9uIGZvciBhbGwgRGVjYWYgVUkgY29tcG9uZW50cywgcHJvdmlkaW5nXG4gKiBzaGFyZWQgZnVuY3Rpb25hbGl0eSBmb3IgbG9jYWxpemF0aW9uLCBlbGVtZW50IHJlZmVyZW5jZXMsIGFuZCBzdHlsaW5nLiBUaGlzIGFic3RyYWN0IGNsYXNzXG4gKiBpbXBsZW1lbnRzIGNvbW1vbiBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzIHRoYXQgYXJlIHVzZWQgYWNyb3NzIHRoZSBjb21wb25lbnQgbGlicmFyeSwgZW5zdXJpbmdcbiAqIGNvbnNpc3RlbnQgYmVoYXZpb3IgYW5kIHJlZHVjaW5nIGNvZGUgZHVwbGljYXRpb24uIENvbXBvbmVudHMgdGhhdCBleHRlbmQgdGhpcyBjbGFzcyBpbmhlcml0XG4gKiBpdHMgY2FwYWJpbGl0aWVzIGZvciBoYW5kbGluZyB0cmFuc2xhdGlvbnMsIGFjY2Vzc2luZyBET00gZWxlbWVudHMsIGFuZCBhcHBseWluZyBjdXN0b20gc3R5bGluZy5cbiAqXG4gKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlIHRoYXQgdGhpcyBjb21wb25lbnQgd29ya3Mgd2l0aFxuICogQHBhcmFtIHtzdHJpbmd9IGluc3RhbmNlIC0gVGhlIGNvbXBvbmVudCBpbnN0YW5jZSB0b2tlbiB1c2VkIGZvciBpZGVudGlmaWNhdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IGxvY2FsZSAtIFRoZSBsb2NhbGUgdG8gYmUgdXNlZCBmb3IgdHJhbnNsYXRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ09yQm9vbGVhbn0gdHJhbnNsYXRhYmxlIC0gV2hldGhlciB0aGUgY29tcG9uZW50IHNob3VsZCBiZSB0cmFuc2xhdGVkXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lIC0gQWRkaXRpb25hbCBDU1MgY2xhc3NlcyB0byBhcHBseSB0byB0aGUgY29tcG9uZW50XG4gKiBAcGFyYW0ge1wiaW9zXCIgfCBcIm1kXCIgfCB1bmRlZmluZWR9IG1vZGUgLSBDb21wb25lbnQgcGxhdGZvcm0gc3R5bGVcbiAqXG4gKiBAY29tcG9uZW50IE5neEJhc2VDb21wb25lbnRcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBAQ29tcG9uZW50KHtcbiAqICAgc2VsZWN0b3I6ICdhcHAtbXktY29tcG9uZW50JyxcbiAqICAgdGVtcGxhdGVVcmw6ICcuL215LWNvbXBvbmVudC5jb21wb25lbnQuaHRtbCcsXG4gKiAgIHN0eWxlVXJsczogWycuL215LWNvbXBvbmVudC5jb21wb25lbnQuc2NzcyddXG4gKiB9KVxuICogZXhwb3J0IGNsYXNzIE15Q29tcG9uZW50IGV4dGVuZHMgTmd4QmFzZUNvbXBvbmVudCB7XG4gKiAgIGNvbnN0cnVjdG9yKEBJbmplY3QoJ2luc3RhbmNlVG9rZW4nKSBpbnN0YW5jZTogc3RyaW5nKSB7XG4gKiAgICAgc3VwZXIoaW5zdGFuY2UpO1xuICogICB9XG4gKlxuICogICBuZ09uSW5pdCgpIHtcbiAqICAgICB0aGlzLmluaXRpYWxpemUoKTtcbiAqICAgICAvLyBDb21wb25lbnQtc3BlY2lmaWMgaW5pdGlhbGl6YXRpb25cbiAqICAgfVxuICogfVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEFwcCBhcyBBcHBsaWNhdGlvblxuICogICBwYXJ0aWNpcGFudCBDb21wIGFzIENvbXBvbmVudFxuICogICBwYXJ0aWNpcGFudCBCYXNlIGFzIE5neEJhc2VDb21wb25lbnRcbiAqICAgcGFydGljaXBhbnQgRW5naW5lIGFzIE5neFJlbmRlcmluZ0VuZ2luZTJcbiAqXG4gKiAgIEFwcC0+PkNvbXA6IENyZWF0ZSBjb21wb25lbnRcbiAqICAgQ29tcC0+PkJhc2U6IHN1cGVyKGluc3RhbmNlKVxuICogICBCYXNlLT4+QmFzZTogU2V0IGNvbXBvbmVudE5hbWUgJiBjb21wb25lbnRMb2NhbGVcbiAqXG4gKiAgIEFwcC0+PkNvbXA6IFNldCBASW5wdXQgcHJvcGVydGllc1xuICogICBDb21wLT4+QmFzZTogbmdPbkNoYW5nZXMoY2hhbmdlcylcbiAqXG4gKiAgIGFsdCBtb2RlbCBjaGFuZ2VkXG4gKiAgICAgQmFzZS0+PkJhc2U6IGdldE1vZGVsKG1vZGVsKVxuICogICAgIEJhc2UtPj5FbmdpbmU6IGdldERlY29yYXRvcnMobW9kZWwsIHt9KVxuICogICAgIEVuZ2luZS0tPj5CYXNlOiBSZXR1cm4gZGVjb3JhdG9yIG1ldGFkYXRhXG4gKiAgICAgQmFzZS0+PkJhc2U6IENvbmZpZ3VyZSBtYXBwZXIgYW5kIGl0ZW1cbiAqICAgICBCYXNlLT4+QmFzZTogZ2V0TG9jYWxlKHRyYW5zbGF0YWJsZSlcbiAqICAgZWxzZSBsb2NhbGUvdHJhbnNsYXRhYmxlIGNoYW5nZWRcbiAqICAgICBCYXNlLT4+QmFzZTogZ2V0TG9jYWxlKHRyYW5zbGF0YWJsZSlcbiAqICAgZW5kXG4gKlxuICogICBBcHAtPj5Db21wOiBuZ09uSW5pdCgpXG4gKiAgIENvbXAtPj5CYXNlOiBpbml0aWFsaXplKClcbiAqICAgQmFzZS0+PkJhc2U6IFNldCBpbml0aWFsaXplZCBmbGFnXG4gKi9cbkBDb21wb25lbnQoe1xuICBzdGFuZGFsb25lOiB0cnVlLFxuICB0ZW1wbGF0ZTogJycsXG59KVxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE5neEJhc2VDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZmVyZW5jZSB0byB0aGUgY29tcG9uZW50J3MgZWxlbWVudC5cbiAgICogQHN1bW1hcnkgUHJvdmlkZXMgZGlyZWN0IGFjY2VzcyB0byB0aGUgbmF0aXZlIERPTSBlbGVtZW50IG9mIHRoZSBjb21wb25lbnQgdGhyb3VnaCBBbmd1bGFyJ3NcbiAgICogVmlld0NoaWxkIGRlY29yYXRvci4gVGhpcyByZWZlcmVuY2UgY2FuIGJlIHVzZWQgdG8gbWFuaXB1bGF0ZSB0aGUgRE9NIGVsZW1lbnQgZGlyZWN0bHksXG4gICAqIGFwcGx5IGN1c3RvbSBzdHlsZXMsIG9yIGFjY2VzcyBuYXRpdmUgZWxlbWVudCBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzLiBUaGUgZWxlbWVudCBpc1xuICAgKiBpZGVudGlmaWVkIGJ5IHRoZSAnY29tcG9uZW50JyB0ZW1wbGF0ZSByZWZlcmVuY2UgdmFyaWFibGUuXG4gICAqXG4gICAqIEB0eXBlIHtFbGVtZW50UmVmfVxuICAgKiBAbWVtYmVyT2YgTmd4QmFzZUNvbXBvbmVudFxuICAgKi9cbiAgQFZpZXdDaGlsZCgnY29tcG9uZW50JywgeyByZWFkOiBFbGVtZW50UmVmLCBzdGF0aWM6IHRydWUgfSlcbiAgY29tcG9uZW50ITogRWxlbWVudFJlZjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBuYW1lIG9mIHRoZSBjb21wb25lbnQuXG4gICAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgbmFtZSBvZiB0aGUgY29tcG9uZW50LCB3aGljaCBpcyB0eXBpY2FsbHkgZGVyaXZlZCBmcm9tIHRoZSBjbGFzcyBuYW1lLlxuICAgKiBUaGlzIHByb3BlcnR5IGlzIHVzZWQgaW50ZXJuYWxseSBmb3IgdmFyaW91cyBwdXJwb3NlcyBzdWNoIGFzIGxvZ2dpbmcsIGRlcml2aW5nIHRoZSBkZWZhdWx0XG4gICAqIGxvY2FsZSwgYW5kIHBvdGVudGlhbGx5IGZvciBjb21wb25lbnQgaWRlbnRpZmljYXRpb24gaW4gZGVidWdnaW5nIG9yIGVycm9yIHJlcG9ydGluZy5cbiAgICpcbiAgICogVGhlIGBjb21wb25lbnROYW1lYCBpcyBzZXQgZHVyaW5nIHRoZSBjb21wb25lbnQncyBpbml0aWFsaXphdGlvbiBwcm9jZXNzIGFuZCBzaG91bGQgbm90XG4gICAqIGJlIG1vZGlmaWVkIGV4dGVybmFsbHkuIEl0J3MgbWFya2VkIGFzIHByb3RlY3RlZCB0byBhbGxvdyBhY2Nlc3MgaW4gZGVyaXZlZCBjbGFzc2VzIHdoaWxlXG4gICAqIHByZXZlbnRpbmcgZGlyZWN0IGFjY2VzcyBmcm9tIG91dHNpZGUgdGhlIGNvbXBvbmVudCBoaWVyYXJjaHkuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBwcm90ZWN0ZWRcbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gSW5zaWRlIGEgZGVyaXZlZCBjb21wb25lbnQgY2xhc3NcbiAgICogY29uc29sZS5sb2codGhpcy5jb21wb25lbnROYW1lKTsgLy8gT3V0cHV0czogXCJNeUN1c3RvbUNvbXBvbmVudFwiXG4gICAqL1xuICBjb21wb25lbnROYW1lITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSByZW5kZXJlci5cbiAgICogQHN1bW1hcnkgQSB1bmlxdWUgaWRlbnRpZmllciB1c2VkIHRvIHJlZmVyZW5jZSB0aGUgY29tcG9uZW50J3MgcmVuZGVyZXIgaW5zdGFuY2UuXG4gICAqIFRoaXMgY2FuIGJlIHVzZWQgZm9yIHRhcmdldGluZyBzcGVjaWZpYyByZW5kZXJlciBpbnN0YW5jZXMgd2hlbiBtdWx0aXBsZSBjb21wb25lbnRzXG4gICAqIGFyZSBwcmVzZW50IG9uIHRoZSBzYW1lIHBhZ2UuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBOZ3hCYXNlQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICByZW5kZXJlcklkITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVwb3NpdG9yeSBtb2RlbCBmb3IgZGF0YSBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBUaGUgZGF0YSBtb2RlbCByZXBvc2l0b3J5IHRoYXQgdGhpcyBjb21wb25lbnQgd2lsbCB1c2UgZm9yIENSVUQgb3BlcmF0aW9ucy5cbiAgICogVGhpcyBwcm92aWRlcyBhIGNvbm5lY3Rpb24gdG8gdGhlIGRhdGEgbGF5ZXIgZm9yIHJldHJpZXZpbmcgYW5kIG1hbmlwdWxhdGluZyBkYXRhLlxuICAgKlxuICAgKiBAdHlwZSB7TW9kZWx8IHVuZGVmaW5lZH1cbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG1vZGVsITogIE1vZGVsIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHJlcG9zaXRvcnkgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIGRhdGEgbW9kZWwuXG4gICAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgY29ubmVjdGlvbiB0byB0aGUgZGF0YSBsYXllciBmb3IgcmV0cmlldmluZyBhbmQgbWFuaXB1bGF0aW5nIGRhdGEuXG4gICAqIFRoaXMgaXMgYW4gaW5zdGFuY2Ugb2YgdGhlIGBEZWNhZlJlcG9zaXRvcnlgIGNsYXNzIGZyb20gdGhlIGBAZGVjYWYtdHMvY29yZWAgcGFja2FnZSxcbiAgICogd2hpY2ggaXMgaW5pdGlhbGl6ZWQgaW4gdGhlIGByZXBvc2l0b3J5YCBnZXR0ZXIgbWV0aG9kLlxuICAgKlxuICAgKiBUaGUgcmVwb3NpdG9yeSBpcyB1c2VkIHRvIHBlcmZvcm0gQ1JVRCAoQ3JlYXRlLCBSZWFkLCBVcGRhdGUsIERlbGV0ZSkgb3BlcmF0aW9ucyBvbiB0aGVcbiAgICogZGF0YSBtb2RlbCwgc3VjaCBhcyBmZXRjaGluZyBkYXRhLCBjcmVhdGluZyBuZXcgaXRlbXMsIHVwZGF0aW5nIGV4aXN0aW5nIGl0ZW1zLCBhbmQgZGVsZXRpbmdcbiAgICogaXRlbXMuIEl0IGFsc28gcHJvdmlkZXMgbWV0aG9kcyBmb3IgcXVlcnlpbmcgYW5kIGZpbHRlcmluZyBkYXRhIGJhc2VkIG9uIHNwZWNpZmljIGNyaXRlcmlhLlxuICAgKlxuICAgKiBAdHlwZSB7RGVjYWZSZXBvc2l0b3J5PE1vZGVsPn1cbiAgICogQHByaXZhdGVcbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIHByb3RlY3RlZCBfcmVwb3NpdG9yeT86IERlY2FmUmVwb3NpdG9yeTxNb2RlbD47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEeW5hbWljIHByb3BlcnRpZXMgY29uZmlndXJhdGlvbiBvYmplY3QuXG4gICAqIEBzdW1tYXJ5IENvbnRhaW5zIGtleS12YWx1ZSBwYWlycyBvZiBkeW5hbWljIHByb3BlcnRpZXMgdGhhdCBjYW4gYmUgYXBwbGllZCB0byB0aGUgY29tcG9uZW50XG4gICAqIGF0IHJ1bnRpbWUuIFRoaXMgZmxleGlibGUgY29uZmlndXJhdGlvbiBvYmplY3QgYWxsb3dzIGZvciBkeW5hbWljIHByb3BlcnR5IGFzc2lnbm1lbnQgd2l0aG91dFxuICAgKiByZXF1aXJpbmcgZXhwbGljaXQgaW5wdXQgYmluZGluZ3MgZm9yIGV2ZXJ5IHBvc3NpYmxlIGNvbmZpZ3VyYXRpb24gb3B0aW9uLiBQcm9wZXJ0aWVzIGZyb21cbiAgICogdGhpcyBvYmplY3QgYXJlIHBhcnNlZCBhbmQgYXBwbGllZCB0byB0aGUgY29tcG9uZW50IGluc3RhbmNlIHRocm91Z2ggdGhlIHBhcnNlUHJvcHMgbWV0aG9kLFxuICAgKiBlbmFibGluZyBjdXN0b21pemFibGUgY29tcG9uZW50IGJlaGF2aW9yIGJhc2VkIG9uIGV4dGVybmFsIGNvbmZpZ3VyYXRpb24uXG4gICAqXG4gICAqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn1cbiAgICogQGRlZmF1bHQge31cbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29uZmlndXJhdGlvbiBmb3IgbGlzdCBpdGVtIHJlbmRlcmluZ1xuICAgKiBAc3VtbWFyeSBEZWZpbmVzIGhvdyBsaXN0IGl0ZW1zIHNob3VsZCBiZSByZW5kZXJlZCBpbiB0aGUgY29tcG9uZW50LlxuICAgKiBUaGlzIHByb3BlcnR5IGhvbGRzIGEgY29uZmlndXJhdGlvbiBvYmplY3QgdGhhdCBzcGVjaWZpZXMgdGhlIHRhZyBuYW1lXG4gICAqIGFuZCBvdGhlciBwcm9wZXJ0aWVzIG5lZWRlZCB0byByZW5kZXIgbGlzdCBpdGVtcyBjb3JyZWN0bHkuIFRoZSB0YWcgcHJvcGVydHlcbiAgICogaWRlbnRpZmllcyB3aGljaCBjb21wb25lbnQgc2hvdWxkIGJlIHVzZWQgdG8gcmVuZGVyIGVhY2ggaXRlbSBpbiBhIGxpc3QuXG4gICAqIEFkZGl0aW9uYWwgcHJvcGVydGllcyBjYW4gYmUgaW5jbHVkZWQgdG8gY3VzdG9taXplIHRoZSByZW5kZXJpbmcgYmVoYXZpb3IuXG4gICAqXG4gICAqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn1cbiAgICogQGRlZmF1bHQge3RhZzogXCJcIn1cbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGl0ZW06IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0geyB0YWc6ICcnIH07XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmltYXJ5IGtleSBmaWVsZCBuYW1lIGZvciB0aGUgbW9kZWwuXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB3aGljaCBmaWVsZCBpbiB0aGUgbW9kZWwgc2hvdWxkIGJlIHVzZWQgYXMgdGhlIHByaW1hcnkga2V5LlxuICAgKiBUaGlzIGlzIHR5cGljYWxseSB1c2VkIGZvciBpZGVudGlmeWluZyB1bmlxdWUgcmVjb3JkcyBpbiBvcGVyYXRpb25zIGxpa2UgdXBkYXRlIGFuZCBkZWxldGUuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBkZWZhdWx0ICdpZCdcbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHBrOiBzdHJpbmcgPSAnaWQnO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQmFzZSByb3V0ZSBmb3IgbmF2aWdhdGlvbiByZWxhdGVkIHRvIHRoaXMgY29tcG9uZW50LlxuICAgKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBiYXNlIHJvdXRlIHBhdGggdXNlZCBmb3IgbmF2aWdhdGlvbiBhY3Rpb25zIHJlbGF0ZWQgdG8gdGhpcyBjb21wb25lbnQuXG4gICAqIFRoaXMgaXMgb2Z0ZW4gdXNlZCBhcyBhIHByZWZpeCBmb3IgY29uc3RydWN0aW5nIG5hdmlnYXRpb24gVVJMcy5cbiAgICpcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHJvdXRlITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXZhaWxhYmxlIENSVUQgb3BlcmF0aW9ucyBmb3IgdGhpcyBjb21wb25lbnQuXG4gICAqIEBzdW1tYXJ5IERlZmluZXMgd2hpY2ggQ1JVRCBvcGVyYXRpb25zIChDcmVhdGUsIFJlYWQsIFVwZGF0ZSwgRGVsZXRlKSBhcmUgYXZhaWxhYmxlXG4gICAqIGZvciB0aGlzIGNvbXBvbmVudC4gVGhpcyBhZmZlY3RzIHdoaWNoIG9wZXJhdGlvbnMgY2FuIGJlIHBlcmZvcm1lZCBvbiB0aGUgZGF0YS5cbiAgICpcbiAgICogQGRlZmF1bHQgW09wZXJhdGlvbktleXMuUkVBRF1cbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG9wZXJhdGlvbnM6IENydWRPcGVyYXRpb25zW10gPSBbT3BlcmF0aW9uS2V5cy5SRUFEXTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgY3VycmVudCByZWNvcmQuXG4gICAqIEBzdW1tYXJ5IEEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBjdXJyZW50IHJlY29yZCBiZWluZyBkaXNwbGF5ZWQgb3IgbWFuaXB1bGF0ZWQuXG4gICAqIFRoaXMgaXMgdHlwaWNhbGx5IHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCB0aGUgcHJpbWFyeSBrZXkgZm9yIG9wZXJhdGlvbnMgb24gc3BlY2lmaWMgcmVjb3Jkcy5cbiAgICpcbiAgICogQHR5cGUge3N0cmluZyB8IG51bWJlcn1cbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHVpZCE6IHN0cmluZyB8IG51bWJlcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZpZWxkIG1hcHBpbmcgY29uZmlndXJhdGlvbi5cbiAgICogQHN1bW1hcnkgRGVmaW5lcyBob3cgZmllbGRzIGZyb20gdGhlIGRhdGEgbW9kZWwgc2hvdWxkIGJlIG1hcHBlZCB0byBwcm9wZXJ0aWVzIHVzZWQgYnkgdGhlIGNvbXBvbmVudC5cbiAgICogVGhpcyBhbGxvd3MgZm9yIGZsZXhpYmxlIGRhdGEgYmluZGluZyBiZXR3ZWVuIHRoZSBtb2RlbCBhbmQgdGhlIGNvbXBvbmVudCdzIGRpc3BsYXkgbG9naWMuXG4gICAqXG4gICAqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+fVxuICAgKiBAbWVtYmVyT2YgTmd4QmFzZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgbWFwcGVyOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbG9jYWxlIHRvIGJlIHVzZWQgZm9yIHRyYW5zbGF0aW9ucy5cbiAgICogQHN1bW1hcnkgU3BlY2lmaWVzIHRoZSBsb2NhbGUgaWRlbnRpZmllciB0byB1c2Ugd2hlbiB0cmFuc2xhdGluZyBjb21wb25lbnQgdGV4dC5cbiAgICogVGhpcyBjYW4gYmUgc2V0IGV4cGxpY2l0bHkgdmlhIGlucHV0IHByb3BlcnR5IHRvIG92ZXJyaWRlIHRoZSBhdXRvbWF0aWNhbGx5IGRlcml2ZWRcbiAgICogbG9jYWxlIGZyb20gdGhlIGNvbXBvbmVudCBuYW1lLiBUaGUgbG9jYWxlIGlzIHR5cGljYWxseSBhIGxhbmd1YWdlIGNvZGUgKGUuZy4sICdlbicsICdmcicpXG4gICAqIG9yIGEgbGFuZ3VhZ2UtcmVnaW9uIGNvZGUgKGUuZy4sICdlbi1VUycsICdmci1DQScpIHRoYXQgZGV0ZXJtaW5lcyB3aGljaCB0cmFuc2xhdGlvblxuICAgKiBzZXQgdG8gdXNlIGZvciB0aGUgY29tcG9uZW50J3MgdGV4dCBjb250ZW50LlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKiBAbWVtYmVyT2YgTmd4QmFzZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgbG9jYWxlITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGV0ZXJtaW5lcyBpZiB0aGUgY29tcG9uZW50IHNob3VsZCBiZSB0cmFuc2xhdGVkLlxuICAgKiBAc3VtbWFyeSBDb250cm9scyB3aGV0aGVyIHRoZSBjb21wb25lbnQncyB0ZXh0IGNvbnRlbnQgc2hvdWxkIGJlIHByb2Nlc3NlZCBmb3IgdHJhbnNsYXRpb24uXG4gICAqIFdoZW4gdHJ1ZSwgdGhlIGNvbXBvbmVudCB3aWxsIGF0dGVtcHQgdG8gdHJhbnNsYXRlIHRleHQgdXNpbmcgdGhlIHNwZWNpZmllZCBsb2NhbGUuXG4gICAqIFdoZW4gZmFsc2UsIHRleHQgaXMgZGlzcGxheWVkIGFzLWlzIHdpdGhvdXQgdHJhbnNsYXRpb24uIFRoaXMgcHJvcGVydHkgYWNjZXB0cyBlaXRoZXJcbiAgICogYSBib29sZWFuIHZhbHVlIG9yIGEgc3RyaW5nIHRoYXQgY2FuIGJlIGNvbnZlcnRlZCB0byBhIGJvb2xlYW4gKGUuZy4sICd0cnVlJywgJ2ZhbHNlJywgJzEnLCAnMCcpLlxuICAgKlxuICAgKiBAdHlwZSB7U3RyaW5nT3JCb29sZWFufVxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKiBAbWVtYmVyT2YgTmd4QmFzZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgdHJhbnNsYXRhYmxlOiBTdHJpbmdPckJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWRkaXRpb25hbCBDU1MgY2xhc3MgbmFtZXMgdG8gYXBwbHkgdG8gdGhlIGNvbXBvbmVudC5cbiAgICogQHN1bW1hcnkgQWxsb3dzIGN1c3RvbSBDU1MgY2xhc3NlcyB0byBiZSBhZGRlZCB0byB0aGUgY29tcG9uZW50J3Mgcm9vdCBlbGVtZW50LlxuICAgKiBUaGVzZSBjbGFzc2VzIGFyZSBhcHBlbmRlZCB0byBhbnkgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgY2xhc3NlcyBiYXNlZCBvbiBvdGhlclxuICAgKiBjb21wb25lbnQgcHJvcGVydGllcy4gTXVsdGlwbGUgY2xhc3NlcyBjYW4gYmUgcHJvdmlkZWQgYXMgYSBzcGFjZS1zZXBhcmF0ZWQgc3RyaW5nLlxuICAgKiBUaGlzIHByb3ZpZGVzIGEgd2F5IHRvIGN1c3RvbWl6ZSB0aGUgY29tcG9uZW50J3MgYXBwZWFyYW5jZSBiZXlvbmQgdGhlIGJ1aWx0LWluIHN0eWxpbmcgb3B0aW9ucy5cbiAgICpcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICogQGRlZmF1bHQgXCJcIlxuICAgKiBAbWVtYmVyT2YgTmd4QmFzZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgY2xhc3NOYW1lOiBzdHJpbmcgPSAnJztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbXBvbmVudCBwbGF0Zm9ybSBzdHlsZS5cbiAgICogQHN1bW1hcnkgQ29udHJvbHMgdGhlIHZpc3VhbCBhcHBlYXJhbmNlIG9mIHRoZSBjb21wb25lbnQgYmFzZWQgb24gcGxhdGZvcm0gZGVzaWduIGd1aWRlbGluZXMuXG4gICAqIFRoZSAnaW9zJyBtb2RlIGZvbGxvd3MgaU9TIGRlc2lnbiBwYXR0ZXJucywgd2hpbGUgJ21kJyAoTWF0ZXJpYWwgRGVzaWduKSBmb2xsb3dzIEFuZHJvaWQvR29vZ2xlXG4gICAqIGRlc2lnbiBwYXR0ZXJucy4gVGhpcyBwcm9wZXJ0eSBhZmZlY3RzIHZhcmlvdXMgdmlzdWFsIGFzcGVjdHMgc3VjaCBhcyBhbmltYXRpb25zLCBmb3JtIGVsZW1lbnRzLFxuICAgKiBhbmQgaWNvbnMuIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBhbGxvd3MgY29tcG9uZW50cyB0byBtYWludGFpbiBwbGF0Zm9ybS1zcGVjaWZpYyBzdHlsaW5nXG4gICAqIGZvciBhIG1vcmUgbmF0aXZlIGxvb2sgYW5kIGZlZWwuXG4gICAqXG4gICAqIEB0eXBlIHsoXCJpb3NcIiB8IFwibWRcIiB8IHVuZGVmaW5lZCl9XG4gICAqIEBkZWZhdWx0IFwibWRcIlxuICAgKiBAbWVtYmVyT2YgTmd4QmFzZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgbW9kZTogJ2lvcycgfCAnbWQnIHwgdW5kZWZpbmVkID0gJ21kJztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBsb2NhbGUgZGVyaXZlZCBmcm9tIHRoZSBjb21wb25lbnQncyBjbGFzcyBuYW1lLlxuICAgKiBAc3VtbWFyeSBTdG9yZXMgdGhlIGF1dG9tYXRpY2FsbHkgZGVyaXZlZCBsb2NhbGUgYmFzZWQgb24gdGhlIGNvbXBvbmVudCdzIGNsYXNzIG5hbWUuXG4gICAqIFRoaXMgaXMgZGV0ZXJtaW5lZCBkdXJpbmcgY29tcG9uZW50IGluaXRpYWxpemF0aW9uIGFuZCBzZXJ2ZXMgYXMgYSBmYWxsYmFjayB3aGVuIG5vXG4gICAqIGV4cGxpY2l0IGxvY2FsZSBpcyBwcm92aWRlZCB2aWEgdGhlIGxvY2FsZSBpbnB1dCBwcm9wZXJ0eS4gVGhlIGRlcml2YXRpb24gaXMgaGFuZGxlZFxuICAgKiBieSB0aGUgZ2V0TG9jYWxlRnJvbUNsYXNzTmFtZSB1dGlsaXR5IGZ1bmN0aW9uLCB3aGljaCBleHRyYWN0cyBhIGxvY2FsZSBpZGVudGlmaWVyXG4gICAqIGZyb20gdGhlIGNvbXBvbmVudCdzIGNsYXNzIG5hbWUuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBtZW1iZXJPZiBOZ3hCYXNlQ29tcG9uZW50XG4gICAqL1xuICBjb21wb25lbnRMb2NhbGUhOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb250cm9scyB3aGV0aGVyIGNoaWxkIGNvbXBvbmVudHMgc2hvdWxkIGJlIHJlbmRlcmVkXG4gICAqIEBzdW1tYXJ5IERldGVybWluZXMgaWYgY2hpbGQgY29tcG9uZW50cyBzaG91bGQgYmUgcmVuZGVyZWQgYnkgdGhlIGNvbXBvbmVudC5cbiAgICogVGhpcyBjYW4gYmUgc2V0IHRvIGEgYm9vbGVhbiB2YWx1ZSBvciBhIHN0cmluZyB0aGF0IGNhbiBiZSBjb252ZXJ0ZWQgdG8gYSBib29sZWFuLlxuICAgKiBXaGVuIHRydWUsIGNoaWxkIGNvbXBvbmVudHMgZGVmaW5lZCBpbiB0aGUgbW9kZWwgd2lsbCBiZSByZW5kZXJlZC4gV2hlbiBmYWxzZSxcbiAgICogY2hpbGQgY29tcG9uZW50cyB3aWxsIGJlIHNraXBwZWQuIFRoaXMgcHJvdmlkZXMgY29udHJvbCBvdmVyIHRoZSByZW5kZXJpbmcgZGVwdGguXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmcgfCBTdHJpbmdPckJvb2xlYW59XG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHJlbmRlckNoaWxkOiBzdHJpbmcgfCBTdHJpbmdPckJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmxhZyBpbmRpY2F0aW5nIGlmIHRoZSBjb21wb25lbnQgaGFzIGJlZW4gaW5pdGlhbGl6ZWRcbiAgICogQHN1bW1hcnkgVHJhY2tzIHdoZXRoZXIgdGhlIGNvbXBvbmVudCBoYXMgY29tcGxldGVkIGl0cyBpbml0aWFsaXphdGlvbiBwcm9jZXNzLlxuICAgKiBUaGlzIGZsYWcgaXMgdXNlZCB0byBwcmV2ZW50IGR1cGxpY2F0ZSBpbml0aWFsaXphdGlvbiBhbmQgdG8gZGV0ZXJtaW5lIGlmXG4gICAqIGNlcnRhaW4gb3BlcmF0aW9ucyB0aGF0IHJlcXVpcmUgaW5pdGlhbGl6YXRpb24gY2FuIGJlIHBlcmZvcm1lZC5cbiAgICpcbiAgICogQHR5cGUge2Jvb2xlYW59XG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICBpbml0aWFsaXplZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXZlbnQgZW1pdHRlciBmb3IgY3VzdG9tIHJlbmRlcmVyIGV2ZW50cy5cbiAgICogQHN1bW1hcnkgRW1pdHMgY3VzdG9tIGV2ZW50cyB0aGF0IG9jY3VyIHdpdGhpbiBjaGlsZCBjb21wb25lbnRzIG9yIHRoZSBsYXlvdXQgaXRzZWxmLlxuICAgKiBUaGlzIGFsbG93cyBwYXJlbnQgY29tcG9uZW50cyB0byBsaXN0ZW4gZm9yIGFuZCByZXNwb25kIHRvIHVzZXIgaW50ZXJhY3Rpb25zIG9yXG4gICAqIHN0YXRlIGNoYW5nZXMgd2l0aGluIHRoZSBncmlkIGxheW91dC4gRXZlbnRzIGFyZSBwYXNzZWQgdXAgdGhlIGNvbXBvbmVudCBoaWVyYXJjaHlcbiAgICogdG8gZW5hYmxlIGNvb3JkaW5hdGVkIGJlaGF2aW9yIGFjcm9zcyB0aGUgYXBwbGljYXRpb24uXG4gICAqXG4gICAqIEB0eXBlIHtFdmVudEVtaXR0ZXI8UmVuZGVyZXJDdXN0b21FdmVudD59XG4gICAqIEBtZW1iZXJPZiBOZ3hCYXNlQ29tcG9uZW50XG4gICAqL1xuICBAT3V0cHV0KClcbiAgbGlzdGVuRXZlbnQ6IEV2ZW50RW1pdHRlcjxSZW5kZXJlckN1c3RvbUV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8UmVuZGVyZXJDdXN0b21FdmVudD4oKTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZmVyZW5jZSB0byB0aGUgcmVuZGVyaW5nIGVuZ2luZSBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBQcm92aWRlcyBhY2Nlc3MgdG8gdGhlIE5neFJlbmRlcmluZ0VuZ2luZTIgc2luZ2xldG9uIGluc3RhbmNlLFxuICAgKiB3aGljaCBoYW5kbGVzIHRoZSByZW5kZXJpbmcgb2YgY29tcG9uZW50cyBiYXNlZCBvbiBtb2RlbCBkZWZpbml0aW9ucy5cbiAgICogVGhpcyBlbmdpbmUgaXMgdXNlZCB0byBleHRyYWN0IGRlY29yYXRvciBtZXRhZGF0YSBhbmQgcmVuZGVyIGNoaWxkIGNvbXBvbmVudHMuXG4gICAqXG4gICAqIEB0eXBlIHtOZ3hSZW5kZXJpbmdFbmdpbmUyfVxuICAgKi9cbiAgcmVuZGVyaW5nRW5naW5lOiBOZ3hSZW5kZXJpbmdFbmdpbmUyID1cbiAgICBOZ3hSZW5kZXJpbmdFbmdpbmUyLmdldCgpIGFzIHVua25vd24gYXMgTmd4UmVuZGVyaW5nRW5naW5lMjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExvZ2dlciBpbnN0YW5jZSBmb3IgdGhlIGNvbXBvbmVudC5cbiAgICogQHN1bW1hcnkgUHJvdmlkZXMgbG9nZ2luZyBjYXBhYmlsaXRpZXMgZm9yIHRoZSBjb21wb25lbnQsIGFsbG93aW5nIGZvciBjb25zaXN0ZW50XG4gICAqIGFuZCBzdHJ1Y3R1cmVkIGxvZ2dpbmcgb2YgaW5mb3JtYXRpb24sIHdhcm5pbmdzLCBhbmQgZXJyb3JzLiBUaGlzIGxvZ2dlciBpcyBpbml0aWFsaXplZFxuICAgKiBpbiB0aGUgbmdPbkluaXQgbWV0aG9kIHVzaW5nIHRoZSBnZXRMb2dnZXIgZnVuY3Rpb24gZnJvbSB0aGUgRm9yQW5ndWxhck1vZHVsZS5cbiAgICpcbiAgICogVGhlIGxvZ2dlciBpcyB1c2VkIHRocm91Z2hvdXQgdGhlIGNvbXBvbmVudCB0byByZWNvcmQgaW1wb3J0YW50IGV2ZW50cywgZGVidWcgaW5mb3JtYXRpb24sXG4gICAqIGFuZCBwb3RlbnRpYWwgaXNzdWVzLiBJdCBoZWxwcyBpbiBtb25pdG9yaW5nIHRoZSBjb21wb25lbnQncyBiZWhhdmlvciwgdHJhY2tpbmcgdGhlIGZsb3dcbiAgICogb2Ygb3BlcmF0aW9ucywgYW5kIGZhY2lsaXRhdGluZyBlYXNpZXIgZGVidWdnaW5nIGFuZCBtYWludGVuYW5jZS5cbiAgICpcbiAgICogQHR5cGUge0xvZ2dlcn1cbiAgICogQHByaXZhdGVcbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIGxvZ2dlciE6IExvZ2dlcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTmd4QmFzZUNvbXBvbmVudC5cbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIGJhc2UgY29tcG9uZW50IHdpdGggdGhlIHByb3ZpZGVkIGluc3RhbmNlIHRva2VuLlxuICAgKiBUaGlzIGNvbnN0cnVjdG9yIHNldHMgdXAgdGhlIGZ1bmRhbWVudGFsIHByb3BlcnRpZXMgcmVxdWlyZWQgYnkgYWxsIERlY2FmIGNvbXBvbmVudHMsXG4gICAqIGluY2x1ZGluZyB0aGUgY29tcG9uZW50IG5hbWUsIGxvY2FsZSBzZXR0aW5ncywgYW5kIGxvZ2dpbmcgY2FwYWJpbGl0aWVzLiBUaGUgaW5zdGFuY2VcbiAgICogdG9rZW4gaXMgdXNlZCBmb3IgY29tcG9uZW50IGlkZW50aWZpY2F0aW9uIGFuZCBsb2NhbGUgZGVyaXZhdGlvbi5cbiAgICpcbiAgICogVGhlIGNvbnN0cnVjdG9yIHBlcmZvcm1zIHRoZSBmb2xsb3dpbmcgaW5pdGlhbGl6YXRpb24gc3RlcHM6XG4gICAqIDEuIFNldHMgdGhlIGNvbXBvbmVudE5hbWUgZnJvbSB0aGUgcHJvdmlkZWQgaW5zdGFuY2UgdG9rZW5cbiAgICogMi4gRGVyaXZlcyB0aGUgY29tcG9uZW50TG9jYWxlIGZyb20gdGhlIGNsYXNzIG5hbWUgdXNpbmcgdXRpbGl0eSBmdW5jdGlvbnNcbiAgICogMy4gSW5pdGlhbGl6ZXMgdGhlIGxvZ2dlciBpbnN0YW5jZSBmb3IgdGhlIGNvbXBvbmVudFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gaW5zdGFuY2UgLSBUaGUgY29tcG9uZW50IGluc3RhbmNlIHRva2VuIHVzZWQgZm9yIGlkZW50aWZpY2F0aW9uXG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IEEgYXMgQW5ndWxhclxuICAgKiAgIHBhcnRpY2lwYW50IEMgYXMgQ29tcG9uZW50XG4gICAqICAgcGFydGljaXBhbnQgQiBhcyBOZ3hCYXNlQ29tcG9uZW50XG4gICAqICAgcGFydGljaXBhbnQgVSBhcyBVdGlsc1xuICAgKiAgIHBhcnRpY2lwYW50IEwgYXMgTG9nZ2VyXG4gICAqXG4gICAqICAgQS0+PkM6IG5ldyBDb21wb25lbnQoaW5zdGFuY2UpXG4gICAqICAgQy0+PkI6IHN1cGVyKGluc3RhbmNlKVxuICAgKiAgIEItPj5COiBTZXQgY29tcG9uZW50TmFtZSA9IGluc3RhbmNlXG4gICAqICAgQi0+PlU6IGdldExvY2FsZUZyb21DbGFzc05hbWUoaW5zdGFuY2UpXG4gICAqICAgVS0tPj5COiBSZXR1cm4gZGVyaXZlZCBsb2NhbGVcbiAgICogICBCLT4+QjogU2V0IGNvbXBvbmVudExvY2FsZVxuICAgKiAgIEItPj5MOiBnZXRMb2dnZXIodGhpcylcbiAgICogICBMLS0+PkI6IFJldHVybiBsb2dnZXIgaW5zdGFuY2VcbiAgICogICBCLT4+QjogU2V0IGxvZ2dlclxuICAgKlxuICAgKiBAbWVtYmVyT2YgTmd4QmFzZUNvbXBvbmVudFxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9wcmVmZXItaW5qZWN0XG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihASW5qZWN0KCdpbnN0YW5jZVRva2VuJykgcHJvdGVjdGVkIGluc3RhbmNlOiBzdHJpbmcpIHtcbiAgICB0aGlzLmNvbXBvbmVudE5hbWUgPSBpbnN0YW5jZTtcbiAgICB0aGlzLmNvbXBvbmVudExvY2FsZSA9IGdldExvY2FsZUZyb21DbGFzc05hbWUoaW5zdGFuY2UpO1xuICAgIHRoaXMubG9nZ2VyID0gZ2V0TG9nZ2VyKHRoaXMpO1xuICAgIHRoaXMuZ2V0TG9jYWxlKHRoaXMudHJhbnNsYXRhYmxlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0dGVyIGZvciB0aGUgcmVwb3NpdG9yeSBpbnN0YW5jZS5cbiAgICogQHN1bW1hcnkgUHJvdmlkZXMgYSBjb25uZWN0aW9uIHRvIHRoZSBkYXRhIGxheWVyIGZvciByZXRyaWV2aW5nIGFuZCBtYW5pcHVsYXRpbmcgZGF0YS5cbiAgICogVGhpcyBtZXRob2QgaW5pdGlhbGl6ZXMgdGhlIGBfcmVwb3NpdG9yeWAgcHJvcGVydHkgaWYgaXQgaXMgbm90IGFscmVhZHkgc2V0LCBlbnN1cmluZ1xuICAgKiB0aGF0IGEgc2luZ2xlIGluc3RhbmNlIG9mIHRoZSByZXBvc2l0b3J5IGlzIHVzZWQgdGhyb3VnaG91dCB0aGUgY29tcG9uZW50LlxuICAgKlxuICAgKiBUaGUgcmVwb3NpdG9yeSBpcyB1c2VkIHRvIHBlcmZvcm0gQ1JVRCBvcGVyYXRpb25zIG9uIHRoZSBkYXRhIG1vZGVsLCBzdWNoIGFzIGZldGNoaW5nIGRhdGEsXG4gICAqIGNyZWF0aW5nIG5ldyBpdGVtcywgdXBkYXRpbmcgZXhpc3RpbmcgaXRlbXMsIGFuZCBkZWxldGluZyBpdGVtcy4gSXQgYWxzbyBwcm92aWRlcyBtZXRob2RzXG4gICAqIGZvciBxdWVyeWluZyBhbmQgZmlsdGVyaW5nIGRhdGEgYmFzZWQgb24gc3BlY2lmaWMgY3JpdGVyaWEuXG4gICAqXG4gICAqIEByZXR1cm5zIHtEZWNhZlJlcG9zaXRvcnk8TW9kZWw+fSBUaGUgaW5pdGlhbGl6ZWQgcmVwb3NpdG9yeSBpbnN0YW5jZS5cbiAgICogQHByaXZhdGVcbiAgICogQG1lbWJlck9mIE5neEJhc2VDb21wb25lbnRcbiAgICovXG4gIHByb3RlY3RlZCBnZXQgcmVwb3NpdG9yeSgpOiBEZWNhZlJlcG9zaXRvcnk8TW9kZWw+IHtcbiAgICB0cnkge1xuICAgICAgaWYgKCF0aGlzLl9yZXBvc2l0b3J5KSB7XG4gICAgICAgIGNvbnN0IG1vZGVsTmFtZSAgPSAodGhpcy5tb2RlbCBhcyBNb2RlbCkuY29uc3RydWN0b3IubmFtZVxuICAgICAgICBjb25zdCBjb25zdHJ1Y3RvciA9IE1vZGVsLmdldChtb2RlbE5hbWUpO1xuICAgICAgICBpZiAoIWNvbnN0cnVjdG9yKVxuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgICAgJ0Nhbm5vdCBmaW5kIG1vZGVsLiB3YXMgaXQgcmVnaXN0ZXJlZCB3aXRoIEBtb2RlbD8nLFxuICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuX3JlcG9zaXRvcnkgPSBSZXBvc2l0b3J5LmZvck1vZGVsKGNvbnN0cnVjdG9yKTtcbiAgICAgICAgdGhpcy5tb2RlbCA9IG5ldyBjb25zdHJ1Y3RvcigpIGFzIE1vZGVsO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgKGVycm9yIGFzIEVycm9yKT8ubWVzc2FnZSB8fCBlcnJvciBhcyBzdHJpbmdcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9yZXBvc2l0b3J5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXJzZXMgYW5kIGFwcGxpZXMgcHJvcGVydGllcyBmcm9tIHRoZSBwcm9wcyBvYmplY3QgdG8gdGhlIGNvbXBvbmVudCBpbnN0YW5jZS5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaXRlcmF0ZXMgdGhyb3VnaCB0aGUgcHJvcGVydGllcyBvZiB0aGUgcHJvdmlkZWQgaW5zdGFuY2Ugb2JqZWN0XG4gICAqIGFuZCBhcHBsaWVzIGFueSBtYXRjaGluZyBwcm9wZXJ0aWVzIGZyb20gdGhlIGNvbXBvbmVudCdzIHByb3BzIGNvbmZpZ3VyYXRpb24gdG8gdGhlXG4gICAqIGNvbXBvbmVudCBpbnN0YW5jZS4gVGhpcyBhbGxvd3MgZm9yIGR5bmFtaWMgcHJvcGVydHkgYXNzaWdubWVudCBiYXNlZCBvbiBjb25maWd1cmF0aW9uXG4gICAqIHN0b3JlZCBpbiB0aGUgcHJvcHMgb2JqZWN0LCBlbmFibGluZyBmbGV4aWJsZSBjb21wb25lbnQgY3VzdG9taXphdGlvbiB3aXRob3V0IHJlcXVpcmluZ1xuICAgKiBleHBsaWNpdCBwcm9wZXJ0eSBiaW5kaW5nIGZvciBldmVyeSBwb3NzaWJsZSBjb25maWd1cmF0aW9uIG9wdGlvbi5cbiAgICpcbiAgICogVGhlIG1ldGhvZCBwZXJmb3JtcyBhIHNhZmUgcHJvcGVydHkgYXNzaWdubWVudCBieSBjaGVja2luZyBpZiBlYWNoIGtleSBmcm9tIHRoZSBpbnN0YW5jZVxuICAgKiBleGlzdHMgaW4gdGhlIHByb3BzIG9iamVjdCBiZWZvcmUgYXBwbHlpbmcgaXQuIFRoaXMgcHJldmVudHMgYWNjaWRlbnRhbCBwcm9wZXJ0eVxuICAgKiBvdmVyd3JpdGluZyBhbmQgZW5zdXJlcyBvbmx5IGludGVuZGVkIHByb3BlcnRpZXMgYXJlIG1vZGlmaWVkLlxuICAgKlxuICAgKiBAcGFyYW0ge0tleVZhbHVlfSBpbnN0YW5jZSAtIFRoZSBjb21wb25lbnQgaW5zdGFuY2Ugb2JqZWN0IHRvIHByb2Nlc3NcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQyBhcyBDb21wb25lbnRcbiAgICogICBwYXJ0aWNpcGFudCBCIGFzIE5neEJhc2VDb21wb25lbnRcbiAgICogICBwYXJ0aWNpcGFudCBQIGFzIFByb3BzIE9iamVjdFxuICAgKlxuICAgKiAgIEMtPj5COiBwYXJzZVByb3BzKGluc3RhbmNlKVxuICAgKiAgIEItPj5COiBHZXQgT2JqZWN0LmtleXMoaW5zdGFuY2UpXG4gICAqICAgbG9vcCBGb3IgZWFjaCBrZXkgaW4gaW5zdGFuY2VcbiAgICogICAgIEItPj5QOiBDaGVjayBpZiBrZXkgZXhpc3RzIGluIHRoaXMucHJvcHNcbiAgICogICAgIGFsdCBLZXkgZXhpc3RzIGluIHByb3BzXG4gICAqICAgICAgIEItPj5COiBTZXQgdGhpc1trZXldID0gdGhpcy5wcm9wc1trZXldXG4gICAqICAgICBlbHNlIEtleSBub3QgaW4gcHJvcHNcbiAgICogICAgICAgTm90ZSBvdmVyIEI6IFNraXAgdGhpcyBrZXlcbiAgICogICAgIGVuZFxuICAgKiAgIGVuZFxuICAgKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEBtZW1iZXJPZiBOZ3hCYXNlQ29tcG9uZW50XG4gICAqL1xuICBwcm90ZWN0ZWQgcGFyc2VQcm9wcyhpbnN0YW5jZTogS2V5VmFsdWUpOiB2b2lkIHtcbiAgICBPYmplY3Qua2V5cyhpbnN0YW5jZSkuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICBpZihPYmplY3Qua2V5cyh0aGlzLnByb3BzKS5pbmNsdWRlcyhrZXkpKVxuICAgICAgICAodGhpcyBhcyBLZXlWYWx1ZSlba2V5XSA9IHRoaXMucHJvcHNba2V5XTtcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIGNoYW5nZXMgdG8gY29tcG9uZW50IGlucHV0c1xuICAgKiBAc3VtbWFyeSBUaGlzIEFuZ3VsYXIgbGlmZWN5Y2xlIGhvb2sgaXMgY2FsbGVkIHdoZW4gaW5wdXQgcHJvcGVydGllcyBjaGFuZ2UuXG4gICAqIEl0IHJlc3BvbmRzIHRvIGNoYW5nZXMgaW4gdGhlIG1vZGVsLCBsb2NhbGUsIG9yIHRyYW5zbGF0YWJsZSBwcm9wZXJ0aWVzIGJ5XG4gICAqIHVwZGF0aW5nIHRoZSBjb21wb25lbnQncyBpbnRlcm5hbCBzdGF0ZSBhY2NvcmRpbmdseS4gV2hlbiB0aGUgbW9kZWwgY2hhbmdlcyxcbiAgICogaXQgY2FsbHMgZ2V0TW9kZWwgdG8gcHJvY2VzcyB0aGUgbmV3IG1vZGVsIGFuZCBnZXRMb2NhbGUgdG8gdXBkYXRlIHRoZSBsb2NhbGUuXG4gICAqIFdoZW4gbG9jYWxlIG9yIHRyYW5zbGF0YWJsZSBwcm9wZXJ0aWVzIGNoYW5nZSwgaXQgY2FsbHMgZ2V0TG9jYWxlIHRvIHVwZGF0ZVxuICAgKiB0aGUgdHJhbnNsYXRpb24gc2V0dGluZ3MuXG4gICAqXG4gICAqIEBwYXJhbSB7U2ltcGxlQ2hhbmdlc30gY2hhbmdlcyAtIE9iamVjdCBjb250YWluaW5nIGNoYW5nZWQgcHJvcGVydGllc1xuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzW0Jhc2VDb21wb25lbnRQcm9wcy5NT0RFTF0pIHtcbiAgICAgIGNvbnN0IHsgY3VycmVudFZhbHVlIH0gPSBjaGFuZ2VzW0Jhc2VDb21wb25lbnRQcm9wcy5NT0RFTF07XG4gICAgICBpZiAoY3VycmVudFZhbHVlKSB0aGlzLmdldE1vZGVsKGN1cnJlbnRWYWx1ZSk7XG4gICAgICB0aGlzLmdldExvY2FsZSh0aGlzLnRyYW5zbGF0YWJsZSk7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIGNoYW5nZXNbQmFzZUNvbXBvbmVudFByb3BzLklOSVRJQUxJWkVEXSB8fFxuICAgICAgY2hhbmdlc1tCYXNlQ29tcG9uZW50UHJvcHMuTE9DQUxFXSB8fFxuICAgICAgY2hhbmdlc1tCYXNlQ29tcG9uZW50UHJvcHMuVFJBTlNMQVRBQkxFXVxuICAgIClcbiAgICAgIHRoaXMuZ2V0TG9jYWxlKHRoaXMudHJhbnNsYXRhYmxlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgYXBwcm9wcmlhdGUgbG9jYWxlIHN0cmluZyBiYXNlZCBvbiB0aGUgdHJhbnNsYXRhYmxlIGZsYWcgYW5kIGF2YWlsYWJsZSBsb2NhbGVzLlxuICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIHdoaWNoIGxvY2FsZSBzdHJpbmcgdG8gdXNlIGZvciB0cmFuc2xhdGlvbiBiYXNlZCBvbiB0aGUgdHJhbnNsYXRhYmxlIGZsYWdcbiAgICogYW5kIGF2YWlsYWJsZSBsb2NhbGUgc2V0dGluZ3MuIFRoaXMgbWV0aG9kIGZpcnN0IGNvbnZlcnRzIHRoZSB0cmFuc2xhdGFibGUgcGFyYW1ldGVyIHRvIGEgYm9vbGVhblxuICAgKiB1c2luZyB0aGUgc3RyaW5nVG9Cb29sZWFuIHV0aWxpdHkgZnVuY3Rpb24uIElmIHRyYW5zbGF0YWJsZSBpcyBmYWxzZSwgaXQgcmV0dXJucyBhbiBlbXB0eSBzdHJpbmcsXG4gICAqIGluZGljYXRpbmcgbm8gdHJhbnNsYXRpb24gc2hvdWxkIGJlIHBlcmZvcm1lZC4gSWYgdHJhbnNsYXRhYmxlIGlzIHRydWUsIGl0IGNoZWNrcyBmb3IgYW4gZXhwbGljaXRseVxuICAgKiBwcm92aWRlZCBsb2NhbGUgdmlhIHRoZSBsb2NhbGUgcHJvcGVydHkuIElmIG5vIGV4cGxpY2l0IGxvY2FsZSBpcyBhdmFpbGFibGUsIGl0IGZhbGxzIGJhY2sgdG8gdGhlXG4gICAqIGNvbXBvbmVudExvY2FsZSBkZXJpdmVkIGZyb20gdGhlIGNvbXBvbmVudCdzIGNsYXNzIG5hbWUuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nT3JCb29sZWFufSB0cmFuc2xhdGFibGUgLSBXaGV0aGVyIHRoZSBjb21wb25lbnQgc2hvdWxkIGJlIHRyYW5zbGF0ZWRcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgbG9jYWxlIHN0cmluZyB0byB1c2UgZm9yIHRyYW5zbGF0aW9uLCBvciBlbXB0eSBzdHJpbmcgaWYgbm90IHRyYW5zbGF0YWJsZVxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDIGFzIENvbXBvbmVudFxuICAgKiAgIHBhcnRpY2lwYW50IE4gYXMgTmd4QmFzZUNvbXBvbmVudFxuICAgKiAgIHBhcnRpY2lwYW50IFMgYXMgU3RyaW5nVXRpbHNcbiAgICpcbiAgICogICBDLT4+TjogZ2V0TG9jYWxlKHRyYW5zbGF0YWJsZSlcbiAgICogICBOLT4+Uzogc3RyaW5nVG9Cb29sZWFuKHRyYW5zbGF0YWJsZSlcbiAgICogICBTLS0+Pk46IFJldHVybiBib29sZWFuIHZhbHVlXG4gICAqICAgTi0+Pk46IFN0b3JlIGluIHRoaXMudHJhbnNsYXRhYmxlXG4gICAqICAgYWx0IHRyYW5zbGF0YWJsZSBpcyBmYWxzZVxuICAgKiAgICAgTi0tPj5DOiBSZXR1cm4gZW1wdHkgc3RyaW5nXG4gICAqICAgZWxzZSB0cmFuc2xhdGFibGUgaXMgdHJ1ZVxuICAgKiAgICAgYWx0IHRoaXMubG9jYWxlIGlzIGRlZmluZWRcbiAgICogICAgICAgTi0tPj5DOiBSZXR1cm4gdGhpcy5sb2NhbGVcbiAgICogICAgIGVsc2UgdGhpcy5sb2NhbGUgaXMgbm90IGRlZmluZWRcbiAgICogICAgICAgTi0tPj5DOiBSZXR1cm4gdGhpcy5jb21wb25lbnRMb2NhbGVcbiAgICogICAgIGVuZFxuICAgKiAgIGVuZFxuICAgKi9cbiAgZ2V0TG9jYWxlKHRyYW5zbGF0YWJsZTogU3RyaW5nT3JCb29sZWFuKTogc3RyaW5nIHtcbiAgICB0aGlzLnRyYW5zbGF0YWJsZSA9IHN0cmluZ1RvQm9vbGVhbih0cmFuc2xhdGFibGUpO1xuICAgIGlmICghdGhpcy50cmFuc2xhdGFibGUpXG4gICAgICByZXR1cm4gJyc7XG4gICAgaWYgKCF0aGlzLmxvY2FsZSlcbiAgICAgIHRoaXMubG9jYWxlID0gdGhpcy5jb21wb25lbnRMb2NhbGU7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSByb3V0ZSBmb3IgdGhlIGNvbXBvbmVudFxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIHJvdXRlIHBhdGggZm9yIHRoZSBjb21wb25lbnQsIGdlbmVyYXRpbmcgb25lIGJhc2VkIG9uIHRoZSBtb2RlbFxuICAgKiBpZiBubyByb3V0ZSBpcyBleHBsaWNpdGx5IHNldC4gVGhpcyBtZXRob2QgY2hlY2tzIGlmIGEgcm91dGUgaXMgYWxyZWFkeSBkZWZpbmVkLCBhbmQgaWYgbm90LFxuICAgKiBpdCBjcmVhdGVzIGEgZGVmYXVsdCByb3V0ZSBiYXNlZCBvbiB0aGUgbW9kZWwncyBjb25zdHJ1Y3RvciBuYW1lLiBUaGUgZ2VuZXJhdGVkIHJvdXRlIGZvbGxvd3NcbiAgICogdGhlIHBhdHRlcm4gJy9tb2RlbC97TW9kZWxOYW1lfScuIFRoaXMgaXMgdXNlZnVsIGZvciBhdXRvbWF0aWMgcm91dGluZyBpbiBDUlVEIG9wZXJhdGlvbnMuXG4gICAqXG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHJvdXRlIHBhdGggZm9yIHRoZSBjb21wb25lbnQsIG9yIGVtcHR5IHN0cmluZyBpZiBubyByb3V0ZSBpcyBhdmFpbGFibGVcbiAgICovXG4gIGdldFJvdXRlKCk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLnJvdXRlICYmIHRoaXMubW9kZWwgaW5zdGFuY2VvZiBNb2RlbClcbiAgICAgIHRoaXMucm91dGUgPSBgL21vZGVsLyR7dGhpcy5tb2RlbD8uY29uc3RydWN0b3IubmFtZX1gO1xuICAgIHJldHVybiB0aGlzLnJvdXRlIHx8ICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXNvbHZlcyBhbmQgc2V0cyB0aGUgY29tcG9uZW50J3MgbW9kZWxcbiAgICogQHN1bW1hcnkgUHJvY2Vzc2VzIHRoZSBwcm92aWRlZCBtb2RlbCBwYXJhbWV0ZXIsIHdoaWNoIGNhbiBiZSBlaXRoZXIgYSBNb2RlbCBpbnN0YW5jZVxuICAgKiBvciBhIHN0cmluZyBpZGVudGlmaWVyLiBJZiBhIHN0cmluZyBpcyBwcm92aWRlZCwgaXQgYXR0ZW1wdHMgdG8gcmVzb2x2ZSB0aGUgYWN0dWFsIG1vZGVsXG4gICAqIGZyb20gdGhlIGluamVjdGFibGVzIHJlZ2lzdHJ5LiBBZnRlciByZXNvbHZpbmcgdGhlIG1vZGVsLCBpdCBjYWxscyBzZXRNb2RlbERlZmluaXRpb25zXG4gICAqIHRvIGNvbmZpZ3VyZSB0aGUgY29tcG9uZW50IGJhc2VkIG9uIHRoZSBtb2RlbCdzIG1ldGFkYXRhLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IE1vZGVsfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSBvciBpZGVudGlmaWVyIHN0cmluZ1xuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgZ2V0TW9kZWwobW9kZWw6IHN0cmluZyB8IE1vZGVsKTogdm9pZCB7XG4gICAgaWYgKCEobW9kZWwgaW5zdGFuY2VvZiBNb2RlbCkpXG4gICAgICB0aGlzLm1vZGVsID0gZ2V0SW5qZWN0YWJsZXNSZWdpc3RyeSgpLmdldChtb2RlbCkgYXMgTW9kZWw7XG4gICAgdGhpcy5zZXRNb2RlbERlZmluaXRpb25zKHRoaXMubW9kZWwgYXMgTW9kZWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb25maWd1cmVzIGNvbXBvbmVudCBwcm9wZXJ0aWVzIGJhc2VkIG9uIG1vZGVsIG1ldGFkYXRhXG4gICAqIEBzdW1tYXJ5IEV4dHJhY3RzIGFuZCBhcHBsaWVzIGNvbmZpZ3VyYXRpb24gZnJvbSB0aGUgbW9kZWwncyBkZWNvcmF0b3JzIHRvIHNldCB1cFxuICAgKiB0aGUgY29tcG9uZW50LiBUaGlzIG1ldGhvZCB1c2VzIHRoZSByZW5kZXJpbmcgZW5naW5lIHRvIHJldHJpZXZlIGRlY29yYXRvciBtZXRhZGF0YVxuICAgKiBmcm9tIHRoZSBtb2RlbCwgdGhlbiBjb25maWd1cmVzIHRoZSBjb21wb25lbnQncyBtYXBwZXIgYW5kIGl0ZW0gcHJvcGVydGllcyBhY2NvcmRpbmdseS5cbiAgICogSXQgZW5zdXJlcyB0aGUgcm91dGUgaXMgcHJvcGVybHkgc2V0IGFuZCBtZXJnZXMgdmFyaW91cyBwcm9wZXJ0aWVzIGZyb20gdGhlIG1vZGVsJ3NcbiAgICogbWV0YWRhdGEgaW50byB0aGUgY29tcG9uZW50J3MgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtNb2RlbH0gbW9kZWwgLSBUaGUgbW9kZWwgdG8gZXh0cmFjdCBjb25maWd1cmF0aW9uIGZyb21cbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHNldE1vZGVsRGVmaW5pdGlvbnMobW9kZWw6IE1vZGVsKTogdm9pZCB7XG4gICAgaWYgKG1vZGVsIGluc3RhbmNlb2YgTW9kZWwpIHtcbiAgICAgIHRoaXMuZ2V0Um91dGUoKTtcbiAgICAgIHRoaXMubW9kZWwgPSBtb2RlbDtcbiAgICAgIGNvbnN0IGZpZWxkID0gdGhpcy5yZW5kZXJpbmdFbmdpbmUuZ2V0RGVjb3JhdG9ycyh0aGlzLm1vZGVsIGFzIE1vZGVsLCB7fSk7XG4gICAgICBjb25zdHsgcHJvcHMsIGl0ZW0sIGNoaWxkcmVuIH0gPSBmaWVsZDtcbiAgICAgIHRoaXMucHJvcHMgPSBPYmplY3QuYXNzaWduKHByb3BzIHx8IHt9LCB7Y2hpbGRyZW46IGNoaWxkcmVuIHx8IFtdfSk7XG4gICAgICBpZihpdGVtPy5wcm9wcz8uWydtYXBwZXInXSlcbiAgICAgICAgdGhpcy5tYXBwZXIgPSBpdGVtPy5wcm9wcyFbJ21hcHBlciddIHx8IHt9O1xuICAgICAgdGhpcy5pdGVtID0ge1xuICAgICAgICB0YWc6IGl0ZW0/LnRhZyB8fCAnJyxcbiAgICAgICAgLi4uaXRlbT8ucHJvcHMsXG4gICAgICAgIC4uLih0aGlzLm1hcHBlciA/IHttYXBwZXI6IHRoaXMubWFwcGVyfSA6IHt9KSxcbiAgICAgICAgLi4ueyByb3V0ZTogaXRlbT8ucHJvcHM/Llsncm91dGUnXSB8fCB0aGlzLnJvdXRlIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgdGhlIGNvbXBvbmVudFxuICAgKiBAc3VtbWFyeSBQZXJmb3JtcyBvbmUtdGltZSBpbml0aWFsaXphdGlvbiBvZiB0aGUgY29tcG9uZW50LiBUaGlzIG1ldGhvZCBjaGVja3MgaWZcbiAgICogdGhlIGNvbXBvbmVudCBoYXMgYWxyZWFkeSBiZWVuIGluaXRpYWxpemVkIHRvIHByZXZlbnQgZHVwbGljYXRlIGluaXRpYWxpemF0aW9uLlxuICAgKiBXaGVuIGNhbGxlZCBmb3IgdGhlIGZpcnN0IHRpbWUsIGl0IHNldHMgdGhlIGluaXRpYWxpemVkIGZsYWcgdG8gdHJ1ZSBhbmQgbG9nc1xuICAgKiBhbiBpbml0aWFsaXphdGlvbiBtZXNzYWdlIHdpdGggdGhlIGNvbXBvbmVudCBuYW1lLiBUaGlzIG1ldGhvZCBpcyB0eXBpY2FsbHkgY2FsbGVkXG4gICAqIGR1cmluZyB0aGUgY29tcG9uZW50J3MgbGlmZWN5Y2xlIHNldHVwLlxuICAgKi9cbiAgaW5pdGlhbGl6ZSgpOiB2b2lkIHtcbiAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBjdXN0b20gZXZlbnRzIGZyb20gY2hpbGQgY29tcG9uZW50cy5cbiAgICogQHN1bW1hcnkgUmVjZWl2ZXMgZXZlbnRzIGZyb20gY2hpbGQgcmVuZGVyZXIgY29tcG9uZW50cyBhbmQgZm9yd2FyZHMgdGhlbSB0byBwYXJlbnRcbiAgICogY29tcG9uZW50cyB0aHJvdWdoIHRoZSBsaXN0ZW5FdmVudCBvdXRwdXQuIFRoaXMgY3JlYXRlcyBhbiBldmVudCBwcm9wYWdhdGlvbiBjaGFpblxuICAgKiB0aGF0IGFsbG93cyBldmVudHMgdG8gYnViYmxlIHVwIHRocm91Z2ggdGhlIGNvbXBvbmVudCBoaWVyYXJjaHksIGVuYWJsaW5nIGNvb3JkaW5hdGVkXG4gICAqIHJlc3BvbnNlcyB0byB1c2VyIGludGVyYWN0aW9ucyBhY3Jvc3MgdGhlIGxheW91dCBzdHJ1Y3R1cmUuXG4gICAqXG4gICAqIEBwYXJhbSB7UmVuZGVyZXJDdXN0b21FdmVudH0gZXZlbnQgLSBUaGUgY3VzdG9tIGV2ZW50IGZyb20gYSBjaGlsZCBjb21wb25lbnRcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQyBhcyBDaGlsZCBDb21wb25lbnRcbiAgICogICBwYXJ0aWNpcGFudCBMIGFzIE5neEJhc2VDb21wb25lbnRcbiAgICogICBwYXJ0aWNpcGFudCBQIGFzIFBhcmVudCBDb21wb25lbnRcbiAgICpcbiAgICogICBDLT4+TDogRW1pdCBSZW5kZXJlckN1c3RvbUV2ZW50XG4gICAqICAgTC0+Pkw6IGhhbmRsZUV2ZW50KGV2ZW50KVxuICAgKiAgIEwtPj5QOiBsaXN0ZW5FdmVudC5lbWl0KGV2ZW50KVxuICAgKiAgIE5vdGUgb3ZlciBQOiBIYW5kbGUgZXZlbnQgaW4gcGFyZW50XG4gICAqXG4gICAqIEBtZW1iZXJPZiBOZ3hCYXNlQ29tcG9uZW50XG4gICAqL1xuICBoYW5kbGVFdmVudChldmVudDogUmVuZGVyZXJDdXN0b21FdmVudCk6IHZvaWQge1xuICAgIHRoaXMubGlzdGVuRXZlbnQuZW1pdChldmVudCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRyYWNrcyBpdGVtcyBpbiBuZ0ZvciBsb29wcyBmb3Igb3B0aW1hbCBjaGFuZ2UgZGV0ZWN0aW9uLlxuICAgKiBAc3VtbWFyeSBQcm92aWRlcyBhIHRyYWNraW5nIGZ1bmN0aW9uIGZvciBBbmd1bGFyJ3MgKm5nRm9yIGRpcmVjdGl2ZSB0byBvcHRpbWl6ZSByZW5kZXJpbmdcbiAgICogcGVyZm9ybWFuY2UuIFRoaXMgbWV0aG9kIGdlbmVyYXRlcyB1bmlxdWUgaWRlbnRpZmllcnMgZm9yIGxpc3QgaXRlbXMgYmFzZWQgb24gdGhlaXIgaW5kZXhcbiAgICogYW5kIGNvbnRlbnQsIGFsbG93aW5nIEFuZ3VsYXIgdG8gZWZmaWNpZW50bHkgdHJhY2sgY2hhbmdlcyBhbmQgbWluaW1pemUgRE9NIG1hbmlwdWxhdGlvbnNcbiAgICogZHVyaW5nIGxpc3QgdXBkYXRlcy4gVGhlIHRyYWNraW5nIGZ1bmN0aW9uIGlzIGVzc2VudGlhbCBmb3IgbWFpbnRhaW5pbmcgY29tcG9uZW50IHN0YXRlXG4gICAqIGFuZCBwcmV2ZW50aW5nIHVubmVjZXNzYXJ5IHJlLXJlbmRlcmluZyBvZiB1bmNoYW5nZWQgaXRlbXMuXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCAtIFRoZSBpbmRleCBvZiB0aGUgaXRlbSBpbiB0aGUgbGlzdFxuICAgKiBAcGFyYW0ge0tleVZhbHVlIHwgc3RyaW5nIHwgbnVtYmVyfSBpdGVtIC0gVGhlIGl0ZW0gZGF0YSB0byB0cmFja1xuICAgKiBAcmV0dXJucyB7c3RyaW5nIHwgbnVtYmVyfSBBIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgaXRlbVxuICAgKiBAbWVtYmVyT2YgTmd4QmFzZUNvbXBvbmVudFxuICAgKi9cbiAgdHJhY2tJdGVtRm4oaW5kZXg6IG51bWJlciwgaXRlbTogS2V5VmFsdWUgfCBzdHJpbmcgfCBudW1iZXIpOiBzdHJpbmcgfCBudW1iZXIge1xuICAgIHJldHVybiBgJHtpbmRleH0tJHtpdGVtfWA7XG4gIH1cbn1cbiJdfQ==