@myrmidon/cadmus-refs-asserted-ids 2.0.0 → 2.1.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.
@@ -0,0 +1,405 @@
1
+ import { Component, EventEmitter, Inject, Input, Output, } from '@angular/core';
2
+ import { Validators, } from '@angular/forms';
3
+ import { debounceTime, distinctUntilChanged, forkJoin, take, } from 'rxjs';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "../services/item-ref-lookup.service";
6
+ import * as i2 from "../services/pin-ref-lookup.service";
7
+ import * as i3 from "@myrmidon/cadmus-api";
8
+ import * as i4 from "@angular/material/snack-bar";
9
+ import * as i5 from "@angular/forms";
10
+ import * as i6 from "@angular/common";
11
+ import * as i7 from "@angular/cdk/clipboard";
12
+ import * as i8 from "@angular/material/button";
13
+ import * as i9 from "@angular/material/checkbox";
14
+ import * as i10 from "@angular/material/expansion";
15
+ import * as i11 from "@angular/material/form-field";
16
+ import * as i12 from "@angular/material/icon";
17
+ import * as i13 from "@angular/material/input";
18
+ import * as i14 from "@angular/material/select";
19
+ import * as i15 from "@angular/material/core";
20
+ import * as i16 from "@myrmidon/cadmus-refs-lookup";
21
+ import * as i17 from "@myrmidon/ng-tools";
22
+ // from Cadmus general parts
23
+ const METADATA_PART_ID = 'it.vedph.metadata';
24
+ /*
25
+ * Scoped pin-based lookup component. This component provides a list
26
+ * of pin-based searches, with a lookup control. Whenever the user
27
+ * picks a pin value, he gets the details about its item and part, and
28
+ * item's metadata part, if any. He can then use these data to build
29
+ * some EID by variously assembling these components.
30
+ */
31
+ class PinTargetLookupComponent {
32
+ /**
33
+ * True when the by-type pin lookup mode is active.
34
+ * User can change mode unless modeSwitching is false.
35
+ */
36
+ get pinByTypeMode() {
37
+ return this.byTypeMode?.value;
38
+ }
39
+ set pinByTypeMode(value) {
40
+ if (!this.byTypeMode) {
41
+ this._startWithByTypeMode = value;
42
+ }
43
+ else {
44
+ this.byTypeMode.setValue(value || false);
45
+ this.byTypeMode.updateValueAndValidity();
46
+ }
47
+ }
48
+ /**
49
+ * The target to be edited.
50
+ */
51
+ get target() {
52
+ return this._target;
53
+ }
54
+ set target(value) {
55
+ if (this._target === value) {
56
+ return;
57
+ }
58
+ this._target = value || undefined;
59
+ this.updateForm(this._target);
60
+ }
61
+ constructor(_presetLookupDefs, itemLookupService, pinLookupService, _itemService, _thesService, _snackbar, formBuilder) {
62
+ this._presetLookupDefs = _presetLookupDefs;
63
+ this.itemLookupService = itemLookupService;
64
+ this.pinLookupService = pinLookupService;
65
+ this._itemService = _itemService;
66
+ this._thesService = _thesService;
67
+ this._snackbar = _snackbar;
68
+ this.partTypeKeys = [];
69
+ this.itemParts = [];
70
+ this._subs = [];
71
+ this.modelEntries = [];
72
+ // this is the default filter for the pin lookup, which will
73
+ // be merged with values provided by user here
74
+ this.filter = {
75
+ text: '',
76
+ limit: 10,
77
+ };
78
+ // form
79
+ this.item = formBuilder.control(null);
80
+ this.itemPart = formBuilder.control(null);
81
+ this.partTypeKey = formBuilder.control(null);
82
+ this.gid = formBuilder.control(null, [
83
+ Validators.required,
84
+ Validators.maxLength(300),
85
+ ]);
86
+ this.label = formBuilder.control(null, [
87
+ Validators.required,
88
+ Validators.maxLength(300),
89
+ ]);
90
+ this.byTypeMode = formBuilder.control(false, { nonNullable: true });
91
+ this.external = formBuilder.control(false, { nonNullable: true });
92
+ this.form = formBuilder.group({
93
+ item: this.item,
94
+ itemPart: this.itemPart,
95
+ partTypeKey: this.partTypeKey,
96
+ gid: this.gid,
97
+ label: this.label,
98
+ byTypeMode: this.byTypeMode,
99
+ external: this.external,
100
+ });
101
+ // events
102
+ this.targetChange = new EventEmitter();
103
+ this.editorClose = new EventEmitter();
104
+ }
105
+ forceByItem() {
106
+ this.pinByTypeMode = false;
107
+ this.canSwitchMode = false;
108
+ }
109
+ setupKeys() {
110
+ // use DI presets if no lookup definitions
111
+ if (!this.lookupDefinitions) {
112
+ this.lookupDefinitions = this._presetLookupDefs;
113
+ }
114
+ // keys are all the defined lookup searches
115
+ this.partTypeKeys = Object.keys(this.lookupDefinitions);
116
+ // if no keys, get them from thesaurus model-types;
117
+ // if this is not available, just force by item mode.
118
+ if (!this.partTypeKeys.length) {
119
+ if (this.modelEntries?.length) {
120
+ // set lookupDefinitions from thesaurus entries
121
+ this.lookupDefinitions = {};
122
+ this.modelEntries.forEach((e) => {
123
+ this.lookupDefinitions[e.value] = {
124
+ name: e.value,
125
+ typeId: e.id,
126
+ };
127
+ });
128
+ // set type keys from thesaurus entries
129
+ this.partTypeKeys = this.modelEntries.map((e) => e.value);
130
+ }
131
+ }
132
+ // if still no keys, force by item mode
133
+ if (!this.partTypeKeys.length) {
134
+ this.forceByItem();
135
+ }
136
+ else {
137
+ // if there is only one key, set it as the default
138
+ if (this.partTypeKeys.length === 1) {
139
+ this.partTypeKey.setValue(this.partTypeKeys[0]);
140
+ }
141
+ }
142
+ }
143
+ canBuildGid() {
144
+ return (!this.external.value && !this.gid.value) || this.gid.pristine;
145
+ }
146
+ canBuildLabel() {
147
+ return (!this.external.value && !this.label.value) || this.label.pristine;
148
+ }
149
+ ngOnInit() {
150
+ // set start mode if required
151
+ if (this._startWithByTypeMode) {
152
+ this.byTypeMode.setValue(true);
153
+ }
154
+ // whenever item changes, update item's parts and filter
155
+ this._subs.push(this.item.valueChanges
156
+ .pipe(distinctUntilChanged(), debounceTime(300))
157
+ .subscribe((item) => {
158
+ this.itemPart.setValue(null);
159
+ this.itemParts = item?.parts || [];
160
+ this.filter = {
161
+ ...this.filter,
162
+ itemId: item?.id,
163
+ };
164
+ }));
165
+ // whenever itemPart changes, update target and eventually gid
166
+ this._subs.push(this.itemPart.valueChanges
167
+ .pipe(distinctUntilChanged(), debounceTime(300))
168
+ .subscribe((part) => {
169
+ if (!this.gid.value || this.gid.pristine) {
170
+ this.gid.setValue(this.buildGid());
171
+ }
172
+ this.filter = {
173
+ ...this.filter,
174
+ partId: part?.id,
175
+ };
176
+ this.updateTarget();
177
+ }));
178
+ // whenever partTypeKey changes, update filter's options
179
+ this._subs.push(this.partTypeKey.valueChanges
180
+ .pipe(distinctUntilChanged(), debounceTime(300))
181
+ .subscribe((key) => {
182
+ this.pinFilterOptions = key
183
+ ? this.lookupDefinitions[key]
184
+ : undefined;
185
+ }));
186
+ // load model-types thesaurus entries
187
+ this._thesService.getThesaurus('model-types', true).subscribe({
188
+ next: (t) => {
189
+ this.modelEntries = t.entries || [];
190
+ if (this.modelEntries?.length) {
191
+ this.setupKeys();
192
+ }
193
+ else {
194
+ this.forceByItem();
195
+ }
196
+ },
197
+ error: () => {
198
+ this.forceByItem();
199
+ },
200
+ });
201
+ }
202
+ ngOnDestroy() {
203
+ for (let i = 0; i < this._subs.length; i++) {
204
+ this._subs[i].unsubscribe();
205
+ }
206
+ }
207
+ buildGid() {
208
+ // the GID is the part ID if any, or the item ID, followed by
209
+ // the pin's value (=EID)
210
+ const pin = this.lookupData?.pin;
211
+ if (!pin) {
212
+ return null;
213
+ }
214
+ return pin.partId
215
+ ? `P${pin.partId}/${pin.value}`
216
+ : `I${pin.itemId}/${pin.value}`;
217
+ }
218
+ buildLabel() {
219
+ if (!this.lookupData?.pin) {
220
+ return null;
221
+ }
222
+ const sb = [];
223
+ // pin value
224
+ sb.push(this.lookupData.pin.value);
225
+ // item title
226
+ sb.push(' | ');
227
+ sb.push(this.lookupData.item.title || this.lookupData.item.id);
228
+ // part type and role
229
+ const e = this.modelEntries?.find((e) => e.id === this.lookupData.pin.partTypeId);
230
+ sb.push(' (');
231
+ sb.push(e?.value || this.lookupData.pin.partTypeId);
232
+ if (this.lookupData.pin.roleId) {
233
+ sb.push(`, ${this.lookupData.pin.roleId}`);
234
+ }
235
+ sb.push(')');
236
+ return sb.join('');
237
+ }
238
+ getTarget() {
239
+ if (this.external.value) {
240
+ return {
241
+ gid: this.gid.value || '',
242
+ label: this.label.value || '',
243
+ };
244
+ }
245
+ else {
246
+ const pin = this.lookupData?.pin;
247
+ return {
248
+ itemId: pin?.itemId || '',
249
+ partId: pin?.partId || '',
250
+ partTypeId: pin?.partTypeId || '',
251
+ roleId: pin?.roleId || '',
252
+ name: pin?.name || '',
253
+ value: pin?.value || '',
254
+ gid: pin?.value || '',
255
+ label: pin?.value || '',
256
+ };
257
+ }
258
+ }
259
+ updateTarget() {
260
+ this._noFormUpdate = true;
261
+ if (this.canBuildGid()) {
262
+ this.gid.setValue(this.buildGid());
263
+ this.gid.markAsDirty();
264
+ }
265
+ if (this.canBuildLabel()) {
266
+ this.label.setValue(this.buildLabel());
267
+ this.label.markAsDirty();
268
+ }
269
+ this.target = this.getTarget();
270
+ this._noFormUpdate = false;
271
+ }
272
+ updateForm(target) {
273
+ if (this._noFormUpdate) {
274
+ return;
275
+ }
276
+ // build pin info from target
277
+ if (!target) {
278
+ this.lookupData = undefined;
279
+ this.form.reset();
280
+ return;
281
+ }
282
+ this.external.setValue(!target.name);
283
+ this.lookupData = {
284
+ pin: {
285
+ itemId: target.itemId || '',
286
+ partId: target.partId || '',
287
+ partTypeId: target.partTypeId || '',
288
+ roleId: target.roleId || '',
289
+ name: target.name || '',
290
+ value: target.value || '',
291
+ },
292
+ };
293
+ // get item
294
+ if (target.itemId) {
295
+ this._itemService.getItem(target.itemId, true).subscribe({
296
+ next: (item) => {
297
+ this.item.setValue(item);
298
+ this.form.markAsPristine();
299
+ },
300
+ error: (error) => {
301
+ if (error) {
302
+ console.error(JSON.stringify(error));
303
+ }
304
+ },
305
+ });
306
+ }
307
+ }
308
+ /**
309
+ * Called when the item lookup changes (item is looked up
310
+ * by its title).
311
+ *
312
+ * @param item The item got from lookup.
313
+ */
314
+ onItemLookupChange(item) {
315
+ // load item's parts
316
+ this._itemService.getItem(item.id, true).subscribe({
317
+ next: (i) => {
318
+ // setting the item will trigger its parts update
319
+ this.item.setValue(i);
320
+ this.updateTarget();
321
+ },
322
+ error: (error) => {
323
+ if (error) {
324
+ console.error(JSON.stringify(error));
325
+ }
326
+ this.itemPart.setValue(null);
327
+ this.itemParts = [];
328
+ this.updateTarget();
329
+ },
330
+ });
331
+ }
332
+ loadItemInfo(pin) {
333
+ forkJoin({
334
+ item: this._itemService.getItem(pin.itemId, false),
335
+ part: this._itemService.getPartFromTypeAndRole(pin.itemId, METADATA_PART_ID),
336
+ })
337
+ .pipe(take(1))
338
+ .subscribe({
339
+ next: (result) => {
340
+ this.lookupData = {
341
+ pin: pin,
342
+ item: result.item,
343
+ metaPart: result.part,
344
+ };
345
+ this.updateTarget();
346
+ },
347
+ error: (error) => {
348
+ this.lookupData = undefined;
349
+ console.error(error ? JSON.stringify(error) : 'Error loading item/metadata');
350
+ },
351
+ });
352
+ }
353
+ /**
354
+ * Called when the pin lookup change. A pin is looked up by its
355
+ * name and value (=the filter's text), and optionally by:
356
+ * - its index lookup definition (selected by partTypeKey).
357
+ * - its item (defined by item, in filter).
358
+ * - its part (defined by itemPart, in filter).
359
+ *
360
+ * @param info The pin info from pin lookup.
361
+ */
362
+ onPinLookupChange(info) {
363
+ this.loadItemInfo(info);
364
+ }
365
+ onCopied() {
366
+ this._snackbar.open('Copied to clipboard', 'OK', {
367
+ duration: 1500,
368
+ });
369
+ }
370
+ close() {
371
+ this.editorClose.emit();
372
+ }
373
+ save() {
374
+ if (this.form.invalid) {
375
+ return;
376
+ }
377
+ this._target = this.getTarget();
378
+ this.targetChange.emit(this._target);
379
+ }
380
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: PinTargetLookupComponent, deps: [{ token: 'indexLookupDefinitions' }, { token: i1.ItemRefLookupService }, { token: i2.PinRefLookupService }, { token: i3.ItemService }, { token: i3.ThesaurusService }, { token: i4.MatSnackBar }, { token: i5.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
381
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.1", type: PinTargetLookupComponent, selector: "cadmus-pin-target-lookup", inputs: { pinByTypeMode: "pinByTypeMode", canSwitchMode: "canSwitchMode", canEditTarget: "canEditTarget", lookupDefinitions: "lookupDefinitions", target: "target" }, outputs: { editorClose: "editorClose", targetChange: "targetChange" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- external -->\r\n <mat-checkbox [formControl]=\"external\">external</mat-checkbox>\r\n\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <div>\r\n <mat-form-field *ngIf=\"external.value || canEditTarget\">\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n <mat-error\r\n *ngIf=\"$any(label).errors?.required && (label.dirty || label.touched)\"\r\n >label required</mat-error\r\n >\r\n <mat-error\r\n *ngIf=\"\r\n $any(label).errors?.maxLength && (label.dirty || label.touched)\r\n \"\r\n >label too long</mat-error\r\n >\r\n </mat-form-field>\r\n <div\r\n *ngIf=\"!external.value && !canEditTarget && label.value\"\r\n class=\"info\"\r\n >\r\n <span class=\"label\">label</span>{{ label.value }}\r\n </div>\r\n </div>\r\n\r\n <!-- gid -->\r\n <div>\r\n <mat-form-field *ngIf=\"external.value || canEditTarget\">\r\n <mat-label>GID</mat-label>\r\n <input matInput [formControl]=\"gid\" />\r\n <mat-error\r\n *ngIf=\"$any(gid).errors?.required && (gid.dirty || gid.touched)\"\r\n >GID required</mat-error\r\n >\r\n <mat-error\r\n *ngIf=\"$any(gid).errors?.maxLength && (gid.dirty || gid.touched)\"\r\n >GID too long</mat-error\r\n >\r\n </mat-form-field>\r\n <div *ngIf=\"!external.value && !canEditTarget && gid.value\" class=\"info\">\r\n <span class=\"label\">GID</span> <span class=\"gid\">{{ gid.value }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- BY ITEM -->\r\n <div *ngIf=\"!external.value\">\r\n <fieldset *ngIf=\"!byTypeMode.value\" class=\"form-row\">\r\n <legend>pin filters</legend>\r\n <!-- item filter -->\r\n <cadmus-ref-lookup\r\n [service]=\"itemLookupService\"\r\n label=\"item\"\r\n (itemChange)=\"onItemLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n\r\n <!-- part filter -->\r\n <mat-form-field *ngIf=\"itemParts.length\">\r\n <mat-label>part</mat-label>\r\n <mat-select [formControl]=\"itemPart\">\r\n <mat-option [value]=\"null\">(any)</mat-option>\r\n <mat-option *ngFor=\"let p of itemParts\" [value]=\"p\">{{\r\n p.typeId | flatLookup : modelEntries : \"id\" : \"value\"\r\n }}</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </fieldset>\r\n\r\n <!-- BY TYPE -->\r\n <div *ngIf=\"byTypeMode.value\">\r\n <!-- par type filter -->\r\n <mat-form-field *ngIf=\"partTypeKeys?.length\">\r\n <mat-label>part type</mat-label>\r\n <mat-select [formControl]=\"partTypeKey\">\r\n <mat-option *ngFor=\"let k of partTypeKeys\" [value]=\"k\">{{\r\n k\r\n }}</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- PIN -->\r\n <div class=\"form-row\">\r\n <!-- pin lookup -->\r\n <cadmus-ref-lookup\r\n [service]=\"pinLookupService\"\r\n [baseFilter]=\"filter\"\r\n [options]=\"pinFilterOptions\"\r\n label=\"pin\"\r\n (itemChange)=\"onPinLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n <!-- mode switcher -->\r\n <div>\r\n <mat-checkbox [formControl]=\"byTypeMode\" *ngIf=\"canSwitchMode\">\r\n by type</mat-checkbox\r\n >\r\n </div>\r\n </div>\r\n\r\n <!-- data -->\r\n <mat-expansion-panel id=\"data\" *ngIf=\"lookupData?.pin?.name\">\r\n <mat-expansion-panel-header>pin data</mat-expansion-panel-header>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n <tr *ngIf=\"lookupData?.pin?.value\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ lookupData!.pin.value }}</td>\r\n </tr>\r\n <!-- item ID -->\r\n <tr *ngIf=\"lookupData?.pin?.itemId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.itemId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ lookupData!.pin.itemId }}</td>\r\n </tr>\r\n <!-- item title -->\r\n <tr *ngIf=\"lookupData?.item?.title\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.item!.title\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item title</td>\r\n <td>{{ lookupData!.item!.title }}</td>\r\n </tr>\r\n <!-- part ID -->\r\n <tr *ngIf=\"lookupData?.pin?.partId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ lookupData!.pin.partId }}</td>\r\n </tr>\r\n <!-- part type ID -->\r\n <tr *ngIf=\"lookupData?.pin?.partTypeId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partTypeId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ lookupData!.pin!.partTypeId }}</td>\r\n </tr>\r\n <!-- part role ID -->\r\n <tr *ngIf=\"lookupData?.pin?.roleId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.roleId!\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ lookupData!.pin!.roleId }}</td>\r\n </tr>\r\n\r\n <!-- part's metadata -->\r\n <tr\r\n *ngFor=\"\r\n let m of lookupData?.metaPart?.metadata || [];\r\n let i = index\r\n \"\r\n >\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"m.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n </div>\r\n\r\n <!-- buttons -->\r\n <div>\r\n <button mat-flat-button type=\"button\" (click)=\"close()\">\r\n <mat-icon color=\"warn\">close</mat-icon>\r\n </button>\r\n <button mat-flat-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon color=\"primary\">check_circle</mat-icon> target\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".metadata{color:#4a3001}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px;margin:8px 0}.info .label{background-color:#fff;color:silver;margin:0 6px}#data{margin:8px 0}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.label{border:1px solid silver;border-radius:6px;padding:4px}fieldset{border:1px solid silver;border-radius:6px;padding:4px 8px;margin-bottom:8px}legend{color:silver}\n"], dependencies: [{ kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i7.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "component", type: i8.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i8.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "component", type: i10.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["disabled", "expanded", "hideToggle", "togglePosition"], outputs: ["opened", "closed", "expandedChange", "afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i10.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["tabIndex", "expandedHeight", "collapsedHeight"] }, { kind: "component", type: i11.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i11.MatLabel, selector: "mat-label" }, { kind: "directive", type: i11.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i12.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i14.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i15.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i16.RefLookupComponent, selector: "cadmus-ref-lookup", inputs: ["label", "limit", "baseFilter", "service", "item", "required", "hasMore", "linkTemplate", "optDialog", "options"], outputs: ["itemChange", "moreRequest"] }, { kind: "pipe", type: i17.FlatLookupPipe, name: "flatLookup" }] }); }
382
+ }
383
+ export { PinTargetLookupComponent };
384
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: PinTargetLookupComponent, decorators: [{
385
+ type: Component,
386
+ args: [{ selector: 'cadmus-pin-target-lookup', template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- external -->\r\n <mat-checkbox [formControl]=\"external\">external</mat-checkbox>\r\n\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <div>\r\n <mat-form-field *ngIf=\"external.value || canEditTarget\">\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n <mat-error\r\n *ngIf=\"$any(label).errors?.required && (label.dirty || label.touched)\"\r\n >label required</mat-error\r\n >\r\n <mat-error\r\n *ngIf=\"\r\n $any(label).errors?.maxLength && (label.dirty || label.touched)\r\n \"\r\n >label too long</mat-error\r\n >\r\n </mat-form-field>\r\n <div\r\n *ngIf=\"!external.value && !canEditTarget && label.value\"\r\n class=\"info\"\r\n >\r\n <span class=\"label\">label</span>{{ label.value }}\r\n </div>\r\n </div>\r\n\r\n <!-- gid -->\r\n <div>\r\n <mat-form-field *ngIf=\"external.value || canEditTarget\">\r\n <mat-label>GID</mat-label>\r\n <input matInput [formControl]=\"gid\" />\r\n <mat-error\r\n *ngIf=\"$any(gid).errors?.required && (gid.dirty || gid.touched)\"\r\n >GID required</mat-error\r\n >\r\n <mat-error\r\n *ngIf=\"$any(gid).errors?.maxLength && (gid.dirty || gid.touched)\"\r\n >GID too long</mat-error\r\n >\r\n </mat-form-field>\r\n <div *ngIf=\"!external.value && !canEditTarget && gid.value\" class=\"info\">\r\n <span class=\"label\">GID</span> <span class=\"gid\">{{ gid.value }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- BY ITEM -->\r\n <div *ngIf=\"!external.value\">\r\n <fieldset *ngIf=\"!byTypeMode.value\" class=\"form-row\">\r\n <legend>pin filters</legend>\r\n <!-- item filter -->\r\n <cadmus-ref-lookup\r\n [service]=\"itemLookupService\"\r\n label=\"item\"\r\n (itemChange)=\"onItemLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n\r\n <!-- part filter -->\r\n <mat-form-field *ngIf=\"itemParts.length\">\r\n <mat-label>part</mat-label>\r\n <mat-select [formControl]=\"itemPart\">\r\n <mat-option [value]=\"null\">(any)</mat-option>\r\n <mat-option *ngFor=\"let p of itemParts\" [value]=\"p\">{{\r\n p.typeId | flatLookup : modelEntries : \"id\" : \"value\"\r\n }}</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </fieldset>\r\n\r\n <!-- BY TYPE -->\r\n <div *ngIf=\"byTypeMode.value\">\r\n <!-- par type filter -->\r\n <mat-form-field *ngIf=\"partTypeKeys?.length\">\r\n <mat-label>part type</mat-label>\r\n <mat-select [formControl]=\"partTypeKey\">\r\n <mat-option *ngFor=\"let k of partTypeKeys\" [value]=\"k\">{{\r\n k\r\n }}</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- PIN -->\r\n <div class=\"form-row\">\r\n <!-- pin lookup -->\r\n <cadmus-ref-lookup\r\n [service]=\"pinLookupService\"\r\n [baseFilter]=\"filter\"\r\n [options]=\"pinFilterOptions\"\r\n label=\"pin\"\r\n (itemChange)=\"onPinLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n <!-- mode switcher -->\r\n <div>\r\n <mat-checkbox [formControl]=\"byTypeMode\" *ngIf=\"canSwitchMode\">\r\n by type</mat-checkbox\r\n >\r\n </div>\r\n </div>\r\n\r\n <!-- data -->\r\n <mat-expansion-panel id=\"data\" *ngIf=\"lookupData?.pin?.name\">\r\n <mat-expansion-panel-header>pin data</mat-expansion-panel-header>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n <tr *ngIf=\"lookupData?.pin?.value\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ lookupData!.pin.value }}</td>\r\n </tr>\r\n <!-- item ID -->\r\n <tr *ngIf=\"lookupData?.pin?.itemId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.itemId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ lookupData!.pin.itemId }}</td>\r\n </tr>\r\n <!-- item title -->\r\n <tr *ngIf=\"lookupData?.item?.title\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.item!.title\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item title</td>\r\n <td>{{ lookupData!.item!.title }}</td>\r\n </tr>\r\n <!-- part ID -->\r\n <tr *ngIf=\"lookupData?.pin?.partId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ lookupData!.pin.partId }}</td>\r\n </tr>\r\n <!-- part type ID -->\r\n <tr *ngIf=\"lookupData?.pin?.partTypeId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partTypeId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ lookupData!.pin!.partTypeId }}</td>\r\n </tr>\r\n <!-- part role ID -->\r\n <tr *ngIf=\"lookupData?.pin?.roleId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.roleId!\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ lookupData!.pin!.roleId }}</td>\r\n </tr>\r\n\r\n <!-- part's metadata -->\r\n <tr\r\n *ngFor=\"\r\n let m of lookupData?.metaPart?.metadata || [];\r\n let i = index\r\n \"\r\n >\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"m.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n </div>\r\n\r\n <!-- buttons -->\r\n <div>\r\n <button mat-flat-button type=\"button\" (click)=\"close()\">\r\n <mat-icon color=\"warn\">close</mat-icon>\r\n </button>\r\n <button mat-flat-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon color=\"primary\">check_circle</mat-icon> target\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".metadata{color:#4a3001}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px;margin:8px 0}.info .label{background-color:#fff;color:silver;margin:0 6px}#data{margin:8px 0}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.label{border:1px solid silver;border-radius:6px;padding:4px}fieldset{border:1px solid silver;border-radius:6px;padding:4px 8px;margin-bottom:8px}legend{color:silver}\n"] }]
387
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
388
+ type: Inject,
389
+ args: ['indexLookupDefinitions']
390
+ }] }, { type: i1.ItemRefLookupService }, { type: i2.PinRefLookupService }, { type: i3.ItemService }, { type: i3.ThesaurusService }, { type: i4.MatSnackBar }, { type: i5.FormBuilder }]; }, propDecorators: { pinByTypeMode: [{
391
+ type: Input
392
+ }], canSwitchMode: [{
393
+ type: Input
394
+ }], canEditTarget: [{
395
+ type: Input
396
+ }], lookupDefinitions: [{
397
+ type: Input
398
+ }], target: [{
399
+ type: Input
400
+ }], editorClose: [{
401
+ type: Output
402
+ }], targetChange: [{
403
+ type: Output
404
+ }] } });
405
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGluLXRhcmdldC1sb29rdXAuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbXlybWlkb24vY2FkbXVzLXJlZnMtYXNzZXJ0ZWQtaWRzL3NyYy9saWIvcGluLXRhcmdldC1sb29rdXAvcGluLXRhcmdldC1sb29rdXAuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbXlybWlkb24vY2FkbXVzLXJlZnMtYXNzZXJ0ZWQtaWRzL3NyYy9saWIvcGluLXRhcmdldC1sb29rdXAvcGluLXRhcmdldC1sb29rdXAuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFHTCxNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUlMLFVBQVUsR0FDWCxNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFFTCxZQUFZLEVBQ1osb0JBQW9CLEVBQ3BCLFFBQVEsRUFDUixJQUFJLEdBQ0wsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFtQmQsNEJBQTRCO0FBQzVCLE1BQU0sZ0JBQWdCLEdBQUcsbUJBQW1CLENBQUM7QUFtQzdDOzs7Ozs7R0FNRztBQUNILE1BS2Esd0JBQXdCO0lBTW5DOzs7T0FHRztJQUNILElBQ1csYUFBYTtRQUN0QixPQUFPLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDO0lBQ2hDLENBQUM7SUFDRCxJQUFXLGFBQWEsQ0FBQyxLQUEwQjtRQUNqRCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNwQixJQUFJLENBQUMsb0JBQW9CLEdBQUcsS0FBSyxDQUFDO1NBQ25DO2FBQU07WUFDTCxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLENBQUM7WUFDekMs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QUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2QyxDQUFDOzhHQWpjVSx3QkFBd0Isa0JBOEZ6Qix3QkFBd0I7a0dBOUZ2Qix3QkFBd0IsNlNDeEZyQywrN1FBdVBBOztTRC9KYSx3QkFBd0I7MkZBQXhCLHdCQUF3QjtrQkFMcEMsU0FBUzsrQkFDRSwwQkFBMEI7OzBCQWtHakMsTUFBTTsyQkFBQyx3QkFBd0I7OE5BbkZ2QixhQUFhO3NCQUR2QixLQUFLO2dCQWlCQyxhQUFhO3NCQURuQixLQUFLO2dCQU9DLGFBQWE7c0JBRG5CLEtBQUs7Z0JBV0MsaUJBQWlCO3NCQUR2QixLQUFLO2dCQU9LLE1BQU07c0JBRGhCLEtBQUs7Z0JBZ0JDLFdBQVc7c0JBRGpCLE1BQU07Z0JBT0EsWUFBWTtzQkFEbEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbmplY3QsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIEZvcm1CdWlsZGVyLFxuICBGb3JtQ29udHJvbCxcbiAgRm9ybUdyb3VwLFxuICBWYWxpZGF0b3JzLFxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge1xuICBTdWJzY3JpcHRpb24sXG4gIGRlYm91bmNlVGltZSxcbiAgZGlzdGluY3RVbnRpbENoYW5nZWQsXG4gIGZvcmtKb2luLFxuICB0YWtlLFxufSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE1hdFNuYWNrQmFyIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc25hY2stYmFyJztcblxuaW1wb3J0IHsgSXRlbVNlcnZpY2UsIFRoZXNhdXJ1c1NlcnZpY2UgfSBmcm9tICdAbXlybWlkb24vY2FkbXVzLWFwaSc7XG5pbXBvcnQge1xuICBEYXRhUGluSW5mbyxcbiAgSW5kZXhMb29rdXBEZWZpbml0aW9uLFxuICBJbmRleExvb2t1cERlZmluaXRpb25zLFxuICBJdGVtLFxuICBQYXJ0LFxuICBUaGVzYXVydXNFbnRyeSxcbn0gZnJvbSAnQG15cm1pZG9uL2NhZG11cy1jb3JlJztcblxuaW1wb3J0IHtcbiAgUGluUmVmTG9va3VwRmlsdGVyLFxuICBQaW5SZWZMb29rdXBTZXJ2aWNlLFxufSBmcm9tICcuLi9zZXJ2aWNlcy9waW4tcmVmLWxvb2t1cC5zZXJ2aWNlJztcbmltcG9ydCB7IEl0ZW1SZWZMb29rdXBTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvaXRlbS1yZWYtbG9va3VwLnNlcnZpY2UnO1xuXG4vLyBmcm9tIENhZG11cyBnZW5lcmFsIHBhcnRzXG5jb25zdCBNRVRBREFUQV9QQVJUX0lEID0gJ2l0LnZlZHBoLm1ldGFkYXRhJztcbmludGVyZmFjZSBNZXRhZGF0YVBhcnQgZXh0ZW5kcyBQYXJ0IHtcbiAgbWV0YWRhdGE6IHtcbiAgICB0eXBlPzogc3RyaW5nO1xuICAgIG5hbWU6IHN0cmluZztcbiAgICB2YWx1ZTogc3RyaW5nO1xuICB9W107XG59XG5cbi8qKlxuICogUGluIGxvb2t1cCBkYXRhIHVzZWQgaW50ZXJuYWxseSBieSB0aGUgY29tcG9uZW50LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBpbkxvb2t1cERhdGEge1xuICBwaW46IERhdGFQaW5JbmZvO1xuICBpdGVtPzogSXRlbTtcbiAgbWV0YVBhcnQ/OiBNZXRhZGF0YVBhcnQ7XG59XG5cbi8qKlxuICogQSBwaW4tYmFzZWQgdGFyZ2V0LiBUaGlzIGluY2x1ZGVzIHBpbidzIG5hbWUgYW5kIHZhbHVlLCBhbmRcbiAqIHRoZSBpdGVtJ3MgSUQgYW5kIG9wdGlvbmFsIHBhcnQgSURzLiBUaGUgbGFiZWwgaXMgYSB1c2VyIGZyaWVuZGx5XG4gKiBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHRhcmdldCwgd2hpbGUgdGhlIGdpZCBpcyBhIGdsb2JhbGx5XG4gKiB1bmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHRhcmdldC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQaW5UYXJnZXQge1xuICBnaWQ6IHN0cmluZztcbiAgbGFiZWw6IHN0cmluZztcbiAgaXRlbUlkPzogc3RyaW5nO1xuICBwYXJ0SWQ/OiBzdHJpbmc7XG4gIHBhcnRUeXBlSWQ/OiBzdHJpbmc7XG4gIHJvbGVJZD86IHN0cmluZztcbiAgbmFtZT86IHN0cmluZztcbiAgdmFsdWU/OiBzdHJpbmc7XG59XG5cbi8qXG4gKiBTY29wZWQgcGluLWJhc2VkIGxvb2t1cCBjb21wb25lbnQuIFRoaXMgY29tcG9uZW50IHByb3ZpZGVzIGEgbGlzdFxuICogb2YgcGluLWJhc2VkIHNlYXJjaGVzLCB3aXRoIGEgbG9va3VwIGNvbnRyb2wuIFdoZW5ldmVyIHRoZSB1c2VyXG4gKiBwaWNrcyBhIHBpbiB2YWx1ZSwgaGUgZ2V0cyB0aGUgZGV0YWlscyBhYm91dCBpdHMgaXRlbSBhbmQgcGFydCwgYW5kXG4gKiBpdGVtJ3MgbWV0YWRhdGEgcGFydCwgaWYgYW55LiBIZSBjYW4gdGhlbiB1c2UgdGhlc2UgZGF0YSB0byBidWlsZFxuICogc29tZSBFSUQgYnkgdmFyaW91c2x5IGFzc2VtYmxpbmcgdGhlc2UgY29tcG9uZW50cy5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY2FkbXVzLXBpbi10YXJnZXQtbG9va3VwJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3Bpbi10YXJnZXQtbG9va3VwLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vcGluLXRhcmdldC1sb29rdXAuY29tcG9uZW50LmNzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBQaW5UYXJnZXRMb29rdXBDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgX3N1YnM6IFN1YnNjcmlwdGlvbltdO1xuICBwcml2YXRlIF90YXJnZXQ6IFBpblRhcmdldCB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBfbm9Gb3JtVXBkYXRlPzogYm9vbGVhbjtcbiAgcHJpdmF0ZSBfc3RhcnRXaXRoQnlUeXBlTW9kZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRydWUgd2hlbiB0aGUgYnktdHlwZSBwaW4gbG9va3VwIG1vZGUgaXMgYWN0aXZlLlxuICAgKiBVc2VyIGNhbiBjaGFuZ2UgbW9kZSB1bmxlc3MgbW9kZVN3aXRjaGluZyBpcyBmYWxzZS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBnZXQgcGluQnlUeXBlTW9kZSgpOiBib29sZWFuIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5ieVR5cGVNb2RlPy52YWx1ZTtcbiAgfVxuICBwdWJsaWMgc2V0IHBpbkJ5VHlwZU1vZGUodmFsdWU6IGJvb2xlYW4gfCB1bmRlZmluZWQpIHtcbiAgICBpZiAoIXRoaXMuYnlUeXBlTW9kZSkge1xuICAgICAgdGhpcy5fc3RhcnRXaXRoQnlUeXBlTW9kZSA9IHZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmJ5VHlwZU1vZGUuc2V0VmFsdWUodmFsdWUgfHwgZmFsc2UpO1xuICAgICAgdGhpcy5ieVR5cGVNb2RlLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJ1ZSB3aGVuIHRoZSB1c2VyIGNhbiBzd2l0Y2ggYmV0d2VlbiBieS10eXBlIGFuZCBieS1pdGVtIG1vZGUuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgY2FuU3dpdGNoTW9kZT86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBUcnVlIHdoZW4gdGhlIHVzZXIgY2FuIGVkaXQgdGhlIHRhcmdldCdzIGdpZC9sYWJlbCBmb3IgaW50ZXJuYWxcbiAgICogdGFyZ2V0cy5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjYW5FZGl0VGFyZ2V0PzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRoZSBsb29rdXAgZGVmaW5pdGlvbnMgdG8gYmUgdXNlZCBmb3IgdGhlIGJ5LXR5cGUgbG9va3VwLiBJZlxuICAgKiBub3Qgc3BlY2lmaWVkLCB0aGUgbG9va3VwIGRlZmluaXRpb25zIHdpbGwgYmUgZ290IHZpYSBpbmplY3Rpb25cbiAgICogd2hlbiBhdmFpbGFibGU7IGlmIHRoZSBpbmplY3RlZCBkZWZpbml0aW9ucyBhcmUgZW1wdHksIHRoZVxuICAgKiBsb29rdXAgZGVmaW5pdGlvbnMgd2lsbCBiZSBidWlsdCBmcm9tIHRoZSBtb2RlbC10eXBlcyB0aGVzYXVydXM7XG4gICAqIGlmIHRoaXMgaXMgbm90IGF2YWlsYWJsZSBlaXRoZXIsIHRoZSBieS10eXBlIGxvb2t1cCB3aWxsIGJlXG4gICAqIGRpc2FibGVkLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIGxvb2t1cERlZmluaXRpb25zPzogSW5kZXhMb29rdXBEZWZpbml0aW9ucztcblxuICAvKipcbiAgICogVGhlIHRhcmdldCB0byBiZSBlZGl0ZWQuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgZ2V0IHRhcmdldCgpOiBQaW5UYXJnZXQgfCB1bmRlZmluZWQgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fdGFyZ2V0O1xuICB9XG4gIHB1YmxpYyBzZXQgdGFyZ2V0KHZhbHVlOiBQaW5UYXJnZXQgfCB1bmRlZmluZWQgfCBudWxsKSB7XG4gICAgaWYgKHRoaXMuX3RhcmdldCA9PT0gdmFsdWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5fdGFyZ2V0ID0gdmFsdWUgfHwgdW5kZWZpbmVkO1xuICAgIHRoaXMudXBkYXRlRm9ybSh0aGlzLl90YXJnZXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB1c2VyIGNsb3NlcyB0aGUgZWRpdG9yLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyBlZGl0b3JDbG9zZTogRXZlbnRFbWl0dGVyPGFueT47XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW5ldmVyIHRoZSB0YXJnZXQgY2hhbmdlcy5cbiAgICogVGhlIGV2ZW50J3MgdmFsdWUgaXMgdGhlIG5ldyB0YXJnZXQuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgcHVibGljIHRhcmdldENoYW5nZTogRXZlbnRFbWl0dGVyPFBpblRhcmdldD47XG5cbiAgLy8gYnkgdHlwZVxuICBwdWJsaWMgbW9kZWxFbnRyaWVzOiBUaGVzYXVydXNFbnRyeVtdO1xuICBwdWJsaWMgcGFydFR5cGVLZXlzOiBzdHJpbmdbXTtcbiAgLy8gYnkgaXRlbVxuICBwdWJsaWMgaXRlbVBhcnRzOiBQYXJ0W107XG4gIC8vIGZvcm0gLSBieSBpdGVtXG4gIHB1YmxpYyBpdGVtOiBGb3JtQ29udHJvbDxJdGVtIHwgbnVsbD47XG4gIHB1YmxpYyBpdGVtUGFydDogRm9ybUNvbnRyb2w8UGFydCB8IG51bGw+O1xuICAvLyBmb3JtIC0gYnkgdHlwZVxuICBwdWJsaWMgcGFydFR5cGVLZXk6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xuICAvLyBmb3JtIC0gYm90aFxuICBwdWJsaWMgZ2lkOiBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPjtcbiAgcHVibGljIGxhYmVsOiBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPjtcbiAgcHVibGljIGJ5VHlwZU1vZGU6IEZvcm1Db250cm9sPGJvb2xlYW4+O1xuICBwdWJsaWMgZXh0ZXJuYWw6IEZvcm1Db250cm9sPGJvb2xlYW4+O1xuICBwdWJsaWMgZm9ybTogRm9ybUdyb3VwO1xuXG4gIHB1YmxpYyBmaWx0ZXI6IFBpblJlZkxvb2t1cEZpbHRlcjtcbiAgcHVibGljIHBpbkZpbHRlck9wdGlvbnM/OiBJbmRleExvb2t1cERlZmluaXRpb247XG4gIHB1YmxpYyBsb29rdXBEYXRhPzogUGluTG9va3VwRGF0YTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KCdpbmRleExvb2t1cERlZmluaXRpb25zJylcbiAgICBwcml2YXRlIF9wcmVzZXRMb29rdXBEZWZzOiBJbmRleExvb2t1cERlZmluaXRpb25zLFxuICAgIHB1YmxpYyBpdGVtTG9va3VwU2VydmljZTogSXRlbVJlZkxvb2t1cFNlcnZpY2UsXG4gICAgcHVibGljIHBpbkxvb2t1cFNlcnZpY2U6IFBpblJlZkxvb2t1cFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBfaXRlbVNlcnZpY2U6IEl0ZW1TZXJ2aWNlLFxuICAgIHByaXZhdGUgX3RoZXNTZXJ2aWNlOiBUaGVzYXVydXNTZXJ2aWNlLFxuICAgIHByaXZhdGUgX3NuYWNrYmFyOiBNYXRTbmFja0JhcixcbiAgICBmb3JtQnVpbGRlcjogRm9ybUJ1aWxkZXJcbiAgKSB7XG4gICAgdGhpcy5wYXJ0VHlwZUtleXMgPSBbXTtcbiAgICB0aGlzLml0ZW1QYXJ0cyA9IFtdO1xuICAgIHRoaXMuX3N1YnMgPSBbXTtcbiAgICB0aGlzLm1vZGVsRW50cmllcyA9IFtdO1xuICAgIC8vIHRoaXMgaXMgdGhlIGRlZmF1bHQgZmlsdGVyIGZvciB0aGUgcGluIGxvb2t1cCwgd2hpY2ggd2lsbFxuICAgIC8vIGJlIG1lcmdlZCB3aXRoIHZhbHVlcyBwcm92aWRlZCBieSB1c2VyIGhlcmVcbiAgICB0aGlzLmZpbHRlciA9IHtcbiAgICAgIHRleHQ6ICcnLFxuICAgICAgbGltaXQ6IDEwLFxuICAgIH07XG4gICAgLy8gZm9ybVxuICAgIHRoaXMuaXRlbSA9IGZvcm1CdWlsZGVyLmNvbnRyb2wobnVsbCk7XG4gICAgdGhpcy5pdGVtUGFydCA9IGZvcm1CdWlsZGVyLmNvbnRyb2wobnVsbCk7XG4gICAgdGhpcy5wYXJ0VHlwZUtleSA9IGZvcm1CdWlsZGVyLmNvbnRyb2wobnVsbCk7XG4gICAgdGhpcy5naWQgPSBmb3JtQnVpbGRlci5jb250cm9sKG51bGwsIFtcbiAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWQsXG4gICAgICBWYWxpZGF0b3JzLm1heExlbmd0aCgzMDApLFxuICAgIF0pO1xuICAgIHRoaXMubGFiZWwgPSBmb3JtQnVpbGRlci5jb250cm9sKG51bGwsIFtcbiAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWQsXG4gICAgICBWYWxpZGF0b3JzLm1heExlbmd0aCgzMDApLFxuICAgIF0pO1xuICAgIHRoaXMuYnlUeXBlTW9kZSA9IGZvcm1CdWlsZGVyLmNvbnRyb2woZmFsc2UsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XG4gICAgdGhpcy5leHRlcm5hbCA9IGZvcm1CdWlsZGVyLmNvbnRyb2woZmFsc2UsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XG4gICAgdGhpcy5mb3JtID0gZm9ybUJ1aWxkZXIuZ3JvdXAoe1xuICAgICAgaXRlbTogdGhpcy5pdGVtLFxuICAgICAgaXRlbVBhcnQ6IHRoaXMuaXRlbVBhcnQsXG4gICAgICBwYXJ0VHlwZUtleTogdGhpcy5wYXJ0VHlwZUtleSxcbiAgICAgIGdpZDogdGhpcy5naWQsXG4gICAgICBsYWJlbDogdGhpcy5sYWJlbCxcbiAgICAgIGJ5VHlwZU1vZGU6IHRoaXMuYnlUeXBlTW9kZSxcbiAgICAgIGV4dGVybmFsOiB0aGlzLmV4dGVybmFsLFxuICAgIH0pO1xuICAgIC8vIGV2ZW50c1xuICAgIHRoaXMudGFyZ2V0Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxQaW5UYXJnZXQ+KCk7XG4gICAgdGhpcy5lZGl0b3JDbG9zZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICB9XG5cbiAgcHJpdmF0ZSBmb3JjZUJ5SXRlbSgpOiB2b2lkIHtcbiAgICB0aGlzLnBpbkJ5VHlwZU1vZGUgPSBmYWxzZTtcbiAgICB0aGlzLmNhblN3aXRjaE1vZGUgPSBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXBLZXlzKCk6IHZvaWQge1xuICAgIC8vIHVzZSBESSBwcmVzZXRzIGlmIG5vIGxvb2t1cCBkZWZpbml0aW9uc1xuICAgIGlmICghdGhpcy5sb29rdXBEZWZpbml0aW9ucykge1xuICAgICAgdGhpcy5sb29rdXBEZWZpbml0aW9ucyA9IHRoaXMuX3ByZXNldExvb2t1cERlZnM7XG4gICAgfVxuICAgIC8vIGtleXMgYXJlIGFsbCB0aGUgZGVmaW5lZCBsb29rdXAgc2VhcmNoZXNcbiAgICB0aGlzLnBhcnRUeXBlS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMubG9va3VwRGVmaW5pdGlvbnMpO1xuXG4gICAgLy8gaWYgbm8ga2V5cywgZ2V0IHRoZW0gZnJvbSB0aGVzYXVydXMgbW9kZWwtdHlwZXM7XG4gICAgLy8gaWYgdGhpcyBpcyBub3QgYXZhaWxhYmxlLCBqdXN0IGZvcmNlIGJ5IGl0ZW0gbW9kZS5cbiAgICBpZiAoIXRoaXMucGFydFR5cGVLZXlzLmxlbmd0aCkge1xuICAgICAgaWYgKHRoaXMubW9kZWxFbnRyaWVzPy5sZW5ndGgpIHtcbiAgICAgICAgLy8gc2V0IGxvb2t1cERlZmluaXRpb25zIGZyb20gdGhlc2F1cnVzIGVudHJpZXNcbiAgICAgICAgdGhpcy5sb29rdXBEZWZpbml0aW9ucyA9IHt9O1xuICAgICAgICB0aGlzLm1vZGVsRW50cmllcy5mb3JFYWNoKChlKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb29rdXBEZWZpbml0aW9ucyFbZS52YWx1ZV0gPSB7XG4gICAgICAgICAgICBuYW1lOiBlLnZhbHVlLFxuICAgICAgICAgICAgdHlwZUlkOiBlLmlkLFxuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBzZXQgdHlwZSBrZXlzIGZyb20gdGhlc2F1cnVzIGVudHJpZXNcbiAgICAgICAgdGhpcy5wYXJ0VHlwZUtleXMgPSB0aGlzLm1vZGVsRW50cmllcy5tYXAoKGUpID0+IGUudmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGlmIHN0aWxsIG5vIGtleXMsIGZvcmNlIGJ5IGl0ZW0gbW9kZVxuICAgIGlmICghdGhpcy5wYXJ0VHlwZUtleXMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmZvcmNlQnlJdGVtKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGlmIHRoZXJlIGlzIG9ubHkgb25lIGtleSwgc2V0IGl0IGFzIHRoZSBkZWZhdWx0XG4gICAgICBpZiAodGhpcy5wYXJ0VHlwZUtleXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHRoaXMucGFydFR5cGVLZXkuc2V0VmFsdWUodGhpcy5wYXJ0VHlwZUtleXNbMF0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2FuQnVpbGRHaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICghdGhpcy5leHRlcm5hbC52YWx1ZSAmJiAhdGhpcy5naWQudmFsdWUpIHx8IHRoaXMuZ2lkLnByaXN0aW5lO1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5CdWlsZExhYmVsKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoIXRoaXMuZXh0ZXJuYWwudmFsdWUgJiYgIXRoaXMubGFiZWwudmFsdWUpIHx8IHRoaXMubGFiZWwucHJpc3RpbmU7XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgLy8gc2V0IHN0YXJ0IG1vZGUgaWYgcmVxdWlyZWRcbiAgICBpZiAodGhpcy5fc3RhcnRXaXRoQnlUeXBlTW9kZSkge1xuICAgICAgdGhpcy5ieVR5cGVNb2RlLnNldFZhbHVlKHRydWUpO1xuICAgIH1cblxuICAgIC8vIHdoZW5ldmVyIGl0ZW0gY2hhbmdlcywgdXBkYXRlIGl0ZW0ncyBwYXJ0cyBhbmQgZmlsdGVyXG4gICAgdGhpcy5fc3Vicy5wdXNoKFxuICAgICAgdGhpcy5pdGVtLnZhbHVlQ2hhbmdlc1xuICAgICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLCBkZWJvdW5jZVRpbWUoMzAwKSlcbiAgICAgICAgLnN1YnNjcmliZSgoaXRlbSkgPT4ge1xuICAgICAgICAgIHRoaXMuaXRlbVBhcnQuc2V0VmFsdWUobnVsbCk7XG4gICAgICAgICAgdGhpcy5pdGVtUGFydHMgPSBpdGVtPy5wYXJ0cyB8fCBbXTtcbiAgICAgICAgICB0aGlzLmZpbHRlciA9IHtcbiAgICAgICAgICAgIC4uLnRoaXMuZmlsdGVyLFxuICAgICAgICAgICAgaXRlbUlkOiBpdGVtPy5pZCxcbiAgICAgICAgICB9O1xuICAgICAgICB9KVxuICAgICk7XG5cbiAgICAvLyB3aGVuZXZlciBpdGVtUGFydCBjaGFuZ2VzLCB1cGRhdGUgdGFyZ2V0IGFuZCBldmVudHVhbGx5IGdpZFxuICAgIHRoaXMuX3N1YnMucHVzaChcbiAgICAgIHRoaXMuaXRlbVBhcnQudmFsdWVDaGFuZ2VzXG4gICAgICAgIC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksIGRlYm91bmNlVGltZSgzMDApKVxuICAgICAgICAuc3Vic2NyaWJlKChwYXJ0KSA9PiB7XG4gICAgICAgICAgaWYgKCF0aGlzLmdpZC52YWx1ZSB8fCB0aGlzLmdpZC5wcmlzdGluZSkge1xuICAgICAgICAgICAgdGhpcy5naWQuc2V0VmFsdWUodGhpcy5idWlsZEdpZCgpKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5maWx0ZXIgPSB7XG4gICAgICAgICAgICAuLi50aGlzLmZpbHRlcixcbiAgICAgICAgICAgIHBhcnRJZDogcGFydD8uaWQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLnVwZGF0ZVRhcmdldCgpO1xuICAgICAgICB9KVxuICAgICk7XG5cbiAgICAvLyB3aGVuZXZlciBwYXJ0VHlwZUtleSBjaGFuZ2VzLCB1cGRhdGUgZmlsdGVyJ3Mgb3B0aW9uc1xuICAgIHRoaXMuX3N1YnMucHVzaChcbiAgICAgIHRoaXMucGFydFR5cGVLZXkudmFsdWVDaGFuZ2VzXG4gICAgICAgIC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksIGRlYm91bmNlVGltZSgzMDApKVxuICAgICAgICAuc3Vic2NyaWJlKChrZXkpID0+IHtcbiAgICAgICAgICB0aGlzLnBpbkZpbHRlck9wdGlvbnMgPSBrZXlcbiAgICAgICAgICAgID8gdGhpcy5sb29rdXBEZWZpbml0aW9ucyFba2V5XVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIH0pXG4gICAgKTtcblxuICAgIC8vIGxvYWQgbW9kZWwtdHlwZXMgdGhlc2F1cnVzIGVudHJpZXNcbiAgICB0aGlzLl90aGVzU2VydmljZS5nZXRUaGVzYXVydXMoJ21vZGVsLXR5cGVzJywgdHJ1ZSkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6ICh0KSA9PiB7XG4gICAgICAgIHRoaXMubW9kZWxFbnRyaWVzID0gdC5lbnRyaWVzIHx8IFtdO1xuICAgICAgICBpZiAodGhpcy5tb2RlbEVudHJpZXM/Lmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMuc2V0dXBLZXlzKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5mb3JjZUJ5SXRlbSgpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZXJyb3I6ICgpID0+IHtcbiAgICAgICAgdGhpcy5mb3JjZUJ5SXRlbSgpO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX3N1YnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuX3N1YnNbaV0udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkR2lkKCk6IHN0cmluZyB8IG51bGwge1xuICAgIC8vIHRoZSBHSUQgaXMgdGhlIHBhcnQgSUQgaWYgYW55LCBvciB0aGUgaXRlbSBJRCwgZm9sbG93ZWQgYnlcbiAgICAvLyB0aGUgcGluJ3MgdmFsdWUgKD1FSUQpXG4gICAgY29uc3QgcGluID0gdGhpcy5sb29rdXBEYXRhPy5waW47XG4gICAgaWYgKCFwaW4pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gcGluLnBhcnRJZFxuICAgICAgPyBgUCR7cGluLnBhcnRJZH0vJHtwaW4udmFsdWV9YFxuICAgICAgOiBgSSR7cGluLml0ZW1JZH0vJHtwaW4udmFsdWV9YDtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRMYWJlbCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBpZiAoIXRoaXMubG9va3VwRGF0YT8ucGluKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3Qgc2I6IHN0cmluZ1tdID0gW107XG4gICAgLy8gcGluIHZhbHVlXG4gICAgc2IucHVzaCh0aGlzLmxvb2t1cERhdGEucGluLnZhbHVlISk7XG4gICAgLy8gaXRlbSB0aXRsZVxuICAgIHNiLnB1c2goJyB8ICcpO1xuICAgIHNiLnB1c2godGhpcy5sb29rdXBEYXRhLml0ZW0hLnRpdGxlIHx8IHRoaXMubG9va3VwRGF0YS5pdGVtIS5pZCk7XG4gICAgLy8gcGFydCB0eXBlIGFuZCByb2xlXG4gICAgY29uc3QgZSA9IHRoaXMubW9kZWxFbnRyaWVzPy5maW5kKFxuICAgICAgKGUpID0+IGUuaWQgPT09IHRoaXMubG9va3VwRGF0YSEucGluLnBhcnRUeXBlSWRcbiAgICApO1xuICAgIHNiLnB1c2goJyAoJyk7XG4gICAgc2IucHVzaChlPy52YWx1ZSB8fCB0aGlzLmxvb2t1cERhdGEucGluLnBhcnRUeXBlSWQpO1xuICAgIGlmICh0aGlzLmxvb2t1cERhdGEucGluLnJvbGVJZCkge1xuICAgICAgc2IucHVzaChgLCAke3RoaXMubG9va3VwRGF0YS5waW4ucm9sZUlkfWApO1xuICAgIH1cbiAgICBzYi5wdXNoKCcpJyk7XG4gICAgcmV0dXJuIHNiLmpvaW4oJycpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUYXJnZXQoKTogUGluVGFyZ2V0IHtcbiAgICBpZiAodGhpcy5leHRlcm5hbC52YWx1ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZ2lkOiB0aGlzLmdpZC52YWx1ZSB8fCAnJyxcbiAgICAgICAgbGFiZWw6IHRoaXMubGFiZWwudmFsdWUgfHwgJycsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBwaW4gPSB0aGlzLmxvb2t1cERhdGE/LnBpbjtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGl0ZW1JZDogcGluPy5pdGVtSWQgfHwgJycsXG4gICAgICAgIHBhcnRJZDogcGluPy5wYXJ0SWQgfHwgJycsXG4gICAgICAgIHBhcnRUeXBlSWQ6IHBpbj8ucGFydFR5cGVJZCB8fCAnJyxcbiAgICAgICAgcm9sZUlkOiBwaW4/LnJvbGVJZCB8fCAnJyxcbiAgICAgICAgbmFtZTogcGluPy5uYW1lIHx8ICcnLFxuICAgICAgICB2YWx1ZTogcGluPy52YWx1ZSB8fCAnJyxcbiAgICAgICAgZ2lkOiBwaW4/LnZhbHVlIHx8ICcnLFxuICAgICAgICBsYWJlbDogcGluPy52YWx1ZSB8fCAnJyxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVUYXJnZXQoKTogdm9pZCB7XG4gICAgdGhpcy5fbm9Gb3JtVXBkYXRlID0gdHJ1ZTtcblxuICAgIGlmICh0aGlzLmNhbkJ1aWxkR2lkKCkpIHtcbiAgICAgIHRoaXMuZ2lkLnNldFZhbHVlKHRoaXMuYnVpbGRHaWQoKSk7XG4gICAgICB0aGlzLmdpZC5tYXJrQXNEaXJ0eSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5jYW5CdWlsZExhYmVsKCkpIHtcbiAgICAgIHRoaXMubGFiZWwuc2V0VmFsdWUodGhpcy5idWlsZExhYmVsKCkpO1xuICAgICAgdGhpcy5sYWJlbC5tYXJrQXNEaXJ0eSgpO1xuICAgIH1cbiAgICB0aGlzLnRhcmdldCA9IHRoaXMuZ2V0VGFyZ2V0KCk7XG5cbiAgICB0aGlzLl9ub0Zvcm1VcGRhdGUgPSBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlRm9ybSh0YXJnZXQ/OiBQaW5UYXJnZXQpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fbm9Gb3JtVXBkYXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIGJ1aWxkIHBpbiBpbmZvIGZyb20gdGFyZ2V0XG4gICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgIHRoaXMubG9va3VwRGF0YSA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMuZm9ybS5yZXNldCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmV4dGVybmFsLnNldFZhbHVlKCF0YXJnZXQubmFtZSk7XG4gICAgdGhpcy5sb29rdXBEYXRhID0ge1xuICAgICAgcGluOiB7XG4gICAgICAgIGl0ZW1JZDogdGFyZ2V0Lml0ZW1JZCB8fCAnJyxcbiAgICAgICAgcGFydElkOiB0YXJnZXQucGFydElkIHx8ICcnLFxuICAgICAgICBwYXJ0VHlwZUlkOiB0YXJnZXQucGFydFR5cGVJZCB8fCAnJyxcbiAgICAgICAgcm9sZUlkOiB0YXJnZXQucm9sZUlkIHx8ICcnLFxuICAgICAgICBuYW1lOiB0YXJnZXQubmFtZSB8fCAnJyxcbiAgICAgICAgdmFsdWU6IHRhcmdldC52YWx1ZSB8fCAnJyxcbiAgICAgIH0sXG4gICAgfTtcbiAgICAvLyBnZXQgaXRlbVxuICAgIGlmICh0YXJnZXQuaXRlbUlkKSB7XG4gICAgICB0aGlzLl9pdGVtU2VydmljZS5nZXRJdGVtKHRhcmdldC5pdGVtSWQsIHRydWUpLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChpdGVtKSA9PiB7XG4gICAgICAgICAgdGhpcy5pdGVtLnNldFZhbHVlKGl0ZW0pO1xuICAgICAgICAgIHRoaXMuZm9ybS5tYXJrQXNQcmlzdGluZSgpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIHRoZSBpdGVtIGxvb2t1cCBjaGFuZ2VzIChpdGVtIGlzIGxvb2tlZCB1cFxuICAgKiBieSBpdHMgdGl0bGUpLlxuICAgKlxuICAgKiBAcGFyYW0gaXRlbSBUaGUgaXRlbSBnb3QgZnJvbSBsb29rdXAuXG4gICAqL1xuICBwdWJsaWMgb25JdGVtTG9va3VwQ2hhbmdlKGl0ZW06IEl0ZW0pOiB2b2lkIHtcbiAgICAvLyBsb2FkIGl0ZW0ncyBwYXJ0c1xuICAgIHRoaXMuX2l0ZW1TZXJ2aWNlLmdldEl0ZW0oaXRlbS5pZCwgdHJ1ZSkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IChpKSA9PiB7XG4gICAgICAgIC8vIHNldHRpbmcgdGhlIGl0ZW0gd2lsbCB0cmlnZ2VyIGl0cyBwYXJ0cyB1cGRhdGVcbiAgICAgICAgdGhpcy5pdGVtLnNldFZhbHVlKGkpO1xuICAgICAgICB0aGlzLnVwZGF0ZVRhcmdldCgpO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaXRlbVBhcnQuc2V0VmFsdWUobnVsbCk7XG4gICAgICAgIHRoaXMuaXRlbVBhcnRzID0gW107XG4gICAgICAgIHRoaXMudXBkYXRlVGFyZ2V0KCk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBsb2FkSXRlbUluZm8ocGluOiBEYXRhUGluSW5mbyk6IHZvaWQge1xuICAgIGZvcmtKb2luKHtcbiAgICAgIGl0ZW06IHRoaXMuX2l0ZW1TZXJ2aWNlLmdldEl0ZW0ocGluLml0ZW1JZCwgZmFsc2UpLFxuICAgICAgcGFydDogdGhpcy5faXRlbVNlcnZpY2UuZ2V0UGFydEZyb21UeXBlQW5kUm9sZShcbiAgICAgICAgcGluLml0ZW1JZCxcbiAgICAgICAgTUVUQURBVEFfUEFSVF9JRFxuICAgICAgKSxcbiAgICB9KVxuICAgICAgLnBpcGUodGFrZSgxKSlcbiAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiAocmVzdWx0KSA9PiB7XG4gICAgICAgICAgdGhpcy5sb29rdXBEYXRhID0ge1xuICAgICAgICAgICAgcGluOiBwaW4sXG4gICAgICAgICAgICBpdGVtOiByZXN1bHQuaXRlbSxcbiAgICAgICAgICAgIG1ldGFQYXJ0OiByZXN1bHQucGFydCBhcyBNZXRhZGF0YVBhcnQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLnVwZGF0ZVRhcmdldCgpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb29rdXBEYXRhID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICBlcnJvciA/IEpTT04uc3RyaW5naWZ5KGVycm9yKSA6ICdFcnJvciBsb2FkaW5nIGl0ZW0vbWV0YWRhdGEnXG4gICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIHRoZSBwaW4gbG9va3VwIGNoYW5nZS4gQSBwaW4gaXMgbG9va2VkIHVwIGJ5IGl0c1xuICAgKiBuYW1lIGFuZCB2YWx1ZSAoPXRoZSBmaWx0ZXIncyB0ZXh0KSwgYW5kIG9wdGlvbmFsbHkgYnk6XG4gICAqIC0gaXRzIGluZGV4IGxvb2t1cCBkZWZpbml0aW9uIChzZWxlY3RlZCBieSBwYXJ0VHlwZUtleSkuXG4gICAqIC0gaXRzIGl0ZW0gKGRlZmluZWQgYnkgaXRlbSwgaW4gZmlsdGVyKS5cbiAgICogLSBpdHMgcGFydCAoZGVmaW5lZCBieSBpdGVtUGFydCwgaW4gZmlsdGVyKS5cbiAgICpcbiAgICogQHBhcmFtIGluZm8gVGhlIHBpbiBpbmZvIGZyb20gcGluIGxvb2t1cC5cbiAgICovXG4gIHB1YmxpYyBvblBpbkxvb2t1cENoYW5nZShpbmZvOiBEYXRhUGluSW5mbyk6IHZvaWQge1xuICAgIHRoaXMubG9hZEl0ZW1JbmZvKGluZm8pO1xuICB9XG5cbiAgcHVibGljIG9uQ29waWVkKCk6IHZvaWQge1xuICAgIHRoaXMuX3NuYWNrYmFyLm9wZW4oJ0NvcGllZCB0byBjbGlwYm9hcmQnLCAnT0snLCB7XG4gICAgICBkdXJhdGlvbjogMTUwMCxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBjbG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLmVkaXRvckNsb3NlLmVtaXQoKTtcbiAgfVxuXG4gIHB1YmxpYyBzYXZlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmZvcm0uaW52YWxpZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl90YXJnZXQgPSB0aGlzLmdldFRhcmdldCgpO1xuICAgIHRoaXMudGFyZ2V0Q2hhbmdlLmVtaXQodGhpcy5fdGFyZ2V0KTtcbiAgfVxufVxuIiwiPGZvcm0gW2Zvcm1Hcm91cF09XCJmb3JtXCIgKHN1Ym1pdCk9XCJzYXZlKClcIj5cclxuICA8IS0tIGV4dGVybmFsIC0tPlxyXG4gIDxtYXQtY2hlY2tib3ggW2Zvcm1Db250cm9sXT1cImV4dGVybmFsXCI+ZXh0ZXJuYWw8L21hdC1jaGVja2JveD5cclxuXHJcbiAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICA8IS0tIGxhYmVsIC0tPlxyXG4gICAgPGRpdj5cclxuICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiZXh0ZXJuYWwudmFsdWUgfHwgY2FuRWRpdFRhcmdldFwiPlxyXG4gICAgICAgIDxtYXQtbGFiZWw+bGFiZWw8L21hdC1sYWJlbD5cclxuICAgICAgICA8aW5wdXQgbWF0SW5wdXQgW2Zvcm1Db250cm9sXT1cImxhYmVsXCIgLz5cclxuICAgICAgICA8bWF0LWVycm9yXHJcbiAgICAgICAgICAqbmdJZj1cIiRhbnkobGFiZWwpLmVycm9ycz8ucmVxdWlyZWQgJiYgKGxhYmVsLmRpcnR5IHx8IGxhYmVsLnRvdWNoZWQpXCJcclxuICAgICAgICAgID5sYWJlbCByZXF1aXJlZDwvbWF0LWVycm9yXHJcbiAgICAgICAgPlxyXG4gICAgICAgIDxtYXQtZXJyb3JcclxuICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICRhbnkobGFiZWwpLmVycm9ycz8ubWF4TGVuZ3RoICYmIChsYWJlbC5kaXJ0eSB8fCBsYWJlbC50b3VjaGVkKVxyXG4gICAgICAgICAgXCJcclxuICAgICAgICAgID5sYWJlbCB0b28gbG9uZzwvbWF0LWVycm9yXHJcbiAgICAgICAgPlxyXG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICA8ZGl2XHJcbiAgICAgICAgKm5nSWY9XCIhZXh0ZXJuYWwudmFsdWUgJiYgIWNhbkVkaXRUYXJnZXQgJiYgbGFiZWwudmFsdWVcIlxyXG4gICAgICAgIGNsYXNzPVwiaW5mb1wiXHJcbiAgICAgID5cclxuICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsXCI+bGFiZWw8L3NwYW4+e3sgbGFiZWwudmFsdWUgfX1cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIGdpZCAtLT5cclxuICAgIDxkaXY+XHJcbiAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cImV4dGVybmFsLnZhbHVlIHx8IGNhbkVkaXRUYXJnZXRcIj5cclxuICAgICAgICA8bWF0LWxhYmVsPkdJRDwvbWF0LWxhYmVsPlxyXG4gICAgICAgIDxpbnB1dCBtYXRJbnB1dCBbZm9ybUNvbnRyb2xdPVwiZ2lkXCIgLz5cclxuICAgICAgICA8bWF0LWVycm9yXHJcbiAgICAgICAgICAqbmdJZj1cIiRhbnkoZ2lkKS5lcnJvcnM/LnJlcXVpcmVkICYmIChnaWQuZGlydHkgfHwgZ2lkLnRvdWNoZWQpXCJcclxuICAgICAgICAgID5HSUQgcmVxdWlyZWQ8L21hdC1lcnJvclxyXG4gICAgICAgID5cclxuICAgICAgICA8bWF0LWVycm9yXHJcbiAgICAgICAgICAqbmdJZj1cIiRhbnkoZ2lkKS5lcnJvcnM/Lm1heExlbmd0aCAmJiAoZ2lkLmRpcnR5IHx8IGdpZC50b3VjaGVkKVwiXHJcbiAgICAgICAgICA+R0lEIHRvbyBsb25nPC9tYXQtZXJyb3JcclxuICAgICAgICA+XHJcbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgIDxkaXYgKm5nSWY9XCIhZXh0ZXJuYWwudmFsdWUgJiYgIWNhbkVkaXRUYXJnZXQgJiYgZ2lkLnZhbHVlXCIgY2xhc3M9XCJpbmZvXCI+XHJcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJsYWJlbFwiPkdJRDwvc3Bhbj4gPHNwYW4gY2xhc3M9XCJnaWRcIj57eyBnaWQudmFsdWUgfX08L3NwYW4+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcblxyXG4gIDwhLS0gQlkgSVRFTSAtLT5cclxuICA8ZGl2ICpuZ0lmPVwiIWV4dGVybmFsLnZhbHVlXCI+XHJcbiAgICA8ZmllbGRzZXQgKm5nSWY9XCIhYnlUeXBlTW9kZS52YWx1ZVwiIGNsYXNzPVwiZm9ybS1yb3dcIj5cclxuICAgICAgPGxlZ2VuZD5waW4gZmlsdGVyczwvbGVnZW5kPlxyXG4gICAgICA8IS0tIGl0ZW0gZmlsdGVyIC0tPlxyXG4gICAgICA8Y2FkbXVzLXJlZi1sb29rdXBcclxuICAgICAgICBbc2VydmljZV09XCJpdGVtTG9va3VwU2VydmljZVwiXHJcbiAgICAgICAgbGFiZWw9XCJpdGVtXCJcclxuICAgICAgICAoaXRlbUNoYW5nZSk9XCJvbkl0ZW1Mb29rdXBDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgID48L2NhZG11cy1yZWYtbG9va3VwPlxyXG5cclxuICAgICAgPCEtLSBwYXJ0IGZpbHRlciAtLT5cclxuICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiaXRlbVBhcnRzLmxlbmd0aFwiPlxyXG4gICAgICAgIDxtYXQtbGFiZWw+cGFydDwvbWF0LWxhYmVsPlxyXG4gICAgICAgIDxtYXQtc2VsZWN0IFtmb3JtQ29udHJvbF09XCJpdGVtUGFydFwiPlxyXG4gICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIm51bGxcIj4oYW55KTwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgIDxtYXQtb3B0aW9uICpuZ0Zvcj1cImxldCBwIG9mIGl0ZW1QYXJ0c1wiIFt2YWx1ZV09XCJwXCI+e3tcclxuICAgICAgICAgICAgcC50eXBlSWQgfCBmbGF0TG9va3VwIDogbW9kZWxFbnRyaWVzIDogXCJpZFwiIDogXCJ2YWx1ZVwiXHJcbiAgICAgICAgICB9fTwvbWF0LW9wdGlvbj5cclxuICAgICAgICA8L21hdC1zZWxlY3Q+XHJcbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICA8L2ZpZWxkc2V0PlxyXG5cclxuICAgIDwhLS0gQlkgVFlQRSAtLT5cclxuICAgIDxkaXYgKm5nSWY9XCJieVR5cGVNb2RlLnZhbHVlXCI+XHJcbiAgICAgIDwhLS0gcGFyIHR5cGUgZmlsdGVyIC0tPlxyXG4gICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJwYXJ0VHlwZUtleXM/Lmxlbmd0aFwiPlxyXG4gICAgICAgIDxtYXQtbGFiZWw+cGFydCB0eXBlPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgPG1hdC1zZWxlY3QgW2Zvcm1Db250cm9sXT1cInBhcnRUeXBlS2V5XCI+XHJcbiAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgayBvZiBwYXJ0VHlwZUtleXNcIiBbdmFsdWVdPVwia1wiPnt7XHJcbiAgICAgICAgICAgIGtcclxuICAgICAgICAgIH19PC9tYXQtb3B0aW9uPlxyXG4gICAgICAgIDwvbWF0LXNlbGVjdD5cclxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDwhLS0gUElOIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICAgIDwhLS0gcGluIGxvb2t1cCAtLT5cclxuICAgICAgPGNhZG11cy1yZWYtbG9va3VwXHJcbiAgICAgICAgW3NlcnZpY2VdPVwicGluTG9va3VwU2VydmljZVwiXHJcbiAgICAgICAgW2Jhc2VGaWx0ZXJdPVwiZmlsdGVyXCJcclxuICAgICAgICBbb3B0aW9uc109XCJwaW5GaWx0ZXJPcHRpb25zXCJcclxuICAgICAgICBsYWJlbD1cInBpblwiXHJcbiAgICAgICAgKGl0ZW1DaGFuZ2UpPVwib25QaW5Mb29rdXBDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgID48L2NhZG11cy1yZWYtbG9va3VwPlxyXG4gICAgICA8IS0tIG1vZGUgc3dpdGNoZXIgLS0+XHJcbiAgICAgIDxkaXY+XHJcbiAgICAgICAgPG1hdC1jaGVja2JveCBbZm9ybUNvbnRyb2xdPVwiYnlUeXBlTW9kZVwiICpuZ0lmPVwiY2FuU3dpdGNoTW9kZVwiPlxyXG4gICAgICAgICAgYnkgdHlwZTwvbWF0LWNoZWNrYm94XHJcbiAgICAgICAgPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDwhLS0gZGF0YSAtLT5cclxuICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsIGlkPVwiZGF0YVwiICpuZ0lmPVwibG9va3VwRGF0YT8ucGluPy5uYW1lXCI+XHJcbiAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5waW4gZGF0YTwvbWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XHJcbiAgICAgIDwhLS0gdGFibGUgLS0+XHJcbiAgICAgIDx0YWJsZT5cclxuICAgICAgICA8dGhlYWQ+XHJcbiAgICAgICAgICA8dGg+PC90aD5cclxuICAgICAgICAgIDx0aD5zb3VyY2U8L3RoPlxyXG4gICAgICAgICAgPHRoPnZhbHVlPC90aD5cclxuICAgICAgICA8L3RoZWFkPlxyXG4gICAgICAgIDx0Ym9keT5cclxuICAgICAgICAgIDwhLS0gcGluIC0tPlxyXG4gICAgICAgICAgPHRyICpuZ0lmPVwibG9va3VwRGF0YT8ucGluPy52YWx1ZVwiPlxyXG4gICAgICAgICAgICA8dGQ+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICBbY2RrQ29weVRvQ2xpcGJvYXJkXT1cImxvb2t1cERhdGEhLnBpbiEudmFsdWVcIlxyXG4gICAgICAgICAgICAgICAgKGNka0NvcHlUb0NsaXBib2FyZENvcGllZCk9XCJvbkNvcGllZCgpXCJcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8bWF0LWljb24+Y29udGVudF9jb3B5PC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPHRkPnBpbjwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZD57eyBsb29rdXBEYXRhIS5waW4udmFsdWUgfX08L3RkPlxyXG4gICAgICAgICAgPC90cj5cclxuICAgICAgICAgIDwhLS0gaXRlbSBJRCAtLT5cclxuICAgICAgICAgIDx0ciAqbmdJZj1cImxvb2t1cERhdGE/LnBpbj8uaXRlbUlkXCI+XHJcbiAgICAgICAgICAgIDx0ZD5cclxuICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxyXG4gICAgICAgICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgICAgICAgICAgIFtjZGtDb3B5VG9DbGlwYm9hcmRdPVwibG9va3VwRGF0YSEucGluIS5pdGVtSWRcIlxyXG4gICAgICAgICAgICAgICAgKGNka0NvcHlUb0NsaXBib2FyZENvcGllZCk9XCJvbkNvcGllZCgpXCJcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8bWF0LWljb24+Y29udGVudF9jb3B5PC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPHRkPml0ZW0gSUQ8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+e3sgbG9va3VwRGF0YSEucGluLml0ZW1JZCB9fTwvdGQ+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgPCEtLSBpdGVtIHRpdGxlIC0tPlxyXG4gICAgICAgICAgPHRyICpuZ0lmPVwibG9va3VwRGF0YT8uaXRlbT8udGl0bGVcIj5cclxuICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgW2Nka0NvcHlUb0NsaXBib2FyZF09XCJsb29rdXBEYXRhIS5pdGVtIS50aXRsZVwiXHJcbiAgICAgICAgICAgICAgICAoY2RrQ29weVRvQ2xpcGJvYXJkQ29waWVkKT1cIm9uQ29waWVkKClcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jb250ZW50X2NvcHk8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+aXRlbSB0aXRsZTwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZD57eyBsb29rdXBEYXRhIS5pdGVtIS50aXRsZSB9fTwvdGQ+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgPCEtLSBwYXJ0IElEIC0tPlxyXG4gICAgICAgICAgPHRyICpuZ0lmPVwibG9va3VwRGF0YT8ucGluPy5wYXJ0SWRcIj5cclxuICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgW2Nka0NvcHlUb0NsaXBib2FyZF09XCJsb29rdXBEYXRhIS5waW4hLnBhcnRJZFwiXHJcbiAgICAgICAgICAgICAgICAoY2RrQ29weVRvQ2xpcGJvYXJkQ29waWVkKT1cIm9uQ29waWVkKClcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jb250ZW50X2NvcHk8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+cGFydCBJRDwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZD57eyBsb29rdXBEYXRhIS5waW4ucGFydElkIH19PC90ZD5cclxuICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICA8IS0tIHBhcnQgdHlwZSBJRCAtLT5cclxuICAgICAgICAgIDx0ciAqbmdJZj1cImxvb2t1cERhdGE/LnBpbj8ucGFydFR5cGVJZFwiPlxyXG4gICAgICAgICAgICA8dGQ+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICBbY2RrQ29weVRvQ2xpcGJvYXJkXT1cImxvb2t1cERhdGEhLnBpbiEucGFydFR5cGVJZFwiXHJcbiAgICAgICAgICAgICAgICAoY2RrQ29weVRvQ2xpcGJvYXJkQ29waWVkKT1cIm9uQ29waWVkKClcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jb250ZW50X2NvcHk8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+cGFydCB0eXBlIElEPC90ZD5cclxuICAgICAgICAgICAgPHRkPnt7IGxvb2t1cERhdGEhLnBpbiEucGFydFR5cGVJZCB9fTwvdGQ+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgPCEtLSBwYXJ0IHJvbGUgSUQgLS0+XHJcbiAgICAgICAgICA8dHIgKm5nSWY9XCJsb29rdXBEYXRhPy5waW4/LnJvbGVJZFwiPlxyXG4gICAgICAgICAgICA8dGQ+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICBbY2RrQ29weVRvQ2xpcGJvYXJkXT1cImxvb2t1cERhdGEhLnBpbiEucm9sZUlkIVwiXHJcbiAgICAgICAgICAgICAgICAoY2RrQ29weVRvQ2xpcGJvYXJkQ29waWVkKT1cIm9uQ29waWVkKClcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jb250ZW50X2NvcHk8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+cGFydCByb2xlIElEPC90ZD5cclxuICAgICAgICAgICAgPHRkPnt7IGxvb2t1cERhdGEhLnBpbiEucm9sZUlkIH19PC90ZD5cclxuICAgICAgICAgIDwvdHI+XHJcblxyXG4gICAgICAgICAgPCEtLSBwYXJ0J3MgbWV0YWRhdGEgLS0+XHJcbiAgICAgICAgICA8dHJcclxuICAgICAgICAgICAgKm5nRm9yPVwiXHJcbiAgICAgICAgICAgICAgbGV0IG0gb2YgbG9va3VwRGF0YT8ubWV0YVBhcnQ/Lm1ldGFkYXRhIHx8IFtdO1xyXG4gICAgICAgICAgICAgIGxldCBpID0gaW5kZXhcclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgW2Nka0NvcHlUb0NsaXBib2FyZF09XCJtLnZhbHVlXCJcclxuICAgICAgICAgICAgICAgIChjZGtDb3B5VG9DbGlwYm9hcmRDb3BpZWQpPVwib25Db3BpZWQoKVwiXHJcbiAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmNvbnRlbnRfY29weTwvbWF0LWljb24+XHJcbiAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZCBjbGFzcz1cIm1ldGFkYXRhXCI+e3sgbS5uYW1lIH19PC90ZD5cclxuICAgICAgICAgICAgPHRkIGNsYXNzPVwibWV0YWRhdGFcIj57eyBtLnZhbHVlIH19PC90ZD5cclxuICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgPC90Ym9keT5cclxuICAgICAgPC90YWJsZT5cclxuICAgIDwvbWF0LWV4cGFuc2lvbi1wYW5lbD5cclxuICA8L2Rpdj5cclxuXHJcbiAgPCEtLSBidXR0b25zIC0tPlxyXG4gIDxkaXY+XHJcbiAgICA8YnV0dG9uIG1hdC1mbGF0LWJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cImNsb3NlKClcIj5cclxuICAgICAgPG1hdC1pY29uIGNvbG9yPVwid2FyblwiPmNsb3NlPC9tYXQtaWNvbj5cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgPGJ1dHRvbiBtYXQtZmxhdC1idXR0b24gdHlwZT1cInN1Ym1pdFwiIFtkaXNhYmxlZF09XCJmb3JtLmludmFsaWRcIj5cclxuICAgICAgPG1hdC1pY29uIGNvbG9yPVwicHJpbWFyeVwiPmNoZWNrX2NpcmNsZTwvbWF0LWljb24+IHRhcmdldFxyXG4gICAgPC9idXR0b24+XHJcbiAgPC9kaXY+XHJcbjwvZm9ybT5cclxuIl19