@nova-ui/bits
Version:
SolarWinds Nova Framework
326 lines • 47.7 kB
JavaScript
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { CdkHeaderCell } from "@angular/cdk/table";
import { Component, ElementRef, HostBinding, HostListener, Input, NgZone, Renderer2, } from "@angular/core";
import _isNil from "lodash/isNil";
import _isUndefined from "lodash/isUndefined";
import { fromEvent } from "rxjs";
import { filter, pluck } from "rxjs/operators";
import { TableColumnDefDirective } from "./table-column-def.directive";
import { UtilService } from "../../../services/util.service";
import { FIXED_WIDTH_CLASS } from "../constants";
import { TableResizePhase } from "../table-resizer/table-resizer.directive";
import { TableStateHandlerService, } from "../table-state-handler.service";
import * as i0 from "@angular/core";
import * as i1 from "./table-column-def.directive";
import * as i2 from "../table-state-handler.service";
import * as i3 from "../../../services/util.service";
import * as i4 from "@angular/common";
import * as i5 from "../../icon/icon.component";
import * as i6 from "../table-resizer/table-resizer.directive";
/**
* @ignore
*/
export class TableHeaderCellComponent extends CdkHeaderCell {
// binding classes
get isIconCell() {
return this.columnDef.type === "icon";
}
/**
* Conditionally applies a fixed-width marker class for letting external entities
* know whether manual updates to the cell's width are allowed.
*/
get fixedWidth() {
return this.isIconCell;
}
get shouldBeDarkOnSorting() {
return this.sortingState.isColumnSorted;
}
get shouldBeDarkOnReorder() {
return this.leftEdgeActive || this.rightEdgeActive;
}
get isSortable() {
return (this.tableStateHandlerService.sortable &&
!this.isColumnSortingDisabled);
}
get isColumnSorted() {
return this.sortingState.isColumnSorted;
}
get isReorderable() {
return this.tableStateHandlerService.reorderable;
}
get tooltip() {
return this.tooltipText;
}
mouseMovedOver() {
if (this.isColumnResizable() && !this.resizeInProgress) {
this.rightEdgeActive = this.isCursorInCell = true;
}
}
mouseMovedOut() {
// There are some of edge cases of incorrect highlighting that is covered with these booleans
this.isCursorInCell = false;
if (this.isColumnResizable() && this.resizeEventPhase !== "start") {
this.rightEdgeActive = false;
}
}
clicked() {
if (this.tableStateHandlerService.sortable &&
!this.isColumnSortingDisabled &&
this.resizeEventPhase !== TableResizePhase.start) {
const cellIndex = this.tableStateHandlerService.tableColumns.indexOf(this.columnDef.name);
this.tableStateHandlerService.sortColumn(cellIndex);
}
}
// listening for drag n drop events
dragStarted(event) {
if (this.isReorderable) {
const dragTarget = event.target;
const dragCellIndex = this.tableStateHandlerService.getTargetElementCellIndex(event);
this.tableStateHandlerService.dragCellIndex = dragCellIndex;
event.stopPropagation();
if (!event.dataTransfer) {
throw new Error("dataTransfer is null");
}
event.dataTransfer.effectAllowed = "move";
// Prevents dropping foreign elements into table header row
// Also drag n drop doesn't work in Firefox if no data is attached to event.dataTransfer
event.dataTransfer.setData("text", dragCellIndex.toString());
const windowSelection = window.getSelection();
// Prevents dragging a halo of multiple elements, if being selected on screen
if (!_isNil(windowSelection?.type) &&
windowSelection?.type === "Range") {
windowSelection.removeAllRanges();
event.dataTransfer.setDragImage(dragTarget, dragTarget.clientWidth / 2, dragTarget.clientHeight / 2);
}
}
}
dropped(event) {
const dragCellIndex = this.tableStateHandlerService.dragCellIndex;
const dataTransferData = event.dataTransfer?.getData("text");
event.stopPropagation();
event.preventDefault();
this.tableStateHandlerService.draggedOverCell.next(undefined);
if (!_isNil(dragCellIndex) &&
!_isNil(dataTransferData) &&
dragCellIndex.toString() === dataTransferData) {
this.tableStateHandlerService.reorderColumnsOnDrop();
}
}
dragEnd(event) {
event.stopPropagation();
this.tableStateHandlerService.draggedOverCell.next(undefined);
}
constructor(columnDef, elementRef, tableStateHandlerService, utilService, zone, renderer) {
super(columnDef, elementRef);
this.columnDef = columnDef;
this.elementRef = elementRef;
this.tableStateHandlerService = tableStateHandlerService;
this.utilService = utilService;
this.zone = zone;
this.renderer = renderer;
this.isColumnSortingDisabled = false;
this.subscriptions = [];
this.resizable = false;
this.tableStateHandlerService.columnType = {
columnName: this.columnDef.name,
columnType: this.columnDef.type || "default",
};
}
ngOnInit() {
const alignment = this.alignment
? `align-${this.alignment}`
: this.tableStateHandlerService.getAlignment(this.columnDef.name);
this.resizable = this.tableStateHandlerService.resizable;
this.elementRef.nativeElement.classList.add(alignment);
this.currentCellIndex =
this.tableStateHandlerService.tableColumns.indexOf(this.columnDef.name);
this.sortingState = this.tableStateHandlerService.getSortingState(this.currentCellIndex);
if (this.resizable) {
// Get initial width
const columnWidth = this.tableStateHandlerService.getColumnWidth(this.columnDef.name);
this.elementRef.nativeElement.style.width = columnWidth + "px";
this.subscriptions.push(this.tableStateHandlerService.shouldHighlightEdge
.pipe(filter((value) => {
// When resize is in progress on other columns this one shouldn't be highlighted
this.resizeInProgress =
value.columnIndex !== this.currentCellIndex &&
value.eventPhase === "start";
return value.columnIndex === this.currentCellIndex;
}), pluck("eventPhase"))
.subscribe((eventPhase) => {
this.resizeEventPhase = eventPhase;
this.rightEdgeActive = this.isCursorInCell;
}));
}
this.subscriptions.push(this.tableStateHandlerService.columnWidthSubject.subscribe(() => {
const columnWidth = this.tableStateHandlerService.getColumnWidth(this.columnDef.name);
if (columnWidth > 45) {
this.renderer.setStyle(this.elementRef.nativeElement, "width", columnWidth + "px");
}
}));
if (this.isSortable) {
this.subscriptions.push(this.tableStateHandlerService.sortingState.subscribe(() => {
this.sortingState =
this.tableStateHandlerService.getSortingState(this.currentCellIndex);
}));
}
if (this.isReorderable) {
this.subscriptions.push(this.tableStateHandlerService.draggedOverCell.subscribe((draggedOverCell) => {
this.rightEdgeActive = this.leftEdgeActive = false;
if (draggedOverCell?.cellIndex === this.currentCellIndex) {
this.rightEdgeActive =
draggedOverCell?.dropAlignment === "right";
this.leftEdgeActive =
draggedOverCell?.dropAlignment === "left";
}
}));
}
}
ngOnChanges(changes) {
if (changes.alignment && !changes.alignment.firstChange) {
const newAlignment = `align-${changes.alignment.currentValue}`;
const oldAlignment = `align-${changes.alignment.previousValue}`;
this.elementRef.nativeElement.classList.remove(oldAlignment);
this.elementRef.nativeElement.classList.add(newAlignment);
}
}
ngAfterViewInit() {
this.zone.runOutsideAngular(() => {
this.subscriptions.push(fromEvent(this.elementRef.nativeElement, "dragover").subscribe((event) => {
event.stopPropagation();
event.preventDefault();
this.tableStateHandlerService.setDraggedOverCell(event);
}));
});
}
isColumnResizable() {
const isColumnTypeResizable = _isUndefined(this.columnDef.type);
return this.tableStateHandlerService.resizable && isColumnTypeResizable;
}
onColumnWidthChange(offset) {
const currentWidth = this.tableStateHandlerService.getColumnWidth(this.columnDef.name);
const resultWidth = currentWidth + offset;
// resultWidth must be more than 45 because minimum width of the column is 46px
if (resultWidth > 45 || offset > 0) {
this.tableStateHandlerService.setColumnWidth(this.columnDef.name, resultWidth);
}
}
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableHeaderCellComponent, deps: [{ token: i1.TableColumnDefDirective }, { token: i0.ElementRef }, { token: i2.TableStateHandlerService }, { token: i3.UtilService }, { token: i0.NgZone }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TableHeaderCellComponent, selector: "nui-header-cell, th[nui-header-cell]", inputs: { alignment: "alignment", tooltipText: "tooltipText", isColumnSortingDisabled: "isColumnSortingDisabled" }, host: { attributes: { "role": "columnheader" }, listeners: { "mouseover": "mouseMovedOver()", "mouseleave": "mouseMovedOut()", "click": "clicked()", "dragstart": "dragStarted($event)", "drop": "dropped($event)", "dragend": "dragEnd($event)" }, properties: { "class.nui-table__icon-cell": "this.isIconCell", "class.nui-fixed-width": "this.fixedWidth", "class.nui-table__table-header-cell--sortable--dark": "this.shouldBeDarkOnSorting", "class.nui-table__table-header-cell--reorderable--dark": "this.shouldBeDarkOnReorder", "class.nui-table__table-header-cell--sortable": "this.isSortable", "class.nui-table__table-header-cell--sortable--text-black": "this.isColumnSorted", "attr.draggable": "this.isReorderable", "class.nui-table__table-header-cell--reorderable": "this.isReorderable", "attr.title": "this.tooltip", "class.nui-table__table-cell--left-edge-action": "this.leftEdgeActive", "class.nui-table__table-cell--right-edge-action": "this.rightEdgeActive" }, classAttribute: "nui-table__table-header-cell" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: ` <ng-content></ng-content>
<nui-icon
*ngIf="sortingState.isColumnSorted"
class="nui-table__sorting-icon"
[icon]="sortingState.sortingIcon"
iconColor="gray"
></nui-icon>
<span
*ngIf="isColumnResizable()"
(click)="$event.stopPropagation()"
nuiTableResizer
[columnIndex]="currentCellIndex"
(resizerMovement)="onColumnWidthChange($event)"
></span>`, isInline: true, dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i5.IconComponent, selector: "nui-icon", inputs: ["iconColor", "brushType", "iconHoverColor", "iconSize", "cssClass", "fillContainer", "status", "childStatus", "icon", "counter"] }, { kind: "directive", type: i6.TableResizerDirective, selector: "[nuiTableResizer]", inputs: ["columnIndex"], outputs: ["resizerMovement"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableHeaderCellComponent, decorators: [{
type: Component,
args: [{
selector: "nui-header-cell, th[nui-header-cell]",
host: {
role: "columnheader",
class: "nui-table__table-header-cell",
},
template: ` <ng-content></ng-content>
<nui-icon
*ngIf="sortingState.isColumnSorted"
class="nui-table__sorting-icon"
[icon]="sortingState.sortingIcon"
iconColor="gray"
></nui-icon>
<span
*ngIf="isColumnResizable()"
(click)="$event.stopPropagation()"
nuiTableResizer
[columnIndex]="currentCellIndex"
(resizerMovement)="onColumnWidthChange($event)"
></span>`,
}]
}], ctorParameters: () => [{ type: i1.TableColumnDefDirective }, { type: i0.ElementRef }, { type: i2.TableStateHandlerService }, { type: i3.UtilService }, { type: i0.NgZone }, { type: i0.Renderer2 }], propDecorators: { alignment: [{
type: Input
}], tooltipText: [{
type: Input
}], isColumnSortingDisabled: [{
type: Input
}], isIconCell: [{
type: HostBinding,
args: ["class.nui-table__icon-cell"]
}], fixedWidth: [{
type: HostBinding,
args: [`class.${FIXED_WIDTH_CLASS}`]
}], shouldBeDarkOnSorting: [{
type: HostBinding,
args: ["class.nui-table__table-header-cell--sortable--dark"]
}], shouldBeDarkOnReorder: [{
type: HostBinding,
args: ["class.nui-table__table-header-cell--reorderable--dark"]
}], isSortable: [{
type: HostBinding,
args: ["class.nui-table__table-header-cell--sortable"]
}], isColumnSorted: [{
type: HostBinding,
args: ["class.nui-table__table-header-cell--sortable--text-black"]
}], isReorderable: [{
type: HostBinding,
args: ["attr.draggable"]
}, {
type: HostBinding,
args: ["class.nui-table__table-header-cell--reorderable"]
}], tooltip: [{
type: HostBinding,
args: ["attr.title"]
}], leftEdgeActive: [{
type: HostBinding,
args: ["class.nui-table__table-cell--left-edge-action"]
}], rightEdgeActive: [{
type: HostBinding,
args: ["class.nui-table__table-cell--right-edge-action"]
}], mouseMovedOver: [{
type: HostListener,
args: ["mouseover"]
}], mouseMovedOut: [{
type: HostListener,
args: ["mouseleave"]
}], clicked: [{
type: HostListener,
args: ["click"]
}], dragStarted: [{
type: HostListener,
args: ["dragstart", ["$event"]]
}], dropped: [{
type: HostListener,
args: ["drop", ["$event"]]
}], dragEnd: [{
type: HostListener,
args: ["dragend", ["$event"]]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtaGVhZGVyLWNlbGwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90YWJsZS90YWJsZS1jZWxsL3RhYmxlLWhlYWRlci1jZWxsLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ25ELE9BQU8sRUFFSCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFdBQVcsRUFDWCxZQUFZLEVBQ1osS0FBSyxFQUNMLE1BQU0sRUFJTixTQUFTLEdBRVosTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxNQUFNLE1BQU0sY0FBYyxDQUFDO0FBQ2xDLE9BQU8sWUFBWSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxTQUFTLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQy9DLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFL0MsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFFdkUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzdELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNqRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUM1RSxP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LFdBQVc7dUJBQUMsZ0JBQWdCOztzQkFDNUIsV0FBVzt1QkFBQyxpREFBaUQ7Z0JBTTFELE9BQU87c0JBRFYsV0FBVzt1QkFBQyxZQUFZO2dCQU16QixjQUFjO3NCQURiLFdBQVc7dUJBQUMsK0NBQStDO2dCQUc1RCxlQUFlO3NCQURkLFdBQVc7dUJBQUMsZ0RBQWdEO2dCQUk3RCxjQUFjO3NCQURiLFlBQVk7dUJBQUMsV0FBVztnQkFRekIsYUFBYTtzQkFEWixZQUFZO3VCQUFDLFlBQVk7Z0JBVTFCLE9BQU87c0JBRE4sWUFBWTt1QkFBQyxPQUFPO2dCQWlCckIsV0FBVztzQkFEVixZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFxQ3JDLE9BQU87c0JBRE4sWUFBWTt1QkFBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBbUJoQyxPQUFPO3NCQUROLFlBQVk7dUJBQUMsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7IENka0hlYWRlckNlbGwgfSBmcm9tIFwiQGFuZ3VsYXIvY2RrL3RhYmxlXCI7XG5pbXBvcnQge1xuICAgIEFmdGVyVmlld0luaXQsXG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgSG9zdEJpbmRpbmcsXG4gICAgSG9zdExpc3RlbmVyLFxuICAgIElucHV0LFxuICAgIE5nWm9uZSxcbiAgICBPbkNoYW5nZXMsXG4gICAgT25EZXN0cm95LFxuICAgIE9uSW5pdCxcbiAgICBSZW5kZXJlcjIsXG4gICAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCBfaXNOaWwgZnJvbSBcImxvZGFzaC9pc05pbFwiO1xuaW1wb3J0IF9pc1VuZGVmaW5lZCBmcm9tIFwibG9kYXNoL2lzVW5kZWZpbmVkXCI7XG5pbXBvcnQgeyBmcm9tRXZlbnQsIFN1YnNjcmlwdGlvbiB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyBmaWx0ZXIsIHBsdWNrIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCI7XG5cbmltcG9ydCB7IFRhYmxlQ29sdW1uRGVmRGlyZWN0aXZlIH0gZnJvbSBcIi4vdGFibGUtY29sdW1uLWRlZi5kaXJlY3RpdmVcIjtcbmltcG9ydCB7IElEcmFnRXZlbnQgfSBmcm9tIFwiLi4vLi4vLi4vY29tbW9uL2RpcmVjdGl2ZXMvcHVibGljLWFwaVwiO1xuaW1wb3J0IHsgVXRpbFNlcnZpY2UgfSBmcm9tIFwiLi4vLi4vLi4vc2VydmljZXMvdXRpbC5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBGSVhFRF9XSURUSF9DTEFTUyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IFRhYmxlUmVzaXplUGhhc2UgfSBmcm9tIFwiLi4vdGFibGUtcmVzaXplci90YWJsZS1yZXNpemVyLmRpcmVjdGl2ZVwiO1xuaW1wb3J0IHtcbiAgICBDb2x1bW5UeXBlLFxuICAgIElUYWJsZVNvcnRpbmdTdGF0ZSxcbiAgICBUYWJsZVN0YXRlSGFuZGxlclNlcnZpY2UsXG59IGZyb20gXCIuLi90YWJsZS1zdGF0ZS1oYW5kbGVyLnNlcnZpY2VcIjtcbmltcG9ydCB7IE5vblJlc2l6YWJsZUNvbHVtblR5cGVzLCBUYWJsZUFsaWdubWVudE9wdGlvbnMgfSBmcm9tIFwiLi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6IFwibnVpLWhlYWRlci1jZWxsLCB0aFtudWktaGVhZGVyLWNlbGxdXCIsXG4gICAgaG9zdDoge1xuICAgICAgICByb2xlOiBcImNvbHVtbmhlYWRlclwiLFxuICAgICAgICBjbGFzczogXCJudWktdGFibGVfX3RhYmxlLWhlYWRlci1jZWxsXCIsXG4gICAgfSxcbiAgICB0ZW1wbGF0ZTogYCA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgICAgIDxudWktaWNvblxuICAgICAgICAgICAgKm5nSWY9XCJzb3J0aW5nU3RhdGUuaXNDb2x1bW5Tb3J0ZWRcIlxuICAgICAgICAgICAgY2xhc3M9XCJudWktdGFibGVfX3NvcnRpbmctaWNvblwiXG4gICAgICAgICAgICBbaWNvbl09XCJzb3J0aW5nU3RhdGUuc29ydGluZ0ljb25cIlxuICAgICAgICAgICAgaWNvbkNvbG9yPVwiZ3JheVwiXG4gICAgICAgID48L251aS1pY29uPlxuICAgICAgICA8c3BhblxuICAgICAgICAgICAgKm5nSWY9XCJpc0NvbHVtblJlc2l6YWJsZSgpXCJcbiAgICAgICAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgICAgICAgbnVpVGFibGVSZXNpemVyXG4gICAgICAgICAgICBbY29sdW1uSW5kZXhdPVwiY3VycmVudENlbGxJbmRleFwiXG4gICAgICAgICAgICAocmVzaXplck1vdmVtZW50KT1cIm9uQ29sdW1uV2lkdGhDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgID48L3NwYW4+YCxcbn0pXG5leHBvcnQgY2xhc3MgVGFibGVIZWFkZXJDZWxsQ29tcG9uZW50XG4gICAgZXh0ZW5kcyBDZGtIZWFkZXJDZWxsXG4gICAgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95XG57XG4gICAgQElucHV0KCkgYWxpZ25tZW50OiBUYWJsZUFsaWdubWVudE9wdGlvbnM7XG4gICAgQElucHV0KCkgdG9vbHRpcFRleHQ6IHN0cmluZztcbiAgICBASW5wdXQoKSBpc0NvbHVtblNvcnRpbmdEaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHB1YmxpYyBjdXJyZW50Q2VsbEluZGV4OiBudW1iZXI7XG4gICAgcHJpdmF0ZSByZXNpemVJblByb2dyZXNzOiBib29sZWFuO1xuICAgIC8vIEhlbHBzIHRvIHNob3cvaGlkZSBlZGdlIGhpZ2hsaWdodCB3aGVuIGN1cnNvciBpcyBvdXRzaWRlIG9mIHRoZSByZXNpemFibGUgaGVhZGVyIGNlbGxcbiAgICBwcml2YXRlIGlzQ3Vyc29ySW5DZWxsOiBib29sZWFuO1xuICAgIHByaXZhdGUgcmVzaXplRXZlbnRQaGFzZTogVGFibGVSZXNpemVQaGFzZTtcbiAgICBwcml2YXRlIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XG4gICAgcHVibGljIHJlc2l6YWJsZSA9IGZhbHNlO1xuICAgIHB1YmxpYyBzb3J0aW5nU3RhdGU6IElUYWJsZVNvcnRpbmdTdGF0ZTtcblxuICAgIC8vIGJpbmRpbmcgY2xhc3Nlc1xuICAgIEBIb3N0QmluZGluZyhcImNsYXNzLm51aS10YWJsZV9faWNvbi1jZWxsXCIpXG4gICAgZ2V0IGlzSWNvbkNlbGwoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbHVtbkRlZi50eXBlID09PSBcImljb25cIjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb25kaXRpb25hbGx5IGFwcGxpZXMgYSBmaXhlZC13aWR0aCBtYXJrZXIgY2xhc3MgZm9yIGxldHRpbmcgZXh0ZXJuYWwgZW50aXRpZXNcbiAgICAgKiBrbm93IHdoZXRoZXIgbWFudWFsIHVwZGF0ZXMgdG8gdGhlIGNlbGwncyB3aWR0aCBhcmUgYWxsb3dlZC5cbiAgICAgKi9cbiAgICBASG9zdEJpbmRpbmcoYGNsYXNzLiR7RklYRURfV0lEVEhfQ0xBU1N9YClcbiAgICBnZXQgZml4ZWRXaWR0aCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNJY29uQ2VsbDtcbiAgICB9XG5cbiAgICBASG9zdEJpbmRpbmcoXCJjbGFzcy5udWktdGFibGVfX3RhYmxlLWhlYWRlci1jZWxsLS1zb3J0YWJsZS0tZGFya1wiKVxuICAgIGdldCBzaG91bGRCZURhcmtPblNvcnRpbmcoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnNvcnRpbmdTdGF0ZS5pc0NvbHVtblNvcnRlZDtcbiAgICB9XG5cbiAgICBASG9zdEJpbmRpbmcoXCJjbGFzcy5udWktdGFibGVfX3RhYmxlLWhlYWRlci1jZWxsLS1yZW9yZGVyYWJsZS0tZGFya1wiKVxuICAgIGdldCBzaG91bGRCZURhcmtPblJlb3JkZXIoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmxlZnRFZGdlQWN0aXZlIHx8IHRoaXMucmlnaHRFZGdlQWN0aXZlO1xuICAgIH1cblxuICAgIEBIb3N0QmluZGluZyhcImNsYXNzLm51aS10YWJsZV9fdGFibGUtaGVhZGVyLWNlbGwtLXNvcnRhYmxlXCIpXG4gICAgZ2V0IGlzU29ydGFibGUoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLnRhYmxlU3RhdGVIYW5kbGVyU2VydmljZS5zb3J0YWJsZSAmJlxuICAgICAgICAgICAgIXRoaXMuaXNDb2x1bW5Tb3J0aW5nRGlzYWJsZWRcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBASG9zdEJpbmRpbmcoXCJjbGFzcy5udWktdGFibGVfX3RhYmxlLWhlYWRlci1jZWxsLS1zb3J0YWJsZS0tdGV4dC1ibGFja1wiKVxuICAgIGdldCBpc0NvbHVtblNvcnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc29ydGluZ1N0YXRlLmlzQ29sdW1uU29ydGVkO1xuICAgIH1cblxuICAgIEBIb3N0QmluZGluZyhcImF0dHIuZHJhZ2dhYmxlXCIpXG4gICAgQEhvc3RCaW5kaW5nKFwiY2xhc3MubnVpLXRhYmxlX190YWJsZS1oZWFkZXItY2VsbC0tcmVvcmRlcmFibGVcIilcbiAgICBnZXQgaXNSZW9yZGVyYWJsZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGFibGVTdGF0ZUhhbmRsZXJTZXJ2aWNlLnJlb3JkZXJhYmxlO1xuICAgIH1cblxuICAgIEBIb3N0QmluZGluZyhcImF0dHIudGl0bGVcIilcbiAgICBnZXQgdG9vbHRpcCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy50b29sdGlwVGV4dDtcbiAgICB9XG5cbiAgICBASG9zdEJpbmRpbmcoXCJjbGFzcy5udWktdGFibGVfX3RhYmxlLWNlbGwtLWxlZnQtZWRnZS1hY3Rpb25cIilcbiAgICBsZWZ0RWRnZUFjdGl2ZTogYm9vbGVhbjtcbiAgICBASG9zdEJpbmRpbmcoXCJjbGFzcy5udWktdGFibGVfX3RhYmxlLWNlbGwtLXJpZ2h0LWVkZ2UtYWN0aW9uXCIpXG4gICAgcmlnaHRFZGdlQWN0aXZlOiBib29sZWFuO1xuXG4gICAgQEhvc3RMaXN0ZW5lcihcIm1vdXNlb3ZlclwiKVxuICAgIG1vdXNlTW92ZWRPdmVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5pc0NvbHVtblJlc2l6YWJsZSgpICYmICF0aGlzLnJlc2l6ZUluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgIHRoaXMucmlnaHRFZGdlQWN0aXZlID0gdGhpcy5pc0N1cnNvckluQ2VsbCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBASG9zdExpc3RlbmVyKFwibW91c2VsZWF2ZVwiKVxuICAgIG1vdXNlTW92ZWRPdXQoKTogdm9pZCB7XG4gICAgICAgIC8vIFRoZXJlIGFyZSBzb21lIG9mIGVkZ2UgY2FzZXMgb2YgaW5jb3JyZWN0IGhpZ2hsaWdodGluZyB0aGF0IGlzIGNvdmVyZWQgd2l0aCB0aGVzZSBib29sZWFuc1xuICAgICAgICB0aGlzLmlzQ3Vyc29ySW5DZWxsID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLmlzQ29sdW1uUmVzaXphYmxlKCkgJiYgdGhpcy5yZXNpemVFdmVudFBoYXNlICE9PSBcInN0YXJ0XCIpIHtcbiAgICAgICAgICAgIHRoaXMucmlnaHRFZGdlQWN0aXZlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBASG9zdExpc3RlbmVyKFwiY2xpY2tcIilcbiAgICBjbGlja2VkKCk6IHZvaWQge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLnRhYmxlU3RhdGVIYW5kbGVyU2VydmljZS5zb3J0YWJsZSAmJlxuICAgICAgICAgICAgIXRoaXMuaXNDb2x1bW5Tb3J0aW5nRGlzYWJsZWQgJiZcbiAgICAgICAgICAgIHRoaXMucmVzaXplRXZlbnRQaGFzZSAhPT0gVGFibGVSZXNpemVQaGFzZS5zdGFydFxuICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IGNlbGxJbmRleCA9XG4gICAgICAgICAgICAgICAgdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2UudGFibGVDb2x1bW5zLmluZGV4T2YoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uRGVmLm5hbWVcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2Uuc29ydENvbHVtbihjZWxsSW5kZXgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gbGlzdGVuaW5nIGZvciBkcmFnIG4gZHJvcCBldmVudHNcbiAgICBASG9zdExpc3RlbmVyKFwiZHJhZ3N0YXJ0XCIsIFtcIiRldmVudFwiXSlcbiAgICBkcmFnU3RhcnRlZChldmVudDogSURyYWdFdmVudCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5pc1Jlb3JkZXJhYmxlKSB7XG4gICAgICAgICAgICBjb25zdCBkcmFnVGFyZ2V0ID0gPEVsZW1lbnQ+ZXZlbnQudGFyZ2V0O1xuICAgICAgICAgICAgY29uc3QgZHJhZ0NlbGxJbmRleCA9XG4gICAgICAgICAgICAgICAgdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2UuZ2V0VGFyZ2V0RWxlbWVudENlbGxJbmRleChldmVudCk7XG5cbiAgICAgICAgICAgIHRoaXMudGFibGVTdGF0ZUhhbmRsZXJTZXJ2aWNlLmRyYWdDZWxsSW5kZXggPSBkcmFnQ2VsbEluZGV4O1xuICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgICAgICAgIGlmICghZXZlbnQuZGF0YVRyYW5zZmVyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZGF0YVRyYW5zZmVyIGlzIG51bGxcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5lZmZlY3RBbGxvd2VkID0gXCJtb3ZlXCI7XG5cbiAgICAgICAgICAgIC8vIFByZXZlbnRzIGRyb3BwaW5nIGZvcmVpZ24gZWxlbWVudHMgaW50byB0YWJsZSBoZWFkZXIgcm93XG4gICAgICAgICAgICAvLyBBbHNvIGRyYWcgbiBkcm9wIGRvZXNuJ3Qgd29yayBpbiBGaXJlZm94IGlmIG5vIGRhdGEgaXMgYXR0YWNoZWQgdG8gZXZlbnQuZGF0YVRyYW5zZmVyXG4gICAgICAgICAgICBldmVudC5kYXRhVHJhbnNmZXIuc2V0RGF0YShcInRleHRcIiwgZHJhZ0NlbGxJbmRleC50b1N0cmluZygpKTtcblxuICAgICAgICAgICAgY29uc3Qgd2luZG93U2VsZWN0aW9uOiBTZWxlY3Rpb24gfCBudWxsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgLy8gUHJldmVudHMgZHJhZ2dpbmcgYSBoYWxvIG9mIG11bHRpcGxlIGVsZW1lbnRzLCBpZiBiZWluZyBzZWxlY3RlZCBvbiBzY3JlZW5cbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAhX2lzTmlsKHdpbmRvd1NlbGVjdGlvbj8udHlwZSkgJiZcbiAgICAgICAgICAgICAgICB3aW5kb3dTZWxlY3Rpb24/LnR5cGUgPT09IFwiUmFuZ2VcIlxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgd2luZG93U2VsZWN0aW9uLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgICAgICAgICAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5zZXREcmFnSW1hZ2UoXG4gICAgICAgICAgICAgICAgICAgIGRyYWdUYXJnZXQsXG4gICAgICAgICAgICAgICAgICAgIGRyYWdUYXJnZXQuY2xpZW50V2lkdGggLyAyLFxuICAgICAgICAgICAgICAgICAgICBkcmFnVGFyZ2V0LmNsaWVudEhlaWdodCAvIDJcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgQEhvc3RMaXN0ZW5lcihcImRyb3BcIiwgW1wiJGV2ZW50XCJdKVxuICAgIGRyb3BwZWQoZXZlbnQ6IElEcmFnRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZHJhZ0NlbGxJbmRleCA9IHRoaXMudGFibGVTdGF0ZUhhbmRsZXJTZXJ2aWNlLmRyYWdDZWxsSW5kZXg7XG4gICAgICAgIGNvbnN0IGRhdGFUcmFuc2ZlckRhdGEgPSBldmVudC5kYXRhVHJhbnNmZXI/LmdldERhdGEoXCJ0ZXh0XCIpO1xuXG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLnRhYmxlU3RhdGVIYW5kbGVyU2VydmljZS5kcmFnZ2VkT3ZlckNlbGwubmV4dCh1bmRlZmluZWQpO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgICFfaXNOaWwoZHJhZ0NlbGxJbmRleCkgJiZcbiAgICAgICAgICAgICFfaXNOaWwoZGF0YVRyYW5zZmVyRGF0YSkgJiZcbiAgICAgICAgICAgIGRyYWdDZWxsSW5kZXgudG9TdHJpbmcoKSA9PT0gZGF0YVRyYW5zZmVyRGF0YVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMudGFibGVTdGF0ZUhhbmRsZXJTZXJ2aWNlLnJlb3JkZXJDb2x1bW5zT25Ecm9wKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBASG9zdExpc3RlbmVyKFwiZHJhZ2VuZFwiLCBbXCIkZXZlbnRcIl0pXG4gICAgZHJhZ0VuZChldmVudDogSURyYWdFdmVudCk6IHZvaWQge1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2UuZHJhZ2dlZE92ZXJDZWxsLm5leHQodW5kZWZpbmVkKTtcbiAgICB9XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSBjb2x1bW5EZWY6IFRhYmxlQ29sdW1uRGVmRGlyZWN0aXZlLFxuICAgICAgICBwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgICAgIHByaXZhdGUgdGFibGVTdGF0ZUhhbmRsZXJTZXJ2aWNlOiBUYWJsZVN0YXRlSGFuZGxlclNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgdXRpbFNlcnZpY2U6IFV0aWxTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHpvbmU6IE5nWm9uZSxcbiAgICAgICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyXG4gICAgKSB7XG4gICAgICAgIHN1cGVyKGNvbHVtbkRlZiwgZWxlbWVudFJlZik7XG5cbiAgICAgICAgdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2UuY29sdW1uVHlwZSA9IDxDb2x1bW5UeXBlPntcbiAgICAgICAgICAgIGNvbHVtbk5hbWU6IHRoaXMuY29sdW1uRGVmLm5hbWUsXG4gICAgICAgICAgICBjb2x1bW5UeXBlOiB0aGlzLmNvbHVtbkRlZi50eXBlIHx8IFwiZGVmYXVsdFwiLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgYWxpZ25tZW50ID0gdGhpcy5hbGlnbm1lbnRcbiAgICAgICAgICAgID8gYGFsaWduLSR7dGhpcy5hbGlnbm1lbnR9YFxuICAgICAgICAgICAgOiB0aGlzLnRhYmxlU3RhdGVIYW5kbGVyU2VydmljZS5nZXRBbGlnbm1lbnQodGhpcy5jb2x1bW5EZWYubmFtZSk7XG5cbiAgICAgICAgdGhpcy5yZXNpemFibGUgPSB0aGlzLnRhYmxlU3RhdGVIYW5kbGVyU2VydmljZS5yZXNpemFibGU7XG4gICAgICAgIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNsYXNzTGlzdC5hZGQoYWxpZ25tZW50KTtcbiAgICAgICAgdGhpcy5jdXJyZW50Q2VsbEluZGV4ID1cbiAgICAgICAgICAgIHRoaXMudGFibGVTdGF0ZUhhbmRsZXJTZXJ2aWNlLnRhYmxlQ29sdW1ucy5pbmRleE9mKFxuICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uRGVmLm5hbWVcbiAgICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuc29ydGluZ1N0YXRlID0gdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2UuZ2V0U29ydGluZ1N0YXRlKFxuICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2VsbEluZGV4XG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKHRoaXMucmVzaXphYmxlKSB7XG4gICAgICAgICAgICAvLyBHZXQgaW5pdGlhbCB3aWR0aFxuICAgICAgICAgICAgY29uc3QgY29sdW1uV2lkdGggPSB0aGlzLnRhYmxlU3RhdGVIYW5kbGVyU2VydmljZS5nZXRDb2x1bW5XaWR0aChcbiAgICAgICAgICAgICAgICB0aGlzLmNvbHVtbkRlZi5uYW1lXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5zdHlsZS53aWR0aCA9IGNvbHVtbldpZHRoICsgXCJweFwiO1xuICAgICAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICAgICAgICAgICAgdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2Uuc2hvdWxkSGlnaGxpZ2h0RWRnZVxuICAgICAgICAgICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcigodmFsdWUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHJlc2l6ZSBpcyBpbiBwcm9ncmVzcyBvbiBvdGhlciBjb2x1bW5zIHRoaXMgb25lIHNob3VsZG4ndCBiZSBoaWdobGlnaHRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzaXplSW5Qcm9ncmVzcyA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLmNvbHVtbkluZGV4ICE9PSB0aGlzLmN1cnJlbnRDZWxsSW5kZXggJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUuZXZlbnRQaGFzZSA9PT0gXCJzdGFydFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb2x1bW5JbmRleCA9PT0gdGhpcy5jdXJyZW50Q2VsbEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICBwbHVjayhcImV2ZW50UGhhc2VcIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKChldmVudFBoYXNlOiBUYWJsZVJlc2l6ZVBoYXNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZUV2ZW50UGhhc2UgPSBldmVudFBoYXNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yaWdodEVkZ2VBY3RpdmUgPSB0aGlzLmlzQ3Vyc29ySW5DZWxsO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgICAgICAgIHRoaXMudGFibGVTdGF0ZUhhbmRsZXJTZXJ2aWNlLmNvbHVtbldpZHRoU3ViamVjdC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbHVtbldpZHRoID1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2UuZ2V0Q29sdW1uV2lkdGgoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbHVtbkRlZi5uYW1lXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbldpZHRoID4gNDUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgXCJ3aWR0aFwiLCBjb2x1bW5XaWR0aCArIFwicHhcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAodGhpcy5pc1NvcnRhYmxlKSB7XG4gICAgICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgICAgICAgICAgICB0aGlzLnRhYmxlU3RhdGVIYW5kbGVyU2VydmljZS5zb3J0aW5nU3RhdGUuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zb3J0aW5nU3RhdGUgPVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2UuZ2V0U29ydGluZ1N0YXRlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudENlbGxJbmRleFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmlzUmVvcmRlcmFibGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgICAgICAgICAgIHRoaXMudGFibGVTdGF0ZUhhbmRsZXJTZXJ2aWNlLmRyYWdnZWRPdmVyQ2VsbC5zdWJzY3JpYmUoXG4gICAgICAgICAgICAgICAgICAgIChkcmFnZ2VkT3ZlckNlbGwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmlnaHRFZGdlQWN0aXZlID0gdGhpcy5sZWZ0RWRnZUFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdnZWRPdmVyQ2VsbD8uY2VsbEluZGV4ID09PSB0aGlzLmN1cnJlbnRDZWxsSW5kZXhcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmlnaHRFZGdlQWN0aXZlID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ2dlZE92ZXJDZWxsPy5kcm9wQWxpZ25tZW50ID09PSBcInJpZ2h0XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sZWZ0RWRnZUFjdGl2ZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdnZWRPdmVyQ2VsbD8uZHJvcEFsaWdubWVudCA9PT0gXCJsZWZ0XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICAgICAgaWYgKGNoYW5nZXMuYWxpZ25tZW50ICYmICFjaGFuZ2VzLmFsaWdubWVudC5maXJzdENoYW5nZSkge1xuICAgICAgICAgICAgY29uc3QgbmV3QWxpZ25tZW50ID0gYGFsaWduLSR7Y2hhbmdlcy5hbGlnbm1lbnQuY3VycmVudFZhbHVlfWA7XG4gICAgICAgICAgICBjb25zdCBvbGRBbGlnbm1lbnQgPSBgYWxpZ24tJHtjaGFuZ2VzLmFsaWdubWVudC5wcmV2aW91c1ZhbHVlfWA7XG4gICAgICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKG9sZEFsaWdubWVudCk7XG4gICAgICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QuYWRkKG5ld0FsaWdubWVudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICAgICAgICAgICAgZnJvbUV2ZW50PERyYWdFdmVudD4oXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICBcImRyYWdvdmVyXCJcbiAgICAgICAgICAgICAgICApLnN1YnNjcmliZSgoZXZlbnQ6IERyYWdFdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2Uuc2V0RHJhZ2dlZE92ZXJDZWxsKGV2ZW50KTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGlzQ29sdW1uUmVzaXphYmxlKCk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBpc0NvbHVtblR5cGVSZXNpemFibGUgPSBfaXNVbmRlZmluZWQoXG4gICAgICAgICAgICA8Tm9uUmVzaXphYmxlQ29sdW1uVHlwZXM+dGhpcy5jb2x1bW5EZWYudHlwZVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gdGhpcy50YWJsZVN0YXRlSGFuZGxlclNlcnZpY2UucmVzaXphYmxlICYmIGlzQ29sdW1uVHlwZVJlc2l6YWJsZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25Db2x1bW5XaWR0aENoYW5nZShvZmZzZXQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBjdXJyZW50V2lkdGggPSB0aGlzLnRhYmxlU3RhdGVIYW5kbGVyU2VydmljZS5nZXRDb2x1bW5XaWR0aCh0aGlzLmNvbHVtbkRlZi5uYW1lKTtcbiAgICAgICAgY29uc3QgcmVzdWx0V2lkdGggPSBjdXJyZW50V2lkdGggKyBvZmZzZXQ7XG5cbiAgICAgICAgLy8gcmVzdWx0V2lkdGggbXVzdCBiZSBtb3JlIHRoYW4gNDUgYmVjYXVzZSBtaW5pbXVtIHdpZHRoIG9mIHRoZSBjb2x1bW4gaXMgNDZweFxuICAgICAgICBpZiAocmVzdWx0V2lkdGggPiA0NSB8fCBvZmZzZXQgPiAwKSB7XG4gICAgICAgICAgICB0aGlzLnRhYmxlU3RhdGVIYW5kbGVyU2VydmljZS5zZXRDb2x1bW5XaWR0aChcbiAgICAgICAgICAgICAgICB0aGlzLmNvbHVtbkRlZi5uYW1lLFxuICAgICAgICAgICAgICAgIHJlc3VsdFdpZHRoXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZm9yRWFjaCgoc3Vic2NyaXB0aW9uKSA9PlxuICAgICAgICAgICAgc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKClcbiAgICAgICAgKTtcbiAgICB9XG59XG4iXX0=