@huntsman-cancer-institute/cod 16.0.1 → 17.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/cod.module.d.ts +30 -31
  2. package/components/attribute-absolute.component.d.ts +28 -28
  3. package/components/attribute-base.d.ts +135 -135
  4. package/components/attribute-container.component.d.ts +50 -50
  5. package/components/attribute-default.component.d.ts +20 -20
  6. package/components/attribute-edit.component.d.ts +15 -15
  7. package/components/attribute-flex.component.d.ts +25 -25
  8. package/date/date-util.d.ts +9 -9
  9. package/esm2022/cod.module.mjs +114 -119
  10. package/esm2022/components/attribute-absolute.component.mjs +104 -104
  11. package/esm2022/components/attribute-base.mjs +564 -564
  12. package/esm2022/components/attribute-container.component.mjs +155 -155
  13. package/esm2022/components/attribute-default.component.mjs +63 -63
  14. package/esm2022/components/attribute-edit.component.mjs +33 -33
  15. package/esm2022/components/attribute-flex.component.mjs +58 -58
  16. package/esm2022/date/date-util.mjs +59 -59
  17. package/esm2022/huntsman-cancer-institute-cod.mjs +4 -4
  18. package/esm2022/index.mjs +20 -21
  19. package/esm2022/model/attribute-choice.entity.mjs +1 -1
  20. package/esm2022/model/attribute-configuration.dto.mjs +1 -1
  21. package/esm2022/model/attribute-configuration.entity.mjs +1 -1
  22. package/esm2022/model/attribute-container.entity.mjs +1 -1
  23. package/esm2022/model/attribute-dictionary.entity.mjs +1 -1
  24. package/esm2022/model/attribute-long-text.entity.mjs +1 -1
  25. package/esm2022/model/attribute-value-grid-row.entity.mjs +1 -1
  26. package/esm2022/model/attribute-value-set.entity.mjs +1 -1
  27. package/esm2022/model/attribute-value.entity.mjs +2 -2
  28. package/esm2022/model/attribute.entity.mjs +1 -1
  29. package/esm2022/model/dictionary-entries.dto.mjs +2 -2
  30. package/esm2022/model/extractable-field-status.entity.mjs +1 -1
  31. package/esm2022/model/graphical-attribute.entity.mjs +1 -1
  32. package/esm2022/model/pre-eval.dto.mjs +2 -2
  33. package/esm2022/pipes/is-group-attribute.pipe.mjs +32 -32
  34. package/esm2022/services/attribute.service.mjs +1211 -1211
  35. package/fesm2022/huntsman-cancer-institute-cod.mjs +2289 -2542
  36. package/fesm2022/huntsman-cancer-institute-cod.mjs.map +1 -1
  37. package/index.d.ts +26 -27
  38. package/model/attribute-choice.entity.d.ts +16 -16
  39. package/model/attribute-configuration.dto.d.ts +13 -13
  40. package/model/attribute-configuration.entity.d.ts +12 -12
  41. package/model/attribute-container.entity.d.ts +9 -9
  42. package/model/attribute-dictionary.entity.d.ts +12 -12
  43. package/model/attribute-long-text.entity.d.ts +4 -4
  44. package/model/attribute-value-grid-row.entity.d.ts +7 -7
  45. package/model/attribute-value-set.entity.d.ts +11 -11
  46. package/model/attribute-value.entity.d.ts +28 -28
  47. package/model/attribute.entity.d.ts +26 -26
  48. package/model/dictionary-entries.dto.d.ts +6 -6
  49. package/model/extractable-field-status.entity.d.ts +8 -8
  50. package/model/graphical-attribute.entity.d.ts +13 -13
  51. package/model/pre-eval.dto.d.ts +5 -5
  52. package/package.json +16 -8
  53. package/pipes/is-group-attribute.pipe.d.ts +13 -13
  54. package/services/attribute.service.d.ts +263 -263
  55. package/components/attribute-configuration.component.d.ts +0 -52
  56. package/esm2022/components/attribute-configuration.component.mjs +0 -263
@@ -1,1211 +1,1211 @@
1
- import { Inject, Injectable, InjectionToken, isDevMode } from "@angular/core";
2
- import { HttpClient, HttpParams } from "@angular/common/http";
3
- import { Router } from "@angular/router";
4
- import { BehaviorSubject, forkJoin, Subject } from "rxjs";
5
- import { DictionaryService } from "@huntsman-cancer-institute/dictionary-service";
6
- import { PreEvalDTO } from "../model/pre-eval.dto";
7
- import { DictionaryEntriesDTO } from "../model/dictionary-entries.dto";
8
- import * as i0 from "@angular/core";
9
- import * as i1 from "@huntsman-cancer-institute/dictionary-service";
10
- import * as i2 from "@angular/common/http";
11
- import * as i3 from "@angular/router";
12
- export let ATTRIBUTE_ENDPOINT = new InjectionToken("attributeEndpoint");
13
- export const BOOLEAN = ["N", "Y"];
14
- export const EXTENDED_BOOLEAN = ["N", "Y", "U"];
15
- /**
16
- * A service created for each attribute configuration instance. This makes calls to the backend to get the configuration
17
- * and value set. It also stores common data that different attributes might need (e.g. a list of attribute choices).
18
- */
19
- export class AttributeService {
20
- constructor(dictionaryService, http, router, attributeEndpoint) {
21
- this.dictionaryService = dictionaryService;
22
- this.http = http;
23
- this.router = router;
24
- this.attributeEndpoint = attributeEndpoint;
25
- this.attributeContextLoadingSubject = new BehaviorSubject(false);
26
- this.attributeContextListSubject = new BehaviorSubject(undefined);
27
- this.attributeSecurityContextListSubject = new BehaviorSubject(undefined);
28
- this.filter1ListSubject = new BehaviorSubject(undefined);
29
- this.filter2ListSubject = new BehaviorSubject(undefined);
30
- this.dictionaryListSubject = new BehaviorSubject(undefined);
31
- this.postConfigurationSubject = new Subject();
32
- this.attributeConfigurationDimensionSubject = new BehaviorSubject(undefined);
33
- this.attributeConfigurationListSubject = new BehaviorSubject(undefined);
34
- this.attributeConfigurationListLoadingSubject = new BehaviorSubject(false);
35
- this.attributeConfigurationDTOSubject = new BehaviorSubject(undefined);
36
- this.attributeConfigurationSubject = new BehaviorSubject(undefined);
37
- this.attributeValueSetSubject = new BehaviorSubject(undefined);
38
- this.attributeValuePushedSubject = new Subject();
39
- this.loadingSubject = new BehaviorSubject(false);
40
- this.attributeMap = new Map();
41
- this.containerUpdated = new Subject();
42
- this.gridRowSaved = new Subject();
43
- this.gridRowDeleted = new Subject();
44
- this.dirty = new BehaviorSubject(false);
45
- this.updatedAttributeValues = [];
46
- this.slicedAttributeValues = [];
47
- this.uniqueId = 0;
48
- if (isDevMode()) {
49
- console.debug("Created New AttributeService");
50
- }
51
- }
52
- setBoundData(boundData) {
53
- this.boundData = boundData;
54
- if (this.attributeValueSetSubject.getValue()) {
55
- this.notifyAttributes();
56
- }
57
- }
58
- getAttributeValueCountByAttribute(idAttribute) {
59
- return this.http.get(this.attributeEndpoint + "attribute-value-count", { params: new HttpParams().set("idAttribute", idAttribute.toString()) });
60
- }
61
- getAttributeValueCountByContainer(idAttributeContainer) {
62
- return this.http.get(this.attributeEndpoint + "attribute-value-count", { params: new HttpParams().set("idAttributeContainer", idAttributeContainer.toString()) });
63
- }
64
- getDictionaryValueCount(idAttributeDictionary) {
65
- return this.http.get(this.attributeEndpoint + "attribute-dictionary-count", { params: new HttpParams().set("idAttributeDictionary", idAttributeDictionary.toString()) });
66
- }
67
- fetchAttributeContext() {
68
- this.attributeContextLoadingSubject.next(true);
69
- forkJoin([
70
- this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.AttributeSecurityContext"),
71
- this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.AttributeContext"),
72
- this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.Filter1"),
73
- this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.Filter2"),
74
- this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.AttributeDictionary")
75
- ]).subscribe((responses) => {
76
- this.dictionaryListSubject.next(responses[4]);
77
- this.filter1ListSubject.next(responses[2]);
78
- this.filter2ListSubject.next(responses[3]);
79
- this.attributeContextListSubject.next(responses[1]);
80
- responses[0].sort(this.sortAttributeSecurityContextList);
81
- this.attributeSecurityContextListSubject.next(responses[0]);
82
- this.attributeContextLoadingSubject.next(false);
83
- });
84
- }
85
- //Gets the dictionary entries from the map (so we don't load over and over and over for the same dictionary)
86
- getDictionaryEntries(attribute, values, groupAttributeRowId, referencedAttributeValue) {
87
- let bs = new Subject();
88
- //Handle XPATH
89
- if (attribute.attributeDictionary.xpath) {
90
- let entriesDTO = new DictionaryEntriesDTO();
91
- let xpath = attribute.attributeDictionary.xpath;
92
- //Filtered by another dictionary? Parse to get array of all dictionary class names needed
93
- let dictClasses = [];
94
- let pos = 0;
95
- while (xpath.indexOf("/Dictionaries/Dictionary", pos) >= 0) {
96
- let start = xpath.indexOf("/Dictionaries/Dictionary", pos);
97
- start = xpath.indexOf("'", start);
98
- let end = xpath.indexOf("'", start + 1);
99
- dictClasses.push(attribute.attributeDictionary.xpath.substring(start + 1, end));
100
- pos = end;
101
- }
102
- //Potentially load multiple dictionaries
103
- let forkCalls = [];
104
- for (let className of dictClasses) {
105
- forkCalls.push(this.dictionaryService.getDictionaryEntriesAsXML(className));
106
- }
107
- //Deal with the results together
108
- forkJoin(forkCalls).subscribe((responses) => {
109
- //We're only going to do xpath on the xml for the first dictionary
110
- const parser = new DOMParser();
111
- let doc = parser.parseFromString(responses[0], "application/xml");
112
- //Have to evaluate sub-expression. This doesn't actually support expressions like [@x = (/xpath-sub-expression)]
113
- let secondaryXml = undefined;
114
- if (responses.length > 1) {
115
- secondaryXml = responses[1];
116
- }
117
- //Pre-evaluate and simplify XPATH
118
- let dto = this.preEvaluateXpath(attribute.attributeDictionary.xpath, secondaryXml, groupAttributeRowId, referencedAttributeValue);
119
- //Evaluate XPATH expression
120
- let entries = [];
121
- entriesDTO.entriesIncludeSelectedValue = false;
122
- try {
123
- let xPathResult = document.evaluate(dto.expression, doc, null, XPathResult.ANY_TYPE, null);
124
- //Iterate xpath results (nodes)
125
- var node = null;
126
- while (node = xPathResult.iterateNext()) {
127
- let entry = this.getJsonEntryFromNode(node);
128
- entries.push(entry);
129
- }
130
- }
131
- catch (e) {
132
- // No matching entries here.
133
- }
134
- //What about dictionary entries where isActive='N', but the id was used in a previously saved value?
135
- //We add that value to the dropdown, in that case, so it can be selected
136
- //ReferencedAttributeValue only gets passed in when the filter attribute changes. In that scenario we do not want to add the old value to the list
137
- if (attribute.isMultiValue !== "Y") {
138
- for (let av of values) {
139
- let present = false;
140
- if (av && !referencedAttributeValue) {
141
- for (var i = entries.length - 1; i >= 0; i--) {
142
- if (entries[i].value === av.valueIdDictionary) {
143
- present = true;
144
- break;
145
- }
146
- }
147
- //If the currently saved value is not in the list, add it.
148
- if (!present) {
149
- let xpath = "/Dictionaries/Dictionary[@className='" + attribute.attributeDictionary.className + "']/DictionaryEntry[@value='" + av.valueIdDictionary + "']";
150
- //The entry was probably already loaded, but excluded by the xpath. We can use that.
151
- let node = document.evaluate(xpath, doc, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
152
- if (node) {
153
- entries.push(this.getJsonEntryFromNode(node));
154
- entriesDTO.entriesIncludeSelectedValue = true;
155
- }
156
- }
157
- }
158
- }
159
- }
160
- //Set the behavior subject with the filtered values for the dictionary
161
- entriesDTO.entries = entries;
162
- entriesDTO.referencedAttribute = dto.referencedAttribute;
163
- bs.next(entriesDTO);
164
- });
165
- }
166
- //Non-xpath
167
- else {
168
- //DictionayService just used http get, so should not need to unsubscribe, since http does that
169
- this.dictionaryService.getDictionaryDropdownEntries(attribute.attributeDictionary.className).subscribe((entries) => {
170
- //Make value fields
171
- for (var i = entries.length - 1; i >= 0; i--) {
172
- entries[i].value = entries[i].id.toString();
173
- }
174
- let entriesDTO = new DictionaryEntriesDTO();
175
- entriesDTO.entries = entries;
176
- entriesDTO.entriesIncludeSelectedValue = true; //A bit of an assumption, but if it isn't filtered, it had better include all the values!
177
- bs.next(entriesDTO);
178
- });
179
- }
180
- return bs;
181
- }
182
- getJsonEntryFromNode(node) {
183
- //Create JSON objects from the nodes
184
- let entry = {};
185
- for (var i = node.attributes.length - 1; i >= 0; i--) {
186
- entry[node.attributes[i].name] = node.attributes[i].value;
187
- }
188
- return entry;
189
- }
190
- preEvaluateXpath(xpath, secondaryXml, groupAttributeRowId, referencedAttributeValue) {
191
- let dto = new PreEvalDTO();
192
- //SecurityAdvisor/@codeCancerGroup
193
- while (xpath.indexOf("/SecurityAdvisor/@codeCancerGroup") >= 0) {
194
- xpath = xpath.replace("/SecurityAdvisor/@codeCancerGroup", "'" + this.getAttributeConfigurationSubject().value.codeAttributeSecurityContext + "'");
195
- }
196
- //Replace some of the context parameters ${x.value} - This is more Altio specific stuff that was used in CCR
197
- let paramPos = xpath.search("\\${[A-Za-z0-9_]+\\.value}");
198
- while (paramPos >= 0) {
199
- let prefix = xpath.substring(0, paramPos);
200
- let varName = xpath.substring(paramPos + 2, xpath.indexOf(".", paramPos));
201
- let suffix = xpath.substring(xpath.indexOf("}", paramPos) + 1);
202
- var av;
203
- //If there IS a referencedAttributeValue, we can use the value directly. Otherwise we try to find it in the AVS
204
- if (!referencedAttributeValue) {
205
- //Find the attribute, matching the varName.
206
- //Do this first, so we get a reference to the related attribute, regardless of whether there is already a value
207
- //Iterate attributes to find one that matches the value
208
- this.attributeMap.forEach((attribute) => {
209
- //Attributes that match the name
210
- if (attribute.attributeName === varName) {
211
- dto.referencedAttribute = attribute;
212
- return;
213
- }
214
- //If this is a grid, look for attributes in the row
215
- if (attribute.attributes) {
216
- for (let gridColumnAttribute of attribute.attributes) {
217
- //If the name matches AND the value in the AVS was part of the SAME ROW we are evaluating XPATH for, we can use the value for evaluation
218
- if (gridColumnAttribute.attributeName === varName) {
219
- dto.referencedAttribute = gridColumnAttribute;
220
- return;
221
- }
222
- }
223
- }
224
- });
225
- let avs = this.attributeValueSetSubject.getValue();
226
- //If we found the attribute and have values...
227
- if (dto.referencedAttribute && avs) {
228
- //Look through all the values to find the one for the referenced attribute (and SAME grid row if in a grid row)
229
- av = avs.attributeValues.find((av) => {
230
- //If this is an AV for a grid row, it must be for the same grid row we are looking for
231
- if (typeof av.groupAttributeRowId !== 'undefined' && typeof groupAttributeRowId !== 'undefined' && av.groupAttributeRowId !== groupAttributeRowId) {
232
- return false;
233
- }
234
- //If we looked up the attribute matching the value by id AND the name of the attribute is the one we ar looking for from the XPATH, we can use it for evaluation
235
- //Found an AttributeValue that the dictionary is filtered by
236
- if (dto.referencedAttribute.idAttribute === av.idAttribute) {
237
- return true;
238
- }
239
- else {
240
- return false;
241
- }
242
- });
243
- }
244
- }
245
- //Use the referencedAttributeValue if provided (this happens when already known, during changes to the referenced attribute)
246
- if (referencedAttributeValue) {
247
- xpath = prefix + "'" + referencedAttributeValue.value + "'" + suffix;
248
- }
249
- //Found the AttributeValue for the attribute that the dictionary is filtered by
250
- else if (av) {
251
- xpath = prefix + "'" + av.value + "'" + suffix;
252
- }
253
- //Didn't find an attribute for varName
254
- else {
255
- //Maybe the varName is from elsewhere in the app (non-COD), and provided in boundData
256
- if (this.boundData && this.boundData[varName]) {
257
- xpath = prefix + "'" + this.boundData[varName] + "'" + suffix;
258
- }
259
- //Nothing matches. Change to empty string. Will probably result in NO entries, which would be correct.
260
- else {
261
- xpath = prefix + "''" + suffix;
262
- }
263
- }
264
- paramPos = xpath.search("\\${[A-Za-z0-9_]+\\.value}");
265
- }
266
- //Have to evaluate sub-expression. This handles expressions like [@x = (/xpath-sub-expression)]
267
- let inExpressionPos = xpath.search("\\[@[A-Za-z0-9_]+\\s*=\\s*\\(");
268
- if (inExpressionPos > 0 && secondaryXml) {
269
- let prefix = xpath.substring(0, inExpressionPos + 1);
270
- let expressionEnd = xpath.indexOf(")", inExpressionPos);
271
- let variable = xpath.substring(inExpressionPos + 1, xpath.indexOf("=", inExpressionPos));
272
- let subExpression = xpath.substring(xpath.indexOf("(", inExpressionPos) + 1, expressionEnd);
273
- let suffix = xpath.substring(expressionEnd + 1);
274
- xpath = prefix;
275
- //Evaluate XPATH expression
276
- const parser = new DOMParser();
277
- let doc = parser.parseFromString(secondaryXml, "application/xml");
278
- let xPathResult = document.evaluate(subExpression, doc, null, XPathResult.ANY_TYPE, null);
279
- //Iterate xpath results (nodes)
280
- var node = xPathResult.iterateNext();
281
- while (node) {
282
- xpath = xpath + variable + "='" + node.nodeValue + "'";
283
- node = xPathResult.iterateNext();
284
- if (node) {
285
- xpath = xpath + " or ";
286
- }
287
- }
288
- xpath = xpath + suffix;
289
- }
290
- dto.expression = xpath;
291
- return dto;
292
- }
293
- sortAttributeSecurityContextList(a, b) {
294
- return a.description.toLowerCase().localeCompare(b.description.toLowerCase());
295
- }
296
- fetchAttributeConfigurationList(codeAttributeSecurityContext) {
297
- if (isDevMode()) {
298
- console.debug("fetchAttributeConfigurationList: " + codeAttributeSecurityContext);
299
- }
300
- this.attributeConfigurationListLoadingSubject.next(true);
301
- let url = this.attributeEndpoint + "configurations";
302
- let params = new HttpParams();
303
- if (codeAttributeSecurityContext) {
304
- params = params.set("codeAttributeSecurityContext", codeAttributeSecurityContext);
305
- }
306
- this.http.get(url, { params: params }).subscribe((configurationList) => {
307
- this.attributeConfigurationListLoadingSubject.next(false);
308
- let dtos = [];
309
- for (let cfg of configurationList) {
310
- let dto = this.getAttributeConfigurationDTO(cfg);
311
- if (dto) {
312
- dtos.push(dto);
313
- }
314
- }
315
- dtos.sort(this.sortAttributeConfigurationList);
316
- this.attributeConfigurationListSubject.next(dtos);
317
- });
318
- }
319
- sortAttributeConfigurationList(a, b) {
320
- const displaya = a.codeAttributeSecurityContextDisplay
321
- + a.extensionDescription
322
- + (a.filter1Display || "")
323
- + (a.filter2Display || "");
324
- const displayb = b.codeAttributeSecurityContextDisplay
325
- + b.extensionDescription
326
- + (b.filter1Display || "")
327
- + (b.filter2Display || "");
328
- return displaya.toLowerCase().localeCompare(displayb.toLowerCase());
329
- }
330
- //Used by cod-editor
331
- clear() {
332
- this.idAttributeConfiguration = undefined;
333
- this.idFilter1 = undefined;
334
- this.idFilter2 = undefined;
335
- this.attributeConfigurationDTOSubject.next(undefined);
336
- this.attributeConfigurationSubject.next(undefined);
337
- }
338
- createAttributeConfiguration(attributeConfiguration) {
339
- attributeConfiguration.idAttributeConfiguration = undefined;
340
- this.http.post(this.attributeEndpoint + "configurations", attributeConfiguration).subscribe((attributeConfiguration) => {
341
- this.idAttributeConfiguration = attributeConfiguration.idAttributeConfiguration;
342
- this.postConfigurationSubject.next(true);
343
- this.attributeConfigurationSubject.next(attributeConfiguration);
344
- this.router.navigateByUrl("/editor/attribute-configuration/" + attributeConfiguration.idAttributeConfiguration);
345
- });
346
- }
347
- setAttributeConfigurationById(idAttributeConfiguration, idAttributeValueSet, idParentObject) {
348
- if (idAttributeConfiguration !== -1) {
349
- this.newAttributeConfiguration = undefined;
350
- }
351
- //Only load if the AttributeConfiguration has changed
352
- if (this.idAttributeConfiguration !== idAttributeConfiguration) {
353
- //Clear ASAP
354
- this.idAttributeConfiguration = idAttributeConfiguration;
355
- this.idAttributeValueSet = idAttributeValueSet;
356
- this.idFilter1 = undefined;
357
- this.idFilter2 = undefined;
358
- this.attributeMap.clear();
359
- this.attributeConfigurationDTOSubject.next(undefined);
360
- this.attributeConfigurationSubject.next(undefined);
361
- this.fetchAttributeConfiguration(idAttributeValueSet, idParentObject);
362
- }
363
- //Or load the AttributeValueSet if that changed (possible to switch from one event to another of the same type, for example
364
- //The AttributeConfiguration must also have finished loading and not already working on loading the values
365
- else if (this.idAttributeValueSet !== idAttributeValueSet && this.attributeConfigurationSubject.getValue()) {
366
- this.setAttributeValueSet(idAttributeValueSet, idParentObject);
367
- }
368
- }
369
- /**
370
- * Sets the attribute configuration identifiers to be used by this service. This prompts a new configuration
371
- * request to be made.
372
- *
373
- * @param {number} idFilter1
374
- * @param {number} idFilter2
375
- */
376
- /* This is commented out for now because it is both unimplemented and incomplete (loading a configuration
377
- * filter would really also require the attribute context and attributesecurity context plus a service on
378
- * the back end that actually does this work. For now, only loading by idAttributeConfiguration
379
- *
380
- setAttributeConfigurationByFilter(idFilter1: number, idFilter2?: number): void {
381
- if (isDevMode()) {
382
- console.debug("setAttributeConfigurationByFilter: " + idFilter1 + " " + idFilter2);
383
- }
384
-
385
- this.newAttributeConfiguration = undefined;
386
- //this.idAttributeConfiguration = undefined;
387
- this.idFilter1 = idFilter1;
388
- this.idFilter2 = idFilter2;
389
-
390
- this.fetchAttributeConfiguration();
391
- }
392
- */
393
- /**
394
- * Sets the id of the attribute value set. This will prompt a request to pull this from the backend.
395
- *
396
- * @param {number} idAttributeValueSet
397
- */
398
- setAttributeValueSet(idAttributeValueSet, idParentObject) {
399
- //Only load the AttributeValueSet if it has been changed
400
- if (this.idAttributeValueSet !== idAttributeValueSet) {
401
- this.idAttributeValueSet = idAttributeValueSet;
402
- this.fetchAttributeValueSet(idParentObject);
403
- }
404
- }
405
- /**
406
- * The request to download the attribute configuration.
407
- */
408
- fetchAttributeConfiguration(idAttributeValueSet, idParentObject) {
409
- if (this.newAttributeConfiguration) {
410
- this.attributeConfigurationDTOSubject.next(undefined);
411
- this.attributeConfigurationSubject.next(this.newAttributeConfiguration);
412
- return;
413
- }
414
- else if (this.idAttributeConfiguration === -1) {
415
- this.attributeConfigurationDTOSubject.next(undefined);
416
- this.attributeConfigurationSubject.next({
417
- idAttributeConfiguration: -2
418
- });
419
- return;
420
- }
421
- this.loadingSubject.next(true);
422
- let url;
423
- if (this.idAttributeConfiguration && this.idAttributeConfiguration > -1) {
424
- url = this.attributeEndpoint + "configurations/" + this.idAttributeConfiguration;
425
- }
426
- else {
427
- //This is not fully implemented
428
- //url = this.attributeEndpoint + "configurations/filter/" + this.idFilter1;
429
- //if (this.idFilter2) {
430
- //url += "/" + this.idFilter2;
431
- //}
432
- }
433
- this.http.get(url).subscribe((attributeConfiguration) => {
434
- this.setAttributeConfiguration(attributeConfiguration);
435
- this.loadingSubject.next(false);
436
- //Now load the attributeValueSet - This will always happen when a new configuration is loaded
437
- this.idAttributeValueSet = undefined; //Force it to change in this scenario
438
- this.setAttributeValueSet(idAttributeValueSet, idParentObject);
439
- this.dirty.next(false);
440
- }, (error) => {
441
- console.error(error);
442
- this.loadingSubject.next(false);
443
- this.setAttributeConfiguration(undefined);
444
- });
445
- }
446
- setAttributeConfiguration(attributeConfiguration) {
447
- this.attributeMap.clear();
448
- if (isDevMode()) {
449
- console.debug("AttributeService.setAttributeConfiguration");
450
- console.debug(attributeConfiguration);
451
- }
452
- if (attributeConfiguration) {
453
- if (attributeConfiguration.baseWindowTemplate) {
454
- this.getBaseWindowDimension(attributeConfiguration.baseWindowTemplate);
455
- }
456
- if (attributeConfiguration.attributeContainers) {
457
- attributeConfiguration.attributeContainers.sort((a, b) => {
458
- if (a.sortOrder < b.sortOrder) {
459
- return -1;
460
- }
461
- else if (a.sortOrder > b.sortOrder) {
462
- return 1;
463
- }
464
- else {
465
- return 0;
466
- }
467
- });
468
- }
469
- for (let attributeContainer of attributeConfiguration.attributeContainers) {
470
- /**
471
- * First sort attributes using the y and x positioning. If using absolute position, the order doesn't matter,
472
- * but if we want the absolute positioning to guide auto layout, then use this order.
473
- */
474
- attributeContainer.graphicalAttributes.sort((a, b) => {
475
- if (a.tabOrder < b.tabOrder) {
476
- return -1;
477
- }
478
- else if (a.tabOrder > b.tabOrder) {
479
- return 1;
480
- }
481
- else {
482
- return 0;
483
- }
484
- });
485
- for (let attribute of attributeContainer.graphicalAttributes) {
486
- this.attributeMap.set(attribute.idAttribute, attribute);
487
- }
488
- }
489
- }
490
- this.attributeConfigurationDTOSubject.next(this.getAttributeConfigurationDTO(attributeConfiguration));
491
- this.attributeConfigurationSubject.next(attributeConfiguration);
492
- }
493
- /**
494
- * The request to pull the attribute value set.
495
- * Required the AttributeConfiguration to be pre-loaded
496
- */
497
- fetchAttributeValueSet(idParentObject) {
498
- this.loadingSubject.next(true);
499
- this.idParentObject = idParentObject;
500
- let url = this.attributeEndpoint + "attribute-value-set/" + this.idAttributeValueSet;
501
- let ac = this.attributeConfigurationSubject.getValue();
502
- let queryParams = new HttpParams()
503
- .set("codeAttributeSecurityContext", ac.codeAttributeSecurityContext)
504
- .set("codeAttributeContext", ac.codeAttributeContext)
505
- .set("idParentObject", (idParentObject) ? idParentObject.toString() : "");
506
- //Clear ASAP
507
- this.slicedAttributeValues = [];
508
- this.updatedAttributeValues = [];
509
- this.attributeValueSetSubject.next(undefined);
510
- this.http.get(url, { params: queryParams }).subscribe((attributeValueSet) => {
511
- //Initialize attributeValues if it does not exist
512
- if (!attributeValueSet.attributeValues) {
513
- attributeValueSet.attributeValues = [];
514
- }
515
- this.attributeValueSetSubject.next(attributeValueSet);
516
- this.loadingSubject.next(false);
517
- this.dirty.next(false);
518
- }, (error) => {
519
- console.error(error);
520
- this.loadingSubject.next(false);
521
- this.attributeValueSetSubject.next(undefined);
522
- });
523
- }
524
- getBaseWindowDimension(baseWindowTemplate) {
525
- this.http.get(this.attributeEndpoint + "base-window-dimension", { params: new HttpParams().set("baseWindowTemplate", baseWindowTemplate) })
526
- .subscribe((dimension) => {
527
- this.attributeConfigurationDimensionSubject.next(dimension);
528
- });
529
- }
530
- /**
531
- * Currently a simple notifier that the configuration or attribute value set has changed and components may need to be refreshed.
532
- *
533
- */
534
- notifyAttributes() {
535
- this.containerUpdated.next(true);
536
- }
537
- /**
538
- * Post the attribute configuration after editing. Post the entire thing as it cascades down. The editor allows you
539
- * to modify every container and only then save the entire configuration.
540
- *
541
- * @param {AttributeConfiguration} attributeConfiguration
542
- */
543
- postAttributeConfiguration(attributeConfiguration) {
544
- let url = this.attributeEndpoint + "configurations/" + attributeConfiguration.idAttributeConfiguration;
545
- this.loadingSubject.next(true);
546
- this.setNegativeIdsToUndefined(attributeConfiguration);
547
- this.http.post(url, attributeConfiguration).subscribe(() => {
548
- // Prevent error in subsequent saves. See Metabuilder / MB-23
549
- this.http.get(url).subscribe((attributeConfiguration) => {
550
- if (isDevMode()) {
551
- console.debug(attributeConfiguration);
552
- }
553
- this.postConfigurationSubject.next(true);
554
- this.attributeConfigurationSubject.next(attributeConfiguration);
555
- }, (error) => {
556
- console.error(error);
557
- }, () => {
558
- this.loadingSubject.next(false);
559
- });
560
- }, (error) => {
561
- console.error(error);
562
- });
563
- }
564
- /**
565
- * Put the attribute value set. When editing, attributes already post their updated values to this services under
566
- * a separate array. What we do is merge in these updated or created values with the current attribute value set (avs).
567
- * While doing this, set the id of the avs and nullify any negative ids.
568
- */
569
- updateAttributeValueSet() {
570
- let url = this.attributeEndpoint + "attribute-value-set/";
571
- let ac = this.attributeConfigurationSubject.getValue();
572
- let queryParams = new HttpParams()
573
- .set("codeAttributeSecurityContext", ac.codeAttributeSecurityContext)
574
- .set("codeAttributeContext", ac.codeAttributeContext)
575
- .set("idParentObject", (this.idParentObject) ? this.idParentObject.toString() : "");
576
- let avs = Object.assign({}, this.attributeValueSetSubject.getValue());
577
- for (let i = this.updatedAttributeValues.length - 1; i >= 0; i--) {
578
- this.updatedAttributeValues[i].idAttributeValueSet = this.idAttributeValueSet;
579
- if (this.updatedAttributeValues[i].idAttributeValue < 0) {
580
- this.updatedAttributeValues[i].idAttributeValue = undefined;
581
- }
582
- let j = 0;
583
- for (j = 0; j < avs.attributeValues.length; j++) {
584
- if (this.updatedAttributeValues[i].idAttributeValue === avs.attributeValues[j].idAttributeValue) {
585
- break;
586
- }
587
- }
588
- if (j < avs.attributeValues.length) {
589
- avs.attributeValues[j] = this.updatedAttributeValues[i];
590
- this.updatedAttributeValues.splice(i, 1);
591
- }
592
- }
593
- for (let i = 0; i < this.slicedAttributeValues.length; i++) {
594
- let j = 0;
595
- for (j = 0; j < avs.attributeValues.length; j++) {
596
- if (this.slicedAttributeValues[i].idAttributeValue === avs.attributeValues[j].idAttributeValue) {
597
- break;
598
- }
599
- }
600
- if (j < avs.attributeValues.length) {
601
- avs.attributeValues.splice(j, 1);
602
- }
603
- }
604
- avs.attributeValues = avs.attributeValues.concat(this.updatedAttributeValues);
605
- this.loadingSubject.next(true);
606
- let resultSubject = new Subject();
607
- this.http.put(url, avs, { params: queryParams }).subscribe((attributeValueSet) => {
608
- if (isDevMode()) {
609
- console.debug(attributeValueSet);
610
- }
611
- //Initialize attributeValues if it does not exist
612
- if (!attributeValueSet.attributeValues) {
613
- attributeValueSet.attributeValues = [];
614
- }
615
- this.slicedAttributeValues = [];
616
- this.updatedAttributeValues = [];
617
- this.attributeValueSetSubject.next(attributeValueSet);
618
- this.loadingSubject.next(false);
619
- this.dirty.next(false);
620
- //Send the results to the observer (if any), then complete
621
- resultSubject.next(attributeValueSet);
622
- resultSubject.complete();
623
- }, (error) => {
624
- console.error(error);
625
- this.loadingSubject.next(false);
626
- resultSubject.error(error);
627
- });
628
- return resultSubject;
629
- }
630
- /**
631
- * Get the attributeConfigurationSubject.
632
- *
633
- * @returns {BehaviorSubject<AttributeConfiguration>}
634
- */
635
- getAttributeConfigurationSubject() {
636
- return this.attributeConfigurationSubject;
637
- }
638
- getDirtySubject() {
639
- return this.dirty;
640
- }
641
- /**
642
- * Get the attributeValueSetSubject;
643
- *
644
- * @returns {BehaviorSubject<AttributeValueSet>}
645
- */
646
- getAttributeValueSet() {
647
- return this.attributeValueSetSubject;
648
- }
649
- /**
650
- * Get the attributeValuePushedSubject;
651
- *
652
- * @returns {Subject<AttributeValue>}
653
- */
654
- getAttributeValuePushedSubject() {
655
- return this.attributeValuePushedSubject;
656
- }
657
- /**
658
- * Get all attribute values based upon the idAttribute.
659
- *
660
- * @param {number} idAttributes
661
- * @returns {AttributeValue[]}
662
- */
663
- getAttributeValues(idAttribute, groupAttributeRowId) {
664
- let attributeValues = [];
665
- if (this.attributeValueSetSubject.getValue()) {
666
- //Go through all the updated attribute values first (so we preserve across changing tabs, etc)
667
- let i = 0;
668
- for (i = 0; i < this.updatedAttributeValues.length; i++) {
669
- if (this.updatedAttributeValues[i].idAttribute === idAttribute && (!groupAttributeRowId || groupAttributeRowId === this.updatedAttributeValues[i].groupAttributeRowId)) {
670
- attributeValues.push(Object.assign({}, this.updatedAttributeValues[i]));
671
- }
672
- else if (this.updatedAttributeValues[i].idGroupAttribute === idAttribute && (!groupAttributeRowId || groupAttributeRowId === this.updatedAttributeValues[i].groupAttributeRowId)) {
673
- attributeValues.push(Object.assign({}, this.updatedAttributeValues[i]));
674
- }
675
- }
676
- //Go through all the regular attributes
677
- for (let attributeValue of this.attributeValueSetSubject.getValue().attributeValues) {
678
- //Regular attributes (normal and group, which get multiple)
679
- if (attributeValue.idAttribute === idAttribute || attributeValue.idGroupAttribute === idAttribute) {
680
- //If row id specified, only care about values for that row
681
- if (typeof groupAttributeRowId === 'undefined' || attributeValue.groupAttributeRowId === groupAttributeRowId) {
682
- //If not already added...
683
- if (!attributeValues.find((existing) => existing.idAttributeValue === attributeValue.idAttributeValue)) {
684
- //Don't want the original if it was removed (sliced)
685
- if (!this.slicedAttributeValues.find((sav) => sav.idAttributeValue === attributeValue.idAttributeValue)) {
686
- attributeValues.push(Object.assign({}, attributeValue));
687
- }
688
- }
689
- }
690
- }
691
- }
692
- }
693
- return attributeValues;
694
- }
695
- /**
696
- * Get all child attributes of the idAttribute. Most likely for attributes that define columns of a grid.
697
- *
698
- * @param {number} idAttribute
699
- * @returns {Attribute[]}
700
- */
701
- getGroupAttributes(idAttribute) {
702
- let attributes = [];
703
- this.attributeMap.forEach((attribute) => {
704
- if (attribute.idGroupAttribute === idAttribute) {
705
- attributes.push(attribute);
706
- }
707
- });
708
- return attributes;
709
- }
710
- /**
711
- * Set the width which is a requirement of the absolute positioning.
712
- *
713
- * @param {number} width
714
- */
715
- setWidth(width) {
716
- this.width = width;
717
- }
718
- /**
719
- * Get the width.
720
- *
721
- * @returns {number}
722
- */
723
- getWidth() {
724
- return this.width;
725
- }
726
- /**
727
- * Get the array of attribute choices for the idAttribute.
728
- *
729
- * @param {number} idAttribute
730
- * @returns {AttributeChoice[]}
731
- */
732
- getAttributeChoices(idAttribute) {
733
- return this.attributeMap.get(idAttribute).attributeChoices;
734
- }
735
- getLoadingSubject() {
736
- return this.loadingSubject;
737
- }
738
- /**
739
- * Get the containerUpdated subject.
740
- *
741
- * @returns {Subject<number>}
742
- */
743
- getContainerUpdated() {
744
- return this.containerUpdated;
745
- }
746
- getGridRowSavedSubject() {
747
- return this.gridRowSaved;
748
- }
749
- getGridRowDeletedSubject() {
750
- return this.gridRowDeleted;
751
- }
752
- /**
753
- * Clear the updated and deleted attribute value arrays.
754
- *
755
- */
756
- clearUpdatedAttributeValues() {
757
- this.slicedAttributeValues = [];
758
- this.updatedAttributeValues = [];
759
- this.dirty.next(false);
760
- this.notifyAttributes();
761
- }
762
- /**
763
- * Clear the updated and deleted grid row attributes for the specified grid row
764
- *
765
- */
766
- clearUpdatedGridRowAttributeValues(groupAttributeRowId) {
767
- let remainingAttributes = [];
768
- this.slicedAttributeValues = this.slicedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
769
- this.updatedAttributeValues = this.updatedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
770
- //Shouldn't be a need to change dirty or notify attributes
771
- }
772
- saveGridRowAttributeValues(idGroupAttribute, groupAttributeRowId) {
773
- let rowValues = this.updatedAttributeValues.filter((av) => av.groupAttributeRowId === groupAttributeRowId);
774
- for (let j = 0; j < rowValues.length; j++) {
775
- //set the idAttributeValueSet if necessary
776
- if (!rowValues[j].idAttributeValueSet) {
777
- rowValues[j].idAttributeValueSet = this.idAttributeValueSet;
778
- }
779
- //remove all negative ids (new values)
780
- if (rowValues[j].idAttributeValue < 0) {
781
- rowValues[j].idAttributeValue = undefined;
782
- }
783
- }
784
- //For multi values that were sliced (de-selected) we're going to find them and null out the value, instead of removing.
785
- //That means they actaully need to be added to the rowValues
786
- //Removed multi values within an existing row
787
- let removedValues = this.slicedAttributeValues.filter((av) => av.groupAttributeRowId === groupAttributeRowId);
788
- for (let i = 0; i < removedValues.length; i++) {
789
- removedValues[i].valueAttributeChoice = undefined;
790
- removedValues[i].valueIdDictionary = undefined;
791
- rowValues.push(removedValues[i]);
792
- }
793
- let avgr = {
794
- idAttributeValueSet: this.idAttributeValueSet,
795
- idGroupAttribute: idGroupAttribute,
796
- groupAttributeRowId: groupAttributeRowId,
797
- attributeValues: rowValues
798
- };
799
- let url = this.attributeEndpoint + "attribute-value-grid-row/";
800
- let ac = this.attributeConfigurationSubject.getValue();
801
- let queryParams = new HttpParams()
802
- .set("codeAttributeSecurityContext", ac.codeAttributeSecurityContext)
803
- .set("codeAttributeContext", ac.codeAttributeContext)
804
- .set("idParentObject", (this.idParentObject) ? this.idParentObject.toString() : "");
805
- this.loadingSubject.next(true);
806
- //Save new row
807
- if (groupAttributeRowId < 0) {
808
- this.http.post(url, avgr, { params: queryParams }).subscribe((attributeValueGridRow) => {
809
- //Add the grid row to the original attribute values
810
- let avs = this.attributeValueSetSubject.getValue();
811
- for (let i = 0; i < attributeValueGridRow.attributeValues.length; i++) {
812
- avs.attributeValues.push(attributeValueGridRow.attributeValues[i]);
813
- }
814
- //Remove the updated and sliced values for the grid row, now (these are the old ones with the negative rowid)
815
- this.slicedAttributeValues = this.slicedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
816
- this.updatedAttributeValues = this.updatedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
817
- this.attributeValueSetSubject.next(avs);
818
- this.gridRowSaved.next(attributeValueGridRow);
819
- this.loadingSubject.next(false);
820
- }, (error) => {
821
- console.error(error);
822
- this.loadingSubject.next(false);
823
- });
824
- }
825
- //Update existing row
826
- else {
827
- this.http.put(url, avgr, { params: queryParams }).subscribe((attributeValueGridRow) => {
828
- //Add the grid row to the original attribute values
829
- let avs = this.attributeValueSetSubject.getValue();
830
- //Remove all old values for row
831
- let index = avs.attributeValues.findIndex((av) => av.groupAttributeRowId === groupAttributeRowId);
832
- while (index > 0) {
833
- //Remove value
834
- avs.attributeValues.splice(index, 1);
835
- //Find the next one
836
- index = avs.attributeValues.findIndex((av) => av.groupAttributeRowId === groupAttributeRowId);
837
- }
838
- //Add all the current values
839
- for (let i = 0; i < attributeValueGridRow.attributeValues.length; i++) {
840
- avs.attributeValues.push(attributeValueGridRow.attributeValues[i]);
841
- }
842
- //Remove the sliced and updated values for the grid row
843
- this.slicedAttributeValues = this.slicedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
844
- this.updatedAttributeValues = this.updatedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
845
- this.attributeValueSetSubject.next(avs);
846
- this.gridRowSaved.next(attributeValueGridRow);
847
- this.loadingSubject.next(false);
848
- }, (error) => {
849
- console.error(error);
850
- this.loadingSubject.next(false);
851
- });
852
- }
853
- }
854
- deleteGridRowAttributeValues(idGroupAttribute, groupAttributeRowId) {
855
- let url = this.attributeEndpoint + "attribute-value-grid-row/";
856
- let ac = this.attributeConfigurationSubject.getValue();
857
- let queryParams = new HttpParams()
858
- .set("codeAttributeSecurityContext", ac.codeAttributeSecurityContext)
859
- .set("codeAttributeContext", ac.codeAttributeContext)
860
- .set("idParentObject", (this.idParentObject) ? this.idParentObject.toString() : "");
861
- let avgr = {
862
- idAttributeValueSet: this.idAttributeValueSet,
863
- idGroupAttribute: idGroupAttribute,
864
- groupAttributeRowId: groupAttributeRowId,
865
- attributeValues: []
866
- };
867
- this.loadingSubject.next(true);
868
- this.http.request('delete', url, { body: avgr, params: queryParams }).subscribe(() => {
869
- //Remove the grid row from the original attribute values
870
- let avs = this.attributeValueSetSubject.getValue();
871
- avs.attributeValues = avs.attributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
872
- this.attributeValueSetSubject.next(avs);
873
- this.gridRowDeleted.next(avgr);
874
- this.loadingSubject.next(false);
875
- }, (error) => {
876
- console.error(error);
877
- this.loadingSubject.next(false);
878
- });
879
- }
880
- /**
881
- * Push an attribute to the attribute map.
882
- *
883
- * @param {Attribute} attribute
884
- */
885
- pushAttribute(attribute) {
886
- this.attributeMap.set(attribute.idAttribute, attribute);
887
- }
888
- pushAttributeValueMultiChoice(attributeValue) {
889
- //Remove from sliced if present
890
- let i = 0;
891
- for (i = 0; i < this.slicedAttributeValues.length; i++) {
892
- if (this.slicedAttributeValues[i].idAttribute === attributeValue.idAttribute && this.slicedAttributeValues[i].valueAttributeChoice.idAttributeChoice === attributeValue.valueAttributeChoice.idAttributeChoice) {
893
- break;
894
- }
895
- }
896
- //Remove from sliced attribute values (no longer removing)
897
- if (i < this.slicedAttributeValues.length) {
898
- this.slicedAttributeValues.splice(i, 1);
899
- }
900
- //Otherwise push the value, so it will be saved
901
- else {
902
- this.pushAttributeValue(attributeValue);
903
- }
904
- }
905
- pushAttributeValueMultiDict(attributeValue) {
906
- //Remove from sliced if present
907
- let i = 0;
908
- for (i = 0; i < this.slicedAttributeValues.length; i++) {
909
- if (this.slicedAttributeValues[i].idAttribute === attributeValue.idAttribute && this.slicedAttributeValues[i].valueIdDictionary === attributeValue.valueIdDictionary) {
910
- break;
911
- }
912
- }
913
- //Remove from sliced attribute values (no longer removing)
914
- if (i < this.slicedAttributeValues.length) {
915
- this.slicedAttributeValues.splice(i, 1);
916
- }
917
- //Otherwise push the value, so it will be saved
918
- else {
919
- this.pushAttributeValue(attributeValue);
920
- }
921
- }
922
- /**
923
- * Push a new or updated attribute value. The current one is just removed and the new one appended to the array.
924
- *
925
- * @param {AttributeValue} attributeValue
926
- */
927
- pushAttributeValue(attributeValue) {
928
- if (isDevMode()) {
929
- console.debug("pushAttributeValue");
930
- console.debug(attributeValue);
931
- }
932
- let i = 0;
933
- for (i = 0; i < this.updatedAttributeValues.length; i++) {
934
- if (this.updatedAttributeValues[i].idAttributeValue === attributeValue.idAttributeValue) {
935
- break;
936
- }
937
- }
938
- if (i < this.updatedAttributeValues.length) {
939
- this.updatedAttributeValues.splice(i, 1);
940
- }
941
- this.updatedAttributeValues.push(attributeValue);
942
- this.attributeValuePushedSubject.next(attributeValue);
943
- //Only setting dirty for non grid-rows (those are saved immediately)
944
- if (!attributeValue.idGroupAttribute) {
945
- this.dirty.next(true);
946
- }
947
- }
948
- /**
949
- * For pushing multiple attribute values at once. This would typically be for a multi choice.
950
- *
951
- * @param {Attribute} attribute
952
- * @param {AttributeValue[]} attributeValues
953
- */
954
- pushAttributeValues(attribute, attributeValues) {
955
- if (isDevMode()) {
956
- console.debug("pushAttributeValues");
957
- console.debug(attributeValues);
958
- }
959
- for (let i = 0; i < attributeValues.length; i++) {
960
- let j = 0;
961
- for (j = 0; j < this.updatedAttributeValues.length; j++) {
962
- if (this.updatedAttributeValues[j].idAttribute !== attribute.idAttribute) {
963
- continue;
964
- }
965
- else if (this.updatedAttributeValues[j].idAttributeValue === attributeValues[i].idAttributeValue) {
966
- break;
967
- }
968
- }
969
- if (j < this.updatedAttributeValues.length) {
970
- this.updatedAttributeValues[j] = attributeValues[i];
971
- }
972
- else {
973
- this.updatedAttributeValues.push(attributeValues[i]);
974
- }
975
- }
976
- if (isDevMode()) {
977
- console.debug(this.updatedAttributeValues);
978
- }
979
- //Only setting dirty for non grid-rows (those are saved immediately)
980
- if (!attribute.idGroupAttribute) {
981
- this.dirty.next(true);
982
- }
983
- }
984
- /**
985
- * Push a value in the case where an attribute value doesn't exist.
986
- *
987
- * @param {Attribute} attribute
988
- * @param value
989
- */
990
- pushValue(attribute, value) {
991
- let attributeValue = {
992
- idAttribute: attribute.idAttribute,
993
- idAttributeValueSet: this.idAttributeValueSet
994
- };
995
- if (attribute.codeAttributeDataType === "TXT") {
996
- attributeValue.valueLongText = {
997
- idLongText: undefined,
998
- textData: value
999
- };
1000
- }
1001
- this.updatedAttributeValues.push(attributeValue);
1002
- this.dirty.next(true);
1003
- }
1004
- /**
1005
- * Remove an attribute value. Typically in the case of a multi select where the unselected value is removed.
1006
- *
1007
- * @param {Attribute} attribute
1008
- * @param {AttributeChoice} attributeChoice
1009
- */
1010
- spliceAttributeValueChoice(attribute, attributeChoice) {
1011
- if (isDevMode()) {
1012
- console.debug("sliceAttributeValue: " + attribute.idAttribute + ", " + attributeChoice.idAttributeChoice);
1013
- }
1014
- let i = 0;
1015
- for (i = 0; i < this.updatedAttributeValues.length; i++) {
1016
- if (this.updatedAttributeValues[i].idAttribute === attribute.idAttribute && this.updatedAttributeValues[i].valueAttributeChoice.idAttributeChoice === attributeChoice.idAttributeChoice) {
1017
- break;
1018
- }
1019
- }
1020
- //Remove from updated attribute values (not previously saved)
1021
- if (i < this.updatedAttributeValues.length) {
1022
- this.updatedAttributeValues.splice(i, 1);
1023
- }
1024
- //Add to sliced values (previously saved - need to remove)
1025
- else {
1026
- for (i = 0; i < this.attributeValueSetSubject.getValue().attributeValues.length; i++) {
1027
- if (this.attributeValueSetSubject.getValue().attributeValues[i].idAttribute === attribute.idAttribute
1028
- && this.attributeValueSetSubject.getValue().attributeValues[i].valueAttributeChoice.idAttributeChoice === attributeChoice.idAttributeChoice) {
1029
- this.slicedAttributeValues.push(this.attributeValueSetSubject.getValue().attributeValues[i]);
1030
- break;
1031
- }
1032
- }
1033
- }
1034
- //Only flagging dirty for non-grid rows (those are saved immediately)
1035
- if (!attribute.idGroupAttribute) {
1036
- this.dirty.next(true);
1037
- }
1038
- }
1039
- /**
1040
- * Remove an attribute value. Typically in the case of a multi select where the unselected value is removed.
1041
- *
1042
- * @param {Attribute} attribute
1043
- * @param {AttributeChoice} attributeChoice
1044
- */
1045
- spliceAttributeValueDict(attribute, value) {
1046
- if (isDevMode()) {
1047
- console.debug("sliceAttributeValue: " + attribute.idAttribute + ", " + value);
1048
- }
1049
- let i = 0;
1050
- for (i = 0; i < this.updatedAttributeValues.length; i++) {
1051
- if (this.updatedAttributeValues[i].idAttribute === attribute.idAttribute && this.updatedAttributeValues[i].valueIdDictionary === value) {
1052
- break;
1053
- }
1054
- }
1055
- //Remove from updated attribute values (not previously saved)
1056
- if (i < this.updatedAttributeValues.length) {
1057
- this.updatedAttributeValues.splice(i, 1);
1058
- }
1059
- //Add to sliced values (previously saved - need to remove)
1060
- else {
1061
- for (i = 0; i < this.attributeValueSetSubject.getValue().attributeValues.length; i++) {
1062
- if (this.attributeValueSetSubject.getValue().attributeValues[i].idAttribute === attribute.idAttribute
1063
- && this.attributeValueSetSubject.getValue().attributeValues[i].valueIdDictionary === value) {
1064
- this.slicedAttributeValues.push(this.attributeValueSetSubject.getValue().attributeValues[i]);
1065
- break;
1066
- }
1067
- }
1068
- }
1069
- //Only flagging dirty for non-grid rows (those are saved immediately)
1070
- if (!attribute.idGroupAttribute) {
1071
- this.dirty.next(true);
1072
- }
1073
- }
1074
- /**
1075
- * Get the attribute based upon the idAttribute. This is from the map of attributes.
1076
- *
1077
- * @param {number} idAttribute
1078
- * @returns {Attribute}
1079
- */
1080
- getAttribute(idAttribute) {
1081
- return this.attributeMap.get(idAttribute);
1082
- }
1083
- /**
1084
- * For the attribute configuration, set all of the negative ids to undefined prior to posting.
1085
- *
1086
- * @param {AttributeConfiguration} attributeConfiguration
1087
- */
1088
- setNegativeIdsToUndefined(attributeConfiguration) {
1089
- if (attributeConfiguration.idAttributeConfiguration < 0) {
1090
- attributeConfiguration.idAttributeConfiguration = undefined;
1091
- }
1092
- for (let attributeContainer of attributeConfiguration.attributeContainers) {
1093
- if (attributeContainer.idAttributeContainer < 0) {
1094
- attributeContainer.idAttributeContainer = undefined;
1095
- }
1096
- for (let attribute of attributeContainer.graphicalAttributes) {
1097
- if (attribute.idAttribute < 0) {
1098
- attribute.idAttribute = undefined;
1099
- }
1100
- if (attribute.attributeChoices) {
1101
- for (let attributeChoice of attribute.attributeChoices) {
1102
- delete attribute["value"];
1103
- if (attributeChoice.idAttribute < 0) {
1104
- attributeChoice.idAttribute = undefined;
1105
- }
1106
- if (attributeChoice.idAttributeChoice < 0) {
1107
- attributeChoice.idAttributeChoice = undefined;
1108
- }
1109
- }
1110
- }
1111
- }
1112
- }
1113
- }
1114
- /**
1115
- * Creates a display name for the attribute configuration based on the context code and id.
1116
- *
1117
- * @param {AttributeConfiguration} configuration
1118
- * @returns {string}
1119
- */
1120
- getConfigurationName(configuration) {
1121
- if (configuration.idAttributeConfiguration === -1) {
1122
- return "New";
1123
- }
1124
- let name = configuration.codeAttributeSecurityContextDisplay + ": " + configuration.extensionDescription;
1125
- if (configuration.idFilter1) {
1126
- name += " - " + configuration.filter1Display;
1127
- }
1128
- if (configuration.idFilter2) {
1129
- name += " - " + configuration.filter2Display;
1130
- }
1131
- return name;
1132
- }
1133
- getAttributeConfigurationDTO(cfg) {
1134
- if (!cfg) {
1135
- return undefined;
1136
- }
1137
- let dto = {
1138
- idAttributeConfiguration: cfg.idAttributeConfiguration,
1139
- codeAttributeContext: cfg.codeAttributeContext,
1140
- codeAttributeSecurityContext: cfg.codeAttributeSecurityContext,
1141
- idFilter1: cfg.idFilter1,
1142
- idFilter2: cfg.idFilter2
1143
- };
1144
- if (this.attributeContextListSubject.getValue()) {
1145
- dto.extensionDescription = this.attributeContextListSubject.getValue().filter((ctx) => {
1146
- return ctx.codeAttributeContext === cfg.codeAttributeContext;
1147
- })[0].extensionDescription;
1148
- }
1149
- if (this.attributeSecurityContextListSubject.getValue()) {
1150
- let result = this.attributeSecurityContextListSubject.getValue().filter((filter) => {
1151
- return filter.codeAttributeSecurityContext === cfg.codeAttributeSecurityContext;
1152
- });
1153
- dto.codeAttributeSecurityContextDisplay = (result && result.length > 0) ? result[0].description : undefined;
1154
- }
1155
- if (this.filter1ListSubject.getValue()) {
1156
- let result = this.filter1ListSubject.getValue().filter((filter) => {
1157
- return filter.codeAttributeContext === cfg.codeAttributeContext
1158
- && filter.codeAttributeSecurityContext === cfg.codeAttributeSecurityContext
1159
- && filter.idFilter1 === cfg.idFilter1;
1160
- });
1161
- dto.filter1Display = (result && result.length > 0) ? result[0].display : undefined;
1162
- }
1163
- if (this.filter2ListSubject.getValue()) {
1164
- let result = this.filter2ListSubject.getValue().filter((filter) => {
1165
- return filter.codeAttributeContext === cfg.codeAttributeContext
1166
- && filter.codeAttributeSecurityContext === cfg.codeAttributeSecurityContext
1167
- && filter.idFilter1 === cfg.idFilter1
1168
- && filter.idFilter2 === cfg.idFilter2;
1169
- });
1170
- dto.filter2Display = (result && result.length > 0) ? result[0].display : undefined;
1171
- }
1172
- return dto;
1173
- }
1174
- getSecurityCodeContext(code) {
1175
- return this.attributeSecurityContextListSubject.getValue().filter((filter) => {
1176
- return filter.codeAttributeSecurityContext === code;
1177
- })[0];
1178
- }
1179
- getAttributeContextLoadingSubject() {
1180
- return this.attributeContextLoadingSubject;
1181
- }
1182
- getFilter1For(codeAttributeContext, codeAttributeSecurityContext) {
1183
- return this.filter1ListSubject.getValue().filter((item) => {
1184
- return item.codeAttributeContext === codeAttributeContext && item.codeAttributeSecurityContext === codeAttributeSecurityContext;
1185
- });
1186
- }
1187
- getFilter2For(codeAttributeContext, codeAttributeSecurityContext, idFilter1) {
1188
- return this.filter2ListSubject.getValue().filter((item) => {
1189
- return item.codeAttributeContext === codeAttributeContext
1190
- && item.codeAttributeSecurityContext === codeAttributeSecurityContext
1191
- && item.idFilter1 === idFilter1;
1192
- });
1193
- }
1194
- /**
1195
- * Track new idAttributeValues via a negative number for internal tracking. Remove this fake id prior to post.
1196
- *
1197
- * @returns {number}
1198
- */
1199
- getUniqueId() {
1200
- return --this.uniqueId;
1201
- }
1202
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AttributeService, deps: [{ token: i1.DictionaryService }, { token: i2.HttpClient }, { token: i3.Router }, { token: ATTRIBUTE_ENDPOINT }], target: i0.ɵɵFactoryTarget.Injectable }); }
1203
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AttributeService }); }
1204
- }
1205
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AttributeService, decorators: [{
1206
- type: Injectable
1207
- }], ctorParameters: function () { return [{ type: i1.DictionaryService }, { type: i2.HttpClient }, { type: i3.Router }, { type: undefined, decorators: [{
1208
- type: Inject,
1209
- args: [ATTRIBUTE_ENDPOINT]
1210
- }] }]; } });
1211
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0cmlidXRlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb2Qvc3JjL3NlcnZpY2VzL2F0dHJpYnV0ZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDNUUsT0FBTyxFQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RCxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFdkMsT0FBTyxFQUFDLGVBQWUsRUFBRSxRQUFRLEVBQWMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBRXBFLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLCtDQUErQyxDQUFDO0FBV2hGLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRCxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxpQ0FBaUMsQ0FBQzs7Ozs7QUFHckUsTUFBTSxDQUFDLElBQUksa0JBQWtCLEdBQUcsSUFBSSxjQUFjLENBQVMsbUJBQW1CLENBQUMsQ0FBQztBQUNoRixNQUFNLENBQUMsTUFBTSxPQUFPLEdBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDNUMsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBRTFEOzs7R0FHRztBQUVILE1BQU0sT0FBTyxnQkFBZ0I7SUE4QzNCLFlBQW9CLGlCQUFvQyxFQUNwQyxJQUFnQixFQUNoQixNQUFjLEVBQ2MsaUJBQXlCO1FBSHJELHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUNoQixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2Msc0JB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O0lBQ1IsQ0FBQztJQUVELGlDQUFpQztRQUMvQixPQUFPLElBQUksQ0FBQyw4QkFBOEIsQ0FBQztJQUM3QyxDQUFDO0lBRUQsYUFBYSxDQUFDLG9CQUE0QixFQUFFLDRCQUFvQztRQUM5RSxPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFTLEVBQUUsRUFBRTtZQUM3RCxPQUFPLElBQUksQ0FBQyxvQkFBb0IsS0FBSyxvQkFBb0IsSUFBSSxJQUFJLENBQUMsNEJBQTRCLEtBQUssNEJBQTRCLENBQUM7UUFDbEksQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsYUFBYSxDQUFDLG9CQUE0QixFQUFFLDRCQUFvQyxFQUFFLFNBQWlCO1FBQ2pHLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQVMsRUFBRSxFQUFFO1lBQzdELE9BQU8sSUFBSSxDQUFDLG9CQUFvQixLQUFLLG9CQUFvQjttQkFDcEQsSUFBSSxDQUFDLDRCQUE0QixLQUFLLDRCQUE0QjttQkFDbEUsSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUM7UUFDcEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILFdBQVc7UUFDVCxPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN6QixDQUFDOytHQWw1Q1UsZ0JBQWdCLG1HQWlEUCxrQkFBa0I7bUhBakQzQixnQkFBZ0I7OzRGQUFoQixnQkFBZ0I7a0JBRDVCLFVBQVU7OzBCQWtESSxNQUFNOzJCQUFDLGtCQUFrQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7SW5qZWN0LCBJbmplY3RhYmxlLCBJbmplY3Rpb25Ub2tlbiwgaXNEZXZNb2RlfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xyXG5pbXBvcnQge0h0dHBDbGllbnQsIEh0dHBQYXJhbXN9IGZyb20gXCJAYW5ndWxhci9jb21tb24vaHR0cFwiO1xyXG5pbXBvcnQge1JvdXRlcn0gZnJvbSBcIkBhbmd1bGFyL3JvdXRlclwiO1xyXG5cclxuaW1wb3J0IHtCZWhhdmlvclN1YmplY3QsIGZvcmtKb2luLCBPYnNlcnZhYmxlLCBTdWJqZWN0fSBmcm9tIFwicnhqc1wiO1xyXG5cclxuaW1wb3J0IHtEaWN0aW9uYXJ5U2VydmljZX0gZnJvbSBcIkBodW50c21hbi1jYW5jZXItaW5zdGl0dXRlL2RpY3Rpb25hcnktc2VydmljZVwiO1xyXG5cclxuaW1wb3J0IHtBdHRyaWJ1dGV9IGZyb20gXCIuLi9tb2RlbC9hdHRyaWJ1dGUuZW50aXR5XCI7XHJcbmltcG9ydCB7QXR0cmlidXRlQ2hvaWNlfSBmcm9tIFwiLi4vbW9kZWwvYXR0cmlidXRlLWNob2ljZS5lbnRpdHlcIjtcclxuaW1wb3J0IHtBdHRyaWJ1dGVWYWx1ZX0gZnJvbSBcIi4uL21vZGVsL2F0dHJpYnV0ZS12YWx1ZS5lbnRpdHlcIjtcclxuaW1wb3J0IHtBdHRyaWJ1dGVDb25maWd1cmF0aW9ufSBmcm9tIFwiLi4vbW9kZWwvYXR0cmlidXRlLWNvbmZpZ3VyYXRpb24uZW50aXR5XCI7XHJcbmltcG9ydCB7QXR0cmlidXRlVmFsdWVTZXR9IGZyb20gXCIuLi9tb2RlbC9hdHRyaWJ1dGUtdmFsdWUtc2V0LmVudGl0eVwiO1xyXG5pbXBvcnQge0F0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE99IGZyb20gXCIuLi9tb2RlbC9hdHRyaWJ1dGUtY29uZmlndXJhdGlvbi5kdG9cIjtcclxuaW1wb3J0IHtHcmFwaGljYWxBdHRyaWJ1dGV9IGZyb20gXCIuLi9tb2RlbC9ncmFwaGljYWwtYXR0cmlidXRlLmVudGl0eVwiO1xyXG5pbXBvcnQge0F0dHJpYnV0ZUNvbnRhaW5lcn0gZnJvbSBcIi4uL21vZGVsL2F0dHJpYnV0ZS1jb250YWluZXIuZW50aXR5XCI7XHJcbmltcG9ydCB7QXR0cmlidXRlVmFsdWVHcmlkUm93fSBmcm9tIFwiLi4vbW9kZWwvYXR0cmlidXRlLXZhbHVlLWdyaWQtcm93LmVudGl0eVwiO1xyXG5pbXBvcnQge1ByZUV2YWxEVE99IGZyb20gXCIuLi9tb2RlbC9wcmUtZXZhbC5kdG9cIjtcclxuaW1wb3J0IHtEaWN0aW9uYXJ5RW50cmllc0RUT30gZnJvbSBcIi4uL21vZGVsL2RpY3Rpb25hcnktZW50cmllcy5kdG9cIjtcclxuXHJcblxyXG5leHBvcnQgbGV0IEFUVFJJQlVURV9FTkRQT0lOVCA9IG5ldyBJbmplY3Rpb25Ub2tlbjxzdHJpbmc+KFwiYXR0cmlidXRlRW5kcG9pbnRcIik7XHJcbmV4cG9ydCBjb25zdCBCT09MRUFOOiBzdHJpbmdbXSA9IFtcIk5cIiwgXCJZXCJdO1xyXG5leHBvcnQgY29uc3QgRVhURU5ERURfQk9PTEVBTjogc3RyaW5nW10gPSBbXCJOXCIsIFwiWVwiLCBcIlVcIl07XHJcblxyXG4vKipcclxuICogQSBzZXJ2aWNlIGNyZWF0ZWQgZm9yIGVhY2ggYXR0cmlidXRlIGNvbmZpZ3VyYXRpb24gaW5zdGFuY2UuICBUaGlzIG1ha2VzIGNhbGxzIHRvIHRoZSBiYWNrZW5kIHRvIGdldCB0aGUgY29uZmlndXJhdGlvblxyXG4gKiBhbmQgdmFsdWUgc2V0LiAgSXQgYWxzbyBzdG9yZXMgY29tbW9uIGRhdGEgdGhhdCBkaWZmZXJlbnQgYXR0cmlidXRlcyBtaWdodCBuZWVkIChlLmcuIGEgbGlzdCBvZiBhdHRyaWJ1dGUgY2hvaWNlcykuXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBBdHRyaWJ1dGVTZXJ2aWNlIHtcclxuXHJcbiAgbmV3QXR0cmlidXRlQ29uZmlndXJhdGlvbjogQXR0cmlidXRlQ29uZmlndXJhdGlvbjtcclxuICBpZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IG51bWJlcjtcclxuICBpZEZpbHRlcjE6IG51bWJlcjtcclxuICBpZEZpbHRlcjI6IG51bWJlcjtcclxuICBpZEF0dHJpYnV0ZVZhbHVlU2V0OiBudW1iZXI7XHJcbiAgaWRQYXJlbnRPYmplY3Q6IG51bWJlcjtcclxuICBib3VuZERhdGE6IGFueTtcclxuXHJcbiAgYXR0cmlidXRlQ29udGV4dExvYWRpbmdTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcclxuXHJcbiAgYXR0cmlidXRlQ29udGV4dExpc3RTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8YW55W10+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxhbnlbXT4odW5kZWZpbmVkKTtcclxuICBhdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRMaXN0U3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGFueVtdPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8YW55W10+KHVuZGVmaW5lZCk7XHJcbiAgZmlsdGVyMUxpc3RTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8YW55W10+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxhbnlbXT4odW5kZWZpbmVkKTtcclxuICBmaWx0ZXIyTGlzdFN1YmplY3Q6IEJlaGF2aW9yU3ViamVjdDxhbnlbXT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGFueVtdPih1bmRlZmluZWQpO1xyXG4gIGRpY3Rpb25hcnlMaXN0U3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGFueVtdPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8YW55W10+KHVuZGVmaW5lZCk7XHJcblxyXG5cclxuICBwb3N0Q29uZmlndXJhdGlvblN1YmplY3Q6IFN1YmplY3Q8Ym9vbGVhbj4gPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xyXG4gIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EaW1lbnNpb25TdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8YW55PiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8YW55Pih1bmRlZmluZWQpO1xyXG5cclxuICBhdHRyaWJ1dGVDb25maWd1cmF0aW9uTGlzdFN1YmplY3Q6IEJlaGF2aW9yU3ViamVjdDxBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPW10+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPW10+KHVuZGVmaW5lZCk7XHJcbiAgYXR0cmlidXRlQ29uZmlndXJhdGlvbkxpc3RMb2FkaW5nU3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XHJcblxyXG4gIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE9TdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8QXR0cmlidXRlQ29uZmlndXJhdGlvbkRUTz4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8+KHVuZGVmaW5lZCk7XHJcblxyXG4gIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25TdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8QXR0cmlidXRlQ29uZmlndXJhdGlvbj4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24+KHVuZGVmaW5lZCk7XHJcbiAgYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8QXR0cmlidXRlVmFsdWVTZXQ+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZVNldD4odW5kZWZpbmVkKTtcclxuICBhdHRyaWJ1dGVWYWx1ZVB1c2hlZFN1YmplY3Q6IFN1YmplY3Q8QXR0cmlidXRlVmFsdWU+ID0gbmV3IFN1YmplY3Q8QXR0cmlidXRlVmFsdWU+KCk7XHJcblxyXG4gIGxvYWRpbmdTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcclxuXHJcbiAgYXR0cmlidXRlTWFwOiBNYXA8bnVtYmVyLCBBdHRyaWJ1dGU+ID0gbmV3IE1hcDxudW1iZXIsIEF0dHJpYnV0ZT4oKTtcclxuXHJcbiAgd2lkdGg6IG51bWJlcjtcclxuXHJcbiAgY29udGFpbmVyVXBkYXRlZDogU3ViamVjdDxib29sZWFuPiA9IG5ldyBTdWJqZWN0PGJvb2xlYW4+KCk7XHJcbiAgZ3JpZFJvd1NhdmVkOiBTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlR3JpZFJvdz4gPSBuZXcgU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZUdyaWRSb3c+KCk7XHJcbiAgZ3JpZFJvd0RlbGV0ZWQ6IFN1YmplY3Q8QXR0cmlidXRlVmFsdWVHcmlkUm93PiA9IG5ldyBTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlR3JpZFJvdz4oKTtcclxuICBkaXJ0eTogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XHJcbiAgdXBkYXRlZEF0dHJpYnV0ZVZhbHVlczogQXR0cmlidXRlVmFsdWVbXSA9IFtdO1xyXG4gIHNsaWNlZEF0dHJpYnV0ZVZhbHVlczogQXR0cmlidXRlVmFsdWVbXSA9IFtdO1xyXG5cclxuICBwcml2YXRlIHVuaXF1ZUlkOiBudW1iZXIgPSAwO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGRpY3Rpb25hcnlTZXJ2aWNlOiBEaWN0aW9uYXJ5U2VydmljZSxcclxuICAgICAgICAgICAgICBwcml2YXRlIGh0dHA6IEh0dHBDbGllbnQsXHJcbiAgICAgICAgICAgICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcclxuICAgICAgICAgICAgICBASW5qZWN0KEFUVFJJQlVURV9FTkRQT0lOVCkgcHJpdmF0ZSBhdHRyaWJ1dGVFbmRwb2ludDogc3RyaW5nKSB7XHJcbiAgICBpZiAoaXNEZXZNb2RlKCkpIHtcclxuICAgICAgY29uc29sZS5kZWJ1ZyhcIkNyZWF0ZWQgTmV3IEF0dHJpYnV0ZVNlcnZpY2VcIik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzZXRCb3VuZERhdGEoYm91bmREYXRhOiBhbnkpIHtcclxuICAgIHRoaXMuYm91bmREYXRhID0gYm91bmREYXRhO1xyXG5cclxuICAgIGlmICh0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpKSB7XHJcbiAgICAgIHRoaXMubm90aWZ5QXR0cmlidXRlcygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0QXR0cmlidXRlVmFsdWVDb3VudEJ5QXR0cmlidXRlKGlkQXR0cmlidXRlOiBudW1iZXIpOiBPYnNlcnZhYmxlPG51bWJlcj4ge1xyXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8bnVtYmVyPih0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJhdHRyaWJ1dGUtdmFsdWUtY291bnRcIiwge3BhcmFtczogbmV3IEh0dHBQYXJhbXMoKS5zZXQoXCJpZEF0dHJpYnV0ZVwiLCBpZEF0dHJpYnV0ZS50b1N0cmluZygpKX0pO1xyXG4gIH1cclxuXHJcbiAgZ2V0QXR0cmlidXRlVmFsdWVDb3VudEJ5Q29udGFpbmVyKGlkQXR0cmlidXRlQ29udGFpbmVyOiBudW1iZXIpOiBPYnNlcnZhYmxlPG51bWJlcj4ge1xyXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8bnVtYmVyPih0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJhdHRyaWJ1dGUtdmFsdWUtY291bnRcIiwge3BhcmFtczogbmV3IEh0dHBQYXJhbXMoKS5zZXQoXCJpZEF0dHJpYnV0ZUNvbnRhaW5lclwiLCBpZEF0dHJpYnV0ZUNvbnRhaW5lci50b1N0cmluZygpKX0pO1xyXG4gIH1cclxuXHJcbiAgZ2V0RGljdGlvbmFyeVZhbHVlQ291bnQoaWRBdHRyaWJ1dGVEaWN0aW9uYXJ5OiBudW1iZXIpOiBPYnNlcnZhYmxlPG51bWJlcj4ge1xyXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8bnVtYmVyPih0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJhdHRyaWJ1dGUtZGljdGlvbmFyeS1jb3VudFwiLCB7cGFyYW1zOiBuZXcgSHR0cFBhcmFtcygpLnNldChcImlkQXR0cmlidXRlRGljdGlvbmFyeVwiLCBpZEF0dHJpYnV0ZURpY3Rpb25hcnkudG9TdHJpbmcoKSl9KTtcclxuICB9XHJcblxyXG4gIGZldGNoQXR0cmlidXRlQ29udGV4dCgpOiB2b2lkIHtcclxuICAgIHRoaXMuYXR0cmlidXRlQ29udGV4dExvYWRpbmdTdWJqZWN0Lm5leHQodHJ1ZSk7XHJcblxyXG4gICAgZm9ya0pvaW4oW1xyXG4gICAgICB0aGlzLmRpY3Rpb25hcnlTZXJ2aWNlLmdldERpY3Rpb25hcnlFbnRyaWVzKFwiaGNpLnJpLmF0dHIubW9kZWwuQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0XCIpLFxyXG4gICAgICB0aGlzLmRpY3Rpb25hcnlTZXJ2aWNlLmdldERpY3Rpb25hcnlFbnRyaWVzKFwiaGNpLnJpLmF0dHIubW9kZWwuQXR0cmlidXRlQ29udGV4dFwiKSxcclxuICAgICAgdGhpcy5kaWN0aW9uYXJ5U2VydmljZS5nZXREaWN0aW9uYXJ5RW50cmllcyhcImhjaS5yaS5hdHRyLm1vZGVsLkZpbHRlcjFcIiksXHJcbiAgICAgIHRoaXMuZGljdGlvbmFyeVNlcnZpY2UuZ2V0RGljdGlvbmFyeUVudHJpZXMoXCJoY2kucmkuYXR0ci5tb2RlbC5GaWx0ZXIyXCIpLFxyXG4gICAgICB0aGlzLmRpY3Rpb25hcnlTZXJ2aWNlLmdldERpY3Rpb25hcnlFbnRyaWVzKFwiaGNpLnJpLmF0dHIubW9kZWwuQXR0cmlidXRlRGljdGlvbmFyeVwiKVxyXG4gICAgXSkuc3Vic2NyaWJlKChyZXNwb25zZXM6IGFueVtdKSA9PiB7XHJcblxyXG4gICAgICB0aGlzLmRpY3Rpb25hcnlMaXN0U3ViamVjdC5uZXh0KHJlc3BvbnNlc1s0XSk7XHJcbiAgICAgIHRoaXMuZmlsdGVyMUxpc3RTdWJqZWN0Lm5leHQocmVzcG9uc2VzWzJdKTtcclxuICAgICAgdGhpcy5maWx0ZXIyTGlzdFN1YmplY3QubmV4dChyZXNwb25zZXNbM10pO1xyXG4gICAgICB0aGlzLmF0dHJpYnV0ZUNvbnRleHRMaXN0U3ViamVjdC5uZXh0KHJlc3BvbnNlc1sxXSk7XHJcblxyXG4gICAgICByZXNwb25zZXNbMF0uc29ydCh0aGlzLnNvcnRBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRMaXN0KTtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRMaXN0U3ViamVjdC5uZXh0KHJlc3BvbnNlc1swXSk7XHJcblxyXG4gICAgICB0aGlzLmF0dHJpYnV0ZUNvbnRleHRMb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy9HZXRzIHRoZSBkaWN0aW9uYXJ5IGVudHJpZXMgZnJvbSB0aGUgbWFwIChzbyB3ZSBkb24ndCBsb2FkIG92ZXIgYW5kIG92ZXIgYW5kIG92ZXIgZm9yIHRoZSBzYW1lIGRpY3Rpb25hcnkpXHJcbiAgZ2V0RGljdGlvbmFyeUVudHJpZXMoYXR0cmlidXRlOiBBdHRyaWJ1dGUsIHZhbHVlczogQXR0cmlidXRlVmFsdWVbXSwgZ3JvdXBBdHRyaWJ1dGVSb3dJZD86IG51bWJlciwgcmVmZXJlbmNlZEF0dHJpYnV0ZVZhbHVlPzogQXR0cmlidXRlVmFsdWUpOiBPYnNlcnZhYmxlPERpY3Rpb25hcnlFbnRyaWVzRFRPPiB7XHJcbiAgICBsZXQgYnMgPSBuZXcgU3ViamVjdDxEaWN0aW9uYXJ5RW50cmllc0RUTz4oKTtcclxuXHJcbiAgICAvL0hhbmRsZSBYUEFUSFxyXG4gICAgaWYgKGF0dHJpYnV0ZS5hdHRyaWJ1dGVEaWN0aW9uYXJ5LnhwYXRoKSB7XHJcbiAgICAgIGxldCBlbnRyaWVzRFRPID0gbmV3IERpY3Rpb25hcnlFbnRyaWVzRFRPKCk7XHJcbiAgICAgIGxldCB4cGF0aCA9IGF0dHJpYnV0ZS5hdHRyaWJ1dGVEaWN0aW9uYXJ5LnhwYXRoO1xyXG5cclxuICAgICAgLy9GaWx0ZXJlZCBieSBhbm90aGVyIGRpY3Rpb25hcnk/IFBhcnNlIHRvIGdldCBhcnJheSBvZiBhbGwgZGljdGlvbmFyeSBjbGFzcyBuYW1lcyBuZWVkZWRcclxuICAgICAgbGV0IGRpY3RDbGFzc2VzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICBsZXQgcG9zID0gMDtcclxuICAgICAgd2hpbGUgKHhwYXRoLmluZGV4T2YoXCIvRGljdGlvbmFyaWVzL0RpY3Rpb25hcnlcIiwgcG9zKSA+PSAwKSB7XHJcbiAgICAgICAgbGV0IHN0YXJ0ID0geHBhdGguaW5kZXhPZihcIi9EaWN0aW9uYXJpZXMvRGljdGlvbmFyeVwiLCBwb3MpO1xyXG4gICAgICAgIHN0YXJ0ID0geHBhdGguaW5kZXhPZihcIidcIiwgc3RhcnQpO1xyXG4gICAgICAgIGxldCBlbmQgPSB4cGF0aC5pbmRleE9mKFwiJ1wiLCBzdGFydCArIDEpO1xyXG4gICAgICAgIGRpY3RDbGFzc2VzLnB1c2goYXR0cmlidXRlLmF0dHJpYnV0ZURpY3Rpb25hcnkueHBhdGguc3Vic3RyaW5nKHN0YXJ0ICsgMSwgZW5kKSlcclxuICAgICAgICBwb3MgPSBlbmQ7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vUG90ZW50aWFsbHkgbG9hZCBtdWx0aXBsZSBkaWN0aW9uYXJpZXNcclxuICAgICAgbGV0IGZvcmtDYWxscyA9IFtdO1xyXG4gICAgICBmb3IgKGxldCBjbGFzc05hbWUgb2YgZGljdENsYXNzZXMpIHtcclxuICAgICAgICBmb3JrQ2FsbHMucHVzaCh0aGlzLmRpY3Rpb25hcnlTZXJ2aWNlLmdldERpY3Rpb25hcnlFbnRyaWVzQXNYTUwoY2xhc3NOYW1lKSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vRGVhbCB3aXRoIHRoZSByZXN1bHRzIHRvZ2V0aGVyXHJcbiAgICAgIGZvcmtKb2luKGZvcmtDYWxscykuc3Vic2NyaWJlKChyZXNwb25zZXM6IGFueVtdKSA9PiB7XHJcbiAgICAgICAgLy9XZSdyZSBvbmx5IGdvaW5nIHRvIGRvIHhwYXRoIG9uIHRoZSB4bWwgZm9yIHRoZSBmaXJzdCBkaWN0aW9uYXJ5XHJcbiAgICAgICAgY29uc3QgcGFyc2VyID0gbmV3IERPTVBhcnNlcigpO1xyXG4gICAgICAgIGxldCBkb2MgPSBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKHJlc3BvbnNlc1swXSwgXCJhcHBsaWNhdGlvbi94bWxcIik7XHJcblxyXG4gICAgICAgIC8vSGF2ZSB0byBldmFsdWF0ZSBzdWItZXhwcmVzc2lvbi4gVGhpcyBkb2Vzbid0IGFjdHVhbGx5IHN1cHBvcnQgZXhwcmVzc2lvbnMgbGlrZSBbQHggPSAoL3hwYXRoLXN1Yi1leHByZXNzaW9uKV1cclxuICAgICAgICBsZXQgc2Vjb25kYXJ5WG1sID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIGlmIChyZXNwb25zZXMubGVuZ3RoID4gMSkge1xyXG4gICAgICAgICAgc2Vjb25kYXJ5WG1sID0gcmVzcG9uc2VzWzFdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9QcmUtZXZhbHVhdGUgYW5kIHNpbXBsaWZ5IFhQQVRIXHJcbiAgICAgICAgbGV0IGR0bzpQcmVFdmFsRFRPID0gdGhpcy5wcmVFdmFsdWF0ZVhwYXRoKGF0dHJpYnV0ZS5hdHRyaWJ1dGVEaWN0aW9uYXJ5LnhwYXRoLCBzZWNvbmRhcnlYbWwsIGdyb3VwQXR0cmlidXRlUm93SWQsIHJlZmVyZW5jZWRBdHRyaWJ1dGVWYWx1ZSk7XHJcblxyXG4gICAgICAgIC8vRXZhbHVhdGUgWFBBVEggZXhwcmVzc2lvblxyXG4gICAgICAgIGxldCBlbnRyaWVzID0gW107XHJcbiAgICAgICAgZW50cmllc0RUTy5lbnRyaWVzSW5jbHVkZVNlbGVjdGVkVmFsdWUgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgdHJ5e1xyXG4gICAgICAgICAgbGV0IHhQYXRoUmVzdWx0ID0gZG9jdW1lbnQuZXZhbHVhdGUoZHRvLmV4cHJlc3Npb24sIGRvYywgbnVsbCwgWFBhdGhSZXN1bHQuQU5ZX1RZUEUsIG51bGwpO1xyXG5cclxuICAgICAgICAgIC8vSXRlcmF0ZSB4cGF0aCByZXN1bHRzIChub2RlcylcclxuICAgICAgICAgIHZhciBub2RlID0gbnVsbDtcclxuICAgICAgICAgIHdoaWxlKG5vZGUgPSB4UGF0aFJlc3VsdC5pdGVyYXRlTmV4dCgpKSB7XHJcblxyXG4gICAgICAgICAgICBsZXQgZW50cnkgPSB0aGlzLmdldEpzb25FbnRyeUZyb21Ob2RlKG5vZGUpO1xyXG4gICAgICAgICAgICBlbnRyaWVzLnB1c2goZW50cnkpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1jYXRjaCAoZSkge1xyXG4gICAgICAgICAgLy8gTm8gbWF0Y2hpbmcgZW50cmllcyBoZXJlLlxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9XaGF0IGFib3V0IGRpY3Rpb25hcnkgZW50cmllcyB3aGVyZSBpc0FjdGl2ZT0nTicsIGJ1dCB0aGUgaWQgd2FzIHVzZWQgaW4gYSBwcmV2aW91c2x5IHNhdmVkIHZhbHVlP1xyXG4gICAgICAgIC8vV2UgYWRkIHRoYXQgdmFsdWUgdG8gdGhlIGRyb3Bkb3duLCBpbiB0aGF0IGNhc2UsIHNvIGl0IGNhbiBiZSBzZWxlY3RlZFxyXG4gICAgICAgIC8vUmVmZXJlbmNlZEF0dHJpYnV0ZVZhbHVlIG9ubHkgZ2V0cyBwYXNzZWQgaW4gd2hlbiB0aGUgZmlsdGVyIGF0dHJpYnV0ZSBjaGFuZ2VzLiBJbiB0aGF0IHNjZW5hcmlvIHdlIGRvIG5vdCB3YW50IHRvIGFkZCB0aGUgb2xkIHZhbHVlIHRvIHRoZSBsaXN0XHJcbiAgICAgICAgaWYgKGF0dHJpYnV0ZS5pc011bHRpVmFsdWUgIT09IFwiWVwiKSB7XHJcbiAgICAgICAgICBmb3IgKGxldCBhdiBvZiB2YWx1ZXMpIHtcclxuICAgICAgICAgICAgbGV0IHByZXNlbnQ6Ym9vbGVhbiA9IGZhbHNlO1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgICAgIGlmIChhdiAmJiAhIHJlZmVyZW5jZWRBdHRyaWJ1dGVWYWx1ZSkge1xyXG4gICAgICAgICAgICAgIGZvcih2YXIgaSA9IGVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICAgICAgICAgIGlmIChlbnRyaWVzW2ldLnZhbHVlID09PSBhdi52YWx1ZUlkRGljdGlvbmFyeSkge1xyXG4gICAgICAgICAgICAgICAgICBwcmVzZW50ID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgIC8vSWYgdGhlIGN1cnJlbnRseSBzYXZlZCB2YWx1ZSBpcyBub3QgaW4gdGhlIGxpc3QsIGFkZCBpdC5cclxuICAgICAgICAgICAgICBpZiAoISBwcmVzZW50KSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBsZXQgeHBhdGggPSBcIi9EaWN0aW9uYXJpZXMvRGljdGlvbmFyeVtAY2xhc3NOYW1lPSdcIiArIGF0dHJpYnV0ZS5hdHRyaWJ1dGVEaWN0aW9uYXJ5LmNsYXNzTmFtZSArIFwiJ10vRGljdGlvbmFyeUVudHJ5W0B2YWx1ZT0nXCIgKyBhdi52YWx1ZUlkRGljdGlvbmFyeSArIFwiJ11cIjtcclxuICAgICAgICAgICAgICAgIC8vVGhlIGVudHJ5IHdhcyBwcm9iYWJseSBhbHJlYWR5IGxvYWRlZCwgYnV0IGV4Y2x1ZGVkIGJ5IHRoZSB4cGF0aC4gV2UgY2FuIHVzZSB0aGF0LlxyXG4gICAgICBcclxuICAgICAgICAgICAgICAgIGxldCBub2RlID0gZG9jdW1lbnQuZXZhbHVhdGUoeHBhdGgsIGRvYywgbnVsbCwgWFBhdGhSZXN1bHQuQU5ZX1VOT1JERVJFRF9OT0RFX1RZUEUsIG51bGwpLnNpbmdsZU5vZGVWYWx1ZTtcclxuICAgICAgICAgICAgICAgIGlmIChub2RlKSB7XHJcbiAgICAgICAgICAgICAgICAgIGVudHJpZXMucHVzaCh0aGlzLmdldEpzb25FbnRyeUZyb21Ob2RlKG5vZGUpKTtcclxuICAgICAgICAgICAgICAgICAgZW50cmllc0RUTy5lbnRyaWVzSW5jbHVkZVNlbGVjdGVkVmFsdWUgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcblxyXG4gICAgICAgIC8vU2V0IHRoZSBiZWhhdmlvciBzdWJqZWN0IHdpdGggdGhlIGZpbHRlcmVkIHZhbHVlcyBmb3IgdGhlIGRpY3Rpb25hcnlcclxuICAgICAgICBlbnRyaWVzRFRPLmVudHJpZXMgPSBlbnRyaWVzO1xyXG4gICAgICAgIGVudHJpZXNEVE8ucmVmZXJlbmNlZEF0dHJpYnV0ZSA9IGR0by5yZWZlcmVuY2VkQXR0cmlidXRlO1xyXG4gICAgICAgIGJzLm5leHQoZW50cmllc0RUTyk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgIH1cclxuICAgIC8vTm9uLXhwYXRoXHJcbiAgICBlbHNlIHtcclxuICAgICAgLy9EaWN0aW9uYXlTZXJ2aWNlIGp1c3QgdXNlZCBodHRwIGdldCwgc28gc2hvdWxkIG5vdCBuZWVkIHRvIHVuc3Vic2NyaWJlLCBzaW5jZSBodHRwIGRvZXMgdGhhdFxyXG4gICAgICB0aGlzLmRpY3Rpb25hcnlTZXJ2aWNlLmdldERpY3Rpb25hcnlEcm9wZG93bkVudHJpZXMoYXR0cmlidXRlLmF0dHJpYnV0ZURpY3Rpb25hcnkuY2xhc3NOYW1lKS5zdWJzY3JpYmUoKGVudHJpZXM6IGFueVtdKSA9PiB7XHJcbiAgICAgICAgLy9NYWtlIHZhbHVlIGZpZWxkc1xyXG4gICAgICAgIGZvcih2YXIgaSA9IGVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICAgIGVudHJpZXNbaV0udmFsdWUgPSBlbnRyaWVzW2ldLmlkLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgZW50cmllc0RUTyA9IG5ldyBEaWN0aW9uYXJ5RW50cmllc0RUTygpO1xyXG4gICAgICAgIGVudHJpZXNEVE8uZW50cmllcyA9IGVudHJpZXM7XHJcbiAgICAgICAgZW50cmllc0RUTy5lbnRyaWVzSW5jbHVkZVNlbGVjdGVkVmFsdWUgPSB0cnVlOyAvL0EgYml0IG9mIGFuIGFzc3VtcHRpb24sIGJ1dCBpZiBpdCBpc24ndCBmaWx0ZXJlZCwgaXQgaGFkIGJldHRlciBpbmNsdWRlIGFsbCB0aGUgdmFsdWVzIVxyXG4gICAgICAgIGJzLm5leHQoZW50cmllc0RUTyk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBicztcclxuICB9XHJcblxyXG4gIGdldEpzb25FbnRyeUZyb21Ob2RlKG5vZGU6IGFueSk6IGFueSB7XHJcbiAgICAvL0NyZWF0ZSBKU09OIG9iamVjdHMgZnJvbSB0aGUgbm9kZXNcclxuICAgIGxldCBlbnRyeTogYW55ID0ge307XHJcbiAgICBmb3IodmFyIGkgPSBub2RlLmF0dHJpYnV0ZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgZW50cnlbbm9kZS5hdHRyaWJ1dGVzW2ldLm5hbWVdID0gbm9kZS5hdHRyaWJ1dGVzW2ldLnZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBlbnRyeTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJlRXZhbHVhdGVYcGF0aCh4cGF0aDogc3RyaW5nLCBzZWNvbmRhcnlYbWw6IHN0cmluZywgZ3JvdXBBdHRyaWJ1dGVSb3dJZDogbnVtYmVyLCByZWZlcmVuY2VkQXR0cmlidXRlVmFsdWU6IEF0dHJpYnV0ZVZhbHVlKTogUHJlRXZhbERUTyB7XHJcbiAgICBsZXQgZHRvOlByZUV2YWxEVE8gPSBuZXcgUHJlRXZhbERUTygpO1xyXG5cclxuICAgIC8vU2VjdXJpdHlBZHZpc29yL0Bjb2RlQ2FuY2VyR3JvdXBcclxuICAgIHdoaWxlICh4cGF0aC5pbmRleE9mKFwiL1NlY3VyaXR5QWR2aXNvci9AY29kZUNhbmNlckdyb3VwXCIpID49IDApIHtcclxuICAgICAgeHBhdGggPSB4cGF0aC5yZXBsYWNlKFwiL1NlY3VyaXR5QWR2aXNvci9AY29kZUNhbmNlckdyb3VwXCIsIFwiJ1wiICsgdGhpcy5nZXRBdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdCgpLnZhbHVlLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQgKyBcIidcIik7XHJcbiAgICB9XHJcblxyXG4gICAgLy9SZXBsYWNlIHNvbWUgb2YgdGhlIGNvbnRleHQgcGFyYW1ldGVycyAke3gudmFsdWV9IC0gVGhpcyBpcyBtb3JlIEFsdGlvIHNwZWNpZmljIHN0dWZmIHRoYXQgd2FzIHVzZWQgaW4gQ0NSXHJcbiAgICBsZXQgcGFyYW1Qb3MgPSB4cGF0aC5zZWFyY2goXCJcXFxcJHtbQS1aYS16MC05X10rXFxcXC52YWx1ZX1cIik7XHJcbiAgICB3aGlsZSAocGFyYW1Qb3MgPj0gMCkge1xyXG4gICAgICBsZXQgcHJlZml4ID0geHBhdGguc3Vic3RyaW5nKDAsIHBhcmFtUG9zKTtcclxuICAgICAgbGV0IHZhck5hbWUgPSB4cGF0aC5zdWJzdHJpbmcocGFyYW1Qb3MgKyAyLCB4cGF0aC5pbmRleE9mKFwiLlwiLCBwYXJhbVBvcykpO1xyXG4gICAgICBsZXQgc3VmZml4ID0geHBhdGguc3Vic3RyaW5nKHhwYXRoLmluZGV4T2YoXCJ9XCIsIHBhcmFtUG9zKSArIDEpO1xyXG5cclxuICAgICAgdmFyIGF2O1xyXG5cclxuICAgICAgLy9JZiB0aGVyZSBJUyBhIHJlZmVyZW5jZWRBdHRyaWJ1dGVWYWx1ZSwgd2UgY2FuIHVzZSB0aGUgdmFsdWUgZGlyZWN0bHkuIE90aGVyd2lzZSB3ZSB0cnkgdG8gZmluZCBpdCBpbiB0aGUgQVZTXHJcbiAgICAgIGlmICghIHJlZmVyZW5jZWRBdHRyaWJ1dGVWYWx1ZSkge1xyXG5cclxuICAgICAgICAvL0ZpbmQgdGhlIGF0dHJpYnV0ZSwgbWF0Y2hpbmcgdGhlIHZhck5hbWUuXHJcbiAgICAgICAgLy9EbyB0aGlzIGZpcnN0LCBzbyB3ZSBnZXQgYSByZWZlcmVuY2UgdG8gdGhlIHJlbGF0ZWQgYXR0cmlidXRlLCByZWdhcmRsZXNzIG9mIHdoZXRoZXIgdGhlcmUgaXMgYWxyZWFkeSBhIHZhbHVlXHJcblxyXG4gICAgICAgIC8vSXRlcmF0ZSBhdHRyaWJ1dGVzIHRvIGZpbmQgb25lIHRoYXQgbWF0Y2hlcyB0aGUgdmFsdWVcclxuICAgICAgICB0aGlzLmF0dHJpYnV0ZU1hcC5mb3JFYWNoKChhdHRyaWJ1dGU6IEF0dHJpYnV0ZSkgPT4ge1xyXG4gICAgICAgICAgLy9BdHRyaWJ1dGVzIHRoYXQgbWF0Y2ggdGhlIG5hbWVcclxuICAgICAgICAgIGlmIChhdHRyaWJ1dGUuYXR0cmlidXRlTmFtZSA9PT0gdmFyTmFtZSkge1xyXG4gICAgICAgICAgICBkdG8ucmVmZXJlbmNlZEF0dHJpYnV0ZSA9IGF0dHJpYnV0ZTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC8vSWYgdGhpcyBpcyBhIGdyaWQsIGxvb2sgZm9yIGF0dHJpYnV0ZXMgaW4gdGhlIHJvd1xyXG4gICAgICAgICAgaWYgKGF0dHJpYnV0ZS5hdHRyaWJ1dGVzKSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGdyaWRDb2x1bW5BdHRyaWJ1dGUgIG9mIGF0dHJpYnV0ZS5hdHRyaWJ1dGVzKSB7XHJcbiAgICAgICAgICAgICAgLy9JZiB0aGUgbmFtZSBtYXRjaGVzIEFORCB0aGUgdmFsdWUgaW4gdGhlIEFWUyB3YXMgcGFydCBvZiB0aGUgU0FNRSBST1cgd2UgYXJlIGV2YWx1YXRpbmcgWFBBVEggZm9yLCB3ZSBjYW4gdXNlIHRoZSB2YWx1ZSBmb3IgZXZhbHVhdGlvblxyXG4gICAgICAgICAgICAgIGlmIChncmlkQ29sdW1uQXR0cmlidXRlLmF0dHJpYnV0ZU5hbWUgPT09IHZhck5hbWUpIHtcclxuICAgICAgICAgICAgICAgIGR0by5yZWZlcmVuY2VkQXR0cmlidXRlID0gZ3JpZENvbHVtbkF0dHJpYnV0ZTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcblxyXG5cclxuICAgICAgICBsZXQgYXZzID0gdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKTtcclxuICAgICAgICAvL0lmIHdlIGZvdW5kIHRoZSBhdHRyaWJ1dGUgYW5kIGhhdmUgdmFsdWVzLi4uXHJcbiAgICAgICAgaWYgKGR0by5yZWZlcmVuY2VkQXR0cmlidXRlICYmIGF2cykge1xyXG5cclxuICAgICAgICAgIC8vTG9vayB0aHJvdWdoIGFsbCB0aGUgdmFsdWVzIHRvIGZpbmQgdGhlIG9uZSBmb3IgdGhlIHJlZmVyZW5jZWQgYXR0cmlidXRlIChhbmQgU0FNRSBncmlkIHJvdyBpZiBpbiBhIGdyaWQgcm93KVxyXG4gICAgICAgICAgYXYgPSBhdnMuYXR0cmlidXRlVmFsdWVzLmZpbmQoKGF2KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAvL0lmIHRoaXMgaXMgYW4gQVYgZm9yIGEgZ3JpZCByb3csIGl0IG11c3QgYmUgZm9yIHRoZSBzYW1lIGdyaWQgcm93IHdlIGFyZSBsb29raW5nIGZvclxyXG4gICAgICAgICAgICBpZiAodHlwZW9mIGF2Lmdyb3VwQXR0cmlidXRlUm93SWQgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBncm91cEF0dHJpYnV0ZVJvd0lkICE9PSAndW5kZWZpbmVkJyAmJiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkICE9PSBncm91cEF0dHJpYnV0ZVJvd0lkKSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG5cclxuICAgICAgICAgICAgLy9JZiB3ZSBsb29rZWQgdXAgdGhlIGF0dHJpYnV0ZSBtYXRjaGluZyB0aGUgdmFsdWUgYnkgaWQgQU5EIHRoZSBuYW1lIG9mIHRoZSBhdHRyaWJ1dGUgaXMgdGhlIG9uZSB3ZSBhciBsb29raW5nIGZvciBmcm9tIHRoZSBYUEFUSCwgd2UgY2FuIHVzZSBpdCBmb3IgZXZhbHVhdGlvblxyXG4gICAgICAgICAgICAgLy9Gb3VuZCBhbiBBdHRyaWJ1dGVWYWx1ZSB0aGF0IHRoZSBkaWN0aW9uYXJ5IGlzIGZpbHRlcmVkIGJ5XHJcbiAgICAgICAgICAgIGlmIChkdG8ucmVmZXJlbmNlZEF0dHJpYnV0ZS5pZEF0dHJpYnV0ZSA9PT0gYXYuaWRBdHRyaWJ1dGUpIHtcclxuICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvL1VzZSB0aGUgcmVmZXJlbmNlZEF0dHJpYnV0ZVZhbHVlIGlmIHByb3ZpZGVkICh0aGlzIGhhcHBlbnMgd2hlbiBhbHJlYWR5IGtub3duLCBkdXJpbmcgY2hhbmdlcyB0byB0aGUgcmVmZXJlbmNlZCBhdHRyaWJ1dGUpXHJcbiAgICAgIGlmIChyZWZlcmVuY2VkQXR0cmlidXRlVmFsdWUpIHtcclxuICAgICAgICB4cGF0aCA9IHByZWZpeCArIFwiJ1wiICsgcmVmZXJlbmNlZEF0dHJpYnV0ZVZhbHVlLnZhbHVlICsgXCInXCIgKyBzdWZmaXg7XHJcbiAgICAgIH1cclxuICAgICAgLy9Gb3VuZCB0aGUgQXR0cmlidXRlVmFsdWUgZm9yIHRoZSBhdHRyaWJ1dGUgdGhhdCB0aGUgZGljdGlvbmFyeSBpcyBmaWx0ZXJlZCBieVxyXG4gICAgICBlbHNlIGlmIChhdikge1xyXG4gICAgICAgIHhwYXRoID0gcHJlZml4ICsgXCInXCIgKyBhdi52YWx1ZSArIFwiJ1wiICsgc3VmZml4O1xyXG4gICAgICB9XHJcbiAgICAgIC8vRGlkbid0IGZpbmQgYW4gYXR0cmlidXRlIGZvciB2YXJOYW1lXHJcbiAgICAgIGVsc2Uge1xyXG4gICAgICAgIC8vTWF5YmUgdGhlIHZhck5hbWUgaXMgZnJvbSBlbHNld2hlcmUgaW4gdGhlIGFwcCAobm9uLUNPRCksIGFuZCBwcm92aWRlZCBpbiBib3VuZERhdGFcclxuICAgICAgICBpZiAodGhpcy5ib3VuZERhdGEgJiYgdGhpcy5ib3VuZERhdGFbdmFyTmFtZV0pIHtcclxuICAgICAgICAgIHhwYXRoID0gcHJlZml4ICsgXCInXCIgKyB0aGlzLmJvdW5kRGF0YVt2YXJOYW1lXSArIFwiJ1wiICsgc3VmZml4O1xyXG4gICAgICAgIH1cclxuICAgICAgICAvL05vdGhpbmcgbWF0Y2hlcy4gQ2hhbmdlIHRvIGVtcHR5IHN0cmluZy4gV2lsbCBwcm9iYWJseSByZXN1bHQgaW4gTk8gZW50cmllcywgd2hpY2ggd291bGQgYmUgY29ycmVjdC5cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgIHhwYXRoID0gcHJlZml4ICsgXCInJ1wiICsgc3VmZml4O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgcGFyYW1Qb3MgPSB4cGF0aC5zZWFyY2goXCJcXFxcJHtbQS1aYS16MC05X10rXFxcXC52YWx1ZX1cIik7XHJcbiAgICB9XHJcblxyXG4gICAgLy9IYXZlIHRvIGV2YWx1YXRlIHN1Yi1leHByZXNzaW9uLiBUaGlzIGhhbmRsZXMgZXhwcmVzc2lvbnMgbGlrZSBbQHggPSAoL3hwYXRoLXN1Yi1leHByZXNzaW9uKV1cclxuICAgIGxldCBpbkV4cHJlc3Npb25Qb3MgPSB4cGF0aC5zZWFyY2goXCJcXFxcW0BbQS1aYS16MC05X10rXFxcXHMqPVxcXFxzKlxcXFwoXCIpO1xyXG5cclxuICAgIGlmIChpbkV4cHJlc3Npb25Qb3MgPiAwICYmIHNlY29uZGFyeVhtbCkge1xyXG4gICAgICBsZXQgcHJlZml4ID0geHBhdGguc3Vic3RyaW5nKDAsIGluRXhwcmVzc2lvblBvcyArIDEpO1xyXG4gICAgICBsZXQgZXhwcmVzc2lvbkVuZCA9IHhwYXRoLmluZGV4T2YoXCIpXCIsIGluRXhwcmVzc2lvblBvcyk7XHJcbiAgICAgIGxldCB2YXJpYWJsZSA9IHhwYXRoLnN1YnN0cmluZyhpbkV4cHJlc3Npb25Qb3MgKyAxLCB4cGF0aC5pbmRleE9mKFwiPVwiLCBpbkV4cHJlc3Npb25Qb3MpKTtcclxuICAgICAgbGV0IHN1YkV4cHJlc3Npb24gPSB4cGF0aC5zdWJzdHJpbmcoeHBhdGguaW5kZXhPZihcIihcIiwgaW5FeHByZXNzaW9uUG9zKSArIDEsIGV4cHJlc3Npb25FbmQpO1xyXG4gICAgICBsZXQgc3VmZml4ID0geHBhdGguc3Vic3RyaW5nKGV4cHJlc3Npb25FbmQgKyAxKTtcclxuXHJcbiAgICAgIHhwYXRoID0gcHJlZml4O1xyXG5cclxuICAgICAgLy9FdmFsdWF0ZSBYUEFUSCBleHByZXNzaW9uXHJcbiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcclxuICAgICAgbGV0IGRvYyA9IHBhcnNlci5wYXJzZUZyb21TdHJpbmcoc2Vjb25kYXJ5WG1sLCBcImFwcGxpY2F0aW9uL3htbFwiKTtcclxuICAgICAgbGV0IHhQYXRoUmVzdWx0ID0gZG9jdW1lbnQuZXZhbHVhdGUoc3ViRXhwcmVzc2lvbiwgZG9jLCBudWxsLCBYUGF0aFJlc3VsdC5BTllfVFlQRSwgbnVsbCk7XHJcblxyXG4gICAgICAvL0l0ZXJhdGUgeHBhdGggcmVzdWx0cyAobm9kZXMpXHJcbiAgICAgIHZhciBub2RlID0geFBhdGhSZXN1bHQuaXRlcmF0ZU5leHQoKTtcclxuXHJcbiAgICAgIHdoaWxlKG5vZGUpIHtcclxuICAgICAgICB4cGF0aCA9IHhwYXRoICsgdmFyaWFibGUgKyBcIj0nXCIgKyBub2RlLm5vZGVWYWx1ZSArIFwiJ1wiXHJcblxyXG4gICAgICAgIG5vZGUgPSB4UGF0aFJlc3VsdC5pdGVyYXRlTmV4dCgpO1xyXG5cclxuICAgICAgICBpZiAobm9kZSkge1xyXG4gICAgICAgICAgeHBhdGggPSB4cGF0aCArIFwiIG9yIFwiO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgeHBhdGggPSB4cGF0aCArIHN1ZmZpeDtcclxuICAgIH1cclxuXHJcbiAgICBkdG8uZXhwcmVzc2lvbiA9IHhwYXRoO1xyXG4gICAgcmV0dXJuIGR0bztcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc29ydEF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dExpc3QoYTogYW55LCBiOiBhbnkpIHtcclxuICAgIHJldHVybiBhLmRlc2NyaXB0aW9uLnRvTG93ZXJDYXNlKCkubG9jYWxlQ29tcGFyZShiLmRlc2NyaXB0aW9uLnRvTG93ZXJDYXNlKCkpO1xyXG4gIH1cclxuXHJcbiAgZmV0Y2hBdHRyaWJ1dGVDb25maWd1cmF0aW9uTGlzdChjb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0Pzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAoaXNEZXZNb2RlKCkpIHtcclxuICAgICAgY29uc29sZS5kZWJ1ZyhcImZldGNoQXR0cmlidXRlQ29uZmlndXJhdGlvbkxpc3Q6IFwiICsgY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uTGlzdExvYWRpbmdTdWJqZWN0Lm5leHQodHJ1ZSk7XHJcblxyXG4gICAgbGV0IHVybDogc3RyaW5nID0gdGhpcy5hdHRyaWJ1dGVFbmRwb2ludCArIFwiY29uZmlndXJhdGlvbnNcIjtcclxuICAgIGxldCBwYXJhbXM6IEh0dHBQYXJhbXMgPSBuZXcgSHR0cFBhcmFtcygpO1xyXG4gICAgaWYgKGNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQpIHtcclxuICAgICAgcGFyYW1zID0gcGFyYW1zLnNldChcImNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRcIiwgY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5odHRwLmdldDxBdHRyaWJ1dGVDb25maWd1cmF0aW9uW10+KHVybCwge3BhcmFtczogcGFyYW1zfSkuc3Vic2NyaWJlKChjb25maWd1cmF0aW9uTGlzdDogQXR0cmlidXRlQ29uZmlndXJhdGlvbltdKSA9PiB7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvbkxpc3RMb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuXHJcbiAgICAgIGxldCBkdG9zOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPW10gPSBbXTtcclxuICAgICAgZm9yIChsZXQgY2ZnIG9mIGNvbmZpZ3VyYXRpb25MaXN0KSB7XHJcbiAgICAgICAgbGV0IGR0bzogQXR0cmlidXRlQ29uZmlndXJhdGlvbkRUTyA9IHRoaXMuZ2V0QXR0cmlidXRlQ29uZmlndXJhdGlvbkRUTyhjZmcpO1xyXG4gICAgICAgIGlmIChkdG8pIHtcclxuICAgICAgICAgIGR0b3MucHVzaChkdG8pO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgZHRvcy5zb3J0KHRoaXMuc29ydEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25MaXN0KTtcclxuXHJcbiAgICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvbkxpc3RTdWJqZWN0Lm5leHQoZHRvcyk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc29ydEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25MaXN0KGE6IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8sIGI6IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8pIHtcclxuICAgIGNvbnN0IGRpc3BsYXlhID0gYS5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0RGlzcGxheVxyXG4gICAgICArIGEuZXh0ZW5zaW9uRGVzY3JpcHRpb25cclxuICAgICAgKyAoYS5maWx0ZXIxRGlzcGxheSB8fCBcIlwiKVxyXG4gICAgICArIChhLmZpbHRlcjJEaXNwbGF5IHx8IFwiXCIpO1xyXG5cclxuICAgIGNvbnN0IGRpc3BsYXliID0gYi5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0RGlzcGxheVxyXG4gICAgICArIGIuZXh0ZW5zaW9uRGVzY3JpcHRpb25cclxuICAgICAgKyAoYi5maWx0ZXIxRGlzcGxheSB8fCBcIlwiKVxyXG4gICAgICArIChiLmZpbHRlcjJEaXNwbGF5IHx8IFwiXCIpO1xyXG5cclxuICAgIHJldHVybiBkaXNwbGF5YS50b0xvd2VyQ2FzZSgpLmxvY2FsZUNvbXBhcmUoZGlzcGxheWIudG9Mb3dlckNhc2UoKSk7XHJcbiAgfVxyXG5cclxuICAvL1VzZWQgYnkgY29kLWVkaXRvclxyXG4gIGNsZWFyKCk6IHZvaWQge1xyXG4gICAgdGhpcy5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLmlkRmlsdGVyMSA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuaWRGaWx0ZXIyID0gdW5kZWZpbmVkO1xyXG5cclxuICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvbkRUT1N1YmplY3QubmV4dCh1bmRlZmluZWQpO1xyXG4gICAgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdC5uZXh0KHVuZGVmaW5lZCk7XHJcbiAgfVxyXG5cclxuICBjcmVhdGVBdHRyaWJ1dGVDb25maWd1cmF0aW9uKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pOiB2b2lkIHtcclxuICAgIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uID0gdW5kZWZpbmVkO1xyXG5cclxuICAgIHRoaXMuaHR0cC5wb3N0PEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24+KHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImNvbmZpZ3VyYXRpb25zXCIsIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pLnN1YnNjcmliZSgoYXR0cmlidXRlQ29uZmlndXJhdGlvbjogQXR0cmlidXRlQ29uZmlndXJhdGlvbikgPT4ge1xyXG4gICAgICB0aGlzLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiA9IGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uO1xyXG5cclxuICAgICAgdGhpcy5wb3N0Q29uZmlndXJhdGlvblN1YmplY3QubmV4dCh0cnVlKTtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdC5uZXh0KGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pO1xyXG4gICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZUJ5VXJsKFwiL2VkaXRvci9hdHRyaWJ1dGUtY29uZmlndXJhdGlvbi9cIiArIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc2V0QXR0cmlidXRlQ29uZmlndXJhdGlvbkJ5SWQoaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uOiBudW1iZXIsIGlkQXR0cmlidXRlVmFsdWVTZXQ6IG51bWJlciwgaWRQYXJlbnRPYmplY3Q6IG51bWJlcik6IHZvaWQge1xyXG4gICAgaWYgKGlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiAhPT0gLTEpIHtcclxuICAgICAgdGhpcy5uZXdBdHRyaWJ1dGVDb25maWd1cmF0aW9uID0gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIC8vT25seSBsb2FkIGlmIHRoZSBBdHRyaWJ1dGVDb25maWd1cmF0aW9uIGhhcyBjaGFuZ2VkXHJcbiAgICBpZiAodGhpcy5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gIT09IGlkQXR0cmlidXRlQ29uZmlndXJhdGlvbikge1xyXG4gICAgICAvL0NsZWFyIEFTQVBcclxuICAgICAgdGhpcy5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPSBpZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb247XHJcbiAgICAgIHRoaXMuaWRBdHRyaWJ1dGVWYWx1ZVNldCA9IGlkQXR0cmlidXRlVmFsdWVTZXQ7XHJcbiAgICAgIHRoaXMuaWRGaWx0ZXIxID0gdW5kZWZpbmVkO1xyXG4gICAgICB0aGlzLmlkRmlsdGVyMiA9IHVuZGVmaW5lZDtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVNYXAuY2xlYXIoKTtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPU3ViamVjdC5uZXh0KHVuZGVmaW5lZCk7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QubmV4dCh1bmRlZmluZWQpO1xyXG5cclxuICAgICAgdGhpcy5mZXRjaEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24oaWRBdHRyaWJ1dGVWYWx1ZVNldCwgaWRQYXJlbnRPYmplY3QpO1xyXG4gICAgfVxyXG4gICAgLy9PciBsb2FkIHRoZSBBdHRyaWJ1dGVWYWx1ZVNldCBpZiB0aGF0IGNoYW5nZWQgKHBvc3NpYmxlIHRvIHN3aXRjaCBmcm9tIG9uZSBldmVudCB0byBhbm90aGVyIG9mIHRoZSBzYW1lIHR5cGUsIGZvciBleGFtcGxlXHJcbiAgICAvL1RoZSBBdHRyaWJ1dGVDb25maWd1cmF0aW9uIG11c3QgYWxzbyBoYXZlIGZpbmlzaGVkIGxvYWRpbmcgYW5kIG5vdCBhbHJlYWR5IHdvcmtpbmcgb24gbG9hZGluZyB0aGUgdmFsdWVzXHJcbiAgICBlbHNlIGlmICh0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXQgIT09IGlkQXR0cmlidXRlVmFsdWVTZXQgJiYgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdC5nZXRWYWx1ZSgpKSB7XHJcbiAgICAgIHRoaXMuc2V0QXR0cmlidXRlVmFsdWVTZXQoaWRBdHRyaWJ1dGVWYWx1ZVNldCwgaWRQYXJlbnRPYmplY3QpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcblxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIHRoZSBhdHRyaWJ1dGUgY29uZmlndXJhdGlvbiBpZGVudGlmaWVycyB0byBiZSB1c2VkIGJ5IHRoaXMgc2VydmljZS4gIFRoaXMgcHJvbXB0cyBhIG5ldyBjb25maWd1cmF0aW9uXHJcbiAgICogcmVxdWVzdCB0byBiZSBtYWRlLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtudW1iZXJ9IGlkRmlsdGVyMVxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpZEZpbHRlcjJcclxuICAgKi9cclxuLyogVGhpcyBpcyBjb21tZW50ZWQgb3V0IGZvciBub3cgYmVjYXVzZSBpdCBpcyBib3RoIHVuaW1wbGVtZW50ZWQgYW5kIGluY29tcGxldGUgKGxvYWRpbmcgYSBjb25maWd1cmF0aW9uXHJcbiAqIGZpbHRlciB3b3VsZCByZWFsbHkgYWxzbyByZXF1aXJlIHRoZSBhdHRyaWJ1dGUgY29udGV4dCBhbmQgYXR0cmlidXRlc2VjdXJpdHkgY29udGV4dCBwbHVzIGEgc2VydmljZSBvblxyXG4gKiB0aGUgYmFjayBlbmQgdGhhdCBhY3R1YWxseSBkb2VzIHRoaXMgd29yay4gRm9yIG5vdywgb25seSBsb2FkaW5nIGJ5IGlkQXR0cmlidXRlQ29uZmlndXJhdGlvblxyXG4gKlxyXG4gIHNldEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25CeUZpbHRlcihpZEZpbHRlcjE6IG51bWJlciwgaWRGaWx0ZXIyPzogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBpZiAoaXNEZXZNb2RlKCkpIHtcclxuICAgICAgY29uc29sZS5kZWJ1ZyhcInNldEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25CeUZpbHRlcjogXCIgKyBpZEZpbHRlcjEgKyBcIiBcIiArIGlkRmlsdGVyMik7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5uZXdBdHRyaWJ1dGVDb25maWd1cmF0aW9uID0gdW5kZWZpbmVkO1xyXG4gICAgLy90aGlzLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuaWRGaWx0ZXIxID0gaWRGaWx0ZXIxO1xyXG4gICAgdGhpcy5pZEZpbHRlcjIgPSBpZEZpbHRlcjI7XHJcblxyXG4gICAgdGhpcy5mZXRjaEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24oKTtcclxuICB9XHJcbiovXHJcblxyXG4gIC8qKlxyXG4gICAqIFNldHMgdGhlIGlkIG9mIHRoZSBhdHRyaWJ1dGUgdmFsdWUgc2V0LiAgVGhpcyB3aWxsIHByb21wdCBhIHJlcXVlc3QgdG8gcHVsbCB0aGlzIGZyb20gdGhlIGJhY2tlbmQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge251bWJlcn0gaWRBdHRyaWJ1dGVWYWx1ZVNldFxyXG4gICAqL1xyXG4gIHNldEF0dHJpYnV0ZVZhbHVlU2V0KGlkQXR0cmlidXRlVmFsdWVTZXQ6IG51bWJlciwgaWRQYXJlbnRPYmplY3Q6IG51bWJlcikge1xyXG4gICAgLy9Pbmx5IGxvYWQgdGhlIEF0dHJpYnV0ZVZhbHVlU2V0IGlmIGl0IGhhcyBiZWVuIGNoYW5nZWRcclxuICAgIGlmICh0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXQgIT09IGlkQXR0cmlidXRlVmFsdWVTZXQpIHtcclxuICAgICAgdGhpcy5pZEF0dHJpYnV0ZVZhbHVlU2V0ID0gaWRBdHRyaWJ1dGVWYWx1ZVNldDtcclxuXHJcbiAgICAgIHRoaXMuZmV0Y2hBdHRyaWJ1dGVWYWx1ZVNldChpZFBhcmVudE9iamVjdCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGUgcmVxdWVzdCB0byBkb3dubG9hZCB0aGUgYXR0cmlidXRlIGNvbmZpZ3VyYXRpb24uXHJcbiAgICovXHJcbiAgZmV0Y2hBdHRyaWJ1dGVDb25maWd1cmF0aW9uKGlkQXR0cmlidXRlVmFsdWVTZXQ6IG51bWJlciwgaWRQYXJlbnRPYmplY3Q6IG51bWJlcik6IHZvaWQge1xyXG5cclxuICAgIGlmICh0aGlzLm5ld0F0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pIHtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPU3ViamVjdC5uZXh0KHVuZGVmaW5lZCk7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QubmV4dCh0aGlzLm5ld0F0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9IGVsc2UgaWYgKHRoaXMuaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uID09PSAtMSkge1xyXG4gICAgICB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE9TdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdC5uZXh0KDxBdHRyaWJ1dGVDb25maWd1cmF0aW9uPntcclxuICAgICAgICBpZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IC0yXHJcbiAgICAgIH0pO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KHRydWUpO1xyXG5cclxuICAgIGxldCB1cmw6IHN0cmluZztcclxuICAgIGlmICh0aGlzLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiAmJiB0aGlzLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiA+IC0xKSB7XHJcbiAgICAgIHVybCA9IHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImNvbmZpZ3VyYXRpb25zL1wiICsgdGhpcy5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb247XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvL1RoaXMgaXMgbm90IGZ1bGx5IGltcGxlbWVudGVkXHJcblx0ICAvL3VybCA9IHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImNvbmZpZ3VyYXRpb25zL2ZpbHRlci9cIiArIHRoaXMuaWRGaWx0ZXIxO1xyXG4gICAgICAvL2lmICh0aGlzLmlkRmlsdGVyMikge1xyXG4gICAgICAgIC8vdXJsICs9IFwiL1wiICsgdGhpcy5pZEZpbHRlcjI7XHJcbiAgICAgIC8vfVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaHR0cC5nZXQ8QXR0cmlidXRlQ29uZmlndXJhdGlvbj4odXJsKS5zdWJzY3JpYmUoKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pID0+IHtcclxuICAgICAgdGhpcy5zZXRBdHRyaWJ1dGVDb25maWd1cmF0aW9uKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pO1xyXG4gICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG5cclxuICAgICAgLy9Ob3cgbG9hZCB0aGUgYXR0cmlidXRlVmFsdWVTZXQgLSBUaGlzIHdpbGwgYWx3YXlzIGhhcHBlbiB3aGVuIGEgbmV3IGNvbmZpZ3VyYXRpb24gaXMgbG9hZGVkXHJcbiAgICAgIHRoaXMuaWRBdHRyaWJ1dGVWYWx1ZVNldCA9IHVuZGVmaW5lZDsgLy9Gb3JjZSBpdCB0byBjaGFuZ2UgaW4gdGhpcyBzY2VuYXJpb1xyXG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZVZhbHVlU2V0KGlkQXR0cmlidXRlVmFsdWVTZXQsIGlkUGFyZW50T2JqZWN0KTtcclxuICAgICAgdGhpcy5kaXJ0eS5uZXh0KGZhbHNlKTtcclxuICAgIH0sXHJcbiAgICAoZXJyb3IpID0+IHtcclxuICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XHJcbiAgICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dChmYWxzZSk7XHJcbiAgICAgIHRoaXMuc2V0QXR0cmlidXRlQ29uZmlndXJhdGlvbih1bmRlZmluZWQpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzZXRBdHRyaWJ1dGVDb25maWd1cmF0aW9uKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pOiB2b2lkIHtcclxuICAgIHRoaXMuYXR0cmlidXRlTWFwLmNsZWFyKCk7XHJcblxyXG4gICAgaWYgKGlzRGV2TW9kZSgpKSB7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoXCJBdHRyaWJ1dGVTZXJ2aWNlLnNldEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25cIik7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoYXR0cmlidXRlQ29uZmlndXJhdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pIHtcclxuICAgICAgaWYgKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uYmFzZVdpbmRvd1RlbXBsYXRlKSB7XHJcbiAgICAgICAgdGhpcy5nZXRCYXNlV2luZG93RGltZW5zaW9uKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uYmFzZVdpbmRvd1RlbXBsYXRlKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uYXR0cmlidXRlQ29udGFpbmVycykge1xyXG4gICAgICAgIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uYXR0cmlidXRlQ29udGFpbmVycy5zb3J0KChhOiBBdHRyaWJ1dGVDb250YWluZXIsIGI6IEF0dHJpYnV0ZUNvbnRhaW5lcikgPT4ge1xyXG4gICAgICAgICAgaWYgKGEuc29ydE9yZGVyIDwgYi5zb3J0T3JkZXIpIHtcclxuICAgICAgICAgICAgcmV0dXJuIC0xO1xyXG4gICAgICAgICAgfSBlbHNlIGlmIChhLnNvcnRPcmRlciA+IGIuc29ydE9yZGVyKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAxO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIDA7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGZvciAobGV0IGF0dHJpYnV0ZUNvbnRhaW5lciBvZiBhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmF0dHJpYnV0ZUNvbnRhaW5lcnMpIHtcclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBGaXJzdCBzb3J0IGF0dHJpYnV0ZXMgdXNpbmcgdGhlIHkgYW5kIHggcG9zaXRpb25pbmcuICBJZiB1c2luZyBhYnNvbHV0ZSBwb3NpdGlvbiwgdGhlIG9yZGVyIGRvZXNuJ3QgbWF0dGVyLFxyXG4gICAgICAgICAqIGJ1dCBpZiB3ZSB3YW50IHRoZSBhYnNvbHV0ZSBwb3NpdGlvbmluZyB0byBndWlkZSBhdXRvIGxheW91dCwgdGhlbiB1c2UgdGhpcyBvcmRlci5cclxuICAgICAgICAgKi9cclxuICAgICAgICBhdHRyaWJ1dGVDb250YWluZXIuZ3JhcGhpY2FsQXR0cmlidXRlcy5zb3J0KChhOiBHcmFwaGljYWxBdHRyaWJ1dGUsIGI6IEdyYXBoaWNhbEF0dHJpYnV0ZSkgPT4ge1xyXG4gICAgICAgICAgaWYgKGEudGFiT3JkZXIgPCBiLnRhYk9yZGVyKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAtMTtcclxuICAgICAgICAgIH0gZWxzZSBpZiAoYS50YWJPcmRlciA+IGIudGFiT3JkZXIpIHtcclxuICAgICAgICAgICAgcmV0dXJuIDE7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gMDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgYXR0cmlidXRlIG9mIGF0dHJpYnV0ZUNvbnRhaW5lci5ncmFwaGljYWxBdHRyaWJ1dGVzKSB7XHJcbiAgICAgICAgICB0aGlzLmF0dHJpYnV0ZU1hcC5zZXQoYXR0cmlidXRlLmlkQXR0cmlidXRlLCBhdHRyaWJ1dGUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvbkRUT1N1YmplY3QubmV4dCh0aGlzLmdldEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8oYXR0cmlidXRlQ29uZmlndXJhdGlvbikpO1xyXG4gICAgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdC5uZXh0KGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIHJlcXVlc3QgdG8gcHVsbCB0aGUgYXR0cmlidXRlIHZhbHVlIHNldC5cclxuICAgKiBSZXF1aXJlZCB0aGUgQXR0cmlidXRlQ29uZmlndXJhdGlvbiB0byBiZSBwcmUtbG9hZGVkXHJcbiAgICovXHJcbiAgZmV0Y2hBdHRyaWJ1dGVWYWx1ZVNldChpZFBhcmVudE9iamVjdDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQodHJ1ZSk7XHJcbiAgICB0aGlzLmlkUGFyZW50T2JqZWN0ID0gaWRQYXJlbnRPYmplY3Q7XHJcblxyXG4gICAgbGV0IHVybDogc3RyaW5nID0gdGhpcy5hdHRyaWJ1dGVFbmRwb2ludCArIFwiYXR0cmlidXRlLXZhbHVlLXNldC9cIiArIHRoaXMuaWRBdHRyaWJ1dGVWYWx1ZVNldDtcclxuXHJcbiAgICBsZXQgYWM6IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPSB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25TdWJqZWN0LmdldFZhbHVlKCk7XHJcblxyXG4gICAgbGV0IHF1ZXJ5UGFyYW1zOiBIdHRwUGFyYW1zID0gbmV3IEh0dHBQYXJhbXMoKVxyXG4gICAgLnNldChcImNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRcIiwgYWMuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dClcclxuICAgIC5zZXQoXCJjb2RlQXR0cmlidXRlQ29udGV4dFwiLCBhYy5jb2RlQXR0cmlidXRlQ29udGV4dClcclxuICAgIC5zZXQoXCJpZFBhcmVudE9iamVjdFwiLCAoaWRQYXJlbnRPYmplY3QpP2lkUGFyZW50T2JqZWN0LnRvU3RyaW5nKCk6XCJcIik7XHJcblxyXG4gICAgLy9DbGVhciBBU0FQXHJcbiAgICB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcyA9IFtdO1xyXG4gICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzID0gW107XHJcbiAgICB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5uZXh0KHVuZGVmaW5lZCk7XHJcblxyXG4gICAgdGhpcy5odHRwLmdldDxBdHRyaWJ1dGVWYWx1ZVNldD4odXJsLCB7cGFyYW1zOiBxdWVyeVBhcmFtc30pLnN1YnNjcmliZSgoYXR0cmlidXRlVmFsdWVTZXQ6IEF0dHJpYnV0ZVZhbHVlU2V0KSA9PiB7XHJcbiAgICAgIC8vSW5pdGlhbGl6ZSBhdHRyaWJ1dGVWYWx1ZXMgaWYgaXQgZG9lcyBub3QgZXhpc3RcclxuICAgICAgaWYgKCEgYXR0cmlidXRlVmFsdWVTZXQuYXR0cmlidXRlVmFsdWVzKSB7XHJcbiAgICAgICAgYXR0cmlidXRlVmFsdWVTZXQuYXR0cmlidXRlVmFsdWVzID0gW107XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0Lm5leHQoYXR0cmlidXRlVmFsdWVTZXQpO1xyXG4gICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG4gICAgICB0aGlzLmRpcnR5Lm5leHQoZmFsc2UpO1xyXG4gICAgfSxcclxuICAgIChlcnJvcikgPT4ge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcclxuICAgICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QubmV4dCh1bmRlZmluZWQpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBnZXRCYXNlV2luZG93RGltZW5zaW9uKGJhc2VXaW5kb3dUZW1wbGF0ZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLmh0dHAuZ2V0KHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImJhc2Utd2luZG93LWRpbWVuc2lvblwiLCB7cGFyYW1zOiBuZXcgSHR0cFBhcmFtcygpLnNldChcImJhc2VXaW5kb3dUZW1wbGF0ZVwiLCBiYXNlV2luZG93VGVtcGxhdGUpfSlcclxuICAgICAgLnN1YnNjcmliZSgoZGltZW5zaW9uOiBhbnkpID0+IHtcclxuICAgICAgICB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EaW1lbnNpb25TdWJqZWN0Lm5leHQoZGltZW5zaW9uKTtcclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDdXJyZW50bHkgYSBzaW1wbGUgbm90aWZpZXIgdGhhdCB0aGUgY29uZmlndXJhdGlvbiBvciBhdHRyaWJ1dGUgdmFsdWUgc2V0IGhhcyBjaGFuZ2VkIGFuZCBjb21wb25lbnRzIG1heSBuZWVkIHRvIGJlIHJlZnJlc2hlZC5cclxuICAgKlxyXG4gICAqL1xyXG4gIG5vdGlmeUF0dHJpYnV0ZXMoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNvbnRhaW5lclVwZGF0ZWQubmV4dCh0cnVlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBvc3QgdGhlIGF0dHJpYnV0ZSBjb25maWd1cmF0aW9uIGFmdGVyIGVkaXRpbmcuICBQb3N0IHRoZSBlbnRpcmUgdGhpbmcgYXMgaXQgY2FzY2FkZXMgZG93bi4gIFRoZSBlZGl0b3IgYWxsb3dzIHlvdVxyXG4gICAqIHRvIG1vZGlmeSBldmVyeSBjb250YWluZXIgYW5kIG9ubHkgdGhlbiBzYXZlIHRoZSBlbnRpcmUgY29uZmlndXJhdGlvbi5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlQ29uZmlndXJhdGlvbn0gYXR0cmlidXRlQ29uZmlndXJhdGlvblxyXG4gICAqL1xyXG4gIHBvc3RBdHRyaWJ1dGVDb25maWd1cmF0aW9uKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pOiB2b2lkIHtcclxuICAgIGxldCB1cmw6IHN0cmluZyA9IHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImNvbmZpZ3VyYXRpb25zL1wiICsgYXR0cmlidXRlQ29uZmlndXJhdGlvbi5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb247XHJcblxyXG4gICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KHRydWUpO1xyXG5cclxuICAgIHRoaXMuc2V0TmVnYXRpdmVJZHNUb1VuZGVmaW5lZChhdHRyaWJ1dGVDb25maWd1cmF0aW9uKTtcclxuXHJcbiAgICB0aGlzLmh0dHAucG9zdCh1cmwsIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pLnN1YnNjcmliZSgoKSA9PiB7XHJcblxyXG4gICAgICAvLyBQcmV2ZW50IGVycm9yIGluIHN1YnNlcXVlbnQgc2F2ZXMuIFNlZSBNZXRhYnVpbGRlciAvIE1CLTIzXHJcbiAgICAgIHRoaXMuaHR0cC5nZXQ8QXR0cmlidXRlQ29uZmlndXJhdGlvbj4odXJsKS5zdWJzY3JpYmUoKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pID0+IHtcclxuICAgICAgICBpZiAoaXNEZXZNb2RlKCkpIHtcclxuICAgICAgICAgIGNvbnNvbGUuZGVidWcoYXR0cmlidXRlQ29uZmlndXJhdGlvbik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLnBvc3RDb25maWd1cmF0aW9uU3ViamVjdC5uZXh0KHRydWUpO1xyXG4gICAgICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QubmV4dChhdHRyaWJ1dGVDb25maWd1cmF0aW9uKTtcclxuICAgICAgfSxcclxuICAgICAgKGVycm9yKSA9PiB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XHJcbiAgICAgIH0sXHJcbiAgICAgICgpID0+IHtcclxuICAgICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICB9LFxyXG4gICAgKGVycm9yKSA9PiB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFB1dCB0aGUgYXR0cmlidXRlIHZhbHVlIHNldC4gIFdoZW4gZWRpdGluZywgYXR0cmlidXRlcyBhbHJlYWR5IHBvc3QgdGhlaXIgdXBkYXRlZCB2YWx1ZXMgdG8gdGhpcyBzZXJ2aWNlcyB1bmRlclxyXG4gICAqIGEgc2VwYXJhdGUgYXJyYXkuICBXaGF0IHdlIGRvIGlzIG1lcmdlIGluIHRoZXNlIHVwZGF0ZWQgb3IgY3JlYXRlZCB2YWx1ZXMgd2l0aCB0aGUgY3VycmVudCBhdHRyaWJ1dGUgdmFsdWUgc2V0IChhdnMpLlxyXG4gICAqIFdoaWxlIGRvaW5nIHRoaXMsIHNldCB0aGUgaWQgb2YgdGhlIGF2cyBhbmQgbnVsbGlmeSBhbnkgbmVnYXRpdmUgaWRzLlxyXG4gICAqL1xyXG4gIHVwZGF0ZUF0dHJpYnV0ZVZhbHVlU2V0KCk6IFN1YmplY3Q8QXR0cmlidXRlVmFsdWVTZXQ+IHtcclxuICAgIGxldCB1cmw6IHN0cmluZyA9IHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImF0dHJpYnV0ZS12YWx1ZS1zZXQvXCIgO1xyXG5cclxuICAgIGxldCBhYzogQXR0cmlidXRlQ29uZmlndXJhdGlvbiA9IHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QuZ2V0VmFsdWUoKTtcclxuXHJcbiAgICBsZXQgcXVlcnlQYXJhbXM6IEh0dHBQYXJhbXMgPSBuZXcgSHR0cFBhcmFtcygpXHJcbiAgICAuc2V0KFwiY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dFwiLCBhYy5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0KVxyXG4gICAgLnNldChcImNvZGVBdHRyaWJ1dGVDb250ZXh0XCIsIGFjLmNvZGVBdHRyaWJ1dGVDb250ZXh0KVxyXG4gICAgLnNldChcImlkUGFyZW50T2JqZWN0XCIsICh0aGlzLmlkUGFyZW50T2JqZWN0KT90aGlzLmlkUGFyZW50T2JqZWN0LnRvU3RyaW5nKCk6XCJcIik7XHJcblxyXG4gICAgbGV0IGF2czogQXR0cmlidXRlVmFsdWVTZXQgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpKTtcclxuICAgIGZvciAobGV0IGkgPSB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2ldLmlkQXR0cmlidXRlVmFsdWVTZXQgPSB0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXQ7XHJcbiAgICAgIGlmICh0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uaWRBdHRyaWJ1dGVWYWx1ZSA8IDApIHtcclxuICAgICAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uaWRBdHRyaWJ1dGVWYWx1ZSA9IHVuZGVmaW5lZDtcclxuICAgICAgfVxyXG5cclxuICAgICAgbGV0IGo6IG51bWJlciA9IDA7XHJcbiAgICAgIGZvciAoaiA9IDA7IGogPCBhdnMuYXR0cmlidXRlVmFsdWVzLmxlbmd0aDsgaisrKSB7XHJcbiAgICAgICAgaWYgKHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZVZhbHVlID09PSBhdnMuYXR0cmlidXRlVmFsdWVzW2pdLmlkQXR0cmlidXRlVmFsdWUpIHtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBpZiAoaiA8IGF2cy5hdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgYXZzLmF0dHJpYnV0ZVZhbHVlc1tqXSA9IHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXTtcclxuICAgICAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMuc3BsaWNlKGksIDEpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGxldCBqOiBudW1iZXIgPSAwO1xyXG4gICAgICBmb3IgKGogPSAwOyBqIDwgYXZzLmF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgIGlmICh0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZVZhbHVlID09PSBhdnMuYXR0cmlidXRlVmFsdWVzW2pdLmlkQXR0cmlidXRlVmFsdWUpIHtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBpZiAoaiA8IGF2cy5hdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgYXZzLmF0dHJpYnV0ZVZhbHVlcy5zcGxpY2UoaiwgMSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGF2cy5hdHRyaWJ1dGVWYWx1ZXMgPSBhdnMuYXR0cmlidXRlVmFsdWVzLmNvbmNhdCh0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMpO1xyXG5cclxuICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dCh0cnVlKTtcclxuXHJcbiAgICBsZXQgcmVzdWx0U3ViamVjdDogU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZVNldD4gPSBuZXcgU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZVNldD4oKTtcclxuXHJcbiAgICB0aGlzLmh0dHAucHV0KHVybCwgYXZzLCB7cGFyYW1zOiBxdWVyeVBhcmFtc30pLnN1YnNjcmliZSgoYXR0cmlidXRlVmFsdWVTZXQ6IEF0dHJpYnV0ZVZhbHVlU2V0KSA9PiB7XHJcbiAgICAgICAgaWYgKGlzRGV2TW9kZSgpKSB7XHJcbiAgICAgICAgICBjb25zb2xlLmRlYnVnKGF0dHJpYnV0ZVZhbHVlU2V0KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vSW5pdGlhbGl6ZSBhdHRyaWJ1dGVWYWx1ZXMgaWYgaXQgZG9lcyBub3QgZXhpc3RcclxuICAgICAgICBpZiAoISBhdHRyaWJ1dGVWYWx1ZVNldC5hdHRyaWJ1dGVWYWx1ZXMpIHtcclxuICAgICAgICAgIGF0dHJpYnV0ZVZhbHVlU2V0LmF0dHJpYnV0ZVZhbHVlcyA9IFtdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMgPSBbXTtcclxuICAgICAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMgPSBbXTtcclxuICAgICAgICB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5uZXh0KGF0dHJpYnV0ZVZhbHVlU2V0KTtcclxuICAgICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG4gICAgICAgIHRoaXMuZGlydHkubmV4dChmYWxzZSk7XHJcblxyXG4gICAgICAgIC8vU2VuZCB0aGUgcmVzdWx0cyB0byB0aGUgb2JzZXJ2ZXIgKGlmIGFueSksIHRoZW4gY29tcGxldGVcclxuICAgICAgICByZXN1bHRTdWJqZWN0Lm5leHQoYXR0cmlidXRlVmFsdWVTZXQpO1xyXG4gICAgICAgIHJlc3VsdFN1YmplY3QuY29tcGxldGUoKTtcclxuICAgICAgfSxcclxuICAgICAgKGVycm9yKSA9PiB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XHJcbiAgICAgICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuICAgICAgICByZXN1bHRTdWJqZWN0LmVycm9yKGVycm9yKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHJlc3VsdFN1YmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgdGhlIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25TdWJqZWN0LlxyXG4gICAqXHJcbiAgICogQHJldHVybnMge0JlaGF2aW9yU3ViamVjdDxBdHRyaWJ1dGVDb25maWd1cmF0aW9uPn1cclxuICAgKi9cclxuICBnZXRBdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdCgpOiBCZWhhdmlvclN1YmplY3Q8QXR0cmlidXRlQ29uZmlndXJhdGlvbj4ge1xyXG4gICAgcmV0dXJuIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3Q7XHJcbiAgfVxyXG5cclxuICBnZXREaXJ0eVN1YmplY3QoKTogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+IHtcclxuICAgIHJldHVybiB0aGlzLmRpcnR5O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IHRoZSBhdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3Q7XHJcbiAgICpcclxuICAgKiBAcmV0dXJucyB7QmVoYXZpb3JTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlU2V0Pn1cclxuICAgKi9cclxuICBnZXRBdHRyaWJ1dGVWYWx1ZVNldCgpOiBCZWhhdmlvclN1YmplY3Q8QXR0cmlidXRlVmFsdWVTZXQ+IHtcclxuICAgIHJldHVybiB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB0aGUgYXR0cmlidXRlVmFsdWVQdXNoZWRTdWJqZWN0O1xyXG4gICAqXHJcbiAgICogQHJldHVybnMge1N1YmplY3Q8QXR0cmlidXRlVmFsdWU+fVxyXG4gICAqL1xyXG4gIGdldEF0dHJpYnV0ZVZhbHVlUHVzaGVkU3ViamVjdCgpOiBTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlPiB7XHJcbiAgICByZXR1cm4gdGhpcy5hdHRyaWJ1dGVWYWx1ZVB1c2hlZFN1YmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgYWxsIGF0dHJpYnV0ZSB2YWx1ZXMgYmFzZWQgdXBvbiB0aGUgaWRBdHRyaWJ1dGUuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge251bWJlcn0gaWRBdHRyaWJ1dGVzXHJcbiAgICogQHJldHVybnMge0F0dHJpYnV0ZVZhbHVlW119XHJcbiAgICovXHJcbiAgZ2V0QXR0cmlidXRlVmFsdWVzKGlkQXR0cmlidXRlOiBudW1iZXIsIGdyb3VwQXR0cmlidXRlUm93SWQ6IG51bWJlcik6IEF0dHJpYnV0ZVZhbHVlW10ge1xyXG5cclxuICAgIGxldCBhdHRyaWJ1dGVWYWx1ZXM6IEF0dHJpYnV0ZVZhbHVlW10gPSBbXTtcclxuXHJcbiAgICBpZih0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpKSB7XHJcblxyXG4gICAgICAvL0dvIHRocm91Z2ggYWxsIHRoZSB1cGRhdGVkIGF0dHJpYnV0ZSB2YWx1ZXMgZmlyc3QgKHNvIHdlIHByZXNlcnZlIGFjcm9zcyBjaGFuZ2luZyB0YWJzLCBldGMpXHJcbiAgICAgIGxldCBpOiBudW1iZXIgPSAwO1xyXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgaWYgKHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZSA9PT0gaWRBdHRyaWJ1dGUgJiYgKCFncm91cEF0dHJpYnV0ZVJvd0lkIHx8IGdyb3VwQXR0cmlidXRlUm93SWQgPT09IHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS5ncm91cEF0dHJpYnV0ZVJvd0lkKSkge1xyXG4gICAgICAgICAgYXR0cmlidXRlVmFsdWVzLnB1c2goT2JqZWN0LmFzc2lnbih7fSwgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2ldKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS5pZEdyb3VwQXR0cmlidXRlID09PSBpZEF0dHJpYnV0ZSAmJiAoIWdyb3VwQXR0cmlidXRlUm93SWQgfHwgZ3JvdXBBdHRyaWJ1dGVSb3dJZCA9PT0gdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2ldLmdyb3VwQXR0cmlidXRlUm93SWQpKSB7XHJcbiAgICAgICAgICBhdHRyaWJ1dGVWYWx1ZXMucHVzaChPYmplY3QuYXNzaWduKHt9LCB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV0pKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vR28gdGhyb3VnaCBhbGwgdGhlIHJlZ3VsYXIgYXR0cmlidXRlc1xyXG4gICAgICBmb3IgKGxldCBhdHRyaWJ1dGVWYWx1ZSBvZiB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpLmF0dHJpYnV0ZVZhbHVlcykge1xyXG4gICAgICAgIC8vUmVndWxhciBhdHRyaWJ1dGVzIChub3JtYWwgYW5kIGdyb3VwLCB3aGljaCBnZXQgbXVsdGlwbGUpXHJcbiAgICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlLmlkQXR0cmlidXRlID09PSBpZEF0dHJpYnV0ZSB8fCBhdHRyaWJ1dGVWYWx1ZS5pZEdyb3VwQXR0cmlidXRlID09PSBpZEF0dHJpYnV0ZSkge1xyXG4gICAgICAgICAgLy9JZiByb3cgaWQgc3BlY2lmaWVkLCBvbmx5IGNhcmUgYWJvdXQgdmFsdWVzIGZvciB0aGF0IHJvd1xyXG4gICAgICAgICAgaWYgKHR5cGVvZiBncm91cEF0dHJpYnV0ZVJvd0lkID09PSAndW5kZWZpbmVkJyB8fCBhdHRyaWJ1dGVWYWx1ZS5ncm91cEF0dHJpYnV0ZVJvd0lkID09PSBncm91cEF0dHJpYnV0ZVJvd0lkKSB7XHJcblxyXG4gICAgICAgICAgICAvL0lmIG5vdCBhbHJlYWR5IGFkZGVkLi4uXHJcbiAgICAgICAgICAgIGlmICghIGF0dHJpYnV0ZVZhbHVlcy5maW5kKChleGlzdGluZykgPT4gZXhpc3RpbmcuaWRBdHRyaWJ1dGVWYWx1ZSA9PT0gYXR0cmlidXRlVmFsdWUuaWRBdHRyaWJ1dGVWYWx1ZSkpIHtcclxuXHJcbiAgICAgICAgICAgICAgLy9Eb24ndCB3YW50IHRoZSBvcmlnaW5hbCBpZiBpdCB3YXMgcmVtb3ZlZCAoc2xpY2VkKVxyXG4gICAgICAgICAgICAgIGlmICghIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzLmZpbmQoKHNhdikgPT4gc2F2LmlkQXR0cmlidXRlVmFsdWUgPT09IGF0dHJpYnV0ZVZhbHVlLmlkQXR0cmlidXRlVmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVWYWx1ZXMucHVzaChPYmplY3QuYXNzaWduKHt9LCBhdHRyaWJ1dGVWYWx1ZSkpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBhdHRyaWJ1dGVWYWx1ZXM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgYWxsIGNoaWxkIGF0dHJpYnV0ZXMgb2YgdGhlIGlkQXR0cmlidXRlLiAgTW9zdCBsaWtlbHkgZm9yIGF0dHJpYnV0ZXMgdGhhdCBkZWZpbmUgY29sdW1ucyBvZiBhIGdyaWQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge251bWJlcn0gaWRBdHRyaWJ1dGVcclxuICAgKiBAcmV0dXJucyB7QXR0cmlidXRlW119XHJcbiAgICovXHJcbiAgZ2V0R3JvdXBBdHRyaWJ1dGVzKGlkQXR0cmlidXRlOiBudW1iZXIpOiBBdHRyaWJ1dGVbXSB7XHJcbiAgICBsZXQgYXR0cmlidXRlczogQXR0cmlidXRlW10gPSBbXTtcclxuXHJcbiAgICB0aGlzLmF0dHJpYnV0ZU1hcC5mb3JFYWNoKChhdHRyaWJ1dGU6IEF0dHJpYnV0ZSkgPT4ge1xyXG4gICAgICBpZiAoYXR0cmlidXRlLmlkR3JvdXBBdHRyaWJ1dGUgPT09IGlkQXR0cmlidXRlKSB7XHJcbiAgICAgICAgYXR0cmlidXRlcy5wdXNoKGF0dHJpYnV0ZSk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiBhdHRyaWJ1dGVzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0IHRoZSB3aWR0aCB3aGljaCBpcyBhIHJlcXVpcmVtZW50IG9mIHRoZSBhYnNvbHV0ZSBwb3NpdGlvbmluZy5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxyXG4gICAqL1xyXG4gIHNldFdpZHRoKHdpZHRoOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB0aGUgd2lkdGguXHJcbiAgICpcclxuICAgKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gICAqL1xyXG4gIGdldFdpZHRoKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gdGhpcy53aWR0aDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB0aGUgYXJyYXkgb2YgYXR0cmlidXRlIGNob2ljZXMgZm9yIHRoZSBpZEF0dHJpYnV0ZS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpZEF0dHJpYnV0ZVxyXG4gICAqIEByZXR1cm5zIHtBdHRyaWJ1dGVDaG9pY2VbXX1cclxuICAgKi9cclxuICBnZXRBdHRyaWJ1dGVDaG9pY2VzKGlkQXR0cmlidXRlOiBudW1iZXIpOiBBdHRyaWJ1dGVDaG9pY2VbXSB7XHJcbiAgICByZXR1cm4gdGhpcy5hdHRyaWJ1dGVNYXAuZ2V0KGlkQXR0cmlidXRlKS5hdHRyaWJ1dGVDaG9pY2VzO1xyXG4gIH1cclxuXHJcbiAgZ2V0TG9hZGluZ1N1YmplY3QoKTogU3ViamVjdDxib29sZWFuPiB7XHJcbiAgICByZXR1cm4gdGhpcy5sb2FkaW5nU3ViamVjdDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB0aGUgY29udGFpbmVyVXBkYXRlZCBzdWJqZWN0LlxyXG4gICAqXHJcbiAgICogQHJldHVybnMge1N1YmplY3Q8bnVtYmVyPn1cclxuICAgKi9cclxuICBnZXRDb250YWluZXJVcGRhdGVkKCk6IFN1YmplY3Q8Ym9vbGVhbj4ge1xyXG4gICAgcmV0dXJuIHRoaXMuY29udGFpbmVyVXBkYXRlZDtcclxuICB9XHJcblxyXG4gIGdldEdyaWRSb3dTYXZlZFN1YmplY3QoKTogU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZUdyaWRSb3c+IHtcclxuICAgIHJldHVybiB0aGlzLmdyaWRSb3dTYXZlZDtcclxuICB9XHJcblxyXG4gIGdldEdyaWRSb3dEZWxldGVkU3ViamVjdCgpOiBTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlR3JpZFJvdz4ge1xyXG4gICAgcmV0dXJuIHRoaXMuZ3JpZFJvd0RlbGV0ZWQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbGVhciB0aGUgdXBkYXRlZCBhbmQgZGVsZXRlZCBhdHRyaWJ1dGUgdmFsdWUgYXJyYXlzLlxyXG4gICAqXHJcbiAgICovXHJcbiAgY2xlYXJVcGRhdGVkQXR0cmlidXRlVmFsdWVzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMgPSBbXTtcclxuICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcyA9IFtdO1xyXG4gICAgdGhpcy5kaXJ0eS5uZXh0KGZhbHNlKTtcclxuICAgIHRoaXMubm90aWZ5QXR0cmlidXRlcygpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2xlYXIgdGhlIHVwZGF0ZWQgYW5kIGRlbGV0ZWQgZ3JpZCByb3cgYXR0cmlidXRlcyBmb3IgdGhlIHNwZWNpZmllZCBncmlkIHJvd1xyXG4gICAqXHJcbiAgICovXHJcbiAgY2xlYXJVcGRhdGVkR3JpZFJvd0F0dHJpYnV0ZVZhbHVlcyhncm91cEF0dHJpYnV0ZVJvd0lkOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGxldCByZW1haW5pbmdBdHRyaWJ1dGVzID0gW107XHJcblxyXG4gICAgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMgPSB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5maWx0ZXIoKGF2KSA9PiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkICE9PSBncm91cEF0dHJpYnV0ZVJvd0lkKTtcclxuICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcyA9ICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMuZmlsdGVyKChhdikgPT4gYXYuZ3JvdXBBdHRyaWJ1dGVSb3dJZCAhPT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCk7XHJcblxyXG4gICAgLy9TaG91bGRuJ3QgYmUgYSBuZWVkIHRvIGNoYW5nZSBkaXJ0eSBvciBub3RpZnkgYXR0cmlidXRlc1xyXG4gIH1cclxuXHJcbiAgc2F2ZUdyaWRSb3dBdHRyaWJ1dGVWYWx1ZXMoaWRHcm91cEF0dHJpYnV0ZTogbnVtYmVyLCBncm91cEF0dHJpYnV0ZVJvd0lkOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGxldCByb3dWYWx1ZXMgPSB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMuZmlsdGVyKChhdikgPT4gYXYuZ3JvdXBBdHRyaWJ1dGVSb3dJZCA9PT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCk7XHJcblxyXG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCByb3dWYWx1ZXMubGVuZ3RoOyBqKyspIHtcclxuICAgICAgLy9zZXQgdGhlIGlkQXR0cmlidXRlVmFsdWVTZXQgaWYgbmVjZXNzYXJ5XHJcbiAgICAgIGlmICghIHJvd1ZhbHVlc1tqXS5pZEF0dHJpYnV0ZVZhbHVlU2V0KSB7XHJcbiAgICAgICAgcm93VmFsdWVzW2pdLmlkQXR0cmlidXRlVmFsdWVTZXQgPSB0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXQ7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vcmVtb3ZlIGFsbCBuZWdhdGl2ZSBpZHMgKG5ldyB2YWx1ZXMpXHJcbiAgICAgIGlmIChyb3dWYWx1ZXNbal0uaWRBdHRyaWJ1dGVWYWx1ZSA8IDApIHtcclxuICAgICAgICByb3dWYWx1ZXNbal0uaWRBdHRyaWJ1dGVWYWx1ZSA9IHVuZGVmaW5lZDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vRm9yIG11bHRpIHZhbHVlcyB0aGF0IHdlcmUgc2xpY2VkIChkZS1zZWxlY3RlZCkgd2UncmUgZ29pbmcgdG8gZmluZCB0aGVtIGFuZCBudWxsIG91dCB0aGUgdmFsdWUsIGluc3RlYWQgb2YgcmVtb3ZpbmcuXHJcbiAgICAvL1RoYXQgbWVhbnMgdGhleSBhY3RhdWxseSBuZWVkIHRvIGJlIGFkZGVkIHRvIHRoZSByb3dWYWx1ZXNcclxuICAgIC8vUmVtb3ZlZCBtdWx0aSB2YWx1ZXMgd2l0aGluIGFuIGV4aXN0aW5nIHJvd1xyXG4gICAgbGV0IHJlbW92ZWRWYWx1ZXMgPSB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5maWx0ZXIoKGF2KSA9PiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkID09PSBncm91cEF0dHJpYnV0ZVJvd0lkKTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVtb3ZlZFZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICByZW1vdmVkVmFsdWVzW2ldLnZhbHVlQXR0cmlidXRlQ2hvaWNlID0gdW5kZWZpbmVkO1xyXG4gICAgICByZW1vdmVkVmFsdWVzW2ldLnZhbHVlSWREaWN0aW9uYXJ5ID0gdW5kZWZpbmVkO1xyXG4gICAgICByb3dWYWx1ZXMucHVzaChyZW1vdmVkVmFsdWVzW2ldKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgYXZncjpBdHRyaWJ1dGVWYWx1ZUdyaWRSb3cgPSA8QXR0cmlidXRlVmFsdWVHcmlkUm93PntcclxuICAgICAgICBpZEF0dHJpYnV0ZVZhbHVlU2V0OiB0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXQsXHJcbiAgICAgICAgaWRHcm91cEF0dHJpYnV0ZTogaWRHcm91cEF0dHJpYnV0ZSxcclxuICAgICAgICBncm91cEF0dHJpYnV0ZVJvd0lkOiBncm91cEF0dHJpYnV0ZVJvd0lkLFxyXG4gICAgICAgIGF0dHJpYnV0ZVZhbHVlczogcm93VmFsdWVzXHJcbiAgICAgIH07XHJcblxyXG4gICAgbGV0IHVybDogc3RyaW5nID0gdGhpcy5hdHRyaWJ1dGVFbmRwb2ludCArIFwiYXR0cmlidXRlLXZhbHVlLWdyaWQtcm93L1wiIDtcclxuXHJcbiAgICBsZXQgYWM6IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPSB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25TdWJqZWN0LmdldFZhbHVlKCk7XHJcblxyXG4gICAgbGV0IHF1ZXJ5UGFyYW1zOiBIdHRwUGFyYW1zID0gbmV3IEh0dHBQYXJhbXMoKVxyXG4gICAgLnNldChcImNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRcIiwgYWMuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dClcclxuICAgIC5zZXQoXCJjb2RlQXR0cmlidXRlQ29udGV4dFwiLCBhYy5jb2RlQXR0cmlidXRlQ29udGV4dClcclxuICAgIC5zZXQoXCJpZFBhcmVudE9iamVjdFwiLCAodGhpcy5pZFBhcmVudE9iamVjdCk/dGhpcy5pZFBhcmVudE9iamVjdC50b1N0cmluZygpOlwiXCIpO1xyXG5cclxuXHJcbiAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQodHJ1ZSk7XHJcblxyXG4gICAgLy9TYXZlIG5ldyByb3dcclxuICAgIGlmIChncm91cEF0dHJpYnV0ZVJvd0lkIDwgMCkge1xyXG4gICAgICB0aGlzLmh0dHAucG9zdCh1cmwsIGF2Z3IsIHtwYXJhbXM6IHF1ZXJ5UGFyYW1zfSkuc3Vic2NyaWJlKChhdHRyaWJ1dGVWYWx1ZUdyaWRSb3c6IEF0dHJpYnV0ZVZhbHVlR3JpZFJvdykgPT4ge1xyXG5cclxuICAgICAgICAvL0FkZCB0aGUgZ3JpZCByb3cgdG8gdGhlIG9yaWdpbmFsIGF0dHJpYnV0ZSB2YWx1ZXNcclxuICAgICAgICBsZXQgYXZzOkF0dHJpYnV0ZVZhbHVlU2V0ID0gdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhdHRyaWJ1dGVWYWx1ZUdyaWRSb3cuYXR0cmlidXRlVmFsdWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICBhdnMuYXR0cmlidXRlVmFsdWVzLnB1c2goYXR0cmlidXRlVmFsdWVHcmlkUm93LmF0dHJpYnV0ZVZhbHVlc1tpXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvL1JlbW92ZSB0aGUgdXBkYXRlZCBhbmQgc2xpY2VkIHZhbHVlcyBmb3IgdGhlIGdyaWQgcm93LCBub3cgKHRoZXNlIGFyZSB0aGUgb2xkIG9uZXMgd2l0aCB0aGUgbmVnYXRpdmUgcm93aWQpXHJcbiAgICAgICAgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMgPSB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5maWx0ZXIoKGF2KSA9PiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkICE9PSBncm91cEF0dHJpYnV0ZVJvd0lkKTtcclxuICAgICAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMgPSAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLmZpbHRlcigoYXYpID0+IGF2Lmdyb3VwQXR0cmlidXRlUm93SWQgIT09IGdyb3VwQXR0cmlidXRlUm93SWQpO1xyXG5cclxuICAgICAgICB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5uZXh0KGF2cyk7XHJcbiAgICAgICAgdGhpcy5ncmlkUm93U2F2ZWQubmV4dChhdHRyaWJ1dGVWYWx1ZUdyaWRSb3cpO1xyXG4gICAgICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dChmYWxzZSk7XHJcbiAgICAgIH0sXHJcbiAgICAgIChlcnJvcikgPT4ge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dChmYWxzZSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgLy9VcGRhdGUgZXhpc3Rpbmcgcm93XHJcbiAgICBlbHNlIHtcclxuICAgICAgdGhpcy5odHRwLnB1dCh1cmwsIGF2Z3IsIHtwYXJhbXM6IHF1ZXJ5UGFyYW1zfSkuc3Vic2NyaWJlKChhdHRyaWJ1dGVWYWx1ZUdyaWRSb3c6IEF0dHJpYnV0ZVZhbHVlR3JpZFJvdykgPT4ge1xyXG5cclxuICAgICAgICAvL0FkZCB0aGUgZ3JpZCByb3cgdG8gdGhlIG9yaWdpbmFsIGF0dHJpYnV0ZSB2YWx1ZXNcclxuICAgICAgICBsZXQgYXZzOkF0dHJpYnV0ZVZhbHVlU2V0ID0gdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKTtcclxuXHJcbiAgICAgICAgLy9SZW1vdmUgYWxsIG9sZCB2YWx1ZXMgZm9yIHJvd1xyXG4gICAgICAgIGxldCBpbmRleCA9IGF2cy5hdHRyaWJ1dGVWYWx1ZXMuZmluZEluZGV4KChhdik9PiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkID09PSBncm91cEF0dHJpYnV0ZVJvd0lkKTtcclxuICAgICAgICB3aGlsZSAoaW5kZXggPiAwKSB7XHJcbiAgICAgICAgICAvL1JlbW92ZSB2YWx1ZVxyXG4gICAgICAgICAgYXZzLmF0dHJpYnV0ZVZhbHVlcy5zcGxpY2UoaW5kZXgsIDEpO1xyXG5cclxuICAgICAgICAgIC8vRmluZCB0aGUgbmV4dCBvbmVcclxuICAgICAgICAgIGluZGV4ID0gYXZzLmF0dHJpYnV0ZVZhbHVlcy5maW5kSW5kZXgoKGF2KT0+IGF2Lmdyb3VwQXR0cmlidXRlUm93SWQgPT09IGdyb3VwQXR0cmlidXRlUm93SWQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9BZGQgYWxsIHRoZSBjdXJyZW50IHZhbHVlc1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXR0cmlidXRlVmFsdWVHcmlkUm93LmF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgYXZzLmF0dHJpYnV0ZVZhbHVlcy5wdXNoKGF0dHJpYnV0ZVZhbHVlR3JpZFJvdy5hdHRyaWJ1dGVWYWx1ZXNbaV0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9SZW1vdmUgdGhlIHNsaWNlZCBhbmQgdXBkYXRlZCB2YWx1ZXMgZm9yIHRoZSBncmlkIHJvd1xyXG4gICAgICAgIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzID0gdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMuZmlsdGVyKChhdikgPT4gYXYuZ3JvdXBBdHRyaWJ1dGVSb3dJZCAhPT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCk7XHJcbiAgICAgICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzID0gIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5maWx0ZXIoKGF2KSA9PiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkICE9PSBncm91cEF0dHJpYnV0ZVJvd0lkKTtcclxuXHJcbiAgICAgICAgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QubmV4dChhdnMpO1xyXG4gICAgICAgIHRoaXMuZ3JpZFJvd1NhdmVkLm5leHQoYXR0cmlidXRlVmFsdWVHcmlkUm93KTtcclxuICAgICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG4gICAgICB9LFxyXG4gICAgICAoZXJyb3IpID0+IHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcclxuICAgICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGRlbGV0ZUdyaWRSb3dBdHRyaWJ1dGVWYWx1ZXMoaWRHcm91cEF0dHJpYnV0ZTogbnVtYmVyLCBncm91cEF0dHJpYnV0ZVJvd0lkOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGxldCB1cmw6IHN0cmluZyA9IHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImF0dHJpYnV0ZS12YWx1ZS1ncmlkLXJvdy9cIiA7XHJcblxyXG4gICAgbGV0IGFjOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uID0gdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdC5nZXRWYWx1ZSgpO1xyXG5cclxuICAgIGxldCBxdWVyeVBhcmFtczogSHR0cFBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKClcclxuICAgIC5zZXQoXCJjb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0XCIsIGFjLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQpXHJcbiAgICAuc2V0KFwiY29kZUF0dHJpYnV0ZUNvbnRleHRcIiwgYWMuY29kZUF0dHJpYnV0ZUNvbnRleHQpXHJcbiAgICAuc2V0KFwiaWRQYXJlbnRPYmplY3RcIiwgKHRoaXMuaWRQYXJlbnRPYmplY3QpP3RoaXMuaWRQYXJlbnRPYmplY3QudG9TdHJpbmcoKTpcIlwiKTtcclxuXHJcbiAgICBsZXQgYXZncjpBdHRyaWJ1dGVWYWx1ZUdyaWRSb3cgPSA8QXR0cmlidXRlVmFsdWVHcmlkUm93PntcclxuICAgICAgICBpZEF0dHJpYnV0ZVZhbHVlU2V0OiB0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXQsXHJcbiAgICAgICAgaWRHcm91cEF0dHJpYnV0ZTogaWRHcm91cEF0dHJpYnV0ZSxcclxuICAgICAgICBncm91cEF0dHJpYnV0ZVJvd0lkOiBncm91cEF0dHJpYnV0ZVJvd0lkLFxyXG4gICAgICAgIGF0dHJpYnV0ZVZhbHVlczogW11cclxuICAgICAgfTtcclxuXHJcbiAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQodHJ1ZSk7XHJcblxyXG4gICAgdGhpcy5odHRwLnJlcXVlc3QoJ2RlbGV0ZScsIHVybCwge2JvZHk6IGF2Z3IsIHBhcmFtczogcXVlcnlQYXJhbXN9KS5zdWJzY3JpYmUoKCkgPT4ge1xyXG5cclxuICAgICAgLy9SZW1vdmUgdGhlIGdyaWQgcm93IGZyb20gdGhlIG9yaWdpbmFsIGF0dHJpYnV0ZSB2YWx1ZXNcclxuICAgICAgbGV0IGF2czpBdHRyaWJ1dGVWYWx1ZVNldCA9IHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCk7XHJcbiAgICAgIGF2cy5hdHRyaWJ1dGVWYWx1ZXMgPSBhdnMuYXR0cmlidXRlVmFsdWVzLmZpbHRlcigoYXYpID0+IGF2Lmdyb3VwQXR0cmlidXRlUm93SWQgIT09IGdyb3VwQXR0cmlidXRlUm93SWQpO1xyXG4gICAgICB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5uZXh0KGF2cyk7XHJcbiAgICAgIHRoaXMuZ3JpZFJvd0RlbGV0ZWQubmV4dChhdmdyKTtcclxuICAgICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuICAgIH0sXHJcbiAgICAoZXJyb3IpID0+IHtcclxuICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XHJcbiAgICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dChmYWxzZSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFB1c2ggYW4gYXR0cmlidXRlIHRvIHRoZSBhdHRyaWJ1dGUgbWFwLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtBdHRyaWJ1dGV9IGF0dHJpYnV0ZVxyXG4gICAqL1xyXG4gIHB1c2hBdHRyaWJ1dGUoYXR0cmlidXRlOiBBdHRyaWJ1dGUpOiB2b2lkIHtcclxuICAgIHRoaXMuYXR0cmlidXRlTWFwLnNldChhdHRyaWJ1dGUuaWRBdHRyaWJ1dGUsIGF0dHJpYnV0ZSk7XHJcbiAgfVxyXG5cclxuXHJcbiAgcHVzaEF0dHJpYnV0ZVZhbHVlTXVsdGlDaG9pY2UoYXR0cmlidXRlVmFsdWU6IEF0dHJpYnV0ZVZhbHVlKTogdm9pZCB7XHJcbiAgICAvL1JlbW92ZSBmcm9tIHNsaWNlZCBpZiBwcmVzZW50XHJcbiAgICBsZXQgaTogbnVtYmVyID0gMDtcclxuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAodGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uaWRBdHRyaWJ1dGUgPT09IGF0dHJpYnV0ZVZhbHVlLmlkQXR0cmlidXRlICYmIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzW2ldLnZhbHVlQXR0cmlidXRlQ2hvaWNlLmlkQXR0cmlidXRlQ2hvaWNlID09PSBhdHRyaWJ1dGVWYWx1ZS52YWx1ZUF0dHJpYnV0ZUNob2ljZS5pZEF0dHJpYnV0ZUNob2ljZSkge1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvL1JlbW92ZSBmcm9tIHNsaWNlZCBhdHRyaWJ1dGUgdmFsdWVzIChubyBsb25nZXIgcmVtb3ZpbmcpXHJcbiAgICBpZiAoaSA8IHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5zcGxpY2UoaSwgMSk7XHJcbiAgICB9XHJcbiAgICAvL090aGVyd2lzZSBwdXNoIHRoZSB2YWx1ZSwgc28gaXQgd2lsbCBiZSBzYXZlZFxyXG4gICAgZWxzZSB7XHJcbiAgICAgIHRoaXMucHVzaEF0dHJpYnV0ZVZhbHVlKGF0dHJpYnV0ZVZhbHVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1c2hBdHRyaWJ1dGVWYWx1ZU11bHRpRGljdChhdHRyaWJ1dGVWYWx1ZTogQXR0cmlidXRlVmFsdWUpOiB2b2lkIHtcclxuICAgIC8vUmVtb3ZlIGZyb20gc2xpY2VkIGlmIHByZXNlbnRcclxuICAgIGxldCBpOiBudW1iZXIgPSAwO1xyXG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGlmICh0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZSA9PT0gYXR0cmlidXRlVmFsdWUuaWRBdHRyaWJ1dGUgJiYgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXNbaV0udmFsdWVJZERpY3Rpb25hcnkgPT09IGF0dHJpYnV0ZVZhbHVlLnZhbHVlSWREaWN0aW9uYXJ5KSB7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vUmVtb3ZlIGZyb20gc2xpY2VkIGF0dHJpYnV0ZSB2YWx1ZXMgKG5vIGxvbmdlciByZW1vdmluZylcclxuICAgIGlmIChpIDwgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzLnNwbGljZShpLCAxKTtcclxuICAgIH1cclxuICAgIC8vT3RoZXJ3aXNlIHB1c2ggdGhlIHZhbHVlLCBzbyBpdCB3aWxsIGJlIHNhdmVkXHJcbiAgICBlbHNlIHtcclxuICAgICAgdGhpcy5wdXNoQXR0cmlidXRlVmFsdWUoYXR0cmlidXRlVmFsdWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUHVzaCBhIG5ldyBvciB1cGRhdGVkIGF0dHJpYnV0ZSB2YWx1ZS4gIFRoZSBjdXJyZW50IG9uZSBpcyBqdXN0IHJlbW92ZWQgYW5kIHRoZSBuZXcgb25lIGFwcGVuZGVkIHRvIHRoZSBhcnJheS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlVmFsdWV9IGF0dHJpYnV0ZVZhbHVlXHJcbiAgICovXHJcbiAgcHVzaEF0dHJpYnV0ZVZhbHVlKGF0dHJpYnV0ZVZhbHVlOiBBdHRyaWJ1dGVWYWx1ZSk6IHZvaWQge1xyXG4gICAgaWYgKGlzRGV2TW9kZSgpKSB7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoXCJwdXNoQXR0cmlidXRlVmFsdWVcIik7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoYXR0cmlidXRlVmFsdWUpO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBpOiBudW1iZXIgPSAwO1xyXG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAodGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2ldLmlkQXR0cmlidXRlVmFsdWUgPT09IGF0dHJpYnV0ZVZhbHVlLmlkQXR0cmlidXRlVmFsdWUpIHtcclxuICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKGkgPCB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5zcGxpY2UoaSwgMSk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLnB1c2goYXR0cmlidXRlVmFsdWUpO1xyXG4gICAgdGhpcy5hdHRyaWJ1dGVWYWx1ZVB1c2hlZFN1YmplY3QubmV4dChhdHRyaWJ1dGVWYWx1ZSk7XHJcblxyXG4gICAgLy9Pbmx5IHNldHRpbmcgZGlydHkgZm9yIG5vbiBncmlkLXJvd3MgKHRob3NlIGFyZSBzYXZlZCBpbW1lZGlhdGVseSlcclxuICAgIGlmICghIGF0dHJpYnV0ZVZhbHVlLmlkR3JvdXBBdHRyaWJ1dGUpIHtcclxuICAgICAgdGhpcy5kaXJ0eS5uZXh0KHRydWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRm9yIHB1c2hpbmcgbXVsdGlwbGUgYXR0cmlidXRlIHZhbHVlcyBhdCBvbmNlLiAgVGhpcyB3b3VsZCB0eXBpY2FsbHkgYmUgZm9yIGEgbXVsdGkgY2hvaWNlLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtBdHRyaWJ1dGV9IGF0dHJpYnV0ZVxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlVmFsdWVbXX0gYXR0cmlidXRlVmFsdWVzXHJcbiAgICovXHJcbiAgcHVzaEF0dHJpYnV0ZVZhbHVlcyhhdHRyaWJ1dGU6IEF0dHJpYnV0ZSwgYXR0cmlidXRlVmFsdWVzOiBBdHRyaWJ1dGVWYWx1ZVtdKTogdm9pZCB7XHJcbiAgICBpZiAoaXNEZXZNb2RlKCkpIHtcclxuICAgICAgY29uc29sZS5kZWJ1ZyhcInB1c2hBdHRyaWJ1dGVWYWx1ZXNcIik7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoYXR0cmlidXRlVmFsdWVzKTtcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBsZXQgajogbnVtYmVyID0gMDtcclxuICAgICAgZm9yIChqID0gMDsgaiA8IHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgIGlmICh0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbal0uaWRBdHRyaWJ1dGUgIT09IGF0dHJpYnV0ZS5pZEF0dHJpYnV0ZSkge1xyXG4gICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbal0uaWRBdHRyaWJ1dGVWYWx1ZSA9PT0gYXR0cmlidXRlVmFsdWVzW2ldLmlkQXR0cmlidXRlVmFsdWUpIHtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBpZiAoaiA8IHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5sZW5ndGgpIHtcclxuICAgICAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbal0gPSBhdHRyaWJ1dGVWYWx1ZXNbaV07XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLnB1c2goYXR0cmlidXRlVmFsdWVzW2ldKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChpc0Rldk1vZGUoKSkge1xyXG4gICAgICBjb25zb2xlLmRlYnVnKHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy9Pbmx5IHNldHRpbmcgZGlydHkgZm9yIG5vbiBncmlkLXJvd3MgKHRob3NlIGFyZSBzYXZlZCBpbW1lZGlhdGVseSlcclxuICAgIGlmICghIGF0dHJpYnV0ZS5pZEdyb3VwQXR0cmlidXRlKSB7XHJcbiAgICAgIHRoaXMuZGlydHkubmV4dCh0cnVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFB1c2ggYSB2YWx1ZSBpbiB0aGUgY2FzZSB3aGVyZSBhbiBhdHRyaWJ1dGUgdmFsdWUgZG9lc24ndCBleGlzdC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlfSBhdHRyaWJ1dGVcclxuICAgKiBAcGFyYW0gdmFsdWVcclxuICAgKi9cclxuICBwdXNoVmFsdWUoYXR0cmlidXRlOiBBdHRyaWJ1dGUsIHZhbHVlOiBhbnkpOiB2b2lkIHtcclxuICAgIGxldCBhdHRyaWJ1dGVWYWx1ZTogQXR0cmlidXRlVmFsdWUgPSA8QXR0cmlidXRlVmFsdWU+e1xyXG4gICAgICBpZEF0dHJpYnV0ZTogYXR0cmlidXRlLmlkQXR0cmlidXRlLFxyXG4gICAgICBpZEF0dHJpYnV0ZVZhbHVlU2V0OiB0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXRcclxuICAgIH07XHJcblxyXG4gICAgaWYgKGF0dHJpYnV0ZS5jb2RlQXR0cmlidXRlRGF0YVR5cGUgPT09IFwiVFhUXCIpIHtcclxuICAgICAgYXR0cmlidXRlVmFsdWUudmFsdWVMb25nVGV4dCA9IHtcclxuICAgICAgICBpZExvbmdUZXh0OiB1bmRlZmluZWQsXHJcbiAgICAgICAgdGV4dERhdGE6IHZhbHVlXHJcbiAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLnB1c2goYXR0cmlidXRlVmFsdWUpO1xyXG4gICAgdGhpcy5kaXJ0eS5uZXh0KHRydWUpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIGFuIGF0dHJpYnV0ZSB2YWx1ZS4gIFR5cGljYWxseSBpbiB0aGUgY2FzZSBvZiBhIG11bHRpIHNlbGVjdCB3aGVyZSB0aGUgdW5zZWxlY3RlZCB2YWx1ZSBpcyByZW1vdmVkLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtBdHRyaWJ1dGV9IGF0dHJpYnV0ZVxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlQ2hvaWNlfSBhdHRyaWJ1dGVDaG9pY2VcclxuICAgKi9cclxuICBzcGxpY2VBdHRyaWJ1dGVWYWx1ZUNob2ljZShhdHRyaWJ1dGU6IEF0dHJpYnV0ZSwgYXR0cmlidXRlQ2hvaWNlOiBBdHRyaWJ1dGVDaG9pY2UpOiB2b2lkIHtcclxuICAgIGlmIChpc0Rldk1vZGUoKSkge1xyXG4gICAgICBjb25zb2xlLmRlYnVnKFwic2xpY2VBdHRyaWJ1dGVWYWx1ZTogXCIgKyBhdHRyaWJ1dGUuaWRBdHRyaWJ1dGUgKyBcIiwgXCIgKyBhdHRyaWJ1dGVDaG9pY2UuaWRBdHRyaWJ1dGVDaG9pY2UpO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBpOiBudW1iZXIgPSAwO1xyXG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAodGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2ldLmlkQXR0cmlidXRlID09PSBhdHRyaWJ1dGUuaWRBdHRyaWJ1dGUgJiYgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2ldLnZhbHVlQXR0cmlidXRlQ2hvaWNlLmlkQXR0cmlidXRlQ2hvaWNlID09PSBhdHRyaWJ1dGVDaG9pY2UuaWRBdHRyaWJ1dGVDaG9pY2UpIHtcclxuICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgLy9SZW1vdmUgZnJvbSB1cGRhdGVkIGF0dHJpYnV0ZSB2YWx1ZXMgKG5vdCBwcmV2aW91c2x5IHNhdmVkKVxyXG4gICAgaWYgKGkgPCB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5zcGxpY2UoaSwgMSk7XHJcbiAgICB9XHJcbiAgICAvL0FkZCB0byBzbGljZWQgdmFsdWVzIChwcmV2aW91c2x5IHNhdmVkIC0gbmVlZCB0byByZW1vdmUpXHJcbiAgICBlbHNlIHtcclxuICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCkuYXR0cmlidXRlVmFsdWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCkuYXR0cmlidXRlVmFsdWVzW2ldLmlkQXR0cmlidXRlID09PSBhdHRyaWJ1dGUuaWRBdHRyaWJ1dGVcclxuICAgICAgICAgICAgJiYgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKS5hdHRyaWJ1dGVWYWx1ZXNbaV0udmFsdWVBdHRyaWJ1dGVDaG9pY2UuaWRBdHRyaWJ1dGVDaG9pY2UgPT09IGF0dHJpYnV0ZUNob2ljZS5pZEF0dHJpYnV0ZUNob2ljZSkge1xyXG4gICAgICAgICAgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMucHVzaCh0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpLmF0dHJpYnV0ZVZhbHVlc1tpXSk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvL09ubHkgZmxhZ2dpbmcgZGlydHkgZm9yIG5vbi1ncmlkIHJvd3MgKHRob3NlIGFyZSBzYXZlZCBpbW1lZGlhdGVseSlcclxuICAgIGlmICghIGF0dHJpYnV0ZS5pZEdyb3VwQXR0cmlidXRlKSB7XHJcbiAgICAgIHRoaXMuZGlydHkubmV4dCh0cnVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICAgKiBSZW1vdmUgYW4gYXR0cmlidXRlIHZhbHVlLiAgVHlwaWNhbGx5IGluIHRoZSBjYXNlIG9mIGEgbXVsdGkgc2VsZWN0IHdoZXJlIHRoZSB1bnNlbGVjdGVkIHZhbHVlIGlzIHJlbW92ZWQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge0F0dHJpYnV0ZX0gYXR0cmlidXRlXHJcbiAgICogQHBhcmFtIHtBdHRyaWJ1dGVDaG9pY2V9IGF0dHJpYnV0ZUNob2ljZVxyXG4gICAqL1xyXG4gIHNwbGljZUF0dHJpYnV0ZVZhbHVlRGljdChhdHRyaWJ1dGU6IEF0dHJpYnV0ZSwgdmFsdWU6IGFueSk6IHZvaWQge1xyXG4gICAgaWYgKGlzRGV2TW9kZSgpKSB7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoXCJzbGljZUF0dHJpYnV0ZVZhbHVlOiBcIiArIGF0dHJpYnV0ZS5pZEF0dHJpYnV0ZSArIFwiLCBcIiArIHZhbHVlKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgaTogbnVtYmVyID0gMDtcclxuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgaWYgKHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZSA9PT0gYXR0cmlidXRlLmlkQXR0cmlidXRlICYmIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS52YWx1ZUlkRGljdGlvbmFyeSA9PT0gdmFsdWUpIHtcclxuICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgLy9SZW1vdmUgZnJvbSB1cGRhdGVkIGF0dHJpYnV0ZSB2YWx1ZXMgKG5vdCBwcmV2aW91c2x5IHNhdmVkKVxyXG4gICAgaWYgKGkgPCB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5zcGxpY2UoaSwgMSk7XHJcbiAgICB9XHJcbiAgICAvL0FkZCB0byBzbGljZWQgdmFsdWVzIChwcmV2aW91c2x5IHNhdmVkIC0gbmVlZCB0byByZW1vdmUpXHJcbiAgICBlbHNlIHtcclxuICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCkuYXR0cmlidXRlVmFsdWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCkuYXR0cmlidXRlVmFsdWVzW2ldLmlkQXR0cmlidXRlID09PSBhdHRyaWJ1dGUuaWRBdHRyaWJ1dGVcclxuICAgICAgICAgICAgJiYgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKS5hdHRyaWJ1dGVWYWx1ZXNbaV0udmFsdWVJZERpY3Rpb25hcnkgPT09IHZhbHVlKSB7XHJcbiAgICAgICAgICB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5wdXNoKHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCkuYXR0cmlidXRlVmFsdWVzW2ldKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vT25seSBmbGFnZ2luZyBkaXJ0eSBmb3Igbm9uLWdyaWQgcm93cyAodGhvc2UgYXJlIHNhdmVkIGltbWVkaWF0ZWx5KVxyXG4gICAgaWYgKCEgYXR0cmlidXRlLmlkR3JvdXBBdHRyaWJ1dGUpIHtcclxuICAgICAgdGhpcy5kaXJ0eS5uZXh0KHRydWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IHRoZSBhdHRyaWJ1dGUgYmFzZWQgdXBvbiB0aGUgaWRBdHRyaWJ1dGUuICBUaGlzIGlzIGZyb20gdGhlIG1hcCBvZiBhdHRyaWJ1dGVzLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtudW1iZXJ9IGlkQXR0cmlidXRlXHJcbiAgICogQHJldHVybnMge0F0dHJpYnV0ZX1cclxuICAgKi9cclxuICBnZXRBdHRyaWJ1dGUoaWRBdHRyaWJ1dGU6IG51bWJlcik6IEF0dHJpYnV0ZSB7XHJcbiAgICByZXR1cm4gdGhpcy5hdHRyaWJ1dGVNYXAuZ2V0KGlkQXR0cmlidXRlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEZvciB0aGUgYXR0cmlidXRlIGNvbmZpZ3VyYXRpb24sIHNldCBhbGwgb2YgdGhlIG5lZ2F0aXZlIGlkcyB0byB1bmRlZmluZWQgcHJpb3IgdG8gcG9zdGluZy5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlQ29uZmlndXJhdGlvbn0gYXR0cmlidXRlQ29uZmlndXJhdGlvblxyXG4gICAqL1xyXG4gIHNldE5lZ2F0aXZlSWRzVG9VbmRlZmluZWQoYXR0cmlidXRlQ29uZmlndXJhdGlvbjogQXR0cmlidXRlQ29uZmlndXJhdGlvbik6IHZvaWQge1xyXG4gICAgaWYgKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uIDwgMCkge1xyXG4gICAgICBhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiA9IHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGxldCBhdHRyaWJ1dGVDb250YWluZXIgb2YgYXR0cmlidXRlQ29uZmlndXJhdGlvbi5hdHRyaWJ1dGVDb250YWluZXJzKSB7XHJcbiAgICAgIGlmIChhdHRyaWJ1dGVDb250YWluZXIuaWRBdHRyaWJ1dGVDb250YWluZXIgIDwgMCkge1xyXG4gICAgICAgIGF0dHJpYnV0ZUNvbnRhaW5lci5pZEF0dHJpYnV0ZUNvbnRhaW5lciA9IHVuZGVmaW5lZDtcclxuICAgICAgfVxyXG5cclxuICAgICAgZm9yIChsZXQgYXR0cmlidXRlIG9mIGF0dHJpYnV0ZUNvbnRhaW5lci5ncmFwaGljYWxBdHRyaWJ1dGVzKSB7XHJcblxyXG4gICAgICAgIGlmIChhdHRyaWJ1dGUuaWRBdHRyaWJ1dGUgIDwgMCkge1xyXG4gICAgICAgICAgYXR0cmlidXRlLmlkQXR0cmlidXRlID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGF0dHJpYnV0ZS5hdHRyaWJ1dGVDaG9pY2VzKSB7XHJcbiAgICAgICAgICBmb3IgKGxldCBhdHRyaWJ1dGVDaG9pY2Ugb2YgYXR0cmlidXRlLmF0dHJpYnV0ZUNob2ljZXMpIHtcclxuICAgICAgICAgICAgZGVsZXRlIGF0dHJpYnV0ZVtcInZhbHVlXCJdO1xyXG5cclxuICAgICAgICAgICAgaWYgKGF0dHJpYnV0ZUNob2ljZS5pZEF0dHJpYnV0ZSAgPCAwKSB7XHJcbiAgICAgICAgICAgICAgYXR0cmlidXRlQ2hvaWNlLmlkQXR0cmlidXRlID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChhdHRyaWJ1dGVDaG9pY2UuaWRBdHRyaWJ1dGVDaG9pY2UgIDwgMCkge1xyXG4gICAgICAgICAgICAgIGF0dHJpYnV0ZUNob2ljZS5pZEF0dHJpYnV0ZUNob2ljZSA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhIGRpc3BsYXkgbmFtZSBmb3IgdGhlIGF0dHJpYnV0ZSBjb25maWd1cmF0aW9uIGJhc2VkIG9uIHRoZSBjb250ZXh0IGNvZGUgYW5kIGlkLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtBdHRyaWJ1dGVDb25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uXHJcbiAgICogQHJldHVybnMge3N0cmluZ31cclxuICAgKi9cclxuICBnZXRDb25maWd1cmF0aW9uTmFtZShjb25maWd1cmF0aW9uOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPKTogc3RyaW5nIHtcclxuICAgIGlmIChjb25maWd1cmF0aW9uLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiA9PT0gLTEpIHtcclxuICAgICAgcmV0dXJuIFwiTmV3XCI7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IG5hbWU6IHN0cmluZyA9IGNvbmZpZ3VyYXRpb24uY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dERpc3BsYXkgKyBcIjogXCIgKyBjb25maWd1cmF0aW9uLmV4dGVuc2lvbkRlc2NyaXB0aW9uO1xyXG5cclxuICAgIGlmIChjb25maWd1cmF0aW9uLmlkRmlsdGVyMSkge1xyXG4gICAgICBuYW1lICs9IFwiIC0gXCIgKyBjb25maWd1cmF0aW9uLmZpbHRlcjFEaXNwbGF5O1xyXG4gICAgfVxyXG4gICAgaWYgKGNvbmZpZ3VyYXRpb24uaWRGaWx0ZXIyKSB7XHJcbiAgICAgIG5hbWUgKz0gXCIgLSBcIiArIGNvbmZpZ3VyYXRpb24uZmlsdGVyMkRpc3BsYXk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbmFtZTtcclxuICB9XHJcblxyXG4gIGdldEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8oY2ZnOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uKTogQXR0cmlidXRlQ29uZmlndXJhdGlvbkRUTyB7XHJcbiAgICBpZiAoIWNmZykge1xyXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBkdG86IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8gPSA8QXR0cmlidXRlQ29uZmlndXJhdGlvbkRUTz57XHJcbiAgICAgIGlkQXR0cmlidXRlQ29uZmlndXJhdGlvbjogY2ZnLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbixcclxuICAgICAgY29kZUF0dHJpYnV0ZUNvbnRleHQ6IGNmZy5jb2RlQXR0cmlidXRlQ29udGV4dCxcclxuICAgICAgY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dDogY2ZnLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQsXHJcbiAgICAgIGlkRmlsdGVyMTogY2ZnLmlkRmlsdGVyMSxcclxuICAgICAgaWRGaWx0ZXIyOiBjZmcuaWRGaWx0ZXIyXHJcbiAgICB9O1xyXG5cclxuICAgIGlmICh0aGlzLmF0dHJpYnV0ZUNvbnRleHRMaXN0U3ViamVjdC5nZXRWYWx1ZSgpKSB7XHJcbiAgICAgIGR0by5leHRlbnNpb25EZXNjcmlwdGlvbiA9IHRoaXMuYXR0cmlidXRlQ29udGV4dExpc3RTdWJqZWN0LmdldFZhbHVlKCkuZmlsdGVyKChjdHg6IGFueSkgPT4ge1xyXG4gICAgICAgIHJldHVybiBjdHguY29kZUF0dHJpYnV0ZUNvbnRleHQgPT09IGNmZy5jb2RlQXR0cmlidXRlQ29udGV4dDtcclxuICAgICAgfSlbMF0uZXh0ZW5zaW9uRGVzY3JpcHRpb247XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuYXR0cmlidXRlU2VjdXJpdHlDb250ZXh0TGlzdFN1YmplY3QuZ2V0VmFsdWUoKSkge1xyXG4gICAgICBsZXQgcmVzdWx0OiBhbnlbXSA9IHRoaXMuYXR0cmlidXRlU2VjdXJpdHlDb250ZXh0TGlzdFN1YmplY3QuZ2V0VmFsdWUoKS5maWx0ZXIoKGZpbHRlcjogYW55KSA9PiB7XHJcbiAgICAgICAgcmV0dXJuIGZpbHRlci5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0ID09PSBjZmcuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dDtcclxuICAgICAgfSk7XHJcbiAgICAgIGR0by5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0RGlzcGxheSA9IChyZXN1bHQgJiYgcmVzdWx0Lmxlbmd0aCA+IDApID8gcmVzdWx0WzBdLmRlc2NyaXB0aW9uIDogdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmZpbHRlcjFMaXN0U3ViamVjdC5nZXRWYWx1ZSgpKSB7XHJcbiAgICAgIGxldCByZXN1bHQ6IGFueVtdID0gdGhpcy5maWx0ZXIxTGlzdFN1YmplY3QuZ2V0VmFsdWUoKS5maWx0ZXIoKGZpbHRlcjogYW55KSA9PiB7XHJcbiAgICAgICAgcmV0dXJuIGZpbHRlci5jb2RlQXR0cmlidXRlQ29udGV4dCA9PT0gY2ZnLmNvZGVBdHRyaWJ1dGVDb250ZXh0XHJcbiAgICAgICAgICAmJiBmaWx0ZXIuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dCA9PT0gY2ZnLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRcclxuICAgICAgICAgICYmIGZpbHRlci5pZEZpbHRlcjEgPT09IGNmZy5pZEZpbHRlcjE7XHJcbiAgICAgIH0pO1xyXG4gICAgICBkdG8uZmlsdGVyMURpc3BsYXkgPSAocmVzdWx0ICYmIHJlc3VsdC5sZW5ndGggPiAwKSA/IHJlc3VsdFswXS5kaXNwbGF5IDogdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmZpbHRlcjJMaXN0U3ViamVjdC5nZXRWYWx1ZSgpKSB7XHJcbiAgICAgIGxldCByZXN1bHQ6IGFueVtdID0gdGhpcy5maWx0ZXIyTGlzdFN1YmplY3QuZ2V0VmFsdWUoKS5maWx0ZXIoKGZpbHRlcjogYW55KSA9PiB7XHJcbiAgICAgICAgcmV0dXJuIGZpbHRlci5jb2RlQXR0cmlidXRlQ29udGV4dCA9PT0gY2ZnLmNvZGVBdHRyaWJ1dGVDb250ZXh0XHJcbiAgICAgICAgICAmJiBmaWx0ZXIuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dCA9PT0gY2ZnLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRcclxuICAgICAgICAgICYmIGZpbHRlci5pZEZpbHRlcjEgPT09IGNmZy5pZEZpbHRlcjFcclxuICAgICAgICAgICYmIGZpbHRlci5pZEZpbHRlcjIgPT09IGNmZy5pZEZpbHRlcjI7XHJcbiAgICAgIH0pO1xyXG4gICAgICBkdG8uZmlsdGVyMkRpc3BsYXkgPSAocmVzdWx0ICYmIHJlc3VsdC5sZW5ndGggPiAwKSA/IHJlc3VsdFswXS5kaXNwbGF5IDogdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBkdG87XHJcbiAgfVxyXG5cclxuICBnZXRTZWN1cml0eUNvZGVDb250ZXh0KGNvZGU6IHN0cmluZyk6IGFueSB7XHJcbiAgICByZXR1cm4gdGhpcy5hdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRMaXN0U3ViamVjdC5nZXRWYWx1ZSgpLmZpbHRlcigoZmlsdGVyOiBhbnkpID0+IHtcclxuICAgICAgcmV0dXJuIGZpbHRlci5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0ID09PSBjb2RlO1xyXG4gICAgfSlbMF07XHJcbiAgfVxyXG5cclxuICBnZXRBdHRyaWJ1dGVDb250ZXh0TG9hZGluZ1N1YmplY3QoKTogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+IHtcclxuICAgIHJldHVybiB0aGlzLmF0dHJpYnV0ZUNvbnRleHRMb2FkaW5nU3ViamVjdDtcclxuICB9XHJcblxyXG4gIGdldEZpbHRlcjFGb3IoY29kZUF0dHJpYnV0ZUNvbnRleHQ6IHN0cmluZywgY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dDogc3RyaW5nKTogYW55W10ge1xyXG4gICAgcmV0dXJuIHRoaXMuZmlsdGVyMUxpc3RTdWJqZWN0LmdldFZhbHVlKCkuZmlsdGVyKChpdGVtOiBhbnkpID0+IHtcclxuICAgICAgcmV0dXJuIGl0ZW0uY29kZUF0dHJpYnV0ZUNvbnRleHQgPT09IGNvZGVBdHRyaWJ1dGVDb250ZXh0ICYmIGl0ZW0uY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dCA9PT0gY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dDtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZ2V0RmlsdGVyMkZvcihjb2RlQXR0cmlidXRlQ29udGV4dDogc3RyaW5nLCBjb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0OiBzdHJpbmcsIGlkRmlsdGVyMTogbnVtYmVyKTogYW55W10ge1xyXG4gICAgcmV0dXJuIHRoaXMuZmlsdGVyMkxpc3RTdWJqZWN0LmdldFZhbHVlKCkuZmlsdGVyKChpdGVtOiBhbnkpID0+IHtcclxuICAgICAgcmV0dXJuIGl0ZW0uY29kZUF0dHJpYnV0ZUNvbnRleHQgPT09IGNvZGVBdHRyaWJ1dGVDb250ZXh0XHJcbiAgICAgICAgJiYgaXRlbS5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0ID09PSBjb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0XHJcbiAgICAgICAgJiYgaXRlbS5pZEZpbHRlcjEgPT09IGlkRmlsdGVyMTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVHJhY2sgbmV3IGlkQXR0cmlidXRlVmFsdWVzIHZpYSBhIG5lZ2F0aXZlIG51bWJlciBmb3IgaW50ZXJuYWwgdHJhY2tpbmcuICBSZW1vdmUgdGhpcyBmYWtlIGlkIHByaW9yIHRvIHBvc3QuXHJcbiAgICpcclxuICAgKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gICAqL1xyXG4gIGdldFVuaXF1ZUlkKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gLS10aGlzLnVuaXF1ZUlkO1xyXG4gIH1cclxufVxyXG4iXX0=
1
+ import { Inject, Injectable, InjectionToken, isDevMode } from "@angular/core";
2
+ import { HttpClient, HttpParams } from "@angular/common/http";
3
+ import { Router } from "@angular/router";
4
+ import { BehaviorSubject, forkJoin, Subject } from "rxjs";
5
+ import { DictionaryService } from "@huntsman-cancer-institute/dictionary-service";
6
+ import { PreEvalDTO } from "../model/pre-eval.dto";
7
+ import { DictionaryEntriesDTO } from "../model/dictionary-entries.dto";
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@huntsman-cancer-institute/dictionary-service";
10
+ import * as i2 from "@angular/common/http";
11
+ import * as i3 from "@angular/router";
12
+ export let ATTRIBUTE_ENDPOINT = new InjectionToken("attributeEndpoint");
13
+ export const BOOLEAN = ["N", "Y"];
14
+ export const EXTENDED_BOOLEAN = ["N", "Y", "U"];
15
+ /**
16
+ * A service created for each attribute configuration instance. This makes calls to the backend to get the configuration
17
+ * and value set. It also stores common data that different attributes might need (e.g. a list of attribute choices).
18
+ */
19
+ export class AttributeService {
20
+ constructor(dictionaryService, http, router, attributeEndpoint) {
21
+ this.dictionaryService = dictionaryService;
22
+ this.http = http;
23
+ this.router = router;
24
+ this.attributeEndpoint = attributeEndpoint;
25
+ this.attributeContextLoadingSubject = new BehaviorSubject(false);
26
+ this.attributeContextListSubject = new BehaviorSubject(undefined);
27
+ this.attributeSecurityContextListSubject = new BehaviorSubject(undefined);
28
+ this.filter1ListSubject = new BehaviorSubject(undefined);
29
+ this.filter2ListSubject = new BehaviorSubject(undefined);
30
+ this.dictionaryListSubject = new BehaviorSubject(undefined);
31
+ this.postConfigurationSubject = new Subject();
32
+ this.attributeConfigurationDimensionSubject = new BehaviorSubject(undefined);
33
+ this.attributeConfigurationListSubject = new BehaviorSubject(undefined);
34
+ this.attributeConfigurationListLoadingSubject = new BehaviorSubject(false);
35
+ this.attributeConfigurationDTOSubject = new BehaviorSubject(undefined);
36
+ this.attributeConfigurationSubject = new BehaviorSubject(undefined);
37
+ this.attributeValueSetSubject = new BehaviorSubject(undefined);
38
+ this.attributeValuePushedSubject = new Subject();
39
+ this.loadingSubject = new BehaviorSubject(false);
40
+ this.attributeMap = new Map();
41
+ this.containerUpdated = new Subject();
42
+ this.gridRowSaved = new Subject();
43
+ this.gridRowDeleted = new Subject();
44
+ this.dirty = new BehaviorSubject(false);
45
+ this.updatedAttributeValues = [];
46
+ this.slicedAttributeValues = [];
47
+ this.uniqueId = 0;
48
+ if (isDevMode()) {
49
+ console.debug("Created New AttributeService");
50
+ }
51
+ }
52
+ setBoundData(boundData) {
53
+ this.boundData = boundData;
54
+ if (this.attributeValueSetSubject.getValue()) {
55
+ this.notifyAttributes();
56
+ }
57
+ }
58
+ getAttributeValueCountByAttribute(idAttribute) {
59
+ return this.http.get(this.attributeEndpoint + "attribute-value-count", { params: new HttpParams().set("idAttribute", idAttribute.toString()) });
60
+ }
61
+ getAttributeValueCountByContainer(idAttributeContainer) {
62
+ return this.http.get(this.attributeEndpoint + "attribute-value-count", { params: new HttpParams().set("idAttributeContainer", idAttributeContainer.toString()) });
63
+ }
64
+ getDictionaryValueCount(idAttributeDictionary) {
65
+ return this.http.get(this.attributeEndpoint + "attribute-dictionary-count", { params: new HttpParams().set("idAttributeDictionary", idAttributeDictionary.toString()) });
66
+ }
67
+ fetchAttributeContext() {
68
+ this.attributeContextLoadingSubject.next(true);
69
+ forkJoin([
70
+ this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.AttributeSecurityContext"),
71
+ this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.AttributeContext"),
72
+ this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.Filter1"),
73
+ this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.Filter2"),
74
+ this.dictionaryService.getDictionaryEntries("hci.ri.attr.model.AttributeDictionary")
75
+ ]).subscribe((responses) => {
76
+ this.dictionaryListSubject.next(responses[4]);
77
+ this.filter1ListSubject.next(responses[2]);
78
+ this.filter2ListSubject.next(responses[3]);
79
+ this.attributeContextListSubject.next(responses[1]);
80
+ responses[0].sort(this.sortAttributeSecurityContextList);
81
+ this.attributeSecurityContextListSubject.next(responses[0]);
82
+ this.attributeContextLoadingSubject.next(false);
83
+ });
84
+ }
85
+ //Gets the dictionary entries from the map (so we don't load over and over and over for the same dictionary)
86
+ getDictionaryEntries(attribute, values, groupAttributeRowId, referencedAttributeValue) {
87
+ let bs = new Subject();
88
+ //Handle XPATH
89
+ if (attribute.attributeDictionary.xpath) {
90
+ let entriesDTO = new DictionaryEntriesDTO();
91
+ let xpath = attribute.attributeDictionary.xpath;
92
+ //Filtered by another dictionary? Parse to get array of all dictionary class names needed
93
+ let dictClasses = [];
94
+ let pos = 0;
95
+ while (xpath.indexOf("/Dictionaries/Dictionary", pos) >= 0) {
96
+ let start = xpath.indexOf("/Dictionaries/Dictionary", pos);
97
+ start = xpath.indexOf("'", start);
98
+ let end = xpath.indexOf("'", start + 1);
99
+ dictClasses.push(attribute.attributeDictionary.xpath.substring(start + 1, end));
100
+ pos = end;
101
+ }
102
+ //Potentially load multiple dictionaries
103
+ let forkCalls = [];
104
+ for (let className of dictClasses) {
105
+ forkCalls.push(this.dictionaryService.getDictionaryEntriesAsXML(className));
106
+ }
107
+ //Deal with the results together
108
+ forkJoin(forkCalls).subscribe((responses) => {
109
+ //We're only going to do xpath on the xml for the first dictionary
110
+ const parser = new DOMParser();
111
+ let doc = parser.parseFromString(responses[0], "application/xml");
112
+ //Have to evaluate sub-expression. This doesn't actually support expressions like [@x = (/xpath-sub-expression)]
113
+ let secondaryXml = undefined;
114
+ if (responses.length > 1) {
115
+ secondaryXml = responses[1];
116
+ }
117
+ //Pre-evaluate and simplify XPATH
118
+ let dto = this.preEvaluateXpath(attribute.attributeDictionary.xpath, secondaryXml, groupAttributeRowId, referencedAttributeValue);
119
+ //Evaluate XPATH expression
120
+ let entries = [];
121
+ entriesDTO.entriesIncludeSelectedValue = false;
122
+ try {
123
+ let xPathResult = document.evaluate(dto.expression, doc, null, XPathResult.ANY_TYPE, null);
124
+ //Iterate xpath results (nodes)
125
+ var node = null;
126
+ while (node = xPathResult.iterateNext()) {
127
+ let entry = this.getJsonEntryFromNode(node);
128
+ entries.push(entry);
129
+ }
130
+ }
131
+ catch (e) {
132
+ // No matching entries here.
133
+ }
134
+ //What about dictionary entries where isActive='N', but the id was used in a previously saved value?
135
+ //We add that value to the dropdown, in that case, so it can be selected
136
+ //ReferencedAttributeValue only gets passed in when the filter attribute changes. In that scenario we do not want to add the old value to the list
137
+ if (attribute.isMultiValue !== "Y") {
138
+ for (let av of values) {
139
+ let present = false;
140
+ if (av && !referencedAttributeValue) {
141
+ for (var i = entries.length - 1; i >= 0; i--) {
142
+ if (entries[i].value === av.valueIdDictionary) {
143
+ present = true;
144
+ break;
145
+ }
146
+ }
147
+ //If the currently saved value is not in the list, add it.
148
+ if (!present) {
149
+ let xpath = "/Dictionaries/Dictionary[@className='" + attribute.attributeDictionary.className + "']/DictionaryEntry[@value='" + av.valueIdDictionary + "']";
150
+ //The entry was probably already loaded, but excluded by the xpath. We can use that.
151
+ let node = document.evaluate(xpath, doc, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
152
+ if (node) {
153
+ entries.push(this.getJsonEntryFromNode(node));
154
+ entriesDTO.entriesIncludeSelectedValue = true;
155
+ }
156
+ }
157
+ }
158
+ }
159
+ }
160
+ //Set the behavior subject with the filtered values for the dictionary
161
+ entriesDTO.entries = entries;
162
+ entriesDTO.referencedAttribute = dto.referencedAttribute;
163
+ bs.next(entriesDTO);
164
+ });
165
+ }
166
+ //Non-xpath
167
+ else {
168
+ //DictionayService just used http get, so should not need to unsubscribe, since http does that
169
+ this.dictionaryService.getDictionaryDropdownEntries(attribute.attributeDictionary.className).subscribe((entries) => {
170
+ //Make value fields
171
+ for (var i = entries.length - 1; i >= 0; i--) {
172
+ entries[i].value = entries[i].id.toString();
173
+ }
174
+ let entriesDTO = new DictionaryEntriesDTO();
175
+ entriesDTO.entries = entries;
176
+ entriesDTO.entriesIncludeSelectedValue = true; //A bit of an assumption, but if it isn't filtered, it had better include all the values!
177
+ bs.next(entriesDTO);
178
+ });
179
+ }
180
+ return bs;
181
+ }
182
+ getJsonEntryFromNode(node) {
183
+ //Create JSON objects from the nodes
184
+ let entry = {};
185
+ for (var i = node.attributes.length - 1; i >= 0; i--) {
186
+ entry[node.attributes[i].name] = node.attributes[i].value;
187
+ }
188
+ return entry;
189
+ }
190
+ preEvaluateXpath(xpath, secondaryXml, groupAttributeRowId, referencedAttributeValue) {
191
+ let dto = new PreEvalDTO();
192
+ //SecurityAdvisor/@codeCancerGroup
193
+ while (xpath.indexOf("/SecurityAdvisor/@codeCancerGroup") >= 0) {
194
+ xpath = xpath.replace("/SecurityAdvisor/@codeCancerGroup", "'" + this.getAttributeConfigurationSubject().value.codeAttributeSecurityContext + "'");
195
+ }
196
+ //Replace some of the context parameters ${x.value} - This is more Altio specific stuff that was used in CCR
197
+ let paramPos = xpath.search("\\${[A-Za-z0-9_]+\\.value}");
198
+ while (paramPos >= 0) {
199
+ let prefix = xpath.substring(0, paramPos);
200
+ let varName = xpath.substring(paramPos + 2, xpath.indexOf(".", paramPos));
201
+ let suffix = xpath.substring(xpath.indexOf("}", paramPos) + 1);
202
+ var av;
203
+ //If there IS a referencedAttributeValue, we can use the value directly. Otherwise we try to find it in the AVS
204
+ if (!referencedAttributeValue) {
205
+ //Find the attribute, matching the varName.
206
+ //Do this first, so we get a reference to the related attribute, regardless of whether there is already a value
207
+ //Iterate attributes to find one that matches the value
208
+ this.attributeMap.forEach((attribute) => {
209
+ //Attributes that match the name
210
+ if (attribute.attributeName === varName) {
211
+ dto.referencedAttribute = attribute;
212
+ return;
213
+ }
214
+ //If this is a grid, look for attributes in the row
215
+ if (attribute.attributes) {
216
+ for (let gridColumnAttribute of attribute.attributes) {
217
+ //If the name matches AND the value in the AVS was part of the SAME ROW we are evaluating XPATH for, we can use the value for evaluation
218
+ if (gridColumnAttribute.attributeName === varName) {
219
+ dto.referencedAttribute = gridColumnAttribute;
220
+ return;
221
+ }
222
+ }
223
+ }
224
+ });
225
+ let avs = this.attributeValueSetSubject.getValue();
226
+ //If we found the attribute and have values...
227
+ if (dto.referencedAttribute && avs) {
228
+ //Look through all the values to find the one for the referenced attribute (and SAME grid row if in a grid row)
229
+ av = avs.attributeValues.find((av) => {
230
+ //If this is an AV for a grid row, it must be for the same grid row we are looking for
231
+ if (typeof av.groupAttributeRowId !== 'undefined' && typeof groupAttributeRowId !== 'undefined' && av.groupAttributeRowId !== groupAttributeRowId) {
232
+ return false;
233
+ }
234
+ //If we looked up the attribute matching the value by id AND the name of the attribute is the one we ar looking for from the XPATH, we can use it for evaluation
235
+ //Found an AttributeValue that the dictionary is filtered by
236
+ if (dto.referencedAttribute.idAttribute === av.idAttribute) {
237
+ return true;
238
+ }
239
+ else {
240
+ return false;
241
+ }
242
+ });
243
+ }
244
+ }
245
+ //Use the referencedAttributeValue if provided (this happens when already known, during changes to the referenced attribute)
246
+ if (referencedAttributeValue) {
247
+ xpath = prefix + "'" + referencedAttributeValue.value + "'" + suffix;
248
+ }
249
+ //Found the AttributeValue for the attribute that the dictionary is filtered by
250
+ else if (av) {
251
+ xpath = prefix + "'" + av.value + "'" + suffix;
252
+ }
253
+ //Didn't find an attribute for varName
254
+ else {
255
+ //Maybe the varName is from elsewhere in the app (non-COD), and provided in boundData
256
+ if (this.boundData && this.boundData[varName]) {
257
+ xpath = prefix + "'" + this.boundData[varName] + "'" + suffix;
258
+ }
259
+ //Nothing matches. Change to empty string. Will probably result in NO entries, which would be correct.
260
+ else {
261
+ xpath = prefix + "''" + suffix;
262
+ }
263
+ }
264
+ paramPos = xpath.search("\\${[A-Za-z0-9_]+\\.value}");
265
+ }
266
+ //Have to evaluate sub-expression. This handles expressions like [@x = (/xpath-sub-expression)]
267
+ let inExpressionPos = xpath.search("\\[@[A-Za-z0-9_]+\\s*=\\s*\\(");
268
+ if (inExpressionPos > 0 && secondaryXml) {
269
+ let prefix = xpath.substring(0, inExpressionPos + 1);
270
+ let expressionEnd = xpath.indexOf(")", inExpressionPos);
271
+ let variable = xpath.substring(inExpressionPos + 1, xpath.indexOf("=", inExpressionPos));
272
+ let subExpression = xpath.substring(xpath.indexOf("(", inExpressionPos) + 1, expressionEnd);
273
+ let suffix = xpath.substring(expressionEnd + 1);
274
+ xpath = prefix;
275
+ //Evaluate XPATH expression
276
+ const parser = new DOMParser();
277
+ let doc = parser.parseFromString(secondaryXml, "application/xml");
278
+ let xPathResult = document.evaluate(subExpression, doc, null, XPathResult.ANY_TYPE, null);
279
+ //Iterate xpath results (nodes)
280
+ var node = xPathResult.iterateNext();
281
+ while (node) {
282
+ xpath = xpath + variable + "='" + node.nodeValue + "'";
283
+ node = xPathResult.iterateNext();
284
+ if (node) {
285
+ xpath = xpath + " or ";
286
+ }
287
+ }
288
+ xpath = xpath + suffix;
289
+ }
290
+ dto.expression = xpath;
291
+ return dto;
292
+ }
293
+ sortAttributeSecurityContextList(a, b) {
294
+ return a.description.toLowerCase().localeCompare(b.description.toLowerCase());
295
+ }
296
+ fetchAttributeConfigurationList(codeAttributeSecurityContext) {
297
+ if (isDevMode()) {
298
+ console.debug("fetchAttributeConfigurationList: " + codeAttributeSecurityContext);
299
+ }
300
+ this.attributeConfigurationListLoadingSubject.next(true);
301
+ let url = this.attributeEndpoint + "configurations";
302
+ let params = new HttpParams();
303
+ if (codeAttributeSecurityContext) {
304
+ params = params.set("codeAttributeSecurityContext", codeAttributeSecurityContext);
305
+ }
306
+ this.http.get(url, { params: params }).subscribe((configurationList) => {
307
+ this.attributeConfigurationListLoadingSubject.next(false);
308
+ let dtos = [];
309
+ for (let cfg of configurationList) {
310
+ let dto = this.getAttributeConfigurationDTO(cfg);
311
+ if (dto) {
312
+ dtos.push(dto);
313
+ }
314
+ }
315
+ dtos.sort(this.sortAttributeConfigurationList);
316
+ this.attributeConfigurationListSubject.next(dtos);
317
+ });
318
+ }
319
+ sortAttributeConfigurationList(a, b) {
320
+ const displaya = a.codeAttributeSecurityContextDisplay
321
+ + a.extensionDescription
322
+ + (a.filter1Display || "")
323
+ + (a.filter2Display || "");
324
+ const displayb = b.codeAttributeSecurityContextDisplay
325
+ + b.extensionDescription
326
+ + (b.filter1Display || "")
327
+ + (b.filter2Display || "");
328
+ return displaya.toLowerCase().localeCompare(displayb.toLowerCase());
329
+ }
330
+ //Used by cod-editor
331
+ clear() {
332
+ this.idAttributeConfiguration = undefined;
333
+ this.idFilter1 = undefined;
334
+ this.idFilter2 = undefined;
335
+ this.attributeConfigurationDTOSubject.next(undefined);
336
+ this.attributeConfigurationSubject.next(undefined);
337
+ }
338
+ createAttributeConfiguration(attributeConfiguration) {
339
+ attributeConfiguration.idAttributeConfiguration = undefined;
340
+ this.http.post(this.attributeEndpoint + "configurations", attributeConfiguration).subscribe((attributeConfiguration) => {
341
+ this.idAttributeConfiguration = attributeConfiguration.idAttributeConfiguration;
342
+ this.postConfigurationSubject.next(true);
343
+ this.attributeConfigurationSubject.next(attributeConfiguration);
344
+ this.router.navigateByUrl("/editor/attribute-configuration/" + attributeConfiguration.idAttributeConfiguration);
345
+ });
346
+ }
347
+ setAttributeConfigurationById(idAttributeConfiguration, idAttributeValueSet, idParentObject) {
348
+ if (idAttributeConfiguration !== -1) {
349
+ this.newAttributeConfiguration = undefined;
350
+ }
351
+ //Only load if the AttributeConfiguration has changed
352
+ if (this.idAttributeConfiguration !== idAttributeConfiguration) {
353
+ //Clear ASAP
354
+ this.idAttributeConfiguration = idAttributeConfiguration;
355
+ this.idAttributeValueSet = idAttributeValueSet;
356
+ this.idFilter1 = undefined;
357
+ this.idFilter2 = undefined;
358
+ this.attributeMap.clear();
359
+ this.attributeConfigurationDTOSubject.next(undefined);
360
+ this.attributeConfigurationSubject.next(undefined);
361
+ this.fetchAttributeConfiguration(idAttributeValueSet, idParentObject);
362
+ }
363
+ //Or load the AttributeValueSet if that changed (possible to switch from one event to another of the same type, for example
364
+ //The AttributeConfiguration must also have finished loading and not already working on loading the values
365
+ else if (this.idAttributeValueSet !== idAttributeValueSet && this.attributeConfigurationSubject.getValue()) {
366
+ this.setAttributeValueSet(idAttributeValueSet, idParentObject);
367
+ }
368
+ }
369
+ /**
370
+ * Sets the attribute configuration identifiers to be used by this service. This prompts a new configuration
371
+ * request to be made.
372
+ *
373
+ * @param {number} idFilter1
374
+ * @param {number} idFilter2
375
+ */
376
+ /* This is commented out for now because it is both unimplemented and incomplete (loading a configuration
377
+ * filter would really also require the attribute context and attributesecurity context plus a service on
378
+ * the back end that actually does this work. For now, only loading by idAttributeConfiguration
379
+ *
380
+ setAttributeConfigurationByFilter(idFilter1: number, idFilter2?: number): void {
381
+ if (isDevMode()) {
382
+ console.debug("setAttributeConfigurationByFilter: " + idFilter1 + " " + idFilter2);
383
+ }
384
+
385
+ this.newAttributeConfiguration = undefined;
386
+ //this.idAttributeConfiguration = undefined;
387
+ this.idFilter1 = idFilter1;
388
+ this.idFilter2 = idFilter2;
389
+
390
+ this.fetchAttributeConfiguration();
391
+ }
392
+ */
393
+ /**
394
+ * Sets the id of the attribute value set. This will prompt a request to pull this from the backend.
395
+ *
396
+ * @param {number} idAttributeValueSet
397
+ */
398
+ setAttributeValueSet(idAttributeValueSet, idParentObject) {
399
+ //Only load the AttributeValueSet if it has been changed
400
+ if (this.idAttributeValueSet !== idAttributeValueSet) {
401
+ this.idAttributeValueSet = idAttributeValueSet;
402
+ this.fetchAttributeValueSet(idParentObject);
403
+ }
404
+ }
405
+ /**
406
+ * The request to download the attribute configuration.
407
+ */
408
+ fetchAttributeConfiguration(idAttributeValueSet, idParentObject) {
409
+ if (this.newAttributeConfiguration) {
410
+ this.attributeConfigurationDTOSubject.next(undefined);
411
+ this.attributeConfigurationSubject.next(this.newAttributeConfiguration);
412
+ return;
413
+ }
414
+ else if (this.idAttributeConfiguration === -1) {
415
+ this.attributeConfigurationDTOSubject.next(undefined);
416
+ this.attributeConfigurationSubject.next({
417
+ idAttributeConfiguration: -2
418
+ });
419
+ return;
420
+ }
421
+ this.loadingSubject.next(true);
422
+ let url;
423
+ if (this.idAttributeConfiguration && this.idAttributeConfiguration > -1) {
424
+ url = this.attributeEndpoint + "configurations/" + this.idAttributeConfiguration;
425
+ }
426
+ else {
427
+ //This is not fully implemented
428
+ //url = this.attributeEndpoint + "configurations/filter/" + this.idFilter1;
429
+ //if (this.idFilter2) {
430
+ //url += "/" + this.idFilter2;
431
+ //}
432
+ }
433
+ this.http.get(url).subscribe((attributeConfiguration) => {
434
+ this.setAttributeConfiguration(attributeConfiguration);
435
+ this.loadingSubject.next(false);
436
+ //Now load the attributeValueSet - This will always happen when a new configuration is loaded
437
+ this.idAttributeValueSet = undefined; //Force it to change in this scenario
438
+ this.setAttributeValueSet(idAttributeValueSet, idParentObject);
439
+ this.dirty.next(false);
440
+ }, (error) => {
441
+ console.error(error);
442
+ this.loadingSubject.next(false);
443
+ this.setAttributeConfiguration(undefined);
444
+ });
445
+ }
446
+ setAttributeConfiguration(attributeConfiguration) {
447
+ this.attributeMap.clear();
448
+ if (isDevMode()) {
449
+ console.debug("AttributeService.setAttributeConfiguration");
450
+ console.debug(attributeConfiguration);
451
+ }
452
+ if (attributeConfiguration) {
453
+ if (attributeConfiguration.baseWindowTemplate) {
454
+ this.getBaseWindowDimension(attributeConfiguration.baseWindowTemplate);
455
+ }
456
+ if (attributeConfiguration.attributeContainers) {
457
+ attributeConfiguration.attributeContainers.sort((a, b) => {
458
+ if (a.sortOrder < b.sortOrder) {
459
+ return -1;
460
+ }
461
+ else if (a.sortOrder > b.sortOrder) {
462
+ return 1;
463
+ }
464
+ else {
465
+ return 0;
466
+ }
467
+ });
468
+ }
469
+ for (let attributeContainer of attributeConfiguration.attributeContainers) {
470
+ /**
471
+ * First sort attributes using the y and x positioning. If using absolute position, the order doesn't matter,
472
+ * but if we want the absolute positioning to guide auto layout, then use this order.
473
+ */
474
+ attributeContainer.graphicalAttributes.sort((a, b) => {
475
+ if (a.tabOrder < b.tabOrder) {
476
+ return -1;
477
+ }
478
+ else if (a.tabOrder > b.tabOrder) {
479
+ return 1;
480
+ }
481
+ else {
482
+ return 0;
483
+ }
484
+ });
485
+ for (let attribute of attributeContainer.graphicalAttributes) {
486
+ this.attributeMap.set(attribute.idAttribute, attribute);
487
+ }
488
+ }
489
+ }
490
+ this.attributeConfigurationDTOSubject.next(this.getAttributeConfigurationDTO(attributeConfiguration));
491
+ this.attributeConfigurationSubject.next(attributeConfiguration);
492
+ }
493
+ /**
494
+ * The request to pull the attribute value set.
495
+ * Required the AttributeConfiguration to be pre-loaded
496
+ */
497
+ fetchAttributeValueSet(idParentObject) {
498
+ this.loadingSubject.next(true);
499
+ this.idParentObject = idParentObject;
500
+ let url = this.attributeEndpoint + "attribute-value-set/" + this.idAttributeValueSet;
501
+ let ac = this.attributeConfigurationSubject.getValue();
502
+ let queryParams = new HttpParams()
503
+ .set("codeAttributeSecurityContext", ac.codeAttributeSecurityContext)
504
+ .set("codeAttributeContext", ac.codeAttributeContext)
505
+ .set("idParentObject", (idParentObject) ? idParentObject.toString() : "");
506
+ //Clear ASAP
507
+ this.slicedAttributeValues = [];
508
+ this.updatedAttributeValues = [];
509
+ this.attributeValueSetSubject.next(undefined);
510
+ this.http.get(url, { params: queryParams }).subscribe((attributeValueSet) => {
511
+ //Initialize attributeValues if it does not exist
512
+ if (!attributeValueSet.attributeValues) {
513
+ attributeValueSet.attributeValues = [];
514
+ }
515
+ this.attributeValueSetSubject.next(attributeValueSet);
516
+ this.loadingSubject.next(false);
517
+ this.dirty.next(false);
518
+ }, (error) => {
519
+ console.error(error);
520
+ this.loadingSubject.next(false);
521
+ this.attributeValueSetSubject.next(undefined);
522
+ });
523
+ }
524
+ getBaseWindowDimension(baseWindowTemplate) {
525
+ this.http.get(this.attributeEndpoint + "base-window-dimension", { params: new HttpParams().set("baseWindowTemplate", baseWindowTemplate) })
526
+ .subscribe((dimension) => {
527
+ this.attributeConfigurationDimensionSubject.next(dimension);
528
+ });
529
+ }
530
+ /**
531
+ * Currently a simple notifier that the configuration or attribute value set has changed and components may need to be refreshed.
532
+ *
533
+ */
534
+ notifyAttributes() {
535
+ this.containerUpdated.next(true);
536
+ }
537
+ /**
538
+ * Post the attribute configuration after editing. Post the entire thing as it cascades down. The editor allows you
539
+ * to modify every container and only then save the entire configuration.
540
+ *
541
+ * @param {AttributeConfiguration} attributeConfiguration
542
+ */
543
+ postAttributeConfiguration(attributeConfiguration) {
544
+ let url = this.attributeEndpoint + "configurations/" + attributeConfiguration.idAttributeConfiguration;
545
+ this.loadingSubject.next(true);
546
+ this.setNegativeIdsToUndefined(attributeConfiguration);
547
+ this.http.post(url, attributeConfiguration).subscribe(() => {
548
+ // Prevent error in subsequent saves. See Metabuilder / MB-23
549
+ this.http.get(url).subscribe((attributeConfiguration) => {
550
+ if (isDevMode()) {
551
+ console.debug(attributeConfiguration);
552
+ }
553
+ this.postConfigurationSubject.next(true);
554
+ this.attributeConfigurationSubject.next(attributeConfiguration);
555
+ }, (error) => {
556
+ console.error(error);
557
+ }, () => {
558
+ this.loadingSubject.next(false);
559
+ });
560
+ }, (error) => {
561
+ console.error(error);
562
+ });
563
+ }
564
+ /**
565
+ * Put the attribute value set. When editing, attributes already post their updated values to this services under
566
+ * a separate array. What we do is merge in these updated or created values with the current attribute value set (avs).
567
+ * While doing this, set the id of the avs and nullify any negative ids.
568
+ */
569
+ updateAttributeValueSet() {
570
+ let url = this.attributeEndpoint + "attribute-value-set/";
571
+ let ac = this.attributeConfigurationSubject.getValue();
572
+ let queryParams = new HttpParams()
573
+ .set("codeAttributeSecurityContext", ac.codeAttributeSecurityContext)
574
+ .set("codeAttributeContext", ac.codeAttributeContext)
575
+ .set("idParentObject", (this.idParentObject) ? this.idParentObject.toString() : "");
576
+ let avs = Object.assign({}, this.attributeValueSetSubject.getValue());
577
+ for (let i = this.updatedAttributeValues.length - 1; i >= 0; i--) {
578
+ this.updatedAttributeValues[i].idAttributeValueSet = this.idAttributeValueSet;
579
+ if (this.updatedAttributeValues[i].idAttributeValue < 0) {
580
+ this.updatedAttributeValues[i].idAttributeValue = undefined;
581
+ }
582
+ let j = 0;
583
+ for (j = 0; j < avs.attributeValues.length; j++) {
584
+ if (this.updatedAttributeValues[i].idAttributeValue === avs.attributeValues[j].idAttributeValue) {
585
+ break;
586
+ }
587
+ }
588
+ if (j < avs.attributeValues.length) {
589
+ avs.attributeValues[j] = this.updatedAttributeValues[i];
590
+ this.updatedAttributeValues.splice(i, 1);
591
+ }
592
+ }
593
+ for (let i = 0; i < this.slicedAttributeValues.length; i++) {
594
+ let j = 0;
595
+ for (j = 0; j < avs.attributeValues.length; j++) {
596
+ if (this.slicedAttributeValues[i].idAttributeValue === avs.attributeValues[j].idAttributeValue) {
597
+ break;
598
+ }
599
+ }
600
+ if (j < avs.attributeValues.length) {
601
+ avs.attributeValues.splice(j, 1);
602
+ }
603
+ }
604
+ avs.attributeValues = avs.attributeValues.concat(this.updatedAttributeValues);
605
+ this.loadingSubject.next(true);
606
+ let resultSubject = new Subject();
607
+ this.http.put(url, avs, { params: queryParams }).subscribe((attributeValueSet) => {
608
+ if (isDevMode()) {
609
+ console.debug(attributeValueSet);
610
+ }
611
+ //Initialize attributeValues if it does not exist
612
+ if (!attributeValueSet.attributeValues) {
613
+ attributeValueSet.attributeValues = [];
614
+ }
615
+ this.slicedAttributeValues = [];
616
+ this.updatedAttributeValues = [];
617
+ this.attributeValueSetSubject.next(attributeValueSet);
618
+ this.loadingSubject.next(false);
619
+ this.dirty.next(false);
620
+ //Send the results to the observer (if any), then complete
621
+ resultSubject.next(attributeValueSet);
622
+ resultSubject.complete();
623
+ }, (error) => {
624
+ console.error(error);
625
+ this.loadingSubject.next(false);
626
+ resultSubject.error(error);
627
+ });
628
+ return resultSubject;
629
+ }
630
+ /**
631
+ * Get the attributeConfigurationSubject.
632
+ *
633
+ * @returns {BehaviorSubject<AttributeConfiguration>}
634
+ */
635
+ getAttributeConfigurationSubject() {
636
+ return this.attributeConfigurationSubject;
637
+ }
638
+ getDirtySubject() {
639
+ return this.dirty;
640
+ }
641
+ /**
642
+ * Get the attributeValueSetSubject;
643
+ *
644
+ * @returns {BehaviorSubject<AttributeValueSet>}
645
+ */
646
+ getAttributeValueSet() {
647
+ return this.attributeValueSetSubject;
648
+ }
649
+ /**
650
+ * Get the attributeValuePushedSubject;
651
+ *
652
+ * @returns {Subject<AttributeValue>}
653
+ */
654
+ getAttributeValuePushedSubject() {
655
+ return this.attributeValuePushedSubject;
656
+ }
657
+ /**
658
+ * Get all attribute values based upon the idAttribute.
659
+ *
660
+ * @param {number} idAttributes
661
+ * @returns {AttributeValue[]}
662
+ */
663
+ getAttributeValues(idAttribute, groupAttributeRowId) {
664
+ let attributeValues = [];
665
+ if (this.attributeValueSetSubject.getValue()) {
666
+ //Go through all the updated attribute values first (so we preserve across changing tabs, etc)
667
+ let i = 0;
668
+ for (i = 0; i < this.updatedAttributeValues.length; i++) {
669
+ if (this.updatedAttributeValues[i].idAttribute === idAttribute && (!groupAttributeRowId || groupAttributeRowId === this.updatedAttributeValues[i].groupAttributeRowId)) {
670
+ attributeValues.push(Object.assign({}, this.updatedAttributeValues[i]));
671
+ }
672
+ else if (this.updatedAttributeValues[i].idGroupAttribute === idAttribute && (!groupAttributeRowId || groupAttributeRowId === this.updatedAttributeValues[i].groupAttributeRowId)) {
673
+ attributeValues.push(Object.assign({}, this.updatedAttributeValues[i]));
674
+ }
675
+ }
676
+ //Go through all the regular attributes
677
+ for (let attributeValue of this.attributeValueSetSubject.getValue().attributeValues) {
678
+ //Regular attributes (normal and group, which get multiple)
679
+ if (attributeValue.idAttribute === idAttribute || attributeValue.idGroupAttribute === idAttribute) {
680
+ //If row id specified, only care about values for that row
681
+ if (typeof groupAttributeRowId === 'undefined' || attributeValue.groupAttributeRowId === groupAttributeRowId) {
682
+ //If not already added...
683
+ if (!attributeValues.find((existing) => existing.idAttributeValue === attributeValue.idAttributeValue)) {
684
+ //Don't want the original if it was removed (sliced)
685
+ if (!this.slicedAttributeValues.find((sav) => sav.idAttributeValue === attributeValue.idAttributeValue)) {
686
+ attributeValues.push(Object.assign({}, attributeValue));
687
+ }
688
+ }
689
+ }
690
+ }
691
+ }
692
+ }
693
+ return attributeValues;
694
+ }
695
+ /**
696
+ * Get all child attributes of the idAttribute. Most likely for attributes that define columns of a grid.
697
+ *
698
+ * @param {number} idAttribute
699
+ * @returns {Attribute[]}
700
+ */
701
+ getGroupAttributes(idAttribute) {
702
+ let attributes = [];
703
+ this.attributeMap.forEach((attribute) => {
704
+ if (attribute.idGroupAttribute === idAttribute) {
705
+ attributes.push(attribute);
706
+ }
707
+ });
708
+ return attributes;
709
+ }
710
+ /**
711
+ * Set the width which is a requirement of the absolute positioning.
712
+ *
713
+ * @param {number} width
714
+ */
715
+ setWidth(width) {
716
+ this.width = width;
717
+ }
718
+ /**
719
+ * Get the width.
720
+ *
721
+ * @returns {number}
722
+ */
723
+ getWidth() {
724
+ return this.width;
725
+ }
726
+ /**
727
+ * Get the array of attribute choices for the idAttribute.
728
+ *
729
+ * @param {number} idAttribute
730
+ * @returns {AttributeChoice[]}
731
+ */
732
+ getAttributeChoices(idAttribute) {
733
+ return this.attributeMap.get(idAttribute).attributeChoices;
734
+ }
735
+ getLoadingSubject() {
736
+ return this.loadingSubject;
737
+ }
738
+ /**
739
+ * Get the containerUpdated subject.
740
+ *
741
+ * @returns {Subject<number>}
742
+ */
743
+ getContainerUpdated() {
744
+ return this.containerUpdated;
745
+ }
746
+ getGridRowSavedSubject() {
747
+ return this.gridRowSaved;
748
+ }
749
+ getGridRowDeletedSubject() {
750
+ return this.gridRowDeleted;
751
+ }
752
+ /**
753
+ * Clear the updated and deleted attribute value arrays.
754
+ *
755
+ */
756
+ clearUpdatedAttributeValues() {
757
+ this.slicedAttributeValues = [];
758
+ this.updatedAttributeValues = [];
759
+ this.dirty.next(false);
760
+ this.notifyAttributes();
761
+ }
762
+ /**
763
+ * Clear the updated and deleted grid row attributes for the specified grid row
764
+ *
765
+ */
766
+ clearUpdatedGridRowAttributeValues(groupAttributeRowId) {
767
+ let remainingAttributes = [];
768
+ this.slicedAttributeValues = this.slicedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
769
+ this.updatedAttributeValues = this.updatedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
770
+ //Shouldn't be a need to change dirty or notify attributes
771
+ }
772
+ saveGridRowAttributeValues(idGroupAttribute, groupAttributeRowId) {
773
+ let rowValues = this.updatedAttributeValues.filter((av) => av.groupAttributeRowId === groupAttributeRowId);
774
+ for (let j = 0; j < rowValues.length; j++) {
775
+ //set the idAttributeValueSet if necessary
776
+ if (!rowValues[j].idAttributeValueSet) {
777
+ rowValues[j].idAttributeValueSet = this.idAttributeValueSet;
778
+ }
779
+ //remove all negative ids (new values)
780
+ if (rowValues[j].idAttributeValue < 0) {
781
+ rowValues[j].idAttributeValue = undefined;
782
+ }
783
+ }
784
+ //For multi values that were sliced (de-selected) we're going to find them and null out the value, instead of removing.
785
+ //That means they actaully need to be added to the rowValues
786
+ //Removed multi values within an existing row
787
+ let removedValues = this.slicedAttributeValues.filter((av) => av.groupAttributeRowId === groupAttributeRowId);
788
+ for (let i = 0; i < removedValues.length; i++) {
789
+ removedValues[i].valueAttributeChoice = undefined;
790
+ removedValues[i].valueIdDictionary = undefined;
791
+ rowValues.push(removedValues[i]);
792
+ }
793
+ let avgr = {
794
+ idAttributeValueSet: this.idAttributeValueSet,
795
+ idGroupAttribute: idGroupAttribute,
796
+ groupAttributeRowId: groupAttributeRowId,
797
+ attributeValues: rowValues
798
+ };
799
+ let url = this.attributeEndpoint + "attribute-value-grid-row/";
800
+ let ac = this.attributeConfigurationSubject.getValue();
801
+ let queryParams = new HttpParams()
802
+ .set("codeAttributeSecurityContext", ac.codeAttributeSecurityContext)
803
+ .set("codeAttributeContext", ac.codeAttributeContext)
804
+ .set("idParentObject", (this.idParentObject) ? this.idParentObject.toString() : "");
805
+ this.loadingSubject.next(true);
806
+ //Save new row
807
+ if (groupAttributeRowId < 0) {
808
+ this.http.post(url, avgr, { params: queryParams }).subscribe((attributeValueGridRow) => {
809
+ //Add the grid row to the original attribute values
810
+ let avs = this.attributeValueSetSubject.getValue();
811
+ for (let i = 0; i < attributeValueGridRow.attributeValues.length; i++) {
812
+ avs.attributeValues.push(attributeValueGridRow.attributeValues[i]);
813
+ }
814
+ //Remove the updated and sliced values for the grid row, now (these are the old ones with the negative rowid)
815
+ this.slicedAttributeValues = this.slicedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
816
+ this.updatedAttributeValues = this.updatedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
817
+ this.attributeValueSetSubject.next(avs);
818
+ this.gridRowSaved.next(attributeValueGridRow);
819
+ this.loadingSubject.next(false);
820
+ }, (error) => {
821
+ console.error(error);
822
+ this.loadingSubject.next(false);
823
+ });
824
+ }
825
+ //Update existing row
826
+ else {
827
+ this.http.put(url, avgr, { params: queryParams }).subscribe((attributeValueGridRow) => {
828
+ //Add the grid row to the original attribute values
829
+ let avs = this.attributeValueSetSubject.getValue();
830
+ //Remove all old values for row
831
+ let index = avs.attributeValues.findIndex((av) => av.groupAttributeRowId === groupAttributeRowId);
832
+ while (index > 0) {
833
+ //Remove value
834
+ avs.attributeValues.splice(index, 1);
835
+ //Find the next one
836
+ index = avs.attributeValues.findIndex((av) => av.groupAttributeRowId === groupAttributeRowId);
837
+ }
838
+ //Add all the current values
839
+ for (let i = 0; i < attributeValueGridRow.attributeValues.length; i++) {
840
+ avs.attributeValues.push(attributeValueGridRow.attributeValues[i]);
841
+ }
842
+ //Remove the sliced and updated values for the grid row
843
+ this.slicedAttributeValues = this.slicedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
844
+ this.updatedAttributeValues = this.updatedAttributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
845
+ this.attributeValueSetSubject.next(avs);
846
+ this.gridRowSaved.next(attributeValueGridRow);
847
+ this.loadingSubject.next(false);
848
+ }, (error) => {
849
+ console.error(error);
850
+ this.loadingSubject.next(false);
851
+ });
852
+ }
853
+ }
854
+ deleteGridRowAttributeValues(idGroupAttribute, groupAttributeRowId) {
855
+ let url = this.attributeEndpoint + "attribute-value-grid-row/";
856
+ let ac = this.attributeConfigurationSubject.getValue();
857
+ let queryParams = new HttpParams()
858
+ .set("codeAttributeSecurityContext", ac.codeAttributeSecurityContext)
859
+ .set("codeAttributeContext", ac.codeAttributeContext)
860
+ .set("idParentObject", (this.idParentObject) ? this.idParentObject.toString() : "");
861
+ let avgr = {
862
+ idAttributeValueSet: this.idAttributeValueSet,
863
+ idGroupAttribute: idGroupAttribute,
864
+ groupAttributeRowId: groupAttributeRowId,
865
+ attributeValues: []
866
+ };
867
+ this.loadingSubject.next(true);
868
+ this.http.request('delete', url, { body: avgr, params: queryParams }).subscribe(() => {
869
+ //Remove the grid row from the original attribute values
870
+ let avs = this.attributeValueSetSubject.getValue();
871
+ avs.attributeValues = avs.attributeValues.filter((av) => av.groupAttributeRowId !== groupAttributeRowId);
872
+ this.attributeValueSetSubject.next(avs);
873
+ this.gridRowDeleted.next(avgr);
874
+ this.loadingSubject.next(false);
875
+ }, (error) => {
876
+ console.error(error);
877
+ this.loadingSubject.next(false);
878
+ });
879
+ }
880
+ /**
881
+ * Push an attribute to the attribute map.
882
+ *
883
+ * @param {Attribute} attribute
884
+ */
885
+ pushAttribute(attribute) {
886
+ this.attributeMap.set(attribute.idAttribute, attribute);
887
+ }
888
+ pushAttributeValueMultiChoice(attributeValue) {
889
+ //Remove from sliced if present
890
+ let i = 0;
891
+ for (i = 0; i < this.slicedAttributeValues.length; i++) {
892
+ if (this.slicedAttributeValues[i].idAttribute === attributeValue.idAttribute && this.slicedAttributeValues[i].valueAttributeChoice.idAttributeChoice === attributeValue.valueAttributeChoice.idAttributeChoice) {
893
+ break;
894
+ }
895
+ }
896
+ //Remove from sliced attribute values (no longer removing)
897
+ if (i < this.slicedAttributeValues.length) {
898
+ this.slicedAttributeValues.splice(i, 1);
899
+ }
900
+ //Otherwise push the value, so it will be saved
901
+ else {
902
+ this.pushAttributeValue(attributeValue);
903
+ }
904
+ }
905
+ pushAttributeValueMultiDict(attributeValue) {
906
+ //Remove from sliced if present
907
+ let i = 0;
908
+ for (i = 0; i < this.slicedAttributeValues.length; i++) {
909
+ if (this.slicedAttributeValues[i].idAttribute === attributeValue.idAttribute && this.slicedAttributeValues[i].valueIdDictionary === attributeValue.valueIdDictionary) {
910
+ break;
911
+ }
912
+ }
913
+ //Remove from sliced attribute values (no longer removing)
914
+ if (i < this.slicedAttributeValues.length) {
915
+ this.slicedAttributeValues.splice(i, 1);
916
+ }
917
+ //Otherwise push the value, so it will be saved
918
+ else {
919
+ this.pushAttributeValue(attributeValue);
920
+ }
921
+ }
922
+ /**
923
+ * Push a new or updated attribute value. The current one is just removed and the new one appended to the array.
924
+ *
925
+ * @param {AttributeValue} attributeValue
926
+ */
927
+ pushAttributeValue(attributeValue) {
928
+ if (isDevMode()) {
929
+ console.debug("pushAttributeValue");
930
+ console.debug(attributeValue);
931
+ }
932
+ let i = 0;
933
+ for (i = 0; i < this.updatedAttributeValues.length; i++) {
934
+ if (this.updatedAttributeValues[i].idAttributeValue === attributeValue.idAttributeValue) {
935
+ break;
936
+ }
937
+ }
938
+ if (i < this.updatedAttributeValues.length) {
939
+ this.updatedAttributeValues.splice(i, 1);
940
+ }
941
+ this.updatedAttributeValues.push(attributeValue);
942
+ this.attributeValuePushedSubject.next(attributeValue);
943
+ //Only setting dirty for non grid-rows (those are saved immediately)
944
+ if (!attributeValue.idGroupAttribute) {
945
+ this.dirty.next(true);
946
+ }
947
+ }
948
+ /**
949
+ * For pushing multiple attribute values at once. This would typically be for a multi choice.
950
+ *
951
+ * @param {Attribute} attribute
952
+ * @param {AttributeValue[]} attributeValues
953
+ */
954
+ pushAttributeValues(attribute, attributeValues) {
955
+ if (isDevMode()) {
956
+ console.debug("pushAttributeValues");
957
+ console.debug(attributeValues);
958
+ }
959
+ for (let i = 0; i < attributeValues.length; i++) {
960
+ let j = 0;
961
+ for (j = 0; j < this.updatedAttributeValues.length; j++) {
962
+ if (this.updatedAttributeValues[j].idAttribute !== attribute.idAttribute) {
963
+ continue;
964
+ }
965
+ else if (this.updatedAttributeValues[j].idAttributeValue === attributeValues[i].idAttributeValue) {
966
+ break;
967
+ }
968
+ }
969
+ if (j < this.updatedAttributeValues.length) {
970
+ this.updatedAttributeValues[j] = attributeValues[i];
971
+ }
972
+ else {
973
+ this.updatedAttributeValues.push(attributeValues[i]);
974
+ }
975
+ }
976
+ if (isDevMode()) {
977
+ console.debug(this.updatedAttributeValues);
978
+ }
979
+ //Only setting dirty for non grid-rows (those are saved immediately)
980
+ if (!attribute.idGroupAttribute) {
981
+ this.dirty.next(true);
982
+ }
983
+ }
984
+ /**
985
+ * Push a value in the case where an attribute value doesn't exist.
986
+ *
987
+ * @param {Attribute} attribute
988
+ * @param value
989
+ */
990
+ pushValue(attribute, value) {
991
+ let attributeValue = {
992
+ idAttribute: attribute.idAttribute,
993
+ idAttributeValueSet: this.idAttributeValueSet
994
+ };
995
+ if (attribute.codeAttributeDataType === "TXT") {
996
+ attributeValue.valueLongText = {
997
+ idLongText: undefined,
998
+ textData: value
999
+ };
1000
+ }
1001
+ this.updatedAttributeValues.push(attributeValue);
1002
+ this.dirty.next(true);
1003
+ }
1004
+ /**
1005
+ * Remove an attribute value. Typically in the case of a multi select where the unselected value is removed.
1006
+ *
1007
+ * @param {Attribute} attribute
1008
+ * @param {AttributeChoice} attributeChoice
1009
+ */
1010
+ spliceAttributeValueChoice(attribute, attributeChoice) {
1011
+ if (isDevMode()) {
1012
+ console.debug("sliceAttributeValue: " + attribute.idAttribute + ", " + attributeChoice.idAttributeChoice);
1013
+ }
1014
+ let i = 0;
1015
+ for (i = 0; i < this.updatedAttributeValues.length; i++) {
1016
+ if (this.updatedAttributeValues[i].idAttribute === attribute.idAttribute && this.updatedAttributeValues[i].valueAttributeChoice.idAttributeChoice === attributeChoice.idAttributeChoice) {
1017
+ break;
1018
+ }
1019
+ }
1020
+ //Remove from updated attribute values (not previously saved)
1021
+ if (i < this.updatedAttributeValues.length) {
1022
+ this.updatedAttributeValues.splice(i, 1);
1023
+ }
1024
+ //Add to sliced values (previously saved - need to remove)
1025
+ else {
1026
+ for (i = 0; i < this.attributeValueSetSubject.getValue().attributeValues.length; i++) {
1027
+ if (this.attributeValueSetSubject.getValue().attributeValues[i].idAttribute === attribute.idAttribute
1028
+ && this.attributeValueSetSubject.getValue().attributeValues[i].valueAttributeChoice.idAttributeChoice === attributeChoice.idAttributeChoice) {
1029
+ this.slicedAttributeValues.push(this.attributeValueSetSubject.getValue().attributeValues[i]);
1030
+ break;
1031
+ }
1032
+ }
1033
+ }
1034
+ //Only flagging dirty for non-grid rows (those are saved immediately)
1035
+ if (!attribute.idGroupAttribute) {
1036
+ this.dirty.next(true);
1037
+ }
1038
+ }
1039
+ /**
1040
+ * Remove an attribute value. Typically in the case of a multi select where the unselected value is removed.
1041
+ *
1042
+ * @param {Attribute} attribute
1043
+ * @param {AttributeChoice} attributeChoice
1044
+ */
1045
+ spliceAttributeValueDict(attribute, value) {
1046
+ if (isDevMode()) {
1047
+ console.debug("sliceAttributeValue: " + attribute.idAttribute + ", " + value);
1048
+ }
1049
+ let i = 0;
1050
+ for (i = 0; i < this.updatedAttributeValues.length; i++) {
1051
+ if (this.updatedAttributeValues[i].idAttribute === attribute.idAttribute && this.updatedAttributeValues[i].valueIdDictionary === value) {
1052
+ break;
1053
+ }
1054
+ }
1055
+ //Remove from updated attribute values (not previously saved)
1056
+ if (i < this.updatedAttributeValues.length) {
1057
+ this.updatedAttributeValues.splice(i, 1);
1058
+ }
1059
+ //Add to sliced values (previously saved - need to remove)
1060
+ else {
1061
+ for (i = 0; i < this.attributeValueSetSubject.getValue().attributeValues.length; i++) {
1062
+ if (this.attributeValueSetSubject.getValue().attributeValues[i].idAttribute === attribute.idAttribute
1063
+ && this.attributeValueSetSubject.getValue().attributeValues[i].valueIdDictionary === value) {
1064
+ this.slicedAttributeValues.push(this.attributeValueSetSubject.getValue().attributeValues[i]);
1065
+ break;
1066
+ }
1067
+ }
1068
+ }
1069
+ //Only flagging dirty for non-grid rows (those are saved immediately)
1070
+ if (!attribute.idGroupAttribute) {
1071
+ this.dirty.next(true);
1072
+ }
1073
+ }
1074
+ /**
1075
+ * Get the attribute based upon the idAttribute. This is from the map of attributes.
1076
+ *
1077
+ * @param {number} idAttribute
1078
+ * @returns {Attribute}
1079
+ */
1080
+ getAttribute(idAttribute) {
1081
+ return this.attributeMap.get(idAttribute);
1082
+ }
1083
+ /**
1084
+ * For the attribute configuration, set all of the negative ids to undefined prior to posting.
1085
+ *
1086
+ * @param {AttributeConfiguration} attributeConfiguration
1087
+ */
1088
+ setNegativeIdsToUndefined(attributeConfiguration) {
1089
+ if (attributeConfiguration.idAttributeConfiguration < 0) {
1090
+ attributeConfiguration.idAttributeConfiguration = undefined;
1091
+ }
1092
+ for (let attributeContainer of attributeConfiguration.attributeContainers) {
1093
+ if (attributeContainer.idAttributeContainer < 0) {
1094
+ attributeContainer.idAttributeContainer = undefined;
1095
+ }
1096
+ for (let attribute of attributeContainer.graphicalAttributes) {
1097
+ if (attribute.idAttribute < 0) {
1098
+ attribute.idAttribute = undefined;
1099
+ }
1100
+ if (attribute.attributeChoices) {
1101
+ for (let attributeChoice of attribute.attributeChoices) {
1102
+ delete attribute["value"];
1103
+ if (attributeChoice.idAttribute < 0) {
1104
+ attributeChoice.idAttribute = undefined;
1105
+ }
1106
+ if (attributeChoice.idAttributeChoice < 0) {
1107
+ attributeChoice.idAttributeChoice = undefined;
1108
+ }
1109
+ }
1110
+ }
1111
+ }
1112
+ }
1113
+ }
1114
+ /**
1115
+ * Creates a display name for the attribute configuration based on the context code and id.
1116
+ *
1117
+ * @param {AttributeConfiguration} configuration
1118
+ * @returns {string}
1119
+ */
1120
+ getConfigurationName(configuration) {
1121
+ if (configuration.idAttributeConfiguration === -1) {
1122
+ return "New";
1123
+ }
1124
+ let name = configuration.codeAttributeSecurityContextDisplay + ": " + configuration.extensionDescription;
1125
+ if (configuration.idFilter1) {
1126
+ name += " - " + configuration.filter1Display;
1127
+ }
1128
+ if (configuration.idFilter2) {
1129
+ name += " - " + configuration.filter2Display;
1130
+ }
1131
+ return name;
1132
+ }
1133
+ getAttributeConfigurationDTO(cfg) {
1134
+ if (!cfg) {
1135
+ return undefined;
1136
+ }
1137
+ let dto = {
1138
+ idAttributeConfiguration: cfg.idAttributeConfiguration,
1139
+ codeAttributeContext: cfg.codeAttributeContext,
1140
+ codeAttributeSecurityContext: cfg.codeAttributeSecurityContext,
1141
+ idFilter1: cfg.idFilter1,
1142
+ idFilter2: cfg.idFilter2
1143
+ };
1144
+ if (this.attributeContextListSubject.getValue()) {
1145
+ dto.extensionDescription = this.attributeContextListSubject.getValue().filter((ctx) => {
1146
+ return ctx.codeAttributeContext === cfg.codeAttributeContext;
1147
+ })[0].extensionDescription;
1148
+ }
1149
+ if (this.attributeSecurityContextListSubject.getValue()) {
1150
+ let result = this.attributeSecurityContextListSubject.getValue().filter((filter) => {
1151
+ return filter.codeAttributeSecurityContext === cfg.codeAttributeSecurityContext;
1152
+ });
1153
+ dto.codeAttributeSecurityContextDisplay = (result && result.length > 0) ? result[0].description : undefined;
1154
+ }
1155
+ if (this.filter1ListSubject.getValue()) {
1156
+ let result = this.filter1ListSubject.getValue().filter((filter) => {
1157
+ return filter.codeAttributeContext === cfg.codeAttributeContext
1158
+ && filter.codeAttributeSecurityContext === cfg.codeAttributeSecurityContext
1159
+ && filter.idFilter1 === cfg.idFilter1;
1160
+ });
1161
+ dto.filter1Display = (result && result.length > 0) ? result[0].display : undefined;
1162
+ }
1163
+ if (this.filter2ListSubject.getValue()) {
1164
+ let result = this.filter2ListSubject.getValue().filter((filter) => {
1165
+ return filter.codeAttributeContext === cfg.codeAttributeContext
1166
+ && filter.codeAttributeSecurityContext === cfg.codeAttributeSecurityContext
1167
+ && filter.idFilter1 === cfg.idFilter1
1168
+ && filter.idFilter2 === cfg.idFilter2;
1169
+ });
1170
+ dto.filter2Display = (result && result.length > 0) ? result[0].display : undefined;
1171
+ }
1172
+ return dto;
1173
+ }
1174
+ getSecurityCodeContext(code) {
1175
+ return this.attributeSecurityContextListSubject.getValue().filter((filter) => {
1176
+ return filter.codeAttributeSecurityContext === code;
1177
+ })[0];
1178
+ }
1179
+ getAttributeContextLoadingSubject() {
1180
+ return this.attributeContextLoadingSubject;
1181
+ }
1182
+ getFilter1For(codeAttributeContext, codeAttributeSecurityContext) {
1183
+ return this.filter1ListSubject.getValue().filter((item) => {
1184
+ return item.codeAttributeContext === codeAttributeContext && item.codeAttributeSecurityContext === codeAttributeSecurityContext;
1185
+ });
1186
+ }
1187
+ getFilter2For(codeAttributeContext, codeAttributeSecurityContext, idFilter1) {
1188
+ return this.filter2ListSubject.getValue().filter((item) => {
1189
+ return item.codeAttributeContext === codeAttributeContext
1190
+ && item.codeAttributeSecurityContext === codeAttributeSecurityContext
1191
+ && item.idFilter1 === idFilter1;
1192
+ });
1193
+ }
1194
+ /**
1195
+ * Track new idAttributeValues via a negative number for internal tracking. Remove this fake id prior to post.
1196
+ *
1197
+ * @returns {number}
1198
+ */
1199
+ getUniqueId() {
1200
+ return --this.uniqueId;
1201
+ }
1202
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: AttributeService, deps: [{ token: i1.DictionaryService }, { token: i2.HttpClient }, { token: i3.Router }, { token: ATTRIBUTE_ENDPOINT }], target: i0.ɵɵFactoryTarget.Injectable }); }
1203
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: AttributeService }); }
1204
+ }
1205
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: AttributeService, decorators: [{
1206
+ type: Injectable
1207
+ }], ctorParameters: () => [{ type: i1.DictionaryService }, { type: i2.HttpClient }, { type: i3.Router }, { type: undefined, decorators: [{
1208
+ type: Inject,
1209
+ args: [ATTRIBUTE_ENDPOINT]
1210
+ }] }] });
1211
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0cmlidXRlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb2Qvc3JjL3NlcnZpY2VzL2F0dHJpYnV0ZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDNUUsT0FBTyxFQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RCxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFdkMsT0FBTyxFQUFDLGVBQWUsRUFBRSxRQUFRLEVBQWMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBRXBFLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLCtDQUErQyxDQUFDO0FBV2hGLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRCxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxpQ0FBaUMsQ0FBQzs7Ozs7QUFHckUsTUFBTSxDQUFDLElBQUksa0JBQWtCLEdBQUcsSUFBSSxjQUFjLENBQVMsbUJBQW1CLENBQUMsQ0FBQztBQUNoRixNQUFNLENBQUMsTUFBTSxPQUFPLEdBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDNUMsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBRTFEOzs7R0FHRztBQUVILE1BQU0sT0FBTyxnQkFBZ0I7SUE4QzNCLFlBQW9CLGlCQUFvQyxFQUNwQyxJQUFnQixFQUNoQixNQUFjLEVBQ2MsaUJBQXlCO1FBSHJELHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUNoQixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2Msc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFRO1FBdkN6RSxtQ0FBOEIsR0FBNkIsSUFBSSxlQUFlLENBQVUsS0FBSyxDQUFDLENBQUM7UUFFL0YsZ0NBQTJCLEdBQTJCLElBQUksZUFBZSxDQUFRLFNBQVMsQ0FBQyxDQUFDO1FBQzVGLHdDQUFtQyxHQUEyQixJQUFJLGVBQWUsQ0FBUSxTQUFTLENBQUMsQ0FBQztRQUNwRyx1QkFBa0IsR0FBMkIsSUFBSSxlQUFlLENBQVEsU0FBUyxDQUFDLENBQUM7UUFDbkYsdUJBQWtCLEdBQTJCLElBQUksZUFBZSxDQUFRLFNBQVMsQ0FBQyxDQUFDO1FBQ25GLDBCQUFxQixHQUEyQixJQUFJLGVBQWUsQ0FBUSxTQUFTLENBQUMsQ0FBQztRQUd0Riw2QkFBd0IsR0FBcUIsSUFBSSxPQUFPLEVBQVcsQ0FBQztRQUNwRSwyQ0FBc0MsR0FBeUIsSUFBSSxlQUFlLENBQU0sU0FBUyxDQUFDLENBQUM7UUFFbkcsc0NBQWlDLEdBQWlELElBQUksZUFBZSxDQUE4QixTQUFTLENBQUMsQ0FBQztRQUM5SSw2Q0FBd0MsR0FBNkIsSUFBSSxlQUFlLENBQVUsS0FBSyxDQUFDLENBQUM7UUFFekcscUNBQWdDLEdBQStDLElBQUksZUFBZSxDQUE0QixTQUFTLENBQUMsQ0FBQztRQUV6SSxrQ0FBNkIsR0FBNEMsSUFBSSxlQUFlLENBQXlCLFNBQVMsQ0FBQyxDQUFDO1FBQ2hJLDZCQUF3QixHQUF1QyxJQUFJLGVBQWUsQ0FBb0IsU0FBUyxDQUFDLENBQUM7UUFDakgsZ0NBQTJCLEdBQTRCLElBQUksT0FBTyxFQUFrQixDQUFDO1FBRXJGLG1CQUFjLEdBQTZCLElBQUksZUFBZSxDQUFVLEtBQUssQ0FBQyxDQUFDO1FBRS9FLGlCQUFZLEdBQTJCLElBQUksR0FBRyxFQUFxQixDQUFDO1FBSXBFLHFCQUFnQixHQUFxQixJQUFJLE9BQU8sRUFBVyxDQUFDO1FBQzVELGlCQUFZLEdBQW1DLElBQUksT0FBTyxFQUF5QixDQUFDO1FBQ3BGLG1CQUFjLEdBQW1DLElBQUksT0FBTyxFQUF5QixDQUFDO1FBQ3RGLFVBQUssR0FBNkIsSUFBSSxlQUFlLENBQVUsS0FBSyxDQUFDLENBQUM7UUFDdEUsMkJBQXNCLEdBQXFCLEVBQUUsQ0FBQztRQUM5QywwQkFBcUIsR0FBcUIsRUFBRSxDQUFDO1FBRXJDLGFBQVEsR0FBVyxDQUFDLENBQUM7UUFNM0IsSUFBSSxTQUFTLEVBQUUsRUFBRSxDQUFDO1lBQ2hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUNoRCxDQUFDO0lBQ0gsQ0FBQztJQUVELFlBQVksQ0FBQyxTQUFjO1FBQ3pCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBRTNCLElBQUksSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7WUFDN0MsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDMUIsQ0FBQztJQUNILENBQUM7SUFFRCxpQ0FBaUMsQ0FBQyxXQUFtQjtRQUNuRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFTLElBQUksQ0FBQyxpQkFBaUIsR0FBRyx1QkFBdUIsRUFBRSxFQUFDLE1BQU0sRUFBRSxJQUFJLFVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsV0FBVyxDQUFDLFFBQVEsRUFBRSxDQUFDLEVBQUMsQ0FBQyxDQUFDO0lBQ3hKLENBQUM7SUFFRCxpQ0FBaUMsQ0FBQyxvQkFBNEI7UUFDNUQsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBUyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsdUJBQXVCLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUMsc0JBQXNCLEVBQUUsb0JBQW9CLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBQyxDQUFDLENBQUM7SUFDMUssQ0FBQztJQUVELHVCQUF1QixDQUFDLHFCQUE2QjtRQUNuRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFTLElBQUksQ0FBQyxpQkFBaUIsR0FBRyw0QkFBNEIsRUFBRSxFQUFDLE1BQU0sRUFBRSxJQUFJLFVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsRUFBRSxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUFDLENBQUMsQ0FBQztJQUNqTCxDQUFDO0lBRUQscUJBQXFCO1FBQ25CLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFL0MsUUFBUSxDQUFDO1lBQ1AsSUFBSSxDQUFDLGlCQUFpQixDQUFDLG9CQUFvQixDQUFDLDRDQUE0QyxDQUFDO1lBQ3pGLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxvQkFBb0IsQ0FBQyxvQ0FBb0MsQ0FBQztZQUNqRixJQUFJLENBQUMsaUJBQWlCLENBQUMsb0JBQW9CLENBQUMsMkJBQTJCLENBQUM7WUFDeEUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLG9CQUFvQixDQUFDLDJCQUEyQixDQUFDO1lBQ3hFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxvQkFBb0IsQ0FBQyx1Q0FBdUMsQ0FBQztTQUNyRixDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBZ0IsRUFBRSxFQUFFO1lBRWhDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMzQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFcEQsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztZQUN6RCxJQUFJLENBQUMsbUNBQW1DLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTVELElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsNEdBQTRHO0lBQzVHLG9CQUFvQixDQUFDLFNBQW9CLEVBQUUsTUFBd0IsRUFBRSxtQkFBNEIsRUFBRSx3QkFBeUM7UUFDMUksSUFBSSxFQUFFLEdBQUcsSUFBSSxPQUFPLEVBQXdCLENBQUM7UUFFN0MsY0FBYztRQUNkLElBQUksU0FBUyxDQUFDLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3hDLElBQUksVUFBVSxHQUFHLElBQUksb0JBQW9CLEVBQUUsQ0FBQztZQUM1QyxJQUFJLEtBQUssR0FBRyxTQUFTLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDO1lBRWhELHlGQUF5RjtZQUN6RixJQUFJLFdBQVcsR0FBYSxFQUFFLENBQUM7WUFDL0IsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1lBQ1osT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLDBCQUEwQixFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUMzRCxJQUFJLEtBQUssR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLDBCQUEwQixFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUMzRCxLQUFLLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQ2xDLElBQUksR0FBRyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDeEMsV0FBVyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUE7Z0JBQy9FLEdBQUcsR0FBRyxHQUFHLENBQUM7WUFDWixDQUFDO1lBRUQsd0NBQXdDO1lBQ3hDLElBQUksU0FBUyxHQUFHLEVBQUUsQ0FBQztZQUNuQixLQUFLLElBQUksU0FBUyxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNsQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyx5QkFBeUIsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1lBQzlFLENBQUM7WUFFRCxnQ0FBZ0M7WUFDaEMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFNBQWdCLEVBQUUsRUFBRTtnQkFDakQsa0VBQWtFO2dCQUNsRSxNQUFNLE1BQU0sR0FBRyxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUMvQixJQUFJLEdBQUcsR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO2dCQUVsRSxnSEFBZ0g7Z0JBQ2hILElBQUksWUFBWSxHQUFHLFNBQVMsQ0FBQztnQkFDN0IsSUFBSSxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUN6QixZQUFZLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUM5QixDQUFDO2dCQUVELGlDQUFpQztnQkFDakMsSUFBSSxHQUFHLEdBQWMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsWUFBWSxFQUFFLG1CQUFtQixFQUFFLHdCQUF3QixDQUFDLENBQUM7Z0JBRTdJLDJCQUEyQjtnQkFDM0IsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNqQixVQUFVLENBQUMsMkJBQTJCLEdBQUcsS0FBSyxDQUFDO2dCQUUvQyxJQUFHLENBQUM7b0JBQ0YsSUFBSSxXQUFXLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztvQkFFM0YsK0JBQStCO29CQUMvQixJQUFJLElBQUksR0FBRyxJQUFJLENBQUM7b0JBQ2hCLE9BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO3dCQUV2QyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLENBQUM7d0JBQzVDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3RCLENBQUM7Z0JBQ0gsQ0FBQztnQkFBQSxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNWLDRCQUE0QjtnQkFDOUIsQ0FBQztnQkFFRCxvR0FBb0c7Z0JBQ3BHLHdFQUF3RTtnQkFDeEUsa0pBQWtKO2dCQUNsSixJQUFJLFNBQVMsQ0FBQyxZQUFZLEtBQUssR0FBRyxFQUFFLENBQUM7b0JBQ25DLEtBQUssSUFBSSxFQUFFLElBQUksTUFBTSxFQUFFLENBQUM7d0JBQ3RCLElBQUksT0FBTyxHQUFXLEtBQUssQ0FBQzt3QkFFNUIsSUFBSSxFQUFFLElBQUksQ0FBRSx3QkFBd0IsRUFBRSxDQUFDOzRCQUNyQyxLQUFJLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQ0FDNUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO29DQUM5QyxPQUFPLEdBQUcsSUFBSSxDQUFDO29DQUNmLE1BQU07Z0NBQ1IsQ0FBQzs0QkFDSCxDQUFDOzRCQUVELDBEQUEwRDs0QkFDMUQsSUFBSSxDQUFFLE9BQU8sRUFBRSxDQUFDO2dDQUVkLElBQUksS0FBSyxHQUFHLHVDQUF1QyxHQUFHLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLEdBQUcsNkJBQTZCLEdBQUcsRUFBRSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztnQ0FDNUosb0ZBQW9GO2dDQUVwRixJQUFJLElBQUksR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFdBQVcsQ0FBQyx1QkFBdUIsRUFBRSxJQUFJLENBQUMsQ0FBQyxlQUFlLENBQUM7Z0NBQzFHLElBQUksSUFBSSxFQUFFLENBQUM7b0NBQ1QsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztvQ0FDOUMsVUFBVSxDQUFDLDJCQUEyQixHQUFHLElBQUksQ0FBQztnQ0FDaEQsQ0FBQzs0QkFDSCxDQUFDO3dCQUNILENBQUM7b0JBQ0gsQ0FBQztnQkFDSCxDQUFDO2dCQUdELHNFQUFzRTtnQkFDdEUsVUFBVSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7Z0JBQzdCLFVBQVUsQ0FBQyxtQkFBbUIsR0FBRyxHQUFHLENBQUMsbUJBQW1CLENBQUM7Z0JBQ3pELEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxDQUFDLENBQUM7UUFFTCxDQUFDO1FBQ0QsV0FBVzthQUNOLENBQUM7WUFDSiw4RkFBOEY7WUFDOUYsSUFBSSxDQUFDLGlCQUFpQixDQUFDLDRCQUE0QixDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFjLEVBQUUsRUFBRTtnQkFDeEgsbUJBQW1CO2dCQUNuQixLQUFJLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztvQkFDNUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUM5QyxDQUFDO2dCQUVELElBQUksVUFBVSxHQUFHLElBQUksb0JBQW9CLEVBQUUsQ0FBQztnQkFDNUMsVUFBVSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7Z0JBQzdCLFVBQVUsQ0FBQywyQkFBMkIsR0FBRyxJQUFJLENBQUMsQ0FBQyx5RkFBeUY7Z0JBQ3hJLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsb0JBQW9CLENBQUMsSUFBUztRQUM1QixvQ0FBb0M7UUFDcEMsSUFBSSxLQUFLLEdBQVEsRUFBRSxDQUFDO1FBQ3BCLEtBQUksSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNwRCxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUM1RCxDQUFDO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU8sZ0JBQWdCLENBQUMsS0FBYSxFQUFFLFlBQW9CLEVBQUUsbUJBQTJCLEVBQUUsd0JBQXdDO1FBQ2pJLElBQUksR0FBRyxHQUFjLElBQUksVUFBVSxFQUFFLENBQUM7UUFFdEMsa0NBQWtDO1FBQ2xDLE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQyxtQ0FBbUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQy9ELEtBQUssR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLG1DQUFtQyxFQUFFLEdBQUcsR0FBRyxJQUFJLENBQUMsZ0NBQWdDLEVBQUUsQ0FBQyxLQUFLLENBQUMsNEJBQTRCLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDckosQ0FBQztRQUVELDRHQUE0RztRQUM1RyxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLDRCQUE0QixDQUFDLENBQUM7UUFDMUQsT0FBTyxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDckIsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDMUMsSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDMUUsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUUvRCxJQUFJLEVBQUUsQ0FBQztZQUVQLCtHQUErRztZQUMvRyxJQUFJLENBQUUsd0JBQXdCLEVBQUUsQ0FBQztnQkFFL0IsMkNBQTJDO2dCQUMzQywrR0FBK0c7Z0JBRS9HLHVEQUF1RDtnQkFDdkQsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUFvQixFQUFFLEVBQUU7b0JBQ2pELGdDQUFnQztvQkFDaEMsSUFBSSxTQUFTLENBQUMsYUFBYSxLQUFLLE9BQU8sRUFBRSxDQUFDO3dCQUN4QyxHQUFHLENBQUMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDO3dCQUNwQyxPQUFPO29CQUNULENBQUM7b0JBRUQsbURBQW1EO29CQUNuRCxJQUFJLFNBQVMsQ0FBQyxVQUFVLEVBQUUsQ0FBQzt3QkFDekIsS0FBSyxJQUFJLG1CQUFtQixJQUFLLFNBQVMsQ0FBQyxVQUFVLEVBQUUsQ0FBQzs0QkFDdEQsd0lBQXdJOzRCQUN4SSxJQUFJLG1CQUFtQixDQUFDLGFBQWEsS0FBSyxPQUFPLEVBQUUsQ0FBQztnQ0FDbEQsR0FBRyxDQUFDLG1CQUFtQixHQUFHLG1CQUFtQixDQUFDO2dDQUM5QyxPQUFPOzRCQUNULENBQUM7d0JBQ0gsQ0FBQztvQkFDSCxDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUlILElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDbkQsOENBQThDO2dCQUM5QyxJQUFJLEdBQUcsQ0FBQyxtQkFBbUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztvQkFFbkMsK0dBQStHO29CQUMvRyxFQUFFLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRTt3QkFFbkMsc0ZBQXNGO3dCQUN0RixJQUFJLE9BQU8sRUFBRSxDQUFDLG1CQUFtQixLQUFLLFdBQVcsSUFBSSxPQUFPLG1CQUFtQixLQUFLLFdBQVcsSUFBSSxFQUFFLENBQUMsbUJBQW1CLEtBQUssbUJBQW1CLEVBQUUsQ0FBQzs0QkFDbEosT0FBTyxLQUFLLENBQUM7d0JBQ2YsQ0FBQzt3QkFHRCxnS0FBZ0s7d0JBQy9KLDREQUE0RDt3QkFDN0QsSUFBSSxHQUFHLENBQUMsbUJBQW1CLENBQUMsV0FBVyxLQUFLLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQzs0QkFDM0QsT0FBTyxJQUFJLENBQUM7d0JBQ2QsQ0FBQzs2QkFDSSxDQUFDOzRCQUNKLE9BQU8sS0FBSyxDQUFDO3dCQUNmLENBQUM7b0JBQ0gsQ0FBQyxDQUFDLENBQUE7Z0JBQ0osQ0FBQztZQUNILENBQUM7WUFFRCw0SEFBNEg7WUFDNUgsSUFBSSx3QkFBd0IsRUFBRSxDQUFDO2dCQUM3QixLQUFLLEdBQUcsTUFBTSxHQUFHLEdBQUcsR0FBRyx3QkFBd0IsQ0FBQyxLQUFLLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQztZQUN2RSxDQUFDO1lBQ0QsK0VBQStFO2lCQUMxRSxJQUFJLEVBQUUsRUFBRSxDQUFDO2dCQUNaLEtBQUssR0FBRyxNQUFNLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxLQUFLLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQztZQUNqRCxDQUFDO1lBQ0Qsc0NBQXNDO2lCQUNqQyxDQUFDO2dCQUNKLHFGQUFxRjtnQkFDckYsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztvQkFDOUMsS0FBSyxHQUFHLE1BQU0sR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsR0FBRyxHQUFHLEdBQUcsTUFBTSxDQUFDO2dCQUNoRSxDQUFDO2dCQUNELHNHQUFzRztxQkFDakcsQ0FBQztvQkFDSixLQUFLLEdBQUcsTUFBTSxHQUFHLElBQUksR0FBRyxNQUFNLENBQUM7Z0JBQ2pDLENBQUM7WUFDSCxDQUFDO1lBRUQsUUFBUSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsNEJBQTRCLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBRUQsK0ZBQStGO1FBQy9GLElBQUksZUFBZSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUVwRSxJQUFJLGVBQWUsR0FBRyxDQUFDLElBQUksWUFBWSxFQUFFLENBQUM7WUFDeEMsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsZUFBZSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3JELElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLGVBQWUsQ0FBQyxDQUFDO1lBQ3hELElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsZUFBZSxHQUFHLENBQUMsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxlQUFlLENBQUMsQ0FBQyxDQUFDO1lBQ3pGLElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLEdBQUcsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBQzVGLElBQUksTUFBTSxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBRWhELEtBQUssR0FBRyxNQUFNLENBQUM7WUFFZiwyQkFBMkI7WUFDM0IsTUFBTSxNQUFNLEdBQUcsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUMvQixJQUFJLEdBQUcsR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDLFlBQVksRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ2xFLElBQUksV0FBVyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUUxRiwrQkFBK0I7WUFDL0IsSUFBSSxJQUFJLEdBQUcsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBRXJDLE9BQU0sSUFBSSxFQUFFLENBQUM7Z0JBQ1gsS0FBSyxHQUFHLEtBQUssR0FBRyxRQUFRLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxDQUFBO2dCQUV0RCxJQUFJLEdBQUcsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUVqQyxJQUFJLElBQUksRUFBRSxDQUFDO29CQUNULEtBQUssR0FBRyxLQUFLLEdBQUcsTUFBTSxDQUFDO2dCQUN6QixDQUFDO1lBQ0gsQ0FBQztZQUVELEtBQUssR0FBRyxLQUFLLEdBQUcsTUFBTSxDQUFDO1FBQ3pCLENBQUM7UUFFRCxHQUFHLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUN2QixPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFTyxnQ0FBZ0MsQ0FBQyxDQUFNLEVBQUUsQ0FBTTtRQUNyRCxPQUFPLENBQUMsQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUNoRixDQUFDO0lBRUQsK0JBQStCLENBQUMsNEJBQXFDO1FBQ25FLElBQUksU0FBUyxFQUFFLEVBQUUsQ0FBQztZQUNoQixPQUFPLENBQUMsS0FBSyxDQUFDLG1DQUFtQyxHQUFHLDRCQUE0QixDQUFDLENBQUM7UUFDcEYsQ0FBQztRQUVELElBQUksQ0FBQyx3Q0FBd0MsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFekQsSUFBSSxHQUFHLEdBQVcsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGdCQUFnQixDQUFDO1FBQzVELElBQUksTUFBTSxHQUFlLElBQUksVUFBVSxFQUFFLENBQUM7UUFDMUMsSUFBSSw0QkFBNEIsRUFBRSxDQUFDO1lBQ2pDLE1BQU0sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLDhCQUE4QixFQUFFLDRCQUE0QixDQUFDLENBQUM7UUFDcEYsQ0FBQztRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUEyQixHQUFHLEVBQUUsRUFBQyxNQUFNLEVBQUUsTUFBTSxFQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxpQkFBMkMsRUFBRSxFQUFFO1lBQ3ZILElBQUksQ0FBQyx3Q0FBd0MsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFMUQsSUFBSSxJQUFJLEdBQWdDLEVBQUUsQ0FBQztZQUMzQyxLQUFLLElBQUksR0FBRyxJQUFJLGlCQUFpQixFQUFFLENBQUM7Z0JBQ2xDLElBQUksR0FBRyxHQUE4QixJQUFJLENBQUMsNEJBQTRCLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzVFLElBQUksR0FBRyxFQUFFLENBQUM7b0JBQ1IsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDakIsQ0FBQztZQUNILENBQUM7WUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1lBRS9DLElBQUksQ0FBQyxpQ0FBaUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sOEJBQThCLENBQUMsQ0FBNEIsRUFBRSxDQUE0QjtRQUMvRixNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsbUNBQW1DO2NBQ2xELENBQUMsQ0FBQyxvQkFBb0I7Y0FDdEIsQ0FBQyxDQUFDLENBQUMsY0FBYyxJQUFJLEVBQUUsQ0FBQztjQUN4QixDQUFDLENBQUMsQ0FBQyxjQUFjLElBQUksRUFBRSxDQUFDLENBQUM7UUFFN0IsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFDLG1DQUFtQztjQUNsRCxDQUFDLENBQUMsb0JBQW9CO2NBQ3RCLENBQUMsQ0FBQyxDQUFDLGNBQWMsSUFBSSxFQUFFLENBQUM7Y0FDeEIsQ0FBQyxDQUFDLENBQUMsY0FBYyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRTdCLE9BQU8sUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUN0RSxDQUFDO0lBRUQsb0JBQW9CO0lBQ3BCLEtBQUs7UUFDSCxJQUFJLENBQUMsd0JBQXdCLEdBQUcsU0FBUyxDQUFDO1FBQzFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzNCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBRTNCLElBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdEQsSUFBSSxDQUFDLDZCQUE2QixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRUQsNEJBQTRCLENBQUMsc0JBQThDO1FBQ3pFLHNCQUFzQixDQUFDLHdCQUF3QixHQUFHLFNBQVMsQ0FBQztRQUU1RCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBeUIsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGdCQUFnQixFQUFFLHNCQUFzQixDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsc0JBQThDLEVBQUUsRUFBRTtZQUNySyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsc0JBQXNCLENBQUMsd0JBQXdCLENBQUM7WUFFaEYsSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN6QyxJQUFJLENBQUMsNkJBQTZCLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUM7WUFDaEUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsa0NBQWtDLEdBQUcsc0JBQXNCLENBQUMsd0JBQXdCLENBQUMsQ0FBQztRQUNsSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCw2QkFBNkIsQ0FBQyx3QkFBZ0MsRUFBRSxtQkFBMkIsRUFBRSxjQUFzQjtRQUNqSCxJQUFJLHdCQUF3QixLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDcEMsSUFBSSxDQUFDLHlCQUF5QixHQUFHLFNBQVMsQ0FBQztRQUM3QyxDQUFDO1FBRUQscURBQXFEO1FBQ3JELElBQUksSUFBSSxDQUFDLHdCQUF3QixLQUFLLHdCQUF3QixFQUFFLENBQUM7WUFDL0QsWUFBWTtZQUNaLElBQUksQ0FBQyx3QkFBd0IsR0FBRyx3QkFBd0IsQ0FBQztZQUN6RCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsbUJBQW1CLENBQUM7WUFDL0MsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7WUFDM0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7WUFDM0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsZ0NBQWdDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3RELElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFFbkQsSUFBSSxDQUFDLDJCQUEyQixDQUFDLG1CQUFtQixFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFDRCwySEFBMkg7UUFDM0gsMEdBQTBHO2FBQ3JHLElBQUksSUFBSSxDQUFDLG1CQUFtQixLQUFLLG1CQUFtQixJQUFJLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQzNHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxtQkFBbUIsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNqRSxDQUFDO0lBQ0gsQ0FBQztJQUlEOzs7Ozs7T0FNRztJQUNMOzs7Ozs7Ozs7Ozs7Ozs7O01BZ0JFO0lBRUE7Ozs7T0FJRztJQUNILG9CQUFvQixDQUFDLG1CQUEyQixFQUFFLGNBQXNCO1FBQ3RFLHdEQUF3RDtRQUN4RCxJQUFJLElBQUksQ0FBQyxtQkFBbUIsS0FBSyxtQkFBbUIsRUFBRSxDQUFDO1lBQ3JELElBQUksQ0FBQyxtQkFBbUIsR0FBRyxtQkFBbUIsQ0FBQztZQUUvQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDOUMsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILDJCQUEyQixDQUFDLG1CQUEyQixFQUFFLGNBQXNCO1FBRTdFLElBQUksSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLGdDQUFnQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN0RCxJQUFJLENBQUMsNkJBQTZCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1lBQ3hFLE9BQU87UUFDVCxDQUFDO2FBQU0sSUFBSSxJQUFJLENBQUMsd0JBQXdCLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsZ0NBQWdDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3RELElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxJQUFJLENBQXlCO2dCQUM5RCx3QkFBd0IsRUFBRSxDQUFDLENBQUM7YUFDN0IsQ0FBQyxDQUFDO1lBQ0gsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUUvQixJQUFJLEdBQVcsQ0FBQztRQUNoQixJQUFJLElBQUksQ0FBQyx3QkFBd0IsSUFBSSxJQUFJLENBQUMsd0JBQXdCLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN4RSxHQUFHLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGlCQUFpQixHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQztRQUNuRixDQUFDO2FBQU0sQ0FBQztZQUNOLCtCQUErQjtZQUNsQywyRUFBMkU7WUFDeEUsdUJBQXVCO1lBQ3JCLDhCQUE4QjtZQUNoQyxHQUFHO1FBQ0wsQ0FBQztRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUF5QixHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxzQkFBOEMsRUFBRSxFQUFFO1lBQ3RHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1lBQ3ZELElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBRWhDLDZGQUE2RjtZQUM3RixJQUFJLENBQUMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDLENBQUMscUNBQXFDO1lBQzNFLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxtQkFBbUIsRUFBRSxjQUFjLENBQUMsQ0FBQztZQUMvRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixDQUFDLEVBQ0QsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNSLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzVDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELHlCQUF5QixDQUFDLHNCQUE4QztRQUN0RSxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRTFCLElBQUksU0FBUyxFQUFFLEVBQUUsQ0FBQztZQUNoQixPQUFPLENBQUMsS0FBSyxDQUFDLDRDQUE0QyxDQUFDLENBQUM7WUFDNUQsT0FBTyxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ3hDLENBQUM7UUFFRCxJQUFJLHNCQUFzQixFQUFFLENBQUM7WUFDM0IsSUFBSSxzQkFBc0IsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO2dCQUM5QyxJQUFJLENBQUMsc0JBQXNCLENBQUMsc0JBQXNCLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUN6RSxDQUFDO1lBRUQsSUFBSSxzQkFBc0IsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO2dCQUMvQyxzQkFBc0IsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFxQixFQUFFLENBQXFCLEVBQUUsRUFBRTtvQkFDL0YsSUFBSSxDQUFDLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQzt3QkFDOUIsT0FBTyxDQUFDLENBQUMsQ0FBQztvQkFDWixDQUFDO3lCQUFNLElBQUksQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7d0JBQ3JDLE9BQU8sQ0FBQyxDQUFDO29CQUNYLENBQUM7eUJBQU0sQ0FBQzt3QkFDTixPQUFPLENBQUMsQ0FBQztvQkFDWCxDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUVELEtBQUssSUFBSSxrQkFBa0IsSUFBSSxzQkFBc0IsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO2dCQUMxRTs7O21CQUdHO2dCQUNILGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQXFCLEVBQUUsQ0FBcUIsRUFBRSxFQUFFO29CQUMzRixJQUFJLENBQUMsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO3dCQUM1QixPQUFPLENBQUMsQ0FBQyxDQUFDO29CQUNaLENBQUM7eUJBQU0sSUFBSSxDQUFDLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQzt3QkFDbkMsT0FBTyxDQUFDLENBQUM7b0JBQ1gsQ0FBQzt5QkFBTSxDQUFDO3dCQUNOLE9BQU8sQ0FBQyxDQUFDO29CQUNYLENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBRUgsS0FBSyxJQUFJLFNBQVMsSUFBSSxrQkFBa0IsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO29CQUM3RCxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2dCQUMxRCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLENBQUMsZ0NBQWdDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUM7UUFDdEcsSUFBSSxDQUFDLDZCQUE2QixDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFFRDs7O09BR0c7SUFDSCxzQkFBc0IsQ0FBQyxjQUFzQjtRQUMzQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztRQUVyQyxJQUFJLEdBQUcsR0FBVyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDO1FBRTdGLElBQUksRUFBRSxHQUEyQixJQUFJLENBQUMsNkJBQTZCLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFL0UsSUFBSSxXQUFXLEdBQWUsSUFBSSxVQUFVLEVBQUU7YUFDN0MsR0FBRyxDQUFDLDhCQUE4QixFQUFFLEVBQUUsQ0FBQyw0QkFBNEIsQ0FBQzthQUNwRSxHQUFHLENBQUMsc0JBQXNCLEVBQUUsRUFBRSxDQUFDLG9CQUFvQixDQUFDO2FBQ3BELEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLGNBQWMsQ0FBQyxDQUFBLENBQUMsQ0FBQSxjQUFjLENBQUMsUUFBUSxFQUFFLENBQUEsQ0FBQyxDQUFBLEVBQUUsQ0FBQyxDQUFDO1FBRXRFLFlBQVk7UUFDWixJQUFJLENBQUMscUJBQXFCLEdBQUcsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUU5QyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBb0IsR0FBRyxFQUFFLEVBQUMsTUFBTSxFQUFFLFdBQVcsRUFBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsaUJBQW9DLEVBQUUsRUFBRTtZQUM5RyxpREFBaUQ7WUFDakQsSUFBSSxDQUFFLGlCQUFpQixDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUN4QyxpQkFBaUIsQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1lBQ3pDLENBQUM7WUFFRCxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFDdEQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsQ0FBQyxFQUNELENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDUixPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3JCLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2hDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDaEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsc0JBQXNCLENBQUMsa0JBQTBCO1FBQy9DLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyx1QkFBdUIsRUFBRSxFQUFDLE1BQU0sRUFBRSxJQUFJLFVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsRUFBRSxrQkFBa0IsQ0FBQyxFQUFDLENBQUM7YUFDdEksU0FBUyxDQUFDLENBQUMsU0FBYyxFQUFFLEVBQUU7WUFDNUIsSUFBSSxDQUFDLHNDQUFzQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM5RCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRDs7O09BR0c7SUFDSCxnQkFBZ0I7UUFDZCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILDBCQUEwQixDQUFDLHNCQUE4QztRQUN2RSxJQUFJLEdBQUcsR0FBVyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsaUJBQWlCLEdBQUcsc0JBQXNCLENBQUMsd0JBQXdCLENBQUM7UUFFL0csSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFL0IsSUFBSSxDQUFDLHlCQUF5QixDQUFDLHNCQUFzQixDQUFDLENBQUM7UUFFdkQsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLHNCQUFzQixDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtZQUV6RCw2REFBNkQ7WUFDN0QsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQXlCLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLHNCQUE4QyxFQUFFLEVBQUU7Z0JBQ3RHLElBQUksU0FBUyxFQUFFLEVBQUUsQ0FBQztvQkFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO2dCQUN4QyxDQUFDO2dCQUVELElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3pDLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQztZQUNsRSxDQUFDLEVBQ0QsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDUixPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3ZCLENBQUMsRUFDRCxHQUFHLEVBQUU7Z0JBQ0gsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbEMsQ0FBQyxDQUFDLENBQUM7UUFFTCxDQUFDLEVBQ0QsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNOLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILHVCQUF1QjtRQUNyQixJQUFJLEdBQUcsR0FBVyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsc0JBQXNCLENBQUU7UUFFbkUsSUFBSSxFQUFFLEdBQTJCLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUUvRSxJQUFJLFdBQVcsR0FBZSxJQUFJLFVBQVUsRUFBRTthQUM3QyxHQUFHLENBQUMsOEJBQThCLEVBQUUsRUFBRSxDQUFDLDRCQUE0QixDQUFDO2FBQ3BFLEdBQUcsQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLENBQUMsb0JBQW9CLENBQUM7YUFDcEQsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFBLENBQUMsQ0FBQSxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxDQUFBLENBQUMsQ0FBQSxFQUFFLENBQUMsQ0FBQztRQUVoRixJQUFJLEdBQUcsR0FBc0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDekYsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDakUsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQztZQUM5RSxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDeEQsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixHQUFHLFNBQVMsQ0FBQztZQUM5RCxDQUFDO1lBRUQsSUFBSSxDQUFDLEdBQVcsQ0FBQyxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDaEQsSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLEtBQUssR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO29CQUNoRyxNQUFNO2dCQUNSLENBQUM7WUFDSCxDQUFDO1lBQ0QsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDbkMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3hELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzNDLENBQUM7UUFDSCxDQUFDO1FBQ0QsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUMzRCxJQUFJLENBQUMsR0FBVyxDQUFDLENBQUM7WUFDbEIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUNoRCxJQUFJLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsS0FBSyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUM7b0JBQy9GLE1BQU07Z0JBQ1IsQ0FBQztZQUNILENBQUM7WUFDRCxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNuQyxHQUFHLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDbkMsQ0FBQztRQUNILENBQUM7UUFDRCxHQUFHLENBQUMsZUFBZSxHQUFHLEdBQUcsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBRTlFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRS9CLElBQUksYUFBYSxHQUErQixJQUFJLE9BQU8sRUFBcUIsQ0FBQztRQUVqRixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUMsTUFBTSxFQUFFLFdBQVcsRUFBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsaUJBQW9DLEVBQUUsRUFBRTtZQUM5RixJQUFJLFNBQVMsRUFBRSxFQUFFLENBQUM7Z0JBQ2hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUNuQyxDQUFDO1lBRUQsaURBQWlEO1lBQ2pELElBQUksQ0FBRSxpQkFBaUIsQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDeEMsaUJBQWlCLENBQUMsZUFBZSxHQUFHLEVBQUUsQ0FBQztZQUN6QyxDQUFDO1lBRUQsSUFBSSxDQUFDLHFCQUFxQixHQUFHLEVBQUUsQ0FBQztZQUNoQyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsRUFBRSxDQUFDO1lBQ2pDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUN0RCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNoQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUV2QiwwREFBMEQ7WUFDMUQsYUFBYSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQ3RDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUMzQixDQUFDLEVBQ0QsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNSLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEMsYUFBYSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QixDQUFDLENBQUMsQ0FBQztRQUVMLE9BQU8sYUFBYSxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsZ0NBQWdDO1FBQzlCLE9BQU8sSUFBSSxDQUFDLDZCQUE2QixDQUFDO0lBQzVDLENBQUM7SUFFRCxlQUFlO1FBQ2IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3BCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsb0JBQW9CO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLHdCQUF3QixDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsOEJBQThCO1FBQzVCLE9BQU8sSUFBSSxDQUFDLDJCQUEyQixDQUFDO0lBQzFDLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILGtCQUFrQixDQUFDLFdBQW1CLEVBQUUsbUJBQTJCO1FBRWpFLElBQUksZUFBZSxHQUFxQixFQUFFLENBQUM7UUFFM0MsSUFBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUU1Qyw4RkFBOEY7WUFDOUYsSUFBSSxDQUFDLEdBQVcsQ0FBQyxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUN4RCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEtBQUssV0FBVyxJQUFJLENBQUMsQ0FBQyxtQkFBbUIsSUFBSSxtQkFBbUIsS0FBSyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLENBQUMsRUFBRSxDQUFDO29CQUN2SyxlQUFlLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzFFLENBQUM7cUJBQ0ksSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLEtBQUssV0FBVyxJQUFJLENBQUMsQ0FBQyxtQkFBbUIsSUFBSSxtQkFBbUIsS0FBSyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLENBQUMsRUFBRSxDQUFDO29CQUNqTCxlQUFlLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzFFLENBQUM7WUFDSCxDQUFDO1lBRUQsdUNBQXVDO1lBQ3ZDLEtBQUssSUFBSSxjQUFjLElBQUksSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUNwRiwyREFBMkQ7Z0JBQzNELElBQUksY0FBYyxDQUFDLFdBQVcsS0FBSyxXQUFXLElBQUksY0FBYyxDQUFDLGdCQUFnQixLQUFLLFdBQVcsRUFBRSxDQUFDO29CQUNsRywwREFBMEQ7b0JBQzFELElBQUksT0FBTyxtQkFBbUIsS0FBSyxXQUFXLElBQUksY0FBYyxDQUFDLG1CQUFtQixLQUFLLG1CQUFtQixFQUFFLENBQUM7d0JBRTdHLHlCQUF5Qjt3QkFDekIsSUFBSSxDQUFFLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsS0FBSyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDOzRCQUV4RyxvREFBb0Q7NEJBQ3BELElBQUksQ0FBRSxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEtBQUssY0FBYyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztnQ0FDekcsZUFBZSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDOzRCQUMxRCxDQUFDO3dCQUNILENBQUM7b0JBQ0gsQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLGVBQWUsQ0FBQztJQUN6QixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxrQkFBa0IsQ0FBQyxXQUFtQjtRQUNwQyxJQUFJLFVBQVUsR0FBZ0IsRUFBRSxDQUFDO1FBRWpDLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUMsU0FBb0IsRUFBRSxFQUFFO1lBQ2pELElBQUksU0FBUyxDQUFDLGdCQUFnQixLQUFLLFdBQVcsRUFBRSxDQUFDO2dCQUMvQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQzdCLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsUUFBUSxDQUFDLEtBQWE7UUFDcEIsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxRQUFRO1FBQ04sT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3BCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILG1CQUFtQixDQUFDLFdBQW1CO1FBQ3JDLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsZ0JBQWdCLENBQUM7SUFDN0QsQ0FBQztJQUVELGlCQUFpQjtRQUNmLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUM3QixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILG1CQUFtQjtRQUNqQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztJQUMvQixDQUFDO0lBRUQsc0JBQXNCO1FBQ3BCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUMzQixDQUFDO0lBRUQsd0JBQXdCO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUM3QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsMkJBQTJCO1FBQ3pCLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDLHNCQUFzQixHQUFHLEVBQUUsQ0FBQztRQUNqQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2QixJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsa0NBQWtDLENBQUMsbUJBQTJCO1FBQzVELElBQUksbUJBQW1CLEdBQUcsRUFBRSxDQUFDO1FBRTdCLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsbUJBQW1CLEtBQUssbUJBQW1CLENBQUMsQ0FBQztRQUN2SCxJQUFJLENBQUMsc0JBQXNCLEdBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLG1CQUFtQixLQUFLLG1CQUFtQixDQUFDLENBQUM7UUFFMUgsMERBQTBEO0lBQzVELENBQUM7SUFFRCwwQkFBMEIsQ0FBQyxnQkFBd0IsRUFBRSxtQkFBMkI7UUFDOUUsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLG1CQUFtQixLQUFLLG1CQUFtQixDQUFDLENBQUM7UUFFM0csS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUMxQywwQ0FBMEM7WUFDMUMsSUFBSSxDQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO2dCQUN2QyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDO1lBQzlELENBQUM7WUFFRCxzQ0FBc0M7WUFDdEMsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3RDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsR0FBRyxTQUFTLENBQUM7WUFDNUMsQ0FBQztRQUNILENBQUM7UUFFRCx1SEFBdUg7UUFDdkgsNERBQTREO1FBQzVELDZDQUE2QztRQUM3QyxJQUFJLGFBQWEsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsbUJBQW1CLEtBQUssbUJBQW1CLENBQUMsQ0FBQztRQUM5RyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzlDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxvQkFBb0IsR0FBRyxTQUFTLENBQUM7WUFDbEQsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixHQUFHLFNBQVMsQ0FBQztZQUMvQyxTQUFTLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25DLENBQUM7UUFFRCxJQUFJLElBQUksR0FBZ0Q7WUFDcEQsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLG1CQUFtQjtZQUM3QyxnQkFBZ0IsRUFBRSxnQkFBZ0I7WUFDbEMsbUJBQW1CLEVBQUUsbUJBQW1CO1lBQ3hDLGVBQWUsRUFBRSxTQUFTO1NBQzNCLENBQUM7UUFFSixJQUFJLEdBQUcsR0FBVyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsMkJBQTJCLENBQUU7UUFFeEUsSUFBSSxFQUFFLEdBQTJCLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUUvRSxJQUFJLFdBQVcsR0FBZSxJQUFJLFVBQVUsRUFBRTthQUM3QyxHQUFHLENBQUMsOEJBQThCLEVBQUUsRUFBRSxDQUFDLDRCQUE0QixDQUFDO2FBQ3BFLEdBQUcsQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLENBQUMsb0JBQW9CLENBQUM7YUFDcEQsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFBLENBQUMsQ0FBQSxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxDQUFBLENBQUMsQ0FBQSxFQUFFLENBQUMsQ0FBQztRQUdoRixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUUvQixjQUFjO1FBQ2QsSUFBSSxtQkFBbUIsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM1QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUMsTUFBTSxFQUFFLFdBQVcsRUFBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMscUJBQTRDLEVBQUUsRUFBRTtnQkFFMUcsbURBQW1EO2dCQUNuRCxJQUFJLEdBQUcsR0FBcUIsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUVyRSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcscUJBQXFCLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO29CQUN0RSxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDckUsQ0FBQztnQkFFRCw2R0FBNkc7Z0JBQzdHLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsbUJBQW1CLEtBQUssbUJBQW1CLENBQUMsQ0FBQztnQkFDdkgsSUFBSSxDQUFDLHNCQUFzQixHQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxtQkFBbUIsS0FBSyxtQkFBbUIsQ0FBQyxDQUFDO2dCQUUxSCxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN4QyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO2dCQUM5QyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNsQyxDQUFDLEVBQ0QsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDUixPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNyQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNsQyxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxxQkFBcUI7YUFDaEIsQ0FBQztZQUNKLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBQyxNQUFNLEVBQUUsV0FBVyxFQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxxQkFBNEMsRUFBRSxFQUFFO2dCQUV6RyxtREFBbUQ7Z0JBQ25ELElBQUksR0FBRyxHQUFxQixJQUFJLENBQUMsd0JBQXdCLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBRXJFLCtCQUErQjtnQkFDL0IsSUFBSSxLQUFLLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEVBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxtQkFBbUIsS0FBSyxtQkFBbUIsQ0FBQyxDQUFDO2dCQUNqRyxPQUFPLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDakIsY0FBYztvQkFDZCxHQUFHLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7b0JBRXJDLG1CQUFtQjtvQkFDbkIsS0FBSyxHQUFHLEdBQUcsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxFQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsbUJBQW1CLEtBQUssbUJBQW1CLENBQUMsQ0FBQztnQkFDL0YsQ0FBQztnQkFFRCw0QkFBNEI7Z0JBQzVCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxxQkFBcUIsQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7b0JBQ3RFLEdBQUcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNyRSxDQUFDO2dCQUVELHVEQUF1RDtnQkFDdkQsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxtQkFBbUIsS0FBSyxtQkFBbUIsQ0FBQyxDQUFDO2dCQUN2SCxJQUFJLENBQUMsc0JBQXNCLEdBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLG1CQUFtQixLQUFLLG1CQUFtQixDQUFDLENBQUM7Z0JBRTFILElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ3hDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUM7Z0JBQzlDLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xDLENBQUMsRUFDRCxDQUFDLEtBQUssRUFBRSxFQUFFO2dCQUNSLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3JCLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xDLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7SUFFRCw0QkFBNEIsQ0FBQyxnQkFBd0IsRUFBRSxtQkFBMkI7UUFDaEYsSUFBSSxHQUFHLEdBQVcsSUFBSSxDQUFDLGlCQUFpQixHQUFHLDJCQUEyQixDQUFFO1FBRXhFLElBQUksRUFBRSxHQUEyQixJQUFJLENBQUMsNkJBQTZCLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFL0UsSUFBSSxXQUFXLEdBQWUsSUFBSSxVQUFVLEVBQUU7YUFDN0MsR0FBRyxDQUFDLDhCQUE4QixFQUFFLEVBQUUsQ0FBQyw0QkFBNEIsQ0FBQzthQUNwRSxHQUFHLENBQUMsc0JBQXNCLEVBQUUsRUFBRSxDQUFDLG9CQUFvQixDQUFDO2FBQ3BELEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQSxDQUFDLENBQUEsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsQ0FBQSxDQUFDLENBQUEsRUFBRSxDQUFDLENBQUM7UUFFaEYsSUFBSSxJQUFJLEdBQWdEO1lBQ3BELG1CQUFtQixFQUFFLElBQUksQ0FBQyxtQkFBbUI7WUFDN0MsZ0JBQWdCLEVBQUUsZ0JBQWdCO1lBQ2xDLG1CQUFtQixFQUFFLG1CQUFtQjtZQUN4QyxlQUFlLEVBQUUsRUFBRTtTQUNwQixDQUFDO1FBRUosSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRSxFQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtZQUVqRix3REFBd0Q7WUFDeEQsSUFBSSxHQUFHLEdBQXFCLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNyRSxHQUFHLENBQUMsZUFBZSxHQUFHLEdBQUcsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsbUJBQW1CLEtBQUssbUJBQW1CLENBQUMsQ0FBQztZQUN6RyxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hDLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQy9CLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xDLENBQUMsRUFDRCxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ1IsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNyQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsYUFBYSxDQUFDLFNBQW9CO1FBQ2hDLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUdELDZCQUE2QixDQUFDLGNBQThCO1FBQzFELCtCQUErQjtRQUMvQixJQUFJLENBQUMsR0FBVyxDQUFDLENBQUM7UUFDbEIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDdkQsSUFBSSxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxLQUFLLGNBQWMsQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLGlCQUFpQixLQUFLLGNBQWMsQ0FBQyxvQkFBb0IsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO2dCQUMvTSxNQUFNO1lBQ1IsQ0FBQztRQUNILENBQUM7UUFDRCwwREFBMEQ7UUFDMUQsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzFDLENBQUM7UUFDRCwrQ0FBK0M7YUFDMUMsQ0FBQztZQUNKLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUMxQyxDQUFDO0lBQ0gsQ0FBQztJQUVELDJCQUEyQixDQUFDLGNBQThCO1FBQ3hELCtCQUErQjtRQUMvQixJQUFJLENBQUMsR0FBVyxDQUFDLENBQUM7UUFDbEIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDdkQsSUFBSSxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxLQUFLLGNBQWMsQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixLQUFLLGNBQWMsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO2dCQUNySyxNQUFNO1lBQ1IsQ0FBQztRQUNILENBQUM7UUFDRCwwREFBMEQ7UUFDMUQsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzFDLENBQUM7UUFDRCwrQ0FBK0M7YUFDMUMsQ0FBQztZQUNKLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUMxQyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxrQkFBa0IsQ0FBQyxjQUE4QjtRQUMvQyxJQUFJLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1lBQ3BDLE9BQU8sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDaEMsQ0FBQztRQUVELElBQUksQ0FBQyxHQUFXLENBQUMsQ0FBQztRQUNsQixLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUN4RCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsS0FBSyxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDeEYsTUFBTTtZQUNSLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzNDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzNDLENBQUM7UUFFRCxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQywyQkFBMkIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFdEQsb0VBQW9FO1FBQ3BFLElBQUksQ0FBRSxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUN0QyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsbUJBQW1CLENBQUMsU0FBb0IsRUFBRSxlQUFpQztRQUN6RSxJQUFJLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBQ3JDLE9BQU8sQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDakMsQ0FBQztRQUVELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDaEQsSUFBSSxDQUFDLEdBQVcsQ0FBQyxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUN4RCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEtBQUssU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDO29CQUN6RSxTQUFTO2dCQUNYLENBQUM7cUJBQU0sSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLEtBQUssZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUM7b0JBQ25HLE1BQU07Z0JBQ1IsQ0FBQztZQUNILENBQUM7WUFDRCxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQzNDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsR0FBRyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdEQsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkQsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUM3QyxDQUFDO1FBRUQsb0VBQW9FO1FBQ3BFLElBQUksQ0FBRSxTQUFTLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUNqQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsU0FBUyxDQUFDLFNBQW9CLEVBQUUsS0FBVTtRQUN4QyxJQUFJLGNBQWMsR0FBbUM7WUFDbkQsV0FBVyxFQUFFLFNBQVMsQ0FBQyxXQUFXO1lBQ2xDLG1CQUFtQixFQUFFLElBQUksQ0FBQyxtQkFBbUI7U0FDOUMsQ0FBQztRQUVGLElBQUksU0FBUyxDQUFDLHFCQUFxQixLQUFLLEtBQUssRUFBRSxDQUFDO1lBQzlDLGNBQWMsQ0FBQyxhQUFhLEdBQUc7Z0JBQzdCLFVBQVUsRUFBRSxTQUFTO2dCQUNyQixRQUFRLEVBQUUsS0FBSzthQUNoQixDQUFDO1FBQ0osQ0FBQztRQUVELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsMEJBQTBCLENBQUMsU0FBb0IsRUFBRSxlQUFnQztRQUMvRSxJQUFJLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsR0FBRyxTQUFTLENBQUMsV0FBVyxHQUFHLElBQUksR0FBRyxlQUFlLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUM1RyxDQUFDO1FBRUQsSUFBSSxDQUFDLEdBQVcsQ0FBQyxDQUFDO1FBQ2xCLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3hELElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsS0FBSyxTQUFTLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxpQkFBaUIsS0FBSyxlQUFlLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztnQkFDeEwsTUFBTTtZQUNSLENBQUM7UUFDSCxDQUFDO1FBQ0QsNkRBQTZEO1FBQzdELElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMzQyxDQUFDO1FBQ0QsMERBQTBEO2FBQ3JELENBQUM7WUFDSixLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ3JGLElBQUksSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEtBQUssU0FBUyxDQUFDLFdBQVc7dUJBQzlGLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsb0JBQW9CLENBQUMsaUJBQWlCLEtBQUssZUFBZSxDQUFDLGlCQUFpQixFQUFFLENBQUM7b0JBQ2hKLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUM3RixNQUFNO2dCQUNSLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUVELHFFQUFxRTtRQUNyRSxJQUFJLENBQUUsU0FBUyxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDakMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEIsQ0FBQztJQUNILENBQUM7SUFHRDs7Ozs7T0FLRztJQUNILHdCQUF3QixDQUFDLFNBQW9CLEVBQUUsS0FBVTtRQUN2RCxJQUFJLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsR0FBRyxTQUFTLENBQUMsV0FBVyxHQUFHLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQztRQUNoRixDQUFDO1FBRUQsSUFBSSxDQUFDLEdBQVcsQ0FBQyxDQUFDO1FBQ2xCLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3hELElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsS0FBSyxTQUFTLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxpQkFBaUIsS0FBSyxLQUFLLEVBQUUsQ0FBQztnQkFDdkksTUFBTTtZQUNSLENBQUM7UUFDSCxDQUFDO1FBQ0QsNkRBQTZEO1FBQzdELElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMzQyxDQUFDO1FBQ0QsMERBQTBEO2FBQ3JELENBQUM7WUFDSixLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ3JGLElBQUksSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEtBQUssU0FBUyxDQUFDLFdBQVc7dUJBQzlGLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLEtBQUssS0FBSyxFQUFFLENBQUM7b0JBQy9GLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUM3RixNQUFNO2dCQUNSLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUVELHFFQUFxRTtRQUNyRSxJQUFJLENBQUUsU0FBUyxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDakMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEIsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILFlBQVksQ0FBQyxXQUFtQjtRQUM5QixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gseUJBQXlCLENBQUMsc0JBQThDO1FBQ3RFLElBQUksc0JBQXNCLENBQUMsd0JBQXdCLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDeEQsc0JBQXNCLENBQUMsd0JBQXdCLEdBQUcsU0FBUyxDQUFDO1FBQzlELENBQUM7UUFFRCxLQUFLLElBQUksa0JBQWtCLElBQUksc0JBQXNCLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUMxRSxJQUFJLGtCQUFrQixDQUFDLG9CQUFvQixHQUFJLENBQUMsRUFBRSxDQUFDO2dCQUNqRCxrQkFBa0IsQ0FBQyxvQkFBb0IsR0FBRyxTQUFTLENBQUM7WUFDdEQsQ0FBQztZQUVELEtBQUssSUFBSSxTQUFTLElBQUksa0JBQWtCLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztnQkFFN0QsSUFBSSxTQUFTLENBQUMsV0FBVyxHQUFJLENBQUMsRUFBRSxDQUFDO29CQUMvQixTQUFTLENBQUMsV0FBVyxHQUFHLFNBQVMsQ0FBQztnQkFDcEMsQ0FBQztnQkFFRCxJQUFJLFNBQVMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO29CQUMvQixLQUFLLElBQUksZUFBZSxJQUFJLFNBQVMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO3dCQUN2RCxPQUFPLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQzt3QkFFMUIsSUFBSSxlQUFlLENBQUMsV0FBVyxHQUFJLENBQUMsRUFBRSxDQUFDOzRCQUNyQyxlQUFlLENBQUMsV0FBVyxHQUFHLFNBQVMsQ0FBQzt3QkFDMUMsQ0FBQzt3QkFDRCxJQUFJLGVBQWUsQ0FBQyxpQkFBaUIsR0FBSSxDQUFDLEVBQUUsQ0FBQzs0QkFDM0MsZUFBZSxDQUFDLGlCQUFpQixHQUFHLFNBQVMsQ0FBQzt3QkFDaEQsQ0FBQztvQkFDSCxDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILG9CQUFvQixDQUFDLGFBQXdDO1FBQzNELElBQUksYUFBYSxDQUFDLHdCQUF3QixLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDbEQsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsSUFBSSxJQUFJLEdBQVcsYUFBYSxDQUFDLG1DQUFtQyxHQUFHLElBQUksR0FBRyxhQUFhLENBQUMsb0JBQW9CLENBQUM7UUFFakgsSUFBSSxhQUFhLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDNUIsSUFBSSxJQUFJLEtBQUssR0FBRyxhQUFhLENBQUMsY0FBYyxDQUFDO1FBQy9DLENBQUM7UUFDRCxJQUFJLGFBQWEsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUM1QixJQUFJLElBQUksS0FBSyxHQUFHLGFBQWEsQ0FBQyxjQUFjLENBQUM7UUFDL0MsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELDRCQUE0QixDQUFDLEdBQTJCO1FBQ3RELElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNULE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFFRCxJQUFJLEdBQUcsR0FBeUQ7WUFDOUQsd0JBQXdCLEVBQUUsR0FBRyxDQUFDLHdCQUF3QjtZQUN0RCxvQkFBb0IsRUFBRSxHQUFHLENBQUMsb0JBQW9CO1lBQzlDLDRCQUE0QixFQUFFLEdBQUcsQ0FBQyw0QkFBNEI7WUFDOUQsU0FBUyxFQUFFLEdBQUcsQ0FBQyxTQUFTO1lBQ3hCLFNBQVMsRUFBRSxHQUFHLENBQUMsU0FBUztTQUN6QixDQUFDO1FBRUYsSUFBSSxJQUFJLENBQUMsMkJBQTJCLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUNoRCxHQUFHLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxDQUFDLDJCQUEyQixDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQVEsRUFBRSxFQUFFO2dCQUN6RixPQUFPLEdBQUcsQ0FBQyxvQkFBb0IsS0FBSyxHQUFHLENBQUMsb0JBQW9CLENBQUM7WUFDL0QsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsb0JBQW9CLENBQUM7UUFDN0IsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLG1DQUFtQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7WUFDeEQsSUFBSSxNQUFNLEdBQVUsSUFBSSxDQUFDLG1DQUFtQyxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQVcsRUFBRSxFQUFFO2dCQUM3RixPQUFPLE1BQU0sQ0FBQyw0QkFBNEIsS0FBSyxHQUFHLENBQUMsNEJBQTRCLENBQUM7WUFDbEYsQ0FBQyxDQUFDLENBQUM7WUFDSCxHQUFHLENBQUMsbUNBQW1DLEdBQUcsQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQzlHLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQ3ZDLElBQUksTUFBTSxHQUFVLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFXLEVBQUUsRUFBRTtnQkFDNUUsT0FBTyxNQUFNLENBQUMsb0JBQW9CLEtBQUssR0FBRyxDQUFDLG9CQUFvQjt1QkFDMUQsTUFBTSxDQUFDLDRCQUE0QixLQUFLLEdBQUcsQ0FBQyw0QkFBNEI7dUJBQ3hFLE1BQU0sQ0FBQyxTQUFTLEtBQUssR0FBRyxDQUFDLFNBQVMsQ0FBQztZQUMxQyxDQUFDLENBQUMsQ0FBQztZQUNILEdBQUcsQ0FBQyxjQUFjLEdBQUcsQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ3JGLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQ3ZDLElBQUksTUFBTSxHQUFVLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFXLEVBQUUsRUFBRTtnQkFDNUUsT0FBTyxNQUFNLENBQUMsb0JBQW9CLEtBQUssR0FBRyxDQUFDLG9CQUFvQjt1QkFDMUQsTUFBTSxDQUFDLDRCQUE0QixLQUFLLEdBQUcsQ0FBQyw0QkFBNEI7dUJBQ3hFLE1BQU0sQ0FBQyxTQUFTLEtBQUssR0FBRyxDQUFDLFNBQVM7dUJBQ2xDLE1BQU0sQ0FBQyxTQUFTLEtBQUssR0FBRyxDQUFDLFNBQVMsQ0FBQztZQUMxQyxDQUFDLENBQUMsQ0FBQztZQUNILEdBQUcsQ0FBQyxjQUFjLEdBQUcsQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ3JGLENBQUM7UUFFRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRCxzQkFBc0IsQ0FBQyxJQUFZO1FBQ2pDLE9BQU8sSUFBSSxDQUFDLG1DQUFtQyxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQVcsRUFBRSxFQUFFO1lBQ2hGLE9BQU8sTUFBTSxDQUFDLDRCQUE0QixLQUFLLElBQUksQ0FBQztRQUN0RCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNSLENBQUM7SUFFRCxpQ0FBaUM7UUFDL0IsT0FBTyxJQUFJLENBQUMsOEJBQThCLENBQUM7SUFDN0MsQ0FBQztJQUVELGFBQWEsQ0FBQyxvQkFBNEIsRUFBRSw0QkFBb0M7UUFDOUUsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBUyxFQUFFLEVBQUU7WUFDN0QsT0FBTyxJQUFJLENBQUMsb0JBQW9CLEtBQUssb0JBQW9CLElBQUksSUFBSSxDQUFDLDRCQUE0QixLQUFLLDRCQUE0QixDQUFDO1FBQ2xJLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGFBQWEsQ0FBQyxvQkFBNEIsRUFBRSw0QkFBb0MsRUFBRSxTQUFpQjtRQUNqRyxPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFTLEVBQUUsRUFBRTtZQUM3RCxPQUFPLElBQUksQ0FBQyxvQkFBb0IsS0FBSyxvQkFBb0I7bUJBQ3BELElBQUksQ0FBQyw0QkFBNEIsS0FBSyw0QkFBNEI7bUJBQ2xFLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxDQUFDO1FBQ3BDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxXQUFXO1FBQ1QsT0FBTyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDekIsQ0FBQzs4R0FsNUNVLGdCQUFnQixtR0FpRFAsa0JBQWtCO2tIQWpEM0IsZ0JBQWdCOzsyRkFBaEIsZ0JBQWdCO2tCQUQ1QixVQUFVOzswQkFrREksTUFBTTsyQkFBQyxrQkFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdCwgSW5qZWN0YWJsZSwgSW5qZWN0aW9uVG9rZW4sIGlzRGV2TW9kZX0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHtIdHRwQ2xpZW50LCBIdHRwUGFyYW1zfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uL2h0dHBcIjtcclxuaW1wb3J0IHtSb3V0ZXJ9IGZyb20gXCJAYW5ndWxhci9yb3V0ZXJcIjtcclxuXHJcbmltcG9ydCB7QmVoYXZpb3JTdWJqZWN0LCBmb3JrSm9pbiwgT2JzZXJ2YWJsZSwgU3ViamVjdH0gZnJvbSBcInJ4anNcIjtcclxuXHJcbmltcG9ydCB7RGljdGlvbmFyeVNlcnZpY2V9IGZyb20gXCJAaHVudHNtYW4tY2FuY2VyLWluc3RpdHV0ZS9kaWN0aW9uYXJ5LXNlcnZpY2VcIjtcclxuXHJcbmltcG9ydCB7QXR0cmlidXRlfSBmcm9tIFwiLi4vbW9kZWwvYXR0cmlidXRlLmVudGl0eVwiO1xyXG5pbXBvcnQge0F0dHJpYnV0ZUNob2ljZX0gZnJvbSBcIi4uL21vZGVsL2F0dHJpYnV0ZS1jaG9pY2UuZW50aXR5XCI7XHJcbmltcG9ydCB7QXR0cmlidXRlVmFsdWV9IGZyb20gXCIuLi9tb2RlbC9hdHRyaWJ1dGUtdmFsdWUuZW50aXR5XCI7XHJcbmltcG9ydCB7QXR0cmlidXRlQ29uZmlndXJhdGlvbn0gZnJvbSBcIi4uL21vZGVsL2F0dHJpYnV0ZS1jb25maWd1cmF0aW9uLmVudGl0eVwiO1xyXG5pbXBvcnQge0F0dHJpYnV0ZVZhbHVlU2V0fSBmcm9tIFwiLi4vbW9kZWwvYXR0cmlidXRlLXZhbHVlLXNldC5lbnRpdHlcIjtcclxuaW1wb3J0IHtBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPfSBmcm9tIFwiLi4vbW9kZWwvYXR0cmlidXRlLWNvbmZpZ3VyYXRpb24uZHRvXCI7XHJcbmltcG9ydCB7R3JhcGhpY2FsQXR0cmlidXRlfSBmcm9tIFwiLi4vbW9kZWwvZ3JhcGhpY2FsLWF0dHJpYnV0ZS5lbnRpdHlcIjtcclxuaW1wb3J0IHtBdHRyaWJ1dGVDb250YWluZXJ9IGZyb20gXCIuLi9tb2RlbC9hdHRyaWJ1dGUtY29udGFpbmVyLmVudGl0eVwiO1xyXG5pbXBvcnQge0F0dHJpYnV0ZVZhbHVlR3JpZFJvd30gZnJvbSBcIi4uL21vZGVsL2F0dHJpYnV0ZS12YWx1ZS1ncmlkLXJvdy5lbnRpdHlcIjtcclxuaW1wb3J0IHtQcmVFdmFsRFRPfSBmcm9tIFwiLi4vbW9kZWwvcHJlLWV2YWwuZHRvXCI7XHJcbmltcG9ydCB7RGljdGlvbmFyeUVudHJpZXNEVE99IGZyb20gXCIuLi9tb2RlbC9kaWN0aW9uYXJ5LWVudHJpZXMuZHRvXCI7XHJcblxyXG5cclxuZXhwb3J0IGxldCBBVFRSSUJVVEVfRU5EUE9JTlQgPSBuZXcgSW5qZWN0aW9uVG9rZW48c3RyaW5nPihcImF0dHJpYnV0ZUVuZHBvaW50XCIpO1xyXG5leHBvcnQgY29uc3QgQk9PTEVBTjogc3RyaW5nW10gPSBbXCJOXCIsIFwiWVwiXTtcclxuZXhwb3J0IGNvbnN0IEVYVEVOREVEX0JPT0xFQU46IHN0cmluZ1tdID0gW1wiTlwiLCBcIllcIiwgXCJVXCJdO1xyXG5cclxuLyoqXHJcbiAqIEEgc2VydmljZSBjcmVhdGVkIGZvciBlYWNoIGF0dHJpYnV0ZSBjb25maWd1cmF0aW9uIGluc3RhbmNlLiAgVGhpcyBtYWtlcyBjYWxscyB0byB0aGUgYmFja2VuZCB0byBnZXQgdGhlIGNvbmZpZ3VyYXRpb25cclxuICogYW5kIHZhbHVlIHNldC4gIEl0IGFsc28gc3RvcmVzIGNvbW1vbiBkYXRhIHRoYXQgZGlmZmVyZW50IGF0dHJpYnV0ZXMgbWlnaHQgbmVlZCAoZS5nLiBhIGxpc3Qgb2YgYXR0cmlidXRlIGNob2ljZXMpLlxyXG4gKi9cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgQXR0cmlidXRlU2VydmljZSB7XHJcblxyXG4gIG5ld0F0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb247XHJcbiAgaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uOiBudW1iZXI7XHJcbiAgaWRGaWx0ZXIxOiBudW1iZXI7XHJcbiAgaWRGaWx0ZXIyOiBudW1iZXI7XHJcbiAgaWRBdHRyaWJ1dGVWYWx1ZVNldDogbnVtYmVyO1xyXG4gIGlkUGFyZW50T2JqZWN0OiBudW1iZXI7XHJcbiAgYm91bmREYXRhOiBhbnk7XHJcblxyXG4gIGF0dHJpYnV0ZUNvbnRleHRMb2FkaW5nU3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XHJcblxyXG4gIGF0dHJpYnV0ZUNvbnRleHRMaXN0U3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGFueVtdPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8YW55W10+KHVuZGVmaW5lZCk7XHJcbiAgYXR0cmlidXRlU2VjdXJpdHlDb250ZXh0TGlzdFN1YmplY3Q6IEJlaGF2aW9yU3ViamVjdDxhbnlbXT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGFueVtdPih1bmRlZmluZWQpO1xyXG4gIGZpbHRlcjFMaXN0U3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGFueVtdPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8YW55W10+KHVuZGVmaW5lZCk7XHJcbiAgZmlsdGVyMkxpc3RTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8YW55W10+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxhbnlbXT4odW5kZWZpbmVkKTtcclxuICBkaWN0aW9uYXJ5TGlzdFN1YmplY3Q6IEJlaGF2aW9yU3ViamVjdDxhbnlbXT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGFueVtdPih1bmRlZmluZWQpO1xyXG5cclxuXHJcbiAgcG9zdENvbmZpZ3VyYXRpb25TdWJqZWN0OiBTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcclxuICBhdHRyaWJ1dGVDb25maWd1cmF0aW9uRGltZW5zaW9uU3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGFueT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGFueT4odW5kZWZpbmVkKTtcclxuXHJcbiAgYXR0cmlidXRlQ29uZmlndXJhdGlvbkxpc3RTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8QXR0cmlidXRlQ29uZmlndXJhdGlvbkRUT1tdPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8QXR0cmlidXRlQ29uZmlndXJhdGlvbkRUT1tdPih1bmRlZmluZWQpO1xyXG4gIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25MaXN0TG9hZGluZ1N1YmplY3Q6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xyXG5cclxuICBhdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPU3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPPih1bmRlZmluZWQpO1xyXG5cclxuICBhdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxBdHRyaWJ1dGVDb25maWd1cmF0aW9uPih1bmRlZmluZWQpO1xyXG4gIGF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlU2V0PiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8QXR0cmlidXRlVmFsdWVTZXQ+KHVuZGVmaW5lZCk7XHJcbiAgYXR0cmlidXRlVmFsdWVQdXNoZWRTdWJqZWN0OiBTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlPiA9IG5ldyBTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlPigpO1xyXG5cclxuICBsb2FkaW5nU3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XHJcblxyXG4gIGF0dHJpYnV0ZU1hcDogTWFwPG51bWJlciwgQXR0cmlidXRlPiA9IG5ldyBNYXA8bnVtYmVyLCBBdHRyaWJ1dGU+KCk7XHJcblxyXG4gIHdpZHRoOiBudW1iZXI7XHJcblxyXG4gIGNvbnRhaW5lclVwZGF0ZWQ6IFN1YmplY3Q8Ym9vbGVhbj4gPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xyXG4gIGdyaWRSb3dTYXZlZDogU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZUdyaWRSb3c+ID0gbmV3IFN1YmplY3Q8QXR0cmlidXRlVmFsdWVHcmlkUm93PigpO1xyXG4gIGdyaWRSb3dEZWxldGVkOiBTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlR3JpZFJvdz4gPSBuZXcgU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZUdyaWRSb3c+KCk7XHJcbiAgZGlydHk6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xyXG4gIHVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXM6IEF0dHJpYnV0ZVZhbHVlW10gPSBbXTtcclxuICBzbGljZWRBdHRyaWJ1dGVWYWx1ZXM6IEF0dHJpYnV0ZVZhbHVlW10gPSBbXTtcclxuXHJcbiAgcHJpdmF0ZSB1bmlxdWVJZDogbnVtYmVyID0gMDtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBkaWN0aW9uYXJ5U2VydmljZTogRGljdGlvbmFyeVNlcnZpY2UsXHJcbiAgICAgICAgICAgICAgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50LFxyXG4gICAgICAgICAgICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXHJcbiAgICAgICAgICAgICAgQEluamVjdChBVFRSSUJVVEVfRU5EUE9JTlQpIHByaXZhdGUgYXR0cmlidXRlRW5kcG9pbnQ6IHN0cmluZykge1xyXG4gICAgaWYgKGlzRGV2TW9kZSgpKSB7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoXCJDcmVhdGVkIE5ldyBBdHRyaWJ1dGVTZXJ2aWNlXCIpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2V0Qm91bmREYXRhKGJvdW5kRGF0YTogYW55KSB7XHJcbiAgICB0aGlzLmJvdW5kRGF0YSA9IGJvdW5kRGF0YTtcclxuXHJcbiAgICBpZiAodGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKSkge1xyXG4gICAgICB0aGlzLm5vdGlmeUF0dHJpYnV0ZXMoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGdldEF0dHJpYnV0ZVZhbHVlQ291bnRCeUF0dHJpYnV0ZShpZEF0dHJpYnV0ZTogbnVtYmVyKTogT2JzZXJ2YWJsZTxudW1iZXI+IHtcclxuICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PG51bWJlcj4odGhpcy5hdHRyaWJ1dGVFbmRwb2ludCArIFwiYXR0cmlidXRlLXZhbHVlLWNvdW50XCIsIHtwYXJhbXM6IG5ldyBIdHRwUGFyYW1zKCkuc2V0KFwiaWRBdHRyaWJ1dGVcIiwgaWRBdHRyaWJ1dGUudG9TdHJpbmcoKSl9KTtcclxuICB9XHJcblxyXG4gIGdldEF0dHJpYnV0ZVZhbHVlQ291bnRCeUNvbnRhaW5lcihpZEF0dHJpYnV0ZUNvbnRhaW5lcjogbnVtYmVyKTogT2JzZXJ2YWJsZTxudW1iZXI+IHtcclxuICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PG51bWJlcj4odGhpcy5hdHRyaWJ1dGVFbmRwb2ludCArIFwiYXR0cmlidXRlLXZhbHVlLWNvdW50XCIsIHtwYXJhbXM6IG5ldyBIdHRwUGFyYW1zKCkuc2V0KFwiaWRBdHRyaWJ1dGVDb250YWluZXJcIiwgaWRBdHRyaWJ1dGVDb250YWluZXIudG9TdHJpbmcoKSl9KTtcclxuICB9XHJcblxyXG4gIGdldERpY3Rpb25hcnlWYWx1ZUNvdW50KGlkQXR0cmlidXRlRGljdGlvbmFyeTogbnVtYmVyKTogT2JzZXJ2YWJsZTxudW1iZXI+IHtcclxuICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PG51bWJlcj4odGhpcy5hdHRyaWJ1dGVFbmRwb2ludCArIFwiYXR0cmlidXRlLWRpY3Rpb25hcnktY291bnRcIiwge3BhcmFtczogbmV3IEh0dHBQYXJhbXMoKS5zZXQoXCJpZEF0dHJpYnV0ZURpY3Rpb25hcnlcIiwgaWRBdHRyaWJ1dGVEaWN0aW9uYXJ5LnRvU3RyaW5nKCkpfSk7XHJcbiAgfVxyXG5cclxuICBmZXRjaEF0dHJpYnV0ZUNvbnRleHQoKTogdm9pZCB7XHJcbiAgICB0aGlzLmF0dHJpYnV0ZUNvbnRleHRMb2FkaW5nU3ViamVjdC5uZXh0KHRydWUpO1xyXG5cclxuICAgIGZvcmtKb2luKFtcclxuICAgICAgdGhpcy5kaWN0aW9uYXJ5U2VydmljZS5nZXREaWN0aW9uYXJ5RW50cmllcyhcImhjaS5yaS5hdHRyLm1vZGVsLkF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dFwiKSxcclxuICAgICAgdGhpcy5kaWN0aW9uYXJ5U2VydmljZS5nZXREaWN0aW9uYXJ5RW50cmllcyhcImhjaS5yaS5hdHRyLm1vZGVsLkF0dHJpYnV0ZUNvbnRleHRcIiksXHJcbiAgICAgIHRoaXMuZGljdGlvbmFyeVNlcnZpY2UuZ2V0RGljdGlvbmFyeUVudHJpZXMoXCJoY2kucmkuYXR0ci5tb2RlbC5GaWx0ZXIxXCIpLFxyXG4gICAgICB0aGlzLmRpY3Rpb25hcnlTZXJ2aWNlLmdldERpY3Rpb25hcnlFbnRyaWVzKFwiaGNpLnJpLmF0dHIubW9kZWwuRmlsdGVyMlwiKSxcclxuICAgICAgdGhpcy5kaWN0aW9uYXJ5U2VydmljZS5nZXREaWN0aW9uYXJ5RW50cmllcyhcImhjaS5yaS5hdHRyLm1vZGVsLkF0dHJpYnV0ZURpY3Rpb25hcnlcIilcclxuICAgIF0pLnN1YnNjcmliZSgocmVzcG9uc2VzOiBhbnlbXSkgPT4ge1xyXG5cclxuICAgICAgdGhpcy5kaWN0aW9uYXJ5TGlzdFN1YmplY3QubmV4dChyZXNwb25zZXNbNF0pO1xyXG4gICAgICB0aGlzLmZpbHRlcjFMaXN0U3ViamVjdC5uZXh0KHJlc3BvbnNlc1syXSk7XHJcbiAgICAgIHRoaXMuZmlsdGVyMkxpc3RTdWJqZWN0Lm5leHQocmVzcG9uc2VzWzNdKTtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVDb250ZXh0TGlzdFN1YmplY3QubmV4dChyZXNwb25zZXNbMV0pO1xyXG5cclxuICAgICAgcmVzcG9uc2VzWzBdLnNvcnQodGhpcy5zb3J0QXR0cmlidXRlU2VjdXJpdHlDb250ZXh0TGlzdCk7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlU2VjdXJpdHlDb250ZXh0TGlzdFN1YmplY3QubmV4dChyZXNwb25zZXNbMF0pO1xyXG5cclxuICAgICAgdGhpcy5hdHRyaWJ1dGVDb250ZXh0TG9hZGluZ1N1YmplY3QubmV4dChmYWxzZSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vR2V0cyB0aGUgZGljdGlvbmFyeSBlbnRyaWVzIGZyb20gdGhlIG1hcCAoc28gd2UgZG9uJ3QgbG9hZCBvdmVyIGFuZCBvdmVyIGFuZCBvdmVyIGZvciB0aGUgc2FtZSBkaWN0aW9uYXJ5KVxyXG4gIGdldERpY3Rpb25hcnlFbnRyaWVzKGF0dHJpYnV0ZTogQXR0cmlidXRlLCB2YWx1ZXM6IEF0dHJpYnV0ZVZhbHVlW10sIGdyb3VwQXR0cmlidXRlUm93SWQ/OiBudW1iZXIsIHJlZmVyZW5jZWRBdHRyaWJ1dGVWYWx1ZT86IEF0dHJpYnV0ZVZhbHVlKTogT2JzZXJ2YWJsZTxEaWN0aW9uYXJ5RW50cmllc0RUTz4ge1xyXG4gICAgbGV0IGJzID0gbmV3IFN1YmplY3Q8RGljdGlvbmFyeUVudHJpZXNEVE8+KCk7XHJcblxyXG4gICAgLy9IYW5kbGUgWFBBVEhcclxuICAgIGlmIChhdHRyaWJ1dGUuYXR0cmlidXRlRGljdGlvbmFyeS54cGF0aCkge1xyXG4gICAgICBsZXQgZW50cmllc0RUTyA9IG5ldyBEaWN0aW9uYXJ5RW50cmllc0RUTygpO1xyXG4gICAgICBsZXQgeHBhdGggPSBhdHRyaWJ1dGUuYXR0cmlidXRlRGljdGlvbmFyeS54cGF0aDtcclxuXHJcbiAgICAgIC8vRmlsdGVyZWQgYnkgYW5vdGhlciBkaWN0aW9uYXJ5PyBQYXJzZSB0byBnZXQgYXJyYXkgb2YgYWxsIGRpY3Rpb25hcnkgY2xhc3MgbmFtZXMgbmVlZGVkXHJcbiAgICAgIGxldCBkaWN0Q2xhc3Nlczogc3RyaW5nW10gPSBbXTtcclxuICAgICAgbGV0IHBvcyA9IDA7XHJcbiAgICAgIHdoaWxlICh4cGF0aC5pbmRleE9mKFwiL0RpY3Rpb25hcmllcy9EaWN0aW9uYXJ5XCIsIHBvcykgPj0gMCkge1xyXG4gICAgICAgIGxldCBzdGFydCA9IHhwYXRoLmluZGV4T2YoXCIvRGljdGlvbmFyaWVzL0RpY3Rpb25hcnlcIiwgcG9zKTtcclxuICAgICAgICBzdGFydCA9IHhwYXRoLmluZGV4T2YoXCInXCIsIHN0YXJ0KTtcclxuICAgICAgICBsZXQgZW5kID0geHBhdGguaW5kZXhPZihcIidcIiwgc3RhcnQgKyAxKTtcclxuICAgICAgICBkaWN0Q2xhc3Nlcy5wdXNoKGF0dHJpYnV0ZS5hdHRyaWJ1dGVEaWN0aW9uYXJ5LnhwYXRoLnN1YnN0cmluZyhzdGFydCArIDEsIGVuZCkpXHJcbiAgICAgICAgcG9zID0gZW5kO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvL1BvdGVudGlhbGx5IGxvYWQgbXVsdGlwbGUgZGljdGlvbmFyaWVzXHJcbiAgICAgIGxldCBmb3JrQ2FsbHMgPSBbXTtcclxuICAgICAgZm9yIChsZXQgY2xhc3NOYW1lIG9mIGRpY3RDbGFzc2VzKSB7XHJcbiAgICAgICAgZm9ya0NhbGxzLnB1c2godGhpcy5kaWN0aW9uYXJ5U2VydmljZS5nZXREaWN0aW9uYXJ5RW50cmllc0FzWE1MKGNsYXNzTmFtZSkpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvL0RlYWwgd2l0aCB0aGUgcmVzdWx0cyB0b2dldGhlclxyXG4gICAgICBmb3JrSm9pbihmb3JrQ2FsbHMpLnN1YnNjcmliZSgocmVzcG9uc2VzOiBhbnlbXSkgPT4ge1xyXG4gICAgICAgIC8vV2UncmUgb25seSBnb2luZyB0byBkbyB4cGF0aCBvbiB0aGUgeG1sIGZvciB0aGUgZmlyc3QgZGljdGlvbmFyeVxyXG4gICAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcclxuICAgICAgICBsZXQgZG9jID0gcGFyc2VyLnBhcnNlRnJvbVN0cmluZyhyZXNwb25zZXNbMF0sIFwiYXBwbGljYXRpb24veG1sXCIpO1xyXG5cclxuICAgICAgICAvL0hhdmUgdG8gZXZhbHVhdGUgc3ViLWV4cHJlc3Npb24uIFRoaXMgZG9lc24ndCBhY3R1YWxseSBzdXBwb3J0IGV4cHJlc3Npb25zIGxpa2UgW0B4ID0gKC94cGF0aC1zdWItZXhwcmVzc2lvbildXHJcbiAgICAgICAgbGV0IHNlY29uZGFyeVhtbCA9IHVuZGVmaW5lZDtcclxuICAgICAgICBpZiAocmVzcG9uc2VzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgICAgIHNlY29uZGFyeVhtbCA9IHJlc3BvbnNlc1sxXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vUHJlLWV2YWx1YXRlIGFuZCBzaW1wbGlmeSBYUEFUSFxyXG4gICAgICAgIGxldCBkdG86UHJlRXZhbERUTyA9IHRoaXMucHJlRXZhbHVhdGVYcGF0aChhdHRyaWJ1dGUuYXR0cmlidXRlRGljdGlvbmFyeS54cGF0aCwgc2Vjb25kYXJ5WG1sLCBncm91cEF0dHJpYnV0ZVJvd0lkLCByZWZlcmVuY2VkQXR0cmlidXRlVmFsdWUpO1xyXG5cclxuICAgICAgICAvL0V2YWx1YXRlIFhQQVRIIGV4cHJlc3Npb25cclxuICAgICAgICBsZXQgZW50cmllcyA9IFtdO1xyXG4gICAgICAgIGVudHJpZXNEVE8uZW50cmllc0luY2x1ZGVTZWxlY3RlZFZhbHVlID0gZmFsc2U7XHJcblxyXG4gICAgICAgIHRyeXtcclxuICAgICAgICAgIGxldCB4UGF0aFJlc3VsdCA9IGRvY3VtZW50LmV2YWx1YXRlKGR0by5leHByZXNzaW9uLCBkb2MsIG51bGwsIFhQYXRoUmVzdWx0LkFOWV9UWVBFLCBudWxsKTtcclxuXHJcbiAgICAgICAgICAvL0l0ZXJhdGUgeHBhdGggcmVzdWx0cyAobm9kZXMpXHJcbiAgICAgICAgICB2YXIgbm9kZSA9IG51bGw7XHJcbiAgICAgICAgICB3aGlsZShub2RlID0geFBhdGhSZXN1bHQuaXRlcmF0ZU5leHQoKSkge1xyXG5cclxuICAgICAgICAgICAgbGV0IGVudHJ5ID0gdGhpcy5nZXRKc29uRW50cnlGcm9tTm9kZShub2RlKTtcclxuICAgICAgICAgICAgZW50cmllcy5wdXNoKGVudHJ5KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9Y2F0Y2ggKGUpIHtcclxuICAgICAgICAgIC8vIE5vIG1hdGNoaW5nIGVudHJpZXMgaGVyZS5cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vV2hhdCBhYm91dCBkaWN0aW9uYXJ5IGVudHJpZXMgd2hlcmUgaXNBY3RpdmU9J04nLCBidXQgdGhlIGlkIHdhcyB1c2VkIGluIGEgcHJldmlvdXNseSBzYXZlZCB2YWx1ZT9cclxuICAgICAgICAvL1dlIGFkZCB0aGF0IHZhbHVlIHRvIHRoZSBkcm9wZG93biwgaW4gdGhhdCBjYXNlLCBzbyBpdCBjYW4gYmUgc2VsZWN0ZWRcclxuICAgICAgICAvL1JlZmVyZW5jZWRBdHRyaWJ1dGVWYWx1ZSBvbmx5IGdldHMgcGFzc2VkIGluIHdoZW4gdGhlIGZpbHRlciBhdHRyaWJ1dGUgY2hhbmdlcy4gSW4gdGhhdCBzY2VuYXJpbyB3ZSBkbyBub3Qgd2FudCB0byBhZGQgdGhlIG9sZCB2YWx1ZSB0byB0aGUgbGlzdFxyXG4gICAgICAgIGlmIChhdHRyaWJ1dGUuaXNNdWx0aVZhbHVlICE9PSBcIllcIikge1xyXG4gICAgICAgICAgZm9yIChsZXQgYXYgb2YgdmFsdWVzKSB7XHJcbiAgICAgICAgICAgIGxldCBwcmVzZW50OmJvb2xlYW4gPSBmYWxzZTtcclxuICAgICAgICAgIFxyXG4gICAgICAgICAgICBpZiAoYXYgJiYgISByZWZlcmVuY2VkQXR0cmlidXRlVmFsdWUpIHtcclxuICAgICAgICAgICAgICBmb3IodmFyIGkgPSBlbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZW50cmllc1tpXS52YWx1ZSA9PT0gYXYudmFsdWVJZERpY3Rpb25hcnkpIHtcclxuICAgICAgICAgICAgICAgICAgcHJlc2VudCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAvL0lmIHRoZSBjdXJyZW50bHkgc2F2ZWQgdmFsdWUgaXMgbm90IGluIHRoZSBsaXN0LCBhZGQgaXQuXHJcbiAgICAgICAgICAgICAgaWYgKCEgcHJlc2VudCkge1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgbGV0IHhwYXRoID0gXCIvRGljdGlvbmFyaWVzL0RpY3Rpb25hcnlbQGNsYXNzTmFtZT0nXCIgKyBhdHRyaWJ1dGUuYXR0cmlidXRlRGljdGlvbmFyeS5jbGFzc05hbWUgKyBcIiddL0RpY3Rpb25hcnlFbnRyeVtAdmFsdWU9J1wiICsgYXYudmFsdWVJZERpY3Rpb25hcnkgKyBcIiddXCI7XHJcbiAgICAgICAgICAgICAgICAvL1RoZSBlbnRyeSB3YXMgcHJvYmFibHkgYWxyZWFkeSBsb2FkZWQsIGJ1dCBleGNsdWRlZCBieSB0aGUgeHBhdGguIFdlIGNhbiB1c2UgdGhhdC5cclxuICAgICAgXHJcbiAgICAgICAgICAgICAgICBsZXQgbm9kZSA9IGRvY3VtZW50LmV2YWx1YXRlKHhwYXRoLCBkb2MsIG51bGwsIFhQYXRoUmVzdWx0LkFOWV9VTk9SREVSRURfTk9ERV9UWVBFLCBudWxsKS5zaW5nbGVOb2RlVmFsdWU7XHJcbiAgICAgICAgICAgICAgICBpZiAobm9kZSkge1xyXG4gICAgICAgICAgICAgICAgICBlbnRyaWVzLnB1c2godGhpcy5nZXRKc29uRW50cnlGcm9tTm9kZShub2RlKSk7XHJcbiAgICAgICAgICAgICAgICAgIGVudHJpZXNEVE8uZW50cmllc0luY2x1ZGVTZWxlY3RlZFZhbHVlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG5cclxuICAgICAgICAvL1NldCB0aGUgYmVoYXZpb3Igc3ViamVjdCB3aXRoIHRoZSBmaWx0ZXJlZCB2YWx1ZXMgZm9yIHRoZSBkaWN0aW9uYXJ5XHJcbiAgICAgICAgZW50cmllc0RUTy5lbnRyaWVzID0gZW50cmllcztcclxuICAgICAgICBlbnRyaWVzRFRPLnJlZmVyZW5jZWRBdHRyaWJ1dGUgPSBkdG8ucmVmZXJlbmNlZEF0dHJpYnV0ZTtcclxuICAgICAgICBicy5uZXh0KGVudHJpZXNEVE8pO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICB9XHJcbiAgICAvL05vbi14cGF0aFxyXG4gICAgZWxzZSB7XHJcbiAgICAgIC8vRGljdGlvbmF5U2VydmljZSBqdXN0IHVzZWQgaHR0cCBnZXQsIHNvIHNob3VsZCBub3QgbmVlZCB0byB1bnN1YnNjcmliZSwgc2luY2UgaHR0cCBkb2VzIHRoYXRcclxuICAgICAgdGhpcy5kaWN0aW9uYXJ5U2VydmljZS5nZXREaWN0aW9uYXJ5RHJvcGRvd25FbnRyaWVzKGF0dHJpYnV0ZS5hdHRyaWJ1dGVEaWN0aW9uYXJ5LmNsYXNzTmFtZSkuc3Vic2NyaWJlKChlbnRyaWVzOiBhbnlbXSkgPT4ge1xyXG4gICAgICAgIC8vTWFrZSB2YWx1ZSBmaWVsZHNcclxuICAgICAgICBmb3IodmFyIGkgPSBlbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgICAgICBlbnRyaWVzW2ldLnZhbHVlID0gZW50cmllc1tpXS5pZC50b1N0cmluZygpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IGVudHJpZXNEVE8gPSBuZXcgRGljdGlvbmFyeUVudHJpZXNEVE8oKTtcclxuICAgICAgICBlbnRyaWVzRFRPLmVudHJpZXMgPSBlbnRyaWVzO1xyXG4gICAgICAgIGVudHJpZXNEVE8uZW50cmllc0luY2x1ZGVTZWxlY3RlZFZhbHVlID0gdHJ1ZTsgLy9BIGJpdCBvZiBhbiBhc3N1bXB0aW9uLCBidXQgaWYgaXQgaXNuJ3QgZmlsdGVyZWQsIGl0IGhhZCBiZXR0ZXIgaW5jbHVkZSBhbGwgdGhlIHZhbHVlcyFcclxuICAgICAgICBicy5uZXh0KGVudHJpZXNEVE8pO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gYnM7XHJcbiAgfVxyXG5cclxuICBnZXRKc29uRW50cnlGcm9tTm9kZShub2RlOiBhbnkpOiBhbnkge1xyXG4gICAgLy9DcmVhdGUgSlNPTiBvYmplY3RzIGZyb20gdGhlIG5vZGVzXHJcbiAgICBsZXQgZW50cnk6IGFueSA9IHt9O1xyXG4gICAgZm9yKHZhciBpID0gbm9kZS5hdHRyaWJ1dGVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgIGVudHJ5W25vZGUuYXR0cmlidXRlc1tpXS5uYW1lXSA9IG5vZGUuYXR0cmlidXRlc1tpXS52YWx1ZTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gZW50cnk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByZUV2YWx1YXRlWHBhdGgoeHBhdGg6IHN0cmluZywgc2Vjb25kYXJ5WG1sOiBzdHJpbmcsIGdyb3VwQXR0cmlidXRlUm93SWQ6IG51bWJlciwgcmVmZXJlbmNlZEF0dHJpYnV0ZVZhbHVlOiBBdHRyaWJ1dGVWYWx1ZSk6IFByZUV2YWxEVE8ge1xyXG4gICAgbGV0IGR0bzpQcmVFdmFsRFRPID0gbmV3IFByZUV2YWxEVE8oKTtcclxuXHJcbiAgICAvL1NlY3VyaXR5QWR2aXNvci9AY29kZUNhbmNlckdyb3VwXHJcbiAgICB3aGlsZSAoeHBhdGguaW5kZXhPZihcIi9TZWN1cml0eUFkdmlzb3IvQGNvZGVDYW5jZXJHcm91cFwiKSA+PSAwKSB7XHJcbiAgICAgIHhwYXRoID0geHBhdGgucmVwbGFjZShcIi9TZWN1cml0eUFkdmlzb3IvQGNvZGVDYW5jZXJHcm91cFwiLCBcIidcIiArIHRoaXMuZ2V0QXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QoKS52YWx1ZS5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0ICsgXCInXCIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vUmVwbGFjZSBzb21lIG9mIHRoZSBjb250ZXh0IHBhcmFtZXRlcnMgJHt4LnZhbHVlfSAtIFRoaXMgaXMgbW9yZSBBbHRpbyBzcGVjaWZpYyBzdHVmZiB0aGF0IHdhcyB1c2VkIGluIENDUlxyXG4gICAgbGV0IHBhcmFtUG9zID0geHBhdGguc2VhcmNoKFwiXFxcXCR7W0EtWmEtejAtOV9dK1xcXFwudmFsdWV9XCIpO1xyXG4gICAgd2hpbGUgKHBhcmFtUG9zID49IDApIHtcclxuICAgICAgbGV0IHByZWZpeCA9IHhwYXRoLnN1YnN0cmluZygwLCBwYXJhbVBvcyk7XHJcbiAgICAgIGxldCB2YXJOYW1lID0geHBhdGguc3Vic3RyaW5nKHBhcmFtUG9zICsgMiwgeHBhdGguaW5kZXhPZihcIi5cIiwgcGFyYW1Qb3MpKTtcclxuICAgICAgbGV0IHN1ZmZpeCA9IHhwYXRoLnN1YnN0cmluZyh4cGF0aC5pbmRleE9mKFwifVwiLCBwYXJhbVBvcykgKyAxKTtcclxuXHJcbiAgICAgIHZhciBhdjtcclxuXHJcbiAgICAgIC8vSWYgdGhlcmUgSVMgYSByZWZlcmVuY2VkQXR0cmlidXRlVmFsdWUsIHdlIGNhbiB1c2UgdGhlIHZhbHVlIGRpcmVjdGx5LiBPdGhlcndpc2Ugd2UgdHJ5IHRvIGZpbmQgaXQgaW4gdGhlIEFWU1xyXG4gICAgICBpZiAoISByZWZlcmVuY2VkQXR0cmlidXRlVmFsdWUpIHtcclxuXHJcbiAgICAgICAgLy9GaW5kIHRoZSBhdHRyaWJ1dGUsIG1hdGNoaW5nIHRoZSB2YXJOYW1lLlxyXG4gICAgICAgIC8vRG8gdGhpcyBmaXJzdCwgc28gd2UgZ2V0IGEgcmVmZXJlbmNlIHRvIHRoZSByZWxhdGVkIGF0dHJpYnV0ZSwgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIHRoZXJlIGlzIGFscmVhZHkgYSB2YWx1ZVxyXG5cclxuICAgICAgICAvL0l0ZXJhdGUgYXR0cmlidXRlcyB0byBmaW5kIG9uZSB0aGF0IG1hdGNoZXMgdGhlIHZhbHVlXHJcbiAgICAgICAgdGhpcy5hdHRyaWJ1dGVNYXAuZm9yRWFjaCgoYXR0cmlidXRlOiBBdHRyaWJ1dGUpID0+IHtcclxuICAgICAgICAgIC8vQXR0cmlidXRlcyB0aGF0IG1hdGNoIHRoZSBuYW1lXHJcbiAgICAgICAgICBpZiAoYXR0cmlidXRlLmF0dHJpYnV0ZU5hbWUgPT09IHZhck5hbWUpIHtcclxuICAgICAgICAgICAgZHRvLnJlZmVyZW5jZWRBdHRyaWJ1dGUgPSBhdHRyaWJ1dGU7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAvL0lmIHRoaXMgaXMgYSBncmlkLCBsb29rIGZvciBhdHRyaWJ1dGVzIGluIHRoZSByb3dcclxuICAgICAgICAgIGlmIChhdHRyaWJ1dGUuYXR0cmlidXRlcykge1xyXG4gICAgICAgICAgICBmb3IgKGxldCBncmlkQ29sdW1uQXR0cmlidXRlICBvZiBhdHRyaWJ1dGUuYXR0cmlidXRlcykge1xyXG4gICAgICAgICAgICAgIC8vSWYgdGhlIG5hbWUgbWF0Y2hlcyBBTkQgdGhlIHZhbHVlIGluIHRoZSBBVlMgd2FzIHBhcnQgb2YgdGhlIFNBTUUgUk9XIHdlIGFyZSBldmFsdWF0aW5nIFhQQVRIIGZvciwgd2UgY2FuIHVzZSB0aGUgdmFsdWUgZm9yIGV2YWx1YXRpb25cclxuICAgICAgICAgICAgICBpZiAoZ3JpZENvbHVtbkF0dHJpYnV0ZS5hdHRyaWJ1dGVOYW1lID09PSB2YXJOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICBkdG8ucmVmZXJlbmNlZEF0dHJpYnV0ZSA9IGdyaWRDb2x1bW5BdHRyaWJ1dGU7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG5cclxuXHJcbiAgICAgICAgbGV0IGF2cyA9IHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCk7XHJcbiAgICAgICAgLy9JZiB3ZSBmb3VuZCB0aGUgYXR0cmlidXRlIGFuZCBoYXZlIHZhbHVlcy4uLlxyXG4gICAgICAgIGlmIChkdG8ucmVmZXJlbmNlZEF0dHJpYnV0ZSAmJiBhdnMpIHtcclxuXHJcbiAgICAgICAgICAvL0xvb2sgdGhyb3VnaCBhbGwgdGhlIHZhbHVlcyB0byBmaW5kIHRoZSBvbmUgZm9yIHRoZSByZWZlcmVuY2VkIGF0dHJpYnV0ZSAoYW5kIFNBTUUgZ3JpZCByb3cgaWYgaW4gYSBncmlkIHJvdylcclxuICAgICAgICAgIGF2ID0gYXZzLmF0dHJpYnV0ZVZhbHVlcy5maW5kKChhdikgPT4ge1xyXG5cclxuICAgICAgICAgICAgLy9JZiB0aGlzIGlzIGFuIEFWIGZvciBhIGdyaWQgcm93LCBpdCBtdXN0IGJlIGZvciB0aGUgc2FtZSBncmlkIHJvdyB3ZSBhcmUgbG9va2luZyBmb3JcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgZ3JvdXBBdHRyaWJ1dGVSb3dJZCAhPT0gJ3VuZGVmaW5lZCcgJiYgYXYuZ3JvdXBBdHRyaWJ1dGVSb3dJZCAhPT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCkge1xyXG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuXHJcbiAgICAgICAgICAgIC8vSWYgd2UgbG9va2VkIHVwIHRoZSBhdHRyaWJ1dGUgbWF0Y2hpbmcgdGhlIHZhbHVlIGJ5IGlkIEFORCB0aGUgbmFtZSBvZiB0aGUgYXR0cmlidXRlIGlzIHRoZSBvbmUgd2UgYXIgbG9va2luZyBmb3IgZnJvbSB0aGUgWFBBVEgsIHdlIGNhbiB1c2UgaXQgZm9yIGV2YWx1YXRpb25cclxuICAgICAgICAgICAgIC8vRm91bmQgYW4gQXR0cmlidXRlVmFsdWUgdGhhdCB0aGUgZGljdGlvbmFyeSBpcyBmaWx0ZXJlZCBieVxyXG4gICAgICAgICAgICBpZiAoZHRvLnJlZmVyZW5jZWRBdHRyaWJ1dGUuaWRBdHRyaWJ1dGUgPT09IGF2LmlkQXR0cmlidXRlKSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLy9Vc2UgdGhlIHJlZmVyZW5jZWRBdHRyaWJ1dGVWYWx1ZSBpZiBwcm92aWRlZCAodGhpcyBoYXBwZW5zIHdoZW4gYWxyZWFkeSBrbm93biwgZHVyaW5nIGNoYW5nZXMgdG8gdGhlIHJlZmVyZW5jZWQgYXR0cmlidXRlKVxyXG4gICAgICBpZiAocmVmZXJlbmNlZEF0dHJpYnV0ZVZhbHVlKSB7XHJcbiAgICAgICAgeHBhdGggPSBwcmVmaXggKyBcIidcIiArIHJlZmVyZW5jZWRBdHRyaWJ1dGVWYWx1ZS52YWx1ZSArIFwiJ1wiICsgc3VmZml4O1xyXG4gICAgICB9XHJcbiAgICAgIC8vRm91bmQgdGhlIEF0dHJpYnV0ZVZhbHVlIGZvciB0aGUgYXR0cmlidXRlIHRoYXQgdGhlIGRpY3Rpb25hcnkgaXMgZmlsdGVyZWQgYnlcclxuICAgICAgZWxzZSBpZiAoYXYpIHtcclxuICAgICAgICB4cGF0aCA9IHByZWZpeCArIFwiJ1wiICsgYXYudmFsdWUgKyBcIidcIiArIHN1ZmZpeDtcclxuICAgICAgfVxyXG4gICAgICAvL0RpZG4ndCBmaW5kIGFuIGF0dHJpYnV0ZSBmb3IgdmFyTmFtZVxyXG4gICAgICBlbHNlIHtcclxuICAgICAgICAvL01heWJlIHRoZSB2YXJOYW1lIGlzIGZyb20gZWxzZXdoZXJlIGluIHRoZSBhcHAgKG5vbi1DT0QpLCBhbmQgcHJvdmlkZWQgaW4gYm91bmREYXRhXHJcbiAgICAgICAgaWYgKHRoaXMuYm91bmREYXRhICYmIHRoaXMuYm91bmREYXRhW3Zhck5hbWVdKSB7XHJcbiAgICAgICAgICB4cGF0aCA9IHByZWZpeCArIFwiJ1wiICsgdGhpcy5ib3VuZERhdGFbdmFyTmFtZV0gKyBcIidcIiArIHN1ZmZpeDtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy9Ob3RoaW5nIG1hdGNoZXMuIENoYW5nZSB0byBlbXB0eSBzdHJpbmcuIFdpbGwgcHJvYmFibHkgcmVzdWx0IGluIE5PIGVudHJpZXMsIHdoaWNoIHdvdWxkIGJlIGNvcnJlY3QuXHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICB4cGF0aCA9IHByZWZpeCArIFwiJydcIiArIHN1ZmZpeDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHBhcmFtUG9zID0geHBhdGguc2VhcmNoKFwiXFxcXCR7W0EtWmEtejAtOV9dK1xcXFwudmFsdWV9XCIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vSGF2ZSB0byBldmFsdWF0ZSBzdWItZXhwcmVzc2lvbi4gVGhpcyBoYW5kbGVzIGV4cHJlc3Npb25zIGxpa2UgW0B4ID0gKC94cGF0aC1zdWItZXhwcmVzc2lvbildXHJcbiAgICBsZXQgaW5FeHByZXNzaW9uUG9zID0geHBhdGguc2VhcmNoKFwiXFxcXFtAW0EtWmEtejAtOV9dK1xcXFxzKj1cXFxccypcXFxcKFwiKTtcclxuXHJcbiAgICBpZiAoaW5FeHByZXNzaW9uUG9zID4gMCAmJiBzZWNvbmRhcnlYbWwpIHtcclxuICAgICAgbGV0IHByZWZpeCA9IHhwYXRoLnN1YnN0cmluZygwLCBpbkV4cHJlc3Npb25Qb3MgKyAxKTtcclxuICAgICAgbGV0IGV4cHJlc3Npb25FbmQgPSB4cGF0aC5pbmRleE9mKFwiKVwiLCBpbkV4cHJlc3Npb25Qb3MpO1xyXG4gICAgICBsZXQgdmFyaWFibGUgPSB4cGF0aC5zdWJzdHJpbmcoaW5FeHByZXNzaW9uUG9zICsgMSwgeHBhdGguaW5kZXhPZihcIj1cIiwgaW5FeHByZXNzaW9uUG9zKSk7XHJcbiAgICAgIGxldCBzdWJFeHByZXNzaW9uID0geHBhdGguc3Vic3RyaW5nKHhwYXRoLmluZGV4T2YoXCIoXCIsIGluRXhwcmVzc2lvblBvcykgKyAxLCBleHByZXNzaW9uRW5kKTtcclxuICAgICAgbGV0IHN1ZmZpeCA9IHhwYXRoLnN1YnN0cmluZyhleHByZXNzaW9uRW5kICsgMSk7XHJcblxyXG4gICAgICB4cGF0aCA9IHByZWZpeDtcclxuXHJcbiAgICAgIC8vRXZhbHVhdGUgWFBBVEggZXhwcmVzc2lvblxyXG4gICAgICBjb25zdCBwYXJzZXIgPSBuZXcgRE9NUGFyc2VyKCk7XHJcbiAgICAgIGxldCBkb2MgPSBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKHNlY29uZGFyeVhtbCwgXCJhcHBsaWNhdGlvbi94bWxcIik7XHJcbiAgICAgIGxldCB4UGF0aFJlc3VsdCA9IGRvY3VtZW50LmV2YWx1YXRlKHN1YkV4cHJlc3Npb24sIGRvYywgbnVsbCwgWFBhdGhSZXN1bHQuQU5ZX1RZUEUsIG51bGwpO1xyXG5cclxuICAgICAgLy9JdGVyYXRlIHhwYXRoIHJlc3VsdHMgKG5vZGVzKVxyXG4gICAgICB2YXIgbm9kZSA9IHhQYXRoUmVzdWx0Lml0ZXJhdGVOZXh0KCk7XHJcblxyXG4gICAgICB3aGlsZShub2RlKSB7XHJcbiAgICAgICAgeHBhdGggPSB4cGF0aCArIHZhcmlhYmxlICsgXCI9J1wiICsgbm9kZS5ub2RlVmFsdWUgKyBcIidcIlxyXG5cclxuICAgICAgICBub2RlID0geFBhdGhSZXN1bHQuaXRlcmF0ZU5leHQoKTtcclxuXHJcbiAgICAgICAgaWYgKG5vZGUpIHtcclxuICAgICAgICAgIHhwYXRoID0geHBhdGggKyBcIiBvciBcIjtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHhwYXRoID0geHBhdGggKyBzdWZmaXg7XHJcbiAgICB9XHJcblxyXG4gICAgZHRvLmV4cHJlc3Npb24gPSB4cGF0aDtcclxuICAgIHJldHVybiBkdG87XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNvcnRBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRMaXN0KGE6IGFueSwgYjogYW55KSB7XHJcbiAgICByZXR1cm4gYS5kZXNjcmlwdGlvbi50b0xvd2VyQ2FzZSgpLmxvY2FsZUNvbXBhcmUoYi5kZXNjcmlwdGlvbi50b0xvd2VyQ2FzZSgpKTtcclxuICB9XHJcblxyXG4gIGZldGNoQXR0cmlidXRlQ29uZmlndXJhdGlvbkxpc3QoY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dD86IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKGlzRGV2TW9kZSgpKSB7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoXCJmZXRjaEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25MaXN0OiBcIiArIGNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvbkxpc3RMb2FkaW5nU3ViamVjdC5uZXh0KHRydWUpO1xyXG5cclxuICAgIGxldCB1cmw6IHN0cmluZyA9IHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImNvbmZpZ3VyYXRpb25zXCI7XHJcbiAgICBsZXQgcGFyYW1zOiBIdHRwUGFyYW1zID0gbmV3IEh0dHBQYXJhbXMoKTtcclxuICAgIGlmIChjb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0KSB7XHJcbiAgICAgIHBhcmFtcyA9IHBhcmFtcy5zZXQoXCJjb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0XCIsIGNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaHR0cC5nZXQ8QXR0cmlidXRlQ29uZmlndXJhdGlvbltdPih1cmwsIHtwYXJhbXM6IHBhcmFtc30pLnN1YnNjcmliZSgoY29uZmlndXJhdGlvbkxpc3Q6IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25bXSkgPT4ge1xyXG4gICAgICB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25MaXN0TG9hZGluZ1N1YmplY3QubmV4dChmYWxzZSk7XHJcblxyXG4gICAgICBsZXQgZHRvczogQXR0cmlidXRlQ29uZmlndXJhdGlvbkRUT1tdID0gW107XHJcbiAgICAgIGZvciAobGV0IGNmZyBvZiBjb25maWd1cmF0aW9uTGlzdCkge1xyXG4gICAgICAgIGxldCBkdG86IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8gPSB0aGlzLmdldEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8oY2ZnKTtcclxuICAgICAgICBpZiAoZHRvKSB7XHJcbiAgICAgICAgICBkdG9zLnB1c2goZHRvKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGR0b3Muc29ydCh0aGlzLnNvcnRBdHRyaWJ1dGVDb25maWd1cmF0aW9uTGlzdCk7XHJcblxyXG4gICAgICB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25MaXN0U3ViamVjdC5uZXh0KGR0b3MpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNvcnRBdHRyaWJ1dGVDb25maWd1cmF0aW9uTGlzdChhOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPLCBiOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPKSB7XHJcbiAgICBjb25zdCBkaXNwbGF5YSA9IGEuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dERpc3BsYXlcclxuICAgICAgKyBhLmV4dGVuc2lvbkRlc2NyaXB0aW9uXHJcbiAgICAgICsgKGEuZmlsdGVyMURpc3BsYXkgfHwgXCJcIilcclxuICAgICAgKyAoYS5maWx0ZXIyRGlzcGxheSB8fCBcIlwiKTtcclxuXHJcbiAgICBjb25zdCBkaXNwbGF5YiA9IGIuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dERpc3BsYXlcclxuICAgICAgKyBiLmV4dGVuc2lvbkRlc2NyaXB0aW9uXHJcbiAgICAgICsgKGIuZmlsdGVyMURpc3BsYXkgfHwgXCJcIilcclxuICAgICAgKyAoYi5maWx0ZXIyRGlzcGxheSB8fCBcIlwiKTtcclxuXHJcbiAgICByZXR1cm4gZGlzcGxheWEudG9Mb3dlckNhc2UoKS5sb2NhbGVDb21wYXJlKGRpc3BsYXliLnRvTG93ZXJDYXNlKCkpO1xyXG4gIH1cclxuXHJcbiAgLy9Vc2VkIGJ5IGNvZC1lZGl0b3JcclxuICBjbGVhcigpOiB2b2lkIHtcclxuICAgIHRoaXMuaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy5pZEZpbHRlcjEgPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLmlkRmlsdGVyMiA9IHVuZGVmaW5lZDtcclxuXHJcbiAgICB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE9TdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcclxuICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QubmV4dCh1bmRlZmluZWQpO1xyXG4gIH1cclxuXHJcbiAgY3JlYXRlQXR0cmlidXRlQ29uZmlndXJhdGlvbihhdHRyaWJ1dGVDb25maWd1cmF0aW9uOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uKTogdm9pZCB7XHJcbiAgICBhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiA9IHVuZGVmaW5lZDtcclxuXHJcbiAgICB0aGlzLmh0dHAucG9zdDxBdHRyaWJ1dGVDb25maWd1cmF0aW9uPih0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJjb25maWd1cmF0aW9uc1wiLCBhdHRyaWJ1dGVDb25maWd1cmF0aW9uKS5zdWJzY3JpYmUoKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pID0+IHtcclxuICAgICAgdGhpcy5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPSBhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbjtcclxuXHJcbiAgICAgIHRoaXMucG9zdENvbmZpZ3VyYXRpb25TdWJqZWN0Lm5leHQodHJ1ZSk7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QubmV4dChhdHRyaWJ1dGVDb25maWd1cmF0aW9uKTtcclxuICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGVCeVVybChcIi9lZGl0b3IvYXR0cmlidXRlLWNvbmZpZ3VyYXRpb24vXCIgKyBhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbik7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHNldEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25CeUlkKGlkQXR0cmlidXRlQ29uZmlndXJhdGlvbjogbnVtYmVyLCBpZEF0dHJpYnV0ZVZhbHVlU2V0OiBudW1iZXIsIGlkUGFyZW50T2JqZWN0OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGlmIChpZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gIT09IC0xKSB7XHJcbiAgICAgIHRoaXMubmV3QXR0cmlidXRlQ29uZmlndXJhdGlvbiA9IHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICAvL09ubHkgbG9hZCBpZiB0aGUgQXR0cmlidXRlQ29uZmlndXJhdGlvbiBoYXMgY2hhbmdlZFxyXG4gICAgaWYgKHRoaXMuaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uICE9PSBpZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pIHtcclxuICAgICAgLy9DbGVhciBBU0FQXHJcbiAgICAgIHRoaXMuaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uID0gaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uO1xyXG4gICAgICB0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXQgPSBpZEF0dHJpYnV0ZVZhbHVlU2V0O1xyXG4gICAgICB0aGlzLmlkRmlsdGVyMSA9IHVuZGVmaW5lZDtcclxuICAgICAgdGhpcy5pZEZpbHRlcjIgPSB1bmRlZmluZWQ7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlTWFwLmNsZWFyKCk7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvbkRUT1N1YmplY3QubmV4dCh1bmRlZmluZWQpO1xyXG4gICAgICB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25TdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcclxuXHJcbiAgICAgIHRoaXMuZmV0Y2hBdHRyaWJ1dGVDb25maWd1cmF0aW9uKGlkQXR0cmlidXRlVmFsdWVTZXQsIGlkUGFyZW50T2JqZWN0KTtcclxuICAgIH1cclxuICAgIC8vT3IgbG9hZCB0aGUgQXR0cmlidXRlVmFsdWVTZXQgaWYgdGhhdCBjaGFuZ2VkIChwb3NzaWJsZSB0byBzd2l0Y2ggZnJvbSBvbmUgZXZlbnQgdG8gYW5vdGhlciBvZiB0aGUgc2FtZSB0eXBlLCBmb3IgZXhhbXBsZVxyXG4gICAgLy9UaGUgQXR0cmlidXRlQ29uZmlndXJhdGlvbiBtdXN0IGFsc28gaGF2ZSBmaW5pc2hlZCBsb2FkaW5nIGFuZCBub3QgYWxyZWFkeSB3b3JraW5nIG9uIGxvYWRpbmcgdGhlIHZhbHVlc1xyXG4gICAgZWxzZSBpZiAodGhpcy5pZEF0dHJpYnV0ZVZhbHVlU2V0ICE9PSBpZEF0dHJpYnV0ZVZhbHVlU2V0ICYmIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QuZ2V0VmFsdWUoKSkge1xyXG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZVZhbHVlU2V0KGlkQXR0cmlidXRlVmFsdWVTZXQsIGlkUGFyZW50T2JqZWN0KTtcclxuICAgIH1cclxuICB9XHJcblxyXG5cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0cyB0aGUgYXR0cmlidXRlIGNvbmZpZ3VyYXRpb24gaWRlbnRpZmllcnMgdG8gYmUgdXNlZCBieSB0aGlzIHNlcnZpY2UuICBUaGlzIHByb21wdHMgYSBuZXcgY29uZmlndXJhdGlvblxyXG4gICAqIHJlcXVlc3QgdG8gYmUgbWFkZS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpZEZpbHRlcjFcclxuICAgKiBAcGFyYW0ge251bWJlcn0gaWRGaWx0ZXIyXHJcbiAgICovXHJcbi8qIFRoaXMgaXMgY29tbWVudGVkIG91dCBmb3Igbm93IGJlY2F1c2UgaXQgaXMgYm90aCB1bmltcGxlbWVudGVkIGFuZCBpbmNvbXBsZXRlIChsb2FkaW5nIGEgY29uZmlndXJhdGlvblxyXG4gKiBmaWx0ZXIgd291bGQgcmVhbGx5IGFsc28gcmVxdWlyZSB0aGUgYXR0cmlidXRlIGNvbnRleHQgYW5kIGF0dHJpYnV0ZXNlY3VyaXR5IGNvbnRleHQgcGx1cyBhIHNlcnZpY2Ugb25cclxuICogdGhlIGJhY2sgZW5kIHRoYXQgYWN0dWFsbHkgZG9lcyB0aGlzIHdvcmsuIEZvciBub3csIG9ubHkgbG9hZGluZyBieSBpZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25cclxuICpcclxuICBzZXRBdHRyaWJ1dGVDb25maWd1cmF0aW9uQnlGaWx0ZXIoaWRGaWx0ZXIxOiBudW1iZXIsIGlkRmlsdGVyMj86IG51bWJlcik6IHZvaWQge1xyXG4gICAgaWYgKGlzRGV2TW9kZSgpKSB7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoXCJzZXRBdHRyaWJ1dGVDb25maWd1cmF0aW9uQnlGaWx0ZXI6IFwiICsgaWRGaWx0ZXIxICsgXCIgXCIgKyBpZEZpbHRlcjIpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMubmV3QXR0cmlidXRlQ29uZmlndXJhdGlvbiA9IHVuZGVmaW5lZDtcclxuICAgIC8vdGhpcy5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLmlkRmlsdGVyMSA9IGlkRmlsdGVyMTtcclxuICAgIHRoaXMuaWRGaWx0ZXIyID0gaWRGaWx0ZXIyO1xyXG5cclxuICAgIHRoaXMuZmV0Y2hBdHRyaWJ1dGVDb25maWd1cmF0aW9uKCk7XHJcbiAgfVxyXG4qL1xyXG5cclxuICAvKipcclxuICAgKiBTZXRzIHRoZSBpZCBvZiB0aGUgYXR0cmlidXRlIHZhbHVlIHNldC4gIFRoaXMgd2lsbCBwcm9tcHQgYSByZXF1ZXN0IHRvIHB1bGwgdGhpcyBmcm9tIHRoZSBiYWNrZW5kLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtudW1iZXJ9IGlkQXR0cmlidXRlVmFsdWVTZXRcclxuICAgKi9cclxuICBzZXRBdHRyaWJ1dGVWYWx1ZVNldChpZEF0dHJpYnV0ZVZhbHVlU2V0OiBudW1iZXIsIGlkUGFyZW50T2JqZWN0OiBudW1iZXIpIHtcclxuICAgIC8vT25seSBsb2FkIHRoZSBBdHRyaWJ1dGVWYWx1ZVNldCBpZiBpdCBoYXMgYmVlbiBjaGFuZ2VkXHJcbiAgICBpZiAodGhpcy5pZEF0dHJpYnV0ZVZhbHVlU2V0ICE9PSBpZEF0dHJpYnV0ZVZhbHVlU2V0KSB7XHJcbiAgICAgIHRoaXMuaWRBdHRyaWJ1dGVWYWx1ZVNldCA9IGlkQXR0cmlidXRlVmFsdWVTZXQ7XHJcblxyXG4gICAgICB0aGlzLmZldGNoQXR0cmlidXRlVmFsdWVTZXQoaWRQYXJlbnRPYmplY3QpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIHJlcXVlc3QgdG8gZG93bmxvYWQgdGhlIGF0dHJpYnV0ZSBjb25maWd1cmF0aW9uLlxyXG4gICAqL1xyXG4gIGZldGNoQXR0cmlidXRlQ29uZmlndXJhdGlvbihpZEF0dHJpYnV0ZVZhbHVlU2V0OiBudW1iZXIsIGlkUGFyZW50T2JqZWN0OiBudW1iZXIpOiB2b2lkIHtcclxuXHJcbiAgICBpZiAodGhpcy5uZXdBdHRyaWJ1dGVDb25maWd1cmF0aW9uKSB7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvbkRUT1N1YmplY3QubmV4dCh1bmRlZmluZWQpO1xyXG4gICAgICB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25TdWJqZWN0Lm5leHQodGhpcy5uZXdBdHRyaWJ1dGVDb25maWd1cmF0aW9uKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfSBlbHNlIGlmICh0aGlzLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiA9PT0gLTEpIHtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPU3ViamVjdC5uZXh0KHVuZGVmaW5lZCk7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QubmV4dCg8QXR0cmlidXRlQ29uZmlndXJhdGlvbj57XHJcbiAgICAgICAgaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uOiAtMlxyXG4gICAgICB9KTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dCh0cnVlKTtcclxuXHJcbiAgICBsZXQgdXJsOiBzdHJpbmc7XHJcbiAgICBpZiAodGhpcy5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gJiYgdGhpcy5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPiAtMSkge1xyXG4gICAgICB1cmwgPSB0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJjb25maWd1cmF0aW9ucy9cIiArIHRoaXMuaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy9UaGlzIGlzIG5vdCBmdWxseSBpbXBsZW1lbnRlZFxyXG5cdCAgLy91cmwgPSB0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJjb25maWd1cmF0aW9ucy9maWx0ZXIvXCIgKyB0aGlzLmlkRmlsdGVyMTtcclxuICAgICAgLy9pZiAodGhpcy5pZEZpbHRlcjIpIHtcclxuICAgICAgICAvL3VybCArPSBcIi9cIiArIHRoaXMuaWRGaWx0ZXIyO1xyXG4gICAgICAvL31cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmh0dHAuZ2V0PEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24+KHVybCkuc3Vic2NyaWJlKChhdHRyaWJ1dGVDb25maWd1cmF0aW9uOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uKSA9PiB7XHJcbiAgICAgIHRoaXMuc2V0QXR0cmlidXRlQ29uZmlndXJhdGlvbihhdHRyaWJ1dGVDb25maWd1cmF0aW9uKTtcclxuICAgICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuXHJcbiAgICAgIC8vTm93IGxvYWQgdGhlIGF0dHJpYnV0ZVZhbHVlU2V0IC0gVGhpcyB3aWxsIGFsd2F5cyBoYXBwZW4gd2hlbiBhIG5ldyBjb25maWd1cmF0aW9uIGlzIGxvYWRlZFxyXG4gICAgICB0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXQgPSB1bmRlZmluZWQ7IC8vRm9yY2UgaXQgdG8gY2hhbmdlIGluIHRoaXMgc2NlbmFyaW9cclxuICAgICAgdGhpcy5zZXRBdHRyaWJ1dGVWYWx1ZVNldChpZEF0dHJpYnV0ZVZhbHVlU2V0LCBpZFBhcmVudE9iamVjdCk7XHJcbiAgICAgIHRoaXMuZGlydHkubmV4dChmYWxzZSk7XHJcbiAgICB9LFxyXG4gICAgKGVycm9yKSA9PiB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24odW5kZWZpbmVkKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc2V0QXR0cmlidXRlQ29uZmlndXJhdGlvbihhdHRyaWJ1dGVDb25maWd1cmF0aW9uOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uKTogdm9pZCB7XHJcbiAgICB0aGlzLmF0dHJpYnV0ZU1hcC5jbGVhcigpO1xyXG5cclxuICAgIGlmIChpc0Rldk1vZGUoKSkge1xyXG4gICAgICBjb25zb2xlLmRlYnVnKFwiQXR0cmlidXRlU2VydmljZS5zZXRBdHRyaWJ1dGVDb25maWd1cmF0aW9uXCIpO1xyXG4gICAgICBjb25zb2xlLmRlYnVnKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChhdHRyaWJ1dGVDb25maWd1cmF0aW9uKSB7XHJcbiAgICAgIGlmIChhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmJhc2VXaW5kb3dUZW1wbGF0ZSkge1xyXG4gICAgICAgIHRoaXMuZ2V0QmFzZVdpbmRvd0RpbWVuc2lvbihhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmJhc2VXaW5kb3dUZW1wbGF0ZSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmF0dHJpYnV0ZUNvbnRhaW5lcnMpIHtcclxuICAgICAgICBhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmF0dHJpYnV0ZUNvbnRhaW5lcnMuc29ydCgoYTogQXR0cmlidXRlQ29udGFpbmVyLCBiOiBBdHRyaWJ1dGVDb250YWluZXIpID0+IHtcclxuICAgICAgICAgIGlmIChhLnNvcnRPcmRlciA8IGIuc29ydE9yZGVyKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAtMTtcclxuICAgICAgICAgIH0gZWxzZSBpZiAoYS5zb3J0T3JkZXIgPiBiLnNvcnRPcmRlcikge1xyXG4gICAgICAgICAgICByZXR1cm4gMTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiAwO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBmb3IgKGxldCBhdHRyaWJ1dGVDb250YWluZXIgb2YgYXR0cmlidXRlQ29uZmlndXJhdGlvbi5hdHRyaWJ1dGVDb250YWluZXJzKSB7XHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogRmlyc3Qgc29ydCBhdHRyaWJ1dGVzIHVzaW5nIHRoZSB5IGFuZCB4IHBvc2l0aW9uaW5nLiAgSWYgdXNpbmcgYWJzb2x1dGUgcG9zaXRpb24sIHRoZSBvcmRlciBkb2Vzbid0IG1hdHRlcixcclxuICAgICAgICAgKiBidXQgaWYgd2Ugd2FudCB0aGUgYWJzb2x1dGUgcG9zaXRpb25pbmcgdG8gZ3VpZGUgYXV0byBsYXlvdXQsIHRoZW4gdXNlIHRoaXMgb3JkZXIuXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgYXR0cmlidXRlQ29udGFpbmVyLmdyYXBoaWNhbEF0dHJpYnV0ZXMuc29ydCgoYTogR3JhcGhpY2FsQXR0cmlidXRlLCBiOiBHcmFwaGljYWxBdHRyaWJ1dGUpID0+IHtcclxuICAgICAgICAgIGlmIChhLnRhYk9yZGVyIDwgYi50YWJPcmRlcikge1xyXG4gICAgICAgICAgICByZXR1cm4gLTE7XHJcbiAgICAgICAgICB9IGVsc2UgaWYgKGEudGFiT3JkZXIgPiBiLnRhYk9yZGVyKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAxO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIDA7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIGZvciAobGV0IGF0dHJpYnV0ZSBvZiBhdHRyaWJ1dGVDb250YWluZXIuZ3JhcGhpY2FsQXR0cmlidXRlcykge1xyXG4gICAgICAgICAgdGhpcy5hdHRyaWJ1dGVNYXAuc2V0KGF0dHJpYnV0ZS5pZEF0dHJpYnV0ZSwgYXR0cmlidXRlKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE9TdWJqZWN0Lm5leHQodGhpcy5nZXRBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pKTtcclxuICAgIHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QubmV4dChhdHRyaWJ1dGVDb25maWd1cmF0aW9uKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRoZSByZXF1ZXN0IHRvIHB1bGwgdGhlIGF0dHJpYnV0ZSB2YWx1ZSBzZXQuXHJcbiAgICogUmVxdWlyZWQgdGhlIEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gdG8gYmUgcHJlLWxvYWRlZFxyXG4gICAqL1xyXG4gIGZldGNoQXR0cmlidXRlVmFsdWVTZXQoaWRQYXJlbnRPYmplY3Q6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KHRydWUpO1xyXG4gICAgdGhpcy5pZFBhcmVudE9iamVjdCA9IGlkUGFyZW50T2JqZWN0O1xyXG5cclxuICAgIGxldCB1cmw6IHN0cmluZyA9IHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImF0dHJpYnV0ZS12YWx1ZS1zZXQvXCIgKyB0aGlzLmlkQXR0cmlidXRlVmFsdWVTZXQ7XHJcblxyXG4gICAgbGV0IGFjOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uID0gdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdC5nZXRWYWx1ZSgpO1xyXG5cclxuICAgIGxldCBxdWVyeVBhcmFtczogSHR0cFBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKClcclxuICAgIC5zZXQoXCJjb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0XCIsIGFjLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQpXHJcbiAgICAuc2V0KFwiY29kZUF0dHJpYnV0ZUNvbnRleHRcIiwgYWMuY29kZUF0dHJpYnV0ZUNvbnRleHQpXHJcbiAgICAuc2V0KFwiaWRQYXJlbnRPYmplY3RcIiwgKGlkUGFyZW50T2JqZWN0KT9pZFBhcmVudE9iamVjdC50b1N0cmluZygpOlwiXCIpO1xyXG5cclxuICAgIC8vQ2xlYXIgQVNBUFxyXG4gICAgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMgPSBbXTtcclxuICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcyA9IFtdO1xyXG4gICAgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QubmV4dCh1bmRlZmluZWQpO1xyXG5cclxuICAgIHRoaXMuaHR0cC5nZXQ8QXR0cmlidXRlVmFsdWVTZXQ+KHVybCwge3BhcmFtczogcXVlcnlQYXJhbXN9KS5zdWJzY3JpYmUoKGF0dHJpYnV0ZVZhbHVlU2V0OiBBdHRyaWJ1dGVWYWx1ZVNldCkgPT4ge1xyXG4gICAgICAvL0luaXRpYWxpemUgYXR0cmlidXRlVmFsdWVzIGlmIGl0IGRvZXMgbm90IGV4aXN0XHJcbiAgICAgIGlmICghIGF0dHJpYnV0ZVZhbHVlU2V0LmF0dHJpYnV0ZVZhbHVlcykge1xyXG4gICAgICAgIGF0dHJpYnV0ZVZhbHVlU2V0LmF0dHJpYnV0ZVZhbHVlcyA9IFtdO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5uZXh0KGF0dHJpYnV0ZVZhbHVlU2V0KTtcclxuICAgICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuICAgICAgdGhpcy5kaXJ0eS5uZXh0KGZhbHNlKTtcclxuICAgIH0sXHJcbiAgICAoZXJyb3IpID0+IHtcclxuICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XHJcbiAgICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dChmYWxzZSk7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZ2V0QmFzZVdpbmRvd0RpbWVuc2lvbihiYXNlV2luZG93VGVtcGxhdGU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5odHRwLmdldCh0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJiYXNlLXdpbmRvdy1kaW1lbnNpb25cIiwge3BhcmFtczogbmV3IEh0dHBQYXJhbXMoKS5zZXQoXCJiYXNlV2luZG93VGVtcGxhdGVcIiwgYmFzZVdpbmRvd1RlbXBsYXRlKX0pXHJcbiAgICAgIC5zdWJzY3JpYmUoKGRpbWVuc2lvbjogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uRGltZW5zaW9uU3ViamVjdC5uZXh0KGRpbWVuc2lvbik7XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3VycmVudGx5IGEgc2ltcGxlIG5vdGlmaWVyIHRoYXQgdGhlIGNvbmZpZ3VyYXRpb24gb3IgYXR0cmlidXRlIHZhbHVlIHNldCBoYXMgY2hhbmdlZCBhbmQgY29tcG9uZW50cyBtYXkgbmVlZCB0byBiZSByZWZyZXNoZWQuXHJcbiAgICpcclxuICAgKi9cclxuICBub3RpZnlBdHRyaWJ1dGVzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5jb250YWluZXJVcGRhdGVkLm5leHQodHJ1ZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQb3N0IHRoZSBhdHRyaWJ1dGUgY29uZmlndXJhdGlvbiBhZnRlciBlZGl0aW5nLiAgUG9zdCB0aGUgZW50aXJlIHRoaW5nIGFzIGl0IGNhc2NhZGVzIGRvd24uICBUaGUgZWRpdG9yIGFsbG93cyB5b3VcclxuICAgKiB0byBtb2RpZnkgZXZlcnkgY29udGFpbmVyIGFuZCBvbmx5IHRoZW4gc2F2ZSB0aGUgZW50aXJlIGNvbmZpZ3VyYXRpb24uXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge0F0dHJpYnV0ZUNvbmZpZ3VyYXRpb259IGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25cclxuICAgKi9cclxuICBwb3N0QXR0cmlidXRlQ29uZmlndXJhdGlvbihhdHRyaWJ1dGVDb25maWd1cmF0aW9uOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uKTogdm9pZCB7XHJcbiAgICBsZXQgdXJsOiBzdHJpbmcgPSB0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJjb25maWd1cmF0aW9ucy9cIiArIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uO1xyXG5cclxuICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dCh0cnVlKTtcclxuXHJcbiAgICB0aGlzLnNldE5lZ2F0aXZlSWRzVG9VbmRlZmluZWQoYXR0cmlidXRlQ29uZmlndXJhdGlvbik7XHJcblxyXG4gICAgdGhpcy5odHRwLnBvc3QodXJsLCBhdHRyaWJ1dGVDb25maWd1cmF0aW9uKS5zdWJzY3JpYmUoKCkgPT4ge1xyXG5cclxuICAgICAgLy8gUHJldmVudCBlcnJvciBpbiBzdWJzZXF1ZW50IHNhdmVzLiBTZWUgTWV0YWJ1aWxkZXIgLyBNQi0yM1xyXG4gICAgICB0aGlzLmh0dHAuZ2V0PEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24+KHVybCkuc3Vic2NyaWJlKChhdHRyaWJ1dGVDb25maWd1cmF0aW9uOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uKSA9PiB7XHJcbiAgICAgICAgaWYgKGlzRGV2TW9kZSgpKSB7XHJcbiAgICAgICAgICBjb25zb2xlLmRlYnVnKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5wb3N0Q29uZmlndXJhdGlvblN1YmplY3QubmV4dCh0cnVlKTtcclxuICAgICAgICB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25TdWJqZWN0Lm5leHQoYXR0cmlidXRlQ29uZmlndXJhdGlvbik7XHJcbiAgICAgIH0sXHJcbiAgICAgIChlcnJvcikgPT4ge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgICB9LFxyXG4gICAgICAoKSA9PiB7XHJcbiAgICAgICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgfSxcclxuICAgIChlcnJvcikgPT4ge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQdXQgdGhlIGF0dHJpYnV0ZSB2YWx1ZSBzZXQuICBXaGVuIGVkaXRpbmcsIGF0dHJpYnV0ZXMgYWxyZWFkeSBwb3N0IHRoZWlyIHVwZGF0ZWQgdmFsdWVzIHRvIHRoaXMgc2VydmljZXMgdW5kZXJcclxuICAgKiBhIHNlcGFyYXRlIGFycmF5LiAgV2hhdCB3ZSBkbyBpcyBtZXJnZSBpbiB0aGVzZSB1cGRhdGVkIG9yIGNyZWF0ZWQgdmFsdWVzIHdpdGggdGhlIGN1cnJlbnQgYXR0cmlidXRlIHZhbHVlIHNldCAoYXZzKS5cclxuICAgKiBXaGlsZSBkb2luZyB0aGlzLCBzZXQgdGhlIGlkIG9mIHRoZSBhdnMgYW5kIG51bGxpZnkgYW55IG5lZ2F0aXZlIGlkcy5cclxuICAgKi9cclxuICB1cGRhdGVBdHRyaWJ1dGVWYWx1ZVNldCgpOiBTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlU2V0PiB7XHJcbiAgICBsZXQgdXJsOiBzdHJpbmcgPSB0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJhdHRyaWJ1dGUtdmFsdWUtc2V0L1wiIDtcclxuXHJcbiAgICBsZXQgYWM6IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPSB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25TdWJqZWN0LmdldFZhbHVlKCk7XHJcblxyXG4gICAgbGV0IHF1ZXJ5UGFyYW1zOiBIdHRwUGFyYW1zID0gbmV3IEh0dHBQYXJhbXMoKVxyXG4gICAgLnNldChcImNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHRcIiwgYWMuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dClcclxuICAgIC5zZXQoXCJjb2RlQXR0cmlidXRlQ29udGV4dFwiLCBhYy5jb2RlQXR0cmlidXRlQ29udGV4dClcclxuICAgIC5zZXQoXCJpZFBhcmVudE9iamVjdFwiLCAodGhpcy5pZFBhcmVudE9iamVjdCk/dGhpcy5pZFBhcmVudE9iamVjdC50b1N0cmluZygpOlwiXCIpO1xyXG5cclxuICAgIGxldCBhdnM6IEF0dHJpYnV0ZVZhbHVlU2V0ID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKSk7XHJcbiAgICBmb3IgKGxldCBpID0gdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZVZhbHVlU2V0ID0gdGhpcy5pZEF0dHJpYnV0ZVZhbHVlU2V0O1xyXG4gICAgICBpZiAodGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2ldLmlkQXR0cmlidXRlVmFsdWUgPCAwKSB7XHJcbiAgICAgICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2ldLmlkQXR0cmlidXRlVmFsdWUgPSB1bmRlZmluZWQ7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGxldCBqOiBudW1iZXIgPSAwO1xyXG4gICAgICBmb3IgKGogPSAwOyBqIDwgYXZzLmF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgIGlmICh0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uaWRBdHRyaWJ1dGVWYWx1ZSA9PT0gYXZzLmF0dHJpYnV0ZVZhbHVlc1tqXS5pZEF0dHJpYnV0ZVZhbHVlKSB7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGogPCBhdnMuYXR0cmlidXRlVmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICAgIGF2cy5hdHRyaWJ1dGVWYWx1ZXNbal0gPSB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV07XHJcbiAgICAgICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLnNwbGljZShpLCAxKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBsZXQgajogbnVtYmVyID0gMDtcclxuICAgICAgZm9yIChqID0gMDsgaiA8IGF2cy5hdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoOyBqKyspIHtcclxuICAgICAgICBpZiAodGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uaWRBdHRyaWJ1dGVWYWx1ZSA9PT0gYXZzLmF0dHJpYnV0ZVZhbHVlc1tqXS5pZEF0dHJpYnV0ZVZhbHVlKSB7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGogPCBhdnMuYXR0cmlidXRlVmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICAgIGF2cy5hdHRyaWJ1dGVWYWx1ZXMuc3BsaWNlKGosIDEpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBhdnMuYXR0cmlidXRlVmFsdWVzID0gYXZzLmF0dHJpYnV0ZVZhbHVlcy5jb25jYXQodGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzKTtcclxuXHJcbiAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQodHJ1ZSk7XHJcblxyXG4gICAgbGV0IHJlc3VsdFN1YmplY3Q6IFN1YmplY3Q8QXR0cmlidXRlVmFsdWVTZXQ+ID0gbmV3IFN1YmplY3Q8QXR0cmlidXRlVmFsdWVTZXQ+KCk7XHJcblxyXG4gICAgdGhpcy5odHRwLnB1dCh1cmwsIGF2cywge3BhcmFtczogcXVlcnlQYXJhbXN9KS5zdWJzY3JpYmUoKGF0dHJpYnV0ZVZhbHVlU2V0OiBBdHRyaWJ1dGVWYWx1ZVNldCkgPT4ge1xyXG4gICAgICAgIGlmIChpc0Rldk1vZGUoKSkge1xyXG4gICAgICAgICAgY29uc29sZS5kZWJ1ZyhhdHRyaWJ1dGVWYWx1ZVNldCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvL0luaXRpYWxpemUgYXR0cmlidXRlVmFsdWVzIGlmIGl0IGRvZXMgbm90IGV4aXN0XHJcbiAgICAgICAgaWYgKCEgYXR0cmlidXRlVmFsdWVTZXQuYXR0cmlidXRlVmFsdWVzKSB7XHJcbiAgICAgICAgICBhdHRyaWJ1dGVWYWx1ZVNldC5hdHRyaWJ1dGVWYWx1ZXMgPSBbXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzID0gW107XHJcbiAgICAgICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzID0gW107XHJcbiAgICAgICAgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QubmV4dChhdHRyaWJ1dGVWYWx1ZVNldCk7XHJcbiAgICAgICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuICAgICAgICB0aGlzLmRpcnR5Lm5leHQoZmFsc2UpO1xyXG5cclxuICAgICAgICAvL1NlbmQgdGhlIHJlc3VsdHMgdG8gdGhlIG9ic2VydmVyIChpZiBhbnkpLCB0aGVuIGNvbXBsZXRlXHJcbiAgICAgICAgcmVzdWx0U3ViamVjdC5uZXh0KGF0dHJpYnV0ZVZhbHVlU2V0KTtcclxuICAgICAgICByZXN1bHRTdWJqZWN0LmNvbXBsZXRlKCk7XHJcbiAgICAgIH0sXHJcbiAgICAgIChlcnJvcikgPT4ge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dChmYWxzZSk7XHJcbiAgICAgICAgcmVzdWx0U3ViamVjdC5lcnJvcihlcnJvcik7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgIHJldHVybiByZXN1bHRTdWJqZWN0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IHRoZSBhdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdC5cclxuICAgKlxyXG4gICAqIEByZXR1cm5zIHtCZWhhdmlvclN1YmplY3Q8QXR0cmlidXRlQ29uZmlndXJhdGlvbj59XHJcbiAgICovXHJcbiAgZ2V0QXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QoKTogQmVoYXZpb3JTdWJqZWN0PEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24+IHtcclxuICAgIHJldHVybiB0aGlzLmF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25TdWJqZWN0O1xyXG4gIH1cclxuXHJcbiAgZ2V0RGlydHlTdWJqZWN0KCk6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPiB7XHJcbiAgICByZXR1cm4gdGhpcy5kaXJ0eTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB0aGUgYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0O1xyXG4gICAqXHJcbiAgICogQHJldHVybnMge0JlaGF2aW9yU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZVNldD59XHJcbiAgICovXHJcbiAgZ2V0QXR0cmlidXRlVmFsdWVTZXQoKTogQmVoYXZpb3JTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlU2V0PiB7XHJcbiAgICByZXR1cm4gdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgdGhlIGF0dHJpYnV0ZVZhbHVlUHVzaGVkU3ViamVjdDtcclxuICAgKlxyXG4gICAqIEByZXR1cm5zIHtTdWJqZWN0PEF0dHJpYnV0ZVZhbHVlPn1cclxuICAgKi9cclxuICBnZXRBdHRyaWJ1dGVWYWx1ZVB1c2hlZFN1YmplY3QoKTogU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZT4ge1xyXG4gICAgcmV0dXJuIHRoaXMuYXR0cmlidXRlVmFsdWVQdXNoZWRTdWJqZWN0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IGFsbCBhdHRyaWJ1dGUgdmFsdWVzIGJhc2VkIHVwb24gdGhlIGlkQXR0cmlidXRlLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtudW1iZXJ9IGlkQXR0cmlidXRlc1xyXG4gICAqIEByZXR1cm5zIHtBdHRyaWJ1dGVWYWx1ZVtdfVxyXG4gICAqL1xyXG4gIGdldEF0dHJpYnV0ZVZhbHVlcyhpZEF0dHJpYnV0ZTogbnVtYmVyLCBncm91cEF0dHJpYnV0ZVJvd0lkOiBudW1iZXIpOiBBdHRyaWJ1dGVWYWx1ZVtdIHtcclxuXHJcbiAgICBsZXQgYXR0cmlidXRlVmFsdWVzOiBBdHRyaWJ1dGVWYWx1ZVtdID0gW107XHJcblxyXG4gICAgaWYodGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKSkge1xyXG5cclxuICAgICAgLy9HbyB0aHJvdWdoIGFsbCB0aGUgdXBkYXRlZCBhdHRyaWJ1dGUgdmFsdWVzIGZpcnN0IChzbyB3ZSBwcmVzZXJ2ZSBhY3Jvc3MgY2hhbmdpbmcgdGFicywgZXRjKVxyXG4gICAgICBsZXQgaTogbnVtYmVyID0gMDtcclxuICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGlmICh0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uaWRBdHRyaWJ1dGUgPT09IGlkQXR0cmlidXRlICYmICghZ3JvdXBBdHRyaWJ1dGVSb3dJZCB8fCBncm91cEF0dHJpYnV0ZVJvd0lkID09PSB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uZ3JvdXBBdHRyaWJ1dGVSb3dJZCkpIHtcclxuICAgICAgICAgIGF0dHJpYnV0ZVZhbHVlcy5wdXNoKE9iamVjdC5hc3NpZ24oe30sIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXSkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uaWRHcm91cEF0dHJpYnV0ZSA9PT0gaWRBdHRyaWJ1dGUgJiYgKCFncm91cEF0dHJpYnV0ZVJvd0lkIHx8IGdyb3VwQXR0cmlidXRlUm93SWQgPT09IHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS5ncm91cEF0dHJpYnV0ZVJvd0lkKSkge1xyXG4gICAgICAgICAgYXR0cmlidXRlVmFsdWVzLnB1c2goT2JqZWN0LmFzc2lnbih7fSwgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2ldKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvL0dvIHRocm91Z2ggYWxsIHRoZSByZWd1bGFyIGF0dHJpYnV0ZXNcclxuICAgICAgZm9yIChsZXQgYXR0cmlidXRlVmFsdWUgb2YgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKS5hdHRyaWJ1dGVWYWx1ZXMpIHtcclxuICAgICAgICAvL1JlZ3VsYXIgYXR0cmlidXRlcyAobm9ybWFsIGFuZCBncm91cCwgd2hpY2ggZ2V0IG11bHRpcGxlKVxyXG4gICAgICAgIGlmIChhdHRyaWJ1dGVWYWx1ZS5pZEF0dHJpYnV0ZSA9PT0gaWRBdHRyaWJ1dGUgfHwgYXR0cmlidXRlVmFsdWUuaWRHcm91cEF0dHJpYnV0ZSA9PT0gaWRBdHRyaWJ1dGUpIHtcclxuICAgICAgICAgIC8vSWYgcm93IGlkIHNwZWNpZmllZCwgb25seSBjYXJlIGFib3V0IHZhbHVlcyBmb3IgdGhhdCByb3dcclxuICAgICAgICAgIGlmICh0eXBlb2YgZ3JvdXBBdHRyaWJ1dGVSb3dJZCA9PT0gJ3VuZGVmaW5lZCcgfHwgYXR0cmlidXRlVmFsdWUuZ3JvdXBBdHRyaWJ1dGVSb3dJZCA9PT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCkge1xyXG5cclxuICAgICAgICAgICAgLy9JZiBub3QgYWxyZWFkeSBhZGRlZC4uLlxyXG4gICAgICAgICAgICBpZiAoISBhdHRyaWJ1dGVWYWx1ZXMuZmluZCgoZXhpc3RpbmcpID0+IGV4aXN0aW5nLmlkQXR0cmlidXRlVmFsdWUgPT09IGF0dHJpYnV0ZVZhbHVlLmlkQXR0cmlidXRlVmFsdWUpKSB7XHJcblxyXG4gICAgICAgICAgICAgIC8vRG9uJ3Qgd2FudCB0aGUgb3JpZ2luYWwgaWYgaXQgd2FzIHJlbW92ZWQgKHNsaWNlZClcclxuICAgICAgICAgICAgICBpZiAoISB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5maW5kKChzYXYpID0+IHNhdi5pZEF0dHJpYnV0ZVZhbHVlID09PSBhdHRyaWJ1dGVWYWx1ZS5pZEF0dHJpYnV0ZVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgICAgYXR0cmlidXRlVmFsdWVzLnB1c2goT2JqZWN0LmFzc2lnbih7fSwgYXR0cmlidXRlVmFsdWUpKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gYXR0cmlidXRlVmFsdWVzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IGFsbCBjaGlsZCBhdHRyaWJ1dGVzIG9mIHRoZSBpZEF0dHJpYnV0ZS4gIE1vc3QgbGlrZWx5IGZvciBhdHRyaWJ1dGVzIHRoYXQgZGVmaW5lIGNvbHVtbnMgb2YgYSBncmlkLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtudW1iZXJ9IGlkQXR0cmlidXRlXHJcbiAgICogQHJldHVybnMge0F0dHJpYnV0ZVtdfVxyXG4gICAqL1xyXG4gIGdldEdyb3VwQXR0cmlidXRlcyhpZEF0dHJpYnV0ZTogbnVtYmVyKTogQXR0cmlidXRlW10ge1xyXG4gICAgbGV0IGF0dHJpYnV0ZXM6IEF0dHJpYnV0ZVtdID0gW107XHJcblxyXG4gICAgdGhpcy5hdHRyaWJ1dGVNYXAuZm9yRWFjaCgoYXR0cmlidXRlOiBBdHRyaWJ1dGUpID0+IHtcclxuICAgICAgaWYgKGF0dHJpYnV0ZS5pZEdyb3VwQXR0cmlidXRlID09PSBpZEF0dHJpYnV0ZSkge1xyXG4gICAgICAgIGF0dHJpYnV0ZXMucHVzaChhdHRyaWJ1dGUpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gYXR0cmlidXRlcztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldCB0aGUgd2lkdGggd2hpY2ggaXMgYSByZXF1aXJlbWVudCBvZiB0aGUgYWJzb2x1dGUgcG9zaXRpb25pbmcuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcclxuICAgKi9cclxuICBzZXRXaWR0aCh3aWR0aDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgdGhlIHdpZHRoLlxyXG4gICAqXHJcbiAgICogQHJldHVybnMge251bWJlcn1cclxuICAgKi9cclxuICBnZXRXaWR0aCgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMud2lkdGg7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgdGhlIGFycmF5IG9mIGF0dHJpYnV0ZSBjaG9pY2VzIGZvciB0aGUgaWRBdHRyaWJ1dGUuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge251bWJlcn0gaWRBdHRyaWJ1dGVcclxuICAgKiBAcmV0dXJucyB7QXR0cmlidXRlQ2hvaWNlW119XHJcbiAgICovXHJcbiAgZ2V0QXR0cmlidXRlQ2hvaWNlcyhpZEF0dHJpYnV0ZTogbnVtYmVyKTogQXR0cmlidXRlQ2hvaWNlW10ge1xyXG4gICAgcmV0dXJuIHRoaXMuYXR0cmlidXRlTWFwLmdldChpZEF0dHJpYnV0ZSkuYXR0cmlidXRlQ2hvaWNlcztcclxuICB9XHJcblxyXG4gIGdldExvYWRpbmdTdWJqZWN0KCk6IFN1YmplY3Q8Ym9vbGVhbj4ge1xyXG4gICAgcmV0dXJuIHRoaXMubG9hZGluZ1N1YmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgdGhlIGNvbnRhaW5lclVwZGF0ZWQgc3ViamVjdC5cclxuICAgKlxyXG4gICAqIEByZXR1cm5zIHtTdWJqZWN0PG51bWJlcj59XHJcbiAgICovXHJcbiAgZ2V0Q29udGFpbmVyVXBkYXRlZCgpOiBTdWJqZWN0PGJvb2xlYW4+IHtcclxuICAgIHJldHVybiB0aGlzLmNvbnRhaW5lclVwZGF0ZWQ7XHJcbiAgfVxyXG5cclxuICBnZXRHcmlkUm93U2F2ZWRTdWJqZWN0KCk6IFN1YmplY3Q8QXR0cmlidXRlVmFsdWVHcmlkUm93PiB7XHJcbiAgICByZXR1cm4gdGhpcy5ncmlkUm93U2F2ZWQ7XHJcbiAgfVxyXG5cclxuICBnZXRHcmlkUm93RGVsZXRlZFN1YmplY3QoKTogU3ViamVjdDxBdHRyaWJ1dGVWYWx1ZUdyaWRSb3c+IHtcclxuICAgIHJldHVybiB0aGlzLmdyaWRSb3dEZWxldGVkO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2xlYXIgdGhlIHVwZGF0ZWQgYW5kIGRlbGV0ZWQgYXR0cmlidXRlIHZhbHVlIGFycmF5cy5cclxuICAgKlxyXG4gICAqL1xyXG4gIGNsZWFyVXBkYXRlZEF0dHJpYnV0ZVZhbHVlcygpOiB2b2lkIHtcclxuICAgIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzID0gW107XHJcbiAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMgPSBbXTtcclxuICAgIHRoaXMuZGlydHkubmV4dChmYWxzZSk7XHJcbiAgICB0aGlzLm5vdGlmeUF0dHJpYnV0ZXMoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENsZWFyIHRoZSB1cGRhdGVkIGFuZCBkZWxldGVkIGdyaWQgcm93IGF0dHJpYnV0ZXMgZm9yIHRoZSBzcGVjaWZpZWQgZ3JpZCByb3dcclxuICAgKlxyXG4gICAqL1xyXG4gIGNsZWFyVXBkYXRlZEdyaWRSb3dBdHRyaWJ1dGVWYWx1ZXMoZ3JvdXBBdHRyaWJ1dGVSb3dJZDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBsZXQgcmVtYWluaW5nQXR0cmlidXRlcyA9IFtdO1xyXG5cclxuICAgIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzID0gdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMuZmlsdGVyKChhdikgPT4gYXYuZ3JvdXBBdHRyaWJ1dGVSb3dJZCAhPT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCk7XHJcbiAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMgPSAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLmZpbHRlcigoYXYpID0+IGF2Lmdyb3VwQXR0cmlidXRlUm93SWQgIT09IGdyb3VwQXR0cmlidXRlUm93SWQpO1xyXG5cclxuICAgIC8vU2hvdWxkbid0IGJlIGEgbmVlZCB0byBjaGFuZ2UgZGlydHkgb3Igbm90aWZ5IGF0dHJpYnV0ZXNcclxuICB9XHJcblxyXG4gIHNhdmVHcmlkUm93QXR0cmlidXRlVmFsdWVzKGlkR3JvdXBBdHRyaWJ1dGU6IG51bWJlciwgZ3JvdXBBdHRyaWJ1dGVSb3dJZDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBsZXQgcm93VmFsdWVzID0gdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLmZpbHRlcigoYXYpID0+IGF2Lmdyb3VwQXR0cmlidXRlUm93SWQgPT09IGdyb3VwQXR0cmlidXRlUm93SWQpO1xyXG5cclxuICAgIGZvciAobGV0IGogPSAwOyBqIDwgcm93VmFsdWVzLmxlbmd0aDsgaisrKSB7XHJcbiAgICAgIC8vc2V0IHRoZSBpZEF0dHJpYnV0ZVZhbHVlU2V0IGlmIG5lY2Vzc2FyeVxyXG4gICAgICBpZiAoISByb3dWYWx1ZXNbal0uaWRBdHRyaWJ1dGVWYWx1ZVNldCkge1xyXG4gICAgICAgIHJvd1ZhbHVlc1tqXS5pZEF0dHJpYnV0ZVZhbHVlU2V0ID0gdGhpcy5pZEF0dHJpYnV0ZVZhbHVlU2V0O1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvL3JlbW92ZSBhbGwgbmVnYXRpdmUgaWRzIChuZXcgdmFsdWVzKVxyXG4gICAgICBpZiAocm93VmFsdWVzW2pdLmlkQXR0cmlidXRlVmFsdWUgPCAwKSB7XHJcbiAgICAgICAgcm93VmFsdWVzW2pdLmlkQXR0cmlidXRlVmFsdWUgPSB1bmRlZmluZWQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvL0ZvciBtdWx0aSB2YWx1ZXMgdGhhdCB3ZXJlIHNsaWNlZCAoZGUtc2VsZWN0ZWQpIHdlJ3JlIGdvaW5nIHRvIGZpbmQgdGhlbSBhbmQgbnVsbCBvdXQgdGhlIHZhbHVlLCBpbnN0ZWFkIG9mIHJlbW92aW5nLlxyXG4gICAgLy9UaGF0IG1lYW5zIHRoZXkgYWN0YXVsbHkgbmVlZCB0byBiZSBhZGRlZCB0byB0aGUgcm93VmFsdWVzXHJcbiAgICAvL1JlbW92ZWQgbXVsdGkgdmFsdWVzIHdpdGhpbiBhbiBleGlzdGluZyByb3dcclxuICAgIGxldCByZW1vdmVkVmFsdWVzID0gdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMuZmlsdGVyKChhdikgPT4gYXYuZ3JvdXBBdHRyaWJ1dGVSb3dJZCA9PT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCk7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlbW92ZWRWYWx1ZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgcmVtb3ZlZFZhbHVlc1tpXS52YWx1ZUF0dHJpYnV0ZUNob2ljZSA9IHVuZGVmaW5lZDtcclxuICAgICAgcmVtb3ZlZFZhbHVlc1tpXS52YWx1ZUlkRGljdGlvbmFyeSA9IHVuZGVmaW5lZDtcclxuICAgICAgcm93VmFsdWVzLnB1c2gocmVtb3ZlZFZhbHVlc1tpXSk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGF2Z3I6QXR0cmlidXRlVmFsdWVHcmlkUm93ID0gPEF0dHJpYnV0ZVZhbHVlR3JpZFJvdz57XHJcbiAgICAgICAgaWRBdHRyaWJ1dGVWYWx1ZVNldDogdGhpcy5pZEF0dHJpYnV0ZVZhbHVlU2V0LFxyXG4gICAgICAgIGlkR3JvdXBBdHRyaWJ1dGU6IGlkR3JvdXBBdHRyaWJ1dGUsXHJcbiAgICAgICAgZ3JvdXBBdHRyaWJ1dGVSb3dJZDogZ3JvdXBBdHRyaWJ1dGVSb3dJZCxcclxuICAgICAgICBhdHRyaWJ1dGVWYWx1ZXM6IHJvd1ZhbHVlc1xyXG4gICAgICB9O1xyXG5cclxuICAgIGxldCB1cmw6IHN0cmluZyA9IHRoaXMuYXR0cmlidXRlRW5kcG9pbnQgKyBcImF0dHJpYnV0ZS12YWx1ZS1ncmlkLXJvdy9cIiA7XHJcblxyXG4gICAgbGV0IGFjOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uID0gdGhpcy5hdHRyaWJ1dGVDb25maWd1cmF0aW9uU3ViamVjdC5nZXRWYWx1ZSgpO1xyXG5cclxuICAgIGxldCBxdWVyeVBhcmFtczogSHR0cFBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKClcclxuICAgIC5zZXQoXCJjb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0XCIsIGFjLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQpXHJcbiAgICAuc2V0KFwiY29kZUF0dHJpYnV0ZUNvbnRleHRcIiwgYWMuY29kZUF0dHJpYnV0ZUNvbnRleHQpXHJcbiAgICAuc2V0KFwiaWRQYXJlbnRPYmplY3RcIiwgKHRoaXMuaWRQYXJlbnRPYmplY3QpP3RoaXMuaWRQYXJlbnRPYmplY3QudG9TdHJpbmcoKTpcIlwiKTtcclxuXHJcblxyXG4gICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KHRydWUpO1xyXG5cclxuICAgIC8vU2F2ZSBuZXcgcm93XHJcbiAgICBpZiAoZ3JvdXBBdHRyaWJ1dGVSb3dJZCA8IDApIHtcclxuICAgICAgdGhpcy5odHRwLnBvc3QodXJsLCBhdmdyLCB7cGFyYW1zOiBxdWVyeVBhcmFtc30pLnN1YnNjcmliZSgoYXR0cmlidXRlVmFsdWVHcmlkUm93OiBBdHRyaWJ1dGVWYWx1ZUdyaWRSb3cpID0+IHtcclxuXHJcbiAgICAgICAgLy9BZGQgdGhlIGdyaWQgcm93IHRvIHRoZSBvcmlnaW5hbCBhdHRyaWJ1dGUgdmFsdWVzXHJcbiAgICAgICAgbGV0IGF2czpBdHRyaWJ1dGVWYWx1ZVNldCA9IHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCk7XHJcblxyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXR0cmlidXRlVmFsdWVHcmlkUm93LmF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgYXZzLmF0dHJpYnV0ZVZhbHVlcy5wdXNoKGF0dHJpYnV0ZVZhbHVlR3JpZFJvdy5hdHRyaWJ1dGVWYWx1ZXNbaV0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9SZW1vdmUgdGhlIHVwZGF0ZWQgYW5kIHNsaWNlZCB2YWx1ZXMgZm9yIHRoZSBncmlkIHJvdywgbm93ICh0aGVzZSBhcmUgdGhlIG9sZCBvbmVzIHdpdGggdGhlIG5lZ2F0aXZlIHJvd2lkKVxyXG4gICAgICAgIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzID0gdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMuZmlsdGVyKChhdikgPT4gYXYuZ3JvdXBBdHRyaWJ1dGVSb3dJZCAhPT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCk7XHJcbiAgICAgICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzID0gIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5maWx0ZXIoKGF2KSA9PiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkICE9PSBncm91cEF0dHJpYnV0ZVJvd0lkKTtcclxuXHJcbiAgICAgICAgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QubmV4dChhdnMpO1xyXG4gICAgICAgIHRoaXMuZ3JpZFJvd1NhdmVkLm5leHQoYXR0cmlidXRlVmFsdWVHcmlkUm93KTtcclxuICAgICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG4gICAgICB9LFxyXG4gICAgICAoZXJyb3IpID0+IHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcclxuICAgICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIC8vVXBkYXRlIGV4aXN0aW5nIHJvd1xyXG4gICAgZWxzZSB7XHJcbiAgICAgIHRoaXMuaHR0cC5wdXQodXJsLCBhdmdyLCB7cGFyYW1zOiBxdWVyeVBhcmFtc30pLnN1YnNjcmliZSgoYXR0cmlidXRlVmFsdWVHcmlkUm93OiBBdHRyaWJ1dGVWYWx1ZUdyaWRSb3cpID0+IHtcclxuXHJcbiAgICAgICAgLy9BZGQgdGhlIGdyaWQgcm93IHRvIHRoZSBvcmlnaW5hbCBhdHRyaWJ1dGUgdmFsdWVzXHJcbiAgICAgICAgbGV0IGF2czpBdHRyaWJ1dGVWYWx1ZVNldCA9IHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCk7XHJcblxyXG4gICAgICAgIC8vUmVtb3ZlIGFsbCBvbGQgdmFsdWVzIGZvciByb3dcclxuICAgICAgICBsZXQgaW5kZXggPSBhdnMuYXR0cmlidXRlVmFsdWVzLmZpbmRJbmRleCgoYXYpPT4gYXYuZ3JvdXBBdHRyaWJ1dGVSb3dJZCA9PT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCk7XHJcbiAgICAgICAgd2hpbGUgKGluZGV4ID4gMCkge1xyXG4gICAgICAgICAgLy9SZW1vdmUgdmFsdWVcclxuICAgICAgICAgIGF2cy5hdHRyaWJ1dGVWYWx1ZXMuc3BsaWNlKGluZGV4LCAxKTtcclxuXHJcbiAgICAgICAgICAvL0ZpbmQgdGhlIG5leHQgb25lXHJcbiAgICAgICAgICBpbmRleCA9IGF2cy5hdHRyaWJ1dGVWYWx1ZXMuZmluZEluZGV4KChhdik9PiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkID09PSBncm91cEF0dHJpYnV0ZVJvd0lkKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vQWRkIGFsbCB0aGUgY3VycmVudCB2YWx1ZXNcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJpYnV0ZVZhbHVlR3JpZFJvdy5hdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgIGF2cy5hdHRyaWJ1dGVWYWx1ZXMucHVzaChhdHRyaWJ1dGVWYWx1ZUdyaWRSb3cuYXR0cmlidXRlVmFsdWVzW2ldKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vUmVtb3ZlIHRoZSBzbGljZWQgYW5kIHVwZGF0ZWQgdmFsdWVzIGZvciB0aGUgZ3JpZCByb3dcclxuICAgICAgICB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcyA9IHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzLmZpbHRlcigoYXYpID0+IGF2Lmdyb3VwQXR0cmlidXRlUm93SWQgIT09IGdyb3VwQXR0cmlidXRlUm93SWQpO1xyXG4gICAgICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcyA9ICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMuZmlsdGVyKChhdikgPT4gYXYuZ3JvdXBBdHRyaWJ1dGVSb3dJZCAhPT0gZ3JvdXBBdHRyaWJ1dGVSb3dJZCk7XHJcblxyXG4gICAgICAgIHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0Lm5leHQoYXZzKTtcclxuICAgICAgICB0aGlzLmdyaWRSb3dTYXZlZC5uZXh0KGF0dHJpYnV0ZVZhbHVlR3JpZFJvdyk7XHJcbiAgICAgICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuICAgICAgfSxcclxuICAgICAgKGVycm9yKSA9PiB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XHJcbiAgICAgICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBkZWxldGVHcmlkUm93QXR0cmlidXRlVmFsdWVzKGlkR3JvdXBBdHRyaWJ1dGU6IG51bWJlciwgZ3JvdXBBdHRyaWJ1dGVSb3dJZDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBsZXQgdXJsOiBzdHJpbmcgPSB0aGlzLmF0dHJpYnV0ZUVuZHBvaW50ICsgXCJhdHRyaWJ1dGUtdmFsdWUtZ3JpZC1yb3cvXCIgO1xyXG5cclxuICAgIGxldCBhYzogQXR0cmlidXRlQ29uZmlndXJhdGlvbiA9IHRoaXMuYXR0cmlidXRlQ29uZmlndXJhdGlvblN1YmplY3QuZ2V0VmFsdWUoKTtcclxuXHJcbiAgICBsZXQgcXVlcnlQYXJhbXM6IEh0dHBQYXJhbXMgPSBuZXcgSHR0cFBhcmFtcygpXHJcbiAgICAuc2V0KFwiY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dFwiLCBhYy5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0KVxyXG4gICAgLnNldChcImNvZGVBdHRyaWJ1dGVDb250ZXh0XCIsIGFjLmNvZGVBdHRyaWJ1dGVDb250ZXh0KVxyXG4gICAgLnNldChcImlkUGFyZW50T2JqZWN0XCIsICh0aGlzLmlkUGFyZW50T2JqZWN0KT90aGlzLmlkUGFyZW50T2JqZWN0LnRvU3RyaW5nKCk6XCJcIik7XHJcblxyXG4gICAgbGV0IGF2Z3I6QXR0cmlidXRlVmFsdWVHcmlkUm93ID0gPEF0dHJpYnV0ZVZhbHVlR3JpZFJvdz57XHJcbiAgICAgICAgaWRBdHRyaWJ1dGVWYWx1ZVNldDogdGhpcy5pZEF0dHJpYnV0ZVZhbHVlU2V0LFxyXG4gICAgICAgIGlkR3JvdXBBdHRyaWJ1dGU6IGlkR3JvdXBBdHRyaWJ1dGUsXHJcbiAgICAgICAgZ3JvdXBBdHRyaWJ1dGVSb3dJZDogZ3JvdXBBdHRyaWJ1dGVSb3dJZCxcclxuICAgICAgICBhdHRyaWJ1dGVWYWx1ZXM6IFtdXHJcbiAgICAgIH07XHJcblxyXG4gICAgdGhpcy5sb2FkaW5nU3ViamVjdC5uZXh0KHRydWUpO1xyXG5cclxuICAgIHRoaXMuaHR0cC5yZXF1ZXN0KCdkZWxldGUnLCB1cmwsIHtib2R5OiBhdmdyLCBwYXJhbXM6IHF1ZXJ5UGFyYW1zfSkuc3Vic2NyaWJlKCgpID0+IHtcclxuXHJcbiAgICAgIC8vUmVtb3ZlIHRoZSBncmlkIHJvdyBmcm9tIHRoZSBvcmlnaW5hbCBhdHRyaWJ1dGUgdmFsdWVzXHJcbiAgICAgIGxldCBhdnM6QXR0cmlidXRlVmFsdWVTZXQgPSB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpO1xyXG4gICAgICBhdnMuYXR0cmlidXRlVmFsdWVzID0gYXZzLmF0dHJpYnV0ZVZhbHVlcy5maWx0ZXIoKGF2KSA9PiBhdi5ncm91cEF0dHJpYnV0ZVJvd0lkICE9PSBncm91cEF0dHJpYnV0ZVJvd0lkKTtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QubmV4dChhdnMpO1xyXG4gICAgICB0aGlzLmdyaWRSb3dEZWxldGVkLm5leHQoYXZncik7XHJcbiAgICAgIHRoaXMubG9hZGluZ1N1YmplY3QubmV4dChmYWxzZSk7XHJcbiAgICB9LFxyXG4gICAgKGVycm9yKSA9PiB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoZmFsc2UpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQdXNoIGFuIGF0dHJpYnV0ZSB0byB0aGUgYXR0cmlidXRlIG1hcC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlfSBhdHRyaWJ1dGVcclxuICAgKi9cclxuICBwdXNoQXR0cmlidXRlKGF0dHJpYnV0ZTogQXR0cmlidXRlKTogdm9pZCB7XHJcbiAgICB0aGlzLmF0dHJpYnV0ZU1hcC5zZXQoYXR0cmlidXRlLmlkQXR0cmlidXRlLCBhdHRyaWJ1dGUpO1xyXG4gIH1cclxuXHJcblxyXG4gIHB1c2hBdHRyaWJ1dGVWYWx1ZU11bHRpQ2hvaWNlKGF0dHJpYnV0ZVZhbHVlOiBBdHRyaWJ1dGVWYWx1ZSk6IHZvaWQge1xyXG4gICAgLy9SZW1vdmUgZnJvbSBzbGljZWQgaWYgcHJlc2VudFxyXG4gICAgbGV0IGk6IG51bWJlciA9IDA7XHJcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgaWYgKHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzW2ldLmlkQXR0cmlidXRlID09PSBhdHRyaWJ1dGVWYWx1ZS5pZEF0dHJpYnV0ZSAmJiB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlc1tpXS52YWx1ZUF0dHJpYnV0ZUNob2ljZS5pZEF0dHJpYnV0ZUNob2ljZSA9PT0gYXR0cmlidXRlVmFsdWUudmFsdWVBdHRyaWJ1dGVDaG9pY2UuaWRBdHRyaWJ1dGVDaG9pY2UpIHtcclxuICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgLy9SZW1vdmUgZnJvbSBzbGljZWQgYXR0cmlidXRlIHZhbHVlcyAobm8gbG9uZ2VyIHJlbW92aW5nKVxyXG4gICAgaWYgKGkgPCB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5sZW5ndGgpIHtcclxuICAgICAgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMuc3BsaWNlKGksIDEpO1xyXG4gICAgfVxyXG4gICAgLy9PdGhlcndpc2UgcHVzaCB0aGUgdmFsdWUsIHNvIGl0IHdpbGwgYmUgc2F2ZWRcclxuICAgIGVsc2Uge1xyXG4gICAgICB0aGlzLnB1c2hBdHRyaWJ1dGVWYWx1ZShhdHRyaWJ1dGVWYWx1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdXNoQXR0cmlidXRlVmFsdWVNdWx0aURpY3QoYXR0cmlidXRlVmFsdWU6IEF0dHJpYnV0ZVZhbHVlKTogdm9pZCB7XHJcbiAgICAvL1JlbW92ZSBmcm9tIHNsaWNlZCBpZiBwcmVzZW50XHJcbiAgICBsZXQgaTogbnVtYmVyID0gMDtcclxuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAodGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uaWRBdHRyaWJ1dGUgPT09IGF0dHJpYnV0ZVZhbHVlLmlkQXR0cmlidXRlICYmIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzW2ldLnZhbHVlSWREaWN0aW9uYXJ5ID09PSBhdHRyaWJ1dGVWYWx1ZS52YWx1ZUlkRGljdGlvbmFyeSkge1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvL1JlbW92ZSBmcm9tIHNsaWNlZCBhdHRyaWJ1dGUgdmFsdWVzIChubyBsb25nZXIgcmVtb3ZpbmcpXHJcbiAgICBpZiAoaSA8IHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnNsaWNlZEF0dHJpYnV0ZVZhbHVlcy5zcGxpY2UoaSwgMSk7XHJcbiAgICB9XHJcbiAgICAvL090aGVyd2lzZSBwdXNoIHRoZSB2YWx1ZSwgc28gaXQgd2lsbCBiZSBzYXZlZFxyXG4gICAgZWxzZSB7XHJcbiAgICAgIHRoaXMucHVzaEF0dHJpYnV0ZVZhbHVlKGF0dHJpYnV0ZVZhbHVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFB1c2ggYSBuZXcgb3IgdXBkYXRlZCBhdHRyaWJ1dGUgdmFsdWUuICBUaGUgY3VycmVudCBvbmUgaXMganVzdCByZW1vdmVkIGFuZCB0aGUgbmV3IG9uZSBhcHBlbmRlZCB0byB0aGUgYXJyYXkuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge0F0dHJpYnV0ZVZhbHVlfSBhdHRyaWJ1dGVWYWx1ZVxyXG4gICAqL1xyXG4gIHB1c2hBdHRyaWJ1dGVWYWx1ZShhdHRyaWJ1dGVWYWx1ZTogQXR0cmlidXRlVmFsdWUpOiB2b2lkIHtcclxuICAgIGlmIChpc0Rldk1vZGUoKSkge1xyXG4gICAgICBjb25zb2xlLmRlYnVnKFwicHVzaEF0dHJpYnV0ZVZhbHVlXCIpO1xyXG4gICAgICBjb25zb2xlLmRlYnVnKGF0dHJpYnV0ZVZhbHVlKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgaTogbnVtYmVyID0gMDtcclxuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgaWYgKHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZVZhbHVlID09PSBhdHRyaWJ1dGVWYWx1ZS5pZEF0dHJpYnV0ZVZhbHVlKSB7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmIChpIDwgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMuc3BsaWNlKGksIDEpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5wdXNoKGF0dHJpYnV0ZVZhbHVlKTtcclxuICAgIHRoaXMuYXR0cmlidXRlVmFsdWVQdXNoZWRTdWJqZWN0Lm5leHQoYXR0cmlidXRlVmFsdWUpO1xyXG5cclxuICAgIC8vT25seSBzZXR0aW5nIGRpcnR5IGZvciBub24gZ3JpZC1yb3dzICh0aG9zZSBhcmUgc2F2ZWQgaW1tZWRpYXRlbHkpXHJcbiAgICBpZiAoISBhdHRyaWJ1dGVWYWx1ZS5pZEdyb3VwQXR0cmlidXRlKSB7XHJcbiAgICAgIHRoaXMuZGlydHkubmV4dCh0cnVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEZvciBwdXNoaW5nIG11bHRpcGxlIGF0dHJpYnV0ZSB2YWx1ZXMgYXQgb25jZS4gIFRoaXMgd291bGQgdHlwaWNhbGx5IGJlIGZvciBhIG11bHRpIGNob2ljZS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlfSBhdHRyaWJ1dGVcclxuICAgKiBAcGFyYW0ge0F0dHJpYnV0ZVZhbHVlW119IGF0dHJpYnV0ZVZhbHVlc1xyXG4gICAqL1xyXG4gIHB1c2hBdHRyaWJ1dGVWYWx1ZXMoYXR0cmlidXRlOiBBdHRyaWJ1dGUsIGF0dHJpYnV0ZVZhbHVlczogQXR0cmlidXRlVmFsdWVbXSk6IHZvaWQge1xyXG4gICAgaWYgKGlzRGV2TW9kZSgpKSB7XHJcbiAgICAgIGNvbnNvbGUuZGVidWcoXCJwdXNoQXR0cmlidXRlVmFsdWVzXCIpO1xyXG4gICAgICBjb25zb2xlLmRlYnVnKGF0dHJpYnV0ZVZhbHVlcyk7XHJcbiAgICB9XHJcblxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgbGV0IGo6IG51bWJlciA9IDA7XHJcbiAgICAgIGZvciAoaiA9IDA7IGogPCB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoOyBqKyspIHtcclxuICAgICAgICBpZiAodGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2pdLmlkQXR0cmlidXRlICE9PSBhdHRyaWJ1dGUuaWRBdHRyaWJ1dGUpIHtcclxuICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2pdLmlkQXR0cmlidXRlVmFsdWUgPT09IGF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZVZhbHVlKSB7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGogPCB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzW2pdID0gYXR0cmlidXRlVmFsdWVzW2ldO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5wdXNoKGF0dHJpYnV0ZVZhbHVlc1tpXSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZiAoaXNEZXZNb2RlKCkpIHtcclxuICAgICAgY29uc29sZS5kZWJ1Zyh0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vT25seSBzZXR0aW5nIGRpcnR5IGZvciBub24gZ3JpZC1yb3dzICh0aG9zZSBhcmUgc2F2ZWQgaW1tZWRpYXRlbHkpXHJcbiAgICBpZiAoISBhdHRyaWJ1dGUuaWRHcm91cEF0dHJpYnV0ZSkge1xyXG4gICAgICB0aGlzLmRpcnR5Lm5leHQodHJ1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQdXNoIGEgdmFsdWUgaW4gdGhlIGNhc2Ugd2hlcmUgYW4gYXR0cmlidXRlIHZhbHVlIGRvZXNuJ3QgZXhpc3QuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge0F0dHJpYnV0ZX0gYXR0cmlidXRlXHJcbiAgICogQHBhcmFtIHZhbHVlXHJcbiAgICovXHJcbiAgcHVzaFZhbHVlKGF0dHJpYnV0ZTogQXR0cmlidXRlLCB2YWx1ZTogYW55KTogdm9pZCB7XHJcbiAgICBsZXQgYXR0cmlidXRlVmFsdWU6IEF0dHJpYnV0ZVZhbHVlID0gPEF0dHJpYnV0ZVZhbHVlPntcclxuICAgICAgaWRBdHRyaWJ1dGU6IGF0dHJpYnV0ZS5pZEF0dHJpYnV0ZSxcclxuICAgICAgaWRBdHRyaWJ1dGVWYWx1ZVNldDogdGhpcy5pZEF0dHJpYnV0ZVZhbHVlU2V0XHJcbiAgICB9O1xyXG5cclxuICAgIGlmIChhdHRyaWJ1dGUuY29kZUF0dHJpYnV0ZURhdGFUeXBlID09PSBcIlRYVFwiKSB7XHJcbiAgICAgIGF0dHJpYnV0ZVZhbHVlLnZhbHVlTG9uZ1RleHQgPSB7XHJcbiAgICAgICAgaWRMb25nVGV4dDogdW5kZWZpbmVkLFxyXG4gICAgICAgIHRleHREYXRhOiB2YWx1ZVxyXG4gICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlcy5wdXNoKGF0dHJpYnV0ZVZhbHVlKTtcclxuICAgIHRoaXMuZGlydHkubmV4dCh0cnVlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlbW92ZSBhbiBhdHRyaWJ1dGUgdmFsdWUuICBUeXBpY2FsbHkgaW4gdGhlIGNhc2Ugb2YgYSBtdWx0aSBzZWxlY3Qgd2hlcmUgdGhlIHVuc2VsZWN0ZWQgdmFsdWUgaXMgcmVtb3ZlZC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlfSBhdHRyaWJ1dGVcclxuICAgKiBAcGFyYW0ge0F0dHJpYnV0ZUNob2ljZX0gYXR0cmlidXRlQ2hvaWNlXHJcbiAgICovXHJcbiAgc3BsaWNlQXR0cmlidXRlVmFsdWVDaG9pY2UoYXR0cmlidXRlOiBBdHRyaWJ1dGUsIGF0dHJpYnV0ZUNob2ljZTogQXR0cmlidXRlQ2hvaWNlKTogdm9pZCB7XHJcbiAgICBpZiAoaXNEZXZNb2RlKCkpIHtcclxuICAgICAgY29uc29sZS5kZWJ1ZyhcInNsaWNlQXR0cmlidXRlVmFsdWU6IFwiICsgYXR0cmlidXRlLmlkQXR0cmlidXRlICsgXCIsIFwiICsgYXR0cmlidXRlQ2hvaWNlLmlkQXR0cmlidXRlQ2hvaWNlKTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgaTogbnVtYmVyID0gMDtcclxuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgaWYgKHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZSA9PT0gYXR0cmlidXRlLmlkQXR0cmlidXRlICYmIHRoaXMudXBkYXRlZEF0dHJpYnV0ZVZhbHVlc1tpXS52YWx1ZUF0dHJpYnV0ZUNob2ljZS5pZEF0dHJpYnV0ZUNob2ljZSA9PT0gYXR0cmlidXRlQ2hvaWNlLmlkQXR0cmlidXRlQ2hvaWNlKSB7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vUmVtb3ZlIGZyb20gdXBkYXRlZCBhdHRyaWJ1dGUgdmFsdWVzIChub3QgcHJldmlvdXNseSBzYXZlZClcclxuICAgIGlmIChpIDwgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMuc3BsaWNlKGksIDEpO1xyXG4gICAgfVxyXG4gICAgLy9BZGQgdG8gc2xpY2VkIHZhbHVlcyAocHJldmlvdXNseSBzYXZlZCAtIG5lZWQgdG8gcmVtb3ZlKVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpLmF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGlmICh0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpLmF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZSA9PT0gYXR0cmlidXRlLmlkQXR0cmlidXRlXHJcbiAgICAgICAgICAgICYmIHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCkuYXR0cmlidXRlVmFsdWVzW2ldLnZhbHVlQXR0cmlidXRlQ2hvaWNlLmlkQXR0cmlidXRlQ2hvaWNlID09PSBhdHRyaWJ1dGVDaG9pY2UuaWRBdHRyaWJ1dGVDaG9pY2UpIHtcclxuICAgICAgICAgIHRoaXMuc2xpY2VkQXR0cmlidXRlVmFsdWVzLnB1c2godGhpcy5hdHRyaWJ1dGVWYWx1ZVNldFN1YmplY3QuZ2V0VmFsdWUoKS5hdHRyaWJ1dGVWYWx1ZXNbaV0pO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy9Pbmx5IGZsYWdnaW5nIGRpcnR5IGZvciBub24tZ3JpZCByb3dzICh0aG9zZSBhcmUgc2F2ZWQgaW1tZWRpYXRlbHkpXHJcbiAgICBpZiAoISBhdHRyaWJ1dGUuaWRHcm91cEF0dHJpYnV0ZSkge1xyXG4gICAgICB0aGlzLmRpcnR5Lm5leHQodHJ1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIGFuIGF0dHJpYnV0ZSB2YWx1ZS4gIFR5cGljYWxseSBpbiB0aGUgY2FzZSBvZiBhIG11bHRpIHNlbGVjdCB3aGVyZSB0aGUgdW5zZWxlY3RlZCB2YWx1ZSBpcyByZW1vdmVkLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtBdHRyaWJ1dGV9IGF0dHJpYnV0ZVxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlQ2hvaWNlfSBhdHRyaWJ1dGVDaG9pY2VcclxuICAgKi9cclxuICBzcGxpY2VBdHRyaWJ1dGVWYWx1ZURpY3QoYXR0cmlidXRlOiBBdHRyaWJ1dGUsIHZhbHVlOiBhbnkpOiB2b2lkIHtcclxuICAgIGlmIChpc0Rldk1vZGUoKSkge1xyXG4gICAgICBjb25zb2xlLmRlYnVnKFwic2xpY2VBdHRyaWJ1dGVWYWx1ZTogXCIgKyBhdHRyaWJ1dGUuaWRBdHRyaWJ1dGUgKyBcIiwgXCIgKyB2YWx1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGk6IG51bWJlciA9IDA7XHJcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGlmICh0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV0uaWRBdHRyaWJ1dGUgPT09IGF0dHJpYnV0ZS5pZEF0dHJpYnV0ZSAmJiB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXNbaV0udmFsdWVJZERpY3Rpb25hcnkgPT09IHZhbHVlKSB7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vUmVtb3ZlIGZyb20gdXBkYXRlZCBhdHRyaWJ1dGUgdmFsdWVzIChub3QgcHJldmlvdXNseSBzYXZlZClcclxuICAgIGlmIChpIDwgdGhpcy51cGRhdGVkQXR0cmlidXRlVmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnVwZGF0ZWRBdHRyaWJ1dGVWYWx1ZXMuc3BsaWNlKGksIDEpO1xyXG4gICAgfVxyXG4gICAgLy9BZGQgdG8gc2xpY2VkIHZhbHVlcyAocHJldmlvdXNseSBzYXZlZCAtIG5lZWQgdG8gcmVtb3ZlKVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpLmF0dHJpYnV0ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGlmICh0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpLmF0dHJpYnV0ZVZhbHVlc1tpXS5pZEF0dHJpYnV0ZSA9PT0gYXR0cmlidXRlLmlkQXR0cmlidXRlXHJcbiAgICAgICAgICAgICYmIHRoaXMuYXR0cmlidXRlVmFsdWVTZXRTdWJqZWN0LmdldFZhbHVlKCkuYXR0cmlidXRlVmFsdWVzW2ldLnZhbHVlSWREaWN0aW9uYXJ5ID09PSB2YWx1ZSkge1xyXG4gICAgICAgICAgdGhpcy5zbGljZWRBdHRyaWJ1dGVWYWx1ZXMucHVzaCh0aGlzLmF0dHJpYnV0ZVZhbHVlU2V0U3ViamVjdC5nZXRWYWx1ZSgpLmF0dHJpYnV0ZVZhbHVlc1tpXSk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvL09ubHkgZmxhZ2dpbmcgZGlydHkgZm9yIG5vbi1ncmlkIHJvd3MgKHRob3NlIGFyZSBzYXZlZCBpbW1lZGlhdGVseSlcclxuICAgIGlmICghIGF0dHJpYnV0ZS5pZEdyb3VwQXR0cmlidXRlKSB7XHJcbiAgICAgIHRoaXMuZGlydHkubmV4dCh0cnVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB0aGUgYXR0cmlidXRlIGJhc2VkIHVwb24gdGhlIGlkQXR0cmlidXRlLiAgVGhpcyBpcyBmcm9tIHRoZSBtYXAgb2YgYXR0cmlidXRlcy5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpZEF0dHJpYnV0ZVxyXG4gICAqIEByZXR1cm5zIHtBdHRyaWJ1dGV9XHJcbiAgICovXHJcbiAgZ2V0QXR0cmlidXRlKGlkQXR0cmlidXRlOiBudW1iZXIpOiBBdHRyaWJ1dGUge1xyXG4gICAgcmV0dXJuIHRoaXMuYXR0cmlidXRlTWFwLmdldChpZEF0dHJpYnV0ZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBGb3IgdGhlIGF0dHJpYnV0ZSBjb25maWd1cmF0aW9uLCBzZXQgYWxsIG9mIHRoZSBuZWdhdGl2ZSBpZHMgdG8gdW5kZWZpbmVkIHByaW9yIHRvIHBvc3RpbmcuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge0F0dHJpYnV0ZUNvbmZpZ3VyYXRpb259IGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25cclxuICAgKi9cclxuICBzZXROZWdhdGl2ZUlkc1RvVW5kZWZpbmVkKGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24pOiB2b2lkIHtcclxuICAgIGlmIChhdHRyaWJ1dGVDb25maWd1cmF0aW9uLmlkQXR0cmlidXRlQ29uZmlndXJhdGlvbiA8IDApIHtcclxuICAgICAgYXR0cmlidXRlQ29uZmlndXJhdGlvbi5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPSB1bmRlZmluZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgZm9yIChsZXQgYXR0cmlidXRlQ29udGFpbmVyIG9mIGF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24uYXR0cmlidXRlQ29udGFpbmVycykge1xyXG4gICAgICBpZiAoYXR0cmlidXRlQ29udGFpbmVyLmlkQXR0cmlidXRlQ29udGFpbmVyICA8IDApIHtcclxuICAgICAgICBhdHRyaWJ1dGVDb250YWluZXIuaWRBdHRyaWJ1dGVDb250YWluZXIgPSB1bmRlZmluZWQ7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGZvciAobGV0IGF0dHJpYnV0ZSBvZiBhdHRyaWJ1dGVDb250YWluZXIuZ3JhcGhpY2FsQXR0cmlidXRlcykge1xyXG5cclxuICAgICAgICBpZiAoYXR0cmlidXRlLmlkQXR0cmlidXRlICA8IDApIHtcclxuICAgICAgICAgIGF0dHJpYnV0ZS5pZEF0dHJpYnV0ZSA9IHVuZGVmaW5lZDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChhdHRyaWJ1dGUuYXR0cmlidXRlQ2hvaWNlcykge1xyXG4gICAgICAgICAgZm9yIChsZXQgYXR0cmlidXRlQ2hvaWNlIG9mIGF0dHJpYnV0ZS5hdHRyaWJ1dGVDaG9pY2VzKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSBhdHRyaWJ1dGVbXCJ2YWx1ZVwiXTtcclxuXHJcbiAgICAgICAgICAgIGlmIChhdHRyaWJ1dGVDaG9pY2UuaWRBdHRyaWJ1dGUgIDwgMCkge1xyXG4gICAgICAgICAgICAgIGF0dHJpYnV0ZUNob2ljZS5pZEF0dHJpYnV0ZSA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoYXR0cmlidXRlQ2hvaWNlLmlkQXR0cmlidXRlQ2hvaWNlICA8IDApIHtcclxuICAgICAgICAgICAgICBhdHRyaWJ1dGVDaG9pY2UuaWRBdHRyaWJ1dGVDaG9pY2UgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYSBkaXNwbGF5IG5hbWUgZm9yIHRoZSBhdHRyaWJ1dGUgY29uZmlndXJhdGlvbiBiYXNlZCBvbiB0aGUgY29udGV4dCBjb2RlIGFuZCBpZC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7QXR0cmlidXRlQ29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvblxyXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XHJcbiAgICovXHJcbiAgZ2V0Q29uZmlndXJhdGlvbk5hbWUoY29uZmlndXJhdGlvbjogQXR0cmlidXRlQ29uZmlndXJhdGlvbkRUTyk6IHN0cmluZyB7XHJcbiAgICBpZiAoY29uZmlndXJhdGlvbi5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24gPT09IC0xKSB7XHJcbiAgICAgIHJldHVybiBcIk5ld1wiO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBuYW1lOiBzdHJpbmcgPSBjb25maWd1cmF0aW9uLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHREaXNwbGF5ICsgXCI6IFwiICsgY29uZmlndXJhdGlvbi5leHRlbnNpb25EZXNjcmlwdGlvbjtcclxuXHJcbiAgICBpZiAoY29uZmlndXJhdGlvbi5pZEZpbHRlcjEpIHtcclxuICAgICAgbmFtZSArPSBcIiAtIFwiICsgY29uZmlndXJhdGlvbi5maWx0ZXIxRGlzcGxheTtcclxuICAgIH1cclxuICAgIGlmIChjb25maWd1cmF0aW9uLmlkRmlsdGVyMikge1xyXG4gICAgICBuYW1lICs9IFwiIC0gXCIgKyBjb25maWd1cmF0aW9uLmZpbHRlcjJEaXNwbGF5O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5hbWU7XHJcbiAgfVxyXG5cclxuICBnZXRBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPKGNmZzogQXR0cmlidXRlQ29uZmlndXJhdGlvbik6IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8ge1xyXG4gICAgaWYgKCFjZmcpIHtcclxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgZHRvOiBBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPID0gPEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb25EVE8+e1xyXG4gICAgICBpZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IGNmZy5pZEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24sXHJcbiAgICAgIGNvZGVBdHRyaWJ1dGVDb250ZXh0OiBjZmcuY29kZUF0dHJpYnV0ZUNvbnRleHQsXHJcbiAgICAgIGNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQ6IGNmZy5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0LFxyXG4gICAgICBpZEZpbHRlcjE6IGNmZy5pZEZpbHRlcjEsXHJcbiAgICAgIGlkRmlsdGVyMjogY2ZnLmlkRmlsdGVyMlxyXG4gICAgfTtcclxuXHJcbiAgICBpZiAodGhpcy5hdHRyaWJ1dGVDb250ZXh0TGlzdFN1YmplY3QuZ2V0VmFsdWUoKSkge1xyXG4gICAgICBkdG8uZXh0ZW5zaW9uRGVzY3JpcHRpb24gPSB0aGlzLmF0dHJpYnV0ZUNvbnRleHRMaXN0U3ViamVjdC5nZXRWYWx1ZSgpLmZpbHRlcigoY3R4OiBhbnkpID0+IHtcclxuICAgICAgICByZXR1cm4gY3R4LmNvZGVBdHRyaWJ1dGVDb250ZXh0ID09PSBjZmcuY29kZUF0dHJpYnV0ZUNvbnRleHQ7XHJcbiAgICAgIH0pWzBdLmV4dGVuc2lvbkRlc2NyaXB0aW9uO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dExpc3RTdWJqZWN0LmdldFZhbHVlKCkpIHtcclxuICAgICAgbGV0IHJlc3VsdDogYW55W10gPSB0aGlzLmF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dExpc3RTdWJqZWN0LmdldFZhbHVlKCkuZmlsdGVyKChmaWx0ZXI6IGFueSkgPT4ge1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXIuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dCA9PT0gY2ZnLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQ7XHJcbiAgICAgIH0pO1xyXG4gICAgICBkdG8uY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dERpc3BsYXkgPSAocmVzdWx0ICYmIHJlc3VsdC5sZW5ndGggPiAwKSA/IHJlc3VsdFswXS5kZXNjcmlwdGlvbiA6IHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5maWx0ZXIxTGlzdFN1YmplY3QuZ2V0VmFsdWUoKSkge1xyXG4gICAgICBsZXQgcmVzdWx0OiBhbnlbXSA9IHRoaXMuZmlsdGVyMUxpc3RTdWJqZWN0LmdldFZhbHVlKCkuZmlsdGVyKChmaWx0ZXI6IGFueSkgPT4ge1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXIuY29kZUF0dHJpYnV0ZUNvbnRleHQgPT09IGNmZy5jb2RlQXR0cmlidXRlQ29udGV4dFxyXG4gICAgICAgICAgJiYgZmlsdGVyLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQgPT09IGNmZy5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0XHJcbiAgICAgICAgICAmJiBmaWx0ZXIuaWRGaWx0ZXIxID09PSBjZmcuaWRGaWx0ZXIxO1xyXG4gICAgICB9KTtcclxuICAgICAgZHRvLmZpbHRlcjFEaXNwbGF5ID0gKHJlc3VsdCAmJiByZXN1bHQubGVuZ3RoID4gMCkgPyByZXN1bHRbMF0uZGlzcGxheSA6IHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5maWx0ZXIyTGlzdFN1YmplY3QuZ2V0VmFsdWUoKSkge1xyXG4gICAgICBsZXQgcmVzdWx0OiBhbnlbXSA9IHRoaXMuZmlsdGVyMkxpc3RTdWJqZWN0LmdldFZhbHVlKCkuZmlsdGVyKChmaWx0ZXI6IGFueSkgPT4ge1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXIuY29kZUF0dHJpYnV0ZUNvbnRleHQgPT09IGNmZy5jb2RlQXR0cmlidXRlQ29udGV4dFxyXG4gICAgICAgICAgJiYgZmlsdGVyLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQgPT09IGNmZy5jb2RlQXR0cmlidXRlU2VjdXJpdHlDb250ZXh0XHJcbiAgICAgICAgICAmJiBmaWx0ZXIuaWRGaWx0ZXIxID09PSBjZmcuaWRGaWx0ZXIxXHJcbiAgICAgICAgICAmJiBmaWx0ZXIuaWRGaWx0ZXIyID09PSBjZmcuaWRGaWx0ZXIyO1xyXG4gICAgICB9KTtcclxuICAgICAgZHRvLmZpbHRlcjJEaXNwbGF5ID0gKHJlc3VsdCAmJiByZXN1bHQubGVuZ3RoID4gMCkgPyByZXN1bHRbMF0uZGlzcGxheSA6IHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gZHRvO1xyXG4gIH1cclxuXHJcbiAgZ2V0U2VjdXJpdHlDb2RlQ29udGV4dChjb2RlOiBzdHJpbmcpOiBhbnkge1xyXG4gICAgcmV0dXJuIHRoaXMuYXR0cmlidXRlU2VjdXJpdHlDb250ZXh0TGlzdFN1YmplY3QuZ2V0VmFsdWUoKS5maWx0ZXIoKGZpbHRlcjogYW55KSA9PiB7XHJcbiAgICAgIHJldHVybiBmaWx0ZXIuY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dCA9PT0gY29kZTtcclxuICAgIH0pWzBdO1xyXG4gIH1cclxuXHJcbiAgZ2V0QXR0cmlidXRlQ29udGV4dExvYWRpbmdTdWJqZWN0KCk6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPiB7XHJcbiAgICByZXR1cm4gdGhpcy5hdHRyaWJ1dGVDb250ZXh0TG9hZGluZ1N1YmplY3Q7XHJcbiAgfVxyXG5cclxuICBnZXRGaWx0ZXIxRm9yKGNvZGVBdHRyaWJ1dGVDb250ZXh0OiBzdHJpbmcsIGNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQ6IHN0cmluZyk6IGFueVtdIHtcclxuICAgIHJldHVybiB0aGlzLmZpbHRlcjFMaXN0U3ViamVjdC5nZXRWYWx1ZSgpLmZpbHRlcigoaXRlbTogYW55KSA9PiB7XHJcbiAgICAgIHJldHVybiBpdGVtLmNvZGVBdHRyaWJ1dGVDb250ZXh0ID09PSBjb2RlQXR0cmlidXRlQ29udGV4dCAmJiBpdGVtLmNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQgPT09IGNvZGVBdHRyaWJ1dGVTZWN1cml0eUNvbnRleHQ7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGdldEZpbHRlcjJGb3IoY29kZUF0dHJpYnV0ZUNvbnRleHQ6IHN0cmluZywgY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dDogc3RyaW5nLCBpZEZpbHRlcjE6IG51bWJlcik6IGFueVtdIHtcclxuICAgIHJldHVybiB0aGlzLmZpbHRlcjJMaXN0U3ViamVjdC5nZXRWYWx1ZSgpLmZpbHRlcigoaXRlbTogYW55KSA9PiB7XHJcbiAgICAgIHJldHVybiBpdGVtLmNvZGVBdHRyaWJ1dGVDb250ZXh0ID09PSBjb2RlQXR0cmlidXRlQ29udGV4dFxyXG4gICAgICAgICYmIGl0ZW0uY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dCA9PT0gY29kZUF0dHJpYnV0ZVNlY3VyaXR5Q29udGV4dFxyXG4gICAgICAgICYmIGl0ZW0uaWRGaWx0ZXIxID09PSBpZEZpbHRlcjE7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRyYWNrIG5ldyBpZEF0dHJpYnV0ZVZhbHVlcyB2aWEgYSBuZWdhdGl2ZSBudW1iZXIgZm9yIGludGVybmFsIHRyYWNraW5nLiAgUmVtb3ZlIHRoaXMgZmFrZSBpZCBwcmlvciB0byBwb3N0LlxyXG4gICAqXHJcbiAgICogQHJldHVybnMge251bWJlcn1cclxuICAgKi9cclxuICBnZXRVbmlxdWVJZCgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIC0tdGhpcy51bmlxdWVJZDtcclxuICB9XHJcbn1cclxuIl19