@huntsman-cancer-institute/cod 16.0.0 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cod.module.d.ts +31 -31
- package/components/attribute-absolute.component.d.ts +28 -28
- package/components/attribute-base.d.ts +135 -135
- package/components/attribute-configuration.component.d.ts +52 -52
- package/components/attribute-container.component.d.ts +50 -50
- package/components/attribute-default.component.d.ts +20 -20
- package/components/attribute-edit.component.d.ts +15 -15
- package/components/attribute-flex.component.d.ts +25 -25
- package/date/date-util.d.ts +9 -9
- package/esm2022/cod.module.mjs +119 -119
- package/esm2022/components/attribute-absolute.component.mjs +104 -104
- package/esm2022/components/attribute-base.mjs +564 -564
- package/esm2022/components/attribute-configuration.component.mjs +138 -138
- package/esm2022/components/attribute-container.component.mjs +155 -155
- package/esm2022/components/attribute-default.component.mjs +63 -63
- package/esm2022/components/attribute-edit.component.mjs +33 -33
- package/esm2022/components/attribute-flex.component.mjs +58 -58
- package/esm2022/date/date-util.mjs +59 -59
- package/esm2022/huntsman-cancer-institute-cod.mjs +4 -4
- package/esm2022/index.mjs +20 -20
- package/esm2022/model/attribute-choice.entity.mjs +1 -1
- package/esm2022/model/attribute-configuration.dto.mjs +1 -1
- package/esm2022/model/attribute-configuration.entity.mjs +1 -1
- package/esm2022/model/attribute-container.entity.mjs +1 -1
- package/esm2022/model/attribute-dictionary.entity.mjs +1 -1
- package/esm2022/model/attribute-long-text.entity.mjs +1 -1
- package/esm2022/model/attribute-value-grid-row.entity.mjs +1 -1
- package/esm2022/model/attribute-value-set.entity.mjs +1 -1
- package/esm2022/model/attribute-value.entity.mjs +2 -2
- package/esm2022/model/attribute.entity.mjs +1 -1
- package/esm2022/model/dictionary-entries.dto.mjs +2 -2
- package/esm2022/model/extractable-field-status.entity.mjs +1 -1
- package/esm2022/model/graphical-attribute.entity.mjs +1 -1
- package/esm2022/model/pre-eval.dto.mjs +2 -2
- package/esm2022/pipes/is-group-attribute.pipe.mjs +32 -32
- package/esm2022/services/attribute.service.mjs +1211 -1211
- package/fesm2022/huntsman-cancer-institute-cod.mjs +2409 -2409
- package/fesm2022/huntsman-cancer-institute-cod.mjs.map +1 -1
- package/index.d.ts +27 -27
- package/model/attribute-choice.entity.d.ts +16 -16
- package/model/attribute-configuration.dto.d.ts +13 -13
- package/model/attribute-configuration.entity.d.ts +12 -12
- package/model/attribute-container.entity.d.ts +9 -9
- package/model/attribute-dictionary.entity.d.ts +12 -12
- package/model/attribute-long-text.entity.d.ts +4 -4
- package/model/attribute-value-grid-row.entity.d.ts +7 -7
- package/model/attribute-value-set.entity.d.ts +11 -11
- package/model/attribute-value.entity.d.ts +28 -28
- package/model/attribute.entity.d.ts +26 -26
- package/model/dictionary-entries.dto.d.ts +6 -6
- package/model/extractable-field-status.entity.d.ts +8 -8
- package/model/graphical-attribute.entity.d.ts +13 -13
- package/model/pre-eval.dto.d.ts +5 -5
- package/package.json +23 -7
- package/pipes/is-group-attribute.pipe.d.ts +13 -13
- package/services/attribute.service.d.ts +263 -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: "
|
|
1203
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1204
|
-
}
|
|
1205
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1206
|
-
type: Injectable
|
|
1207
|
-
}], ctorParameters:
|
|
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0cmlidXRlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb2Qvc3JjL3NlcnZpY2VzL2F0dHJpYnV0ZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDNUUsT0FBTyxFQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RCxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFdkMsT0FBTyxFQUFDLGVBQWUsRUFBRSxRQUFRLEVBQWMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBRXBFLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLCtDQUErQyxDQUFDO0FBV2hGLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRCxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxpQ0FBaUMsQ0FBQzs7Ozs7QUFHckUsTUFBTSxDQUFDLElBQUksa0JBQWtCLEdBQUcsSUFBSSxjQUFjLENBQVMsbUJBQW1CLENBQUMsQ0FBQztBQUNoRixNQUFNLENBQUMsTUFBTSxPQUFPLEdBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDNUMsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBRTFEOzs7R0FHRztBQUVILE1BQU0sT0FBTyxnQkFBZ0I7SUE4QzNCLFlBQW9CLGlCQUFvQyxFQUNwQyxJQUFnQixFQUNoQixNQUFjLEVBQ2MsaUJBQXlCO1FBSHJELHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUNoQixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2Msc0JB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QUVELGFBQWEsQ0FBQyxvQkFBNEIsRUFBRSw0QkFBb0MsRUFBRSxTQUFpQjtRQUNqRyxPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFTLEVBQUUsRUFBRTtZQUM3RCxPQUFPLElBQUksQ0FBQyxvQkFBb0IsS0FBSyxvQkFBb0I7bUJBQ3BELElBQUksQ0FBQyw0QkFBNEIsS0FBSyw0QkFBNEI7bUJBQ2xFLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxDQUFDO1FBQ3BDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxXQUFXO1FBQ1QsT0FBTyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDekIsQ0FBQzs4R0FsNUNVLGdCQUFnQixtR0FpRFAsa0JBQWtCO2tIQWpEM0IsZ0JBQWdCOzsyRkFBaEIsZ0JBQWdCO2tCQUQ1QixVQUFVOzswQkFrREksTUFBTTsyQkFBQyxrQkFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdCwgSW5qZWN0YWJsZSwgSW5qZWN0aW9uVG9rZW4sIGlzRGV2TW9kZX0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHtIdHRwQ2xpZW50LCBIdHRwUGFyYW1zfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uL2h0dHBcIjtcclxuaW1wb3J0IHtSb3V0ZXJ9IGZyb20gXCJAYW5ndWxhci9yb3V0ZXJcIjtcclxuXHJcbmltcG9ydCB7QmVoYXZpb3JTdWJqZWN0LCBmb3JrSm9pbiwgT2JzZXJ2YWJsZSwgU3ViamVjdH0gZnJvbSBcInJ4anNcIjtcclxuXHJcbmltcG9ydCB7RGljdGlvbmFyeVNlcnZpY2V9IGZyb20gXCJAaHVudHNtYW4tY2FuY2VyLWluc3RpdHV0ZS9kaWN0aW9uYXJ5LXNlcnZpY2VcIjtcclxuXHJcbmltcG9ydCB7QXR0cmlidXRlfSBmcm9tIFwiLi4vbW9kZWwvYXR0cmlidXRlLmVudGl0eVwiO1xyXG5pbXBvcnQge0F0dHJpYnV0ZUNob2ljZX0gZnJvbSBcIi4uL21vZGVsL2F0dHJpYnV0ZS1jaG9pY2UuZW50aXR5XCI7XHJcbmltcG9ydCB7QXR0cmlidXRlVmFsdWV9IGZyb20gXCIuLi9tb2RlbC9hdHRyaWJ1dGUtdmFsdWUuZW50aXR5XCI7XHJcbmltcG9ydCB7QXR0cmlidXRlQ29uZmlndXJhdGlvbn0gZnJvbSBcIi4uL21vZGVsL2F0dHJpYnV0ZS1jb25maWd1cmF0aW9uLmVudGl0eVwiO1xyXG5pbXBvcnQge0F0dHJpYnV0ZVZhbHVlU2V0fSBmcm9tIFwiLi4vbW9kZWwvYXR0cmlidXRlLXZhbHVlLXNldC5lbnRpdHlcIjtcclxuaW1wb3J0IHtBdHRyaWJ1dGVDb25maWd1cmF0aW9uRFRPfSBmcm9tIFwiLi4vbW9kZWwvYXR0cmlidXRlLWNvbmZpZ3VyYXRpb24uZHRvXCI7XHJcbmltcG9ydCB7R3JhcGhpY2FsQXR0cmlidXRlfSBmcm9tIFwiLi4vbW9kZWwvZ3JhcGhpY2FsLWF0dHJpYnV0ZS5lbnRpdHlcIjtcclxuaW1wb3J0IHtBdHRyaWJ1dGVDb250YWluZXJ9IGZyb20gXCIuLi9tb2RlbC9hdHRyaWJ1dGUtY29udGFpbmVyLmVudGl0eVwiO1xyXG5pbXBvcnQge0F0dHJpYnV0ZVZhbHVlR3JpZFJvd30gZnJvbSBcIi4uL21vZGVsL2F0dHJpYnV0ZS12YWx1ZS1ncmlkLXJvdy5lbnRpdHlcIjtcclxuaW1wb3J0IHtQcmVFdmFsRFRPfSBmcm9tIFwiLi4vbW9kZWwvcHJlLWV2YWwuZHRvXCI7XHJcbmltcG9ydCB7RGljdGlvbmFyeUVudHJpZXNEVE99IGZyb20gXCIuLi9tb2RlbC9kaWN0aW9uYXJ5LWVudHJpZXMuZHRvXCI7XHJcblxyXG5cclxuZXhwb3J0IGxldCBBVFRSSUJVVEVfRU5EUE9JTlQgPSBuZXcgSW5qZWN0aW9uVG9rZW48c3RyaW5nPihcImF0dHJpYnV0ZUVuZHBvaW50XCIpO1xyXG5leHBvcnQgY29uc3QgQk9PTEVBTjogc3RyaW5nW10gPSBbXCJOXCIsIFwiWVwiXTtcclxuZXhwb3J0IGNvbnN0IEVYVEVOREVEX0JPT0xFQU46IHN0cmluZ1tdID0gW1wiTlwiLCBcIllcIiwgXCJVXCJdO1xyXG5cclxuLyoqXHJcbiAqIEEgc2VydmljZSBjcmVhdGVkIGZvciBlYWNoIGF0dHJpYnV0ZSBjb25maWd1cmF0aW9uIGluc3RhbmNlLiAgVGhpcyBtYWtlcyBjYWxscyB0byB0aGUgYmFja2VuZCB0byBnZXQgdGhlIGNvbmZpZ3VyYXRpb25cclxuICogYW5kIHZhbHVlIHNldC4gIEl0IGFsc28gc3RvcmVzIGNvbW1vbiBkYXRhIHRoYXQgZGlmZmVyZW50IGF0dHJpYnV0ZXMgbWlnaHQgbmVlZCAoZS5nLiBhIGxpc3Qgb2YgYXR0cmlidXRlIGNob2ljZXMpLlxyXG4gKi9cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgQXR0cmlidXRlU2VydmljZSB7XHJcblxyXG4gIG5ld0F0dHJpYnV0ZUNvbmZpZ3VyYXRpb246IEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb247XHJcbiAgaWRBdHRyaWJ1dGVDb25maWd1cmF0aW9uOiBudW1iZXI7XHJcbiAgaWRGaWx0ZXIxOiBudW1iZXI7XHJcbiAgaWRGaWx0ZXIyOiBudW1iZXI7XHJcbiAgaWRBdHRyaWJ1dGVWYWx1ZVNldDogbnVtYmVyO1xyXG4gIGlkUGFyZW50T2JqZWN0OiBudW1iZXI7XHJcbiAgYm91bmREYXRhOiBhbnk7XHJcblxyXG4gIGF0dHJpYnV0ZUNvbnRleHRMb2FkaW5nU3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+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
|