UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

348 lines 53.3 kB
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion'; import { Component, HostBinding, inject, Input } from '@angular/core'; import { Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { DashboardService } from '../dashboard.service'; import { DashboardStackMode } from './dashboard-stack-mode.enum'; import * as i0 from "@angular/core"; import * as i1 from "../../../directives/drag/drag.directive"; import * as i2 from "@angular/common"; export class DashboardWidgetComponent { /** Defines the column the widget is placed in */ set col(col) { if (col !== null && col !== undefined) { this.setColumn(coerceNumberProperty(col)); this.dashboardService.renderDashboard(); } } get col() { return this.getColumn(); } /** Defines the row the widget is placed in */ set row(row) { if (row !== null && row !== undefined) { this.setRow(coerceNumberProperty(row)); this.dashboardService.renderDashboard(); } } get row() { return this.getRow(); } /** Defines the number of columns this widget should occupy. */ get colSpan() { return this.getColumnSpan(); } set colSpan(colSpan) { if (colSpan !== null && colSpan !== undefined) { this.setColumnSpan(coerceNumberProperty(colSpan)); } } /** Defines the number of rows this widget should occupy. */ get rowSpan() { return this.getRowSpan(); } set rowSpan(rowSpan) { if (rowSpan !== null && rowSpan !== undefined) { this.setRowSpan(coerceNumberProperty(rowSpan)); } } /** Defines the minimum number of columns this widget should occupy. */ get minColSpan() { return this._minColSpan; } set minColSpan(minColumns) { this._minColSpan = coerceNumberProperty(minColumns); } /** Defines the minimum number of rows this widget should occupy. */ get minRowSpan() { return this._minRowSpan; } set minRowSpan(minRows) { this._minRowSpan = coerceNumberProperty(minRows); } /** Defines whether or not this widget will be automatically repositioned */ set autoPositioning(autoPositioning) { this._autoPositioning = coerceBooleanProperty(autoPositioning); } get autoPositioning() { return this._autoPositioning; } constructor() { this.dashboardService = inject(DashboardService); /** Defines whether or not this widget can be resized. */ this.resizable = false; /** Defines a function that returns an aria label for the widget */ this.widgetAriaLabel = this.getDefaultAriaLabel; this.x = 0; this.y = 0; this.width = 100; this.height = 100; this.padding = 0; this.zIndex = null; this.role = 'group'; this.isDragging = false; this.isGrabbing = false; this.isResizing = false; this.isDraggable = false; this._column = { regular: undefined, stacked: undefined }; this._row = { regular: undefined, stacked: undefined }; this._columnSpan = { regular: 1, stacked: 1 }; this._rowSpan = { regular: 1, stacked: 1 }; this._minColSpan = 1; this._minRowSpan = 1; this._autoPositioning = true; this._onDestroy = new Subject(); // subscribe to option changes this.dashboardService.options$.pipe(takeUntil(this._onDestroy)) .subscribe(() => this.update()); // every time the layout changes we want to update the aria label this.dashboardService.layout$.pipe(takeUntil(this._onDestroy)) .subscribe(() => this.ariaLabel = this.getAriaLabel()); // allow widget movements to be animated this.dashboardService.isDragging$.pipe(takeUntil(this._onDestroy), map(widget => widget === this)) .subscribe(isDragging => this.isDragging = isDragging); // allow widget movements to be animated this.dashboardService.isGrabbing$.pipe(takeUntil(this._onDestroy), map(widget => widget === this)) .subscribe(isGrabbing => this.isGrabbing = isGrabbing); } ngOnInit() { this._columnSpan.regular = this.colSpan; this._rowSpan.regular = this.rowSpan; this._rowSpan.stacked = this.rowSpan; this._row.regular = this.row; this._row.stacked = this.row; this._column.regular = this.col; this._column.stacked = this.col; if (!this.id) { console.warn('Dashboard Widget is missing an ID.'); // set random id - keeps things working but prevents exporting of positions this.id = Math.floor(Math.random() * 100000).toString(); } } ngAfterViewInit() { // add the widget to the dashboard this.dashboardService.addWidget(this); // apply the current options this.update(); } ngOnChanges(changes) { if (this.hasPosition() && (changes.colSpan || changes.rowSpan)) { this.dashboardService.resizeWidget(this); this.dashboardService.renderDashboard(); } } /** * If component is removed, then unregister it from the service */ ngOnDestroy() { this._onDestroy.next(); this._onDestroy.complete(); this.dashboardService.removeWidget(this); } /** * Apply the current dashboard options */ update() { // get the current options at the time const { padding, columns } = this.dashboardService.options; this.padding = padding; this._columnSpan.stacked = columns; } /** * Set the actual position and size values */ render() { this.x = this.getColumn() * this.dashboardService.getColumnWidth(); this.y = this.getRow() * this.dashboardService.getRowHeight(); this.width = this.getColumnSpan() * this.dashboardService.getColumnWidth(); this.height = this.getRowSpan() * this.dashboardService.getRowHeight(); } getColumn(mode = DashboardStackMode.Auto) { switch (mode) { case DashboardStackMode.Auto: return this.getStackableValue(this._column); case DashboardStackMode.Regular: return this._column.regular; case DashboardStackMode.Stacked: return this._column.stacked; } } getRow(mode = DashboardStackMode.Auto) { switch (mode) { case DashboardStackMode.Auto: return this.getStackableValue(this._row); case DashboardStackMode.Regular: return this._row.regular; case DashboardStackMode.Stacked: return this._row.stacked; } } setColumn(column, render = true) { this.setStackableValue(this._column, column); if (render) { this.render(); } } setRow(row, render = true) { this.setStackableValue(this._row, row); if (render) { this.render(); } } getColumnSpan() { return this.getStackableValue(this._columnSpan); } getRowSpan() { return this.getStackableValue(this._rowSpan); } setColumnSpan(columnSpan, render = true) { if (columnSpan >= this.minColSpan) { this.setStackableValue(this._columnSpan, columnSpan); if (render) { this.render(); } } } setRowSpan(rowSpan, render = true) { if (rowSpan >= this.minRowSpan) { this.setStackableValue(this._rowSpan, rowSpan); if (render) { this.render(); } } } bringToFront() { this.zIndex = 1; } sendToBack() { this.zIndex = null; } setBounds(x, y, width, height) { this.x = x; this.y = y; this.width = width; this.height = height; } dragstart(handle, event, direction) { this.isResizing = true; this.dashboardService.isGrabbing$.next(null); this.dashboardService.onResizeStart({ widget: this, direction, event, handle }); } drag(handle, event, direction) { this.dashboardService.onResizeDrag({ widget: this, direction, event, handle }); } dragend() { this.isResizing = false; this.dashboardService.onResizeEnd(); } getAriaLabel() { if (this.widgetAriaLabel && typeof this.widgetAriaLabel === 'string') { return this.widgetAriaLabel; } else if (this.widgetAriaLabel && typeof this.widgetAriaLabel === 'function') { return this.widgetAriaLabel(this); } return this.ariaLabel; } getDefaultAriaLabel(widget) { let options = ''; if (widget.resizable && widget.isDraggable) { options = 'It can be moved and resized.'; } else if (widget.resizable) { options = 'It can be resized.'; } else if (widget.isDraggable) { options = 'It can be moved.'; } return `${widget.name} panel in row ${widget.getRow()}, column ${widget.getColumn()}, is ${widget.getColumnSpan()} columns wide and ${widget.getRowSpan()} rows high. ${options}`; } /** * Allows automatic setting of stackable value * @param property The current StackableValue object * @param value The value to set in the appropriate field */ setStackableValue(property, value) { if (this.dashboardService.stacked) { property.stacked = value; } else { property.regular = value; } } /** * Return the appropriate value from a stackable value * @param property The Stackable value object */ getStackableValue(property) { return this.dashboardService.stacked ? property.stacked : property.regular; } /** Determine if the layout has been performed yet */ hasPosition() { return this.getColumn() !== undefined && this.getRow() !== undefined; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: DashboardWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.12", type: DashboardWidgetComponent, selector: "ux-dashboard-widget", inputs: { id: "id", name: "name", col: "col", row: "row", colSpan: "colSpan", rowSpan: "rowSpan", minColSpan: "minColSpan", minRowSpan: "minRowSpan", resizable: "resizable", autoPositioning: "autoPositioning", widgetAriaLabel: "widgetAriaLabel", role: "role" }, host: { properties: { "style.left.px": "this.x", "style.top.px": "this.y", "style.width.px": "this.width", "style.height.px": "this.height", "style.padding.px": "this.padding", "style.z-index": "this.zIndex", "attr.aria-label": "this.ariaLabel", "attr.role": "this.role", "class.dragging": "this.isDragging", "class.grabbing": "this.isGrabbing", "class.resizing": "this.isResizing" } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"widget-content widget-col-span-{{ getColumnSpan() }} widget-row-span-{{ getRowSpan() }}\">\n <ng-content></ng-content>\n</div>\n\n<div uxDrag\n #handleTop\n class=\"resizer-handle handle-top\"\n (onDragStart)=\"dragstart(handleTop, $event, 0)\"\n (onDrag)=\"drag(handleTop, $event, 0)\"\n (onDragEnd)=\"dragend()\"\n [style.top.px]=\"padding\"\n [hidden]=\"!resizable\">\n</div>\n\n<div uxDrag\n #handleTopRight\n class=\"resizer-handle handle-top-right\"\n (onDragStart)=\"dragstart(handleTopRight, $event, 1)\"\n (onDrag)=\"drag(handleTopRight, $event, 1)\"\n (onDragEnd)=\"dragend()\"\n [style.top.px]=\"padding\"\n [style.right.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleRight\n class=\"resizer-handle handle-right\"\n (onDragStart)=\"dragstart(handleRight, $event, 2)\"\n (onDrag)=\"drag(handleRight, $event, 2)\"\n (onDragEnd)=\"dragend()\"\n [style.right.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleBottomRight\n class=\"resizer-handle handle-bottom-right\"\n (onDragStart)=\"dragstart(handleBottomRight, $event, 3)\"\n (onDrag)=\"drag(handleBottomRight, $event, 3)\"\n (onDragEnd)=\"dragend()\"\n [style.bottom.px]=\"padding\"\n [style.right.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleBottom\n class=\"resizer-handle handle-bottom\"\n (onDragStart)=\"dragstart(handleBottom, $event, 4)\"\n (onDrag)=\"drag(handleBottom, $event, 4)\"\n (onDragEnd)=\"dragend()\"\n [style.bottom.px]=\"padding\"\n [hidden]=\"!resizable\">\n</div>\n\n<div uxDrag\n #handleBottomLeft\n class=\"resizer-handle handle-bottom-left\"\n (onDragStart)=\"dragstart(handleBottomLeft, $event, 5)\"\n (onDrag)=\"drag(handleBottomLeft, $event, 5)\"\n (onDragEnd)=\"dragend()\"\n [style.bottom.px]=\"padding\"\n [style.left.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleLeft\n class=\"resizer-handle handle-left\"\n (onDragStart)=\"dragstart(handleLeft, $event, 6)\"\n (onDrag)=\"drag(handleLeft, $event, 6)\"\n (onDragEnd)=\"dragend()\"\n [style.left.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleTopLeft\n class=\"resizer-handle handle-top-left\"\n (onDragStart)=\"dragstart(handleTopLeft, $event, 7)\"\n (onDrag)=\"drag(handleTopLeft, $event, 7)\"\n (onDragEnd)=\"dragend()\"\n [style.top.px]=\"padding\"\n [style.left.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>", dependencies: [{ kind: "directive", type: i1.DragDirective, selector: "[uxDrag]", inputs: ["clone", "group", "model", "draggable"], outputs: ["onDragStart", "onDrag", "onDragScroll", "onDragEnd", "onDrop", "onDropEnter", "onDropLeave"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: DashboardWidgetComponent, decorators: [{ type: Component, args: [{ selector: 'ux-dashboard-widget', template: "<div class=\"widget-content widget-col-span-{{ getColumnSpan() }} widget-row-span-{{ getRowSpan() }}\">\n <ng-content></ng-content>\n</div>\n\n<div uxDrag\n #handleTop\n class=\"resizer-handle handle-top\"\n (onDragStart)=\"dragstart(handleTop, $event, 0)\"\n (onDrag)=\"drag(handleTop, $event, 0)\"\n (onDragEnd)=\"dragend()\"\n [style.top.px]=\"padding\"\n [hidden]=\"!resizable\">\n</div>\n\n<div uxDrag\n #handleTopRight\n class=\"resizer-handle handle-top-right\"\n (onDragStart)=\"dragstart(handleTopRight, $event, 1)\"\n (onDrag)=\"drag(handleTopRight, $event, 1)\"\n (onDragEnd)=\"dragend()\"\n [style.top.px]=\"padding\"\n [style.right.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleRight\n class=\"resizer-handle handle-right\"\n (onDragStart)=\"dragstart(handleRight, $event, 2)\"\n (onDrag)=\"drag(handleRight, $event, 2)\"\n (onDragEnd)=\"dragend()\"\n [style.right.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleBottomRight\n class=\"resizer-handle handle-bottom-right\"\n (onDragStart)=\"dragstart(handleBottomRight, $event, 3)\"\n (onDrag)=\"drag(handleBottomRight, $event, 3)\"\n (onDragEnd)=\"dragend()\"\n [style.bottom.px]=\"padding\"\n [style.right.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleBottom\n class=\"resizer-handle handle-bottom\"\n (onDragStart)=\"dragstart(handleBottom, $event, 4)\"\n (onDrag)=\"drag(handleBottom, $event, 4)\"\n (onDragEnd)=\"dragend()\"\n [style.bottom.px]=\"padding\"\n [hidden]=\"!resizable\">\n</div>\n\n<div uxDrag\n #handleBottomLeft\n class=\"resizer-handle handle-bottom-left\"\n (onDragStart)=\"dragstart(handleBottomLeft, $event, 5)\"\n (onDrag)=\"drag(handleBottomLeft, $event, 5)\"\n (onDragEnd)=\"dragend()\"\n [style.bottom.px]=\"padding\"\n [style.left.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleLeft\n class=\"resizer-handle handle-left\"\n (onDragStart)=\"dragstart(handleLeft, $event, 6)\"\n (onDrag)=\"drag(handleLeft, $event, 6)\"\n (onDragEnd)=\"dragend()\"\n [style.left.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>\n\n<div uxDrag\n #handleTopLeft\n class=\"resizer-handle handle-top-left\"\n (onDragStart)=\"dragstart(handleTopLeft, $event, 7)\"\n (onDrag)=\"drag(handleTopLeft, $event, 7)\"\n (onDragEnd)=\"dragend()\"\n [style.top.px]=\"padding\"\n [style.left.px]=\"padding\"\n [hidden]=\"!resizable || (dashboardService.stacked$ | async)\">\n</div>" }] }], ctorParameters: () => [], propDecorators: { id: [{ type: Input }], name: [{ type: Input }], col: [{ type: Input }], row: [{ type: Input }], colSpan: [{ type: Input }], rowSpan: [{ type: Input }], minColSpan: [{ type: Input }], minRowSpan: [{ type: Input }], resizable: [{ type: Input }], autoPositioning: [{ type: Input }], widgetAriaLabel: [{ type: Input }], x: [{ type: HostBinding, args: ['style.left.px'] }], y: [{ type: HostBinding, args: ['style.top.px'] }], width: [{ type: HostBinding, args: ['style.width.px'] }], height: [{ type: HostBinding, args: ['style.height.px'] }], padding: [{ type: HostBinding, args: ['style.padding.px'] }], zIndex: [{ type: HostBinding, args: ['style.z-index'] }], ariaLabel: [{ type: HostBinding, args: ['attr.aria-label'] }], role: [{ type: HostBinding, args: ['attr.role'] }, { type: Input }], isDragging: [{ type: HostBinding, args: ['class.dragging'] }], isGrabbing: [{ type: HostBinding, args: ['class.grabbing'] }], isResizing: [{ type: HostBinding, args: ['class.resizing'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGFzaGJvYXJkLXdpZGdldC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9kYXNoYm9hcmQvd2lkZ2V0L2Rhc2hib2FyZC13aWRnZXQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvZGFzaGJvYXJkL3dpZGdldC9kYXNoYm9hcmQtd2lkZ2V0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBZ0IscUJBQXFCLEVBQUUsb0JBQW9CLEVBQWUsTUFBTSx1QkFBdUIsQ0FBQztBQUMvRyxPQUFPLEVBQWlCLFNBQVMsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBK0MsTUFBTSxlQUFlLENBQUM7QUFDbEksT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2hELE9BQU8sRUFBbUIsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQzs7OztBQU1qRSxNQUFNLE9BQU8sd0JBQXdCO0lBVWpDLGlEQUFpRDtJQUNqRCxJQUFhLEdBQUcsQ0FBQyxHQUFXO1FBQ3hCLElBQUksR0FBRyxLQUFLLElBQUksSUFBSSxHQUFHLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDcEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUM1QyxDQUFDO0lBQ0wsQ0FBQztJQUVELElBQUksR0FBRztRQUNILE9BQU8sSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFRCw4Q0FBOEM7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VztRQUNmLE9BQU8sSUFBSSxDQUFDLFNBQVMsRUFBRSxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEtBQUssU0FBUyxDQUFDO0lBQ3pFLENBQUM7K0dBeFZRLHdCQUF3QjttR0FBeEIsd0JBQXdCLHl0QkNYckMsNDBGQXNGTTs7NEZEM0VPLHdCQUF3QjtrQkFKcEMsU0FBUzsrQkFDSSxxQkFBcUI7d0RBUXRCLEVBQUU7c0JBQVYsS0FBSztnQkFHRyxJQUFJO3NCQUFaLEtBQUs7Z0JBR08sR0FBRztzQkFBZixLQUFLO2dCQVlPLEdBQUc7c0JBQWYsS0FBSztnQkFZTyxPQUFPO3NCQUFuQixLQUFLO2dCQVdPLE9BQU87c0JBQW5CLEtBQUs7Z0JBV08sVUFBVTtzQkFBdEIsS0FBSztnQkFTTyxVQUFVO3NCQUF0QixLQUFLO2dCQVNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBR08sZUFBZTtzQkFBM0IsS0FBSztnQkFTRyxlQUFlO3NCQUF2QixLQUFLO2dCQUV3QixDQUFDO3NCQUE5QixXQUFXO3VCQUFDLGVBQWU7Z0JBQ0MsQ0FBQztzQkFBN0IsV0FBVzt1QkFBQyxjQUFjO2dCQUNJLEtBQUs7c0JBQW5DLFdBQVc7dUJBQUMsZ0JBQWdCO2dCQUNHLE1BQU07c0JBQXJDLFdBQVc7dUJBQUMsaUJBQWlCO2dCQUNHLE9BQU87c0JBQXZDLFdBQVc7dUJBQUMsa0JBQWtCO2dCQUNELE1BQU07c0JBQW5DLFdBQVc7dUJBQUMsZUFBZTtnQkFDSSxTQUFTO3NCQUF4QyxXQUFXO3VCQUFDLGlCQUFpQjtnQkFDSyxJQUFJO3NCQUF0QyxXQUFXO3VCQUFDLFdBQVc7O3NCQUFHLEtBQUs7Z0JBQ0QsVUFBVTtzQkFBeEMsV0FBVzt1QkFBQyxnQkFBZ0I7Z0JBQ0UsVUFBVTtzQkFBeEMsV0FBVzt1QkFBQyxnQkFBZ0I7Z0JBQ0UsVUFBVTtzQkFBeEMsV0FBVzt1QkFBQyxnQkFBZ0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCb29sZWFuSW5wdXQsIGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSwgY29lcmNlTnVtYmVyUHJvcGVydHksIE51bWJlcklucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvZXJjaW9uJztcbmltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgSG9zdEJpbmRpbmcsIGluamVjdCwgSW5wdXQsIE9uQ2hhbmdlcywgT25EZXN0cm95LCBPbkluaXQsIFNpbXBsZUNoYW5nZXMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQWN0aW9uRGlyZWN0aW9uLCBEYXNoYm9hcmRTZXJ2aWNlIH0gZnJvbSAnLi4vZGFzaGJvYXJkLnNlcnZpY2UnO1xuaW1wb3J0IHsgRGFzaGJvYXJkU3RhY2tNb2RlIH0gZnJvbSAnLi9kYXNoYm9hcmQtc3RhY2stbW9kZS5lbnVtJztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICd1eC1kYXNoYm9hcmQtd2lkZ2V0JyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vZGFzaGJvYXJkLXdpZGdldC5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgRGFzaGJvYXJkV2lkZ2V0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcyB7XG5cbiAgICByZWFkb25seSBkYXNoYm9hcmRTZXJ2aWNlID0gaW5qZWN0KERhc2hib2FyZFNlcnZpY2UpO1xuXG4gICAgLyoqIFNldHMgdGhlIElEIG9mIHRoZSB3aWRnZXQuIEVhY2ggd2lkZ2V0IHNob3VsZCBiZSBnaXZlbiBhIHVuaXF1ZSBJRC4gKi9cbiAgICBASW5wdXQoKSBpZDogc3RyaW5nO1xuXG4gICAgLyoqIERlZmluZXMgYSBuYW1lIGZvciB0aGUgd2lkZ2V0IHVzZWQgZm9yIGFjY2Vzc2liaWxpdHkgKi9cbiAgICBASW5wdXQoKSBuYW1lOiBzdHJpbmc7XG5cbiAgICAvKiogRGVmaW5lcyB0aGUgY29sdW1uIHRoZSB3aWRnZXQgaXMgcGxhY2VkIGluICovXG4gICAgQElucHV0KCkgc2V0IGNvbChjb2w6IG51bWJlcikge1xuICAgICAgICBpZiAoY29sICE9PSBudWxsICYmIGNvbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLnNldENvbHVtbihjb2VyY2VOdW1iZXJQcm9wZXJ0eShjb2wpKTtcbiAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS5yZW5kZXJEYXNoYm9hcmQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldCBjb2woKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29sdW1uKCk7XG4gICAgfVxuXG4gICAgLyoqIERlZmluZXMgdGhlIHJvdyB0aGUgd2lkZ2V0IGlzIHBsYWNlZCBpbiAqL1xuICAgIEBJbnB1dCgpIHNldCByb3cocm93OiBudW1iZXIpIHtcbiAgICAgICAgaWYgKHJvdyAhPT0gbnVsbCAmJiByb3cgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5zZXRSb3coY29lcmNlTnVtYmVyUHJvcGVydHkocm93KSk7XG4gICAgICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2UucmVuZGVyRGFzaGJvYXJkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXQgcm93KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFJvdygpO1xuICAgIH1cblxuICAgIC8qKiBEZWZpbmVzIHRoZSBudW1iZXIgb2YgY29sdW1ucyB0aGlzIHdpZGdldCBzaG91bGQgb2NjdXB5LiAqL1xuICAgIEBJbnB1dCgpIGdldCBjb2xTcGFuKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2x1bW5TcGFuKCk7XG4gICAgfVxuXG4gICAgc2V0IGNvbFNwYW4oY29sU3BhbjogbnVtYmVyKSB7XG4gICAgICAgIGlmIChjb2xTcGFuICE9PSBudWxsICYmIGNvbFNwYW4gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5zZXRDb2x1bW5TcGFuKGNvZXJjZU51bWJlclByb3BlcnR5KGNvbFNwYW4pKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBEZWZpbmVzIHRoZSBudW1iZXIgb2Ygcm93cyB0aGlzIHdpZGdldCBzaG91bGQgb2NjdXB5LiAqL1xuICAgIEBJbnB1dCgpIGdldCByb3dTcGFuKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRSb3dTcGFuKCk7XG4gICAgfVxuXG4gICAgc2V0IHJvd1NwYW4ocm93U3BhbjogbnVtYmVyKSB7XG4gICAgICAgIGlmIChyb3dTcGFuICE9PSBudWxsICYmIHJvd1NwYW4gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5zZXRSb3dTcGFuKGNvZXJjZU51bWJlclByb3BlcnR5KHJvd1NwYW4pKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBEZWZpbmVzIHRoZSBtaW5pbXVtIG51bWJlciBvZiBjb2x1bW5zIHRoaXMgd2lkZ2V0IHNob3VsZCBvY2N1cHkuICovXG4gICAgQElucHV0KCkgZ2V0IG1pbkNvbFNwYW4oKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21pbkNvbFNwYW47XG4gICAgfVxuXG4gICAgc2V0IG1pbkNvbFNwYW4obWluQ29sdW1uczogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuX21pbkNvbFNwYW4gPSBjb2VyY2VOdW1iZXJQcm9wZXJ0eShtaW5Db2x1bW5zKTtcbiAgICB9XG5cbiAgICAvKiogRGVmaW5lcyB0aGUgbWluaW11bSBudW1iZXIgb2Ygcm93cyB0aGlzIHdpZGdldCBzaG91bGQgb2NjdXB5LiAqL1xuICAgIEBJbnB1dCgpIGdldCBtaW5Sb3dTcGFuKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLl9taW5Sb3dTcGFuO1xuICAgIH1cblxuICAgIHNldCBtaW5Sb3dTcGFuKG1pblJvd3M6IG51bWJlcikge1xuICAgICAgICB0aGlzLl9taW5Sb3dTcGFuID0gY29lcmNlTnVtYmVyUHJvcGVydHkobWluUm93cyk7XG4gICAgfVxuXG4gICAgLyoqIERlZmluZXMgd2hldGhlciBvciBub3QgdGhpcyB3aWRnZXQgY2FuIGJlIHJlc2l6ZWQuICovXG4gICAgQElucHV0KCkgcmVzaXphYmxlOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogRGVmaW5lcyB3aGV0aGVyIG9yIG5vdCB0aGlzIHdpZGdldCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcmVwb3NpdGlvbmVkICovXG4gICAgQElucHV0KCkgc2V0IGF1dG9Qb3NpdGlvbmluZyhhdXRvUG9zaXRpb25pbmc6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fYXV0b1Bvc2l0aW9uaW5nID0gY29lcmNlQm9vbGVhblByb3BlcnR5KGF1dG9Qb3NpdGlvbmluZyk7XG4gICAgfVxuXG4gICAgZ2V0IGF1dG9Qb3NpdGlvbmluZygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2F1dG9Qb3NpdGlvbmluZztcbiAgICB9XG5cbiAgICAvKiogRGVmaW5lcyBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhbiBhcmlhIGxhYmVsIGZvciB0aGUgd2lkZ2V0ICovXG4gICAgQElucHV0KCkgd2lkZ2V0QXJpYUxhYmVsOiAod2lkZ2V0czogRGFzaGJvYXJkV2lkZ2V0Q29tcG9uZW50KSA9PiBzdHJpbmcgfCBzdHJpbmcgPSB0aGlzLmdldERlZmF1bHRBcmlhTGFiZWw7XG5cbiAgICBASG9zdEJpbmRpbmcoJ3N0eWxlLmxlZnQucHgnKSB4OiBudW1iZXIgPSAwO1xuICAgIEBIb3N0QmluZGluZygnc3R5bGUudG9wLnB4JykgeTogbnVtYmVyID0gMDtcbiAgICBASG9zdEJpbmRpbmcoJ3N0eWxlLndpZHRoLnB4Jykgd2lkdGg6IG51bWJlciA9IDEwMDtcbiAgICBASG9zdEJpbmRpbmcoJ3N0eWxlLmhlaWdodC5weCcpIGhlaWdodDogbnVtYmVyID0gMTAwO1xuICAgIEBIb3N0QmluZGluZygnc3R5bGUucGFkZGluZy5weCcpIHBhZGRpbmc6IG51bWJlciA9IDA7XG4gICAgQEhvc3RCaW5kaW5nKCdzdHlsZS56LWluZGV4JykgekluZGV4OiBudW1iZXIgPSBudWxsO1xuICAgIEBIb3N0QmluZGluZygnYXR0ci5hcmlhLWxhYmVsJykgYXJpYUxhYmVsOiBzdHJpbmc7XG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLnJvbGUnKSBASW5wdXQoKSByb2xlOiBzdHJpbmcgPSAnZ3JvdXAnO1xuICAgIEBIb3N0QmluZGluZygnY2xhc3MuZHJhZ2dpbmcnKSBpc0RyYWdnaW5nOiBib29sZWFuID0gZmFsc2U7XG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5ncmFiYmluZycpIGlzR3JhYmJpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLnJlc2l6aW5nJykgaXNSZXNpemluZzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgaXNEcmFnZ2FibGU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NvbHVtbjogU3RhY2thYmxlVmFsdWUgPSB7IHJlZ3VsYXI6IHVuZGVmaW5lZCwgc3RhY2tlZDogdW5kZWZpbmVkIH07XG4gICAgcHJpdmF0ZSByZWFkb25seSBfcm93OiBTdGFja2FibGVWYWx1ZSA9IHsgcmVndWxhcjogdW5kZWZpbmVkLCBzdGFja2VkOiB1bmRlZmluZWQgfTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jb2x1bW5TcGFuOiBTdGFja2FibGVWYWx1ZSA9IHsgcmVndWxhcjogMSwgc3RhY2tlZDogMSB9O1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX3Jvd1NwYW46IFN0YWNrYWJsZVZhbHVlID0geyByZWd1bGFyOiAxLCBzdGFja2VkOiAxIH07XG4gICAgcHJpdmF0ZSBfbWluQ29sU3BhbjogbnVtYmVyID0gMTtcbiAgICBwcml2YXRlIF9taW5Sb3dTcGFuOiBudW1iZXIgPSAxO1xuICAgIHByaXZhdGUgX2F1dG9Qb3NpdGlvbmluZzogYm9vbGVhbiA9IHRydWU7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfb25EZXN0cm95ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAvLyBzdWJzY3JpYmUgdG8gb3B0aW9uIGNoYW5nZXNcbiAgICAgICAgdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLm9wdGlvbnMkLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMudXBkYXRlKCkpO1xuXG4gICAgICAgIC8vIGV2ZXJ5IHRpbWUgdGhlIGxheW91dCBjaGFuZ2VzIHdlIHdhbnQgdG8gdXBkYXRlIHRoZSBhcmlhIGxhYmVsXG4gICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS5sYXlvdXQkLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuYXJpYUxhYmVsID0gdGhpcy5nZXRBcmlhTGFiZWwoKSk7XG5cbiAgICAgICAgLy8gYWxsb3cgd2lkZ2V0IG1vdmVtZW50cyB0byBiZSBhbmltYXRlZFxuICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2UuaXNEcmFnZ2luZyQucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSwgbWFwKHdpZGdldCA9PiB3aWRnZXQgPT09IHRoaXMpKVxuICAgICAgICAgICAgLnN1YnNjcmliZShpc0RyYWdnaW5nID0+IHRoaXMuaXNEcmFnZ2luZyA9IGlzRHJhZ2dpbmcpO1xuXG4gICAgICAgIC8vIGFsbG93IHdpZGdldCBtb3ZlbWVudHMgdG8gYmUgYW5pbWF0ZWRcbiAgICAgICAgdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLmlzR3JhYmJpbmckLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSksIG1hcCh3aWRnZXQgPT4gd2lkZ2V0ID09PSB0aGlzKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoaXNHcmFiYmluZyA9PiB0aGlzLmlzR3JhYmJpbmcgPSBpc0dyYWJiaW5nKTtcbiAgICB9XG5cbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcblxuICAgICAgICB0aGlzLl9jb2x1bW5TcGFuLnJlZ3VsYXIgPSB0aGlzLmNvbFNwYW47XG4gICAgICAgIHRoaXMuX3Jvd1NwYW4ucmVndWxhciA9IHRoaXMucm93U3BhbjtcbiAgICAgICAgdGhpcy5fcm93U3Bhbi5zdGFja2VkID0gdGhpcy5yb3dTcGFuO1xuICAgICAgICB0aGlzLl9yb3cucmVndWxhciA9IHRoaXMucm93O1xuICAgICAgICB0aGlzLl9yb3cuc3RhY2tlZCA9IHRoaXMucm93O1xuICAgICAgICB0aGlzLl9jb2x1bW4ucmVndWxhciA9IHRoaXMuY29sO1xuICAgICAgICB0aGlzLl9jb2x1bW4uc3RhY2tlZCA9IHRoaXMuY29sO1xuXG4gICAgICAgIGlmICghdGhpcy5pZCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdEYXNoYm9hcmQgV2lkZ2V0IGlzIG1pc3NpbmcgYW4gSUQuJyk7XG5cbiAgICAgICAgICAgIC8vIHNldCByYW5kb20gaWQgLSBrZWVwcyB0aGluZ3Mgd29ya2luZyBidXQgcHJldmVudHMgZXhwb3J0aW5nIG9mIHBvc2l0aW9uc1xuICAgICAgICAgICAgdGhpcy5pZCA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDEwMDAwMCkudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgLy8gYWRkIHRoZSB3aWRnZXQgdG8gdGhlIGRhc2hib2FyZFxuICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2UuYWRkV2lkZ2V0KHRoaXMpO1xuXG4gICAgICAgIC8vIGFwcGx5IHRoZSBjdXJyZW50IG9wdGlvbnNcbiAgICAgICAgdGhpcy51cGRhdGUoKTtcbiAgICB9XG5cbiAgICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmhhc1Bvc2l0aW9uKCkgJiYgKGNoYW5nZXMuY29sU3BhbiB8fCBjaGFuZ2VzLnJvd1NwYW4pKSB7XG4gICAgICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2UucmVzaXplV2lkZ2V0KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLnJlbmRlckRhc2hib2FyZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSWYgY29tcG9uZW50IGlzIHJlbW92ZWQsIHRoZW4gdW5yZWdpc3RlciBpdCBmcm9tIHRoZSBzZXJ2aWNlXG4gICAgICovXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5uZXh0KCk7XG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5jb21wbGV0ZSgpO1xuICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2UucmVtb3ZlV2lkZ2V0KHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFwcGx5IHRoZSBjdXJyZW50IGRhc2hib2FyZCBvcHRpb25zXG4gICAgICovXG4gICAgdXBkYXRlKCk6IHZvaWQge1xuXG4gICAgICAgIC8vIGdldCB0aGUgY3VycmVudCBvcHRpb25zIGF0IHRoZSB0aW1lXG4gICAgICAgIGNvbnN0IHsgcGFkZGluZywgY29sdW1ucyB9ID0gdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLm9wdGlvbnM7XG5cbiAgICAgICAgdGhpcy5wYWRkaW5nID0gcGFkZGluZztcbiAgICAgICAgdGhpcy5fY29sdW1uU3Bhbi5zdGFja2VkID0gY29sdW1ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGFjdHVhbCBwb3NpdGlvbiBhbmQgc2l6ZSB2YWx1ZXNcbiAgICAgKi9cbiAgICByZW5kZXIoKTogdm9pZCB7XG4gICAgICAgIHRoaXMueCA9IHRoaXMuZ2V0Q29sdW1uKCkgKiB0aGlzLmRhc2hib2FyZFNlcnZpY2UuZ2V0Q29sdW1uV2lkdGgoKTtcbiAgICAgICAgdGhpcy55ID0gdGhpcy5nZXRSb3coKSAqIHRoaXMuZGFzaGJvYXJkU2VydmljZS5nZXRSb3dIZWlnaHQoKTtcbiAgICAgICAgdGhpcy53aWR0aCA9IHRoaXMuZ2V0Q29sdW1uU3BhbigpICogdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLmdldENvbHVtbldpZHRoKCk7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gdGhpcy5nZXRSb3dTcGFuKCkgKiB0aGlzLmRhc2hib2FyZFNlcnZpY2UuZ2V0Um93SGVpZ2h0KCk7XG4gICAgfVxuXG4gICAgZ2V0Q29sdW1uKG1vZGU6IERhc2hib2FyZFN0YWNrTW9kZSA9IERhc2hib2FyZFN0YWNrTW9kZS5BdXRvKTogbnVtYmVyIHtcbiAgICAgICAgc3dpdGNoIChtb2RlKSB7XG4gICAgICAgICAgICBjYXNlIERhc2hib2FyZFN0YWNrTW9kZS5BdXRvOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldFN0YWNrYWJsZVZhbHVlKHRoaXMuX2NvbHVtbik7XG5cbiAgICAgICAgICAgIGNhc2UgRGFzaGJvYXJkU3RhY2tNb2RlLlJlZ3VsYXI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NvbHVtbi5yZWd1bGFyO1xuXG4gICAgICAgICAgICBjYXNlIERhc2hib2FyZFN0YWNrTW9kZS5TdGFja2VkOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jb2x1bW4uc3RhY2tlZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldFJvdyhtb2RlOiBEYXNoYm9hcmRTdGFja01vZGUgPSBEYXNoYm9hcmRTdGFja01vZGUuQXV0byk6IG51bWJlciB7XG4gICAgICAgIHN3aXRjaCAobW9kZSkge1xuICAgICAgICAgICAgY2FzZSBEYXNoYm9hcmRTdGFja01vZGUuQXV0bzpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRTdGFja2FibGVWYWx1ZSh0aGlzLl9yb3cpO1xuXG4gICAgICAgICAgICBjYXNlIERhc2hib2FyZFN0YWNrTW9kZS5SZWd1bGFyOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9yb3cucmVndWxhcjtcblxuICAgICAgICAgICAgY2FzZSBEYXNoYm9hcmRTdGFja01vZGUuU3RhY2tlZDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcm93LnN0YWNrZWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRDb2x1bW4oY29sdW1uOiBudW1iZXIsIHJlbmRlcjogYm9vbGVhbiA9IHRydWUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTdGFja2FibGVWYWx1ZSh0aGlzLl9jb2x1bW4sIGNvbHVtbik7XG5cbiAgICAgICAgaWYgKHJlbmRlcikge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFJvdyhyb3c6IG51bWJlciwgcmVuZGVyOiBib29sZWFuID0gdHJ1ZSk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFN0YWNrYWJsZVZhbHVlKHRoaXMuX3Jvdywgcm93KTtcblxuICAgICAgICBpZiAocmVuZGVyKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0Q29sdW1uU3BhbigpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTdGFja2FibGVWYWx1ZSh0aGlzLl9jb2x1bW5TcGFuKTtcbiAgICB9XG5cbiAgICBnZXRSb3dTcGFuKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFN0YWNrYWJsZVZhbHVlKHRoaXMuX3Jvd1NwYW4pO1xuICAgIH1cblxuICAgIHNldENvbHVtblNwYW4oY29sdW1uU3BhbjogbnVtYmVyLCByZW5kZXI6IGJvb2xlYW4gPSB0cnVlKTogdm9pZCB7XG4gICAgICAgIGlmIChjb2x1bW5TcGFuID49IHRoaXMubWluQ29sU3Bhbikge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGFja2FibGVWYWx1ZSh0aGlzLl9jb2x1bW5TcGFuLCBjb2x1bW5TcGFuKTtcblxuICAgICAgICAgICAgaWYgKHJlbmRlcikge1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRSb3dTcGFuKHJvd1NwYW46IG51bWJlciwgcmVuZGVyOiBib29sZWFuID0gdHJ1ZSk6IHZvaWQge1xuICAgICAgICBpZiAocm93U3BhbiA+PSB0aGlzLm1pblJvd1NwYW4pIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhY2thYmxlVmFsdWUodGhpcy5fcm93U3Bhbiwgcm93U3Bhbik7XG5cbiAgICAgICAgICAgIGlmIChyZW5kZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgYnJpbmdUb0Zyb250KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnpJbmRleCA9IDE7XG4gICAgfVxuXG4gICAgc2VuZFRvQmFjaygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy56SW5kZXggPSBudWxsO1xuICAgIH1cblxuICAgIHNldEJvdW5kcyh4OiBudW1iZXIsIHk6IG51bWJlciwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgdGhpcy55ID0geTtcbiAgICAgICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB9XG5cbiAgICBkcmFnc3RhcnQoaGFuZGxlOiBIVE1MRWxlbWVudCwgZXZlbnQ6IE1vdXNlRXZlbnQsIGRpcmVjdGlvbjogQWN0aW9uRGlyZWN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaXNSZXNpemluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS5pc0dyYWJiaW5nJC5uZXh0KG51bGwpO1xuICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2Uub25SZXNpemVTdGFydCh7IHdpZGdldDogdGhpcywgZGlyZWN0aW9uLCBldmVudCwgaGFuZGxlIH0pO1xuICAgIH1cblxuICAgIGRyYWcoaGFuZGxlOiBIVE1MRWxlbWVudCwgZXZlbnQ6IE1vdXNlRXZlbnQsIGRpcmVjdGlvbjogQWN0aW9uRGlyZWN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS5vblJlc2l6ZURyYWcoeyB3aWRnZXQ6IHRoaXMsIGRpcmVjdGlvbiwgZXZlbnQsIGhhbmRsZSB9KTtcbiAgICB9XG5cbiAgICBkcmFnZW5kKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmlzUmVzaXppbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLm9uUmVzaXplRW5kKCk7XG4gICAgfVxuXG4gICAgZ2V0QXJpYUxhYmVsKCk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0aGlzLndpZGdldEFyaWFMYWJlbCAmJiB0eXBlb2YgdGhpcy53aWRnZXRBcmlhTGFiZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWRnZXRBcmlhTGFiZWw7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy53aWRnZXRBcmlhTGFiZWwgJiYgdHlwZW9mIHRoaXMud2lkZ2V0QXJpYUxhYmVsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWRnZXRBcmlhTGFiZWwodGhpcyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5hcmlhTGFiZWw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXREZWZhdWx0QXJpYUxhYmVsKHdpZGdldDogRGFzaGJvYXJkV2lkZ2V0Q29tcG9uZW50KTogc3RyaW5nIHtcblxuICAgICAgICBsZXQgb3B0aW9uczogc3RyaW5nID0gJyc7XG5cbiAgICAgICAgaWYgKHdpZGdldC5yZXNpemFibGUgJiYgd2lkZ2V0LmlzRHJhZ2dhYmxlKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gJ0l0IGNhbiBiZSBtb3ZlZCBhbmQgcmVzaXplZC4nO1xuICAgICAgICB9IGVsc2UgaWYgKHdpZGdldC5yZXNpemFibGUpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSAnSXQgY2FuIGJlIHJlc2l6ZWQuJztcbiAgICAgICAgfSBlbHNlIGlmICh3aWRnZXQuaXNEcmFnZ2FibGUpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSAnSXQgY2FuIGJlIG1vdmVkLic7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYCR7d2lkZ2V0Lm5hbWV9IHBhbmVsIGluIHJvdyAke3dpZGdldC5nZXRSb3coKX0sIGNvbHVtbiAke3dpZGdldC5nZXRDb2x1bW4oKX0sIGlzICR7d2lkZ2V0LmdldENvbHVtblNwYW4oKX0gY29sdW1ucyB3aWRlIGFuZCAke3dpZGdldC5nZXRSb3dTcGFuKCl9IHJvd3MgaGlnaC4gJHtvcHRpb25zfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxsb3dzIGF1dG9tYXRpYyBzZXR0aW5nIG9mIHN0YWNrYWJsZSB2YWx1ZVxuICAgICAqIEBwYXJhbSBwcm9wZXJ0eSBUaGUgY3VycmVudCBTdGFja2FibGVWYWx1ZSBvYmplY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldCBpbiB0aGUgYXBwcm9wcmlhdGUgZmllbGRcbiAgICAgKi9cbiAgICBwcml2YXRlIHNldFN0YWNrYWJsZVZhbHVlKHByb3BlcnR5OiBTdGFja2FibGVWYWx1ZSwgdmFsdWU6IG51bWJlcik6IHZvaWQge1xuXG4gICAgICAgIGlmICh0aGlzLmRhc2hib2FyZFNlcnZpY2Uuc3RhY2tlZCkge1xuICAgICAgICAgICAgcHJvcGVydHkuc3RhY2tlZCA9IHZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvcGVydHkucmVndWxhciA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBhcHByb3ByaWF0ZSB2YWx1ZSBmcm9tIGEgc3RhY2thYmxlIHZhbHVlXG4gICAgICogQHBhcmFtIHByb3BlcnR5IFRoZSBTdGFja2FibGUgdmFsdWUgb2JqZWN0XG4gICAgICovXG4gICAgcHJpdmF0ZSBnZXRTdGFja2FibGVWYWx1ZShwcm9wZXJ0eTogU3RhY2thYmxlVmFsdWUpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLnN0YWNrZWQgPyBwcm9wZXJ0eS5zdGFja2VkIDogcHJvcGVydHkucmVndWxhcjtcbiAgICB9XG5cbiAgICAvKiogRGV0ZXJtaW5lIGlmIHRoZSBsYXlvdXQgaGFzIGJlZW4gcGVyZm9ybWVkIHlldCAqL1xuICAgIHByaXZhdGUgaGFzUG9zaXRpb24oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbHVtbigpICE9PSB1bmRlZmluZWQgJiYgdGhpcy5nZXRSb3coKSAhPT0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9hdXRvUG9zaXRpb25pbmc6IEJvb2xlYW5JbnB1dDtcbiAgICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfY29sOiBOdW1iZXJJbnB1dDtcbiAgICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfcm93OiBOdW1iZXJJbnB1dDtcbiAgICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfY29sU3BhbjogTnVtYmVySW5wdXQ7XG4gICAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX3Jvd1NwYW46IE51bWJlcklucHV0O1xuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9taW5Db2xTcGFuOiBOdW1iZXJJbnB1dDtcbiAgICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfbWluUm93U3BhbjogTnVtYmVySW5wdXQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhY2thYmxlVmFsdWUge1xuICAgIHJlZ3VsYXI6IG51bWJlcjtcbiAgICBzdGFja2VkOiBudW1iZXI7XG59XG4iLCI8ZGl2IGNsYXNzPVwid2lkZ2V0LWNvbnRlbnQgd2lkZ2V0LWNvbC1zcGFuLXt7IGdldENvbHVtblNwYW4oKSB9fSB3aWRnZXQtcm93LXNwYW4te3sgZ2V0Um93U3BhbigpIH19XCI+XG4gICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuPC9kaXY+XG5cbjxkaXYgdXhEcmFnXG4gICAgICNoYW5kbGVUb3BcbiAgICAgY2xhc3M9XCJyZXNpemVyLWhhbmRsZSBoYW5kbGUtdG9wXCJcbiAgICAgKG9uRHJhZ1N0YXJ0KT1cImRyYWdzdGFydChoYW5kbGVUb3AsICRldmVudCwgMClcIlxuICAgICAob25EcmFnKT1cImRyYWcoaGFuZGxlVG9wLCAkZXZlbnQsIDApXCJcbiAgICAgKG9uRHJhZ0VuZCk9XCJkcmFnZW5kKClcIlxuICAgICBbc3R5bGUudG9wLnB4XT1cInBhZGRpbmdcIlxuICAgICBbaGlkZGVuXT1cIiFyZXNpemFibGVcIj5cbjwvZGl2PlxuXG48ZGl2IHV4RHJhZ1xuICA