@wertzui/ngx-restworld-client 13.1.1 → 13.2.1

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.
@@ -0,0 +1,432 @@
1
+ import { Component, ContentChild, Input } from '@angular/core';
2
+ import { PropertyType, NumberTemplate, ProblemDetails } from '@wertzui/ngx-hal-client';
3
+ import { PropertyWithOptions, PropertyWithImage } from '../../models/special-properties';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ import * as i2 from "../restworld-label/restworld-label.component";
7
+ import * as i3 from "primeng/api";
8
+ import * as i4 from "../../services/restworld-client-collection";
9
+ import * as i5 from "primeng/tooltip";
10
+ import * as i6 from "primeng/checkbox";
11
+ import * as i7 from "@angular/forms";
12
+ import * as i8 from "primeng/tristatecheckbox";
13
+ import * as i9 from "../restworld-avatar/restworld-avatar.component";
14
+ import * as i10 from "../../pipes/property-type-format.pipe";
15
+ /**
16
+ * Display the value of a form element with a label that is automatically created from a property in a form template.
17
+ * This may also be a complex object or a collection in which case multiple and nested display elements may be rendered.
18
+ * If you want to display just the value without a label, use RestWorldDisplayComponent <rw-display>.
19
+ */
20
+ export class RestWorldDisplayElementComponent {
21
+ property;
22
+ apiName;
23
+ _value;
24
+ /**
25
+ * The value to display. If not set, the value of the property will be used.
26
+ */
27
+ set value(value) {
28
+ this._value = value;
29
+ }
30
+ get value() {
31
+ return this._value ?? this.property.value;
32
+ }
33
+ get PropertyType() {
34
+ return PropertyType;
35
+ }
36
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayElementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
37
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: RestWorldDisplayElementComponent, selector: "rw-display-element", inputs: { property: "property", apiName: "apiName", value: "value" }, ngImport: i0, template: "<div class=\"grid field\" *ngIf=\"property.type !== PropertyType.Hidden\">\r\n <rw-label [property]=\"property\" class=\"col-12 md:col-2 flex align-items-center\"></rw-label>\r\n <rw-display [property]=\"property\" [value]=\"value\" [apiName]=\"apiName\" class=\"col-12 md:col-10\"></rw-display>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "directive", type: i0.forwardRef(() => i1.NgIf), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i0.forwardRef(() => RestWorldDisplayComponent), selector: "rw-display", inputs: ["property", "apiName", "value"] }, { kind: "component", type: i0.forwardRef(() => i2.RestWorldLabelComponent), selector: "rw-label", inputs: ["property"] }] });
38
+ }
39
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayElementComponent, decorators: [{
40
+ type: Component,
41
+ args: [{ selector: 'rw-display-element', template: "<div class=\"grid field\" *ngIf=\"property.type !== PropertyType.Hidden\">\r\n <rw-label [property]=\"property\" class=\"col-12 md:col-2 flex align-items-center\"></rw-label>\r\n <rw-display [property]=\"property\" [value]=\"value\" [apiName]=\"apiName\" class=\"col-12 md:col-10\"></rw-display>\r\n</div>\r\n" }]
42
+ }], propDecorators: { property: [{
43
+ type: Input,
44
+ args: [{ required: true }]
45
+ }], apiName: [{
46
+ type: Input,
47
+ args: [{ required: true }]
48
+ }], value: [{
49
+ type: Input
50
+ }] } });
51
+ /**
52
+ * Displays a value that is automatically created from a property in a form template.
53
+ * This may also be a complex object or a collection in which case multiple and nested input elements may be rendered.
54
+ * If you also want a label, use RestWorldDisplayElementComponent <rw-display-element>.
55
+ * You can also use one of the different RestWorldDisplay... <rw-display-...> elements to render a specific property type,
56
+ * but it is advised to control the rendered element through the passed in property.
57
+ */
58
+ export class RestWorldDisplayComponent {
59
+ property;
60
+ apiName;
61
+ _value;
62
+ /**
63
+ * The value to display. If not set, the value of the property will be used.
64
+ */
65
+ set value(value) {
66
+ this._value = value;
67
+ }
68
+ get value() {
69
+ return this._value ?? this.property.value;
70
+ }
71
+ get PropertyType() {
72
+ return PropertyType;
73
+ }
74
+ get PropertyWithOptions() {
75
+ return PropertyWithOptions;
76
+ }
77
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
78
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: RestWorldDisplayComponent, selector: "rw-display", inputs: { property: "property", apiName: "apiName", value: "value" }, ngImport: i0, template: "<ng-container *ngIf=\"property.type !== PropertyType.Hidden\">\r\n <rw-display-dropdown *ngIf=\"property.options\" [property]=\"$any(property)\" [selectedValues]=\"$any(value)\" [apiName]=\"apiName\"></rw-display-dropdown>\r\n\r\n <ng-container *ngIf=\"!property.options\">\r\n <ng-container [ngSwitch]=\"property.type\">\r\n <rw-display-object *ngSwitchCase=\"PropertyType.Object\" [property]=\"$any(property)\" [value]=\"$any(value)\" [apiName]=\"apiName\"></rw-display-object>\r\n <rw-display-collection *ngSwitchCase=\"PropertyType.Collection\" [property]=\"$any(property)\" [values]=\"$any(value)\" [apiName]=\"apiName\"></rw-display-collection>\r\n <rw-display-simple *ngSwitchDefault [property]=\"property\" [value]=\"$any(value)\" [apiName]=\"apiName\"></rw-display-simple>\r\n </ng-container>\r\n </ng-container>\r\n</ng-container>\r\n", styles: [""], dependencies: [{ kind: "directive", type: i0.forwardRef(() => i1.NgIf), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgSwitch), selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgSwitchCase), selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgSwitchDefault), selector: "[ngSwitchDefault]" }, { kind: "component", type: i0.forwardRef(() => RestWorldDisplayCollectionComponent), selector: "rw-display-collection", inputs: ["property", "apiName", "values"] }, { kind: "component", type: i0.forwardRef(() => RestWorldDisplayDropdownComponent), selector: "rw-display-dropdown", inputs: ["property", "apiName", "selectedValues", "getLabel", "getTooltip"] }, { kind: "component", type: i0.forwardRef(() => RestWorldDisplayObjectComponent), selector: "rw-display-object", inputs: ["property", "apiName", "value"] }, { kind: "component", type: i0.forwardRef(() => RestWorldDisplaySimpleComponent), selector: "rw-display-simple", inputs: ["property", "apiName", "value"] }] });
79
+ }
80
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayComponent, decorators: [{
81
+ type: Component,
82
+ args: [{ selector: 'rw-display', template: "<ng-container *ngIf=\"property.type !== PropertyType.Hidden\">\r\n <rw-display-dropdown *ngIf=\"property.options\" [property]=\"$any(property)\" [selectedValues]=\"$any(value)\" [apiName]=\"apiName\"></rw-display-dropdown>\r\n\r\n <ng-container *ngIf=\"!property.options\">\r\n <ng-container [ngSwitch]=\"property.type\">\r\n <rw-display-object *ngSwitchCase=\"PropertyType.Object\" [property]=\"$any(property)\" [value]=\"$any(value)\" [apiName]=\"apiName\"></rw-display-object>\r\n <rw-display-collection *ngSwitchCase=\"PropertyType.Collection\" [property]=\"$any(property)\" [values]=\"$any(value)\" [apiName]=\"apiName\"></rw-display-collection>\r\n <rw-display-simple *ngSwitchDefault [property]=\"property\" [value]=\"$any(value)\" [apiName]=\"apiName\"></rw-display-simple>\r\n </ng-container>\r\n </ng-container>\r\n</ng-container>\r\n" }]
83
+ }], propDecorators: { property: [{
84
+ type: Input,
85
+ args: [{ required: true }]
86
+ }], apiName: [{
87
+ type: Input,
88
+ args: [{ required: true }]
89
+ }], value: [{
90
+ type: Input
91
+ }] } });
92
+ /**
93
+ * Displays the value of a collection that is automatically created from the given property.
94
+ * The elements and can also be nested.
95
+ * @remarks It is advised to use RestWorldDisplayComponent <rw-display> and control the rendered elements with the passed in property
96
+ * instead of using this component directly.
97
+ */
98
+ export class RestWorldDisplayCollectionComponent {
99
+ property;
100
+ apiName;
101
+ _values;
102
+ /**
103
+ * The value to display. If not set, the value of the property will be used.
104
+ */
105
+ set values(values) {
106
+ this._values = RestWorldDisplayCollectionComponent.toArray(values);
107
+ }
108
+ get values() {
109
+ return this._values;
110
+ }
111
+ _templates = [];
112
+ get templates() {
113
+ return this._templates;
114
+ }
115
+ ngOnInit() {
116
+ this._templates = this._values ?
117
+ Array.from(RestWorldDisplayCollectionComponent.map(this._values.entries(), entry => (new NumberTemplate({ ...this.property._templates.default, title: entry[0].toString() })))) :
118
+ RestWorldDisplayCollectionComponent.getCollectionEntryTemplates(this.property);
119
+ }
120
+ static *map(iterable, callback) {
121
+ for (let x of iterable) {
122
+ yield callback(x);
123
+ }
124
+ }
125
+ static toArray(arrayOrDictionary) {
126
+ if (!arrayOrDictionary)
127
+ return undefined;
128
+ if (Array.isArray(arrayOrDictionary))
129
+ return arrayOrDictionary;
130
+ return Object.entries(arrayOrDictionary).map(([key, value]) => ({ key, value }));
131
+ }
132
+ static getCollectionEntryTemplates(property) {
133
+ if (!property)
134
+ return [];
135
+ return Object.entries(property._templates)
136
+ .filter(([key, value]) => Number.isInteger(Number.parseInt(key)) && Number.isInteger(Number.parseInt(value?.title ?? "")))
137
+ .map(([, value]) => new NumberTemplate(value));
138
+ }
139
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayCollectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
140
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: RestWorldDisplayCollectionComponent, selector: "rw-display-collection", inputs: { property: "property", apiName: "apiName", values: "values" }, ngImport: i0, template: "<div class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full\">\r\n <div *ngFor=\"let template of templates\" class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full flex justify-content-end\">\r\n <rw-display-template [template]=\"$any(template)\" [value]=\"values ? values[template.title!] : undefined\" [apiName]=\"apiName\" class=\"w-full\"></rw-display-template>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}\n"], dependencies: [{ kind: "directive", type: i0.forwardRef(() => i1.NgForOf), selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i0.forwardRef(() => RestWorldDisplayTemplateComponent), selector: "rw-display-template", inputs: ["template", "apiName", "value"] }] });
141
+ }
142
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayCollectionComponent, decorators: [{
143
+ type: Component,
144
+ args: [{ selector: 'rw-display-collection', template: "<div class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full\">\r\n <div *ngFor=\"let template of templates\" class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full flex justify-content-end\">\r\n <rw-display-template [template]=\"$any(template)\" [value]=\"values ? values[template.title!] : undefined\" [apiName]=\"apiName\" class=\"w-full\"></rw-display-template>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}\n"] }]
145
+ }], propDecorators: { property: [{
146
+ type: Input,
147
+ args: [{ required: true }]
148
+ }], apiName: [{
149
+ type: Input,
150
+ args: [{ required: true }]
151
+ }], values: [{
152
+ type: Input
153
+ }] } });
154
+ /**
155
+ * Displays the value of a dropdown that is automatically created from the given property.
156
+ * If set the dropdown will use the `inline` property of the options to render the `selectedValues` Otherwise it will just render the values, but no prompt for them.
157
+ * @remarks It is advised to use RestWorldDisplayComponent <rw-display> and control the rendered elements with the passed in property
158
+ * instead of using this component directly.
159
+ */
160
+ export class RestWorldDisplayDropdownComponent {
161
+ _messageService;
162
+ _clients;
163
+ property;
164
+ apiName;
165
+ _selectedValues;
166
+ /**
167
+ * The values to display. If not set, the values of the property options will be used.
168
+ */
169
+ set selectedValues(value) {
170
+ if (Array.isArray(value))
171
+ this._selectedValues = value;
172
+ else if (value !== undefined && value !== null)
173
+ this._selectedValues = [value];
174
+ }
175
+ get selectedValues() {
176
+ return this._selectedValues ?? this.property.options.selectedValues ?? [];
177
+ }
178
+ _inline = [];
179
+ /**
180
+ * A function that returns the label for the given item.
181
+ * The default returns the prompt and optionally the value in brackets.
182
+ * The value in brackets will only be displayed if the `cols` field of the property is undefined or greater than 1.
183
+ * Overwrite this function to change the label.
184
+ * @param item The item to get the label for.
185
+ */
186
+ getLabel = this.getLabelInternal;
187
+ /**
188
+ * A function that returns the tooltip for the given item.
189
+ * The default returns all properties of the item except the ones that start with an underscore or the ones that are in the list of default properties to exclude.
190
+ * The default properties to exclude are: createdAt, createdBy, lastChangedAt, lastChangedBy, timestamp, promptField, valueField.
191
+ * Overwrite this function to change the tooltip.
192
+ * @param item The item to get the label for.
193
+ */
194
+ getTooltip = this.getTooltipInternal;
195
+ inputOptionsRef;
196
+ get valueField() {
197
+ return this.property.options.valueField ?? "value";
198
+ }
199
+ get promptField() {
200
+ return this.property.options.promptField ?? "prompt";
201
+ }
202
+ constructor(_messageService, _clients) {
203
+ this._messageService = _messageService;
204
+ this._clients = _clients;
205
+ }
206
+ async ngOnInit() {
207
+ if (this.property.options?.inline && this.property.options.inline.length > 0)
208
+ this._inline = Array.from(this.property.options.inline);
209
+ await this.setInitialSelectedOptionsElementForProperty();
210
+ }
211
+ getOptionItem(value) {
212
+ return this._inline.find(o => this.getValue(o) === value) ?? this.createOptionsItem(value);
213
+ }
214
+ createOptionsItem(value) {
215
+ return { [this.valueField]: value, [this.promptField]: "" };
216
+ }
217
+ getValue(item) {
218
+ if (item === undefined || item === null || !item.hasOwnProperty(this.valueField))
219
+ throw new Error(`The item does not have a property ${this.valueField}.`);
220
+ return item[this.valueField];
221
+ }
222
+ getPrompt(item) {
223
+ if (item === undefined || item === null || !item.hasOwnProperty(this.promptField))
224
+ return "";
225
+ return item[this.promptField];
226
+ }
227
+ getLabelInternal(item) {
228
+ if (item === undefined || item === null)
229
+ return "";
230
+ const prompt = this.getPrompt(item);
231
+ const value = this.getValue(item);
232
+ let label = prompt;
233
+ if (label === undefined || label === null || label === "")
234
+ label = (value?.toString() ?? "");
235
+ else if ((this.property.cols === undefined || this.property.cols > 1) && prompt?.toLowerCase() !== value?.toString().toLowerCase())
236
+ label += ` (${value})`;
237
+ return label;
238
+ }
239
+ getTooltipInternal(item) {
240
+ if (item === undefined || item === null)
241
+ return "";
242
+ const tooltip = Object.entries(item)
243
+ .filter(([key]) => !(key.startsWith('_') || ['createdAt', 'createdBy', 'lastChangedAt', 'lastChangedBy', 'timestamp', this.promptField, this.valueField].includes(key)))
244
+ .reduce((prev, [key, value], index) => `${prev}${index === 0 ? '' : '\n'}${key}: ${RestWorldDisplayDropdownComponent.jsonStringifyWithElipsis(value)}`, '');
245
+ return tooltip;
246
+ }
247
+ async setInitialSelectedOptionsElementForProperty() {
248
+ const options = this.property.options;
249
+ if (!options.link?.href || !this.selectedValues || this.selectedValues.length === 0 || this.selectedValues.every(v => this._inline.some(i => this.getValue(i) === v) ?? false))
250
+ return;
251
+ const filter = `${options.valueField} in (${this.selectedValues})`;
252
+ await this.SetInlineOptionsFromFilter(filter);
253
+ }
254
+ async SetInlineOptionsFromFilter(filter) {
255
+ const options = this.property.options;
256
+ if (!options.link?.href)
257
+ throw new Error('The property does not have a link href.');
258
+ const templatedUri = options.link.href;
259
+ const response = await this.getClient().getListByUri(templatedUri, { $filter: filter, $top: 10 });
260
+ if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
261
+ const message = `An error occurred while getting the initial selected items for the property ${this.property.name}.`;
262
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: message, data: response, sticky: true });
263
+ }
264
+ const items = response.body._embedded.items;
265
+ const newItems = this.combineInlineWithSelected(items);
266
+ this._inline = newItems;
267
+ }
268
+ combineInlineWithSelected(items) {
269
+ const oldInline = this._inline;
270
+ if (!oldInline || oldInline.length === 0)
271
+ return items;
272
+ const itemsToKeep = oldInline.filter(i => this.selectedValues.includes(this.getValue(i)));
273
+ const newItems = items.concat(itemsToKeep.filter(i => !items.includes(i)));
274
+ return newItems;
275
+ }
276
+ getClient() {
277
+ if (!this.apiName)
278
+ throw new Error('Cannot get a client, because the apiName is not set.');
279
+ return this._clients.getClient(this.apiName);
280
+ }
281
+ static jsonStringifyWithElipsis(value) {
282
+ const maxLength = 200;
283
+ const end = 10;
284
+ const start = maxLength - end - 2;
285
+ const json = JSON.stringify(value);
286
+ const shortened = json.length > maxLength ? json.substring(0, start) + '…' + json.substring(json.length - end) : json;
287
+ return shortened;
288
+ }
289
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayDropdownComponent, deps: [{ token: i3.MessageService }, { token: i4.RestWorldClientCollection }], target: i0.ɵɵFactoryTarget.Component });
290
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: RestWorldDisplayDropdownComponent, selector: "rw-display-dropdown", inputs: { property: "property", apiName: "apiName", selectedValues: "selectedValues", getLabel: "getLabel", getTooltip: "getTooltip" }, queries: [{ propertyName: "inputOptionsRef", first: true, predicate: ["inputOptions"], descendants: true }], ngImport: i0, template: "<!-- <ng-template #defaultInputOptions let-property=\"property\" let-selectedValues=\"selectedValues\"> -->\r\n<ng-container *ngFor=\"let value of selectedValues; last as last;\">\r\n <span [pTooltip]=\"getTooltip(getOptionItem(value))\">{{getLabel(getOptionItem(value))}}</span>{{last ? \"\" : \", \"}}\r\n</ng-container>\r\n<!-- </ng-template>\r\n<ng-container *ngTemplateOutlet=\"inputOptionsRef ?? defaultInputOptions; context: { property: property, selectedValues: selectedValues }\"></ng-container> -->", styles: [""], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }] });
291
+ }
292
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayDropdownComponent, decorators: [{
293
+ type: Component,
294
+ args: [{ selector: 'rw-display-dropdown', template: "<!-- <ng-template #defaultInputOptions let-property=\"property\" let-selectedValues=\"selectedValues\"> -->\r\n<ng-container *ngFor=\"let value of selectedValues; last as last;\">\r\n <span [pTooltip]=\"getTooltip(getOptionItem(value))\">{{getLabel(getOptionItem(value))}}</span>{{last ? \"\" : \", \"}}\r\n</ng-container>\r\n<!-- </ng-template>\r\n<ng-container *ngTemplateOutlet=\"inputOptionsRef ?? defaultInputOptions; context: { property: property, selectedValues: selectedValues }\"></ng-container> -->" }]
295
+ }], ctorParameters: () => [{ type: i3.MessageService }, { type: i4.RestWorldClientCollection }], propDecorators: { property: [{
296
+ type: Input,
297
+ args: [{ required: true }]
298
+ }], apiName: [{
299
+ type: Input,
300
+ args: [{ required: true }]
301
+ }], selectedValues: [{
302
+ type: Input
303
+ }], getLabel: [{
304
+ type: Input
305
+ }], getTooltip: [{
306
+ type: Input
307
+ }], inputOptionsRef: [{
308
+ type: ContentChild,
309
+ args: ['inputOptions', { static: false }]
310
+ }] } });
311
+ /**
312
+ * Displays the value of a complex object with multiple properties that is automatically created from the given property.
313
+ * The object can also be nested.
314
+ * @remarks It is advised to use RestWorldDisplayComponent <rw-display> and control the rendered elements with the passed in property
315
+ * instead of using this component directly.
316
+ */
317
+ export class RestWorldDisplayObjectComponent {
318
+ property;
319
+ apiName;
320
+ _value;
321
+ /**
322
+ * The value to display. If not set, the value of the template properties will be used.
323
+ */
324
+ set value(value) {
325
+ this._value = value;
326
+ }
327
+ get value() {
328
+ return this._value;
329
+ }
330
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayObjectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
331
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: RestWorldDisplayObjectComponent, selector: "rw-display-object", inputs: { property: "property", apiName: "apiName", value: "value" }, ngImport: i0, template: "<div class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full\">\r\n <rw-display-template [template]=\"property._templates.default\" [value]=\"value\" [apiName]=\"apiName\"></rw-display-template>\r\n </div>\r\n</div>", styles: [".brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => RestWorldDisplayTemplateComponent), selector: "rw-display-template", inputs: ["template", "apiName", "value"] }] });
332
+ }
333
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayObjectComponent, decorators: [{
334
+ type: Component,
335
+ args: [{ selector: 'rw-display-object', template: "<div class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full\">\r\n <rw-display-template [template]=\"property._templates.default\" [value]=\"value\" [apiName]=\"apiName\"></rw-display-template>\r\n </div>\r\n</div>", styles: [".brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}\n"] }]
336
+ }], propDecorators: { property: [{
337
+ type: Input,
338
+ args: [{ required: true }]
339
+ }], apiName: [{
340
+ type: Input,
341
+ args: [{ required: true }]
342
+ }], value: [{
343
+ type: Input
344
+ }] } });
345
+ /**
346
+ * Displays the value of a simple element, like a string, a number or a Date that is automatically created from the given property.
347
+ * @remarks It is advised to use RestWorldDisplayComponent <rw-display> and control the rendered elements with the passed in property
348
+ * instead of using this component directly.
349
+ */
350
+ export class RestWorldDisplaySimpleComponent {
351
+ property;
352
+ apiName;
353
+ _value;
354
+ /**
355
+ * The value to display. If not set, the value of the property will be used.
356
+ */
357
+ set value(value) {
358
+ this._value = value;
359
+ }
360
+ get value() {
361
+ return this._value ?? this.property.value;
362
+ }
363
+ get PropertyType() {
364
+ return PropertyType;
365
+ }
366
+ static _dateFormat = new Date(3333, 10, 22) // months start at 0 in JS
367
+ .toLocaleDateString()
368
+ .replace("22", "dd")
369
+ .replace("11", "MM")
370
+ .replace("3333", "yyyy")
371
+ .replace("33", "yy");
372
+ get dateFormat() {
373
+ return RestWorldDisplaySimpleComponent._dateFormat;
374
+ }
375
+ static _timeFormat = new Date(1, 1, 1, 22, 33, 44)
376
+ .toLocaleTimeString()
377
+ .replace("22", "hh")
378
+ .replace("33", "mm")
379
+ .replace("44", "ss");
380
+ get timeFormat() {
381
+ return RestWorldDisplaySimpleComponent._timeFormat;
382
+ }
383
+ get PropertyWithImage() {
384
+ return PropertyWithImage;
385
+ }
386
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplaySimpleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
387
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: RestWorldDisplaySimpleComponent, selector: "rw-display-simple", inputs: { property: "property", apiName: "apiName", value: "value" }, ngImport: i0, template: "<ng-container [ngSwitch]=\"property.type\">\r\n <ng-container *ngSwitchCase=\"PropertyType.Text\">\r\n <rw-avatar *ngIf=\"property.name === 'createdBy' || property.name === 'lastChangedBy'\" [user]=\"$any(value)\"></rw-avatar>\r\n <span *ngIf=\"property.name !== 'createdBy' && property.name !== 'lastChangedBy'\" class=\"w-full\">{{value | propertyTypeFormat:property.type}}</span>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"PropertyType.Bool\">\r\n <p-checkbox *ngIf=\"property.required\" [(ngModel)]=\"value\" [binary]=\"true\" [readonly]=\"true\" [disabled]=\"true\"></p-checkbox>\r\n <p-triStateCheckbox *ngIf=\"!property.required\" [(ngModel)]=\"value\" [readonly]=\"true\" [disabled]=\"true\"></p-triStateCheckbox>\r\n </ng-container>\r\n\r\n <span *ngSwitchDefault class=\"w-full\">{{value | propertyTypeFormat:property.type}}</span>\r\n</ng-container>\r\n", styles: [""], dependencies: [{ kind: "component", type: i6.Checkbox, selector: "p-checkbox", inputs: ["value", "name", "disabled", "binary", "label", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "styleClass", "labelStyleClass", "formControl", "checkboxIcon", "readonly", "required", "trueValue", "falseValue"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8.TriStateCheckbox, selector: "p-triStateCheckbox", inputs: ["disabled", "name", "ariaLabel", "ariaLabelledBy", "tabindex", "inputId", "style", "styleClass", "label", "readonly", "checkboxTrueIcon", "checkboxFalseIcon"], outputs: ["onChange"] }, { kind: "component", type: i9.RestWorldAvatarComponent, selector: "rw-avatar", inputs: ["user"] }, { kind: "pipe", type: i10.PropertyTypeFormatPipe, name: "propertyTypeFormat" }] });
388
+ }
389
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplaySimpleComponent, decorators: [{
390
+ type: Component,
391
+ args: [{ selector: 'rw-display-simple', template: "<ng-container [ngSwitch]=\"property.type\">\r\n <ng-container *ngSwitchCase=\"PropertyType.Text\">\r\n <rw-avatar *ngIf=\"property.name === 'createdBy' || property.name === 'lastChangedBy'\" [user]=\"$any(value)\"></rw-avatar>\r\n <span *ngIf=\"property.name !== 'createdBy' && property.name !== 'lastChangedBy'\" class=\"w-full\">{{value | propertyTypeFormat:property.type}}</span>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"PropertyType.Bool\">\r\n <p-checkbox *ngIf=\"property.required\" [(ngModel)]=\"value\" [binary]=\"true\" [readonly]=\"true\" [disabled]=\"true\"></p-checkbox>\r\n <p-triStateCheckbox *ngIf=\"!property.required\" [(ngModel)]=\"value\" [readonly]=\"true\" [disabled]=\"true\"></p-triStateCheckbox>\r\n </ng-container>\r\n\r\n <span *ngSwitchDefault class=\"w-full\">{{value | propertyTypeFormat:property.type}}</span>\r\n</ng-container>\r\n" }]
392
+ }], propDecorators: { property: [{
393
+ type: Input,
394
+ args: [{ required: true }]
395
+ }], apiName: [{
396
+ type: Input,
397
+ args: [{ required: true }]
398
+ }], value: [{
399
+ type: Input
400
+ }] } });
401
+ /**
402
+ * Displays the values of a collection of rw-display-elements automatically created from a template.
403
+ */
404
+ export class RestWorldDisplayTemplateComponent {
405
+ template;
406
+ apiName;
407
+ _value;
408
+ /**
409
+ * The value to display. If not set, the values of the template properties will be used.
410
+ */
411
+ set value(value) {
412
+ this._value = value;
413
+ }
414
+ get value() {
415
+ return this._value;
416
+ }
417
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayTemplateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
418
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: RestWorldDisplayTemplateComponent, selector: "rw-display-template", inputs: { template: "template", apiName: "apiName", value: "value" }, ngImport: i0, template: "<rw-display-element *ngFor=\"let property of template.properties\" [property]=\"property\" [value]=\"value ? value[property.name] : undefined\" [apiName]=\"apiName\"></rw-display-element>", styles: [""], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: RestWorldDisplayElementComponent, selector: "rw-display-element", inputs: ["property", "apiName", "value"] }] });
419
+ }
420
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayTemplateComponent, decorators: [{
421
+ type: Component,
422
+ args: [{ selector: 'rw-display-template', template: "<rw-display-element *ngFor=\"let property of template.properties\" [property]=\"property\" [value]=\"value ? value[property.name] : undefined\" [apiName]=\"apiName\"></rw-display-element>" }]
423
+ }], propDecorators: { template: [{
424
+ type: Input,
425
+ args: [{ required: true }]
426
+ }], apiName: [{
427
+ type: Input,
428
+ args: [{ required: true }]
429
+ }], value: [{
430
+ type: Input
431
+ }] } });
432
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdHdvcmxkLWRpc3BsYXlzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXJlc3R3b3JsZC1jbGllbnQvc3JjL2xpYi9jb21wb25lbnRzL3Jlc3R3b3JsZC1kaXNwbGF5cy9yZXN0d29ybGQtZGlzcGxheXMudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LWVsZW1lbnQvcmVzdHdvcmxkLWRpc3BsYXktZWxlbWVudC5jb21wb25lbnQuaHRtbCIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1yZXN0d29ybGQtY2xpZW50L3NyYy9saWIvY29tcG9uZW50cy9yZXN0d29ybGQtZGlzcGxheXMvcmVzdHdvcmxkLWRpc3BsYXkvcmVzdHdvcmxkLWRpc3BsYXkuY29tcG9uZW50Lmh0bWwiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LWNvbGxlY3Rpb24vcmVzdHdvcmxkLWRpc3BsYXktY29sbGVjdGlvbi5jb21wb25lbnQuaHRtbCIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1yZXN0d29ybGQtY2xpZW50L3NyYy9saWIvY29tcG9uZW50cy9yZXN0d29ybGQtZGlzcGxheXMvcmVzdHdvcmxkLWRpc3BsYXktZHJvcGRvd24vcmVzdHdvcmxkLWRpc3BsYXktZHJvcGRvd24uY29tcG9uZW50Lmh0bWwiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LW9iamVjdC9yZXN0d29ybGQtZGlzcGxheS1vYmplY3QuY29tcG9uZW50Lmh0bWwiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LXNpbXBsZS9yZXN0d29ybGQtZGlzcGxheS1zaW1wbGUuY29tcG9uZW50Lmh0bWwiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LXRlbXBsYXRlL3Jlc3R3b3JsZC1kaXNwbGF5LXRlbXBsYXRlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBdUIsTUFBTSxlQUFlLENBQUM7QUFDcEYsT0FBTyxFQUF5QixZQUFZLEVBQVksY0FBYyxFQUFrSCxjQUFjLEVBQWlCLE1BQU0seUJBQXlCLENBQUM7QUFDdlAsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGlCQUFpQixFQUFFLE1BQU0saUNBQWlDLENBQUE7Ozs7Ozs7Ozs7OztBQU14Rjs7OztHQUlHO0FBTUgsTUFBTSxPQUFPLGdDQUFnQztJQUV6QyxRQUFRLENBQWE7SUFHckIsT0FBTyxDQUFVO0lBRVQsTUFBTSxDQUFvTjtJQUNsTzs7TUFFRTtJQUNGLElBQ1csS0FBSyxDQUFDLEtBQXVOO1FBQ3BPLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLENBQUM7SUFDRCxJQUFXLEtBQUs7UUFDWixPQUFPLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFvQyxDQUFDO0lBQzdFLENBQUM7SUFFRCxJQUFXLFlBQVk7UUFDbkIsT0FBTyxZQUFZLENBQUM7SUFDeEIsQ0FBQzt1R0FyQlEsZ0NBQWdDOzJGQUFoQyxn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dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQUl6QixPQUFPO3NCQUROLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQVFkLEtBQUs7c0JBRGYsS0FBSzs7QUFzQ1Y7O0dBRUc7QUFNSCxNQUFNLE9BQU8saUNBQWlDO0lBRTFDLFFBQVEsQ0FBWTtJQUdwQixPQUFPLENBQVU7SUFFVCxNQUFNLENBQXVCO0lBQ3JDOztNQUVFO0lBQ0YsSUFDVyxLQUFLLENBQUMsS0FBc0M7UUFDbkQsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7SUFDeEIsQ0FBQztJQUNELElBQVcsS0FBSztRQUNaLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUN2QixDQUFDO3VHQWpCUSxpQ0FBaUM7MkZBQWpDLGlDQUFpQyxpSU8vYTlDLDZMQUFtTCx1TFBrQnRLLGdDQUFnQzs7MkZBNlpoQyxpQ0FBaUM7a0JBTDdDLFNBQVM7K0JBQ0kscUJBQXFCOzhCQU0vQixRQUFRO3NCQURQLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQUl6QixPQUFPO3NCQUROLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQVFkLEtBQUs7c0JBRGYsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgQ29udGVudENoaWxkLCBJbnB1dCwgT25Jbml0LCBUZW1wbGF0ZVJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBQcm9wZXJ0eSwgU2ltcGxlVmFsdWUsIFByb3BlcnR5VHlwZSwgVGVtcGxhdGUsIE51bWJlclRlbXBsYXRlLCBUZW1wbGF0ZUR0bywgT3B0aW9ucywgRXh0cmFjdEdlbmVyaWNPcHRpb25zSXRlbVR5cGUsIEV4dHJhY3RWYWx1ZVR5cGUsIEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZSwgUHJvYmxlbURldGFpbHMsIFJlc291cmNlT2ZEdG8gfSBmcm9tICdAd2VydHp1aS9uZ3gtaGFsLWNsaWVudCc7XHJcbmltcG9ydCB7IFByb3BlcnR5V2l0aE9wdGlvbnMsIFByb3BlcnR5V2l0aEltYWdlIH0gZnJvbSAnLi4vLi4vbW9kZWxzL3NwZWNpYWwtcHJvcGVydGllcydcclxuaW1wb3J0IHsgUHJvcGVydHlUZW1wbGF0ZUNvbnRleHQgfSBmcm9tICcuLi8uLi9tb2RlbHMvdGVtcGxhdGluZyc7XHJcbmltcG9ydCB7IE1lc3NhZ2VTZXJ2aWNlIH0gZnJvbSAncHJpbWVuZy9hcGknO1xyXG5pbXBvcnQgeyBSZXN0V29ybGRDbGllbnRDb2xsZWN0aW9uIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVzdHdvcmxkLWNsaWVudC1jb2xsZWN0aW9uJztcclxuaW1wb3J0IHsgUmVzdFdvcmxkQ2xpZW50IH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVzdHdvcmxkLWNsaWVudCc7XHJcblxyXG4vKipcclxuICogRGlzcGxheSB0aGUgdmFsdWUgb2YgYSBmb3JtIGVsZW1lbnQgd2l0aCBhIGxhYmVsIHRoYXQgaXMgYXV0b21hdGljYWxseSBjcmVhdGVkIGZyb20gYSBwcm9wZXJ0eSBpbiBhIGZvcm0gdGVtcGxhdGUuXHJcbiAqIFRoaXMgbWF5IGFsc28gYmUgYSBjb21wbGV4IG9iamVjdCBvciBhIGNvbGxlY3Rpb24gaW4gd2hpY2ggY2FzZSBtdWx0aXBsZSBhbmQgbmVzdGVkIGRpc3BsYXkgZWxlbWVudHMgbWF5IGJlIHJlbmRlcmVkLlxyXG4gKiBJZiB5b3Ugd2FudCB0byBkaXNwbGF5IGp1c3QgdGhlIHZhbHVlIHdpdGhvdXQgYSBsYWJlbCwgdXNlIFJlc3RXb3JsZERpc3BsYXlDb21wb25lbnQgPHJ3LWRpc3BsYXk+LlxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3J3LWRpc3BsYXktZWxlbWVudCcsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktZWxlbWVudC9yZXN0d29ybGQtZGlzcGxheS1lbGVtZW50LmNvbXBvbmVudC5odG1sJyxcclxuICAgIHN0eWxlVXJsOiAnLi9yZXN0d29ybGQtZGlzcGxheS1lbGVtZW50L3Jlc3R3b3JsZC1kaXNwbGF5LWVsZW1lbnQuY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlFbGVtZW50Q29tcG9uZW50PFRQcm9wZXJ0eSBleHRlbmRzIFByb3BlcnR5PFNpbXBsZVZhbHVlLCBzdHJpbmcsIHN0cmluZz4+IHtcclxuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXHJcbiAgICBwcm9wZXJ0eSE6IFRQcm9wZXJ0eTtcclxuXHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgYXBpTmFtZSE6IHN0cmluZztcclxuXHJcbiAgICBwcml2YXRlIF92YWx1ZT86IEV4dHJhY3RWYWx1ZVR5cGU8VFByb3BlcnR5PiB8IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+W10gfCBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PiB8IFJlY29yZDxzdHJpbmcsIFNpbXBsZVZhbHVlPiB8IE1hcDxudW1iZXIsIFJlY29yZDxzdHJpbmcsIFNpbXBsZVZhbHVlPj47XHJcbiAgICAvKipcclxuICAgICAqIFRoZSB2YWx1ZSB0byBkaXNwbGF5LiBJZiBub3Qgc2V0LCB0aGUgdmFsdWUgb2YgdGhlIHByb3BlcnR5IHdpbGwgYmUgdXNlZC5cclxuICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIHNldCB2YWx1ZSh2YWx1ZTogRXh0cmFjdFZhbHVlVHlwZTxUUHJvcGVydHk+IHwgRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT5bXSB8IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+IHwgUmVjb3JkPHN0cmluZywgU2ltcGxlVmFsdWU+IHwgTWFwPG51bWJlciwgUmVjb3JkPHN0cmluZywgU2ltcGxlVmFsdWU+Pikge1xyXG4gICAgICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XHJcbiAgICB9XHJcbiAgICBwdWJsaWMgZ2V0IHZhbHVlKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZSA/PyB0aGlzLnByb3BlcnR5LnZhbHVlIGFzIEV4dHJhY3RWYWx1ZVR5cGU8VFByb3BlcnR5PjtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IFByb3BlcnR5VHlwZSgpIHtcclxuICAgICAgICByZXR1cm4gUHJvcGVydHlUeXBlO1xyXG4gICAgfVxyXG59XHJcbi8qKlxyXG4gKiBEaXNwbGF5cyBhIHZhbHVlIHRoYXQgaXMgYXV0b21hdGljYWxseSBjcmVhdGVkIGZyb20gYSBwcm9wZXJ0eSBpbiBhIGZvcm0gdGVtcGxhdGUuXHJcbiAqIFRoaXMgbWF5IGFsc28gYmUgYSBjb21wbGV4IG9iamVjdCBvciBhIGNvbGxlY3Rpb24gaW4gd2hpY2ggY2FzZSBtdWx0aXBsZSBhbmQgbmVzdGVkIGlucHV0IGVsZW1lbnRzIG1heSBiZSByZW5kZXJlZC5cclxuICogSWYgeW91IGFsc28gd2FudCBhIGxhYmVsLCB1c2UgUmVzdFdvcmxkRGlzcGxheUVsZW1lbnRDb21wb25lbnQgPHJ3LWRpc3BsYXktZWxlbWVudD4uXHJcbiAqIFlvdSBjYW4gYWxzbyB1c2Ugb25lIG9mIHRoZSBkaWZmZXJlbnQgUmVzdFdvcmxkRGlzcGxheS4uLiA8cnctZGlzcGxheS0uLi4+IGVsZW1lbnRzIHRvIHJlbmRlciBhIHNwZWNpZmljICBwcm9wZXJ0eSB0eXBlLFxyXG4gKiBidXQgaXQgaXMgYWR2aXNlZCB0byBjb250cm9sIHRoZSByZW5kZXJlZCBlbGVtZW50IHRocm91Z2ggdGhlIHBhc3NlZCBpbiBwcm9wZXJ0eS5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdydy1kaXNwbGF5JyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9yZXN0d29ybGQtZGlzcGxheS9yZXN0d29ybGQtZGlzcGxheS5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXkvcmVzdHdvcmxkLWRpc3BsYXkuY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlDb21wb25lbnQ8VFByb3BlcnR5IGV4dGVuZHMgUHJvcGVydHk8U2ltcGxlVmFsdWUsIHN0cmluZywgc3RyaW5nPj4ge1xyXG4gICAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcclxuICAgIHByb3BlcnR5ITogVFByb3BlcnR5O1xyXG5cclxuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXHJcbiAgICBhcGlOYW1lITogc3RyaW5nO1xyXG5cclxuICAgIHByaXZhdGUgX3ZhbHVlPzogRXh0cmFjdFZhbHVlVHlwZTxUUHJvcGVydHk+IHwgRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT5bXSB8IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+IHwgUmVjb3JkPHN0cmluZywgU2ltcGxlVmFsdWU+IHwgTWFwPG51bWJlciwgUmVjb3JkPHN0cmluZywgU2ltcGxlVmFsdWU+PjtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIHZhbHVlIHRvIGRpc3BsYXkuIElmIG5vdCBzZXQsIHRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgd2lsbCBiZSB1c2VkLlxyXG4gICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IHZhbHVlKHZhbHVlOiBFeHRyYWN0VmFsdWVUeXBlPFRQcm9wZXJ0eT4gfCBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PltdIHwgRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT4gfCBSZWNvcmQ8c3RyaW5nLCBTaW1wbGVWYWx1ZT4gfCBNYXA8bnVtYmVyLCBSZWNvcmQ8c3RyaW5nLCBTaW1wbGVWYWx1ZT4+IHwgdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgdGhpcy5fdmFsdWUgPSB2YWx1ZTtcclxuICAgIH1cclxuICAgIHB1YmxpYyBnZXQgdmFsdWUoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlID8/IHRoaXMucHJvcGVydHkudmFsdWUgYXMgRXh0cmFjdFZhbHVlVHlwZTxUUHJvcGVydHk+O1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgUHJvcGVydHlUeXBlKCkge1xyXG4gICAgICAgIHJldHVybiBQcm9wZXJ0eVR5cGU7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldCBQcm9wZXJ0eVdpdGhPcHRpb25zKCkge1xyXG4gICAgICAgIHJldHVybiBQcm9wZXJ0eVdpdGhPcHRpb25zPFNpbXBsZVZhbHVlLCBzdHJpbmcsIHN0cmluZz47XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEaXNwbGF5cyB0aGUgdmFsdWUgb2YgYSBjb2xsZWN0aW9uIHRoYXQgaXMgYXV0b21hdGljYWxseSBjcmVhdGVkIGZyb20gdGhlIGdpdmVuIHByb3BlcnR5LlxyXG4gKiBUaGUgZWxlbWVudHMgYW5kIGNhbiBhbHNvIGJlIG5lc3RlZC5cclxuICogQHJlbWFya3MgSXQgaXMgYWR2aXNlZCB0byB1c2UgUmVzdFdvcmxkRGlzcGxheUNvbXBvbmVudCA8cnctZGlzcGxheT4gYW5kIGNvbnRyb2wgdGhlIHJlbmRlcmVkIGVsZW1lbnRzIHdpdGggdGhlIHBhc3NlZCBpbiBwcm9wZXJ0eVxyXG4gKiBpbnN0ZWFkIG9mIHVzaW5nIHRoaXMgY29tcG9uZW50IGRpcmVjdGx5LlxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3J3LWRpc3BsYXktY29sbGVjdGlvbicsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktY29sbGVjdGlvbi9yZXN0d29ybGQtZGlzcGxheS1jb2xsZWN0aW9uLmNvbXBvbmVudC5odG1sJyxcclxuICAgIHN0eWxlVXJsOiAnLi9yZXN0d29ybGQtZGlzcGxheS1jb2xsZWN0aW9uL3Jlc3R3b3JsZC1kaXNwbGF5LWNvbGxlY3Rpb24uY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlDb2xsZWN0aW9uQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXHJcbiAgICBwcm9wZXJ0eSE6IFByb3BlcnR5ICYgeyBfdGVtcGxhdGVzOiB7IGRlZmF1bHQ6IFRlbXBsYXRlIH0gfTtcclxuXHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgYXBpTmFtZSE6IHN0cmluZztcclxuXHJcbiAgICBwcml2YXRlIF92YWx1ZXM/OiBhbnlbXTtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIHZhbHVlIHRvIGRpc3BsYXkuIElmIG5vdCBzZXQsIHRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgd2lsbCBiZSB1c2VkLlxyXG4gICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IHZhbHVlcyh2YWx1ZXM6IGFueVtdIHwgUGFydGlhbDxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB8IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHRoaXMuX3ZhbHVlcyA9IFJlc3RXb3JsZERpc3BsYXlDb2xsZWN0aW9uQ29tcG9uZW50LnRvQXJyYXkodmFsdWVzKTtcclxuICAgIH1cclxuICAgIHB1YmxpYyBnZXQgdmFsdWVzKCk6IGFueVtdIHwgdW5kZWZpbmVkIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3RlbXBsYXRlczogTnVtYmVyVGVtcGxhdGVbXSA9IFtdO1xyXG4gICAgcHVibGljIGdldCB0ZW1wbGF0ZXMoKTogTnVtYmVyVGVtcGxhdGVbXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RlbXBsYXRlcztcclxuICAgIH1cclxuXHJcbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLl90ZW1wbGF0ZXMgPSB0aGlzLl92YWx1ZXMgP1xyXG4gICAgICAgICAgICBBcnJheS5mcm9tKFJlc3RXb3JsZERpc3BsYXlDb2xsZWN0aW9uQ29tcG9uZW50Lm1hcCh0aGlzLl92YWx1ZXMuZW50cmllcygpLCBlbnRyeSA9PiAobmV3IE51bWJlclRlbXBsYXRlKHsgLi4uKHRoaXMucHJvcGVydHkuX3RlbXBsYXRlcy5kZWZhdWx0IGFzIFRlbXBsYXRlRHRvKSwgdGl0bGU6IGVudHJ5WzBdLnRvU3RyaW5nKCkgfSkpKSkgOlxyXG4gICAgICAgICAgICBSZXN0V29ybGREaXNwbGF5Q29sbGVjdGlvbkNvbXBvbmVudC5nZXRDb2xsZWN0aW9uRW50cnlUZW1wbGF0ZXModGhpcy5wcm9wZXJ0eSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgKiBtYXA8VDEsIFQyPihpdGVyYWJsZTogSXRlcmFibGVJdGVyYXRvcjxUMT4sIGNhbGxiYWNrOiAodmFsdWU6IFQxKSA9PiBUMikge1xyXG4gICAgICAgIGZvciAobGV0IHggb2YgaXRlcmFibGUpIHtcclxuICAgICAgICAgICAgeWllbGQgY2FsbGJhY2soeCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIHRvQXJyYXkoYXJyYXlPckRpY3Rpb25hcnk6IGFueVtdIHwgUGFydGlhbDxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB8IHVuZGVmaW5lZCk6IGFueVtdIHwgdW5kZWZpbmVkIHtcclxuICAgICAgICBpZiAoIWFycmF5T3JEaWN0aW9uYXJ5KVxyXG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG5cclxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhcnJheU9yRGljdGlvbmFyeSkpXHJcbiAgICAgICAgICAgIHJldHVybiBhcnJheU9yRGljdGlvbmFyeTtcclxuXHJcbiAgICAgICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKGFycmF5T3JEaWN0aW9uYXJ5KS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gKHsga2V5LCB2YWx1ZSB9KSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0Q29sbGVjdGlvbkVudHJ5VGVtcGxhdGVzKHByb3BlcnR5PzogUHJvcGVydHkpOiBOdW1iZXJUZW1wbGF0ZVtdIHtcclxuICAgICAgICBpZiAoIXByb3BlcnR5KVxyXG4gICAgICAgICAgICByZXR1cm4gW107XHJcblxyXG4gICAgICAgIHJldHVybiBPYmplY3QuZW50cmllcyhwcm9wZXJ0eS5fdGVtcGxhdGVzKVxyXG4gICAgICAgICAgICAuZmlsdGVyKChba2V5LCB2YWx1ZV0pID0+IE51bWJlci5pc0ludGVnZXIoTnVtYmVyLnBhcnNlSW50KGtleSkpICYmIE51bWJlci5pc0ludGVnZXIoTnVtYmVyLnBhcnNlSW50KHZhbHVlPy50aXRsZSA/PyBcIlwiKSkpXHJcbiAgICAgICAgICAgIC5tYXAoKFssIHZhbHVlXSkgPT4gbmV3IE51bWJlclRlbXBsYXRlKHZhbHVlIGFzIFRlbXBsYXRlRHRvKSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEaXNwbGF5cyB0aGUgdmFsdWUgb2YgYSBkcm9wZG93biB0aGF0IGlzIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBmcm9tIHRoZSBnaXZlbiBwcm9wZXJ0eS5cclxuICogSWYgc2V0IHRoZSBkcm9wZG93biB3aWxsIHVzZSB0aGUgYGlubGluZWAgcHJvcGVydHkgb2YgdGhlIG9wdGlvbnMgdG8gcmVuZGVyIHRoZSBgc2VsZWN0ZWRWYWx1ZXNgIE90aGVyd2lzZSBpdCB3aWxsIGp1c3QgcmVuZGVyIHRoZSB2YWx1ZXMsIGJ1dCBubyBwcm9tcHQgZm9yIHRoZW0uXHJcbiAqIEByZW1hcmtzIEl0IGlzIGFkdmlzZWQgdG8gdXNlIFJlc3RXb3JsZERpc3BsYXlDb21wb25lbnQgPHJ3LWRpc3BsYXk+IGFuZCBjb250cm9sIHRoZSByZW5kZXJlZCBlbGVtZW50cyB3aXRoIHRoZSBwYXNzZWQgaW4gcHJvcGVydHlcclxuICogaW5zdGVhZCBvZiB1c2luZyB0aGlzIGNvbXBvbmVudCBkaXJlY3RseS5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdydy1kaXNwbGF5LWRyb3Bkb3duJyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9yZXN0d29ybGQtZGlzcGxheS1kcm9wZG93bi9yZXN0d29ybGQtZGlzcGxheS1kcm9wZG93bi5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktZHJvcGRvd24vcmVzdHdvcmxkLWRpc3BsYXktZHJvcGRvd24uY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlEcm9wZG93bkNvbXBvbmVudDxUUHJvcGVydHkgZXh0ZW5kcyBQcm9wZXJ0eTxTaW1wbGVWYWx1ZSwgc3RyaW5nLCBzdHJpbmc+ICYgeyBvcHRpb25zOiBPcHRpb25zPFNpbXBsZVZhbHVlLCBzdHJpbmcsIHN0cmluZz4gfSwgVE9wdGlvbnNJdGVtIGV4dGVuZHMgRXh0cmFjdEdlbmVyaWNPcHRpb25zSXRlbVR5cGU8VFByb3BlcnR5PiA9IEV4dHJhY3RHZW5lcmljT3B0aW9uc0l0ZW1UeXBlPFRQcm9wZXJ0eT4+IGltcGxlbWVudHMgT25Jbml0IHtcclxuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXHJcbiAgICBwcm9wZXJ0eSE6IFRQcm9wZXJ0eTtcclxuXHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgYXBpTmFtZSE6IHN0cmluZztcclxuXHJcbiAgICBwcml2YXRlIF9zZWxlY3RlZFZhbHVlcz86IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+W107XHJcbiAgICAvKipcclxuICAgICAqIFRoZSB2YWx1ZXMgdG8gZGlzcGxheS4gSWYgbm90IHNldCwgdGhlIHZhbHVlcyBvZiB0aGUgcHJvcGVydHkgb3B0aW9ucyB3aWxsIGJlIHVzZWQuXHJcbiAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBzZXQgc2VsZWN0ZWRWYWx1ZXModmFsdWU6IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+W10gfCBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PiB8IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSlcclxuICAgICAgICAgICAgdGhpcy5fc2VsZWN0ZWRWYWx1ZXMgPSB2YWx1ZSBhcyBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PltdO1xyXG4gICAgICAgIGVsc2UgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwpXHJcbiAgICAgICAgICAgIHRoaXMuX3NlbGVjdGVkVmFsdWVzID0gW3ZhbHVlXTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IHNlbGVjdGVkVmFsdWVzKCk6IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+W10ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9zZWxlY3RlZFZhbHVlcyA/PyAodGhpcy5wcm9wZXJ0eS5vcHRpb25zLnNlbGVjdGVkVmFsdWVzIGFzIHVua25vd24gYXMgRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT5bXSB8IHVuZGVmaW5lZCkgPz8gW107XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfaW5saW5lOiBUT3B0aW9uc0l0ZW1bXSA9IFtdO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQSBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlIGxhYmVsIGZvciB0aGUgZ2l2ZW4gaXRlbS5cclxuICAgICAqIFRoZSBkZWZhdWx0IHJldHVybnMgdGhlIHByb21wdCBhbmQgb3B0aW9uYWxseSB0aGUgdmFsdWUgaW4gYnJhY2tldHMuXHJcbiAgICAgKiBUaGUgdmFsdWUgaW4gYnJhY2tldHMgd2lsbCBvbmx5IGJlIGRpc3BsYXllZCBpZiB0aGUgYGNvbHNgIGZpZWxkIG9mIHRoZSBwcm9wZXJ0eSBpcyB1bmRlZmluZWQgb3IgZ3JlYXRlciB0aGFuIDEuXHJcbiAgICAgKiBPdmVyd3JpdGUgdGhpcyBmdW5jdGlvbiB0byBjaGFuZ2UgdGhlIGxhYmVsLlxyXG4gICAgICogQHBhcmFtIGl0ZW0gVGhlIGl0ZW0gdG8gZ2V0IHRoZSBsYWJlbCBmb3IuXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBnZXRMYWJlbDogKGl0ZW06IFRPcHRpb25zSXRlbSkgPT4gc3RyaW5nID0gdGhpcy5nZXRMYWJlbEludGVybmFsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQSBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlIHRvb2x0aXAgZm9yIHRoZSBnaXZlbiBpdGVtLlxyXG4gICAgICogVGhlIGRlZmF1bHQgcmV0dXJucyBhbGwgcHJvcGVydGllcyBvZiB0aGUgaXRlbSBleGNlcHQgdGhlIG9uZXMgdGhhdCBzdGFydCB3aXRoIGFuIHVuZGVyc2NvcmUgb3IgdGhlIG9uZXMgdGhhdCBhcmUgaW4gdGhlIGxpc3Qgb2YgZGVmYXVsdCBwcm9wZXJ0aWVzIHRvIGV4Y2x1ZGUuXHJcbiAgICAgKiBUaGUgZGVmYXVsdCBwcm9wZXJ0aWVzIHRvIGV4Y2x1ZGUgYXJlOiBjcmVhdGVkQXQsIGNyZWF0ZWRCeSwgbGFzdENoYW5nZWRBdCwgbGFzdENoYW5nZWRCeSwgdGltZXN0YW1wLCBwcm9tcHRGaWVsZCwgdmFsdWVGaWVsZC5cclxuICAgICAqIE92ZXJ3cml0ZSB0aGlzIGZ1bmN0aW9uIHRvIGNoYW5nZSB0aGUgdG9vbHRpcC5cclxuICAgICAqIEBwYXJhbSBpdGVtIFRoZSBpdGVtIHRvIGdldCB0aGUgbGFiZWwgZm9yLlxyXG4gICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgZ2V0VG9vbHRpcDogKGl0ZW06IFRPcHRpb25zSXRlbSkgPT4gc3RyaW5nID0gdGhpcy5nZXRUb29sdGlwSW50ZXJuYWw7XHJcblxyXG4gICAgQENvbnRlbnRDaGlsZCgnaW5wdXRPcHRpb25zJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgICBpbnB1dE9wdGlvbnNSZWY/OiBUZW1wbGF0ZVJlZjxQcm9wZXJ0eVRlbXBsYXRlQ29udGV4dD47XHJcblxyXG4gICAgcHVibGljIGdldCB2YWx1ZUZpZWxkKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvcGVydHkub3B0aW9ucy52YWx1ZUZpZWxkID8/IFwidmFsdWVcIjtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IHByb21wdEZpZWxkKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvcGVydHkub3B0aW9ucy5wcm9tcHRGaWVsZCA/PyBcInByb21wdFwiO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgX21lc3NhZ2VTZXJ2aWNlOiBNZXNzYWdlU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IF9jbGllbnRzOiBSZXN0V29ybGRDbGllbnRDb2xsZWN0aW9uLFxyXG4gICAgKSB7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgbmdPbkluaXQoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgaWYgKHRoaXMucHJvcGVydHkub3B0aW9ucz8uaW5saW5lICYmIHRoaXMucHJvcGVydHkub3B0aW9ucy5pbmxpbmUubGVuZ3RoID4gMClcclxuICAgICAgICAgICAgdGhpcy5faW5saW5lID0gQXJyYXkuZnJvbSh0aGlzLnByb3BlcnR5Lm9wdGlvbnMuaW5saW5lKSBhcyBUT3B0aW9uc0l0ZW1bXTtcclxuXHJcbiAgICAgICAgYXdhaXQgdGhpcy5zZXRJbml0aWFsU2VsZWN0ZWRPcHRpb25zRWxlbWVudEZvclByb3BlcnR5KCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldE9wdGlvbkl0ZW0odmFsdWU6IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+KTogVE9wdGlvbnNJdGVtIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5faW5saW5lLmZpbmQobyA9PiB0aGlzLmdldFZhbHVlKG8gYXMgVE9wdGlvbnNJdGVtKSA9PT0gdmFsdWUpIGFzIFRPcHRpb25zSXRlbSA/PyB0aGlzLmNyZWF0ZU9wdGlvbnNJdGVtKHZhbHVlKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGNyZWF0ZU9wdGlvbnNJdGVtKHZhbHVlOiBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5Pik6IFRPcHRpb25zSXRlbSB7XHJcbiAgICAgICAgcmV0dXJuIHsgW3RoaXMudmFsdWVGaWVsZF06IHZhbHVlLCBbdGhpcy5wcm9tcHRGaWVsZF06IFwiXCIgfSBhcyBUT3B0aW9uc0l0ZW07XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldFZhbHVlKGl0ZW06IFRPcHRpb25zSXRlbSk6IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+IHtcclxuICAgICAgICBpZiAoaXRlbSA9PT0gdW5kZWZpbmVkIHx8IGl0ZW0gPT09IG51bGwgfHwgIWl0ZW0uaGFzT3duUHJvcGVydHkodGhpcy52YWx1ZUZpZWxkKSlcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgaXRlbSBkb2VzIG5vdCBoYXZlIGEgcHJvcGVydHkgJHt0aGlzLnZhbHVlRmllbGR9LmApO1xyXG5cclxuICAgICAgICByZXR1cm4gaXRlbVt0aGlzLnZhbHVlRmllbGQgYXMga2V5b2YgVE9wdGlvbnNJdGVtXSBhcyBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PjtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0UHJvbXB0KGl0ZW06IFRPcHRpb25zSXRlbSk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKGl0ZW0gPT09IHVuZGVmaW5lZCB8fCBpdGVtID09PSBudWxsIHx8ICFpdGVtLmhhc093blByb3BlcnR5KHRoaXMucHJvbXB0RmllbGQpKVxyXG4gICAgICAgICAgICByZXR1cm4gXCJcIjtcclxuXHJcbiAgICAgICAgcmV0dXJuIGl0ZW1bdGhpcy5wcm9tcHRGaWVsZCBhcyBrZXlvZiBUT3B0aW9uc0l0ZW1dIGFzIHN0cmluZztcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0TGFiZWxJbnRlcm5hbChpdGVtOiBUT3B0aW9uc0l0ZW0pOiBzdHJpbmcge1xyXG4gICAgICAgIGlmIChpdGVtID09PSB1bmRlZmluZWQgfHwgaXRlbSA9PT0gbnVsbClcclxuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21wdCA9IHRoaXMuZ2V0UHJvbXB0KGl0ZW0pO1xyXG4gICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5nZXRWYWx1ZShpdGVtKTtcclxuXHJcbiAgICAgICAgbGV0IGxhYmVsID0gcHJvbXB0O1xyXG4gICAgICAgIGlmIChsYWJlbCA9PT0gdW5kZWZpbmVkIHx8IGxhYmVsID09PSBudWxsIHx8IGxhYmVsID09PSBcIlwiKVxyXG4gICAgICAgICAgICBsYWJlbCA9ICh2YWx1ZT8udG9TdHJpbmcoKSA/PyBcIlwiKTtcclxuICAgICAgICBlbHNlIGlmICgodGhpcy5wcm9wZXJ0eS5jb2xzID09PSB1bmRlZmluZWQgfHwgdGhpcy5wcm9wZXJ0eS5jb2xzID4gMSkgJiYgcHJvbXB0Py50b0xvd2VyQ2FzZSgpICE9PSB2YWx1ZT8udG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpKVxyXG4gICAgICAgICAgICBsYWJlbCArPSBgICgke3ZhbHVlfSlgO1xyXG5cclxuICAgICAgICByZXR1cm4gbGFiZWw7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBnZXRUb29sdGlwSW50ZXJuYWwoaXRlbTogVE9wdGlvbnNJdGVtKTogc3RyaW5nIHtcclxuICAgICAgICBpZiAoaXRlbSA9PT0gdW5kZWZpbmVkIHx8IGl0ZW0gPT09IG51bGwpXHJcbiAgICAgICAgICAgIHJldHVybiBcIlwiO1xyXG5cclxuICAgICAgICBjb25zdCB0b29sdGlwID0gT2JqZWN0LmVudHJpZXMoaXRlbSlcclxuICAgICAgICAgICAgLmZpbHRlcigoW2tleV0pID0+ICEoa2V5LnN0YXJ0c1dpdGgoJ18nKSB8fCBbJ2NyZWF0ZWRBdCcsICdjcmVhdGVkQnknLCAnbGFzdENoYW5nZWRBdCcsICdsYXN0Q2hhbmdlZEJ5JywgJ3RpbWVzdGFtcCcsIHRoaXMucHJvbXB0RmllbGQsIHRoaXMudmFsdWVGaWVsZF0uaW5jbHVkZXMoa2V5KSkpXHJcbiAgICAgICAgICAgIC5yZWR1Y2UoKHByZXYsIFtrZXksIHZhbHVlXSwgaW5kZXgpID0+IGAke3ByZXZ9JHtpbmRleCA9PT0gMCA/ICcnIDogJ1xcbid9JHtrZXl9OiAke1Jlc3RXb3JsZERpc3BsYXlEcm9wZG93bkNvbXBvbmVudC5qc29uU3RyaW5naWZ5V2l0aEVsaXBzaXModmFsdWUpfWAsICcnKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRvb2x0aXA7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBhc3luYyBzZXRJbml0aWFsU2VsZWN0ZWRPcHRpb25zRWxlbWVudEZvclByb3BlcnR5KCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLnByb3BlcnR5Lm9wdGlvbnM7XHJcblxyXG4gICAgICAgIGlmICghb3B0aW9ucy5saW5rPy5ocmVmIHx8ICF0aGlzLnNlbGVjdGVkVmFsdWVzIHx8IHRoaXMuc2VsZWN0ZWRWYWx1ZXMubGVuZ3RoID09PSAwIHx8IHRoaXMuc2VsZWN0ZWRWYWx1ZXMuZXZlcnkodiA9PiB0aGlzLl9pbmxpbmUuc29tZShpID0+IHRoaXMuZ2V0VmFsdWUoaSBhcyBUT3B0aW9uc0l0ZW0pID09PSB2KSA/PyBmYWxzZSkpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgY29uc3QgZmlsdGVyID0gYCR7b3B0aW9ucy52YWx1ZUZpZWxkfSBpbiAoJHt0aGlzLnNlbGVjdGVkVmFsdWVzfSlgO1xyXG4gICAgICAgIGF3YWl0IHRoaXMuU2V0SW5saW5lT3B0aW9uc0Zyb21GaWx0ZXIoZmlsdGVyKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGFzeW5jIFNldElubGluZU9wdGlvbnNGcm9tRmlsdGVyKGZpbHRlcjogc3RyaW5nKSB7XHJcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMucHJvcGVydHkub3B0aW9ucztcclxuICAgICAgICBpZiAoIW9wdGlvbnMubGluaz8uaHJlZilcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgcHJvcGVydHkgZG9lcyBub3QgaGF2ZSBhIGxpbmsgaHJlZi4nKTtcclxuXHJcbiAgICAgICAgY29uc3QgdGVtcGxhdGVkVXJpID0gb3B0aW9ucy5saW5rLmhyZWY7XHJcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpLmdldExpc3RCeVVyaTxUT3B0aW9uc0l0ZW0+KHRlbXBsYXRlZFVyaSwgeyAkZmlsdGVyOiBmaWx0ZXIsICR0b3A6IDEwIH0pO1xyXG4gICAgICAgIGlmICghcmVzcG9uc2Uub2sgfHwgUHJvYmxlbURldGFpbHMuaXNQcm9ibGVtRGV0YWlscyhyZXNwb25zZS5ib2R5KSB8fCAhcmVzcG9uc2UuYm9keSkge1xyXG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gYEFuIGVycm9yIG9jY3VycmVkIHdoaWxlIGdldHRpbmcgdGhlIGluaXRpYWwgc2VsZWN0ZWQgaXRlbXMgZm9yIHRoZSBwcm9wZXJ0eSAke3RoaXMucHJvcGVydHkubmFtZX0uYDtcclxuICAgICAgICAgICAgdGhpcy5fbWVzc2FnZVNlcnZpY2UuYWRkKHsgc2V2ZXJpdHk6ICdlcnJvcicsIHN1bW1hcnk6ICdFcnJvcicsIGRldGFpbDogbWVzc2FnZSwgZGF0YTogcmVzcG9uc2UsIHN0aWNreTogdHJ1ZSB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGl0ZW1zID0gcmVzcG9uc2UuYm9keSEuX2VtYmVkZGVkLml0ZW1zIGFzIFJlc291cmNlT2ZEdG88VE9wdGlvbnNJdGVtPltdO1xyXG4gICAgICAgIGNvbnN0IG5ld0l0ZW1zID0gdGhpcy5jb21iaW5lSW5saW5lV2l0aFNlbGVjdGVkKGl0ZW1zKTtcclxuICAgICAgICB0aGlzLl9pbmxpbmUgPSBuZXdJdGVtcztcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGNvbWJpbmVJbmxpbmVXaXRoU2VsZWN0ZWQoaXRlbXM6IFJlc291cmNlT2ZEdG88VE9wdGlvbnNJdGVtPltdKTogVE9wdGlvbnNJdGVtW10ge1xyXG4gICAgICAgIGNvbnN0IG9sZElubGluZSA9IHRoaXMuX2lubGluZSBhcyBSZXNvdXJjZU9mRHRvPFRPcHRpb25zSXRlbT5bXTtcclxuICAgICAgICBpZiAoIW9sZElubGluZSB8fCBvbGRJbmxpbmUubGVuZ3RoID09PSAwKVxyXG4gICAgICAgICAgICByZXR1cm4gaXRlbXM7XHJcblxyXG4gICAgICAgIGNvbnN0IGl0ZW1zVG9LZWVwID0gb2xkSW5saW5lLmZpbHRlcihpID0+IHRoaXMuc2VsZWN0ZWRWYWx1ZXMuaW5jbHVkZXModGhpcy5nZXRWYWx1ZShpIGFzIFRPcHRpb25zSXRlbSkpKTtcclxuICAgICAgICBjb25zdCBuZXdJdGVtcyA9IGl0ZW1zLmNvbmNhdChpdGVtc1RvS2VlcC5maWx0ZXIoaSA9PiAhaXRlbXMuaW5jbHVkZXMoaSkpKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIG5ld0l0ZW1zO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0Q2xpZW50KCk6IFJlc3RXb3JsZENsaWVudCB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmFwaU5hbWUpXHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGdldCBhIGNsaWVudCwgYmVjYXVzZSB0aGUgYXBpTmFtZSBpcyBub3Qgc2V0LicpO1xyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5fY2xpZW50cy5nZXRDbGllbnQodGhpcy5hcGlOYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyBqc29uU3RyaW5naWZ5V2l0aEVsaXBzaXModmFsdWU6IHVua25vd24pIHtcclxuICAgICAgICBjb25zdCBtYXhMZW5ndGggPSAyMDA7XHJcbiAgICAgICAgY29uc3QgZW5kID0gMTA7XHJcbiAgICAgICAgY29uc3Qgc3RhcnQgPSBtYXhMZW5ndGggLSBlbmQgLSAyO1xyXG4gICAgICAgIGNvbnN0IGpzb24gPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XHJcbiAgICAgICAgY29uc3Qgc2hvcnRlbmVkID0ganNvbi5sZW5ndGggPiBtYXhMZW5ndGggPyBqc29uLnN1YnN0cmluZygwLCBzdGFydCkgKyAn4oCmJyArIGpzb24uc3Vic3RyaW5nKGpzb24ubGVuZ3RoIC0gZW5kKSA6IGpzb247XHJcblxyXG4gICAgICAgIHJldHVybiBzaG9ydGVuZWQ7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEaXNwbGF5cyB0aGUgdmFsdWUgb2YgYSBjb21wbGV4IG9iamVjdCB3aXRoIG11bHRpcGxlIHByb3BlcnRpZXMgdGhhdCBpcyBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQgZnJvbSB0aGUgZ2l2ZW4gcHJvcGVydHkuXHJcbiAqIFRoZSBvYmplY3QgY2FuIGFsc28gYmUgbmVzdGVkLlxyXG4gKiBAcmVtYXJrcyBJdCBpcyBhZHZpc2VkIHRvIHVzZSBSZXN0V29ybGREaXNwbGF5Q29tcG9uZW50IDxydy1kaXNwbGF5PiBhbmQgY29udHJvbCB0aGUgcmVuZGVyZWQgZWxlbWVudHMgd2l0aCB0aGUgcGFzc2VkIGluIHByb3BlcnR5XHJcbiAqIGluc3RlYWQgb2YgdXNpbmcgdGhpcyBjb21wb25lbnQgZGlyZWN0bHkuXHJcbiAqL1xyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAncnctZGlzcGxheS1vYmplY3QnLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL3Jlc3R3b3JsZC1kaXNwbGF5LW9iamVjdC9yZXN0d29ybGQtZGlzcGxheS1vYmplY3QuY29tcG9uZW50Lmh0bWwnLFxyXG4gICAgc3R5bGVVcmw6ICcuL3Jlc3R3b3JsZC1kaXNwbGF5LW9iamVjdC9yZXN0d29ybGQtZGlzcGxheS1vYmplY3QuY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlPYmplY3RDb21wb25lbnQge1xyXG4gICAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcclxuICAgIHByb3BlcnR5ITogUHJvcGVydHk8bnVsbCwgbmV2ZXIsIG5ldmVyPiAmIHsgX3RlbXBsYXRlczogeyBkZWZhdWx0OiBUZW1wbGF0ZSB9IH07XHJcblxyXG4gICAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcclxuICAgIGFwaU5hbWUhOiBzdHJpbmc7XHJcblxyXG4gICAgcHJpdmF0ZSBfdmFsdWU/OiBSZWNvcmQ8c3RyaW5nLCBTaW1wbGVWYWx1ZT47XHJcbiAgICAvKipcclxuICAgICAqIFRoZSB2YWx1ZSB0byBkaXNwbGF5LiBJZiBub3Qgc2V0LCB0aGUgdmFsdWUgb2YgdGhlIHRlbXBsYXRlIHByb3BlcnRpZXMgd2lsbCBiZSB1c2VkLlxyXG4gICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IHZhbHVlKHZhbHVlOiBSZWNvcmQ8c3RyaW5nLCBTaW1wbGVWYWx1ZT4gfCB1bmRlZmluZWQpIHtcclxuICAgICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xyXG4gICAgfVxyXG4gICAgcHVibGljIGdldCB2YWx1ZSgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWU7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEaXNwbGF5cyB0aGUgdmFsdWUgb2YgYSBzaW1wbGUgZWxlbWVudCwgbGlrZSBhIHN0cmluZywgYSBudW1iZXIgb3IgYSBEYXRlIHRoYXQgaXMgYXV0b21hdGljYWxseSBjcmVhdGVkIGZyb20gdGhlIGdpdmVuIHByb3BlcnR5LlxyXG4gKiBAcmVtYXJrcyBJdCBpcyBhZHZpc2VkIHRvIHVzZSBSZXN0V29ybGREaXNwbGF5Q29tcG9uZW50IDxydy1kaXNwbGF5PiBhbmQgY29udHJvbCB0aGUgcmVuZGVyZWQgZWxlbWVudHMgd2l0aCB0aGUgcGFzc2VkIGluIHByb3BlcnR5XHJcbiAqIGluc3RlYWQgb2YgdXNpbmcgdGhpcyBjb21wb25lbnQgZGlyZWN0bHkuXHJcbiAqL1xyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAncnctZGlzcGxheS1zaW1wbGUnLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL3Jlc3R3b3JsZC1kaXNwbGF5LXNpbXBsZS9yZXN0d29ybGQtZGlzcGxheS1zaW1wbGUuY29tcG9uZW50Lmh0bWwnLFxyXG4gICAgc3R5bGVVcmw6ICcuL3Jlc3R3b3JsZC1kaXNwbGF5LXNpbXBsZS9yZXN0d29ybGQtZGlzcGxheS1zaW1wbGUuY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlTaW1wbGVDb21wb25lbnQ8VFByb3BlcnR5IGV4dGVuZHMgUHJvcGVydHk8U2ltcGxlVmFsdWUsIHN0cmluZywgc3RyaW5nPj4ge1xyXG4gICAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcclxuICAgIHByb3BlcnR5ITogVFByb3BlcnR5O1xyXG5cclxuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXHJcbiAgICBhcGlOYW1lITogc3RyaW5nO1xyXG5cclxuICAgIHByaXZhdGUgX3ZhbHVlPzogU2ltcGxlVmFsdWU7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSB2YWx1ZSB0byBkaXNwbGF5LiBJZiBub3Qgc2V0LCB0aGUgdmFsdWUgb2YgdGhlIHByb3BlcnR5IHdpbGwgYmUgdXNlZC5cclxuICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIHNldCB2YWx1ZSh2YWx1ZTogU2ltcGxlVmFsdWUpIHtcclxuICAgICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xyXG4gICAgfVxyXG4gICAgcHVibGljIGdldCB2YWx1ZSgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWUgPz8gdGhpcy5wcm9wZXJ0eS52YWx1ZTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IFByb3BlcnR5VHlwZSgpIHtcclxuICAgICAgICByZXR1cm4gUHJvcGVydHlUeXBlO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IF9kYXRlRm9ybWF0ID0gbmV3IERhdGUoMzMzMywgMTAsIDIyKSAvLyBtb250aHMgc3RhcnQgYXQgMCBpbiBKU1xyXG4gICAgICAgIC50b0xvY2FsZURhdGVTdHJpbmcoKVxyXG4gICAgICAgIC5yZXBsYWNlKFwiMjJcIiwgXCJkZFwiKVxyXG4gICAgICAgIC5yZXBsYWNlKFwiMTFcIiwgXCJNTVwiKVxyXG4gICAgICAgIC5yZXBsYWNlKFwiMzMzM1wiLCBcInl5eXlcIilcclxuICAgICAgICAucmVwbGFjZShcIjMzXCIsIFwieXlcIik7XHJcblxyXG4gICAgcHVibGljIGdldCBkYXRlRm9ybWF0KCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIFJlc3RXb3JsZERpc3BsYXlTaW1wbGVDb21wb25lbnQuX2RhdGVGb3JtYXQ7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgX3RpbWVGb3JtYXQgPSBuZXcgRGF0ZSgxLCAxLCAxLCAyMiwgMzMsIDQ0KVxyXG4gICAgICAgIC50b0xvY2FsZVRpbWVTdHJpbmcoKVxyXG4gICAgICAgIC5yZXBsYWNlKFwiMjJcIiwgXCJoaFwiKVxyXG4gICAgICAgIC5yZXBsYWNlKFwiMzNcIiwgXCJtbVwiKVxyXG4gICAgICAgIC5yZXBsYWNlKFwiNDRcIiwgXCJzc1wiKTtcclxuXHJcbiAgICBwdWJsaWMgZ2V0IHRpbWVGb3JtYXQoKSB7XHJcbiAgICAgICAgcmV0dXJuIFJlc3RXb3JsZERpc3BsYXlTaW1wbGVDb21wb25lbnQuX3RpbWVGb3JtYXQ7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldCBQcm9wZXJ0eVdpdGhJbWFnZSgpIHtcclxuICAgICAgICByZXR1cm4gUHJvcGVydHlXaXRoSW1hZ2U7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEaXNwbGF5cyB0aGUgdmFsdWVzIG9mIGEgY29sbGVjdGlvbiBvZiBydy1kaXNwbGF5LWVsZW1lbnRzIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBmcm9tIGEgdGVtcGxhdGUuXHJcbiAqL1xyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAncnctZGlzcGxheS10ZW1wbGF0ZScsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktdGVtcGxhdGUvcmVzdHdvcmxkLWRpc3BsYXktdGVtcGxhdGUuY29tcG9uZW50Lmh0bWwnLFxyXG4gICAgc3R5bGVVcmw6ICcuL3Jlc3R3b3JsZC1kaXNwbGF5LXRlbXBsYXRlL3Jlc3R3b3JsZC1kaXNwbGF5LXRlbXBsYXRlLmNvbXBvbmVudC5jc3MnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBSZXN0V29ybGREaXNwbGF5VGVtcGxhdGVDb21wb25lbnQge1xyXG4gICAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcclxuICAgIHRlbXBsYXRlITogVGVtcGxhdGU7XHJcblxyXG4gICAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcclxuICAgIGFwaU5hbWUhOiBzdHJpbmc7XHJcblxyXG4gICAgcHJpdmF0ZSBfdmFsdWU/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgdmFsdWUgdG8gZGlzcGxheS4gSWYgbm90IHNldCwgdGhlIHZhbHVlcyBvZiB0aGUgdGVtcGxhdGUgcHJvcGVydGllcyB3aWxsIGJlIHVzZWQuXHJcbiAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBzZXQgdmFsdWUodmFsdWU6IFJlY29yZDxzdHJpbmcsIGFueT4gfCB1bmRlZmluZWQpIHtcclxuICAgICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xyXG4gICAgfVxyXG4gICAgcHVibGljIGdldCB2YWx1ZSgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWU7XHJcbiAgICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cImdyaWQgZmllbGRcIiAqbmdJZj1cInByb3BlcnR5LnR5cGUgIT09IFByb3BlcnR5VHlwZS5IaWRkZW5cIj5cclxuICAgIDxydy1sYWJlbCBbcHJvcGVydHldPVwicHJvcGVydHlcIiBjbGFzcz1cImNvbC0xMiBtZDpjb2wtMiBmbGV4IGFsaWduLWl0ZW1zLWNlbnRlclwiPjwvcnctbGFiZWw+XHJcbiAgICA8cnctZGlzcGxheSBbcHJvcGVydHldPVwicHJvcGVydHlcIiBbdmFsdWVdPVwidmFsdWVcIiBbYXBpTmFtZV09XCJhcGlOYW1lXCIgY2xhc3M9XCJjb2wtMTIgbWQ6Y29sLTEwXCI+PC9ydy1kaXNwbGF5PlxyXG48L2Rpdj5cclxuIiwiPG5nLWNvbnRhaW5lciAqbmdJZj1cInByb3BlcnR5LnR5cGUgIT09IFByb3BlcnR5VHlwZS5IaWRkZW5cIj5cclxuICAgIDxydy1kaXNwbGF5LWRyb3Bkb3duICpuZ0lmPVwicHJvcGVydHkub3B0aW9uc1wiIFtwcm9wZXJ0eV09XCIkYW55KHByb3BlcnR5KVwiIFtzZWxlY3RlZFZhbHVlc109XCIkYW55KHZhbHVlKVwiIFthcGlOYW1lXT1cImFwaU5hbWVcIj48L3J3LWRpc3BsYXktZHJvcGRvd24+XHJcblxyXG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFwcm9wZXJ0eS5vcHRpb25zXCI+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lciBbbmdTd2l0Y2hdPVwicHJvcGVydHkudHlwZVwiPlxyXG4gICAgICAgICAgICA8cnctZGlzcGxheS1vYmplY3QgKm5nU3dpdGNoQ2FzZT1cIlByb3BlcnR5VHlwZS5PYmplY3RcIiBbcHJvcGVydHldPVwiJGFueShwcm9wZXJ0eSlcIiBbdmFsdWVdPVwiJGFueSh2YWx1ZSlcIiBbYXBpTmFtZV09XCJhcGlOYW1lXCI+PC9ydy1kaXNwbGF5LW9iamVjdD5cclxuICAgICAgICAgICAgPHJ3LWRpc3BsYXktY29sbGVjdGlvbiAqbmdTd2l0Y2hDYXNlPVwiUHJvcGVydHlUeXBlLkNvbGxlY3Rpb25cIiBbcHJvcGVydHldPVwiJGFueShwcm9wZXJ0eSlcIiBbdmFsdWVzXT1cIiRhbnkodmFsdWUpXCIgW2FwaU5hbWVdPVwiYXBpTmFtZVwiPjwvcnctZGlzcGxheS1jb2xsZWN0aW9uPlxyXG4gICAgICAgICAgICA8cnctZGlzcGxheS1zaW1wbGUgKm5nU3dpdGNoRGVmYXVsdCBbcHJvcGVydHldPVwicHJvcGVydHlcIiBbdmFsdWVdPVwiJGFueSh2YWx1ZSlcIiBbYXBpTmFtZV09XCJhcGlOYW1lXCI+PC9ydy1kaXNwbGF5LXNpbXBsZT5cclxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgIDwvbmctY29udGFpbmVyPlxyXG48L25nLWNvbnRhaW5lcj5cclxuIiwiPGRpdiBjbGFzcz1cImZsZXggYWxpZ24taXRlbXMtY2VudGVyXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYnJhY2VcIj5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cInctZnVsbFwiPlxyXG4gICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IHRlbXBsYXRlIG9mIHRlbXBsYXRlc1wiIGNsYXNzPVwiZmxleCBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJyYWNlXCI+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidy1mdWxsIGZsZXgganVzdGlmeS1jb250ZW50LWVuZFwiPlxyXG4gICAgICAgICAgICAgICAgPHJ3LWRpc3BsYXktdGVtcGxhdGUgW3RlbXBsYXRlXT1cIiRhbnkodGVtcGxhdGUpXCIgW3ZhbHVlXT1cInZhbHVlcyA/IHZhbHVlc1t0ZW1wbGF0ZS50aXRsZSFdIDogdW5kZWZpbmVkXCIgW2FwaU5hbWVdPVwiYXBpTmFtZVwiIGNsYXNzPVwidy1mdWxsXCI+PC9ydy1kaXNwbGF5LXRlbXBsYXRlPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG48L2Rpdj5cclxuIiwiPCEtLSA8bmctdGVtcGxhdGUgI2RlZmF1bHRJbnB1dE9wdGlvbnMgbGV0LXByb3BlcnR5PVwicHJvcGVydHlcIiBsZXQtc2VsZWN0ZWRWYWx1ZXM9XCJzZWxlY3RlZFZhbHVlc1wiPiAtLT5cclxuPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgdmFsdWUgb2Ygc2VsZWN0ZWRWYWx1ZXM7IGxhc3QgYXMgbGFzdDtcIj5cclxuICAgIDxzcGFuIFtwVG9vbHRpcF09XCJnZXRUb29sdGlwKGdldE9wdGlvbkl0ZW0odmFsdWUpKVwiPnt7Z2V0TGFiZWwoZ2V0T3B0aW9uSXRlbSh2YWx1ZSkpfX08L3NwYW4+e3tsYXN0ID8gXCJcIiA6IFwiLCBcIn19XHJcbjwvbmctY29udGFpbmVyPlxyXG48IS0tIDwvbmctdGVtcGxhdGU+XHJcbjxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJpbnB1dE9wdGlvbnNSZWYgPz8gZGVmYXVsdElucHV0T3B0aW9uczsgY29udGV4dDogeyBwcm9wZXJ0eTogcHJvcGVydHksIHNlbGVjdGVkVmFsdWVzOiBzZWxlY3RlZFZhbHVlcyB9XCI+PC9uZy1jb250YWluZXI+IC0tPiIsIjxkaXYgY2xhc3M9XCJmbGV4IGFsaWduLWl0ZW1zLWNlbnRlclwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImJyYWNlXCI+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJ3LWZ1bGxcIj5cclxuICAgICAgICA8cnctZGlzcGxheS10ZW1wbGF0ZSBbdGVtcGxhdGVdPVwicHJvcGVydHkuX3RlbXBsYXRlcy5kZWZhdWx0XCIgW3ZhbHVlXT1cInZhbHVlXCIgW2FwaU5hbWVdPVwiYXBpTmFtZVwiPjwvcnctZGlzcGxheS10ZW1wbGF0ZT5cclxuICAgIDwvZGl2PlxyXG48L2Rpdj4iLCI8bmctY29udGFpbmVyIFtuZ1N3aXRjaF09XCJwcm9wZXJ0eS50eXBlXCI+XHJcbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCJQcm9wZXJ0eVR5cGUuVGV4dFwiPlxyXG4gICAgICAgIDxydy1hdmF0YXIgKm5nSWY9XCJwcm9wZXJ0eS5uYW1lID09PSAnY3JlYXRlZEJ5JyB8fCBwcm9wZXJ0eS5uYW1lID09PSAnbGFzdENoYW5nZWRCeSdcIiBbdXNlcl09XCIkYW55KHZhbHVlKVwiPjwvcnctYXZhdGFyPlxyXG4gICAgICAgIDxzcGFuICpuZ0lmPVwicHJvcGVydHkubmFtZSAhPT0gJ2NyZWF0ZWRCeScgJiYgcHJvcGVydHkubmFtZSAhPT0gJ2xhc3RDaGFuZ2VkQnknXCIgY2xhc3M9XCJ3LWZ1bGxcIj57e3ZhbHVlIHwgcHJvcGVydHlUeXBlRm9ybWF0OnByb3BlcnR5LnR5cGV9fTwvc3Bhbj5cclxuICAgIDwvbmctY29udGFpbmVyPlxyXG5cclxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIlByb3BlcnR5VHlwZS5Cb29sXCI+XHJcbiAgICAgICAgPHAtY2hlY2tib3ggKm5nSWY9XCJwcm9wZXJ0eS5yZXF1aXJlZFwiIFsobmdNb2RlbCldPVwidmFsdWVcIiBbYmluYXJ5XT1cInRydWVcIiBbcmVhZG9ubHldPVwidHJ1ZVwiIFtkaXNhYmxlZF09XCJ0cnVlXCI+PC9wLWNoZWNrYm94PlxyXG4gICAgICAgIDxwLXRyaVN0YXRlQ2hlY2tib3ggKm5nSWY9XCIhcHJvcGVydHkucmVxdWlyZWRcIiBbKG5nTW9kZWwpXT1cInZhbHVlXCIgW3JlYWRvbmx5XT1cInRydWVcIiBbZGlzYWJsZWRdPVwidHJ1ZVwiPjwvcC10cmlTdGF0ZUNoZWNrYm94PlxyXG4gICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgPHNwYW4gKm5nU3dpdGNoRGVmYXVsdCBjbGFzcz1cInctZnVsbFwiPnt7dmFsdWUgfCBwcm9wZXJ0eVR5cGVGb3JtYXQ6cHJvcGVydHkudHlwZX19PC9zcGFuPlxyXG48L25nLWNvbnRhaW5lcj5cclxuIiwiPHJ3LWRpc3BsYXktZWxlbWVudCAqbmdGb3I9XCJsZXQgcHJvcGVydHkgb2YgdGVtcGxhdGUucHJvcGVydGllc1wiIFtwcm9wZXJ0eV09XCJwcm9wZXJ0eVwiIFt2YWx1ZV09XCJ2YWx1ZSA/IHZhbHVlW3Byb3BlcnR5Lm5hbWVdIDogdW5kZWZpbmVkXCIgW2FwaU5hbWVdPVwiYXBpTmFtZVwiPjwvcnctZGlzcGxheS1lbGVtZW50PiJdfQ==