@eo-sdk/client 11.7.0-beta.1 → 11.7.0-beta.2
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/app/eo-framework/actions/actions/workflow-action/simple-workflow-action.component.d.ts.map +1 -1
- package/app/eo-framework/app-shell/app-bar/app-search/app-search.component.d.ts +1 -1
- package/app/eo-framework/app-shell/app-bar/app-search/app-search.component.d.ts.map +1 -1
- package/app/eo-framework/form-elements/organization/organization.component.d.ts +1 -0
- package/app/eo-framework/form-elements/organization/organization.component.d.ts.map +1 -1
- package/app/eo-framework/grid/grid.component.d.ts +7 -0
- package/app/eo-framework/grid/grid.component.d.ts.map +1 -1
- package/app/eo-framework/object-details/object-details.component.d.ts +1 -0
- package/app/eo-framework/object-details/object-details.component.d.ts.map +1 -1
- package/app/eo-framework/object-details/object-history/object-history.component.d.ts +3 -2
- package/app/eo-framework/object-details/object-history/object-history.component.d.ts.map +1 -1
- package/app/eo-framework/result-list/result-list.component.d.ts.map +1 -1
- package/app/eo-framework/ui/indexdata-summary/indexdata-summary.component.d.ts +50 -0
- package/app/eo-framework/ui/indexdata-summary/indexdata-summary.component.d.ts.map +1 -1
- package/app/eo-framework/ui/indexdata-summary/indexdata-summary.interface.d.ts +10 -0
- package/app/eo-framework/ui/indexdata-summary/indexdata-summary.interface.d.ts.map +1 -0
- package/app/eo-framework-core/search/app-search.service.d.ts +12 -1
- package/app/eo-framework-core/search/app-search.service.d.ts.map +1 -1
- package/assets/_default/i18n/de.json +5 -3
- package/assets/_default/i18n/en.json +1132 -1130
- package/esm2022/app/eo-client/about-state/about-state.component.mjs +3 -3
- package/esm2022/app/eo-framework/actions/actions/workflow-action/simple-workflow-action.component.mjs +2 -2
- package/esm2022/app/eo-framework/app-shell/app-bar/app-search/app-search.component.mjs +18 -4
- package/esm2022/app/eo-framework/form-elements/organization/organization.component.mjs +25 -16
- package/esm2022/app/eo-framework/grid/extensions/filter/text/text-filter.component.mjs +3 -3
- package/esm2022/app/eo-framework/grid/grid.component.mjs +32 -6
- package/esm2022/app/eo-framework/object-details/object-details.component.mjs +8 -6
- package/esm2022/app/eo-framework/object-details/object-history/object-history.component.mjs +11 -6
- package/esm2022/app/eo-framework/result-list/result-list.component.mjs +7 -2
- package/esm2022/app/eo-framework/ui/indexdata-summary/indexdata-summary-entry/indexdata-summary-entry.component.mjs +2 -2
- package/esm2022/app/eo-framework/ui/indexdata-summary/indexdata-summary.component.mjs +138 -5
- package/esm2022/app/eo-framework/ui/indexdata-summary/indexdata-summary.interface.mjs +2 -0
- package/esm2022/app/eo-framework-core/search/app-search.service.mjs +25 -4
- package/fesm2022/eo-sdk-client.mjs +264 -725
- package/fesm2022/eo-sdk-client.mjs.map +1 -1
- package/misc/scripts/copy-client-assets.js +1 -1
- package/package.json +3 -3
- package/proxy.config.js +13 -0
- package/app/eo-framework/grid/row-grouping/batchRemover.d.ts +0 -13
- package/app/eo-framework/grid/row-grouping/batchRemover.d.ts.map +0 -1
- package/app/eo-framework/grid/row-grouping/group-stage.d.ts +0 -45
- package/app/eo-framework/grid/row-grouping/group-stage.d.ts.map +0 -1
- package/app/eo-framework/grid/row-grouping/row-grouping.module.d.ts +0 -8
- package/app/eo-framework/grid/row-grouping/row-grouping.module.d.ts.map +0 -1
- package/esm2022/app/eo-framework/grid/row-grouping/batchRemover.mjs +0 -50
- package/esm2022/app/eo-framework/grid/row-grouping/group-stage.mjs +0 -623
- package/esm2022/app/eo-framework/grid/row-grouping/row-grouping.module.mjs +0 -8
- package/proxy.config.json +0 -97
|
@@ -1,623 +0,0 @@
|
|
|
1
|
-
import { __decorate } from "tslib";
|
|
2
|
-
import { _, Autowired, Bean, BeanStub, RowNode } from "@ag-grid-community/core";
|
|
3
|
-
import { BatchRemover } from "./batchRemover";
|
|
4
|
-
let GroupStage = class GroupStage extends BeanStub {
|
|
5
|
-
execute(params) {
|
|
6
|
-
const details = this.createGroupingDetails(params);
|
|
7
|
-
if (details.transactions) {
|
|
8
|
-
this.handleTransaction(details);
|
|
9
|
-
}
|
|
10
|
-
else {
|
|
11
|
-
const afterColsChanged = params.afterColumnsChanged === true;
|
|
12
|
-
this.shotgunResetEverything(details, afterColsChanged);
|
|
13
|
-
}
|
|
14
|
-
if (!details.usingTreeData) {
|
|
15
|
-
// we don't do group sorting for tree data
|
|
16
|
-
this.positionLeafsAndGroups(params.changedPath);
|
|
17
|
-
this.orderGroups(details);
|
|
18
|
-
}
|
|
19
|
-
this.selectableService.updateSelectableAfterGrouping();
|
|
20
|
-
}
|
|
21
|
-
positionLeafsAndGroups(changedPath) {
|
|
22
|
-
changedPath.forEachChangedNodeDepthFirst(group => {
|
|
23
|
-
if (group.childrenAfterGroup) {
|
|
24
|
-
const leafNodes = [];
|
|
25
|
-
const groupNodes = [];
|
|
26
|
-
let unbalancedNode;
|
|
27
|
-
group.childrenAfterGroup.forEach(row => {
|
|
28
|
-
if (!row.childrenAfterGroup?.length) {
|
|
29
|
-
leafNodes.push(row);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
if (row.key === '' && !unbalancedNode) {
|
|
33
|
-
unbalancedNode = row;
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
groupNodes.push(row);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
if (unbalancedNode) {
|
|
41
|
-
groupNodes.push(unbalancedNode);
|
|
42
|
-
}
|
|
43
|
-
group.childrenAfterGroup = [...leafNodes, ...groupNodes];
|
|
44
|
-
}
|
|
45
|
-
}, false);
|
|
46
|
-
}
|
|
47
|
-
createGroupingDetails(params) {
|
|
48
|
-
const { rowNode, changedPath, rowNodeTransactions, rowNodeOrder } = params;
|
|
49
|
-
const usingTreeData = this.gos.get('treeData');
|
|
50
|
-
const groupedCols = usingTreeData ? null : this.columnModel.getRowGroupColumns();
|
|
51
|
-
const details = {
|
|
52
|
-
// someone complained that the parent attribute was causing some change detection
|
|
53
|
-
// to break in an angular add-on. Taking the parent out breaks a cyclic dependency, hence this flag got introduced.
|
|
54
|
-
includeParents: !this.gos.get('suppressParentsInRowNodes'),
|
|
55
|
-
expandByDefault: this.gos.get('groupDefaultExpanded'),
|
|
56
|
-
groupedCols: groupedCols,
|
|
57
|
-
rootNode: rowNode,
|
|
58
|
-
pivotMode: this.columnModel.isPivotMode(),
|
|
59
|
-
groupedColCount: usingTreeData || !groupedCols ? 0 : groupedCols.length,
|
|
60
|
-
rowNodeOrder: rowNodeOrder,
|
|
61
|
-
transactions: rowNodeTransactions,
|
|
62
|
-
// if no transaction, then it's shotgun, changed path would be 'not active' at this point anyway
|
|
63
|
-
changedPath: changedPath,
|
|
64
|
-
groupAllowUnbalanced: this.gos.get('groupAllowUnbalanced'),
|
|
65
|
-
isGroupOpenByDefault: this.gos.getCallback('isGroupOpenByDefault'),
|
|
66
|
-
initialGroupOrderComparator: this.gos.getCallback('initialGroupOrderComparator'),
|
|
67
|
-
usingTreeData: usingTreeData,
|
|
68
|
-
suppressGroupMaintainValueType: this.gos.get('suppressGroupMaintainValueType'),
|
|
69
|
-
getDataPath: usingTreeData ? this.gos.get('getDataPath') : undefined,
|
|
70
|
-
keyCreators: groupedCols?.map(column => column.getColDef().keyCreator) ?? []
|
|
71
|
-
};
|
|
72
|
-
return details;
|
|
73
|
-
}
|
|
74
|
-
handleTransaction(details) {
|
|
75
|
-
details.transactions.forEach(tran => {
|
|
76
|
-
// we don't allow batch remover for tree data as tree data uses Filler Nodes,
|
|
77
|
-
// and creating/deleting filler nodes needs to be done alongside the node deleting
|
|
78
|
-
// and moving. if we want to Batch Remover working with tree data then would need
|
|
79
|
-
// to consider how Filler Nodes would be impacted (it's possible that it can be easily
|
|
80
|
-
// modified to work, however for now I don't have the brain energy to work it all out).
|
|
81
|
-
const batchRemover = !details.usingTreeData ? new BatchRemover() : undefined;
|
|
82
|
-
// the order here of [add, remove, update] needs to be the same as in ClientSideNodeManager,
|
|
83
|
-
// as the order is important when a record with the same id is added and removed in the same
|
|
84
|
-
// transaction.
|
|
85
|
-
if (_.existsAndNotEmpty(tran.remove)) {
|
|
86
|
-
this.removeNodes(tran.remove, details, batchRemover);
|
|
87
|
-
}
|
|
88
|
-
if (_.existsAndNotEmpty(tran.update)) {
|
|
89
|
-
this.moveNodesInWrongPath(tran.update, details, batchRemover);
|
|
90
|
-
}
|
|
91
|
-
if (_.existsAndNotEmpty(tran.add)) {
|
|
92
|
-
this.insertNodes(tran.add, details, false);
|
|
93
|
-
}
|
|
94
|
-
// must flush here, and not allow another transaction to be applied,
|
|
95
|
-
// as each transaction must finish leaving the data in a consistent state.
|
|
96
|
-
if (batchRemover) {
|
|
97
|
-
const parentsWithChildrenRemoved = batchRemover.getAllParents().slice();
|
|
98
|
-
batchRemover.flush();
|
|
99
|
-
this.removeEmptyGroups(parentsWithChildrenRemoved, details);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
if (details.rowNodeOrder) {
|
|
103
|
-
this.sortChildren(details);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// this is used when doing delta updates, eg Redux, keeps nodes in right order
|
|
107
|
-
sortChildren(details) {
|
|
108
|
-
details.changedPath.forEachChangedNodeDepthFirst(node => {
|
|
109
|
-
if (!node.childrenAfterGroup) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
const didSort = _.sortRowNodesByOrder(node.childrenAfterGroup, details.rowNodeOrder);
|
|
113
|
-
if (didSort) {
|
|
114
|
-
details.changedPath.addParentNode(node);
|
|
115
|
-
}
|
|
116
|
-
}, false, true);
|
|
117
|
-
}
|
|
118
|
-
orderGroups(details) {
|
|
119
|
-
const comparator = details.initialGroupOrderComparator;
|
|
120
|
-
if (_.exists(comparator)) {
|
|
121
|
-
recursiveSort(details.rootNode);
|
|
122
|
-
}
|
|
123
|
-
function recursiveSort(rowNode) {
|
|
124
|
-
const doSort = _.exists(rowNode.childrenAfterGroup) &&
|
|
125
|
-
// we only want to sort groups, so we do not sort leafs (a leaf group has leafs as children)
|
|
126
|
-
!rowNode.leafGroup;
|
|
127
|
-
if (doSort) {
|
|
128
|
-
rowNode.childrenAfterGroup.sort((nodeA, nodeB) => comparator({ nodeA, nodeB }));
|
|
129
|
-
rowNode.childrenAfterGroup.forEach((childNode) => recursiveSort(childNode));
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
getExistingPathForNode(node, details) {
|
|
134
|
-
const res = [];
|
|
135
|
-
// when doing tree data, the node is part of the path,
|
|
136
|
-
// but when doing grid grouping, the node is not part of the path so we start with the parent.
|
|
137
|
-
let pointer = details.usingTreeData ? node : node.parent;
|
|
138
|
-
while (pointer && pointer !== details.rootNode) {
|
|
139
|
-
res.push({
|
|
140
|
-
key: pointer.key,
|
|
141
|
-
rowGroupColumn: pointer.rowGroupColumn,
|
|
142
|
-
field: pointer.field
|
|
143
|
-
});
|
|
144
|
-
pointer = pointer.parent;
|
|
145
|
-
}
|
|
146
|
-
res.reverse();
|
|
147
|
-
return res;
|
|
148
|
-
}
|
|
149
|
-
moveNodesInWrongPath(childNodes, details, batchRemover) {
|
|
150
|
-
childNodes.forEach(childNode => {
|
|
151
|
-
// we add node, even if parent has not changed, as the data could have
|
|
152
|
-
// changed, hence aggregations will be wrong
|
|
153
|
-
if (details.changedPath.isActive()) {
|
|
154
|
-
details.changedPath.addParentNode(childNode.parent);
|
|
155
|
-
}
|
|
156
|
-
const infoToKeyMapper = (item) => item.key;
|
|
157
|
-
const oldPath = this.getExistingPathForNode(childNode, details).map(infoToKeyMapper);
|
|
158
|
-
const newPath = this.getGroupInfo(childNode, details).map(infoToKeyMapper);
|
|
159
|
-
const nodeInCorrectPath = _.areEqual(oldPath, newPath);
|
|
160
|
-
if (!nodeInCorrectPath) {
|
|
161
|
-
this.moveNode(childNode, details, batchRemover);
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
moveNode(childNode, details, batchRemover) {
|
|
166
|
-
this.removeNodesInStages([childNode], details, batchRemover);
|
|
167
|
-
this.insertOneNode(childNode, details, true, batchRemover);
|
|
168
|
-
// hack - if we didn't do this, then renaming a tree item (ie changing rowNode.key) wouldn't get
|
|
169
|
-
// refreshed into the gui.
|
|
170
|
-
// this is needed to kick off the event that rowComp listens to for refresh. this in turn
|
|
171
|
-
// then will get each cell in the row to refresh - which is what we need as we don't know which
|
|
172
|
-
// columns will be displaying the rowNode.key info.
|
|
173
|
-
childNode.setData(childNode.data);
|
|
174
|
-
// we add both old and new parents to changed path, as both will need to be refreshed.
|
|
175
|
-
// we already added the old parent (in calling method), so just add the new parent here
|
|
176
|
-
if (details.changedPath.isActive()) {
|
|
177
|
-
const newParent = childNode.parent;
|
|
178
|
-
details.changedPath.addParentNode(newParent);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
removeNodes(leafRowNodes, details, batchRemover) {
|
|
182
|
-
this.removeNodesInStages(leafRowNodes, details, batchRemover);
|
|
183
|
-
if (details.changedPath.isActive()) {
|
|
184
|
-
leafRowNodes.forEach(rowNode => details.changedPath.addParentNode(rowNode.parent));
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
removeNodesInStages(leafRowNodes, details, batchRemover) {
|
|
188
|
-
this.removeNodesFromParents(leafRowNodes, details, batchRemover);
|
|
189
|
-
if (details.usingTreeData) {
|
|
190
|
-
this.postRemoveCreateFillerNodes(leafRowNodes, details);
|
|
191
|
-
// When not TreeData, then removeEmptyGroups is called just before the BatchRemover is flushed.
|
|
192
|
-
// However for TreeData, there is no BatchRemover, so we have to call removeEmptyGroups here.
|
|
193
|
-
const nodeParents = leafRowNodes.map(n => n.parent);
|
|
194
|
-
this.removeEmptyGroups(nodeParents, details);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
forEachParentGroup(details, group, callback) {
|
|
198
|
-
let pointer = group;
|
|
199
|
-
while (pointer && pointer !== details.rootNode) {
|
|
200
|
-
callback(pointer);
|
|
201
|
-
pointer = pointer.parent;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
removeNodesFromParents(nodesToRemove, details, provided) {
|
|
205
|
-
// this method can be called with BatchRemover as optional. if it is missed, we created a local version
|
|
206
|
-
// and flush it at the end. if one is provided, we add to the provided one and it gets flushed elsewhere.
|
|
207
|
-
const batchRemoverIsLocal = provided == null;
|
|
208
|
-
const batchRemoverToUse = provided ? provided : new BatchRemover();
|
|
209
|
-
nodesToRemove.forEach(nodeToRemove => {
|
|
210
|
-
this.removeFromParent(nodeToRemove, batchRemoverToUse);
|
|
211
|
-
// remove from allLeafChildren. we clear down all parents EXCEPT the Root Node, as
|
|
212
|
-
// the ClientSideNodeManager is responsible for the Root Node.
|
|
213
|
-
this.forEachParentGroup(details, nodeToRemove.parent, parentNode => {
|
|
214
|
-
batchRemoverToUse.removeFromAllLeafChildren(parentNode, nodeToRemove);
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
if (batchRemoverIsLocal) {
|
|
218
|
-
batchRemoverToUse.flush();
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
postRemoveCreateFillerNodes(nodesToRemove, details) {
|
|
222
|
-
nodesToRemove.forEach(nodeToRemove => {
|
|
223
|
-
// if not group, and children are present, need to move children to a group.
|
|
224
|
-
// otherwise if no children, we can just remove without replacing.
|
|
225
|
-
const replaceWithGroup = nodeToRemove.hasChildren();
|
|
226
|
-
if (replaceWithGroup) {
|
|
227
|
-
const oldPath = this.getExistingPathForNode(nodeToRemove, details);
|
|
228
|
-
// because we just removed the userGroup, this will always return new support group
|
|
229
|
-
const newGroupNode = this.findParentForNode(nodeToRemove, oldPath, details);
|
|
230
|
-
// these properties are the ones that will be incorrect in the newly created group,
|
|
231
|
-
// so copy them from the old childNode
|
|
232
|
-
newGroupNode.expanded = nodeToRemove.expanded;
|
|
233
|
-
newGroupNode.allLeafChildren = nodeToRemove.allLeafChildren;
|
|
234
|
-
newGroupNode.childrenAfterGroup = nodeToRemove.childrenAfterGroup;
|
|
235
|
-
newGroupNode.childrenMapped = nodeToRemove.childrenMapped;
|
|
236
|
-
newGroupNode.updateHasChildren();
|
|
237
|
-
newGroupNode.childrenAfterGroup.forEach(rowNode => rowNode.parent = newGroupNode);
|
|
238
|
-
}
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
removeEmptyGroups(possibleEmptyGroups, details) {
|
|
242
|
-
// we do this multiple times, as when we remove groups, that means the parent of just removed
|
|
243
|
-
// group can then be empty. to get around this, if we remove, then we check everything again for
|
|
244
|
-
// newly emptied groups. the max number of times this will execute is the depth of the group tree.
|
|
245
|
-
let checkAgain = true;
|
|
246
|
-
const groupShouldBeRemoved = (rowNode) => {
|
|
247
|
-
// because of the while loop below, it's possible we already moved the node,
|
|
248
|
-
// so double check before trying to remove again.
|
|
249
|
-
const mapKey = this.getChildrenMappedKey(rowNode.key, rowNode.rowGroupColumn);
|
|
250
|
-
const parentRowNode = rowNode.parent;
|
|
251
|
-
const groupAlreadyRemoved = (parentRowNode && parentRowNode.childrenMapped) ?
|
|
252
|
-
!parentRowNode.childrenMapped[mapKey] : true;
|
|
253
|
-
if (groupAlreadyRemoved) {
|
|
254
|
-
// if not linked, then group was already removed
|
|
255
|
-
return false;
|
|
256
|
-
}
|
|
257
|
-
// if still not removed, then we remove if this group is empty
|
|
258
|
-
return !!rowNode.isEmptyRowGroupNode();
|
|
259
|
-
};
|
|
260
|
-
while (checkAgain) {
|
|
261
|
-
checkAgain = false;
|
|
262
|
-
const batchRemover = new BatchRemover();
|
|
263
|
-
possibleEmptyGroups.forEach(possibleEmptyGroup => {
|
|
264
|
-
// remove empty groups
|
|
265
|
-
this.forEachParentGroup(details, possibleEmptyGroup, rowNode => {
|
|
266
|
-
if (groupShouldBeRemoved(rowNode)) {
|
|
267
|
-
checkAgain = true;
|
|
268
|
-
this.removeFromParent(rowNode, batchRemover);
|
|
269
|
-
// we remove selection on filler nodes here, as the selection would not be removed
|
|
270
|
-
// from the RowNodeManager, as filler nodes don't exist on the RowNodeManager
|
|
271
|
-
rowNode.setSelectedParams({ newValue: false, source: 'rowGroupChanged' });
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
batchRemover.flush();
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
// removes the node from the parent by:
|
|
279
|
-
// a) removing from childrenAfterGroup (using batchRemover if present, otherwise immediately)
|
|
280
|
-
// b) removing from childrenMapped (immediately)
|
|
281
|
-
// c) setRowTop(null) - as the rowRenderer uses this to know the RowNode is no longer needed
|
|
282
|
-
// d) setRowIndex(null) - as the rowNode will no longer be displayed.
|
|
283
|
-
removeFromParent(child, batchRemover) {
|
|
284
|
-
if (child.parent) {
|
|
285
|
-
if (batchRemover) {
|
|
286
|
-
batchRemover.removeFromChildrenAfterGroup(child.parent, child);
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
_.removeFromArray(child.parent.childrenAfterGroup, child);
|
|
290
|
-
child.parent.updateHasChildren();
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
const mapKey = this.getChildrenMappedKey(child.key, child.rowGroupColumn);
|
|
294
|
-
if (child.parent && child.parent.childrenMapped) {
|
|
295
|
-
child.parent.childrenMapped[mapKey] = undefined;
|
|
296
|
-
}
|
|
297
|
-
// this is important for transition, see rowComp removeFirstPassFuncs. when doing animation and
|
|
298
|
-
// remove, if rowTop is still present, the rowComp thinks it's just moved position.
|
|
299
|
-
child.setRowTop(null);
|
|
300
|
-
child.setRowIndex(null);
|
|
301
|
-
}
|
|
302
|
-
addToParent(child, parent) {
|
|
303
|
-
const mapKey = this.getChildrenMappedKey(child.key, child.rowGroupColumn);
|
|
304
|
-
if (parent) {
|
|
305
|
-
const children = parent.childrenMapped != null;
|
|
306
|
-
if (children) {
|
|
307
|
-
parent.childrenMapped[mapKey] = child;
|
|
308
|
-
}
|
|
309
|
-
parent.childrenAfterGroup.push(child);
|
|
310
|
-
parent.updateHasChildren();
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
areGroupColsEqual(d1, d2) {
|
|
314
|
-
if (d1 == null || d2 == null || d1.pivotMode !== d2.pivotMode) {
|
|
315
|
-
return false;
|
|
316
|
-
}
|
|
317
|
-
return _.areEqual(d1.groupedCols, d2.groupedCols) && _.areEqual(d1.keyCreators, d2.keyCreators);
|
|
318
|
-
}
|
|
319
|
-
checkAllGroupDataAfterColsChanged(details) {
|
|
320
|
-
const recurse = (rowNodes) => {
|
|
321
|
-
if (!rowNodes) {
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
rowNodes.forEach(rowNode => {
|
|
325
|
-
const isLeafNode = !details.usingTreeData && !rowNode.group;
|
|
326
|
-
if (isLeafNode) {
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
const groupInfo = {
|
|
330
|
-
field: rowNode.field,
|
|
331
|
-
key: rowNode.key,
|
|
332
|
-
rowGroupColumn: rowNode.rowGroupColumn,
|
|
333
|
-
leafNode: rowNode.allLeafChildren[0],
|
|
334
|
-
};
|
|
335
|
-
this.setGroupData(rowNode, groupInfo, details);
|
|
336
|
-
recurse(rowNode.childrenAfterGroup);
|
|
337
|
-
});
|
|
338
|
-
};
|
|
339
|
-
recurse(details.rootNode.childrenAfterGroup);
|
|
340
|
-
}
|
|
341
|
-
shotgunResetEverything(details, afterColumnsChanged) {
|
|
342
|
-
if (this.noChangeInGroupingColumns(details, afterColumnsChanged)) {
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
// groups are about to get disposed, so need to deselect any that are selected
|
|
346
|
-
this.selectionService.filterFromSelection((node) => node && !node.group);
|
|
347
|
-
const { rootNode, groupedCols } = details;
|
|
348
|
-
// because we are not creating the root node each time, we have the logic
|
|
349
|
-
// here to change leafGroup once.
|
|
350
|
-
// we set .leafGroup to false for tree data, as .leafGroup is only used when pivoting, and pivoting
|
|
351
|
-
// isn't allowed with treeData, so the grid never actually use .leafGroup when doing treeData.
|
|
352
|
-
rootNode.leafGroup = details.usingTreeData ? false : groupedCols.length === 0;
|
|
353
|
-
// we are doing everything from scratch, so reset childrenAfterGroup and childrenMapped from the rootNode
|
|
354
|
-
rootNode.childrenAfterGroup = [];
|
|
355
|
-
rootNode.childrenMapped = {};
|
|
356
|
-
rootNode.updateHasChildren();
|
|
357
|
-
const sibling = rootNode.sibling;
|
|
358
|
-
if (sibling) {
|
|
359
|
-
sibling.childrenAfterGroup = rootNode.childrenAfterGroup;
|
|
360
|
-
sibling.childrenMapped = rootNode.childrenMapped;
|
|
361
|
-
}
|
|
362
|
-
this.insertNodes(rootNode.allLeafChildren, details, false);
|
|
363
|
-
}
|
|
364
|
-
noChangeInGroupingColumns(details, afterColumnsChanged) {
|
|
365
|
-
let noFurtherProcessingNeeded = false;
|
|
366
|
-
const groupDisplayColumns = this.columnModel.getGroupDisplayColumns();
|
|
367
|
-
const newGroupDisplayColIds = groupDisplayColumns ?
|
|
368
|
-
groupDisplayColumns.map(c => c.getId()).join('-') : '';
|
|
369
|
-
if (afterColumnsChanged) {
|
|
370
|
-
// we only need to redo grouping if doing normal grouping (ie not tree data)
|
|
371
|
-
// and the group cols have changed.
|
|
372
|
-
noFurtherProcessingNeeded = details.usingTreeData || this.areGroupColsEqual(details, this.oldGroupingDetails);
|
|
373
|
-
// if the group display cols have changed, then we need to update rowNode.groupData
|
|
374
|
-
// (regardless of tree data or row grouping)
|
|
375
|
-
if (this.oldGroupDisplayColIds !== newGroupDisplayColIds) {
|
|
376
|
-
this.checkAllGroupDataAfterColsChanged(details);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
this.oldGroupingDetails = details;
|
|
380
|
-
this.oldGroupDisplayColIds = newGroupDisplayColIds;
|
|
381
|
-
return noFurtherProcessingNeeded;
|
|
382
|
-
}
|
|
383
|
-
insertNodes(newRowNodes, details, isMove) {
|
|
384
|
-
newRowNodes.forEach(rowNode => {
|
|
385
|
-
this.insertOneNode(rowNode, details, isMove);
|
|
386
|
-
if (details.changedPath.isActive()) {
|
|
387
|
-
details.changedPath.addParentNode(rowNode.parent);
|
|
388
|
-
}
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
insertOneNode(childNode, details, isMove, batchRemover) {
|
|
392
|
-
const path = this.getGroupInfo(childNode, details);
|
|
393
|
-
const parentGroup = this.findParentForNode(childNode, path, details, batchRemover);
|
|
394
|
-
if (!parentGroup.group) {
|
|
395
|
-
console.warn(`AG Grid: duplicate group keys for row data, keys should be unique`, [parentGroup.data, childNode.data]);
|
|
396
|
-
}
|
|
397
|
-
if (details.usingTreeData) {
|
|
398
|
-
this.swapGroupWithUserNode(parentGroup, childNode, isMove);
|
|
399
|
-
}
|
|
400
|
-
else {
|
|
401
|
-
childNode.parent = parentGroup;
|
|
402
|
-
childNode.level = path.length;
|
|
403
|
-
parentGroup.childrenAfterGroup.push(childNode);
|
|
404
|
-
parentGroup.updateHasChildren();
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
findParentForNode(childNode, path, details, batchRemover) {
|
|
408
|
-
let nextNode = details.rootNode;
|
|
409
|
-
path.forEach((groupInfo, level) => {
|
|
410
|
-
nextNode = this.getOrCreateNextNode(nextNode, groupInfo, level, details);
|
|
411
|
-
// node gets added to all group nodes.
|
|
412
|
-
// note: we do not add to rootNode here, as the rootNode is the master list of rowNodes
|
|
413
|
-
if (!batchRemover?.isRemoveFromAllLeafChildren(nextNode, childNode)) {
|
|
414
|
-
nextNode.allLeafChildren.push(childNode);
|
|
415
|
-
}
|
|
416
|
-
else {
|
|
417
|
-
// if this node is about to be removed, prevent that
|
|
418
|
-
batchRemover?.preventRemoveFromAllLeafChildren(nextNode, childNode);
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
return nextNode;
|
|
422
|
-
}
|
|
423
|
-
swapGroupWithUserNode(fillerGroup, userGroup, isMove) {
|
|
424
|
-
userGroup.parent = fillerGroup.parent;
|
|
425
|
-
userGroup.key = fillerGroup.key;
|
|
426
|
-
userGroup.field = fillerGroup.field;
|
|
427
|
-
userGroup.groupData = fillerGroup.groupData;
|
|
428
|
-
userGroup.level = fillerGroup.level;
|
|
429
|
-
// AG-3441 - preserve the existing expanded status of the node if we're moving it, so that
|
|
430
|
-
// you can drag a sub tree from one parent to another without changing its expansion
|
|
431
|
-
if (!isMove) {
|
|
432
|
-
userGroup.expanded = fillerGroup.expanded;
|
|
433
|
-
}
|
|
434
|
-
// we set .leafGroup to false for tree data, as .leafGroup is only used when pivoting, and pivoting
|
|
435
|
-
// isn't allowed with treeData, so the grid never actually use .leafGroup when doing treeData.
|
|
436
|
-
userGroup.leafGroup = fillerGroup.leafGroup;
|
|
437
|
-
// always null for userGroups, as row grouping is not allowed when doing tree data
|
|
438
|
-
userGroup.rowGroupIndex = fillerGroup.rowGroupIndex;
|
|
439
|
-
userGroup.allLeafChildren = fillerGroup.allLeafChildren;
|
|
440
|
-
userGroup.childrenAfterGroup = fillerGroup.childrenAfterGroup;
|
|
441
|
-
userGroup.childrenMapped = fillerGroup.childrenMapped;
|
|
442
|
-
userGroup.sibling = fillerGroup.sibling;
|
|
443
|
-
userGroup.updateHasChildren();
|
|
444
|
-
this.removeFromParent(fillerGroup);
|
|
445
|
-
userGroup.childrenAfterGroup.forEach((rowNode) => rowNode.parent = userGroup);
|
|
446
|
-
this.addToParent(userGroup, fillerGroup.parent);
|
|
447
|
-
}
|
|
448
|
-
getOrCreateNextNode(parentGroup, groupInfo, level, details) {
|
|
449
|
-
const key = this.getChildrenMappedKey(groupInfo.key, groupInfo.rowGroupColumn);
|
|
450
|
-
let nextNode = parentGroup.childrenMapped ? parentGroup.childrenMapped[key] : undefined;
|
|
451
|
-
if (!nextNode) {
|
|
452
|
-
nextNode = this.createGroup(groupInfo, parentGroup, level, details);
|
|
453
|
-
// attach the new group to the parent
|
|
454
|
-
this.addToParent(nextNode, parentGroup);
|
|
455
|
-
}
|
|
456
|
-
return nextNode;
|
|
457
|
-
}
|
|
458
|
-
createGroup(groupInfo, parent, level, details) {
|
|
459
|
-
const groupNode = new RowNode(this.beans);
|
|
460
|
-
groupNode.group = true;
|
|
461
|
-
groupNode.field = groupInfo.field;
|
|
462
|
-
groupNode.rowGroupColumn = groupInfo.rowGroupColumn;
|
|
463
|
-
this.setGroupData(groupNode, groupInfo, details);
|
|
464
|
-
groupNode.key = groupInfo.key;
|
|
465
|
-
groupNode.id = this.createGroupId(groupNode, parent, details.usingTreeData, level);
|
|
466
|
-
groupNode.level = level;
|
|
467
|
-
groupNode.leafGroup = details.usingTreeData ? false : level === (details.groupedColCount - 1);
|
|
468
|
-
groupNode.allLeafChildren = [];
|
|
469
|
-
// why is this done here? we are not updating the children count as we go,
|
|
470
|
-
// i suspect this is updated in the filter stage
|
|
471
|
-
groupNode.setAllChildrenCount(0);
|
|
472
|
-
groupNode.rowGroupIndex = details.usingTreeData ? null : level;
|
|
473
|
-
groupNode.childrenAfterGroup = [];
|
|
474
|
-
groupNode.childrenMapped = {};
|
|
475
|
-
groupNode.updateHasChildren();
|
|
476
|
-
groupNode.parent = details.includeParents ? parent : null;
|
|
477
|
-
this.setExpandedInitialValue(details, groupNode);
|
|
478
|
-
return groupNode;
|
|
479
|
-
}
|
|
480
|
-
createGroupId(node, parent, usingTreeData, level) {
|
|
481
|
-
let createGroupId;
|
|
482
|
-
if (usingTreeData) {
|
|
483
|
-
createGroupId = (node, parent, level) => {
|
|
484
|
-
if (level < 0) {
|
|
485
|
-
return null;
|
|
486
|
-
} // root node
|
|
487
|
-
const parentId = parent ? createGroupId(parent, parent.parent, level - 1) : null;
|
|
488
|
-
return `${parentId == null ? '' : parentId + '-'}${level}-${node.key}`;
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
else {
|
|
492
|
-
createGroupId = (node, parent) => {
|
|
493
|
-
if (!node.rowGroupColumn) {
|
|
494
|
-
return null;
|
|
495
|
-
} // root node
|
|
496
|
-
const parentId = parent ? createGroupId(parent, parent.parent, 0) : null;
|
|
497
|
-
return `${parentId == null ? '' : parentId + '-'}${node.rowGroupColumn.getColId()}-${node.key}`;
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
// we put 'row-group-' before the group id, so it doesn't clash with standard row id's. we also use 't-' and 'b-'
|
|
501
|
-
// for top pinned and bottom pinned rows.
|
|
502
|
-
return RowNode.ID_PREFIX_ROW_GROUP + createGroupId(node, parent, level);
|
|
503
|
-
}
|
|
504
|
-
setGroupData(groupNode, groupInfo, details) {
|
|
505
|
-
groupNode.groupData = {};
|
|
506
|
-
const groupDisplayCols = this.columnModel.getGroupDisplayColumns();
|
|
507
|
-
groupDisplayCols.forEach(col => {
|
|
508
|
-
// newGroup.rowGroupColumn=null when working off GroupInfo, and we always display the group in the group column
|
|
509
|
-
// if rowGroupColumn is present, then it's grid row grouping and we only include if configuration says so
|
|
510
|
-
const isTreeData = details.usingTreeData;
|
|
511
|
-
if (isTreeData) {
|
|
512
|
-
groupNode.groupData[col.getColId()] = groupInfo.key;
|
|
513
|
-
return;
|
|
514
|
-
}
|
|
515
|
-
const groupColumn = groupNode.rowGroupColumn;
|
|
516
|
-
const isRowGroupDisplayed = groupColumn !== null && col.isRowGroupDisplayed(groupColumn.getId());
|
|
517
|
-
if (isRowGroupDisplayed) {
|
|
518
|
-
if (details.suppressGroupMaintainValueType) {
|
|
519
|
-
groupNode.groupData[col.getColId()] = groupInfo.key;
|
|
520
|
-
}
|
|
521
|
-
else {
|
|
522
|
-
// if maintain group value type, get the value from any leaf node.
|
|
523
|
-
groupNode.groupData[col.getColId()] = this.valueService.getValue(groupColumn, groupInfo.leafNode);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
});
|
|
527
|
-
}
|
|
528
|
-
getChildrenMappedKey(key, rowGroupColumn) {
|
|
529
|
-
if (rowGroupColumn) {
|
|
530
|
-
// grouping by columns
|
|
531
|
-
return rowGroupColumn.getId() + '-' + key;
|
|
532
|
-
}
|
|
533
|
-
// tree data - we don't have rowGroupColumns
|
|
534
|
-
return key;
|
|
535
|
-
}
|
|
536
|
-
setExpandedInitialValue(details, groupNode) {
|
|
537
|
-
// if pivoting the leaf group is never expanded as we do not show leaf rows
|
|
538
|
-
if (details.pivotMode && groupNode.leafGroup) {
|
|
539
|
-
groupNode.expanded = false;
|
|
540
|
-
return;
|
|
541
|
-
}
|
|
542
|
-
// use callback if exists
|
|
543
|
-
const userCallback = details.isGroupOpenByDefault;
|
|
544
|
-
if (userCallback) {
|
|
545
|
-
const params = {
|
|
546
|
-
rowNode: groupNode,
|
|
547
|
-
field: groupNode.field,
|
|
548
|
-
key: groupNode.key,
|
|
549
|
-
level: groupNode.level,
|
|
550
|
-
rowGroupColumn: groupNode.rowGroupColumn
|
|
551
|
-
};
|
|
552
|
-
groupNode.expanded = userCallback(params) == true;
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
// use expandByDefault if exists
|
|
556
|
-
const { expandByDefault } = details;
|
|
557
|
-
if (details.expandByDefault === -1) {
|
|
558
|
-
groupNode.expanded = true;
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
// otherwise
|
|
562
|
-
groupNode.expanded = groupNode.level < expandByDefault;
|
|
563
|
-
}
|
|
564
|
-
getGroupInfo(rowNode, details) {
|
|
565
|
-
if (details.usingTreeData) {
|
|
566
|
-
return this.getGroupInfoFromCallback(rowNode, details);
|
|
567
|
-
}
|
|
568
|
-
return this.getGroupInfoFromGroupColumns(rowNode, details);
|
|
569
|
-
}
|
|
570
|
-
getGroupInfoFromCallback(rowNode, details) {
|
|
571
|
-
const keys = details.getDataPath ? details.getDataPath(rowNode.data) : null;
|
|
572
|
-
if (keys === null || keys === undefined || keys.length === 0) {
|
|
573
|
-
_.warnOnce(`getDataPath() should not return an empty path for data ${rowNode.data}`);
|
|
574
|
-
}
|
|
575
|
-
const groupInfoMapper = (key) => ({ key, field: null, rowGroupColumn: null });
|
|
576
|
-
return keys ? keys.map(groupInfoMapper) : [];
|
|
577
|
-
}
|
|
578
|
-
getGroupInfoFromGroupColumns(rowNode, details) {
|
|
579
|
-
const res = [];
|
|
580
|
-
details.groupedCols.forEach(groupCol => {
|
|
581
|
-
let key = this.valueService.getKeyForNode(groupCol, rowNode);
|
|
582
|
-
let keyExists = key !== null && key !== undefined && key !== '';
|
|
583
|
-
// unbalanced tree and pivot mode don't work together - not because of the grid, it doesn't make
|
|
584
|
-
// mathematical sense as you are building up a cube. so if pivot mode, we put in a blank key where missing.
|
|
585
|
-
// this keeps the tree balanced and hence can be represented as a group.
|
|
586
|
-
const createGroupForEmpty = details.pivotMode || !details.groupAllowUnbalanced;
|
|
587
|
-
if (createGroupForEmpty && !keyExists) {
|
|
588
|
-
key = '';
|
|
589
|
-
keyExists = true;
|
|
590
|
-
}
|
|
591
|
-
if (keyExists) {
|
|
592
|
-
const item = {
|
|
593
|
-
key: key,
|
|
594
|
-
field: groupCol.getColDef().field,
|
|
595
|
-
rowGroupColumn: groupCol,
|
|
596
|
-
leafNode: rowNode,
|
|
597
|
-
};
|
|
598
|
-
res.push(item);
|
|
599
|
-
}
|
|
600
|
-
});
|
|
601
|
-
return res;
|
|
602
|
-
}
|
|
603
|
-
};
|
|
604
|
-
__decorate([
|
|
605
|
-
Autowired('columnModel')
|
|
606
|
-
], GroupStage.prototype, "columnModel", void 0);
|
|
607
|
-
__decorate([
|
|
608
|
-
Autowired('selectableService')
|
|
609
|
-
], GroupStage.prototype, "selectableService", void 0);
|
|
610
|
-
__decorate([
|
|
611
|
-
Autowired('valueService')
|
|
612
|
-
], GroupStage.prototype, "valueService", void 0);
|
|
613
|
-
__decorate([
|
|
614
|
-
Autowired('beans')
|
|
615
|
-
], GroupStage.prototype, "beans", void 0);
|
|
616
|
-
__decorate([
|
|
617
|
-
Autowired('selectionService')
|
|
618
|
-
], GroupStage.prototype, "selectionService", void 0);
|
|
619
|
-
GroupStage = __decorate([
|
|
620
|
-
Bean('groupStage')
|
|
621
|
-
], GroupStage);
|
|
622
|
-
export { GroupStage };
|
|
623
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JvdXAtc3RhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL2VvLWZyYW1ld29yay9ncmlkL3Jvdy1ncm91cGluZy9ncm91cC1zdGFnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUNILENBQUMsRUFDRCxTQUFTLEVBQ1QsSUFBSSxFQUNKLFFBQVEsRUFPUixPQUFPLEVBV1YsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUErQnZDLElBQU0sVUFBVSxHQUFoQixNQUFNLFVBQVcsU0FBUSxRQUFRO0lBaUI3QixPQUFPLENBQUMsTUFBMEI7UUFFckMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRW5ELElBQUksT0FBTyxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNwQyxDQUFDO2FBQU0sQ0FBQztZQUNKLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixLQUFLLElBQUksQ0FBQztZQUM3RCxJQUFJLENBQUMsc0JBQXNCLENBQUMsT0FBTyxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDM0QsQ0FBQztRQUVELElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDekIsMENBQTBDO1lBQzFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsV0FBWSxDQUFDLENBQUM7WUFDakQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM5QixDQUFDO1FBRUQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLDZCQUE2QixFQUFFLENBQUM7SUFDM0QsQ0FBQztJQUVPLHNCQUFzQixDQUFDLFdBQXdCO1FBQ25ELFdBQVcsQ0FBQyw0QkFBNEIsQ0FB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QUFDO2dCQUNmLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkIsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxHQUFHLENBQUM7SUFDZixDQUFDO0NBQ0osQ0FBQTtBQXZzQnFDO0lBQWpDLFNBQVMsQ0FBQyxhQUFhLENBQUM7K0NBQWtDO0FBQ25CO0lBQXZDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQztxREFBOEM7QUFDMUM7SUFBbEMsU0FBUyxDQUFDLGNBQWMsQ0FBQztnREFBb0M7QUFDbEM7SUFBM0IsU0FBUyxDQUFDLE9BQU8sQ0FBQzt5Q0FBc0I7QUFDRjtJQUF0QyxTQUFTLENBQUMsa0JBQWtCLENBQUM7b0RBQTZDO0FBTmxFLFVBQVU7SUFEdEIsSUFBSSxDQUFDLFlBQVksQ0FBQztHQUNOLFVBQVUsQ0F5c0J0QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgICBfLFxyXG4gICAgQXV0b3dpcmVkLFxyXG4gICAgQmVhbixcclxuICAgIEJlYW5TdHViLFxyXG4gICAgQ2hhbmdlZFBhdGgsXHJcbiAgICBDb2x1bW4sXHJcbiAgICBDb2x1bW5Nb2RlbCxcclxuICAgIEdldERhdGFQYXRoLFxyXG4gICAgSVJvd05vZGVTdGFnZSxcclxuICAgIElzR3JvdXBPcGVuQnlEZWZhdWx0UGFyYW1zLFxyXG4gICAgUm93Tm9kZSxcclxuICAgIFJvd05vZGVUcmFuc2FjdGlvbixcclxuICAgIFNlbGVjdGFibGVTZXJ2aWNlLFxyXG4gICAgU3RhZ2VFeGVjdXRlUGFyYW1zLFxyXG4gICAgVmFsdWVTZXJ2aWNlLFxyXG4gICAgQmVhbnMsXHJcbiAgICBJU2VsZWN0aW9uU2VydmljZSxcclxuICAgIFdpdGhvdXRHcmlkQ29tbW9uLFxyXG4gICAgSW5pdGlhbEdyb3VwT3JkZXJDb21wYXJhdG9yUGFyYW1zLFxyXG4gICAgR3JpZE9wdGlvbnMsXHJcbiAgICBLZXlDcmVhdG9yUGFyYW1zXHJcbn0gZnJvbSBcIkBhZy1ncmlkLWNvbW11bml0eS9jb3JlXCI7XHJcbmltcG9ydCB7IEJhdGNoUmVtb3ZlciB9IGZyb20gXCIuL2JhdGNoUmVtb3ZlclwiO1xyXG5cclxuaW50ZXJmYWNlIEdyb3VwSW5mbyB7XHJcbiAgICBrZXk6IHN0cmluZzsgLy8gZS5nLiAnSXJlbGFuZCdcclxuICAgIGZpZWxkOiBzdHJpbmcgfCBudWxsOyAvLyBlLmcuICdjb3VudHJ5J1xyXG4gICAgcm93R3JvdXBDb2x1bW46IENvbHVtbiB8IG51bGw7XHJcbiAgICBsZWFmTm9kZT86IFJvd05vZGU7XHJcbn1cclxuXHJcbmludGVyZmFjZSBHcm91cGluZ0RldGFpbHMge1xyXG4gICAgcGl2b3RNb2RlOiBib29sZWFuO1xyXG4gICAgaW5jbHVkZVBhcmVudHM6IGJvb2xlYW47XHJcbiAgICBleHBhbmRCeURlZmF1bHQ6IG51bWJlcjtcclxuICAgIGNoYW5nZWRQYXRoOiBDaGFuZ2VkUGF0aDtcclxuICAgIHJvb3ROb2RlOiBSb3dOb2RlO1xyXG4gICAgZ3JvdXBlZENvbHM6IENvbHVtbltdO1xyXG4gICAgZ3JvdXBlZENvbENvdW50OiBudW1iZXI7XHJcbiAgICB0cmFuc2FjdGlvbnM6IFJvd05vZGVUcmFuc2FjdGlvbltdO1xyXG4gICAgcm93Tm9kZU9yZGVyOiB7IFtpZDogc3RyaW5nXTogbnVtYmVyOyB9O1xyXG4gICAgXHJcbiAgICBncm91cEFsbG93VW5iYWxhbmNlZDogYm9vbGVhbjtcclxuICAgIGlzR3JvdXBPcGVuQnlEZWZhdWx0OiAocGFyYW1zOiBXaXRob3V0R3JpZENvbW1vbjxJc0dyb3VwT3BlbkJ5RGVmYXVsdFBhcmFtcz4pID0+IGJvb2xlYW47XHJcbiAgICBpbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3I6IChwYXJhbXM6IFdpdGhvdXRHcmlkQ29tbW9uPEluaXRpYWxHcm91cE9yZGVyQ29tcGFyYXRvclBhcmFtcz4pID0+IG51bWJlcjtcclxuICAgIFxyXG4gICAgdXNpbmdUcmVlRGF0YTogYm9vbGVhbjtcclxuICAgIHN1cHByZXNzR3JvdXBNYWludGFpblZhbHVlVHlwZTogYm9vbGVhbjtcclxuICAgIGdldERhdGFQYXRoOiBHZXREYXRhUGF0aCB8IHVuZGVmaW5lZDtcclxuICAgIGtleUNyZWF0b3JzOiAoKChwYXJhbXM6IEtleUNyZWF0b3JQYXJhbXMpID0+IHN0cmluZykgfCB1bmRlZmluZWQpW107XHJcbn1cclxuXHJcbkBCZWFuKCdncm91cFN0YWdlJylcclxuZXhwb3J0IGNsYXNzIEdyb3VwU3RhZ2UgZXh0ZW5kcyBCZWFuU3R1YiBpbXBsZW1lbnRzIElSb3dOb2RlU3RhZ2Uge1xyXG5cclxuICAgIEBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJykgcHJpdmF0ZSBjb2x1bW5Nb2RlbDogQ29sdW1uTW9kZWw7XHJcbiAgICBAQXV0b3dpcmVkKCdzZWxlY3RhYmxlU2VydmljZScpIHByaXZhdGUgc2VsZWN0YWJsZVNlcnZpY2U6IFNlbGVjdGFibGVTZXJ2aWNlO1xyXG4gICAgQEF1dG93aXJlZCgndmFsdWVTZXJ2aWNlJykgcHJpdmF0ZSB2YWx1ZVNlcnZpY2U6IFZhbHVlU2VydmljZTtcclxuICAgIEBBdXRvd2lyZWQoJ2JlYW5zJykgcHJpdmF0ZSBiZWFuczogQmVhbnM7XHJcbiAgICBAQXV0b3dpcmVkKCdzZWxlY3Rpb25TZXJ2aWNlJykgcHJpdmF0ZSBzZWxlY3Rpb25TZXJ2aWNlOiBJU2VsZWN0aW9uU2VydmljZTtcclxuXHJcbiAgICAvLyB3aGVuIGdyb3VwaW5nLCB0aGVzZSBpdGVtcyBhcmUgb2Ygbm90ZTpcclxuICAgIC8vIHJvd05vZGUucGFyZW50OiBSb3dOb2RlOiBzZXQgdG8gdGhlIHBhcmVudFxyXG4gICAgLy8gcm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXA6IFJvd05vZGVbXSA9IHRoZSBkaXJlY3QgY2hpbGRyZW4gb2YgdGhpcyBncm91cFxyXG4gICAgLy8gcm93Tm9kZS5jaGlsZHJlbk1hcHBlZDogc3RyaW5nPT5Sb3dOb2RlID0gY2hpbGRyZW4gbWFwcGVkIGJ5IGdyb3VwIGtleSAod2hlbiBncm91cHMpIG9yIGFuIGVtcHR5IG1hcCBpZiBsZWFmIGdyb3VwICh0aGlzIGlzIHRoZW4gdXNlZCBieSBwaXZvdClcclxuICAgIC8vIGZvciBsZWFmIGdyb3Vwcywgcm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXAgPSByb3dOb2RlLmFsbExlYWZDaGlsZHJlbjtcclxuXHJcbiAgICBwcml2YXRlIG9sZEdyb3VwaW5nRGV0YWlsczogR3JvdXBpbmdEZXRhaWxzO1xyXG4gICAgcHJpdmF0ZSBvbGRHcm91cERpc3BsYXlDb2xJZHM6IHN0cmluZztcclxuXHJcbiAgICBwdWJsaWMgZXhlY3V0ZShwYXJhbXM6IFN0YWdlRXhlY3V0ZVBhcmFtcyk6IHZvaWQge1xyXG5cclxuICAgICAgICBjb25zdCBkZXRhaWxzID0gdGhpcy5jcmVhdGVHcm91cGluZ0RldGFpbHMocGFyYW1zKTtcclxuXHJcbiAgICAgICAgaWYgKGRldGFpbHMudHJhbnNhY3Rpb25zKSB7XHJcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlVHJhbnNhY3Rpb24oZGV0YWlscyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc3QgYWZ0ZXJDb2xzQ2hhbmdlZCA9IHBhcmFtcy5hZnRlckNvbHVtbnNDaGFuZ2VkID09PSB0cnVlO1xyXG4gICAgICAgICAgICB0aGlzLnNob3RndW5SZXNldEV2ZXJ5dGhpbmcoZGV0YWlscywgYWZ0ZXJDb2xzQ2hhbmdlZCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIWRldGFpbHMudXNpbmdUcmVlRGF0YSkge1xyXG4gICAgICAgICAgICAvLyB3ZSBkb24ndCBkbyBncm91cCBzb3J0aW5nIGZvciB0cmVlIGRhdGFcclxuICAgICAgICAgICAgdGhpcy5wb3NpdGlvbkxlYWZzQW5kR3JvdXBzKHBhcmFtcy5jaGFuZ2VkUGF0aCEpO1xyXG4gICAgICAgICAgICB0aGlzLm9yZGVyR3JvdXBzKGRldGFpbHMpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5zZWxlY3RhYmxlU2VydmljZS51cGRhdGVTZWxlY3RhYmxlQWZ0ZXJHcm91cGluZygpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgcG9zaXRpb25MZWFmc0FuZEdyb3VwcyhjaGFuZ2VkUGF0aDogQ2hhbmdlZFBhdGgpIHtcclxuICAgICAgICBjaGFuZ2VkUGF0aC5mb3JFYWNoQ2hhbmdlZE5vZGVEZXB0aEZpcnN0KGdyb3VwID0+IHtcclxuICAgICAgICAgICAgaWYgKGdyb3VwLmNoaWxkcmVuQWZ0ZXJHcm91cCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbGVhZk5vZGVzOiBSb3dOb2RlW10gPSBbXTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGdyb3VwTm9kZXM6IFJvd05vZGVbXSA9IFtdO1xyXG4gICAgICAgICAgICAgICAgbGV0IHVuYmFsYW5jZWROb2RlOiBSb3dOb2RlIHwgdW5kZWZpbmVkO1xyXG5cclxuICAgICAgICAgICAgICAgIGdyb3VwLmNoaWxkcmVuQWZ0ZXJHcm91cC5mb3JFYWNoKHJvdyA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFyb3cuY2hpbGRyZW5BZnRlckdyb3VwPy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGVhZk5vZGVzLnB1c2gocm93KTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocm93LmtleSA9PT0gJycgJiYgIXVuYmFsYW5jZWROb2RlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmJhbGFuY2VkTm9kZSA9IHJvdztcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwTm9kZXMucHVzaChyb3cpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHVuYmFsYW5jZWROb2RlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBOb2Rlcy5wdXNoKHVuYmFsYW5jZWROb2RlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgZ3JvdXAuY2hpbGRyZW5BZnRlckdyb3VwID0gWy4uLmxlYWZOb2RlcywgLi4uZ3JvdXBOb2Rlc107XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LCBmYWxzZSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBjcmVhdGVHcm91cGluZ0RldGFpbHMocGFyYW1zOiBTdGFnZUV4ZWN1dGVQYXJhbXMpOiBHcm91cGluZ0RldGFpbHMge1xyXG4gICAgICAgIGNvbnN0IHsgcm93Tm9kZSwgY2hhbmdlZFBhdGgsIHJvd05vZGVUcmFuc2FjdGlvbnMsIHJvd05vZGVPcmRlciB9ID0gcGFyYW1zO1xyXG5cclxuICAgICAgICBjb25zdCB1c2luZ1RyZWVEYXRhID0gdGhpcy5nb3MuZ2V0KCd0cmVlRGF0YScpO1xyXG5cclxuICAgICAgICBjb25zdCBncm91cGVkQ29scyA9IHVzaW5nVHJlZURhdGEgPyBudWxsIDogdGhpcy5jb2x1bW5Nb2RlbC5nZXRSb3dHcm91cENvbHVtbnMoKTtcclxuXHJcbiAgICAgICAgY29uc3QgZGV0YWlsczogR3JvdXBpbmdEZXRhaWxzID0ge1xyXG4gICAgICAgICAgICAvLyBzb21lb25lIGNvbXBsYWluZWQgdGhhdCB0aGUgcGFyZW50IGF0dHJpYnV0ZSB3YXMgY2F1c2luZyBzb21lIGNoYW5nZSBkZXRlY3Rpb25cclxuICAgICAgICAgICAgLy8gdG8gYnJlYWsgaW4gYW4gYW5ndWxhciBhZGQtb24uICBUYWtpbmcgdGhlIHBhcmVudCBvdXQgYnJlYWtzIGEgY3ljbGljIGRlcGVuZGVuY3ksIGhlbmNlIHRoaXMgZmxhZyBnb3QgaW50cm9kdWNlZC5cclxuICAgICAgICAgICAgaW5jbHVkZVBhcmVudHM6ICF0aGlzLmdvcy5nZXQoJ3N1cHByZXNzUGFyZW50c0luUm93Tm9kZXMnKSxcclxuICAgICAgICAgICAgZXhwYW5kQnlEZWZhdWx0OiB0aGlzLmdvcy5nZXQoJ2dyb3VwRGVmYXVsdEV4cGFuZGVkJyksXHJcbiAgICAgICAgICAgIGdyb3VwZWRDb2xzOiBncm91cGVkQ29scyEsXHJcbiAgICAgICAgICAgIHJvb3ROb2RlOiByb3dOb2RlLFxyXG4gICAgICAgICAgICBwaXZvdE1vZGU6IHRoaXMuY29sdW1uTW9kZWwuaXNQaXZvdE1vZGUoKSxcclxuICAgICAgICAgICAgZ3JvdXBlZENvbENvdW50OiB1c2luZ1RyZWVEYXRhIHx8ICFncm91cGVkQ29scyA/IDAgOiBncm91cGVkQ29scy5sZW5ndGgsXHJcbiAgICAgICAgICAgIHJvd05vZGVPcmRlcjogcm93Tm9kZU9yZGVyISxcclxuICAgICAgICAgICAgdHJhbnNhY3Rpb25zOiByb3dOb2RlVHJhbnNhY3Rpb25zISxcclxuICAgICAgICAgICAgLy8gaWYgbm8gdHJhbnNhY3Rpb24sIHRoZW4gaXQncyBzaG90Z3VuLCBjaGFuZ2VkIHBhdGggd291bGQgYmUgJ25vdCBhY3RpdmUnIGF0IHRoaXMgcG9pbnQgYW55d2F5XHJcbiAgICAgICAgICAgIGNoYW5nZWRQYXRoOiBjaGFuZ2VkUGF0aCEsXHJcbiAgICAgICAgICAgIGdyb3VwQWxsb3dVbmJhbGFuY2VkOiAgdGhpcy5nb3MuZ2V0KCdncm91cEFsbG93VW5iYWxhbmNlZCcpLFxyXG4gICAgICAgICAgICBpc0dyb3VwT3BlbkJ5RGVmYXVsdDogdGhpcy5nb3MuZ2V0Q2FsbGJhY2soJ2lzR3JvdXBPcGVuQnlEZWZhdWx0JykgYXMgYW55LFxyXG4gICAgICAgICAgICBpbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3I6IHRoaXMuZ29zLmdldENhbGxiYWNrKCdpbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3InKSBhcyBhbnksXHJcbiAgICAgICAgICAgIHVzaW5nVHJlZURhdGE6IHVzaW5nVHJlZURhdGEsXHJcbiAgICAgICAgICAgIHN1cHByZXNzR3JvdXBNYWludGFpblZhbHVlVHlwZTogdGhpcy5nb3MuZ2V0KCdzdXBwcmVzc0dyb3VwTWFpbnRhaW5WYWx1ZVR5cGUnKSxcclxuICAgICAgICAgICAgZ2V0RGF0YVBhdGg6IHVzaW5nVHJlZURhdGEgPyB0aGlzLmdvcy5nZXQoJ2dldERhdGFQYXRoJykgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIGtleUNyZWF0b3JzOiBncm91cGVkQ29scz8ubWFwKGNvbHVtbiA9PiBjb2x1bW4uZ2V0Q29sRGVmKCkua2V5Q3JlYXRvcikgPz8gW11cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICByZXR1cm4gZGV0YWlscztcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGhhbmRsZVRyYW5zYWN0aW9uKGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscyk6IHZvaWQge1xyXG5cclxuICAgICAgICBkZXRhaWxzLnRyYW5zYWN0aW9ucy5mb3JFYWNoKHRyYW4gPT4ge1xyXG4gICAgICAgICAgICAvLyB3ZSBkb24ndCBhbGxvdyBiYXRjaCByZW1vdmVyIGZvciB0cmVlIGRhdGEgYXMgdHJlZSBkYXRhIHVzZXMgRmlsbGVyIE5vZGVzLFxyXG4gICAgICAgICAgICAvLyBhbmQgY3JlYXRpbmcvZGVsZXRpbmcgZmlsbGVyIG5vZGVzIG5lZWRzIHRvIGJlIGRvbmUgYWxvbmdzaWRlIHRoZSBub2RlIGRlbGV0aW5nXHJcbiAgICAgICAgICAgIC8vIGFuZCBtb3ZpbmcuIGlmIHdlIHdhbnQgdG8gQmF0Y2ggUmVtb3ZlciB3b3JraW5nIHdpdGggdHJlZSBkYXRhIHRoZW4gd291bGQgbmVlZFxyXG4gICAgICAgICAgICAvLyB0byBjb25zaWRlciBob3cgRmlsbGVyIE5vZGVzIHdvdWxkIGJlIGltcGFjdGVkIChpdCdzIHBvc3NpYmxlIHRoYXQgaXQgY2FuIGJlIGVhc2lseVxyXG4gICAgICAgICAgICAvLyBtb2RpZmllZCB0byB3b3JrLCBob3dldmVyIGZvciBub3cgSSBkb24ndCBoYXZlIHRoZSBicmFpbiBlbmVyZ3kgdG8gd29yayBpdCBhbGwgb3V0KS5cclxuICAgICAgICAgICAgY29uc3QgYmF0Y2hSZW1vdmVyID0gIWRldGFpbHMudXNpbmdUcmVlRGF0YSA/IG5ldyBCYXRjaFJlbW92ZXIoKSA6IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgICAgICAgIC8vIHRoZSBvcmRlciBoZXJlIG9mIFthZGQsIHJlbW92ZSwgdXBkYXRlXSBuZWVkcyB0byBiZSB0aGUgc2FtZSBhcyBpbiBDbGllbnRTaWRlTm9kZU1hbmFnZXIsXHJcbiAgICAgICAgICAgIC8vIGFzIHRoZSBvcmRlciBpcyBpbXBvcnRhbnQgd2hlbiBhIHJlY29yZCB3aXRoIHRoZSBzYW1lIGlkIGlzIGFkZGVkIGFuZCByZW1vdmVkIGluIHRoZSBzYW1lXHJcbiAgICAgICAgICAgIC8vIHRyYW5zYWN0aW9uLlxyXG4gICAgICAgICAgICBpZiAoXy5leGlzdHNBbmROb3RFbXB0eSh0cmFuLnJlbW92ZSkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTm9kZXModHJhbi5yZW1vdmUgYXMgUm93Tm9kZVtdLCBkZXRhaWxzLCBiYXRjaFJlbW92ZXIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChfLmV4aXN0c0FuZE5vdEVtcHR5KHRyYW4udXBkYXRlKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5tb3ZlTm9kZXNJbldyb25nUGF0aCh0cmFuLnVwZGF0ZSBhcyBSb3dOb2RlW10sIGRldGFpbHMsIGJhdGNoUmVtb3Zlcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKF8uZXhpc3RzQW5kTm90RW1wdHkodHJhbi5hZGQpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmluc2VydE5vZGVzKHRyYW4uYWRkIGFzIFJvd05vZGVbXSwgZGV0YWlscywgZmFsc2UpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vIG11c3QgZmx1c2ggaGVyZSwgYW5kIG5vdCBhbGxvdyBhbm90aGVyIHRyYW5zYWN0aW9uIHRvIGJlIGFwcGxpZWQsXHJcbiAgICAgICAgICAgIC8vIGFzIGVhY2ggdHJhbnNhY3Rpb24gbXVzdCBmaW5pc2ggbGVhdmluZyB0aGUgZGF0YSBpbiBhIGNvbnNpc3RlbnQgc3RhdGUuXHJcbiAgICAgICAgICAgIGlmIChiYXRjaFJlbW92ZXIpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBhcmVudHNXaXRoQ2hpbGRyZW5SZW1vdmVkID0gYmF0Y2hSZW1vdmVyLmdldEFsbFBhcmVudHMoKS5zbGljZSgpO1xyXG4gICAgICAgICAgICAgICAgYmF0Y2hSZW1vdmVyLmZsdXNoKCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUVtcHR5R3JvdXBzKHBhcmVudHNXaXRoQ2hpbGRyZW5SZW1vdmVkLCBkZXRhaWxzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBpZiAoZGV0YWlscy5yb3dOb2RlT3JkZXIpIHtcclxuICAgICAgICAgICAgdGhpcy5zb3J0Q2hpbGRyZW4oZGV0YWlscyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIHRoaXMgaXMgdXNlZCB3aGVuIGRvaW5nIGRlbHRhIHVwZGF0ZXMsIGVnIFJlZHV4LCBrZWVwcyBub2RlcyBpbiByaWdodCBvcmRlclxyXG4gICAgcHJpdmF0ZSBzb3J0Q2hpbGRyZW4oZGV0YWlsczogR3JvdXBpbmdEZXRhaWxzKTogdm9pZCB7XHJcbiAgICAgICAgZGV0YWlscy5jaGFuZ2VkUGF0aC5mb3JFYWNoQ2hhbmdlZE5vZGVEZXB0aEZpcnN0KG5vZGUgPT4ge1xyXG4gICAgICAgICAgICBpZiAoIW5vZGUuY2hpbGRyZW5BZnRlckdyb3VwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGRpZFNvcnQgPSBfLnNvcnRSb3dOb2Rlc0J5T3JkZXIobm9kZS5jaGlsZHJlbkFmdGVyR3JvdXAhLCBkZXRhaWxzLnJvd05vZGVPcmRlcik7XHJcbiAgICAgICAgICAgIGlmIChkaWRTb3J0KSB7XHJcbiAgICAgICAgICAgICAgICBkZXRhaWxzLmNoYW5nZWRQYXRoLmFkZFBhcmVudE5vZGUobm9kZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LCBmYWxzZSwgdHJ1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBvcmRlckdyb3VwcyhkZXRhaWxzOiBHcm91cGluZ0RldGFpbHMpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBjb21wYXJhdG9yID0gZGV0YWlscy5pbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3I7XHJcbiAgICAgICAgaWYgKF8uZXhpc3RzKGNvbXBhcmF0b3IpKSB7IHJlY3Vyc2l2ZVNvcnQoZGV0YWlscy5yb290Tm9kZSk7IH1cclxuXHJcbiAgICAgICAgZnVuY3Rpb24gcmVjdXJzaXZlU29ydChyb3dOb2RlOiBSb3dOb2RlKTogdm9pZCB7XHJcbiAgICAgICAgICAgIGNvbnN0IGRvU29ydCA9IF8uZXhpc3RzKHJvd05vZGUuY2hpbGRyZW5BZnRlckdyb3VwKSAmJlxyXG4gICAgICAgICAgICAgICAgLy8gd2Ugb25seSB3YW50IHRvIHNvcnQgZ3JvdXBzLCBzbyB3ZSBkbyBub3Qgc29ydCBsZWFmcyAoYSBsZWFmIGdyb3VwIGhhcyBsZWFmcyBhcyBjaGlsZHJlbilcclxuICAgICAgICAgICAgICAgICFyb3dOb2RlLmxlYWZHcm91cDtcclxuXHJcbiAgICAgICAgICAgIGlmIChkb1NvcnQpIHtcclxuICAgICAgICAgICAgICAgIHJvd05vZGUuY2hpbGRyZW5BZnRlckdyb3VwIS5zb3J0KChub2RlQSwgbm9kZUIpID0+IGNvbXBhcmF0b3IhKHsgbm9kZUEsIG5vZGVCIH0pKTtcclxuICAgICAgICAgICAgICAgIHJvd05vZGUuY2hpbGRyZW5BZnRlckdyb3VwIS5mb3JFYWNoKChjaGlsZE5vZGU6IFJvd05vZGUpID0+IHJlY3Vyc2l2ZVNvcnQoY2hpbGROb2RlKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBnZXRFeGlzdGluZ1BhdGhGb3JOb2RlKG5vZGU6IFJvd05vZGUsIGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscyk6IEdyb3VwSW5mb1tdIHtcclxuICAgICAgICBjb25zdCByZXM6IEdyb3VwSW5mb1tdID0gW107XHJcblxyXG4gICAgICAgIC8vIHdoZW4gZG9pbmcgdHJlZSBkYXRhLCB0aGUgbm9kZSBpcyBwYXJ0IG9mIHRoZSBwYXRoLFxyXG4gICAgICAgIC8vIGJ1dCB3aGVuIGRvaW5nIGdyaWQgZ3JvdXBpbmcsIHRoZSBub2RlIGlzIG5vdCBwYXJ0IG9mIHRoZSBwYXRoIHNvIHdlIHN0YXJ0IHdpdGggdGhlIHBhcmVudC5cclxuICAgICAgICBsZXQgcG9pbnRlciA9IGRldGFpbHMudXNpbmdUcmVlRGF0YSA/IG5vZGUgOiBub2RlLnBhcmVudDtcclxuICAgICAgICB3aGlsZSAocG9pbnRlciAmJiBwb2ludGVyICE9PSBkZXRhaWxzLnJvb3ROb2RlKSB7XHJcbiAgICAgICAgICAgIHJlcy5wdXNoKHtcclxuICAgICAgICAgICAgICAgIGtleTogcG9pbnRlci5rZXkhLFxyXG4gICAgICAgICAgICAgICAgcm93R3JvdXBDb2x1bW46IHBvaW50ZXIucm93R3JvdXBDb2x1bW4sXHJcbiAgICAgICAgICAgICAgICBmaWVsZDogcG9pbnRlci5maWVsZFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgcG9pbnRlciA9IHBvaW50ZXIucGFyZW50O1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXMucmV2ZXJzZSgpO1xyXG4gICAgICAgIHJldHVybiByZXM7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBtb3ZlTm9kZXNJbldyb25nUGF0aChjaGlsZE5vZGVzOiBSb3dOb2RlW10sIGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscywgYmF0Y2hSZW1vdmVyOiBCYXRjaFJlbW92ZXIgfCB1bmRlZmluZWQpOiB2b2lkIHtcclxuICAgICAgICBjaGlsZE5vZGVzLmZvckVhY2goY2hpbGROb2RlID0+IHtcclxuXHJcbiAgICAgICAgICAgIC8vIHdlIGFkZCBub2RlLCBldmVuIGlmIHBhcmVudCBoYXMgbm90IGNoYW5nZWQsIGFzIHRoZSBkYXRhIGNvdWxkIGhhdmVcclxuICAgICAgICAgICAgLy8gY2hhbmdlZCwgaGVuY2UgYWdncmVnYXRpb25zIHdpbGwgYmUgd3JvbmdcclxuICAgICAgICAgICAgaWYgKGRldGFpbHMuY2hhbmdlZFBhdGguaXNBY3RpdmUoKSkge1xyXG4gICAgICAgICAgICAgICAgZGV0YWlscy5jaGFuZ2VkUGF0aC5hZGRQYXJlbnROb2RlKGNoaWxkTm9kZS5wYXJlbnQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBpbmZvVG9LZXlNYXBwZXIgPSAoaXRlbTogR3JvdXBJbmZvKSA9PiBpdGVtLmtleTtcclxuICAgICAgICAgICAgY29uc3Qgb2xkUGF0aDogc3RyaW5nW10gPSB0aGlzLmdldEV4aXN0aW5nUGF0aEZvck5vZGUoY2hpbGROb2RlLCBkZXRhaWxzKS5tYXAoaW5mb1RvS2V5TWFwcGVyKTtcclxuICAgICAgICAgICAgY29uc3QgbmV3UGF0aDogc3RyaW5nW10gPSB0aGlzLmdldEdyb3VwSW5mbyhjaGlsZE5vZGUsIGRldGFpbHMpLm1hcChpbmZvVG9LZXlNYXBwZXIpO1xyXG5cclxuICAgICAgICAgICAgY29uc3Qgbm9kZUluQ29ycmVjdFBhdGggPSBfLmFyZUVxdWFsKG9sZFBhdGgsIG5ld1BhdGgpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCFub2RlSW5Db3JyZWN0UGF0aCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5tb3ZlTm9kZShjaGlsZE5vZGUsIGRldGFpbHMsIGJhdGNoUmVtb3Zlcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIG1vdmVOb2RlKGNoaWxkTm9kZTogUm93Tm9kZSwgZGV0YWlsczogR3JvdXBpbmdEZXRhaWxzLCBiYXRjaFJlbW92ZXI6IEJhdGNoUmVtb3ZlciB8IHVuZGVmaW5lZCk6IHZvaWQge1xyXG5cclxuICAgICAgICB0aGlzLnJlbW92ZU5vZGVzSW5TdGFnZXMoW2NoaWxkTm9kZV0sIGRldGFpbHMsIGJhdGNoUmVtb3Zlcik7XHJcbiAgICAgICAgdGhpcy5pbnNlcnRPbmVOb2RlKGNoaWxkTm9kZSwgZGV0YWlscywgdHJ1ZSwgYmF0Y2hSZW1vdmVyKTtcclxuXHJcbiAgICAgICAgLy8gaGFjayAtIGlmIHdlIGRpZG4ndCBkbyB0aGlzLCB0aGVuIHJlbmFtaW5nIGEgdHJlZSBpdGVtIChpZSBjaGFuZ2luZyByb3dOb2RlLmtleSkgd291bGRuJ3QgZ2V0XHJcbiAgICAgICAgLy8gcmVmcmVzaGVkIGludG8gdGhlIGd1aS5cclxuICAgICAgICAvLyB0aGlzIGlzIG5lZWRlZCB0byBraWNrIG9mZiB0aGUgZXZlbnQgdGhhdCByb3dDb21wIGxpc3RlbnMgdG8gZm9yIHJlZnJlc2guIHRoaXMgaW4gdHVyblxyXG4gICAgICAgIC8vIHRoZW4gd2lsbCBnZXQgZWFjaCBjZWxsIGluIHRoZSByb3cgdG8gcmVmcmVzaCAtIHdoaWNoIGlzIHdoYXQgd2UgbmVlZCBhcyB3ZSBkb24ndCBrbm93IHdoaWNoXHJcbiAgICAgICAgLy8gY29sdW1ucyB3aWxsIGJlIGRpc3BsYXlpbmcgdGhlIHJvd05vZGUua2V5IGluZm8uXHJcbiAgICAgICAgY2hpbGROb2RlLnNldERhdGEoY2hpbGROb2RlLmRhdGEpO1xyXG5cclxuICAgICAgICAvLyB3ZSBhZGQgYm90aCBvbGQgYW5kIG5ldyBwYXJlbnRzIHRvIGNoYW5nZWQgcGF0aCwgYXMgYm90aCB3aWxsIG5lZWQgdG8gYmUgcmVmcmVzaGVkLlxyXG4gICAgICAgIC8vIHdlIGFscmVhZHkgYWRkZWQgdGhlIG9sZCBwYXJlbnQgKGluIGNhbGxpbmcgbWV0aG9kKSwgc28ganVzdCBhZGQgdGhlIG5ldyBwYXJlbnQgaGVyZVxyXG4gICAgICAgIGlmIChkZXRhaWxzLmNoYW5nZWRQYXRoLmlzQWN0aXZlKCkpIHtcclxuICAgICAgICAgICAgY29uc3QgbmV3UGFyZW50ID0gY2hpbGROb2RlLnBhcmVudDtcclxuICAgICAgICAgICAgZGV0YWlscy5jaGFuZ2VkUGF0aC5hZGRQYXJlbnROb2RlKG5ld1BhcmVudCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgcmVtb3ZlTm9kZXMobGVhZlJvd05vZGVzOiBSb3dOb2RlW10sIGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscywgYmF0Y2hSZW1vdmVyOiBCYXRjaFJlbW92ZXIgfCB1bmRlZmluZWQpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnJlbW92ZU5vZGVzSW5TdGFnZXMobGVhZlJvd05vZGVzLCBkZXRhaWxzLCBiYXRjaFJlbW92ZXIpO1xyXG4gICAgICAgIGlmIChkZXRhaWxzLmNoYW5nZWRQYXRoLmlzQWN0aXZlKCkpIHtcclxuICAgICAgICAgICAgbGVhZlJvd05vZGVzLmZvckVhY2gocm93Tm9kZSA9PiBkZXRhaWxzLmNoYW5nZWRQYXRoLmFkZFBhcmVudE5vZGUocm93Tm9kZS5wYXJlbnQpKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSByZW1vdmVOb2Rlc0luU3RhZ2VzKGxlYWZSb3dOb2RlczogUm93Tm9kZVtdLCBkZXRhaWxzOiBHcm91cGluZ0RldGFpbHMsIGJhdGNoUmVtb3ZlcjogQmF0Y2hSZW1vdmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5yZW1vdmVOb2Rlc0Zyb21QYXJlbnRzKGxlYWZSb3dOb2RlcywgZGV0YWlscywgYmF0Y2hSZW1vdmVyKTtcclxuICAgICAgICBpZiAoZGV0YWlscy51c2luZ1RyZWVEYXRhKSB7XHJcbiAgICAgICAgICAgIHRoaXMucG9zdFJlbW92ZUNyZWF0ZUZpbGxlck5vZGVzKGxlYWZSb3dOb2RlcywgZGV0YWlscyk7XHJcblxyXG4gICAgICAgICAgICAvLyBXaGVuIG5vdCBUcmVlRGF0YSwgdGhlbiByZW1vdmVFbXB0eUdyb3VwcyBpcyBjYWxsZWQganVzdCBiZWZvcmUgdGhlIEJhdGNoUmVtb3ZlciBpcyBmbHVzaGVkLlxyXG4gICAgICAgICAgICAvLyBIb3dldmVyIGZvciBUcmVlRGF0YSwgdGhlcmUgaXMgbm8gQmF0Y2hSZW1vdmVyLCBzbyB3ZSBoYXZlIHRvIGNhbGwgcmVtb3ZlRW1wdHlHcm91cHMgaGVyZS5cclxuICAgICAgICAgICAgY29uc3Qgbm9kZVBhcmVudHMgPSBsZWFmUm93Tm9kZXMubWFwKG4gPT4gbi5wYXJlbnQhKTtcclxuICAgICAgICAgICAgdGhpcy5yZW1vdmVFbXB0eUdyb3Vwcyhub2RlUGFyZW50cywgZGV0YWlscyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZm9yRWFjaFBhcmVudEdyb3VwKGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscywgZ3JvdXA6IFJvd05vZGUsIGNhbGxiYWNrOiAocGFyZW50OiBSb3dOb2RlKSA9PiB2b2lkKTogdm9pZCB7XHJcbiAgICAgICAgbGV0IHBvaW50ZXI6IFJvd05vZGUgfCBudWxsID0gZ3JvdXA7XHJcbiAgICAgICAgd2hpbGUgKHBvaW50ZXIgJiYgcG9pbnRlciAhPT0gZGV0YWlscy5yb290Tm9kZSkge1xyXG4gICAgICAgICAgICBjYWxsYmFjayhwb2ludGVyKTtcclxuICAgICAgICAgICAgcG9pbnRlciA9IHBvaW50ZXIucGFyZW50O1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHJlbW92ZU5vZGVzRnJvbVBhcmVudHMobm9kZXNUb1JlbW92ZTogUm93Tm9kZVtdLCBkZXRhaWxzOiBHcm91cGluZ0RldGFpbHMsIHByb3ZpZGVkOiBCYXRjaFJlbW92ZXIgfCB1bmRlZmluZWQpOiB2b2lkIHtcclxuICAgICAgICAvLyB0aGlzIG1ldGhvZCBjYW4gYmUgY2FsbGVkIHdpdGggQmF0Y2hSZW1vdmVyIGFzIG9wdGlvbmFsLiBpZiBpdCBpcyBtaXNzZWQsIHdlIGNyZWF0ZWQgYSBsb2NhbCB2ZXJzaW9uXHJcbiAgICAgICAgLy8gYW5kIGZsdXNoIGl0IGF0IHRoZSBlbmQuIGlmIG9uZSBpcyBwcm92aWRlZCwgd2UgYWRkIHRvIHRoZSBwcm92aWRlZCBvbmUgYW5kIGl0IGdldHMgZmx1c2hlZCBlbHNld2hlcmUuXHJcbiAgICAgICAgY29uc3QgYmF0Y2hSZW1vdmVySXNMb2NhbCA9IHByb3ZpZGVkID09IG51bGw7XHJcbiAgICAgICAgY29uc3QgYmF0Y2hSZW1vdmVyVG9Vc2UgPSBwcm92aWRlZCA/IHByb3ZpZGVkIDogbmV3IEJhdGNoUmVtb3ZlcigpO1xyXG5cclxuICAgICAgICBub2Rlc1RvUmVtb3ZlLmZvckVhY2gobm9kZVRvUmVtb3ZlID0+IHtcclxuICAgICAgICAgICAgdGhpcy5yZW1vdmVGcm9tUGFyZW50KG5vZGVUb1JlbW92ZSwgYmF0Y2hSZW1vdmVyVG9Vc2UpO1xyXG5cclxuICAgICAgICAgICAgLy8gcmVtb3ZlIGZyb20gYWxsTGVhZkNoaWxkcmVuLiB3ZSBjbGVhciBkb3duIGFsbCBwYXJlbnRzIEVYQ0VQVCB0aGUgUm9vdCBOb2RlLCBhc1xyXG4gICAgICAgICAgICAvLyB0aGUgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyIGlzIHJlc3BvbnNpYmxlIGZvciB0aGUgUm9vdCBOb2RlLlxyXG4gICAgICAgICAgICB0aGlzLmZvckVhY2hQYXJlbnRHcm91cChkZXRhaWxzLCBub2RlVG9SZW1vdmUucGFyZW50ISwgcGFyZW50Tm9kZSA9PiB7XHJcbiAgICAgICAgICAgICAgICBiYXRjaFJlbW92ZXJUb1VzZS5yZW1vdmVGcm9tQWxsTGVhZkNoaWxkcmVuKHBhcmVudE5vZGUsIG5vZGVUb1JlbW92ZSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBpZiAoYmF0Y2hSZW1vdmVySXNMb2NhbCkge1xyXG4gICAgICAgICAgICBiYXRjaFJlbW92ZXJUb1VzZS5mbHVzaCgpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHBvc3RSZW1vdmVDcmVhdGVGaWxsZXJOb2Rlcyhub2Rlc1RvUmVtb3ZlOiBSb3dOb2RlW10sIGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscyk6IHZvaWQge1xyXG4gICAgICAgIG5vZGVzVG9SZW1vdmUuZm9yRWFjaChub2RlVG9SZW1vdmUgPT4ge1xyXG5cclxuICAgICAgICAgICAgLy8gaWYgbm90IGdyb3VwLCBhbmQgY2hpbGRyZW4gYXJlIHByZXNlbnQsIG5lZWQgdG8gbW92ZSBjaGlsZHJlbiB0byBhIGdyb3VwLlxyXG4gICAgICAgICAgICAvLyBvdGhlcndpc2UgaWYgbm8gY2hpbGRyZW4sIHdlIGNhbiBqdXN0IHJlbW92ZSB3aXRob3V0IHJlcGxhY2luZy5cclxuICAgICAgICAgICAgY29uc3QgcmVwbGFjZVdpdGhHcm91cCA9IG5vZGVUb1JlbW92ZS5oYXNDaGlsZHJlbigpO1xyXG4gICAgICAgICAgICBpZiAocmVwbGFjZVdpdGhHcm91cCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgb2xkUGF0aCA9IHRoaXMuZ2V0RXhpc3RpbmdQYXRoRm9yTm9kZShub2RlVG9SZW1vdmUsIGRldGFpbHMpO1xyXG4gICAgICAgICAgICAgICAgLy8gYmVjYXVzZSB3ZSBqdXN0IHJlbW92ZWQgdGhlIHVzZXJHcm91cCwgdGhpcyB3aWxsIGFsd2F5cyByZXR1cm4gbmV3IHN1cHBvcnQgZ3JvdXBcclxuICAgICAgICAgICAgICAgIGNvbnN0IG5ld0dyb3VwTm9kZSA9IHRoaXMuZmluZFBhcmVudEZvck5vZGUobm9kZVRvUmVtb3ZlLCBvbGRQYXRoLCBkZXRhaWxzKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyB0aGVzZSBwcm9wZXJ0aWVzIGFyZSB0aGUgb25lcyB0aGF0IHdpbGwgYmUgaW5jb3JyZWN0IGluIHRoZSBuZXdseSBjcmVhdGVkIGdyb3VwLFxyXG4gICAgICAgICAgICAgICAgLy8gc28gY29weSB0aGVtIGZyb20gdGhlIG9sZCBjaGlsZE5vZGVcclxuICAgICAgICAgICAgICAgIG5ld0dyb3VwTm9kZS5leHBhbmRlZCA9IG5vZGVUb1JlbW92ZS5leHBhbmRlZDtcclxuICAgICAgICAgICAgICAgIG5ld0dyb3VwTm9kZS5hbGxMZWFmQ2hpbGRyZW4gPSBub2RlVG9SZW1vdmUuYWxsTGVhZkNoaWxkcmVuO1xyXG4gICAgICAgICAgICAgICAgbmV3R3JvdXBOb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCA9IG5vZGVUb1JlbW92ZS5jaGlsZHJlbkFmdGVyR3JvdXA7XHJcbiAgICAgICAgICAgICAgICBuZXdHcm91cE5vZGUuY2hpbGRyZW5NYXBwZWQgPSBub2RlVG9SZW1vdmUuY2hpbGRyZW5NYXBwZWQ7XHJcbiAgICAgICAgICAgICAgICBuZXdHcm91cE5vZGUudXBkYXRlSGFzQ2hpbGRyZW4oKTtcclxuXHJcbiAgICAgICAgICAgICAgICBuZXdHcm91cE5vZGUuY2hpbGRyZW5BZnRlckdyb3VwIS5mb3JFYWNoKHJvd05vZGUgPT4gcm93Tm9kZS5wYXJlbnQgPSBuZXdHcm91cE5vZGUpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgcmVtb3ZlRW1wdHlHcm91cHMocG9zc2libGVFbXB0eUdyb3VwczogUm93Tm9kZVtdLCBkZXRhaWxzOiBHcm91cGluZ0RldGFpbHMpOiB2b2lkIHtcclxuICAgICAgICAvLyB3ZSBkbyB0aGlzIG11bHRpcGxlIHRpbWVzLCBhcyB3aGVuIHdlIHJlbW92ZSBncm91cHMsIHRoYXQgbWVhbnMgdGhlIHBhcmVudCBvZiBqdXN0IHJlbW92ZWRcclxuICAgICAgICAvLyBncm91cCBjYW4gdGhlbiBiZSBlbXB0eS4gdG8gZ2V0IGFyb3VuZCB0aGlzLCBpZiB3ZSByZW1vdmUsIHRoZW4gd2UgY2hlY2sgZXZlcnl0aGluZyBhZ2FpbiBmb3JcclxuICAgICAgICAvLyBuZXdseSBlbXB0aWVkIGdyb3Vwcy4gdGhlIG1heCBudW1iZXIgb2YgdGltZXMgdGhpcyB3aWxsIGV4ZWN1dGUgaXMgdGhlIGRlcHRoIG9mIHRoZSBncm91cCB0cmVlLlxyXG4gICAgICAgIGxldCBjaGVja0FnYWluID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgY29uc3QgZ3JvdXBTaG91bGRCZVJlbW92ZWQgPSAocm93Tm9kZTogUm93Tm9kZSk6IGJvb2xlYW4gPT4ge1xyXG5cclxuICAgICAgICAgICAgLy8gYmVjYXVzZSBvZiB0aGUgd2hpbGUgbG9vcCBiZWxvdywgaXQncyBwb3NzaWJsZSB3ZSBhbHJlYWR5IG1vdmVkIHRoZSBub2RlLFxyXG4gICAgICAgICAgICAvLyBzbyBkb3VibGUgY2hlY2sgYmVmb3JlIHRyeWluZyB0byByZW1vdmUgYWdhaW4uXHJcbiAgICAgICAgICAgIGNvbnN0IG1hcEtleSA9IHRoaXMuZ2V0Q2hpbGRyZW5NYXBwZWRLZXkocm93Tm9kZS5rZXkhLCByb3dOb2RlLnJvd0dyb3VwQ29sdW1uKTtcclxuICAgICAgICAgICAgY29uc3QgcGFyZW50Um93Tm9kZSA9IHJvd05vZGUucGFyZW50O1xyXG4gICAgICAgICAgICBjb25zdCBncm91cEFscmVhZHlSZW1vdmVkID0gKHBhcmVudFJvd05vZGUgJiYgcGFyZW50Um93Tm9kZS5jaGlsZHJlbk1hcHBlZCkgP1xyXG4gICAgICAgICAgICAgICAgIXBhcmVudFJvd05vZGUuY2hpbGRyZW5NYXBwZWRbbWFwS2V5XSA6IHRydWU7XHJcblxyXG4gICAgICAgICAgICBpZiAoZ3JvdXBBbHJlYWR5UmVtb3ZlZCkge1xyXG4gICAgICAgICAgICAgICAgLy8gaWYgbm90IGxpbmtlZCwgdGhlbiBncm91cCB3YXMgYWxyZWFkeSByZW1vdmVkXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gaWYgc3RpbGwgbm90IHJlbW92ZWQsIHRoZW4gd2UgcmVtb3ZlIGlmIHRoaXMgZ3JvdXAgaXMgZW1wdHlcclxuICAgICAgICAgICAgcmV0dXJuICEhcm93Tm9kZS5pc0VtcHR5Um93R3JvdXBOb2RlKCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgd2hpbGUgKGNoZWNrQWdhaW4pIHtcclxuICAgICAgICAgICAgY2hlY2tBZ2FpbiA9IGZhbHNlO1xyXG4gICAgICAgICAgICBjb25zdCBiYXRjaFJlbW92ZXI6IEJhdGNoUmVtb3ZlciA9IG5ldyBCYXRjaFJlbW92ZXIoKTtcclxuICAgICAgICAgICAgcG9zc2libGVFbXB0eUdyb3Vwcy5mb3JFYWNoKHBvc3NpYmxlRW1wdHlHcm91cCA9PiB7XHJcbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgZW1wdHkgZ3JvdXBzXHJcbiAgICAgICAgICAgICAgICB0aGlzLmZvckVhY2hQYXJlbnRHcm91cChkZXRhaWxzLCBwb3NzaWJsZUVtcHR5R3JvdXAsIHJvd05vZGUgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChncm91cFNob3VsZEJlUmVtb3ZlZChyb3dOb2RlKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjaGVja0FnYWluID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVGcm9tUGFyZW50KHJvd05vZGUsIGJhdGNoUmVtb3Zlcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIHJlbW92ZSBzZWxlY3Rpb24gb24gZmlsbGVyIG5vZGVzIGhlcmUsIGFzIHRoZSBzZWxlY3Rpb24gd291bGQgbm90IGJlIHJlbW92ZWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZnJvbSB0aGUgUm93Tm9kZU1hbmFnZXIsIGFzIGZpbGxlciBub2RlcyBkb24ndCBleGlzdCBvbiB0aGUgUm93Tm9kZU1hbmFnZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgcm93Tm9kZS5zZXRTZWxlY3RlZFBhcmFtcyh7IG5ld1ZhbHVlOiBmYWxzZSwgc291cmNlOiAncm93R3JvdXBDaGFuZ2VkJyB9KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGJhdGNoUmVtb3Zlci5mbHVzaCgpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyByZW1vdmVzIHRoZSBub2RlIGZyb20gdGhlIHBhcmVudCBieTpcclxuICAgIC8vIGEpIHJlbW92aW5nIGZyb20gY2hpbGRyZW5BZnRlckdyb3VwICh1c2luZyBiYXRjaFJlbW92ZXIgaWYgcHJlc2VudCwgb3RoZXJ3aXNlIGltbWVkaWF0ZWx5KVxyXG4gICAgLy8gYikgcmVtb3ZpbmcgZnJvbSBjaGlsZHJlbk1hcHBlZCAoaW1tZWRpYXRlbHkpXHJcbiAgICAvLyBjKSBzZXRSb3dUb3AobnVsbCkgLSBhcyB0aGUgcm93UmVuZGVyZXIgdXNlcyB0aGlzIHRvIGtub3cgdGhlIFJvd05vZGUgaXMgbm8gbG9uZ2VyIG5lZWRlZFxyXG4gICAgLy8gZCkgc2V0Um93SW5kZXgobnVsbCkgLSBhcyB0aGUgcm93Tm9kZSB3aWxsIG5vIGxvbmdlciBiZSBkaXNwbGF5ZWQuXHJcbiAgICBwcml2YXRlIHJlbW92ZUZyb21QYXJlbnQoY2hpbGQ6IFJvd05vZGUsIGJhdGNoUmVtb3Zlcj86IEJhdGNoUmVtb3Zlcikge1xyXG4gICAgICAgIGlmIChjaGlsZC5wYXJlbnQpIHtcclxuICAgICAgICAgICAgaWYgKGJhdGNoUmVtb3Zlcikge1xyXG4gICAgICAgICAgICAgICAgYmF0Y2hSZW1vdmVyLnJlbW92ZUZyb21DaGlsZHJlbkFmdGVyR3JvdXAoY2hpbGQucGFyZW50LCBjaGlsZCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBfLnJlbW92ZUZyb21BcnJheShjaGlsZC5wYXJlbnQuY2hpbGRyZW5BZnRlckdyb3VwISwgY2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgY2hpbGQucGFyZW50LnVwZGF0ZUhhc0NoaWxkcmVuKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgbWFwS2V5ID0gdGhpcy5nZXRDaGlsZHJlbk1hcHBlZEtleShjaGlsZC5rZXkhLCBjaGlsZC5yb3dHcm91cENvbHVtbik7XHJcbiAgICAgICAgaWYgKGNoaWxkLnBhcmVudCAmJiBjaGlsZC5wYXJlbnQuY2hpbGRyZW5NYXBwZWQpIHtcclxuICAgICAgICAgICAgY2hpbGQucGFyZW50LmNoaWxkcmVuTWFwcGVkW21hcEtleV0gPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIHRoaXMgaXMgaW1wb3J0YW50IGZvciB0cmFuc2l0aW9uLCBzZWUgcm93Q29tcCByZW1vdmVGaXJzdFBhc3NGdW5jcy4gd2hlbiBkb2luZyBhbmltYXRpb24gYW5kXHJcbiAgICAgICAgLy8gcmVtb3ZlLCBpZiByb3dUb3AgaXMgc3RpbGwgcHJlc2VudCwgdGhlIHJvd0NvbXAgdGhpbmtzIGl0J3MganVzdCBtb3ZlZCBwb3NpdGlvbi5cclxuICAgICAgICBjaGlsZC5zZXRSb3dUb3AobnVsbCk7XHJcbiAgICAgICAgY2hpbGQuc2V0Um93SW5kZXgobnVsbCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBhZGRUb1BhcmVudChjaGlsZDogUm93Tm9kZSwgcGFyZW50OiBSb3dOb2RlIHwgbnVsbCkge1xyXG4gICAgICAgIGNvbnN0IG1hcEtleSA9IHRoaXMuZ2V0Q2hpbGRyZW5NYXBwZWRLZXkoY2hpbGQua2V5ISwgY2hpbGQucm93R3JvdXBDb2x1bW4pO1xyXG4gICAgICAgIGlmIChwYXJlbnQpIHtcclxuICAgICAgICAgICAgY29uc3QgY2hpbGRyZW4gPSBwYXJlbnQuY2hpbGRyZW5NYXBwZWQgIT0gbnVsbDtcclxuICAgICAgICAgICAgaWYgKGNoaWxkcmVuKSB7XHJcbiAgICAgICAgICAgICAgICBwYXJlbnQuY2hpbGRyZW5NYXBwZWQhW21hcEtleV0gPSBjaGlsZDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBwYXJlbnQuY2hpbGRyZW5BZnRlckdyb3VwIS5wdXNoKGNoaWxkKTtcclxuICAgICAgICAgICAgcGFyZW50LnVwZGF0ZUhhc0NoaWxkcmVuKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgYXJlR3JvdXBDb2xzRXF1YWwoZDE6IEdyb3VwaW5nRGV0YWlscywgZDI6IEdyb3VwaW5nRGV0YWlscyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmIChkMSA9PSBudWxsIHx8IGQyID09IG51bGwgfHwgZDEucGl2b3RNb2RlICE9PSBkMi5waXZvdE1vZGUpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG4gICAgICAgIHJldHVybiBfLmFyZUVxdWFsKGQxLmdyb3VwZWRDb2xzLCBkMi5ncm91cGVkQ29scykgJiYgXy5hcmVFcXVhbChkMS5rZXlDcmVhdG9ycywgZDIua2V5Q3JlYXRvcnMpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY2hlY2tBbGxHcm91cERhdGFBZnRlckNvbHNDaGFuZ2VkKGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscyk6IHZvaWQge1xyXG5cclxuICAgICAgICBjb25zdCByZWN1cnNlID0gKHJvd05vZGVzOiBSb3dOb2RlW10gfCBudWxsKSA9PiB7XHJcbiAgICAgICAgICAgIGlmICghcm93Tm9kZXMpIHsgcmV0dXJuOyB9XHJcbiAgICAgICAgICAgIHJvd05vZGVzLmZvckVhY2gocm93Tm9kZSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpc0xlYWZOb2RlID0gIWRldGFpbHMudXNpbmdUcmVlRGF0YSAmJiAhcm93Tm9kZS5ncm91cDtcclxuICAgICAgICAgICAgICAgIGlmIChpc0xlYWZOb2RlKSB7IHJldHVybjsgfVxyXG4gICAgICAgICAgICAgICAgY29uc3QgZ3JvdXBJbmZvOiBHcm91cEluZm8gPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZmllbGQ6IHJvd05vZGUuZmllbGQsXHJcbiAgICAgICAgICAgICAgICAgICAga2V5OiByb3dOb2RlLmtleSEsXHJcbiAgICAgICAgICAgICAgICAgICAgcm93R3JvdXBDb2x1bW46IHJvd05vZGUucm93R3JvdXBDb2x1bW4sXHJcbiAgICAgICAgICAgICAgICAgICAgbGVhZk5vZGU6IHJvd05vZGUuYWxsTGVhZkNoaWxkcmVuWzBdLFxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2V0R3JvdXBEYXRhKHJvd05vZGUsIGdyb3VwSW5mbywgZGV0YWlscyk7XHJcbiAgICAgICAgICAgICAgICByZWN1cnNlKHJvd05vZGUuY2hpbGRyZW5BZnRlckdyb3VwKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcmVjdXJzZShkZXRhaWxzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzaG90Z3VuUmVzZXRFdmVyeXRoaW5nKGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscywgYWZ0ZXJDb2x1bW5zQ2hhbmdlZDogYm9vbGVhbik6IHZvaWQge1xyXG5cclxuICAgICAgICBpZiAodGhpcy5ub0NoYW5nZUluR3JvdXBpbmdDb2x1bW5zKGRldGFpbHMsIGFmdGVyQ29sdW1uc0NoYW5nZWQpKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGdyb3VwcyBhcmUgYWJvdXQgdG8gZ2V0IGRpc3Bvc2VkLCBzbyBuZWVkIHRvIGRlc2VsZWN0IGFueSB0aGF0IGFyZSBzZWxlY3RlZFxyXG4gICAgICAgIHRoaXMuc2VsZWN0aW9uU2VydmljZS5maWx0ZXJGcm9tU2VsZWN0aW9uKChub2RlOiBSb3dOb2RlKSA9PiBub2RlICYmICFub2RlLmdyb3VwKTtcclxuXHJcbiAgICAgICAgY29uc3QgeyByb290Tm9kZSwgZ3JvdXBlZENvbHMgfSA9IGRldGFpbHM7XHJcbiAgICAgICAgLy8gYmVjYXVzZSB3ZSBhcmUgbm90IGNyZWF0aW5nIHRoZSByb290IG5vZGUgZWFjaCB0aW1lLCB3ZSBoYXZlIHRoZSBsb2dpY1xyXG4gICAgICAgIC8vIGhlcmUgdG8gY2hhbmdlIGxlYWZHcm91cCBvbmNlLlxyXG4gICAgICAgIC8vIHdlIHNldCAubGVhZkdyb3VwIHRvIGZhbHNlIGZvciB0cmVlIGRhdGEsIGFzIC5sZWFmR3JvdXAgaXMgb25seSB1c2VkIHdoZW4gcGl2b3RpbmcsIGFuZCBwaXZvdGluZ1xyXG4gICAgICAgIC8vIGlzbid0IGFsbG93ZWQgd2l0aCB0cmVlRGF0YSwgc28gdGhlIGdyaWQgbmV2ZXIgYWN0dWFsbHkgdXNlIC5sZWFmR3JvdXAgd2hlbiBkb2luZyB0cmVlRGF0YS5cclxuICAgICAgICByb290Tm9kZS5sZWFmR3JvdXAgPSBkZXRhaWxzLnVzaW5nVHJlZURhdGEgPyBmYWxzZSA6IGdyb3VwZWRDb2xzLmxlbmd0aCA9PT0gMDtcclxuXHJcbiAgICAgICAgLy8gd2UgYXJlIGRvaW5nIGV2ZXJ5dGhpbmcgZnJvbSBzY3JhdGNoLCBzbyByZXNldCBjaGlsZHJlbkFmdGVyR3JvdXAgYW5kIGNoaWxkcmVuTWFwcGVkIGZyb20gdGhlIHJvb3ROb2RlXHJcbiAgICAgICAgcm9vdE5vZGUuY2hpbGRyZW5BZnRlckdyb3VwID0gW107XHJcbiAgICAgICAgcm9vdE5vZGUuY2hpbGRyZW5NYXBwZWQgPSB7fTtcclxuICAgICAgICByb290Tm9kZS51cGRhdGVIYXNDaGlsZHJlbigpO1xyXG5cclxuICAgICAgICBjb25zdCBzaWJsaW5nID0gcm9vdE5vZGUuc2libGluZztcclxuICAgICAgICBpZiAoc2libGluZykge1xyXG4gICAgICAgICAgICBzaWJsaW5nLmNoaWxkcmVuQWZ0ZXJHcm91cCA9IHJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cDtcclxuICAgICAgICAgICAgc2libGluZy5jaGlsZHJlbk1hcHBlZCA9IHJvb3ROb2RlLmNoaWxkcmVuTWFwcGVkO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5pbnNlcnROb2Rlcyhyb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4sIGRldGFpbHMsIGZhbHNlKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIG5vQ2hhbmdlSW5Hcm91cGluZ0NvbHVtbnMoZGV0YWlsczogR3JvdXBpbmdEZXRhaWxzLCBhZnRlckNvbHVtbnNDaGFuZ2VkOiBib29sZWFuKTogYm9vbGVhbiB7XHJcbiAgICAgICAgbGV0IG5vRnVydGhlclByb2Nlc3NpbmdOZWVkZWQgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgY29uc3QgZ3JvdXBEaXNwbGF5Q29sdW1ucyA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0R3JvdXBEaXNwbGF5Q29sdW1ucygpO1xyXG4gICAgICAgIGNvbnN0IG5ld0dyb3VwRGlzcGxheUNvbElkcyA9IGdyb3VwRGlzcGxheUNvbHVtbnMgP1xyXG4gICAgICAgICAgICBncm91cERpc3BsYXlDb2x1bW5zLm1hcChjID0+IGMuZ2V0SWQoKSkuam9pbignLScpIDogJyc7XHJcblxyXG4gICAgICAgIGlmIChhZnRlckNvbHVtbnNDaGFuZ2VkKSB7XHJcbiAgICAgICAgICAgIC8vIHdlIG9ubHkgbmVlZCB0byByZWRvIGdyb3VwaW5nIGlmIGRvaW5nIG5vcm1hbCBncm91cGluZyAoaWUgbm90IHRyZWUgZGF0YSlcclxuICAgICAgICAgICAgLy8gYW5kIHRoZSBncm91cCBjb2xzIGhhdmUgY2hhbmdlZC5cclxuICAgICAgICAgICAgbm9GdXJ0aGVyUHJvY2Vzc2luZ05lZWRlZCA9IGRldGFpbHMudXNpbmdUcmVlRGF0YSB8fCB0aGlzLmFyZUdyb3VwQ29sc0VxdWFsKGRldGFpbHMsIHRoaXMub2xkR3JvdXBpbmdEZXRhaWxzKTtcclxuXHJcbiAgICAgICAgICAgIC8vIGlmIHRoZSBncm91cCBkaXNwbGF5IGNvbHMgaGF2ZSBjaGFuZ2VkLCB0aGVuIHdlIG5lZWQgdG8gdXBkYXRlIHJvd05vZGUuZ3JvdXBEYXRhXHJcbiAgICAgICAgICAgIC8vIChyZWdhcmRsZXNzIG9mIHRyZWUgZGF0YSBvciByb3cgZ3JvdXBpbmcpXHJcbiAgICAgICAgICAgIGlmICh0aGlzLm9sZEdyb3VwRGlzcGxheUNvbElkcyAhPT0gbmV3R3JvdXBEaXNwbGF5Q29sSWRzKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNoZWNrQWxsR3JvdXBEYXRhQWZ0ZXJDb2xzQ2hhbmdlZChkZXRhaWxzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5vbGRHcm91cGluZ0RldGFpbHMgPSBkZXRhaWxzO1xyXG4gICAgICAgIHRoaXMub2xkR3JvdXBEaXNwbGF5Q29sSWRzID0gbmV3R3JvdXBEaXNwbGF5Q29sSWRzO1xyXG5cclxuICAgICAgICByZXR1cm4gbm9GdXJ0aGVyUHJvY2Vzc2luZ05lZWRlZDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGluc2VydE5vZGVzKG5ld1Jvd05vZGVzOiBSb3dOb2RlW10sIGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscywgaXNNb3ZlOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICAgICAgbmV3Um93Tm9kZXMuZm9yRWFjaChyb3dOb2RlID0+IHtcclxuICAgICAgICAgICAgdGhpcy5pbnNlcnRPbmVOb2RlKHJvd05vZGUsIGRldGFpbHMsIGlzTW92ZSk7XHJcbiAgICAgICAgICAgIGlmIChkZXRhaWxzLmNoYW5nZWRQYXRoLmlzQWN0aXZlKCkpIHtcclxuICAgICAgICAgICAgICAgIGRldGFpbHMuY2hhbmdlZFBhdGguYWRkUGFyZW50Tm9kZShyb3dOb2RlLnBhcmVudCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGluc2VydE9uZU5vZGUoY2hpbGROb2RlOiBSb3dOb2RlLCBkZXRhaWxzOiBHcm91cGluZ0RldGFpbHMsIGlzTW92ZTogYm9vbGVhbiwgYmF0Y2hSZW1vdmVyPzogQmF0Y2hSZW1vdmVyKTogdm9pZCB7XHJcblxyXG4gICAgICAgIGNvbnN0IHBhdGg6IEdyb3VwSW5mb1tdID0gdGhpcy5nZXRHcm91cEluZm8oY2hpbGROb2RlLCBkZXRhaWxzKTtcclxuXHJcbiAgICAgICAgY29uc3QgcGFyZW50R3JvdXAgPSB0aGlzLmZpbmRQYXJlbnRGb3JOb2RlKGNoaWxkTm9kZSwgcGF0aCwgZGV0YWlscywgYmF0Y2hSZW1vdmVyKTtcclxuICAgICAgICBpZiAoIXBhcmVudEdyb3VwLmdyb3VwKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgQUcgR3JpZDogZHVwbGljYXRlIGdyb3VwIGtleXMgZm9yIHJvdyBkYXRhLCBrZXlzIHNob3VsZCBiZSB1bmlxdWVgLFxyXG4gICAgICAgICAgICAgICAgW3BhcmVudEdyb3VwLmRhdGEsIGNoaWxkTm9kZS5kYXRhXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoZGV0YWlscy51c2luZ1RyZWVEYXRhKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc3dhcEdyb3VwV2l0aFVzZXJOb2RlKHBhcmVudEdyb3VwLCBjaGlsZE5vZGUsIGlzTW92ZSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY2hpbGROb2RlLnBhcmVudCA9IHBhcmVudEdyb3VwO1xyXG4gICAgICAgICAgICBjaGlsZE5vZGUubGV2ZWwgPSBwYXRoLmxlbmd0aDtcclxuICAgICAgICAgICAgcGFyZW50R3JvdXAuY2hpbGRyZW5BZnRlckdyb3VwIS5wdXNoKGNoaWxkTm9kZSk7XHJcbiAgICAgICAgICAgIHBhcmVudEdyb3VwLnVwZGF0ZUhhc0NoaWxkcmVuKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZmluZFBhcmVudEZvck5vZGUoY2hpbGROb2RlOiBSb3dOb2RlLCBwYXRoOiBHcm91cEluZm9bXSwgZGV0YWlsczogR3JvdXBpbmdEZXRhaWxzLCBiYXRjaFJlbW92ZXI/OiBCYXRjaFJlbW92ZXIpOiBSb3dOb2RlIHtcclxuICAgICAgICBsZXQgbmV4dE5vZGU6IFJvd05vZGUgPSBkZXRhaWxzLnJvb3ROb2RlO1xyXG5cclxuICAgICAgICBwYXRoLmZvckVhY2goKGdyb3VwSW5mbywgbGV2ZWwpID0+IHtcclxuICAgICAgICAgICAgbmV4dE5vZGUgPSB0aGlzLmdldE9yQ3JlYXRlTmV4dE5vZGUobmV4dE5vZGUsIGdyb3VwSW5mbywgbGV2ZWwsIGRldGFpbHMpO1xyXG4gICAgICAgICAgICAvLyBub2RlIGdldHMgYWRkZWQgdG8gYWxsIGdyb3VwIG5vZGVzLlxyXG4gICAgICAgICAgICAvLyBub3RlOiB3ZSBkbyBub3QgYWRkIHRvIHJvb3ROb2RlIGhlcmUsIGFzIHRoZSByb290Tm9kZSBpcyB0aGUgbWFzdGVyIGxpc3Qgb2Ygcm93Tm9kZXNcclxuXHJcbiAgICAgICAgICAgIGlmICghYmF0Y2hSZW1vdmVyPy5pc1JlbW92ZUZyb21BbGxMZWFmQ2hpbGRyZW4obmV4dE5vZGUsIGNoaWxkTm9kZSkpIHtcclxuICAgICAgICAgICAgICAgIG5leHROb2RlLmFsbExlYWZDaGlsZHJlbi5wdXNoKGNoaWxkTm9kZSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGlzIG5vZGUgaXMgYWJvdXQgdG8gYmUgcmVtb3ZlZCwgcHJldmVudCB0aGF0XHJcbiAgICAgICAgICAgICAgICBiYXRjaFJlbW92ZXI/LnByZXZlbnRSZW1vdmVGcm9tQWxsTGVhZkNoaWxkcmVuKG5leHROb2RlLCBjaGlsZE5vZGUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBuZXh0Tm9kZTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN3YXBHcm91cFdpdGhVc2VyTm9kZShmaWxsZXJHcm91cDogUm93Tm9kZSwgdXNlckdyb3VwOiBSb3dOb2RlLCBpc01vdmU6IGJvb2xlYW4pIHtcclxuICAgICAgICB1c2VyR3JvdXAucGFyZW50ID0gZmlsbGVyR3JvdXAucGFyZW50O1xyXG4gICAgICAgIHVzZXJHcm91cC5rZXkgPSBmaWxsZXJHcm91cC5rZXk7XHJcbiAgICAgICAgdXNlckdyb3VwLmZpZWxkID0gZmlsbGVyR3JvdXAuZmllbGQ7XHJcbiAgICAgICAgdXNlckdyb3VwLmdyb3VwRGF0YSA9IGZpbGxlckdyb3VwLmdyb3VwRGF0YTtcclxuICAgICAgICB1c2VyR3JvdXAubGV2ZWwgPSBmaWxsZXJHcm91cC5sZXZlbDtcclxuICAgICAgICAvLyBBRy0zNDQxIC0gcHJlc2VydmUgdGhlIGV4aXN0aW5nIGV4cGFuZGVkIHN0YXR1cyBvZiB0aGUgbm9kZSBpZiB3ZSdyZSBtb3ZpbmcgaXQsIHNvIHRoYXRcclxuICAgICAgICAvLyB5b3UgY2FuIGRyYWcgYSBzdWIgdHJlZSBmcm9tIG9uZSBwYXJlbnQgdG8gYW5vdGhlciB3aXRob3V0IGNoYW5naW5nIGl0cyBleHBhbnNpb25cclxuICAgICAgICBpZiAoIWlzTW92ZSkge1xyXG4gICAgICAgICAgICB1c2VyR3JvdXAuZXhwYW5kZWQgPSBmaWxsZXJHcm91cC5leHBhbmRlZDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHdlIHNldCAubGVhZkdyb3VwIHRvIGZhbHNlIGZvciB0cmVlIGRhdGEsIGFzIC5sZWFmR3JvdXAgaXMgb25seSB1c2VkIHdoZW4gcGl2b3RpbmcsIGFuZCBwaXZvdGluZ1xyXG4gICAgICAgIC8vIGlzbid0IGFsbG93ZWQgd2l0aCB0cmVlRGF0YSwgc28gdGhlIGdyaWQgbmV2ZXIgYWN0dWFsbHkgdXNlIC5sZWFmR3JvdXAgd2hlbiBkb2luZyB0cmVlRGF0YS5cclxuICAgICAgICB1c2VyR3JvdXAubGVhZkdyb3VwID0gZmlsbGVyR3JvdXAubGVhZkdyb3VwO1xyXG5cclxuICAgICAgICAvLyBhbHdheXMgbnVsbCBmb3IgdXNlckdyb3VwcywgYXMgcm93IGdyb3VwaW5nIGlzIG5vdCBhbGxvd2VkIHdoZW4gZG9pbmcgdHJlZSBkYXRhXHJcbiAgICAgICAgdXNlckdyb3VwLnJvd0dyb3VwSW5kZXggPSBmaWxsZXJHcm91cC5yb3dHcm91cEluZGV4O1xyXG5cclxuICAgICAgICB1c2VyR3JvdXAuYWxsTGVhZkNoaWxkcmVuID0gZmlsbGVyR3JvdXAuYWxsTGVhZkNoaWxkcmVuO1xyXG4gICAgICAgIHVzZXJHcm91cC5jaGlsZHJlbkFmdGVyR3JvdXAgPSBmaWxsZXJHcm91cC5jaGlsZHJlbkFmdGVyR3JvdXA7XHJcbiAgICAgICAgdXNlckdyb3VwLmNoaWxkcmVuTWFwcGVkID0gZmlsbGVyR3JvdXAuY2hpbGRyZW5NYXBwZWQ7XHJcbiAgICAgICAgdXNlckdyb3VwLnNpYmxpbmcgPSBmaWxsZXJHcm91cC5zaWJsaW5nO1xyXG4gICAgICAgIHVzZXJHcm91cC51cGRhdGVIYXNDaGlsZHJlbigpO1xyXG5cclxuICAgICAgICB0aGlzLnJlbW92ZUZyb21QYXJlbnQoZmlsbGVyR3JvdXApO1xyXG4gICAgICAgIHVzZXJHcm91cC5jaGlsZHJlbkFmdGVyR3JvdXAhLmZvckVhY2goKHJvd05vZGU6IFJvd05vZGUpID0+IHJvd05vZGUucGFyZW50ID0gdXNlckdyb3VwKTtcclxuICAgICAgICB0aGlzLmFkZFRvUGFyZW50KHVzZXJHcm91cCwgZmlsbGVyR3JvdXAucGFyZW50KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGdldE9yQ3JlYXRlTmV4dE5vZGUocGFyZW50R3JvdXA6IFJvd05vZGUsIGdyb3VwSW5mbzogR3JvdXBJbmZvLCBsZXZlbDogbnVtYmVyLFxyXG4gICAgICAgIGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscyk6IFJvd05vZGUge1xyXG5cclxuICAgICAgICBjb25zdCBrZXkgPSB0aGlzLmdldENoaWxkcmVuTWFwcGVkS2V5KGdyb3VwSW5mby5rZXksIGdyb3VwSW5mby5yb3dHcm91cENvbHVtbik7XHJcbiAgICAgICAgbGV0IG5leHROb2RlID0gcGFyZW50R3JvdXAuY2hpbGRyZW5NYXBwZWQgPyBwYXJlbnRHcm91cC5jaGlsZHJlbk1hcHBlZFtrZXldIDogdW5kZWZpbmVkO1xyXG5cclxuICAgICAgICBpZiAoIW5leHROb2RlKSB7XHJcbiAgICAgICAgICAgIG5leHROb2RlID0gdGhpcy5jcmVhdGVHcm91cChncm91cEluZm8sIHBhcmVudEdyb3VwLCBsZXZlbCwgZGV0YWlscyk7XHJcbiAgICAgICAgICAgIC8vIGF0dGFjaCB0aGUgbmV3IGdyb3VwIHRvIHRoZSBwYXJlbnRcclxuICAgICAgICAgICAgdGhpcy5hZGRUb1BhcmVudChuZXh0Tm9kZSwgcGFyZW50R3JvdXApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG5leHROb2RlO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY3JlYXRlR3JvdXAoZ3JvdXBJbmZvOiBHcm91cEluZm8sIHBhcmVudDogUm93Tm9kZSwgbGV2ZWw6IG51bWJlciwgZGV0YWlsczogR3JvdXBpbmdEZXRhaWxzKTogUm93Tm9kZSB7XHJcbiAgICAgICAgY29uc3QgZ3JvdXBOb2RlID0gbmV3IFJvd05vZGUodGhpcy5iZWFucyk7XHJcblxyXG4gICAgICAgIGdyb3VwTm9kZS5ncm91cCA9IHRydWU7XHJcbiAgICAgICAgZ3JvdXBOb2RlLmZpZWxkID0gZ3JvdXBJbmZvLmZpZWxkO1xyXG4gICAgICAgIGdyb3VwTm9kZS5yb3dHcm91cENvbHVtbiA9IGdyb3VwSW5mby5yb3dHcm91cENvbHVtbjtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRHcm91cERhdGEoZ3JvdXBOb2RlLCBncm91cEluZm8sIGRldGFpbHMpO1xyXG5cclxuICAgICAgICBncm91cE5vZGUua2V5ID0gZ3JvdXBJbmZvLmtleTtcclxuICAgICAgICBncm91cE5vZGUuaWQgPSB0aGlzLmNyZWF0ZUdyb3VwSWQoZ3JvdXBOb2RlLCBwYXJlbnQsIGRldGFpbHMudXNpbmdUcmVlRGF0YSwgbGV2ZWwpO1xyXG5cclxuICAgICAgICBncm91cE5vZGUubGV2ZWwgPSBsZXZlbDtcclxuICAgICAgICBncm91cE5vZGUubGVhZkdyb3VwID0gZGV0YWlscy51c2luZ1RyZWVEYXRhID8gZmFsc2UgOiBsZXZlbCA9PT0gKGRldGFpbHMuZ3JvdXBlZENvbENvdW50IC0gMSk7XHJcblxyXG4gICAgICAgIGdyb3VwTm9kZS5hbGxMZWFmQ2hpbGRyZW4gPSBbXTtcclxuXHJcbiAgICAgICAgLy8gd2h5IGlzIHRoaXMgZG9uZSBoZXJlPyB3ZSBhcmUgbm90IHVwZGF0aW5nIHRoZSBjaGlsZHJlbiBjb3VudCBhcyB3ZSBnbyxcclxuICAgICAgICAvLyBpIHN1c3BlY3QgdGhpcyBpcyB1cGRhdGVkIGluIHRoZSBmaWx0ZXIgc3RhZ2VcclxuICAgICAgICBncm91cE5vZGUuc2V0QWxsQ2hpbGRyZW5Db3VudCgwKTtcclxuXHJcbiAgICAgICAgZ3JvdXBOb2RlLnJvd0dyb3VwSW5kZXggPSBkZXRhaWxzLnVzaW5nVHJlZURhdGEgPyBudWxsIDogbGV2ZWw7XHJcblxyXG4gICAgICAgIGdyb3VwTm9kZS5jaGlsZHJlbkFmdGVyR3JvdXAgPSBbXTtcclxuICAgICAgICBncm91cE5vZGUuY2hpbGRyZW5NYXBwZWQgPSB7fTtcclxuICAgICAgICBncm91cE5vZGUudXBkYXRlSGFzQ2hpbGRyZW4oKTtcclxuXHJcbiAgICAgICAgZ3JvdXBOb2RlLnBhcmVudCA9IGRldGFpbHMuaW5jbHVkZVBhcmVudHMgPyBwYXJlbnQgOiBudWxsO1xyXG5cclxuICAgICAgICB0aGlzLnNldEV4cGFuZGVkSW5pdGlhbFZhbHVlKGRldGFpbHMsIGdyb3VwTm9kZSk7XHJcblxyXG4gICAgICAgIHJldHVybiBncm91cE5vZGU7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBjcmVhdGVHcm91cElkKG5vZGU6IFJvd05vZGUsIHBhcmVudDogUm93Tm9kZSwgdXNpbmdUcmVlRGF0YTogYm9vbGVhbiwgbGV2ZWw6IG51bWJlcik6IHN0cmluZyB7XHJcbiAgICAgICAgbGV0IGNyZWF0ZUdyb3VwSWQ6IChub2RlOiBSb3dOb2RlLCBwYXJlbnQ6IFJvd05vZGUgfCBudWxsLCBsZXZlbDogbnVtYmVyKSA9PiBzdHJpbmcgfCBudWxsO1xyXG4gICAgICAgIGlmICh1c2luZ1RyZWVEYXRhKSB7XHJcbiAgICAgICAgICAgIGNyZWF0ZUdyb3VwSWQgPSAobm9kZSwgcGFyZW50LCBsZXZlbCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGxldmVsIDwgMCkgeyByZXR1cm4gbnVsbDsgfSAvLyByb290IG5vZGVcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBhcmVudElkID0gcGFyZW50ID8gY3JlYXRlR3JvdXBJZChwYXJlbnQsIHBhcmVudC5wYXJlbnQsIGxldmVsIC0gMSkgOiBudWxsO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke3BhcmVudElkID09IG51bGwgPyAnJyA6IHBhcmVudElkICsgJy0nfSR7bGV2ZWx9LSR7bm9kZS5rZXl9YDtcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjcmVhdGVHcm91cElkID0gKG5vZGUsIHBhcmVudCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFub2RlLnJvd0dyb3VwQ29sdW1uKSB7IHJldHVybiBudWxsOyB9IC8vIHJvb3Qgbm9kZVxyXG4gICAgICAgICAgICAgICAgY29uc3QgcGFyZW50SWQgPSBwYXJlbnQgPyBjcmVhdGVHcm91cElkKHBhcmVudCwgcGFyZW50LnBhcmVudCwgMCkgOiBudWxsO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke3BhcmVudElkID09IG51bGwgPyAnJyA6IHBhcmVudElkICsgJy0nfSR7bm9kZS5yb3dHcm91cENvbHVtbi5nZXRDb2xJZCgpfS0ke25vZGUua2V5fWA7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyB3ZSBwdXQgJ3Jvdy1ncm91cC0nIGJlZm9yZSB0aGUgZ3JvdXAgaWQsIHNvIGl0IGRvZXNuJ3QgY2xhc2ggd2l0aCBzdGFuZGFyZCByb3cgaWQncy4gd2UgYWxzbyB1c2UgJ3QtJyBhbmQgJ2ItJ1xyXG4gICAgICAgIC8vIGZvciB0b3AgcGlubmVkIGFuZCBib3R0b20gcGlubmVkIHJvd3MuXHJcbiAgICAgICAgcmV0dXJuIFJvd05vZGUuSURfUFJFRklYX1JPV19HUk9VUCArIGNyZWF0ZUdyb3VwSWQobm9kZSwgcGFyZW50LCBsZXZlbCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzZXRHcm91cERhdGEoZ3JvdXBOb2RlOiBSb3dOb2RlLCBncm91cEluZm86IEdyb3VwSW5mbywgZGV0YWlsczogR3JvdXBpbmdEZXRhaWxzKTogdm9pZCB7XHJcbiAgICAgICAgZ3JvdXBOb2RlLmdyb3VwRGF0YSA9IHt9O1xyXG4gICAgICAgIGNvbnN0IGdyb3VwRGlzcGxheUNvbHM6IENvbHVtbltdID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRHcm91cERpc3BsYXlDb2x1bW5zKCk7XHJcbiAgICAgICAgZ3JvdXBEaXNwbGF5Q29scy5mb3JFYWNoKGNvbCA9PiB7XHJcbiAgICAgICAgICAgIC8vIG5ld0dyb3VwLnJvd0dyb3VwQ29sdW1uPW51bGwgd2hlbiB3b3JraW5nIG9mZiBHcm91cEluZm8sIGFuZCB3ZSBhbHdheXMgZGlzcGxheSB0aGUgZ3JvdXAgaW4gdGhlIGdyb3VwIGNvbHVtblxyXG4gICAgICAgICAgICAvLyBpZiByb3dHcm91cENvbHVtbiBpcyBwcmVzZW50LCB0aGVuIGl0J3MgZ3JpZCByb3cgZ3JvdXBpbmcgYW5kIHdlIG9ubHkgaW5jbHVkZSBpZiBjb25maWd1cmF0aW9uIHNheXMgc29cclxuICAgICAgICAgICAgY29uc3QgaXNUcmVlRGF0YSA9IGRldGFpbHMudXNpbmdUcmVlRGF0YTtcclxuICAgICAgICAgICAgaWYgKGlzVHJlZURhdGEpIHtcclxuICAgICAgICAgICAgICAgIGdyb3VwTm9kZS5ncm91cERhdGEhW2NvbC5nZXRDb2xJZCgpXSA9IGdyb3VwSW5mby5rZXk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGdyb3VwQ29sdW1uID0gZ3JvdXBOb2RlLnJvd0dyb3VwQ29sdW1uO1xyXG4gICAgICAgICAgICBjb25zdCBpc1Jvd0dyb3VwRGlzcGxheWVkID0gZ3JvdXBDb2x1bW4gIT09IG51bGwgJiYgY29sLmlzUm93R3JvdXBEaXNwbGF5ZWQoZ3JvdXBDb2x1bW4uZ2V0SWQoKSk7XHJcbiAgICAgICAgICAgIGlmIChpc1Jvd0dyb3VwRGlzcGxheWVkKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZGV0YWlscy5zdXBwcmVzc0dyb3VwTWFpbnRhaW5WYWx1ZVR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBncm91cE5vZGUuZ3JvdXBEYXRhIVtjb2wuZ2V0Q29sSWQoKV0gPSBncm91cEluZm8ua2V5O1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBpZiBtYWludGFpbiBncm91cCB2YWx1ZSB0eXBlLCBnZXQgdGhlIHZhbHVlIGZyb20gYW55IGxlYWYgbm9kZS5cclxuICAgICAgICAgICAgICAgICAgICBncm91cE5vZGUuZ3JvdXBEYXRhIVtjb2wuZ2V0Q29sSWQoKV0gPSB0aGlzLnZhbHVlU2VydmljZS5nZXRWYWx1ZShncm91cENvbHVtbiwgZ3JvdXBJbmZvLmxlYWZOb2RlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0Q2hpbGRyZW5NYXBwZWRLZXkoa2V5OiBzdHJpbmcsIHJvd0dyb3VwQ29sdW1uOiBDb2x1bW4gfCBudWxsKTogc3RyaW5nIHtcclxuICAgICAgICBpZiAocm93R3JvdXBDb2x1bW4pIHtcclxuICAgICAgICAgICAgLy8gZ3JvdXBpbmcgYnkgY29sdW1uc1xyXG4gICAgICAgICAgICByZXR1cm4gcm93R3JvdXBDb2x1bW4uZ2V0SWQoKSArICctJyArIGtleTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gdHJlZSBkYXRhIC0gd2UgZG9uJ3QgaGF2ZSByb3dHcm91cENvbHVtbnNcclxuICAgICAgICByZXR1cm4ga2V5O1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc2V0RXhwYW5kZWRJbml0aWFsVmFsdWUoZGV0YWlsczogR3JvdXBpbmdEZXRhaWxzLCBncm91cE5vZGU6IFJvd05vZGUpOiB2b2lkIHtcclxuICAgICAgICAvLyBpZiBwaXZvdGluZyB0aGUgbGVhZiBncm91cCBpcyBuZXZlciBleHBhbmRlZCBhcyB3ZSBkbyBub3Qgc2hvdyBsZWFmIHJvd3NcclxuICAgICAgICBpZiAoZGV0YWlscy5waXZvdE1vZGUgJiYgZ3JvdXBOb2RlLmxlYWZHcm91cCkge1xyXG4gICAgICAgICAgICBncm91cE5vZGUuZXhwYW5kZWQgPSBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gdXNlIGNhbGxiYWNrIGlmIGV4aXN0c1xyXG4gICAgICAgIGNvbnN0IHVzZXJDYWxsYmFjayA9IGRldGFpbHMuaXNHcm91cE9wZW5CeURlZmF1bHQ7XHJcbiAgICAgICAgaWYgKHVzZXJDYWxsYmFjaykge1xyXG4gICAgICAgICAgICBjb25zdCBwYXJhbXM6IFdpdGhvdXRHcmlkQ29tbW9uPElzR3JvdXBPcGVuQnlEZWZhdWx0UGFyYW1zPiA9IHtcclxuICAgICAgICAgICAgICAgIHJvd05vZGU6IGdyb3VwTm9kZSxcclxuICAgICAgICAgICAgICAgIGZpZWxkOiBncm91cE5vZGUuZmllbGQhLFxyXG4gICAgICAgICAgICAgICAga2V5OiBncm91cE5vZGUua2V5ISxcclxuICAgICAgICAgICAgICAgIGxldmVsOiBncm91cE5vZGUubGV2ZWwsXHJcbiAgICAgICAgICAgICAgICByb3dHcm91cENvbHVtbjogZ3JvdXBOb2RlLnJvd0dyb3VwQ29sdW1uIVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBncm91cE5vZGUuZXhwYW5kZWQgPSB1c2VyQ2FsbGJhY2socGFyYW1zKSA9PSB0cnVlO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyB1c2UgZXhwYW5kQnlEZWZhdWx0IGlmIGV4aXN0c1xyXG4gICAgICAgIGNvbnN0IHsgZXhwYW5kQnlEZWZhdWx0IH0gPSBkZXRhaWxzO1xyXG4gICAgICAgIGlmIChkZXRhaWxzLmV4cGFuZEJ5RGVmYXVsdCA9PT0gLTEpIHtcclxuICAgICAgICAgICAgZ3JvdXBOb2RlLmV4cGFuZGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gb3RoZXJ3aXNlXHJcbiAgICAgICAgZ3JvdXBOb2RlLmV4cGFuZGVkID0gZ3JvdXBOb2RlLmxldmVsIDwgZXhwYW5kQnlEZWZhdWx0O1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0R3JvdXBJbmZvKHJvd05vZGU6IFJvd05vZGUsIGRldGFpbHM6IEdyb3VwaW5nRGV0YWlscyk6IEdyb3VwSW5mb1tdIHtcclxuICAgICAgICBpZiAoZGV0YWlscy51c2luZ1RyZWVEYXRhKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEdyb3VwSW5mb0Zyb21DYWxsYmFjayhyb3dOb2RlLCBkZXRhaWxzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0R3JvdXBJbmZvRnJvbUdyb3VwQ29sdW1ucyhyb3dOb2RlLCBkZXRhaWxzKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGdldEdyb3VwSW5mb0Zyb21DYWxsYmFjayhyb3dOb2RlOiBSb3dOb2RlLCBkZXRhaWxzOiBHcm91cGluZ0RldGFpbHMpOiBHcm91cEluZm9bXSB7ICAgICAgICBcclxuICAgICAgICBjb25zdCBrZXlzOiBzdHJpbmdbXSB8IG51bGwgPSBkZXRhaWxzLmdldERhdGFQYXRoID8gZGV0YWlscy5nZXREYXRhUGF0aChyb3dOb2RlLmRhdGEpIDogbnVsbDtcclxuXHJcbiAgICAgICAgaWYgKGtleXMgPT09IG51bGwgfHwga2V5cyA9PT0gdW5kZWZpbmVkIHx8IGtleXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIF8ud2Fybk9uY2UoYGdldERhdGFQYXRoKCkgc2hvdWxkIG5vdCByZXR1cm4gYW4gZW1wdHkgcGF0aCBmb3IgZGF0YSAke3Jvd05vZGUuZGF0YX1gKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgZ3JvdXBJbmZvTWFwcGVyID0gKGtleTogc3RyaW5nIHwgbnVsbCkgPT4gKHsga2V5LCBmaWVsZDogbnVsbCwgcm93R3JvdXBDb2x1bW46IG51bGwgfSkgYXMgR3JvdXBJbmZvO1xyXG4gICAgICAgIHJldHVybiBrZXlzID8ga2V5cy5tYXAoZ3JvdXBJbmZvTWFwcGVyKSA6IFtdO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0R3JvdXBJbmZvRnJvbUdyb3VwQ29sdW1ucyhyb3dOb2RlOiBSb3dOb2RlLCBkZXRhaWxzOiBHcm91cGluZ0RldGFpbHMpIHtcclxuICAgICAgICBjb25zdCByZXM6IEdyb3VwSW5mb1tdID0gW107XHJcbiAgICAgICAgZGV0YWlscy5ncm91cGVkQ29scy5mb3JFYWNoKGdyb3VwQ29sID0+IHtcclxuICAgICAgICAgICAgbGV0IGtleTogc3RyaW5nID0gdGhpcy52YWx1ZVNlcnZpY2UuZ2V0S2V5Rm9yTm9kZShncm91cENvbCwgcm93Tm9kZSk7XHJcbiAgICAgICAgICAgIGxldCBrZXlFeGlzdHMgPSBrZXkgIT09IG51bGwgJiYga2V5ICE9PSB1bmRlZmluZWQgJiYga2V5ICE9PSAnJztcclxuXHJcbiAgICAgICAgICAgIC8vIHVuYmFsYW5jZWQgdHJlZSBhbmQgcGl2b3QgbW9kZSBkb24ndCB3b3JrIHRvZ2V0aGVyIC0gbm90IGJlY2F1c2Ugb2YgdGhlIGdyaWQsIGl0IGRvZXNuJ3QgbWFrZVxyXG4gICAgICAgICAgICAvLyBtYXRoZW1hdGljYWwgc2Vuc2UgYXMgeW91IGFyZSBidWlsZGluZyB1cCBhIGN1YmUuIHNvIGlmIHBpdm90IG1vZGUsIHdlIHB1dCBpbiBhIGJsYW5rIGtleSB3aGVyZSBtaXNzaW5nLlxyXG4gICAgICAgICAgICAvLyB0aGlzIGtlZXBzIHRoZSB0cmVlIGJhbGFuY2VkIGFuZCBoZW5jZSBjYW4gYmUgcmVwcmVzZW50ZWQgYXMgYSBncm91cC5cclxuICAgICAgICAgICAgY29uc3QgY3JlYXRlR3JvdXBGb3JFbXB0eSA9IGRldGFpbHMucGl2b3RNb2RlIHx8ICFkZXRhaWxzLmdyb3VwQWxsb3dVbmJhbGFuY2VkO1xyXG4gICAgICAgICAgICBpZiAoY3JlYXRlR3JvdXBGb3JFbXB0eSAmJiAha2V5RXhpc3RzKSB7XHJcbiAgICAgICAgICAgICAgICBrZXkgPSAnJztcclxuICAgICAgICAgICAgICAgIGtleUV4aXN0cyA9IHRydWU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmIChrZXlFeGlzdHMpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW0gPSB7XHJcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXksXHJcbiAgICAgICAgICAgICAgICAgICAgZmllbGQ6IGdyb3VwQ29sLmdldENvbERlZigpLmZpZWxkLFxyXG4gICAgICAgICAgICAgICAgICAgIHJvd0dyb3VwQ29sdW1uOiBncm91cENvbCxcclxuICAgICAgICAgICAgICAgICAgICBsZWFmTm9kZTogcm93Tm9kZSxcclxuICAgICAgICAgICAgICAgIH0gYXMgR3JvdXBJbmZvO1xyXG4gICAgICAgICAgICAgICAgcmVzLnB1c2goaXRlbSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm4gcmVzO1xyXG4gICAgfVxyXG59Il19
|