@wertzui/ngx-restworld-client 13.1.0 → 13.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/components/restworld-displays/restworld-displays.mjs +434 -0
- package/esm2022/lib/components/restworld-inputs/restworld-inputs.mjs +3 -4
- package/esm2022/lib/components/restworld-menu-button/restworld-menu-button.component.mjs +2 -2
- package/esm2022/lib/components/restworld-table/restworld-table.component.mjs +7 -10
- package/esm2022/lib/pipes/property-type-format.pipe.mjs +2 -2
- package/esm2022/lib/restworld-client.module.mjs +30 -1
- package/esm2022/public-api.mjs +2 -1
- package/fesm2022/wertzui-ngx-restworld-client.mjs +760 -313
- package/fesm2022/wertzui-ngx-restworld-client.mjs.map +1 -1
- package/lib/components/restworld-displays/restworld-displays.d.ts +192 -0
- package/lib/components/restworld-displays/restworld-displays.d.ts.map +1 -0
- package/lib/components/restworld-image/restworld-image.component.d.ts +1 -1
- package/lib/components/restworld-inputs/restworld-inputs.d.ts +2 -2
- package/lib/components/restworld-inputs/restworld-inputs.d.ts.map +1 -1
- package/lib/pipes/property-type-format.pipe.d.ts +1 -1
- package/lib/pipes/property-type-format.pipe.d.ts.map +1 -1
- package/lib/restworld-client.module.d.ts +49 -48
- package/lib/restworld-client.module.d.ts.map +1 -1
- package/package.json +2 -2
- package/public-api.d.ts +1 -0
- package/public-api.d.ts.map +1 -1
|
@@ -0,0 +1,434 @@
|
|
|
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 (value === undefined)
|
|
171
|
+
this._selectedValues = [];
|
|
172
|
+
else if (Array.isArray(value))
|
|
173
|
+
this._selectedValues = value;
|
|
174
|
+
else
|
|
175
|
+
this._selectedValues = [value];
|
|
176
|
+
}
|
|
177
|
+
get selectedValues() {
|
|
178
|
+
return this._selectedValues ?? this.property.options.selectedValues ?? [];
|
|
179
|
+
}
|
|
180
|
+
_inline = [];
|
|
181
|
+
/**
|
|
182
|
+
* A function that returns the label for the given item.
|
|
183
|
+
* The default returns the prompt and optionally the value in brackets.
|
|
184
|
+
* The value in brackets will only be displayed if the `cols` field of the property is undefined or greater than 1.
|
|
185
|
+
* Overwrite this function to change the label.
|
|
186
|
+
* @param item The item to get the label for.
|
|
187
|
+
*/
|
|
188
|
+
getLabel = this.getLabelInternal;
|
|
189
|
+
/**
|
|
190
|
+
* A function that returns the tooltip for the given item.
|
|
191
|
+
* 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.
|
|
192
|
+
* The default properties to exclude are: createdAt, createdBy, lastChangedAt, lastChangedBy, timestamp, promptField, valueField.
|
|
193
|
+
* Overwrite this function to change the tooltip.
|
|
194
|
+
* @param item The item to get the label for.
|
|
195
|
+
*/
|
|
196
|
+
getTooltip = this.getTooltipInternal;
|
|
197
|
+
inputOptionsRef;
|
|
198
|
+
get valueField() {
|
|
199
|
+
return this.property.options.valueField ?? "value";
|
|
200
|
+
}
|
|
201
|
+
get promptField() {
|
|
202
|
+
return this.property.options.promptField ?? "prompt";
|
|
203
|
+
}
|
|
204
|
+
constructor(_messageService, _clients) {
|
|
205
|
+
this._messageService = _messageService;
|
|
206
|
+
this._clients = _clients;
|
|
207
|
+
}
|
|
208
|
+
async ngOnInit() {
|
|
209
|
+
if (this.property.options?.inline && this.property.options.inline.length > 0)
|
|
210
|
+
this._inline = Array.from(this.property.options.inline);
|
|
211
|
+
await this.setInitialSelectedOptionsElementForProperty();
|
|
212
|
+
}
|
|
213
|
+
getOptionItem(value) {
|
|
214
|
+
return this._inline.find(o => this.getValue(o) === value) ?? this.createOptionsItem(value);
|
|
215
|
+
}
|
|
216
|
+
createOptionsItem(value) {
|
|
217
|
+
return { [this.valueField]: value, [this.promptField]: "" };
|
|
218
|
+
}
|
|
219
|
+
getValue(item) {
|
|
220
|
+
if (item === undefined || item === null || !item.hasOwnProperty(this.valueField))
|
|
221
|
+
throw new Error(`The item does not have a property ${this.valueField}.`);
|
|
222
|
+
return item[this.valueField];
|
|
223
|
+
}
|
|
224
|
+
getPrompt(item) {
|
|
225
|
+
if (item === undefined || item === null || !item.hasOwnProperty(this.promptField))
|
|
226
|
+
return "";
|
|
227
|
+
return item[this.promptField];
|
|
228
|
+
}
|
|
229
|
+
getLabelInternal(item) {
|
|
230
|
+
if (item === undefined || item === null)
|
|
231
|
+
return "";
|
|
232
|
+
const prompt = this.getPrompt(item);
|
|
233
|
+
const value = this.getValue(item);
|
|
234
|
+
let label = prompt;
|
|
235
|
+
if (label === undefined || label === null || label === "")
|
|
236
|
+
label = (value?.toString() ?? "");
|
|
237
|
+
else if ((this.property.cols === undefined || this.property.cols > 1) && prompt?.toLowerCase() !== value?.toString().toLowerCase())
|
|
238
|
+
label += ` (${value})`;
|
|
239
|
+
return label;
|
|
240
|
+
}
|
|
241
|
+
getTooltipInternal(item) {
|
|
242
|
+
if (item === undefined || item === null)
|
|
243
|
+
return "";
|
|
244
|
+
const tooltip = Object.entries(item)
|
|
245
|
+
.filter(([key]) => !(key.startsWith('_') || ['createdAt', 'createdBy', 'lastChangedAt', 'lastChangedBy', 'timestamp', this.promptField, this.valueField].includes(key)))
|
|
246
|
+
.reduce((prev, [key, value], index) => `${prev}${index === 0 ? '' : '\n'}${key}: ${RestWorldDisplayDropdownComponent.jsonStringifyWithElipsis(value)}`, '');
|
|
247
|
+
return tooltip;
|
|
248
|
+
}
|
|
249
|
+
async setInitialSelectedOptionsElementForProperty() {
|
|
250
|
+
const options = this.property.options;
|
|
251
|
+
if (!options.link?.href || !this.selectedValues || this.selectedValues.length === 0 || this.selectedValues.every(v => this._inline.some(i => this.getValue(i) === v) ?? false))
|
|
252
|
+
return;
|
|
253
|
+
const filter = `${options.valueField} in (${this.selectedValues})`;
|
|
254
|
+
await this.SetInlineOptionsFromFilter(filter);
|
|
255
|
+
}
|
|
256
|
+
async SetInlineOptionsFromFilter(filter) {
|
|
257
|
+
const options = this.property.options;
|
|
258
|
+
if (!options.link?.href)
|
|
259
|
+
throw new Error('The property does not have a link href.');
|
|
260
|
+
const templatedUri = options.link.href;
|
|
261
|
+
const response = await this.getClient().getListByUri(templatedUri, { $filter: filter, $top: 10 });
|
|
262
|
+
if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
|
|
263
|
+
const message = `An error occurred while getting the initial selected items for the property ${this.property.name}.`;
|
|
264
|
+
this._messageService.add({ severity: 'error', summary: 'Error', detail: message, data: response, sticky: true });
|
|
265
|
+
}
|
|
266
|
+
const items = response.body._embedded.items;
|
|
267
|
+
const newItems = this.combineInlineWithSelected(items);
|
|
268
|
+
this._inline = newItems;
|
|
269
|
+
}
|
|
270
|
+
combineInlineWithSelected(items) {
|
|
271
|
+
const oldInline = this._inline;
|
|
272
|
+
if (!oldInline || oldInline.length === 0)
|
|
273
|
+
return items;
|
|
274
|
+
const itemsToKeep = oldInline.filter(i => this.selectedValues.includes(this.getValue(i)));
|
|
275
|
+
const newItems = items.concat(itemsToKeep.filter(i => !items.includes(i)));
|
|
276
|
+
return newItems;
|
|
277
|
+
}
|
|
278
|
+
getClient() {
|
|
279
|
+
if (!this.apiName)
|
|
280
|
+
throw new Error('Cannot get a client, because the apiName is not set.');
|
|
281
|
+
return this._clients.getClient(this.apiName);
|
|
282
|
+
}
|
|
283
|
+
static jsonStringifyWithElipsis(value) {
|
|
284
|
+
const maxLength = 200;
|
|
285
|
+
const end = 10;
|
|
286
|
+
const start = maxLength - end - 2;
|
|
287
|
+
const json = JSON.stringify(value);
|
|
288
|
+
const shortened = json.length > maxLength ? json.substring(0, start) + '…' + json.substring(json.length - end) : json;
|
|
289
|
+
return shortened;
|
|
290
|
+
}
|
|
291
|
+
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 });
|
|
292
|
+
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"] }] });
|
|
293
|
+
}
|
|
294
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayDropdownComponent, decorators: [{
|
|
295
|
+
type: Component,
|
|
296
|
+
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> -->" }]
|
|
297
|
+
}], ctorParameters: () => [{ type: i3.MessageService }, { type: i4.RestWorldClientCollection }], propDecorators: { property: [{
|
|
298
|
+
type: Input,
|
|
299
|
+
args: [{ required: true }]
|
|
300
|
+
}], apiName: [{
|
|
301
|
+
type: Input,
|
|
302
|
+
args: [{ required: true }]
|
|
303
|
+
}], selectedValues: [{
|
|
304
|
+
type: Input
|
|
305
|
+
}], getLabel: [{
|
|
306
|
+
type: Input
|
|
307
|
+
}], getTooltip: [{
|
|
308
|
+
type: Input
|
|
309
|
+
}], inputOptionsRef: [{
|
|
310
|
+
type: ContentChild,
|
|
311
|
+
args: ['inputOptions', { static: false }]
|
|
312
|
+
}] } });
|
|
313
|
+
/**
|
|
314
|
+
* Displays the value of a complex object with multiple properties that is automatically created from the given property.
|
|
315
|
+
* The object can also be nested.
|
|
316
|
+
* @remarks It is advised to use RestWorldDisplayComponent <rw-display> and control the rendered elements with the passed in property
|
|
317
|
+
* instead of using this component directly.
|
|
318
|
+
*/
|
|
319
|
+
export class RestWorldDisplayObjectComponent {
|
|
320
|
+
property;
|
|
321
|
+
apiName;
|
|
322
|
+
_value;
|
|
323
|
+
/**
|
|
324
|
+
* The value to display. If not set, the value of the template properties will be used.
|
|
325
|
+
*/
|
|
326
|
+
set value(value) {
|
|
327
|
+
this._value = value;
|
|
328
|
+
}
|
|
329
|
+
get value() {
|
|
330
|
+
return this._value;
|
|
331
|
+
}
|
|
332
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayObjectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
333
|
+
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"] }] });
|
|
334
|
+
}
|
|
335
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayObjectComponent, decorators: [{
|
|
336
|
+
type: Component,
|
|
337
|
+
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"] }]
|
|
338
|
+
}], propDecorators: { property: [{
|
|
339
|
+
type: Input,
|
|
340
|
+
args: [{ required: true }]
|
|
341
|
+
}], apiName: [{
|
|
342
|
+
type: Input,
|
|
343
|
+
args: [{ required: true }]
|
|
344
|
+
}], value: [{
|
|
345
|
+
type: Input
|
|
346
|
+
}] } });
|
|
347
|
+
/**
|
|
348
|
+
* Displays the value of a simple element, like a string, a number or a Date that is automatically created from the given property.
|
|
349
|
+
* @remarks It is advised to use RestWorldDisplayComponent <rw-display> and control the rendered elements with the passed in property
|
|
350
|
+
* instead of using this component directly.
|
|
351
|
+
*/
|
|
352
|
+
export class RestWorldDisplaySimpleComponent {
|
|
353
|
+
property;
|
|
354
|
+
apiName;
|
|
355
|
+
_value;
|
|
356
|
+
/**
|
|
357
|
+
* The value to display. If not set, the value of the property will be used.
|
|
358
|
+
*/
|
|
359
|
+
set value(value) {
|
|
360
|
+
this._value = value;
|
|
361
|
+
}
|
|
362
|
+
get value() {
|
|
363
|
+
return this._value ?? this.property.value;
|
|
364
|
+
}
|
|
365
|
+
get PropertyType() {
|
|
366
|
+
return PropertyType;
|
|
367
|
+
}
|
|
368
|
+
static _dateFormat = new Date(3333, 10, 22) // months start at 0 in JS
|
|
369
|
+
.toLocaleDateString()
|
|
370
|
+
.replace("22", "dd")
|
|
371
|
+
.replace("11", "MM")
|
|
372
|
+
.replace("3333", "yyyy")
|
|
373
|
+
.replace("33", "yy");
|
|
374
|
+
get dateFormat() {
|
|
375
|
+
return RestWorldDisplaySimpleComponent._dateFormat;
|
|
376
|
+
}
|
|
377
|
+
static _timeFormat = new Date(1, 1, 1, 22, 33, 44)
|
|
378
|
+
.toLocaleTimeString()
|
|
379
|
+
.replace("22", "hh")
|
|
380
|
+
.replace("33", "mm")
|
|
381
|
+
.replace("44", "ss");
|
|
382
|
+
get timeFormat() {
|
|
383
|
+
return RestWorldDisplaySimpleComponent._timeFormat;
|
|
384
|
+
}
|
|
385
|
+
get PropertyWithImage() {
|
|
386
|
+
return PropertyWithImage;
|
|
387
|
+
}
|
|
388
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplaySimpleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
389
|
+
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" }] });
|
|
390
|
+
}
|
|
391
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplaySimpleComponent, decorators: [{
|
|
392
|
+
type: Component,
|
|
393
|
+
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" }]
|
|
394
|
+
}], propDecorators: { property: [{
|
|
395
|
+
type: Input,
|
|
396
|
+
args: [{ required: true }]
|
|
397
|
+
}], apiName: [{
|
|
398
|
+
type: Input,
|
|
399
|
+
args: [{ required: true }]
|
|
400
|
+
}], value: [{
|
|
401
|
+
type: Input
|
|
402
|
+
}] } });
|
|
403
|
+
/**
|
|
404
|
+
* Displays the values of a collection of rw-display-elements automatically created from a template.
|
|
405
|
+
*/
|
|
406
|
+
export class RestWorldDisplayTemplateComponent {
|
|
407
|
+
template;
|
|
408
|
+
apiName;
|
|
409
|
+
_value;
|
|
410
|
+
/**
|
|
411
|
+
* The value to display. If not set, the values of the template properties will be used.
|
|
412
|
+
*/
|
|
413
|
+
set value(value) {
|
|
414
|
+
this._value = value;
|
|
415
|
+
}
|
|
416
|
+
get value() {
|
|
417
|
+
return this._value;
|
|
418
|
+
}
|
|
419
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayTemplateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
420
|
+
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"] }] });
|
|
421
|
+
}
|
|
422
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: RestWorldDisplayTemplateComponent, decorators: [{
|
|
423
|
+
type: Component,
|
|
424
|
+
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>" }]
|
|
425
|
+
}], propDecorators: { template: [{
|
|
426
|
+
type: Input,
|
|
427
|
+
args: [{ required: true }]
|
|
428
|
+
}], apiName: [{
|
|
429
|
+
type: Input,
|
|
430
|
+
args: [{ required: true }]
|
|
431
|
+
}], value: [{
|
|
432
|
+
type: Input
|
|
433
|
+
}] } });
|
|
434
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdHdvcmxkLWRpc3BsYXlzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXJlc3R3b3JsZC1jbGllbnQvc3JjL2xpYi9jb21wb25lbnRzL3Jlc3R3b3JsZC1kaXNwbGF5cy9yZXN0d29ybGQtZGlzcGxheXMudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LWVsZW1lbnQvcmVzdHdvcmxkLWRpc3BsYXktZWxlbWVudC5jb21wb25lbnQuaHRtbCIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1yZXN0d29ybGQtY2xpZW50L3NyYy9saWIvY29tcG9uZW50cy9yZXN0d29ybGQtZGlzcGxheXMvcmVzdHdvcmxkLWRpc3BsYXkvcmVzdHdvcmxkLWRpc3BsYXkuY29tcG9uZW50Lmh0bWwiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LWNvbGxlY3Rpb24vcmVzdHdvcmxkLWRpc3BsYXktY29sbGVjdGlvbi5jb21wb25lbnQuaHRtbCIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1yZXN0d29ybGQtY2xpZW50L3NyYy9saWIvY29tcG9uZW50cy9yZXN0d29ybGQtZGlzcGxheXMvcmVzdHdvcmxkLWRpc3BsYXktZHJvcGRvd24vcmVzdHdvcmxkLWRpc3BsYXktZHJvcGRvd24uY29tcG9uZW50Lmh0bWwiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LW9iamVjdC9yZXN0d29ybGQtZGlzcGxheS1vYmplY3QuY29tcG9uZW50Lmh0bWwiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LXNpbXBsZS9yZXN0d29ybGQtZGlzcGxheS1zaW1wbGUuY29tcG9uZW50Lmh0bWwiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL2NvbXBvbmVudHMvcmVzdHdvcmxkLWRpc3BsYXlzL3Jlc3R3b3JsZC1kaXNwbGF5LXRlbXBsYXRlL3Jlc3R3b3JsZC1kaXNwbGF5LXRlbXBsYXRlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBdUIsTUFBTSxlQUFlLENBQUM7QUFDcEYsT0FBTyxFQUF5QixZQUFZLEVBQVksY0FBYyxFQUFrSCxjQUFjLEVBQWlCLE1BQU0seUJBQXlCLENBQUM7QUFDdlAsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGlCQUFpQixFQUFFLE1BQU0saUNBQWlDLENBQUE7Ozs7Ozs7Ozs7OztBQU14Rjs7OztHQUlHO0FBTUgsTUFBTSxPQUFPLGdDQUFnQztJQUV6QyxRQUFRLENBQWE7SUFHckIsT0FBTyxDQUFVO0lBRVQsTUFBTSxDQUFvTjtJQUNsTzs7TUFFRTtJQUNGLElBQ1csS0FBSyxDQUFDLEtBQXVOO1FBQ3BPLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLENBQUM7SUFDRCxJQUFXLEtBQUs7UUFDWixPQUFPLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFvQyxDQUFDO0lBQzdFLENBQUM7SUFFRCxJQUFXLFlBQVk7UUFDbkIsT0FBTyxZQUFZLENBQUM7SUFDeEIsQ0FBQzt1R0FyQlEsZ0NBQWdDOzJGQUFoQyxn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QW1COzhCQU03QixRQUFRO3NCQURQLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQUl6QixPQUFPO3NCQUROLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQVFkLEtBQUs7c0JBRGYsS0FBSzs7QUFzQ1Y7O0dBRUc7QUFNSCxNQUFNLE9BQU8saUNBQWlDO0lBRTFDLFFBQVEsQ0FBWTtJQUdwQixPQUFPLENBQVU7SUFFVCxNQUFNLENBQXVCO0lBQ3JDOztNQUVFO0lBQ0YsSUFDVyxLQUFLLENBQUMsS0FBc0M7UUFDbkQsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7SUFDeEIsQ0FBQztJQUNELElBQVcsS0FBSztRQUNaLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUN2QixDQUFDO3VHQWpCUSxpQ0FBaUM7MkZBQWpDLGlDQUFpQyxpSU9qYjlDLDZMQUFtTCx1TFBrQnRLLGdDQUFnQzs7MkZBK1poQyxpQ0FBaUM7a0JBTDdDLFNBQVM7K0JBQ0kscUJBQXFCOzhCQU0vQixRQUFRO3NCQURQLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQUl6QixPQUFPO3NCQUROLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQVFkLEtBQUs7c0JBRGYsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgQ29udGVudENoaWxkLCBJbnB1dCwgT25Jbml0LCBUZW1wbGF0ZVJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBQcm9wZXJ0eSwgU2ltcGxlVmFsdWUsIFByb3BlcnR5VHlwZSwgVGVtcGxhdGUsIE51bWJlclRlbXBsYXRlLCBUZW1wbGF0ZUR0bywgT3B0aW9ucywgRXh0cmFjdEdlbmVyaWNPcHRpb25zSXRlbVR5cGUsIEV4dHJhY3RWYWx1ZVR5cGUsIEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZSwgUHJvYmxlbURldGFpbHMsIFJlc291cmNlT2ZEdG8gfSBmcm9tICdAd2VydHp1aS9uZ3gtaGFsLWNsaWVudCc7XHJcbmltcG9ydCB7IFByb3BlcnR5V2l0aE9wdGlvbnMsIFByb3BlcnR5V2l0aEltYWdlIH0gZnJvbSAnLi4vLi4vbW9kZWxzL3NwZWNpYWwtcHJvcGVydGllcydcclxuaW1wb3J0IHsgUHJvcGVydHlUZW1wbGF0ZUNvbnRleHQgfSBmcm9tICcuLi8uLi9tb2RlbHMvdGVtcGxhdGluZyc7XHJcbmltcG9ydCB7IE1lc3NhZ2VTZXJ2aWNlIH0gZnJvbSAncHJpbWVuZy9hcGknO1xyXG5pbXBvcnQgeyBSZXN0V29ybGRDbGllbnRDb2xsZWN0aW9uIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVzdHdvcmxkLWNsaWVudC1jb2xsZWN0aW9uJztcclxuaW1wb3J0IHsgUmVzdFdvcmxkQ2xpZW50IH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVzdHdvcmxkLWNsaWVudCc7XHJcblxyXG4vKipcclxuICogRGlzcGxheSB0aGUgdmFsdWUgb2YgYSBmb3JtIGVsZW1lbnQgd2l0aCBhIGxhYmVsIHRoYXQgaXMgYXV0b21hdGljYWxseSBjcmVhdGVkIGZyb20gYSBwcm9wZXJ0eSBpbiBhIGZvcm0gdGVtcGxhdGUuXHJcbiAqIFRoaXMgbWF5IGFsc28gYmUgYSBjb21wbGV4IG9iamVjdCBvciBhIGNvbGxlY3Rpb24gaW4gd2hpY2ggY2FzZSBtdWx0aXBsZSBhbmQgbmVzdGVkIGRpc3BsYXkgZWxlbWVudHMgbWF5IGJlIHJlbmRlcmVkLlxyXG4gKiBJZiB5b3Ugd2FudCB0byBkaXNwbGF5IGp1c3QgdGhlIHZhbHVlIHdpdGhvdXQgYSBsYWJlbCwgdXNlIFJlc3RXb3JsZERpc3BsYXlDb21wb25lbnQgPHJ3LWRpc3BsYXk+LlxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3J3LWRpc3BsYXktZWxlbWVudCcsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktZWxlbWVudC9yZXN0d29ybGQtZGlzcGxheS1lbGVtZW50LmNvbXBvbmVudC5odG1sJyxcclxuICAgIHN0eWxlVXJsOiAnLi9yZXN0d29ybGQtZGlzcGxheS1lbGVtZW50L3Jlc3R3b3JsZC1kaXNwbGF5LWVsZW1lbnQuY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlFbGVtZW50Q29tcG9uZW50PFRQcm9wZXJ0eSBleHRlbmRzIFByb3BlcnR5PFNpbXBsZVZhbHVlLCBzdHJpbmcsIHN0cmluZz4+IHtcclxuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXHJcbiAgICBwcm9wZXJ0eSE6IFRQcm9wZXJ0eTtcclxuXHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgYXBpTmFtZSE6IHN0cmluZztcclxuXHJcbiAgICBwcml2YXRlIF92YWx1ZT86IEV4dHJhY3RWYWx1ZVR5cGU8VFByb3BlcnR5PiB8IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+W10gfCBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PiB8IFJlY29yZDxzdHJpbmcsIFNpbXBsZVZhbHVlPiB8IE1hcDxudW1iZXIsIFJlY29yZDxzdHJpbmcsIFNpbXBsZVZhbHVlPj47XHJcbiAgICAvKipcclxuICAgICAqIFRoZSB2YWx1ZSB0byBkaXNwbGF5LiBJZiBub3Qgc2V0LCB0aGUgdmFsdWUgb2YgdGhlIHByb3BlcnR5IHdpbGwgYmUgdXNlZC5cclxuICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIHNldCB2YWx1ZSh2YWx1ZTogRXh0cmFjdFZhbHVlVHlwZTxUUHJvcGVydHk+IHwgRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT5bXSB8IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+IHwgUmVjb3JkPHN0cmluZywgU2ltcGxlVmFsdWU+IHwgTWFwPG51bWJlciwgUmVjb3JkPHN0cmluZywgU2ltcGxlVmFsdWU+Pikge1xyXG4gICAgICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XHJcbiAgICB9XHJcbiAgICBwdWJsaWMgZ2V0IHZhbHVlKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZSA/PyB0aGlzLnByb3BlcnR5LnZhbHVlIGFzIEV4dHJhY3RWYWx1ZVR5cGU8VFByb3BlcnR5PjtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IFByb3BlcnR5VHlwZSgpIHtcclxuICAgICAgICByZXR1cm4gUHJvcGVydHlUeXBlO1xyXG4gICAgfVxyXG59XHJcbi8qKlxyXG4gKiBEaXNwbGF5cyBhIHZhbHVlIHRoYXQgaXMgYXV0b21hdGljYWxseSBjcmVhdGVkIGZyb20gYSBwcm9wZXJ0eSBpbiBhIGZvcm0gdGVtcGxhdGUuXHJcbiAqIFRoaXMgbWF5IGFsc28gYmUgYSBjb21wbGV4IG9iamVjdCBvciBhIGNvbGxlY3Rpb24gaW4gd2hpY2ggY2FzZSBtdWx0aXBsZSBhbmQgbmVzdGVkIGlucHV0IGVsZW1lbnRzIG1heSBiZSByZW5kZXJlZC5cclxuICogSWYgeW91IGFsc28gd2FudCBhIGxhYmVsLCB1c2UgUmVzdFdvcmxkRGlzcGxheUVsZW1lbnRDb21wb25lbnQgPHJ3LWRpc3BsYXktZWxlbWVudD4uXHJcbiAqIFlvdSBjYW4gYWxzbyB1c2Ugb25lIG9mIHRoZSBkaWZmZXJlbnQgUmVzdFdvcmxkRGlzcGxheS4uLiA8cnctZGlzcGxheS0uLi4+IGVsZW1lbnRzIHRvIHJlbmRlciBhIHNwZWNpZmljICBwcm9wZXJ0eSB0eXBlLFxyXG4gKiBidXQgaXQgaXMgYWR2aXNlZCB0byBjb250cm9sIHRoZSByZW5kZXJlZCBlbGVtZW50IHRocm91Z2ggdGhlIHBhc3NlZCBpbiBwcm9wZXJ0eS5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdydy1kaXNwbGF5JyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9yZXN0d29ybGQtZGlzcGxheS9yZXN0d29ybGQtZGlzcGxheS5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXkvcmVzdHdvcmxkLWRpc3BsYXkuY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlDb21wb25lbnQ8VFByb3BlcnR5IGV4dGVuZHMgUHJvcGVydHk8U2ltcGxlVmFsdWUsIHN0cmluZywgc3RyaW5nPj4ge1xyXG4gICAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcclxuICAgIHByb3BlcnR5ITogVFByb3BlcnR5O1xyXG5cclxuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXHJcbiAgICBhcGlOYW1lITogc3RyaW5nO1xyXG5cclxuICAgIHByaXZhdGUgX3ZhbHVlPzogRXh0cmFjdFZhbHVlVHlwZTxUUHJvcGVydHk+IHwgRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT5bXSB8IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+IHwgUmVjb3JkPHN0cmluZywgU2ltcGxlVmFsdWU+IHwgTWFwPG51bWJlciwgUmVjb3JkPHN0cmluZywgU2ltcGxlVmFsdWU+PjtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIHZhbHVlIHRvIGRpc3BsYXkuIElmIG5vdCBzZXQsIHRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgd2lsbCBiZSB1c2VkLlxyXG4gICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IHZhbHVlKHZhbHVlOiBFeHRyYWN0VmFsdWVUeXBlPFRQcm9wZXJ0eT4gfCBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PltdIHwgRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT4gfCBSZWNvcmQ8c3RyaW5nLCBTaW1wbGVWYWx1ZT4gfCBNYXA8bnVtYmVyLCBSZWNvcmQ8c3RyaW5nLCBTaW1wbGVWYWx1ZT4+IHwgdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgdGhpcy5fdmFsdWUgPSB2YWx1ZTtcclxuICAgIH1cclxuICAgIHB1YmxpYyBnZXQgdmFsdWUoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlID8/IHRoaXMucHJvcGVydHkudmFsdWUgYXMgRXh0cmFjdFZhbHVlVHlwZTxUUHJvcGVydHk+O1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgUHJvcGVydHlUeXBlKCkge1xyXG4gICAgICAgIHJldHVybiBQcm9wZXJ0eVR5cGU7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldCBQcm9wZXJ0eVdpdGhPcHRpb25zKCkge1xyXG4gICAgICAgIHJldHVybiBQcm9wZXJ0eVdpdGhPcHRpb25zPFNpbXBsZVZhbHVlLCBzdHJpbmcsIHN0cmluZz47XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEaXNwbGF5cyB0aGUgdmFsdWUgb2YgYSBjb2xsZWN0aW9uIHRoYXQgaXMgYXV0b21hdGljYWxseSBjcmVhdGVkIGZyb20gdGhlIGdpdmVuIHByb3BlcnR5LlxyXG4gKiBUaGUgZWxlbWVudHMgYW5kIGNhbiBhbHNvIGJlIG5lc3RlZC5cclxuICogQHJlbWFya3MgSXQgaXMgYWR2aXNlZCB0byB1c2UgUmVzdFdvcmxkRGlzcGxheUNvbXBvbmVudCA8cnctZGlzcGxheT4gYW5kIGNvbnRyb2wgdGhlIHJlbmRlcmVkIGVsZW1lbnRzIHdpdGggdGhlIHBhc3NlZCBpbiBwcm9wZXJ0eVxyXG4gKiBpbnN0ZWFkIG9mIHVzaW5nIHRoaXMgY29tcG9uZW50IGRpcmVjdGx5LlxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3J3LWRpc3BsYXktY29sbGVjdGlvbicsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktY29sbGVjdGlvbi9yZXN0d29ybGQtZGlzcGxheS1jb2xsZWN0aW9uLmNvbXBvbmVudC5odG1sJyxcclxuICAgIHN0eWxlVXJsOiAnLi9yZXN0d29ybGQtZGlzcGxheS1jb2xsZWN0aW9uL3Jlc3R3b3JsZC1kaXNwbGF5LWNvbGxlY3Rpb24uY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlDb2xsZWN0aW9uQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXHJcbiAgICBwcm9wZXJ0eSE6IFByb3BlcnR5ICYgeyBfdGVtcGxhdGVzOiB7IGRlZmF1bHQ6IFRlbXBsYXRlIH0gfTtcclxuXHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgYXBpTmFtZSE6IHN0cmluZztcclxuXHJcbiAgICBwcml2YXRlIF92YWx1ZXM/OiBhbnlbXTtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIHZhbHVlIHRvIGRpc3BsYXkuIElmIG5vdCBzZXQsIHRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgd2lsbCBiZSB1c2VkLlxyXG4gICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IHZhbHVlcyh2YWx1ZXM6IGFueVtdIHwgUGFydGlhbDxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB8IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHRoaXMuX3ZhbHVlcyA9IFJlc3RXb3JsZERpc3BsYXlDb2xsZWN0aW9uQ29tcG9uZW50LnRvQXJyYXkodmFsdWVzKTtcclxuICAgIH1cclxuICAgIHB1YmxpYyBnZXQgdmFsdWVzKCk6IGFueVtdIHwgdW5kZWZpbmVkIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3RlbXBsYXRlczogTnVtYmVyVGVtcGxhdGVbXSA9IFtdO1xyXG4gICAgcHVibGljIGdldCB0ZW1wbGF0ZXMoKTogTnVtYmVyVGVtcGxhdGVbXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RlbXBsYXRlcztcclxuICAgIH1cclxuXHJcbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLl90ZW1wbGF0ZXMgPSB0aGlzLl92YWx1ZXMgP1xyXG4gICAgICAgICAgICBBcnJheS5mcm9tKFJlc3RXb3JsZERpc3BsYXlDb2xsZWN0aW9uQ29tcG9uZW50Lm1hcCh0aGlzLl92YWx1ZXMuZW50cmllcygpLCBlbnRyeSA9PiAobmV3IE51bWJlclRlbXBsYXRlKHsgLi4uKHRoaXMucHJvcGVydHkuX3RlbXBsYXRlcy5kZWZhdWx0IGFzIFRlbXBsYXRlRHRvKSwgdGl0bGU6IGVudHJ5WzBdLnRvU3RyaW5nKCkgfSkpKSkgOlxyXG4gICAgICAgICAgICBSZXN0V29ybGREaXNwbGF5Q29sbGVjdGlvbkNvbXBvbmVudC5nZXRDb2xsZWN0aW9uRW50cnlUZW1wbGF0ZXModGhpcy5wcm9wZXJ0eSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgKiBtYXA8VDEsIFQyPihpdGVyYWJsZTogSXRlcmFibGVJdGVyYXRvcjxUMT4sIGNhbGxiYWNrOiAodmFsdWU6IFQxKSA9PiBUMikge1xyXG4gICAgICAgIGZvciAobGV0IHggb2YgaXRlcmFibGUpIHtcclxuICAgICAgICAgICAgeWllbGQgY2FsbGJhY2soeCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIHRvQXJyYXkoYXJyYXlPckRpY3Rpb25hcnk6IGFueVtdIHwgUGFydGlhbDxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB8IHVuZGVmaW5lZCk6IGFueVtdIHwgdW5kZWZpbmVkIHtcclxuICAgICAgICBpZiAoIWFycmF5T3JEaWN0aW9uYXJ5KVxyXG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG5cclxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhcnJheU9yRGljdGlvbmFyeSkpXHJcbiAgICAgICAgICAgIHJldHVybiBhcnJheU9yRGljdGlvbmFyeTtcclxuXHJcbiAgICAgICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKGFycmF5T3JEaWN0aW9uYXJ5KS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gKHsga2V5LCB2YWx1ZSB9KSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0Q29sbGVjdGlvbkVudHJ5VGVtcGxhdGVzKHByb3BlcnR5PzogUHJvcGVydHkpOiBOdW1iZXJUZW1wbGF0ZVtdIHtcclxuICAgICAgICBpZiAoIXByb3BlcnR5KVxyXG4gICAgICAgICAgICByZXR1cm4gW107XHJcblxyXG4gICAgICAgIHJldHVybiBPYmplY3QuZW50cmllcyhwcm9wZXJ0eS5fdGVtcGxhdGVzKVxyXG4gICAgICAgICAgICAuZmlsdGVyKChba2V5LCB2YWx1ZV0pID0+IE51bWJlci5pc0ludGVnZXIoTnVtYmVyLnBhcnNlSW50KGtleSkpICYmIE51bWJlci5pc0ludGVnZXIoTnVtYmVyLnBhcnNlSW50KHZhbHVlPy50aXRsZSA/PyBcIlwiKSkpXHJcbiAgICAgICAgICAgIC5tYXAoKFssIHZhbHVlXSkgPT4gbmV3IE51bWJlclRlbXBsYXRlKHZhbHVlIGFzIFRlbXBsYXRlRHRvKSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEaXNwbGF5cyB0aGUgdmFsdWUgb2YgYSBkcm9wZG93biB0aGF0IGlzIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBmcm9tIHRoZSBnaXZlbiBwcm9wZXJ0eS5cclxuICogSWYgc2V0IHRoZSBkcm9wZG93biB3aWxsIHVzZSB0aGUgYGlubGluZWAgcHJvcGVydHkgb2YgdGhlIG9wdGlvbnMgdG8gcmVuZGVyIHRoZSBgc2VsZWN0ZWRWYWx1ZXNgIE90aGVyd2lzZSBpdCB3aWxsIGp1c3QgcmVuZGVyIHRoZSB2YWx1ZXMsIGJ1dCBubyBwcm9tcHQgZm9yIHRoZW0uXHJcbiAqIEByZW1hcmtzIEl0IGlzIGFkdmlzZWQgdG8gdXNlIFJlc3RXb3JsZERpc3BsYXlDb21wb25lbnQgPHJ3LWRpc3BsYXk+IGFuZCBjb250cm9sIHRoZSByZW5kZXJlZCBlbGVtZW50cyB3aXRoIHRoZSBwYXNzZWQgaW4gcHJvcGVydHlcclxuICogaW5zdGVhZCBvZiB1c2luZyB0aGlzIGNvbXBvbmVudCBkaXJlY3RseS5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdydy1kaXNwbGF5LWRyb3Bkb3duJyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9yZXN0d29ybGQtZGlzcGxheS1kcm9wZG93bi9yZXN0d29ybGQtZGlzcGxheS1kcm9wZG93bi5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktZHJvcGRvd24vcmVzdHdvcmxkLWRpc3BsYXktZHJvcGRvd24uY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlEcm9wZG93bkNvbXBvbmVudDxUUHJvcGVydHkgZXh0ZW5kcyBQcm9wZXJ0eTxTaW1wbGVWYWx1ZSwgc3RyaW5nLCBzdHJpbmc+ICYgeyBvcHRpb25zOiBPcHRpb25zPFNpbXBsZVZhbHVlLCBzdHJpbmcsIHN0cmluZz4gfSwgVE9wdGlvbnNJdGVtIGV4dGVuZHMgRXh0cmFjdEdlbmVyaWNPcHRpb25zSXRlbVR5cGU8VFByb3BlcnR5PiA9IEV4dHJhY3RHZW5lcmljT3B0aW9uc0l0ZW1UeXBlPFRQcm9wZXJ0eT4+IGltcGxlbWVudHMgT25Jbml0IHtcclxuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXHJcbiAgICBwcm9wZXJ0eSE6IFRQcm9wZXJ0eTtcclxuXHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgYXBpTmFtZSE6IHN0cmluZztcclxuXHJcbiAgICBwcml2YXRlIF9zZWxlY3RlZFZhbHVlczogRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT5bXSA9IFtdO1xyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgdmFsdWVzIHRvIGRpc3BsYXkuIElmIG5vdCBzZXQsIHRoZSB2YWx1ZXMgb2YgdGhlIHByb3BlcnR5IG9wdGlvbnMgd2lsbCBiZSB1c2VkLlxyXG4gICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IHNlbGVjdGVkVmFsdWVzKHZhbHVlOiBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PltdIHwgRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT4gfCB1bmRlZmluZWQpIHtcclxuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZClcclxuICAgICAgICAgICAgdGhpcy5fc2VsZWN0ZWRWYWx1ZXMgPSBbXTtcclxuICAgICAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSlcclxuICAgICAgICAgICAgdGhpcy5fc2VsZWN0ZWRWYWx1ZXMgPSB2YWx1ZSBhcyBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PltdO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgdGhpcy5fc2VsZWN0ZWRWYWx1ZXMgPSBbdmFsdWVdO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgc2VsZWN0ZWRWYWx1ZXMoKTogRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT5bXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlbGVjdGVkVmFsdWVzID8/ICh0aGlzLnByb3BlcnR5Lm9wdGlvbnMuc2VsZWN0ZWRWYWx1ZXMgYXMgdW5rbm93biBhcyBFeHRyYWN0R2VuZXJpY09wdGlvbnNTZWxlY3RlZFZhbHVlc1R5cGU8VFByb3BlcnR5PltdIHwgdW5kZWZpbmVkKSA/PyBbXTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9pbmxpbmU6IFRPcHRpb25zSXRlbVtdID0gW107XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgbGFiZWwgZm9yIHRoZSBnaXZlbiBpdGVtLlxyXG4gICAgICogVGhlIGRlZmF1bHQgcmV0dXJucyB0aGUgcHJvbXB0IGFuZCBvcHRpb25hbGx5IHRoZSB2YWx1ZSBpbiBicmFja2V0cy5cclxuICAgICAqIFRoZSB2YWx1ZSBpbiBicmFja2V0cyB3aWxsIG9ubHkgYmUgZGlzcGxheWVkIGlmIHRoZSBgY29sc2AgZmllbGQgb2YgdGhlIHByb3BlcnR5IGlzIHVuZGVmaW5lZCBvciBncmVhdGVyIHRoYW4gMS5cclxuICAgICAqIE92ZXJ3cml0ZSB0aGlzIGZ1bmN0aW9uIHRvIGNoYW5nZSB0aGUgbGFiZWwuXHJcbiAgICAgKiBAcGFyYW0gaXRlbSBUaGUgaXRlbSB0byBnZXQgdGhlIGxhYmVsIGZvci5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIGdldExhYmVsOiAoaXRlbTogVE9wdGlvbnNJdGVtKSA9PiBzdHJpbmcgPSB0aGlzLmdldExhYmVsSW50ZXJuYWw7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgdG9vbHRpcCBmb3IgdGhlIGdpdmVuIGl0ZW0uXHJcbiAgICAgKiBUaGUgZGVmYXVsdCByZXR1cm5zIGFsbCBwcm9wZXJ0aWVzIG9mIHRoZSBpdGVtIGV4Y2VwdCB0aGUgb25lcyB0aGF0IHN0YXJ0IHdpdGggYW4gdW5kZXJzY29yZSBvciB0aGUgb25lcyB0aGF0IGFyZSBpbiB0aGUgbGlzdCBvZiBkZWZhdWx0IHByb3BlcnRpZXMgdG8gZXhjbHVkZS5cclxuICAgICAqIFRoZSBkZWZhdWx0IHByb3BlcnRpZXMgdG8gZXhjbHVkZSBhcmU6IGNyZWF0ZWRBdCwgY3JlYXRlZEJ5LCBsYXN0Q2hhbmdlZEF0LCBsYXN0Q2hhbmdlZEJ5LCB0aW1lc3RhbXAsIHByb21wdEZpZWxkLCB2YWx1ZUZpZWxkLlxyXG4gICAgICogT3ZlcndyaXRlIHRoaXMgZnVuY3Rpb24gdG8gY2hhbmdlIHRoZSB0b29sdGlwLlxyXG4gICAgICogQHBhcmFtIGl0ZW0gVGhlIGl0ZW0gdG8gZ2V0IHRoZSBsYWJlbCBmb3IuXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBnZXRUb29sdGlwOiAoaXRlbTogVE9wdGlvbnNJdGVtKSA9PiBzdHJpbmcgPSB0aGlzLmdldFRvb2x0aXBJbnRlcm5hbDtcclxuXHJcbiAgICBAQ29udGVudENoaWxkKCdpbnB1dE9wdGlvbnMnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICAgIGlucHV0T3B0aW9uc1JlZj86IFRlbXBsYXRlUmVmPFByb3BlcnR5VGVtcGxhdGVDb250ZXh0PjtcclxuXHJcbiAgICBwdWJsaWMgZ2V0IHZhbHVlRmllbGQoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5wcm9wZXJ0eS5vcHRpb25zLnZhbHVlRmllbGQgPz8gXCJ2YWx1ZVwiO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgcHJvbXB0RmllbGQoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5wcm9wZXJ0eS5vcHRpb25zLnByb21wdEZpZWxkID8/IFwicHJvbXB0XCI7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBfbWVzc2FnZVNlcnZpY2U6IE1lc3NhZ2VTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgX2NsaWVudHM6IFJlc3RXb3JsZENsaWVudENvbGxlY3Rpb24sXHJcbiAgICApIHtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBuZ09uSW5pdCgpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAodGhpcy5wcm9wZXJ0eS5vcHRpb25zPy5pbmxpbmUgJiYgdGhpcy5wcm9wZXJ0eS5vcHRpb25zLmlubGluZS5sZW5ndGggPiAwKVxyXG4gICAgICAgICAgICB0aGlzLl9pbmxpbmUgPSBBcnJheS5mcm9tKHRoaXMucHJvcGVydHkub3B0aW9ucy5pbmxpbmUpIGFzIFRPcHRpb25zSXRlbVtdO1xyXG5cclxuICAgICAgICBhd2FpdCB0aGlzLnNldEluaXRpYWxTZWxlY3RlZE9wdGlvbnNFbGVtZW50Rm9yUHJvcGVydHkoKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0T3B0aW9uSXRlbSh2YWx1ZTogRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT4pOiBUT3B0aW9uc0l0ZW0ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9pbmxpbmUuZmluZChvID0+IHRoaXMuZ2V0VmFsdWUobyBhcyBUT3B0aW9uc0l0ZW0pID09PSB2YWx1ZSkgYXMgVE9wdGlvbnNJdGVtID8/IHRoaXMuY3JlYXRlT3B0aW9uc0l0ZW0odmFsdWUpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY3JlYXRlT3B0aW9uc0l0ZW0odmFsdWU6IEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+KTogVE9wdGlvbnNJdGVtIHtcclxuICAgICAgICByZXR1cm4geyBbdGhpcy52YWx1ZUZpZWxkXTogdmFsdWUsIFt0aGlzLnByb21wdEZpZWxkXTogXCJcIiB9IGFzIFRPcHRpb25zSXRlbTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0VmFsdWUoaXRlbTogVE9wdGlvbnNJdGVtKTogRXh0cmFjdEdlbmVyaWNPcHRpb25zU2VsZWN0ZWRWYWx1ZXNUeXBlPFRQcm9wZXJ0eT4ge1xyXG4gICAgICAgIGlmIChpdGVtID09PSB1bmRlZmluZWQgfHwgaXRlbSA9PT0gbnVsbCB8fCAhaXRlbS5oYXNPd25Qcm9wZXJ0eSh0aGlzLnZhbHVlRmllbGQpKVxyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBpdGVtIGRvZXMgbm90IGhhdmUgYSBwcm9wZXJ0eSAke3RoaXMudmFsdWVGaWVsZH0uYCk7XHJcblxyXG4gICAgICAgIHJldHVybiBpdGVtW3RoaXMudmFsdWVGaWVsZCBhcyBrZXlvZiBUT3B0aW9uc0l0ZW1dIGFzIEV4dHJhY3RHZW5lcmljT3B0aW9uc1NlbGVjdGVkVmFsdWVzVHlwZTxUUHJvcGVydHk+O1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRQcm9tcHQoaXRlbTogVE9wdGlvbnNJdGVtKTogc3RyaW5nIHtcclxuICAgICAgICBpZiAoaXRlbSA9PT0gdW5kZWZpbmVkIHx8IGl0ZW0gPT09IG51bGwgfHwgIWl0ZW0uaGFzT3duUHJvcGVydHkodGhpcy5wcm9tcHRGaWVsZCkpXHJcbiAgICAgICAgICAgIHJldHVybiBcIlwiO1xyXG5cclxuICAgICAgICByZXR1cm4gaXRlbVt0aGlzLnByb21wdEZpZWxkIGFzIGtleW9mIFRPcHRpb25zSXRlbV0gYXMgc3RyaW5nO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRMYWJlbEludGVybmFsKGl0ZW06IFRPcHRpb25zSXRlbSk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKGl0ZW0gPT09IHVuZGVmaW5lZCB8fCBpdGVtID09PSBudWxsKVxyXG4gICAgICAgICAgICByZXR1cm4gXCJcIjtcclxuXHJcbiAgICAgICAgY29uc3QgcHJvbXB0ID0gdGhpcy5nZXRQcm9tcHQoaXRlbSk7XHJcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLmdldFZhbHVlKGl0ZW0pO1xyXG5cclxuICAgICAgICBsZXQgbGFiZWwgPSBwcm9tcHQ7XHJcbiAgICAgICAgaWYgKGxhYmVsID09PSB1bmRlZmluZWQgfHwgbGFiZWwgPT09IG51bGwgfHwgbGFiZWwgPT09IFwiXCIpXHJcbiAgICAgICAgICAgIGxhYmVsID0gKHZhbHVlPy50b1N0cmluZygpID8/IFwiXCIpO1xyXG4gICAgICAgIGVsc2UgaWYgKCh0aGlzLnByb3BlcnR5LmNvbHMgPT09IHVuZGVmaW5lZCB8fCB0aGlzLnByb3BlcnR5LmNvbHMgPiAxKSAmJiBwcm9tcHQ/LnRvTG93ZXJDYXNlKCkgIT09IHZhbHVlPy50b1N0cmluZygpLnRvTG93ZXJDYXNlKCkpXHJcbiAgICAgICAgICAgIGxhYmVsICs9IGAgKCR7dmFsdWV9KWA7XHJcblxyXG4gICAgICAgIHJldHVybiBsYWJlbDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGdldFRvb2x0aXBJbnRlcm5hbChpdGVtOiBUT3B0aW9uc0l0ZW0pOiBzdHJpbmcge1xyXG4gICAgICAgIGlmIChpdGVtID09PSB1bmRlZmluZWQgfHwgaXRlbSA9PT0gbnVsbClcclxuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XHJcblxyXG4gICAgICAgIGNvbnN0IHRvb2x0aXAgPSBPYmplY3QuZW50cmllcyhpdGVtKVxyXG4gICAgICAgICAgICAuZmlsdGVyKChba2V5XSkgPT4gIShrZXkuc3RhcnRzV2l0aCgnXycpIHx8IFsnY3JlYXRlZEF0JywgJ2NyZWF0ZWRCeScsICdsYXN0Q2hhbmdlZEF0JywgJ2xhc3RDaGFuZ2VkQnknLCAndGltZXN0YW1wJywgdGhpcy5wcm9tcHRGaWVsZCwgdGhpcy52YWx1ZUZpZWxkXS5pbmNsdWRlcyhrZXkpKSlcclxuICAgICAgICAgICAgLnJlZHVjZSgocHJldiwgW2tleSwgdmFsdWVdLCBpbmRleCkgPT4gYCR7cHJldn0ke2luZGV4ID09PSAwID8gJycgOiAnXFxuJ30ke2tleX06ICR7UmVzdFdvcmxkRGlzcGxheURyb3Bkb3duQ29tcG9uZW50Lmpzb25TdHJpbmdpZnlXaXRoRWxpcHNpcyh2YWx1ZSl9YCwgJycpO1xyXG5cclxuICAgICAgICByZXR1cm4gdG9vbHRpcDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGFzeW5jIHNldEluaXRpYWxTZWxlY3RlZE9wdGlvbnNFbGVtZW50Rm9yUHJvcGVydHkoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMucHJvcGVydHkub3B0aW9ucztcclxuXHJcbiAgICAgICAgaWYgKCFvcHRpb25zLmxpbms/LmhyZWYgfHwgIXRoaXMuc2VsZWN0ZWRWYWx1ZXMgfHwgdGhpcy5zZWxlY3RlZFZhbHVlcy5sZW5ndGggPT09IDAgfHwgdGhpcy5zZWxlY3RlZFZhbHVlcy5ldmVyeSh2ID0+IHRoaXMuX2lubGluZS5zb21lKGkgPT4gdGhpcy5nZXRWYWx1ZShpIGFzIFRPcHRpb25zSXRlbSkgPT09IHYpID8/IGZhbHNlKSlcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBjb25zdCBmaWx0ZXIgPSBgJHtvcHRpb25zLnZhbHVlRmllbGR9IGluICgke3RoaXMuc2VsZWN0ZWRWYWx1ZXN9KWA7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5TZXRJbmxpbmVPcHRpb25zRnJvbUZpbHRlcihmaWx0ZXIpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgYXN5bmMgU2V0SW5saW5lT3B0aW9uc0Zyb21GaWx0ZXIoZmlsdGVyOiBzdHJpbmcpIHtcclxuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5wcm9wZXJ0eS5vcHRpb25zO1xyXG4gICAgICAgIGlmICghb3B0aW9ucy5saW5rPy5ocmVmKVxyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBwcm9wZXJ0eSBkb2VzIG5vdCBoYXZlIGEgbGluayBocmVmLicpO1xyXG5cclxuICAgICAgICBjb25zdCB0ZW1wbGF0ZWRVcmkgPSBvcHRpb25zLmxpbmsuaHJlZjtcclxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCkuZ2V0TGlzdEJ5VXJpPFRPcHRpb25zSXRlbT4odGVtcGxhdGVkVXJpLCB7ICRmaWx0ZXI6IGZpbHRlciwgJHRvcDogMTAgfSk7XHJcbiAgICAgICAgaWYgKCFyZXNwb25zZS5vayB8fCBQcm9ibGVtRGV0YWlscy5pc1Byb2JsZW1EZXRhaWxzKHJlc3BvbnNlLmJvZHkpIHx8ICFyZXNwb25zZS5ib2R5KSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgQW4gZXJyb3Igb2NjdXJyZWQgd2hpbGUgZ2V0dGluZyB0aGUgaW5pdGlhbCBzZWxlY3RlZCBpdGVtcyBmb3IgdGhlIHByb3BlcnR5ICR7dGhpcy5wcm9wZXJ0eS5uYW1lfS5gO1xyXG4gICAgICAgICAgICB0aGlzLl9tZXNzYWdlU2VydmljZS5hZGQoeyBzZXZlcml0eTogJ2Vycm9yJywgc3VtbWFyeTogJ0Vycm9yJywgZGV0YWlsOiBtZXNzYWdlLCBkYXRhOiByZXNwb25zZSwgc3RpY2t5OiB0cnVlIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgaXRlbXMgPSByZXNwb25zZS5ib2R5IS5fZW1iZWRkZWQuaXRlbXMgYXMgUmVzb3VyY2VPZkR0bzxUT3B0aW9uc0l0ZW0+W107XHJcbiAgICAgICAgY29uc3QgbmV3SXRlbXMgPSB0aGlzLmNvbWJpbmVJbmxpbmVXaXRoU2VsZWN0ZWQoaXRlbXMpO1xyXG4gICAgICAgIHRoaXMuX2lubGluZSA9IG5ld0l0ZW1zO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY29tYmluZUlubGluZVdpdGhTZWxlY3RlZChpdGVtczogUmVzb3VyY2VPZkR0bzxUT3B0aW9uc0l0ZW0+W10pOiBUT3B0aW9uc0l0ZW1bXSB7XHJcbiAgICAgICAgY29uc3Qgb2xkSW5saW5lID0gdGhpcy5faW5saW5lIGFzIFJlc291cmNlT2ZEdG88VE9wdGlvbnNJdGVtPltdO1xyXG4gICAgICAgIGlmICghb2xkSW5saW5lIHx8IG9sZElubGluZS5sZW5ndGggPT09IDApXHJcbiAgICAgICAgICAgIHJldHVybiBpdGVtcztcclxuXHJcbiAgICAgICAgY29uc3QgaXRlbXNUb0tlZXAgPSBvbGRJbmxpbmUuZmlsdGVyKGkgPT4gdGhpcy5zZWxlY3RlZFZhbHVlcy5pbmNsdWRlcyh0aGlzLmdldFZhbHVlKGkgYXMgVE9wdGlvbnNJdGVtKSkpO1xyXG4gICAgICAgIGNvbnN0IG5ld0l0ZW1zID0gaXRlbXMuY29uY2F0KGl0ZW1zVG9LZWVwLmZpbHRlcihpID0+ICFpdGVtcy5pbmNsdWRlcyhpKSkpO1xyXG5cclxuICAgICAgICByZXR1cm4gbmV3SXRlbXM7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBnZXRDbGllbnQoKTogUmVzdFdvcmxkQ2xpZW50IHtcclxuICAgICAgICBpZiAoIXRoaXMuYXBpTmFtZSlcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZ2V0IGEgY2xpZW50LCBiZWNhdXNlIHRoZSBhcGlOYW1lIGlzIG5vdCBzZXQuJyk7XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLl9jbGllbnRzLmdldENsaWVudCh0aGlzLmFwaU5hbWUpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIGpzb25TdHJpbmdpZnlXaXRoRWxpcHNpcyh2YWx1ZTogdW5rbm93bikge1xyXG4gICAgICAgIGNvbnN0IG1heExlbmd0aCA9IDIwMDtcclxuICAgICAgICBjb25zdCBlbmQgPSAxMDtcclxuICAgICAgICBjb25zdCBzdGFydCA9IG1heExlbmd0aCAtIGVuZCAtIDI7XHJcbiAgICAgICAgY29uc3QganNvbiA9IEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcclxuICAgICAgICBjb25zdCBzaG9ydGVuZWQgPSBqc29uLmxlbmd0aCA+IG1heExlbmd0aCA/IGpzb24uc3Vic3RyaW5nKDAsIHN0YXJ0KSArICfigKYnICsganNvbi5zdWJzdHJpbmcoanNvbi5sZW5ndGggLSBlbmQpIDoganNvbjtcclxuXHJcbiAgICAgICAgcmV0dXJuIHNob3J0ZW5lZDtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIERpc3BsYXlzIHRoZSB2YWx1ZSBvZiBhIGNvbXBsZXggb2JqZWN0IHdpdGggbXVsdGlwbGUgcHJvcGVydGllcyB0aGF0IGlzIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBmcm9tIHRoZSBnaXZlbiBwcm9wZXJ0eS5cclxuICogVGhlIG9iamVjdCBjYW4gYWxzbyBiZSBuZXN0ZWQuXHJcbiAqIEByZW1hcmtzIEl0IGlzIGFkdmlzZWQgdG8gdXNlIFJlc3RXb3JsZERpc3BsYXlDb21wb25lbnQgPHJ3LWRpc3BsYXk+IGFuZCBjb250cm9sIHRoZSByZW5kZXJlZCBlbGVtZW50cyB3aXRoIHRoZSBwYXNzZWQgaW4gcHJvcGVydHlcclxuICogaW5zdGVhZCBvZiB1c2luZyB0aGlzIGNvbXBvbmVudCBkaXJlY3RseS5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdydy1kaXNwbGF5LW9iamVjdCcsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktb2JqZWN0L3Jlc3R3b3JsZC1kaXNwbGF5LW9iamVjdC5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktb2JqZWN0L3Jlc3R3b3JsZC1kaXNwbGF5LW9iamVjdC5jb21wb25lbnQuY3NzJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgUmVzdFdvcmxkRGlzcGxheU9iamVjdENvbXBvbmVudCB7XHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgcHJvcGVydHkhOiBQcm9wZXJ0eTxudWxsLCBuZXZlciwgbmV2ZXI+ICYgeyBfdGVtcGxhdGVzOiB7IGRlZmF1bHQ6IFRlbXBsYXRlIH0gfTtcclxuXHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgYXBpTmFtZSE6IHN0cmluZztcclxuXHJcbiAgICBwcml2YXRlIF92YWx1ZT86IFJlY29yZDxzdHJpbmcsIFNpbXBsZVZhbHVlPjtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIHZhbHVlIHRvIGRpc3BsYXkuIElmIG5vdCBzZXQsIHRoZSB2YWx1ZSBvZiB0aGUgdGVtcGxhdGUgcHJvcGVydGllcyB3aWxsIGJlIHVzZWQuXHJcbiAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBzZXQgdmFsdWUodmFsdWU6IFJlY29yZDxzdHJpbmcsIFNpbXBsZVZhbHVlPiB8IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XHJcbiAgICB9XHJcbiAgICBwdWJsaWMgZ2V0IHZhbHVlKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIERpc3BsYXlzIHRoZSB2YWx1ZSBvZiBhIHNpbXBsZSBlbGVtZW50LCBsaWtlIGEgc3RyaW5nLCBhIG51bWJlciBvciBhIERhdGUgdGhhdCBpcyBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQgZnJvbSB0aGUgZ2l2ZW4gcHJvcGVydHkuXHJcbiAqIEByZW1hcmtzIEl0IGlzIGFkdmlzZWQgdG8gdXNlIFJlc3RXb3JsZERpc3BsYXlDb21wb25lbnQgPHJ3LWRpc3BsYXk+IGFuZCBjb250cm9sIHRoZSByZW5kZXJlZCBlbGVtZW50cyB3aXRoIHRoZSBwYXNzZWQgaW4gcHJvcGVydHlcclxuICogaW5zdGVhZCBvZiB1c2luZyB0aGlzIGNvbXBvbmVudCBkaXJlY3RseS5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdydy1kaXNwbGF5LXNpbXBsZScsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktc2ltcGxlL3Jlc3R3b3JsZC1kaXNwbGF5LXNpbXBsZS5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktc2ltcGxlL3Jlc3R3b3JsZC1kaXNwbGF5LXNpbXBsZS5jb21wb25lbnQuY3NzJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgUmVzdFdvcmxkRGlzcGxheVNpbXBsZUNvbXBvbmVudDxUUHJvcGVydHkgZXh0ZW5kcyBQcm9wZXJ0eTxTaW1wbGVWYWx1ZSwgc3RyaW5nLCBzdHJpbmc+PiB7XHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgcHJvcGVydHkhOiBUUHJvcGVydHk7XHJcblxyXG4gICAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcclxuICAgIGFwaU5hbWUhOiBzdHJpbmc7XHJcblxyXG4gICAgcHJpdmF0ZSBfdmFsdWU/OiBTaW1wbGVWYWx1ZTtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIHZhbHVlIHRvIGRpc3BsYXkuIElmIG5vdCBzZXQsIHRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgd2lsbCBiZSB1c2VkLlxyXG4gICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IHZhbHVlKHZhbHVlOiBTaW1wbGVWYWx1ZSkge1xyXG4gICAgICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XHJcbiAgICB9XHJcbiAgICBwdWJsaWMgZ2V0IHZhbHVlKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZSA/PyB0aGlzLnByb3BlcnR5LnZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgUHJvcGVydHlUeXBlKCkge1xyXG4gICAgICAgIHJldHVybiBQcm9wZXJ0eVR5cGU7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgX2RhdGVGb3JtYXQgPSBuZXcgRGF0ZSgzMzMzLCAxMCwgMjIpIC8vIG1vbnRocyBzdGFydCBhdCAwIGluIEpTXHJcbiAgICAgICAgLnRvTG9jYWxlRGF0ZVN0cmluZygpXHJcbiAgICAgICAgLnJlcGxhY2UoXCIyMlwiLCBcImRkXCIpXHJcbiAgICAgICAgLnJlcGxhY2UoXCIxMVwiLCBcIk1NXCIpXHJcbiAgICAgICAgLnJlcGxhY2UoXCIzMzMzXCIsIFwieXl5eVwiKVxyXG4gICAgICAgIC5yZXBsYWNlKFwiMzNcIiwgXCJ5eVwiKTtcclxuXHJcbiAgICBwdWJsaWMgZ2V0IGRhdGVGb3JtYXQoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gUmVzdFdvcmxkRGlzcGxheVNpbXBsZUNvbXBvbmVudC5fZGF0ZUZvcm1hdDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBfdGltZUZvcm1hdCA9IG5ldyBEYXRlKDEsIDEsIDEsIDIyLCAzMywgNDQpXHJcbiAgICAgICAgLnRvTG9jYWxlVGltZVN0cmluZygpXHJcbiAgICAgICAgLnJlcGxhY2UoXCIyMlwiLCBcImhoXCIpXHJcbiAgICAgICAgLnJlcGxhY2UoXCIzM1wiLCBcIm1tXCIpXHJcbiAgICAgICAgLnJlcGxhY2UoXCI0NFwiLCBcInNzXCIpO1xyXG5cclxuICAgIHB1YmxpYyBnZXQgdGltZUZvcm1hdCgpIHtcclxuICAgICAgICByZXR1cm4gUmVzdFdvcmxkRGlzcGxheVNpbXBsZUNvbXBvbmVudC5fdGltZUZvcm1hdDtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IFByb3BlcnR5V2l0aEltYWdlKCkge1xyXG4gICAgICAgIHJldHVybiBQcm9wZXJ0eVdpdGhJbWFnZTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIERpc3BsYXlzIHRoZSB2YWx1ZXMgb2YgYSBjb2xsZWN0aW9uIG9mIHJ3LWRpc3BsYXktZWxlbWVudHMgYXV0b21hdGljYWxseSBjcmVhdGVkIGZyb20gYSB0ZW1wbGF0ZS5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdydy1kaXNwbGF5LXRlbXBsYXRlJyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9yZXN0d29ybGQtZGlzcGxheS10ZW1wbGF0ZS9yZXN0d29ybGQtZGlzcGxheS10ZW1wbGF0ZS5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybDogJy4vcmVzdHdvcmxkLWRpc3BsYXktdGVtcGxhdGUvcmVzdHdvcmxkLWRpc3BsYXktdGVtcGxhdGUuY29tcG9uZW50LmNzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc3RXb3JsZERpc3BsYXlUZW1wbGF0ZUNvbXBvbmVudCB7XHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgdGVtcGxhdGUhOiBUZW1wbGF0ZTtcclxuXHJcbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxyXG4gICAgYXBpTmFtZSE6IHN0cmluZztcclxuXHJcbiAgICBwcml2YXRlIF92YWx1ZT86IFJlY29yZDxzdHJpbmcsIGFueT47XHJcbiAgICAvKipcclxuICAgICAqIFRoZSB2YWx1ZSB0byBkaXNwbGF5LiBJZiBub3Qgc2V0LCB0aGUgdmFsdWVzIG9mIHRoZSB0ZW1wbGF0ZSBwcm9wZXJ0aWVzIHdpbGwgYmUgdXNlZC5cclxuICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIHNldCB2YWx1ZSh2YWx1ZTogUmVjb3JkPHN0cmluZywgYW55PiB8IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XHJcbiAgICB9XHJcbiAgICBwdWJsaWMgZ2V0IHZhbHVlKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZTtcclxuICAgIH1cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwiZ3JpZCBmaWVsZFwiICpuZ0lmPVwicHJvcGVydHkudHlwZSAhPT0gUHJvcGVydHlUeXBlLkhpZGRlblwiPlxyXG4gICAgPHJ3LWxhYmVsIFtwcm9wZXJ0eV09XCJwcm9wZXJ0eVwiIGNsYXNzPVwiY29sLTEyIG1kOmNvbC0yIGZsZXggYWxpZ24taXRlbXMtY2VudGVyXCI+PC9ydy1sYWJlbD5cclxuICAgIDxydy1kaXNwbGF5IFtwcm9wZXJ0eV09XCJwcm9wZXJ0eVwiIFt2YWx1ZV09XCJ2YWx1ZVwiIFthcGlOYW1lXT1cImFwaU5hbWVcIiBjbGFzcz1cImNvbC0xMiBtZDpjb2wtMTBcIj48L3J3LWRpc3BsYXk+XHJcbjwvZGl2PlxyXG4iLCI8bmctY29udGFpbmVyICpuZ0lmPVwicHJvcGVydHkudHlwZSAhPT0gUHJvcGVydHlUeXBlLkhpZGRlblwiPlxyXG4gICAgPHJ3LWRpc3BsYXktZHJvcGRvd24gKm5nSWY9XCJwcm9wZXJ0eS5vcHRpb25zXCIgW3Byb3BlcnR5XT1cIiRhbnkocHJvcGVydHkpXCIgW3NlbGVjdGVkVmFsdWVzXT1cIiRhbnkodmFsdWUpXCIgW2FwaU5hbWVdPVwiYXBpTmFtZVwiPjwvcnctZGlzcGxheS1kcm9wZG93bj5cclxuXHJcbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIXByb3BlcnR5Lm9wdGlvbnNcIj5cclxuICAgICAgICA8bmctY29udGFpbmVyIFtuZ1N3aXRjaF09XCJwcm9wZXJ0eS50eXBlXCI+XHJcbiAgICAgICAgICAgIDxydy1kaXNwbGF5LW9iamVjdCAqbmdTd2l0Y2hDYXNlPVwiUHJvcGVydHlUeXBlLk9iamVjdFwiIFtwcm9wZXJ0eV09XCIkYW55KHByb3BlcnR5KVwiIFt2YWx1ZV09XCIkYW55KHZhbHVlKVwiIFthcGlOYW1lXT1cImFwaU5hbWVcIj48L3J3LWRpc3BsYXktb2JqZWN0PlxyXG4gICAgICAgICAgICA8cnctZGlzcGxheS1jb2xsZWN0aW9uICpuZ1N3aXRjaENhc2U9XCJQcm9wZXJ0eVR5cGUuQ29sbGVjdGlvblwiIFtwcm9wZXJ0eV09XCIkYW55KHByb3BlcnR5KVwiIFt2YWx1ZXNdPVwiJGFueSh2YWx1ZSlcIiBbYXBpTmFtZV09XCJhcGlOYW1lXCI+PC9ydy1kaXNwbGF5LWNvbGxlY3Rpb24+XHJcbiAgICAgICAgICAgIDxydy1kaXNwbGF5LXNpbXBsZSAqbmdTd2l0Y2hEZWZhdWx0IFtwcm9wZXJ0eV09XCJwcm9wZXJ0eVwiIFt2YWx1ZV09XCIkYW55KHZhbHVlKVwiIFthcGlOYW1lXT1cImFwaU5hbWVcIj48L3J3LWRpc3BsYXktc2ltcGxlPlxyXG4gICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgPC9uZy1jb250YWluZXI+XHJcbjwvbmctY29udGFpbmVyPlxyXG4iLCI8ZGl2IGNsYXNzPVwiZmxleCBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJicmFjZVwiPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwidy1mdWxsXCI+XHJcbiAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgdGVtcGxhdGUgb2YgdGVtcGxhdGVzXCIgY2xhc3M9XCJmbGV4IGFsaWduLWl0ZW1zLWNlbnRlclwiPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYnJhY2VcIj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3LWZ1bGwgZmxleCBqdXN0aWZ5LWNvbnRlbnQtZW5kXCI+XHJcbiAgICAgICAgICAgICAgICA8cnctZGlzcGxheS10ZW1wbGF0ZSBbdGVtcGxhdGVdPVwiJGFueSh0ZW1wbGF0ZSlcIiBbdmFsdWVdPVwidmFsdWVzID8gdmFsdWVzW3RlbXBsYXRlLnRpdGxlIV0gOiB1bmRlZmluZWRcIiBbYXBpTmFtZV09XCJhcGlOYW1lXCIgY2xhc3M9XCJ3LWZ1bGxcIj48L3J3LWRpc3BsYXktdGVtcGxhdGU+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbjwvZGl2PlxyXG4iLCI8IS0tIDxuZy10ZW1wbGF0ZSAjZGVmYXVsdElucHV0T3B0aW9ucyBsZXQtcHJvcGVydHk9XCJwcm9wZXJ0eVwiIGxldC1zZWxlY3RlZFZhbHVlcz1cInNlbGVjdGVkVmFsdWVzXCI+IC0tPlxyXG48bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCB2YWx1ZSBvZiBzZWxlY3RlZFZhbHVlczsgbGFzdCBhcyBsYXN0O1wiPlxyXG4gICAgPHNwYW4gW3BUb29sdGlwXT1cImdldFRvb2x0aXAoZ2V0T3B0aW9uSXRlbSh2YWx1ZSkpXCI+e3tnZXRMYWJlbChnZXRPcHRpb25JdGVtKHZhbHVlKSl9fTwvc3Bhbj57e2xhc3QgPyBcIlwiIDogXCIsIFwifX1cclxuPC9uZy1jb250YWluZXI+XHJcbjwhLS0gPC9uZy10ZW1wbGF0ZT5cclxuPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImlucHV0T3B0aW9uc1JlZiA/PyBkZWZhdWx0SW5wdXRPcHRpb25zOyBjb250ZXh0OiB7IHByb3BlcnR5OiBwcm9wZXJ0eSwgc2VsZWN0ZWRWYWx1ZXM6IHNlbGVjdGVkVmFsdWVzIH1cIj48L25nLWNvbnRhaW5lcj4gLS0+IiwiPGRpdiBjbGFzcz1cImZsZXggYWxpZ24taXRlbXMtY2VudGVyXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYnJhY2VcIj5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cInctZnVsbFwiPlxyXG4gICAgICAgIDxydy1kaXNwbGF5LXRlbXBsYXRlIFt0ZW1wbGF0ZV09XCJwcm9wZXJ0eS5fdGVtcGxhdGVzLmRlZmF1bHRcIiBbdmFsdWVdPVwidmFsdWVcIiBbYXBpTmFtZV09XCJhcGlOYW1lXCI+PC9ydy1kaXNwbGF5LXRlbXBsYXRlPlxyXG4gICAgPC9kaXY+XHJcbjwvZGl2PiIsIjxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cInByb3BlcnR5LnR5cGVcIj5cclxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIlByb3BlcnR5VHlwZS5UZXh0XCI+XHJcbiAgICAgICAgPHJ3LWF2YXRhciAqbmdJZj1cInByb3BlcnR5Lm5hbWUgPT09ICdjcmVhdGVkQnknIHx8IHByb3BlcnR5Lm5hbWUgPT09ICdsYXN0Q2hhbmdlZEJ5J1wiIFt1c2VyXT1cIiRhbnkodmFsdWUpXCI+PC9ydy1hdmF0YXI+XHJcbiAgICAgICAgPHNwYW4gKm5nSWY9XCJwcm9wZXJ0eS5uYW1lICE9PSAnY3JlYXRlZEJ5JyAmJiBwcm9wZXJ0eS5uYW1lICE9PSAnbGFzdENoYW5nZWRCeSdcIiBjbGFzcz1cInctZnVsbFwiPnt7dmFsdWUgfCBwcm9wZXJ0eVR5cGVGb3JtYXQ6cHJvcGVydHkudHlwZX19PC9zcGFuPlxyXG4gICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiUHJvcGVydHlUeXBlLkJvb2xcIj5cclxuICAgICAgICA8cC1jaGVja2JveCAqbmdJZj1cInByb3BlcnR5LnJlcXVpcmVkXCIgWyhuZ01vZGVsKV09XCJ2YWx1ZVwiIFtiaW5hcnldPVwidHJ1ZVwiIFtyZWFkb25seV09XCJ0cnVlXCIgW2Rpc2FibGVkXT1cInRydWVcIj48L3AtY2hlY2tib3g+XHJcbiAgICAgICAgPHAtdHJpU3RhdGVDaGVja2JveCAqbmdJZj1cIiFwcm9wZXJ0eS5yZXF1aXJlZFwiIFsobmdNb2RlbCldPVwidmFsdWVcIiBbcmVhZG9ubHldPVwidHJ1ZVwiIFtkaXNhYmxlZF09XCJ0cnVlXCI+PC9wLXRyaVN0YXRlQ2hlY2tib3g+XHJcbiAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICA8c3BhbiAqbmdTd2l0Y2hEZWZhdWx0IGNsYXNzPVwidy1mdWxsXCI+e3t2YWx1ZSB8IHByb3BlcnR5VHlwZUZvcm1hdDpwcm9wZXJ0eS50eXBlfX08L3NwYW4+XHJcbjwvbmctY29udGFpbmVyPlxyXG4iLCI8cnctZGlzcGxheS1lbGVtZW50ICpuZ0Zvcj1cImxldCBwcm9wZXJ0eSBvZiB0ZW1wbGF0ZS5wcm9wZXJ0aWVzXCIgW3Byb3BlcnR5XT1cInByb3BlcnR5XCIgW3ZhbHVlXT1cInZhbHVlID8gdmFsdWVbcHJvcGVydHkubmFtZV0gOiB1bmRlZmluZWRcIiBbYXBpTmFtZV09XCJhcGlOYW1lXCI+PC9ydy1kaXNwbGF5LWVsZW1lbnQ+Il19
|