ng-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
389 lines (386 loc) • 50.6 kB
JavaScript
/**
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/
import { __decorate, __metadata } from "tslib";
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Host, Input, NgZone, Optional, Output, QueryList, TemplateRef, ViewChildren, ViewEncapsulation } from '@angular/core';
import { buildGraph } from '@nx-component/hierarchy-graph';
import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation';
import { cancelRequestAnimationFrame } from 'ng-zorro-antd/core/polyfill';
import { InputBoolean } from 'ng-zorro-antd/core/util';
import { forkJoin, ReplaySubject, Subject } from 'rxjs';
import { finalize, skip, take, takeUntil } from 'rxjs/operators';
import { calculateTransform } from './core/utils';
import { NzGraphData } from './data-source/graph-data-source';
import { NzGraphEdgeDirective } from './graph-edge.directive';
import { NzGraphNodeComponent } from './graph-node.component';
import { NzGraphNodeDirective } from './graph-node.directive';
import { nzTypeDefinition, NZ_GRAPH_LAYOUT_SETTING } from './interface';
/** Checks whether an object is a data source. */
export function isDataSource(value) {
// Check if the value is a DataSource by observing if it has a connect function. Cannot
// be checked as an `instanceof DataSource` since people could create their own sources
// that match the interface, but don't extend DataSource.
return value && typeof value.connect === 'function';
}
export class NzGraphComponent {
constructor(cdr, ngZone, elementRef, noAnimation) {
this.cdr = cdr;
this.ngZone = ngZone;
this.elementRef = elementRef;
this.noAnimation = noAnimation;
this.nzRankDirection = 'LR';
this.nzAutoSize = false;
this.nzGraphInitialized = new EventEmitter();
this.nzGraphRendered = new EventEmitter();
this.nzNodeClick = new EventEmitter();
this.requestId = -1;
this.transformStyle = '';
this.graphRenderedSubject$ = new ReplaySubject(1);
this.renderInfo = { labelHeight: 0 };
this.mapOfNodeAttr = {};
this.mapOfEdgeAttr = {};
this.typedNodes = nzTypeDefinition();
this.layoutSetting = NZ_GRAPH_LAYOUT_SETTING;
this.destroy$ = new Subject();
this.nodeTrackByFun = (_, node) => node.name;
this.edgeTrackByFun = (_, edge) => `${edge.v}-${edge.w}`;
this.subGraphTransform = (node) => {
const x = node.x - node.coreBox.width / 2.0;
const y = node.y - node.height / 2.0 + node.paddingTop / 2.0;
return `translate(${x}, ${y})`;
};
this.coreTransform = (node) => {
return `translate(0, ${node.parentNodeName ? node.labelHeight : 0})`;
};
}
ngOnInit() {
this.graphRenderedSubject$.pipe(skip(this.nzAutoSize ? 1 : 0), take(1), takeUntil(this.destroy$)).subscribe(() => {
this.fitCenter();
this.nzGraphInitialized.emit(this);
});
}
ngOnChanges(changes) {
const { nzAutoFit, nzRankDirection, nzGraphData, nzGraphLayoutSettings } = changes;
if (nzGraphLayoutSettings) {
Object.assign(this.layoutSetting, this.nzGraphLayoutSettings || {});
}
if (nzGraphData) {
if (this.dataSource !== this.nzGraphData) {
this._switchDataSource(this.nzGraphData);
}
}
if ((nzAutoFit && !nzAutoFit.firstChange) || (nzRankDirection && !nzRankDirection.firstChange)) {
// Render graph
if (this.dataSource.dataSource) {
this.drawGraph(this.dataSource.dataSource, {
rankDirection: this.nzRankDirection,
expanded: this.dataSource.expansionModel.selected || []
}).then();
}
}
this.cdr.markForCheck();
}
ngAfterViewInit() { }
ngAfterContentChecked() {
if (this.dataSource && !this._dataSubscription) {
this.observeRenderChanges();
}
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
if (this.dataSource && typeof this.dataSource.disconnect === 'function') {
this.dataSource.disconnect();
}
if (this._dataSubscription) {
this._dataSubscription.unsubscribe();
this._dataSubscription = null;
}
cancelRequestAnimationFrame(this.requestId);
}
/**
* Emit event
*/
clickNode(node) {
this.nzNodeClick.emit(node);
}
/**
* Move graph to center and scale automatically
*/
fitCenter() {
const { x, y, k } = calculateTransform(this.elementRef.nativeElement.querySelector('svg'), this.elementRef.nativeElement.querySelector('svg > g'));
this.transformStyle = `translate(${x}, ${y})scale(${k})`;
this.cdr.markForCheck();
}
/**
* re-Draw graph
* @param data
* @param options
* @param needResize
*/
drawGraph(data, options, needResize = false) {
return new Promise(resolve => {
this.requestId = requestAnimationFrame(() => {
var _a;
const renderInfo = this.buildGraphInfo(data, options);
// TODO
// Need better performance
this.renderInfo = renderInfo;
this.cdr.markForCheck();
this.drawNodes(!((_a = this.noAnimation) === null || _a === void 0 ? void 0 : _a.nzNoAnimation)).then(() => {
// Update element
this.cdr.markForCheck();
this.graphRenderedSubject$.next();
this.nzGraphRendered.emit(this);
});
if (needResize) {
this.resizeNodeSize().then(() => {
const dataSource = this.dataSource.dataSource;
return this.drawGraph(dataSource, options, false);
});
}
else {
resolve();
}
});
this.cdr.markForCheck();
});
}
/**
* Redraw all nodes
* @param animate
*/
drawNodes(animate = true) {
return new Promise(resolve => {
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
if (animate) {
this.makeNodesAnimation().subscribe(() => {
resolve();
});
}
else {
this.listOfNodeComponent.map(node => {
node.makeNoAnimation();
});
resolve();
}
});
});
}
resizeNodeSize() {
return new Promise(resolve => {
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
const dataSource = this.dataSource.dataSource;
let scale = this.getScale();
this.listOfNodeElement.forEach(nodeEle => {
var _a;
const contentEle = nodeEle.nativeElement;
if (contentEle) {
let width;
let height;
// Check if foreignObject is set
const clientRect = (_a = contentEle.querySelector('foreignObject > :first-child')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
if (clientRect) {
width = clientRect.width;
height = clientRect.height;
}
else {
const bBoxRect = contentEle.getBBox();
width = bBoxRect.width;
height = bBoxRect.height;
// getBBox will return actual value
scale = 1;
}
// Element id type is string
const node = dataSource.nodes.find(n => `${n.id}` === nodeEle.nativeElement.id);
if (node && width && height) {
node.height = height / scale;
node.width = width / scale;
}
}
});
resolve();
});
});
}
/**
* Switch to the provided data source by resetting the data and unsubscribing from the current
* render change subscription if one exists. If the data source is null, interpret this by
* clearing the node outlet. Otherwise start listening for new data.
*/
_switchDataSource(dataSource) {
if (this.dataSource && typeof this.dataSource.disconnect === 'function') {
this.nzGraphData.disconnect();
}
if (this._dataSubscription) {
this._dataSubscription.unsubscribe();
this._dataSubscription = null;
}
this.dataSource = dataSource;
this.observeRenderChanges();
}
/** Set up a subscription for the data provided by the data source. */
observeRenderChanges() {
let dataStream;
let graphOptions = {
rankDirection: this.nzRankDirection
};
if (isDataSource(this.dataSource)) {
dataStream = this.dataSource.connect();
}
if (dataStream) {
this._dataSubscription = dataStream.pipe(takeUntil(this.destroy$)).subscribe(data => {
graphOptions = {
rankDirection: this.nzRankDirection,
expanded: this.nzGraphData.expansionModel.selected
};
this.drawGraph(data, graphOptions, this.nzAutoSize).then(() => {
this.cdr.detectChanges();
});
});
}
else {
throw Error(`A valid data source must be provided.`);
}
}
// TODO
// A better way?
getScale() {
var _a;
const transform = ((_a = this.elementRef.nativeElement.querySelector('svg > g')) === null || _a === void 0 ? void 0 : _a.getAttribute('transform')) || '';
// Get current scale
const regex = /scale\(([0-9\.]+)\)/g;
const match = regex.exec(transform);
if (match && match[1]) {
return parseFloat(match[1]);
}
return 1;
}
/**
* Get renderInfo and prepare some data
* @param data
* @param options
* @private
*/
buildGraphInfo(data, options) {
this.parseInfo(data);
const renderInfo = buildGraph(data, options, this.layoutSetting);
const dig = (nodes) => {
nodes.forEach(node => {
if (node.type === 1 && this.mapOfNodeAttr.hasOwnProperty(node.name)) {
Object.assign(node, this.mapOfNodeAttr[node.name]);
}
else if (node.type === 0) {
node.edges.forEach(edge => {
if (this.mapOfEdgeAttr.hasOwnProperty(`${edge.v}-${edge.w}`)) {
Object.assign(edge, this.mapOfEdgeAttr[`${edge.v}-${edge.w}`]);
}
});
dig(node.nodes);
}
});
};
dig(renderInfo.nodes);
// Assign data to edges of root graph
renderInfo.edges.forEach(edge => {
if (this.mapOfEdgeAttr.hasOwnProperty(`${edge.v}-${edge.w}`)) {
Object.assign(edge, this.mapOfEdgeAttr[`${edge.v}-${edge.w}`]);
}
});
return renderInfo;
}
/**
* Play with animation
* @private
*/
makeNodesAnimation() {
return forkJoin(...this.listOfNodeComponent.map(node => node.makeAnimation())).pipe(finalize(() => {
this.cdr.detectChanges();
}));
}
parseInfo(data) {
data.nodes.forEach(n => {
this.mapOfNodeAttr[n.id] = n;
});
data.edges.forEach(e => {
this.mapOfEdgeAttr[`${e.v}-${e.w}`] = e;
});
}
}
NzGraphComponent.decorators = [
{ type: Component, args: [{
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
selector: 'nz-graph',
exportAs: 'nzGraph',
template: `
<ng-content></ng-content>
<svg width="100%" height="100%">
<svg:defs nz-graph-defs></svg:defs>
<svg:g [attr.transform]="transformStyle">
<ng-container
[ngTemplateOutlet]="groupTemplate"
[ngTemplateOutletContext]="{ renderNode: renderInfo, type: 'root' }"
></ng-container>
</svg:g>
</svg>
<ng-template #groupTemplate let-renderNode="renderNode" let-type="type">
<svg:g [attr.transform]="type === 'sub' ? subGraphTransform(renderNode) : null">
<svg:g class="core" [attr.transform]="coreTransform(renderNode)">
<svg:g class="nz-graph-edges">
<ng-container *ngFor="let edge of renderNode.edges; trackBy: edgeTrackByFun">
<g class="nz-graph-edge" nz-graph-edge [edge]="edge" [customTemplate]="customGraphEdgeTemplate"></g>
</ng-container>
</svg:g>
<svg:g class="nz-graph-nodes">
<ng-container *ngFor="let node of typedNodes(renderNode.nodes); trackBy: nodeTrackByFun">
<g
*ngIf="node.type !== 2"
class="nz-graph-node"
nz-graph-node
[node]="node"
[customTemplate]="customGraphNodeTemplate"
(nodeClick)="clickNode($event)"
></g>
<ng-container
*ngIf="node.expanded"
[ngTemplateOutlet]="groupTemplate"
[ngTemplateOutletContext]="{ renderNode: node, type: 'sub' }"
></ng-container>
</ng-container>
</svg:g>
</svg:g>
</svg:g>
</ng-template>
`,
host: {
'[class.nz-graph]': 'true',
'[class.nz-graph-auto-size]': 'nzAutoSize'
}
},] }
];
NzGraphComponent.ctorParameters = () => [
{ type: ChangeDetectorRef },
{ type: NgZone },
{ type: ElementRef },
{ type: NzNoAnimationDirective, decorators: [{ type: Host }, { type: Optional }] }
];
NzGraphComponent.propDecorators = {
listOfNodeElement: [{ type: ViewChildren, args: [NzGraphNodeComponent, { read: ElementRef },] }],
listOfNodeComponent: [{ type: ViewChildren, args: [NzGraphNodeComponent,] }],
customGraphNodeTemplate: [{ type: ContentChild, args: [NzGraphNodeDirective, { static: true, read: TemplateRef },] }],
customGraphEdgeTemplate: [{ type: ContentChild, args: [NzGraphEdgeDirective, { static: true, read: TemplateRef },] }],
nzGraphData: [{ type: Input }],
nzRankDirection: [{ type: Input }],
nzGraphLayoutSettings: [{ type: Input }],
nzAutoSize: [{ type: Input }],
nzGraphInitialized: [{ type: Output }],
nzGraphRendered: [{ type: Output }],
nzNodeClick: [{ type: Output }]
};
__decorate([
InputBoolean(),
__metadata("design:type", Object)
], NzGraphComponent.prototype, "nzAutoSize", void 0);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JhcGguY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Ii9ob21lL3ZzdHMvd29yay8xL3MvY29tcG9uZW50cy9ncmFwaC8iLCJzb3VyY2VzIjpbImdyYXBoLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7O0FBRUgsT0FBTyxFQUdMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULFlBQVksRUFDWixVQUFVLEVBQ1YsWUFBWSxFQUNaLElBQUksRUFDSixLQUFLLEVBQ0wsTUFBTSxFQUlOLFFBQVEsRUFDUixNQUFNLEVBQ04sU0FBUyxFQUVULFdBQVcsRUFDWCxZQUFZLEVBQ1osaUJBQWlCLEVBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6RSxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUUxRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFFBQVEsRUFBYyxhQUFhLEVBQUUsT0FBTyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUNsRixPQUFPLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDakUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2xELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUM5RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBV0ws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QUFNOzhCQUNOLE1BQU07MEJBQ04sTUFBTTs7QUFKa0I7SUFBZixZQUFZLEVBQUU7O29EQUFvQiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9naXRodWIuY29tL05HLVpPUlJPL25nLXpvcnJvLWFudGQvYmxvYi9tYXN0ZXIvTElDRU5TRVxuICovXG5cbmltcG9ydCB7XG4gIEFmdGVyQ29udGVudENoZWNrZWQsXG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBDb250ZW50Q2hpbGQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdCxcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgUXVlcnlMaXN0LFxuICBTaW1wbGVDaGFuZ2VzLFxuICBUZW1wbGF0ZVJlZixcbiAgVmlld0NoaWxkcmVuLFxuICBWaWV3RW5jYXBzdWxhdGlvblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGJ1aWxkR3JhcGggfSBmcm9tICdAbngtY29tcG9uZW50L2hpZXJhcmNoeS1ncmFwaCc7XG5pbXBvcnQgeyBOek5vQW5pbWF0aW9uRGlyZWN0aXZlIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL25vLWFuaW1hdGlvbic7XG5pbXBvcnQgeyBjYW5jZWxSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvcG9seWZpbGwnO1xuaW1wb3J0IHsgQm9vbGVhbklucHV0LCBOelNhZmVBbnkgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvdHlwZXMnO1xuaW1wb3J0IHsgSW5wdXRCb29sZWFuIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL3V0aWwnO1xuaW1wb3J0IHsgZm9ya0pvaW4sIE9ic2VydmFibGUsIFJlcGxheVN1YmplY3QsIFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmluYWxpemUsIHNraXAsIHRha2UsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IGNhbGN1bGF0ZVRyYW5zZm9ybSB9IGZyb20gJy4vY29yZS91dGlscyc7XG5pbXBvcnQgeyBOekdyYXBoRGF0YSB9IGZyb20gJy4vZGF0YS1zb3VyY2UvZ3JhcGgtZGF0YS1zb3VyY2UnO1xuaW1wb3J0IHsgTnpHcmFwaEVkZ2VEaXJlY3RpdmUgfSBmcm9tICcuL2dyYXBoLWVkZ2UuZGlyZWN0aXZlJztcbmltcG9ydCB7IE56R3JhcGhOb2RlQ29tcG9uZW50IH0gZnJvbSAnLi9ncmFwaC1ub2RlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBOekdyYXBoTm9kZURpcmVjdGl2ZSB9IGZyb20gJy4vZ3JhcGgtbm9kZS5kaXJlY3RpdmUnO1xuaW1wb3J0IHtcbiAgTnpHcmFwaERhdGFEZWYsXG4gIE56R3JhcGhFZGdlLFxuICBOekdyYXBoRWRnZURlZixcbiAgTnpHcmFwaEdyb3VwTm9kZSxcbiAgTnpHcmFwaExheW91dFNldHRpbmcsXG4gIE56R3JhcGhOb2RlLFxuICBOekdyYXBoTm9kZURlZixcbiAgTnpHcmFwaE9wdGlvbixcbiAgTnpMYXlvdXRTZXR0aW5nLFxuICBOelJhbmtEaXJlY3Rpb24sXG4gIG56VHlwZURlZmluaXRpb24sXG4gIE5aX0dSQVBIX0xBWU9VVF9TRVRUSU5HXG59IGZyb20gJy4vaW50ZXJmYWNlJztcblxuLyoqIENoZWNrcyB3aGV0aGVyIGFuIG9iamVjdCBpcyBhIGRhdGEgc291cmNlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGF0YVNvdXJjZSh2YWx1ZTogTnpTYWZlQW55KTogdmFsdWUgaXMgTnpHcmFwaERhdGEge1xuICAvLyBDaGVjayBpZiB0aGUgdmFsdWUgaXMgYSBEYXRhU291cmNlIGJ5IG9ic2VydmluZyBpZiBpdCBoYXMgYSBjb25uZWN0IGZ1bmN0aW9uLiBDYW5ub3RcbiAgLy8gYmUgY2hlY2tlZCBhcyBhbiBgaW5zdGFuY2VvZiBEYXRhU291cmNlYCBzaW5jZSBwZW9wbGUgY291bGQgY3JlYXRlIHRoZWlyIG93biBzb3VyY2VzXG4gIC8vIHRoYXQgbWF0Y2ggdGhlIGludGVyZmFjZSwgYnV0IGRvbid0IGV4dGVuZCBEYXRhU291cmNlLlxuICByZXR1cm4gdmFsdWUgJiYgdHlwZW9mIHZhbHVlLmNvbm5lY3QgPT09ICdmdW5jdGlvbic7XG59XG5cbkBDb21wb25lbnQoe1xuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgc2VsZWN0b3I6ICduei1ncmFwaCcsXG4gIGV4cG9ydEFzOiAnbnpHcmFwaCcsXG4gIHRlbXBsYXRlOiBgXG4gICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgIDxzdmcgd2lkdGg9XCIxMDAlXCIgaGVpZ2h0PVwiMTAwJVwiPlxuICAgICAgPHN2ZzpkZWZzIG56LWdyYXBoLWRlZnM+PC9zdmc6ZGVmcz5cbiAgICAgIDxzdmc6ZyBbYXR0ci50cmFuc2Zvcm1dPVwidHJhbnNmb3JtU3R5bGVcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImdyb3VwVGVtcGxhdGVcIlxuICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IHJlbmRlck5vZGU6IHJlbmRlckluZm8sIHR5cGU6ICdyb290JyB9XCJcbiAgICAgICAgPjwvbmctY29udGFpbmVyPlxuICAgICAgPC9zdmc6Zz5cbiAgICA8L3N2Zz5cblxuICAgIDxuZy10ZW1wbGF0ZSAjZ3JvdXBUZW1wbGF0ZSBsZXQtcmVuZGVyTm9kZT1cInJlbmRlck5vZGVcIiBsZXQtdHlwZT1cInR5cGVcIj5cbiAgICAgIDxzdmc6ZyBbYXR0ci50cmFuc2Zvcm1dPVwidHlwZSA9PT0gJ3N1YicgPyBzdWJHcmFwaFRyYW5zZm9ybShyZW5kZXJOb2RlKSA6IG51bGxcIj5cbiAgICAgICAgPHN2ZzpnIGNsYXNzPVwiY29yZVwiIFthdHRyLnRyYW5zZm9ybV09XCJjb3JlVHJhbnNmb3JtKHJlbmRlck5vZGUpXCI+XG4gICAgICAgICAgPHN2ZzpnIGNsYXNzPVwibnotZ3JhcGgtZWRnZXNcIj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGVkZ2Ugb2YgcmVuZGVyTm9kZS5lZGdlczsgdHJhY2tCeTogZWRnZVRyYWNrQnlGdW5cIj5cbiAgICAgICAgICAgICAgPGcgY2xhc3M9XCJuei1ncmFwaC1lZGdlXCIgbnotZ3JhcGgtZWRnZSBbZWRnZV09XCJlZGdlXCIgW2N1c3RvbVRlbXBsYXRlXT1cImN1c3RvbUdyYXBoRWRnZVRlbXBsYXRlXCI+PC9nPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgPC9zdmc6Zz5cblxuICAgICAgICAgIDxzdmc6ZyBjbGFzcz1cIm56LWdyYXBoLW5vZGVzXCI+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBub2RlIG9mIHR5cGVkTm9kZXMocmVuZGVyTm9kZS5ub2Rlcyk7IHRyYWNrQnk6IG5vZGVUcmFja0J5RnVuXCI+XG4gICAgICAgICAgICAgIDxnXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJub2RlLnR5cGUgIT09IDJcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwibnotZ3JhcGgtbm9kZVwiXG4gICAgICAgICAgICAgICAgbnotZ3JhcGgtbm9kZVxuICAgICAgICAgICAgICAgIFtub2RlXT1cIm5vZGVcIlxuICAgICAgICAgICAgICAgIFtjdXN0b21UZW1wbGF0ZV09XCJjdXN0b21HcmFwaE5vZGVUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgICAgKG5vZGVDbGljayk9XCJjbGlja05vZGUoJGV2ZW50KVwiXG4gICAgICAgICAgICAgID48L2c+XG5cbiAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgICAgICpuZ0lmPVwibm9kZS5leHBhbmRlZFwiXG4gICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiZ3JvdXBUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgcmVuZGVyTm9kZTogbm9kZSwgdHlwZTogJ3N1YicgfVwiXG4gICAgICAgICAgICAgID48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgIDwvc3ZnOmc+XG4gICAgICAgIDwvc3ZnOmc+XG4gICAgICA8L3N2ZzpnPlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIGAsXG4gIGhvc3Q6IHtcbiAgICAnW2NsYXNzLm56LWdyYXBoXSc6ICd0cnVlJyxcbiAgICAnW2NsYXNzLm56LWdyYXBoLWF1dG8tc2l6ZV0nOiAnbnpBdXRvU2l6ZSdcbiAgfVxufSlcbmV4cG9ydCBjbGFzcyBOekdyYXBoQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQsIEFmdGVyQ29udGVudENoZWNrZWQsIE9uRGVzdHJveSB7XG4gIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9uekF1dG9TaXplOiBCb29sZWFuSW5wdXQ7XG5cbiAgQFZpZXdDaGlsZHJlbihOekdyYXBoTm9kZUNvbXBvbmVudCwgeyByZWFkOiBFbGVtZW50UmVmIH0pIGxpc3RPZk5vZGVFbGVtZW50ITogUXVlcnlMaXN0PEVsZW1lbnRSZWY+O1xuICBAVmlld0NoaWxkcmVuKE56R3JhcGhOb2RlQ29tcG9uZW50KSBsaXN0T2ZOb2RlQ29tcG9uZW50ITogUXVlcnlMaXN0PE56R3JhcGhOb2RlQ29tcG9uZW50PjtcblxuICBAQ29udGVudENoaWxkKE56R3JhcGhOb2RlRGlyZWN0aXZlLCB7IHN0YXRpYzogdHJ1ZSwgcmVhZDogVGVtcGxhdGVSZWYgfSkgY3VzdG9tR3JhcGhOb2RlVGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjx7XG4gICAgJGltcGxpY2l0OiBOekdyYXBoTm9kZSB8IE56R3JhcGhHcm91cE5vZGU7XG4gIH0+O1xuICBAQ29udGVudENoaWxkKE56R3JhcGhFZGdlRGlyZWN0aXZlLCB7IHN0YXRpYzogdHJ1ZSwgcmVhZDogVGVtcGxhdGVSZWYgfSkgY3VzdG9tR3JhcGhFZGdlVGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjx7XG4gICAgJGltcGxpY2l0OiBOekdyYXBoRWRnZTtcbiAgfT47XG4gIC8qKlxuICAgKiBQcm92aWRlcyBhIHN0cmVhbSBjb250YWluaW5nIHRoZSBsYXRlc3QgZGF0YSBhcnJheSB0byByZW5kZXIuXG4gICAqIERhdGEgc291cmNlIGNhbiBiZSBhbiBvYnNlcnZhYmxlIG9mIE56R3JhcGhEYXRhLCBvciBhIE56R3JhcGhEYXRhIHRvIHJlbmRlci5cbiAgICovXG4gIEBJbnB1dCgpIG56R3JhcGhEYXRhITogTnpHcmFwaERhdGE7XG4gIEBJbnB1dCgpIG56UmFua0RpcmVjdGlvbjogTnpSYW5rRGlyZWN0aW9uID0gJ0xSJztcbiAgQElucHV0KCkgbnpHcmFwaExheW91dFNldHRpbmdzPzogTnpHcmFwaExheW91dFNldHRpbmc7XG4gIEBJbnB1dCgpIEBJbnB1dEJvb2xlYW4oKSBuekF1dG9TaXplID0gZmFsc2U7XG5cbiAgQE91dHB1dCgpIHJlYWRvbmx5IG56R3JhcGhJbml0aWFsaXplZCA9IG5ldyBFdmVudEVtaXR0ZXI8TnpHcmFwaENvbXBvbmVudD4oKTtcbiAgQE91dHB1dCgpIHJlYWRvbmx5IG56R3JhcGhSZW5kZXJlZCA9IG5ldyBFdmVudEVtaXR0ZXI8TnpHcmFwaENvbXBvbmVudD4oKTtcbiAgQE91dHB1dCgpIHJlYWRvbmx5IG56Tm9kZUNsaWNrOiBFdmVudEVtaXR0ZXI8TnpHcmFwaE5vZGUgfCBOekdyYXBoR3JvdXBOb2RlPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICByZXF1ZXN0SWQ6IG51bWJlciA9IC0xO1xuICB0cmFuc2Zvcm1TdHlsZSA9ICcnO1xuICBncmFwaFJlbmRlcmVkU3ViamVjdCQgPSBuZXcgUmVwbGF5U3ViamVjdDx2b2lkPigxKTtcbiAgcmVuZGVySW5mbzogTnpHcmFwaEdyb3VwTm9kZSA9IHsgbGFiZWxIZWlnaHQ6IDAgfSBhcyBOekdyYXBoR3JvdXBOb2RlO1xuICBtYXBPZk5vZGVBdHRyOiB7IFtrZXk6IHN0cmluZ106IE56R3JhcGhOb2RlRGVmIH0gPSB7fTtcbiAgbWFwT2ZFZGdlQXR0cjogeyBba2V5OiBzdHJpbmddOiBOekdyYXBoRWRnZURlZiB9ID0ge307XG5cbiAgcHVibGljIHJlYWRvbmx5IHR5cGVkTm9kZXMgPSBuelR5cGVEZWZpbml0aW9uPEFycmF5PE56R3JhcGhOb2RlIHwgTnpHcmFwaEdyb3VwTm9kZT4+KCk7XG4gIHByaXZhdGUgZGF0YVNvdXJjZT86IE56R3JhcGhEYXRhO1xuICBwcml2YXRlIGxheW91dFNldHRpbmc6IE56TGF5b3V0U2V0dGluZyA9IE5aX0dSQVBIX0xBWU9VVF9TRVRUSU5HO1xuICAvKiogRGF0YSBzdWJzY3JpcHRpb24gKi9cbiAgcHJpdmF0ZSBfZGF0YVN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbiB8IG51bGw7XG4gIHByaXZhdGUgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIG5vZGVUcmFja0J5RnVuID0gKF86IG51bWJlciwgbm9kZTogTnpHcmFwaE5vZGUgfCBOekdyYXBoR3JvdXBOb2RlKSA9PiBub2RlLm5hbWU7XG4gIGVkZ2VUcmFja0J5RnVuID0gKF86IG51bWJlciwgZWRnZTogTnpHcmFwaEVkZ2UpID0+IGAke2VkZ2Uudn0tJHtlZGdlLnd9YDtcblxuICBzdWJHcmFwaFRyYW5zZm9ybSA9IChub2RlOiBOekdyYXBoR3JvdXBOb2RlKSA9PiB7XG4gICAgY29uc3QgeCA9IG5vZGUueCAtIG5vZGUuY29yZUJveC53aWR0aCAvIDIuMDtcbiAgICBjb25zdCB5ID0gbm9kZS55IC0gbm9kZS5oZWlnaHQgLyAyLjAgKyBub2RlLnBhZGRpbmdUb3AgLyAyLjA7XG4gICAgcmV0dXJuIGB0cmFuc2xhdGUoJHt4fSwgJHt5fSlgO1xuICB9O1xuXG4gIGNvcmVUcmFuc2Zvcm0gPSAobm9kZTogTnpHcmFwaEdyb3VwTm9kZSkgPT4ge1xuICAgIHJldHVybiBgdHJhbnNsYXRlKDAsICR7bm9kZS5wYXJlbnROb2RlTmFtZSA/IG5vZGUubGFiZWxIZWlnaHQgOiAwfSlgO1xuICB9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIG5nWm9uZTogTmdab25lLFxuICAgIHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICBASG9zdCgpIEBPcHRpb25hbCgpIHB1YmxpYyBub0FuaW1hdGlvbj86IE56Tm9BbmltYXRpb25EaXJlY3RpdmVcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuZ3JhcGhSZW5kZXJlZFN1YmplY3QkLnBpcGUoc2tpcCh0aGlzLm56QXV0b1NpemUgPyAxIDogMCksIHRha2UoMSksIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIHRoaXMuZml0Q2VudGVyKCk7XG4gICAgICB0aGlzLm56R3JhcGhJbml0aWFsaXplZC5lbWl0KHRoaXMpO1xuICAgIH0pO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGNvbnN0IHsgbnpBdXRvRml0LCBuelJhbmtEaXJlY3Rpb24sIG56R3JhcGhEYXRhLCBuekdyYXBoTGF5b3V0U2V0dGluZ3MgfSA9IGNoYW5nZXM7XG4gICAgaWYgKG56R3JhcGhMYXlvdXRTZXR0aW5ncykge1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLmxheW91dFNldHRpbmcsIHRoaXMubnpHcmFwaExheW91dFNldHRpbmdzIHx8IHt9KTtcbiAgICB9XG5cbiAgICBpZiAobnpHcmFwaERhdGEpIHtcbiAgICAgIGlmICh0aGlzLmRhdGFTb3VyY2UgIT09IHRoaXMubnpHcmFwaERhdGEpIHtcbiAgICAgICAgdGhpcy5fc3dpdGNoRGF0YVNvdXJjZSh0aGlzLm56R3JhcGhEYXRhKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoKG56QXV0b0ZpdCAmJiAhbnpBdXRvRml0LmZpcnN0Q2hhbmdlKSB8fCAobnpSYW5rRGlyZWN0aW9uICYmICFuelJhbmtEaXJlY3Rpb24uZmlyc3RDaGFuZ2UpKSB7XG4gICAgICAvLyBSZW5kZXIgZ3JhcGhcbiAgICAgIGlmICh0aGlzLmRhdGFTb3VyY2UhLmRhdGFTb3VyY2UpIHtcbiAgICAgICAgdGhpcy5kcmF3R3JhcGgodGhpcy5kYXRhU291cmNlIS5kYXRhU291cmNlLCB7XG4gICAgICAgICAgcmFua0RpcmVjdGlvbjogdGhpcy5uelJhbmtEaXJlY3Rpb24sXG4gICAgICAgICAgZXhwYW5kZWQ6IHRoaXMuZGF0YVNvdXJjZSEuZXhwYW5zaW9uTW9kZWwuc2VsZWN0ZWQgfHwgW11cbiAgICAgICAgfSkudGhlbigpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge31cblxuICBuZ0FmdGVyQ29udGVudENoZWNrZWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGF0YVNvdXJjZSAmJiAhdGhpcy5fZGF0YVN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5vYnNlcnZlUmVuZGVyQ2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGVzdHJveSQubmV4dCgpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcblxuICAgIGlmICh0aGlzLmRhdGFTb3VyY2UgJiYgdHlwZW9mIHRoaXMuZGF0YVNvdXJjZS5kaXNjb25uZWN0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aGlzLmRhdGFTb3VyY2UuZGlzY29ubmVjdCgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9kYXRhU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uID0gbnVsbDtcbiAgICB9XG4gICAgY2FuY2VsUmVxdWVzdEFuaW1hdGlvbkZyYW1lKHRoaXMucmVxdWVzdElkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbWl0IGV2ZW50XG4gICAqL1xuICBjbGlja05vZGUobm9kZTogTnpHcmFwaE5vZGUgfCBOekdyYXBoR3JvdXBOb2RlKTogdm9pZCB7XG4gICAgdGhpcy5uek5vZGVDbGljay5lbWl0KG5vZGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vdmUgZ3JhcGggdG8gY2VudGVyIGFuZCBzY2FsZSBhdXRvbWF0aWNhbGx5XG4gICAqL1xuICBmaXRDZW50ZXIoKTogdm9pZCB7XG4gICAgY29uc3QgeyB4LCB5LCBrIH0gPSBjYWxjdWxhdGVUcmFuc2Zvcm0oXG4gICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdzdmcnKSxcbiAgICAgIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ3N2ZyA+IGcnKVxuICAgICkhO1xuICAgIHRoaXMudHJhbnNmb3JtU3R5bGUgPSBgdHJhbnNsYXRlKCR7eH0sICR7eX0pc2NhbGUoJHtrfSlgO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIHJlLURyYXcgZ3JhcGhcbiAgICogQHBhcmFtIGRhdGFcbiAgICogQHBhcmFtIG9wdGlvbnNcbiAgICogQHBhcmFtIG5lZWRSZXNpemVcbiAgICovXG4gIGRyYXdHcmFwaChkYXRhOiBOekdyYXBoRGF0YURlZiwgb3B0aW9uczogTnpHcmFwaE9wdGlvbiwgbmVlZFJlc2l6ZTogYm9vbGVhbiA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5yZXF1ZXN0SWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICBjb25zdCByZW5kZXJJbmZvID0gdGhpcy5idWlsZEdyYXBoSW5mbyhkYXRhLCBvcHRpb25zKTtcbiAgICAgICAgLy8gVE9ET1xuICAgICAgICAvLyBOZWVkIGJldHRlciBwZXJmb3JtYW5jZVxuICAgICAgICB0aGlzLnJlbmRlckluZm8gPSByZW5kZXJJbmZvO1xuICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgdGhpcy5kcmF3Tm9kZXMoIXRoaXMubm9BbmltYXRpb24/Lm56Tm9BbmltYXRpb24pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIC8vIFVwZGF0ZSBlbGVtZW50XG4gICAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICAgICAgdGhpcy5ncmFwaFJlbmRlcmVkU3ViamVjdCQubmV4dCgpO1xuICAgICAgICAgIHRoaXMubnpHcmFwaFJlbmRlcmVkLmVtaXQodGhpcyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChuZWVkUmVzaXplKSB7XG4gICAgICAgICAgdGhpcy5yZXNpemVOb2RlU2l6ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZGF0YVNvdXJjZTogTnpHcmFwaERhdGFEZWYgPSB0aGlzLmRhdGFTb3VyY2UhLmRhdGFTb3VyY2UhO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZHJhd0dyYXBoKGRhdGFTb3VyY2UsIG9wdGlvbnMsIGZhbHNlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVkcmF3IGFsbCBub2Rlc1xuICAgKiBAcGFyYW0gYW5pbWF0ZVxuICAgKi9cbiAgZHJhd05vZGVzKGFuaW1hdGU6IGJvb2xlYW4gPSB0cnVlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5uZ1pvbmUub25TdGFibGUucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICBpZiAoYW5pbWF0ZSkge1xuICAgICAgICAgIHRoaXMubWFrZU5vZGVzQW5pbWF0aW9uKCkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmxpc3RPZk5vZGVDb21wb25lbnQubWFwKG5vZGUgPT4ge1xuICAgICAgICAgICAgbm9kZS5tYWtlTm9BbmltYXRpb24oKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNpemVOb2RlU2l6ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICB0aGlzLm5nWm9uZS5vblN0YWJsZS5waXBlKHRha2UoMSkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGRhdGFTb3VyY2U6IE56R3JhcGhEYXRhRGVmID0gdGhpcy5kYXRhU291cmNlIS5kYXRhU291cmNlITtcbiAgICAgICAgbGV0IHNjYWxlID0gdGhpcy5nZXRTY2FsZSgpO1xuXG4gICAgICAgIHRoaXMubGlzdE9mTm9kZUVsZW1lbnQuZm9yRWFjaChub2RlRWxlID0+IHtcbiAgICAgICAgICBjb25zdCBjb250ZW50RWxlID0gbm9kZUVsZS5uYXRpdmVFbGVtZW50O1xuICAgICAgICAgIGlmIChjb250ZW50RWxlKSB7XG4gICAgICAgICAgICBsZXQgd2lkdGg6IG51bWJlcjtcbiAgICAgICAgICAgIGxldCBoZWlnaHQ6IG51bWJlcjtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGZvcmVpZ25PYmplY3QgaXMgc2V0XG4gICAgICAgICAgICBjb25zdCBjbGllbnRSZWN0ID0gY29udGVudEVsZS5xdWVyeVNlbGVjdG9yKCdmb3JlaWduT2JqZWN0ID4gOmZpcnN0LWNoaWxkJyk/LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgaWYgKGNsaWVudFJlY3QpIHtcbiAgICAgICAgICAgICAgd2lkdGggPSBjbGllbnRSZWN0LndpZHRoO1xuICAgICAgICAgICAgICBoZWlnaHQgPSBjbGllbnRSZWN0LmhlaWdodDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNvbnN0IGJCb3hSZWN0ID0gY29udGVudEVsZS5nZXRCQm94KCk7XG4gICAgICAgICAgICAgIHdpZHRoID0gYkJveFJlY3Qud2lkdGg7XG4gICAgICAgICAgICAgIGhlaWdodCA9IGJCb3hSZWN0LmhlaWdodDtcbiAgICAgICAgICAgICAgLy8gZ2V0QkJveCB3aWxsIHJldHVybiBhY3R1YWwgdmFsdWVcbiAgICAgICAgICAgICAgc2NhbGUgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRWxlbWVudCBpZCB0eXBlIGlzIHN0cmluZ1xuICAgICAgICAgICAgY29uc3Qgbm9kZSA9IGRhdGFTb3VyY2Uubm9kZXMuZmluZChuID0+IGAke24uaWR9YCA9PT0gbm9kZUVsZS5uYXRpdmVFbGVtZW50LmlkKTtcblxuICAgICAgICAgICAgaWYgKG5vZGUgJiYgd2lkdGggJiYgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgIG5vZGUuaGVpZ2h0ID0gaGVpZ2h0IC8gc2NhbGU7XG4gICAgICAgICAgICAgIG5vZGUud2lkdGggPSB3aWR0aCAvIHNjYWxlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN3aXRjaCB0byB0aGUgcHJvdmlkZWQgZGF0YSBzb3VyY2UgYnkgcmVzZXR0aW5nIHRoZSBkYXRhIGFuZCB1bnN1YnNjcmliaW5nIGZyb20gdGhlIGN1cnJlbnRcbiAgICogcmVuZGVyIGNoYW5nZSBzdWJzY3JpcHRpb24gaWYgb25lIGV4aXN0cy4gSWYgdGhlIGRhdGEgc291cmNlIGlzIG51bGwsIGludGVycHJldCB0aGlzIGJ5XG4gICAqIGNsZWFyaW5nIHRoZSBub2RlIG91dGxldC4gT3RoZXJ3aXNlIHN0YXJ0IGxpc3RlbmluZyBmb3IgbmV3IGRhdGEuXG4gICAqL1xuICBwcml2YXRlIF9zd2l0Y2hEYXRhU291cmNlKGRhdGFTb3VyY2U6IE56R3JhcGhEYXRhKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGF0YVNvdXJjZSAmJiB0eXBlb2YgdGhpcy5kYXRhU291cmNlLmRpc2Nvbm5lY3QgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRoaXMubnpHcmFwaERhdGEuZGlzY29ubmVjdCgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9kYXRhU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uID0gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLmRhdGFTb3VyY2UgPSBkYXRhU291cmNlO1xuICAgIHRoaXMub2JzZXJ2ZVJlbmRlckNoYW5nZXMoKTtcbiAgfVxuXG4gIC8qKiBTZXQgdXAgYSBzdWJzY3JpcHRpb24gZm9yIHRoZSBkYXRhIHByb3ZpZGVkIGJ5IHRoZSBkYXRhIHNvdXJjZS4gKi9cbiAgcHJpdmF0ZSBvYnNlcnZlUmVuZGVyQ2hhbmdlcygpOiB2b2lkIHtcbiAgICBsZXQgZGF0YVN0cmVhbTogT2JzZXJ2YWJsZTxOekdyYXBoRGF0YURlZj4gfCB1bmRlZmluZWQ7XG4gICAgbGV0IGdyYXBoT3B0aW9uczogTnpHcmFwaE9wdGlvbiA9IHtcbiAgICAgIHJhbmtEaXJlY3Rpb246IHRoaXMubnpSYW5rRGlyZWN0aW9uXG4gICAgfTtcbiAgICBpZiAoaXNEYXRhU291cmNlKHRoaXMuZGF0YVNvdXJjZSkpIHtcbiAgICAgIGRhdGFTdHJlYW0gPSB0aGlzLmRhdGFTb3VyY2UuY29ubmVjdCgpO1xuICAgIH1cblxuICAgIGlmIChkYXRhU3RyZWFtKSB7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uID0gZGF0YVN0cmVhbS5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKGRhdGEgPT4ge1xuICAgICAgICBncmFwaE9wdGlvbnMgPSB7XG4gICAgICAgICAgcmFua0RpcmVjdGlvbjogdGhpcy5uelJhbmtEaXJlY3Rpb24sXG4gICAgICAgICAgZXhwYW5kZWQ6IHRoaXMubnpHcmFwaERhdGEuZXhwYW5zaW9uTW9kZWwuc2VsZWN0ZWRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kcmF3R3JhcGgoZGF0YSwgZ3JhcGhPcHRpb25zLCB0aGlzLm56QXV0b1NpemUpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRXJyb3IoYEEgdmFsaWQgZGF0YSBzb3VyY2UgbXVzdCBiZSBwcm92aWRlZC5gKTtcbiAgICB9XG4gIH1cblxuICAvLyBUT0RPXG4gIC8vIEEgYmV0dGVyIHdheT9cbiAgcHJpdmF0ZSBnZXRTY2FsZSgpOiBudW1iZXIge1xuICAgIGNvbnN0IHRyYW5zZm9ybSA9ICh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdzdmcgPiBnJykgYXMgU1ZHR0VsZW1lbnQpPy5nZXRBdHRyaWJ1dGUoJ3RyYW5zZm9ybScpIHx8ICcnO1xuICAgIC8vIEdldCBjdXJyZW50IHNjYWxlXG4gICAgY29uc3QgcmVnZXggPSAvc2NhbGVcXCgoWzAtOVxcLl0rKVxcKS9nO1xuICAgIGNvbnN0IG1hdGNoID0gcmVnZXguZXhlYyh0cmFuc2Zvcm0pO1xuICAgIGlmIChtYXRjaCAmJiBtYXRjaFsxXSkge1xuICAgICAgcmV0dXJuIHBhcnNlRmxvYXQobWF0Y2hbMV0pO1xuICAgIH1cbiAgICByZXR1cm4gMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcmVuZGVySW5mbyBhbmQgcHJlcGFyZSBzb21lIGRhdGFcbiAgICogQHBhcmFtIGRhdGFcbiAgICogQHBhcmFtIG9wdGlvbnNcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgYnVpbGRHcmFwaEluZm8oZGF0YTogTnpHcmFwaERhdGFEZWYsIG9wdGlvbnM6IE56R3JhcGhPcHRpb24pOiBOekdyYXBoR3JvdXBOb2RlIHtcbiAgICB0aGlzLnBhcnNlSW5mbyhkYXRhKTtcbiAgICBjb25zdCByZW5kZXJJbmZvID0gYnVpbGRHcmFwaChkYXRhLCBvcHRpb25zLCB0aGlzLmxheW91dFNldHRpbmcpIGFzIE56R3JhcGhHcm91cE5vZGU7XG4gICAgY29uc3QgZGlnID0gKG5vZGVzOiBBcnJheTxOekdyYXBoTm9kZSB8IE56R3JhcGhHcm91cE5vZGU+KTogdm9pZCA9PiB7XG4gICAgICBub2Rlcy5mb3JFYWNoKG5vZGUgPT4ge1xuICAgICAgICBpZiAobm9kZS50eXBlID09PSAxICYmIHRoaXMubWFwT2ZOb2RlQXR0ci5oYXNPd25Qcm9wZXJ0eShub2RlLm5hbWUpKSB7XG4gICAgICAgICAgT2JqZWN0LmFzc2lnbihub2RlLCB0aGlzLm1hcE9mTm9kZUF0dHJbbm9kZS5uYW1lXSk7XG4gICAgICAgIH0gZWxzZSBpZiAobm9kZS50eXBlID09PSAwKSB7XG4gICAgICAgICAgKG5vZGUgYXMgTnpHcmFwaEdyb3VwTm9kZSkuZWRnZXMuZm9yRWFjaChlZGdlID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLm1hcE9mRWRnZUF0dHIuaGFzT3duUHJvcGVydHkoYCR7ZWRnZS52fS0ke2VkZ2Uud31gKSkge1xuICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKGVkZ2UsIHRoaXMubWFwT2ZFZGdlQXR0cltgJHtlZGdlLnZ9LSR7ZWRnZS53fWBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICBkaWcobm9kZS5ub2Rlcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG4gICAgZGlnKHJlbmRlckluZm8ubm9kZXMpO1xuICAgIC8vIEFzc2lnbiBkYXRhIHRvIGVkZ2VzIG9mIHJvb3QgZ3JhcGhcbiAgICByZW5kZXJJbmZvLmVkZ2VzLmZvckVhY2goZWRnZSA9PiB7XG4gICAgICBpZiAodGhpcy5tYXBPZkVkZ2VBdHRyLmhhc093blByb3BlcnR5KGAke2VkZ2Uudn0tJHtlZGdlLnd9YCkpIHtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihlZGdlLCB0aGlzLm1hcE9mRWRnZUF0dHJbYCR7ZWRnZS52fS0ke2VkZ2Uud31gXSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlbmRlckluZm87XG4gIH1cblxuICAvKipcbiAgICogUGxheSB3aXRoIGFuaW1hdGlvblxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBt