UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

355 lines 51.8 kB
import { DatePipe } from '@angular/common'; import { ChangeDetectorRef, Component, Injector, Input, ViewChild } from '@angular/core'; import { Globalization } from '@microsoft/windows-admin-center-sdk/core/data/globalization'; import { ChartComponent } from '../chart/chart.component'; import { CoreBaseComponent } from '../common/base.component'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "../chart/chart.component"; import * as i3 from "../legend/legend.component"; const _c0 = ["linechart"]; function LineChartComponent_div_0_div_1_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "div"); i0.ɵɵtext(1); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵattribute("aria-hidden", ctx_r1.showLegend); i0.ɵɵadvance(1); i0.ɵɵtextInterpolate1(" ", ctx_r1.lineChartData.title, ""); } } function LineChartComponent_div_0_sme_legend_2_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "sme-legend", 14); } if (rf & 2) { const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵproperty("legendData", !ctx_r2.chartLegendData || ctx_r2.chartLegendData.length === 0 ? ctx_r2.generatedLegendData : ctx_r2.chartLegendData); i0.ɵɵattribute("aria-label", ctx_r2.lineChartData.title); } } function LineChartComponent_div_0_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "div", 1); i0.ɵɵtemplate(1, LineChartComponent_div_0_div_1_Template, 2, 2, "div", 2); i0.ɵɵtemplate(2, LineChartComponent_div_0_sme_legend_2_Template, 1, 2, "sme-legend", 3); i0.ɵɵelementStart(3, "div", 4)(4, "div", 5); i0.ɵɵelement(5, "sme-chart", 6, 7); i0.ɵɵelementStart(7, "div", 8)(8, "div", 9); i0.ɵɵtext(9); i0.ɵɵelementEnd(); i0.ɵɵelementStart(10, "div", 10); i0.ɵɵtext(11); i0.ɵɵelementEnd()()(); i0.ɵɵelementStart(12, "div", 11)(13, "div", 12); i0.ɵɵtext(14); i0.ɵɵelementEnd(); i0.ɵɵelementStart(15, "div", 13); i0.ɵɵtext(16); i0.ɵɵelementEnd()()()(); } if (rf & 2) { const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx_r0.lineChartData.title); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx_r0.showLegend); i0.ɵɵadvance(3); i0.ɵɵproperty("type", ctx_r0.getTypeString(ctx_r0.lineChartData.type))("data", ctx_r0.lineChartData.chartData)("options", ctx_r0.chartOptions); i0.ɵɵadvance(4); i0.ɵɵtextInterpolate(ctx_r0.lineChartData.xAxisMaxLabel); i0.ɵɵadvance(2); i0.ɵɵtextInterpolate(ctx_r0.lineChartData.xAxisMinLabel); i0.ɵɵadvance(3); i0.ɵɵtextInterpolate1(" ", ctx_r0.lineChartData.yAxisMaxLabel, ""); i0.ɵɵadvance(2); i0.ɵɵtextInterpolate1(" ", ctx_r0.lineChartData.yAxisMinLabel, ""); } } export var LineChartType; (function (LineChartType) { /** * Line chart takes in data as number[] */ LineChartType[LineChartType["Line"] = 1] = "Line"; /** * Scatter chart takes in data as ChartPoint[] with x and y coordinates */ LineChartType[LineChartType["Scatter"] = 2] = "Scatter"; /** * Historical chart takes in data at ChartPoint[] with x and y coordinates * x coordinates or historical chart are in the format of an integer timestamp * so that the tooltips can format the appropriate date */ LineChartType[LineChartType["Historical"] = 3] = "Historical"; })(LineChartType || (LineChartType = {})); export class LineChartComponent extends CoreBaseComponent { /** * Constructs a new instance of @see LineChartComponent * @param injector the injector service for the base class of this component * @param changeDetectorRef provides data change detection to the line chart */ constructor(injector, changeDetectorRef) { super(injector); this.changeDetectorRef = changeDetectorRef; // blue 80 this.primaryLineColor = 'rgba(51, 133, 198, 1.0)'; this.primaryBackgroundColor = 'rgba(51, 133, 198, 0.1)'; // magenta this.secondaryLineColor = 'rgba(180, 0, 158, 1.0)'; this.secondaryBackgroundColor = 'rgba(180, 0, 158, 0.1)'; // teal 80 this.tertiaryLineColor = 'rgba(51, 155, 142, 1.0)'; this.tertiaryBackgroundColor = 'rgba(51, 155, 142, 0.1)'; this.defaultSettings = [ { borderColor: this.primaryLineColor, backgroundColor: this.primaryBackgroundColor, pointHoverBackgroundColor: this.primaryLineColor }, { borderColor: this.secondaryLineColor, backgroundColor: this.secondaryBackgroundColor, pointHoverBackgroundColor: this.secondaryLineColor }, { borderColor: this.tertiaryLineColor, backgroundColor: this.tertiaryBackgroundColor, pointHoverBackgroundColor: this.tertiaryLineColor } ]; } /** * The source name to use for logging */ get logSourceName() { return 'LineChartComponent'; } get showLegend() { const legendData = this.chartLegendData || this.generatedLegendData; return !!(legendData && legendData.length); } /** * Angular lifecycle hook, called after the component is initialized */ ngOnInit() { this.validateChartType(); // preserve options referential integrity const originalOptions = this.chartOptions || {}; const options = MsftSme.deepCopy(originalOptions); this.chartOptions = MsftSme.deepAssign(originalOptions, this.getDefaultOptions(), options); } getDefaultOptions() { return { tooltips: { callbacks: { label: (tooltipItem, data) => { return this.getTooltipLabel(tooltipItem, data); } } }, scales: { yAxes: [{ display: false, ticks: { display: false, min: 0, max: this.lineChartData ? this.lineChartData.ymaxValue : undefined, maxTicksLimit: 1 } }], xAxes: [{ display: false, ticks: { min: this.lineChartData ? this.lineChartData.xAxisMin : undefined, max: this.lineChartData ? this.lineChartData.xAxisMax : undefined }, gridLines: { display: false } } ] }, animation: { duration: 0 }, title: { display: false }, legend: { display: false } }; } /** * Angular lifecycle hook, called after the view is initialized */ ngAfterViewInit() { this.refresh(); this.changeDetectorRef.detectChanges(); } ngOnDestroy() { this.changeDetectorRef.detach(); } // give the charts standard appearance across the whole application unless user sets useCustomSettings useDefaultSettings() { if (!this.chart || !this.lineChartData || !this.lineChartData.chartData || !this.lineChartData.chartData.datasets) { return; } const dataSets = this.lineChartData.chartData.datasets; for (let i = 0; i < Math.min(dataSets.length, 3); i++) { const dataset = dataSets[i]; dataset.borderColor = this.defaultSettings[i].borderColor; dataset.backgroundColor = dataSets.length < 3 ? this.defaultSettings[i].backgroundColor : 'rgba(0,0,0,0)'; dataset.borderWidth = 2; dataset.pointHoverBackgroundColor = this.defaultSettings[i].pointHoverBackgroundColor; dataset.pointRadius = 0; dataset.pointHitRadius = 5; dataset.showLine = true; dataset.lineTension = 0; } } /** * generate legend data if currentValueLabelData is given */ generateLegendData() { this.generatedLegendData = []; const dataSets = this.lineChartData.chartData.datasets; if (!MsftSme.isNullOrUndefined(this.lineChartData.currentValueLabel) && dataSets.length > 0) { const unitLabel = this.lineChartData.unitLabel || ''; this.generatedLegendData.push({ label: '', displayValue: this.lineChartData.currentValueLabel + ' ' + unitLabel, color: dataSets[0].borderColor.toString() }); } else { this.chartLegendData = []; if (!MsftSme.isNullOrUndefined(this.lineChartData.currentValueLabel) && this.lineChartData.firstLabel && dataSets.length > 0) { this.chartLegendData.push({ label: this.lineChartData.firstLabel, displayValue: this.lineChartData.firstCurrentValueLabel, color: dataSets[0].borderColor.toString() }); } if (!MsftSme.isNullOrUndefined(this.lineChartData.currentValueLabel) && this.lineChartData.secondLabel && dataSets.length > 1) { this.chartLegendData.push({ label: this.lineChartData.secondLabel, displayValue: this.lineChartData.secondCurrentValueLabel, color: dataSets[1].borderColor.toString() }); } if (!MsftSme.isNullOrUndefined(this.lineChartData.currentValueLabel) && this.lineChartData.totalLabel && dataSets.length > 2) { this.chartLegendData.push({ label: this.lineChartData.totalLabel, displayValue: this.lineChartData.totalCurrentValueLabel, color: dataSets[2].borderColor.toString() }); } } } /** * Throw error if consumer is trying to graph a scatter plot without x y coordinates */ validateChartType() { if (!this.lineChartData) { return; } this.lineChartData.chartData.datasets.forEach(dataset => { // Note: this would be better written with a check on every element of the array, // However tsc is unable to typecheck Array.every on a union of array types. // So we assume the type is number[] if the first element is a number. const isNumArray = dataset.data && dataset.data.length > 0 && typeof dataset.data[0] === 'number'; if (isNumArray && this.lineChartData && this.lineChartData.type && this.lineChartData.type !== LineChartType.Line) { throw new Error('Historical and Scatter chart types require all dataset data to be of type ChartPoint[]'); } }); } /** * return the string for the type of line chart * @param type the type of line chart */ getTypeString(type) { return type === LineChartType.Scatter || type === LineChartType.Historical ? 'scatter' : 'line'; } /** * Returns tool tip label according to the type of chart being used * @param tooltipItem - the specific item that needs a tooltip * @param data - the linearchartdata object */ getTooltipLabel(tooltipItem, data) { const dataset = data.datasets[tooltipItem.datasetIndex]; const dataPoint = dataset.data[tooltipItem.index]; const title = dataset.label; let value = ''; let label = ''; if (this.lineChartData.type === LineChartType.Historical) { // this is where tooltip pretty printing needs to happen value = this.tooltipFormatter ? this.tooltipFormatter(dataPoint.y) : Globalization.number(dataPoint.y, { maximumFractionDigits: 2 }); label = Globalization.dateTimeOnly(new Date(dataPoint.x)); } else if (this.lineChartData.type === LineChartType.Scatter) { value = this.tooltipFormatter ? this.tooltipFormatter(dataPoint.y) : Globalization.number(dataPoint.y, { maximumFractionDigits: 2 }); label = dataPoint.x; } else { const tmpValue = dataPoint.y ? dataPoint.y : dataPoint; value = this.tooltipFormatter ? this.tooltipFormatter(tmpValue) : Globalization.number(tmpValue, { maximumFractionDigits: 2 }); } return label ? '{0} {1}: {2}'.format(title, label, value) : '{0}: {1}'.format(title, value); } /** * Refresh the chart when new data is added to lineChartData input */ refresh() { if (!this.useCustomSettings) { this.useDefaultSettings(); } if (!this.chartLegendData || this.chartLegendData.length === 0) { this.generateLegendData(); } if (this.lineChartData && this.chartOptions) { const scalesChanged = this.chartOptions.scales.yAxes[0].ticks.max !== this.lineChartData.ymaxValue || this.chartOptions.scales.xAxes[0].ticks.min !== this.lineChartData.xAxisMin || this.chartOptions.scales.xAxes[0].ticks.max !== this.lineChartData.xAxisMax; if (scalesChanged) { this.chartOptions.scales.yAxes[0].ticks.max = this.lineChartData.ymaxValue; this.chartOptions.scales.xAxes[0].ticks.min = this.lineChartData.xAxisMin; this.chartOptions.scales.xAxes[0].ticks.max = this.lineChartData.xAxisMax; if (this.chart) { this.chart.initialize(); } } } if (this.chart) { this.chart.refresh(); } } } /** @nocollapse */ LineChartComponent.ɵfac = function LineChartComponent_Factory(t) { return new (t || LineChartComponent)(i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); }; /** @nocollapse */ LineChartComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: LineChartComponent, selectors: [["sme-line-chart"]], viewQuery: function LineChartComponent_Query(rf, ctx) { if (rf & 1) { i0.ɵɵviewQuery(_c0, 5); } if (rf & 2) { let _t; i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.chart = _t.first); } }, inputs: { tooltipFormatter: "tooltipFormatter", lineChartData: "lineChartData", useCustomSettings: "useCustomSettings", chartLegendData: "chartLegendData", chartOptions: "chartOptions" }, features: [i0.ɵɵProvidersFeature([DatePipe]), i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [["class", "sme-focus-zone", 4, "ngIf"], [1, "sme-focus-zone"], [4, "ngIf"], [3, "legendData", 4, "ngIf"], [1, "sme-arrange-stack-h", "sme-arrange-overflow-show"], [1, "sme-position-stretch-h"], [1, "sme-position-flex-none", "sme-layout-block", "sme-border-bottom-sm", "sme-border-right-sm", "sme-border-color-base-80", 3, "type", "data", "options"], ["linechart", ""], [1, "sme-margin-top-xxs", "sme-color-black-60"], [1, "sme-layout-float-left", "sme-font-label"], [1, "sme-layout-float-right", "sme-font-label"], [1, "sme-position-flex-auto", "sme-arrange-stack-v", "sme-margin-left-xxs", "sme-margin-bottom-md", "sme-arrange-stack-v", "sme-color-black-60"], [1, "sme-font-label", "sme-position-flex-auto", "sme-layout-line-chart-y-axis"], [1, "sme-font-label", "sme-position-flex-none", "sme-layout-line-chart-y-axis"], [3, "legendData"]], template: function LineChartComponent_Template(rf, ctx) { if (rf & 1) { i0.ɵɵtemplate(0, LineChartComponent_div_0_Template, 17, 9, "div", 0); } if (rf & 2) { i0.ɵɵproperty("ngIf", ctx.lineChartData); } }, dependencies: [i1.NgIf, i2.ChartComponent, i3.LegendComponent], encapsulation: 2 }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LineChartComponent, [{ type: Component, args: [{ selector: 'sme-line-chart', providers: [DatePipe], template: "<div *ngIf=\"lineChartData\" class=\"sme-focus-zone\">\r\n <div *ngIf=\"lineChartData.title\" [attr.aria-hidden]=\"showLegend\"> {{ lineChartData.title }}</div>\r\n\r\n <sme-legend *ngIf=\"showLegend\"\r\n [legendData]=\"(!chartLegendData || chartLegendData.length === 0) ? generatedLegendData : chartLegendData\"\r\n [attr.aria-label]=\"lineChartData.title\">\r\n </sme-legend>\r\n\r\n <div class=\"sme-arrange-stack-h sme-arrange-overflow-show\">\r\n <div class=\"sme-position-stretch-h\">\r\n <sme-chart\r\n class=\"sme-position-flex-none sme-layout-block sme-border-bottom-sm sme-border-right-sm sme-border-color-base-80\"\r\n #linechart [type]=\"getTypeString(lineChartData.type)\" [data]=\"lineChartData.chartData\"\r\n [options]=\"chartOptions\"></sme-chart>\r\n <div class=\"sme-margin-top-xxs sme-color-black-60\">\r\n <div class=\"sme-layout-float-left sme-font-label\">{{ lineChartData.xAxisMaxLabel }}</div>\r\n <div class=\"sme-layout-float-right sme-font-label\">{{ lineChartData.xAxisMinLabel }}</div>\r\n </div>\r\n </div>\r\n <div\r\n class=\"sme-position-flex-auto sme-arrange-stack-v sme-margin-left-xxs sme-margin-bottom-md sme-arrange-stack-v sme-color-black-60\">\r\n <div class=\"sme-font-label sme-position-flex-auto sme-layout-line-chart-y-axis\">\r\n {{ lineChartData.yAxisMaxLabel }}</div>\r\n <div class=\"sme-font-label sme-position-flex-none sme-layout-line-chart-y-axis\">\r\n {{ lineChartData.yAxisMinLabel }}</div>\r\n </div>\r\n </div>\r\n\r\n</div>" }] }], function () { return [{ type: i0.Injector }, { type: i0.ChangeDetectorRef }]; }, { chart: [{ type: ViewChild, args: ['linechart'] }], tooltipFormatter: [{ type: Input }], lineChartData: [{ type: Input }], useCustomSettings: [{ type: Input }], chartLegendData: [{ type: Input }], chartOptions: [{ type: Input }] }); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGluZS1jaGFydC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9saW5lLWNoYXJ0L2xpbmUtY2hhcnQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vYW5ndWxhci9zcmMvY29udHJvbHMvbGluZS1jaGFydC9saW5lLWNoYXJ0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBQWlCLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFxQixTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0gsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDZEQUE2RCxDQUFDO0FBRTVGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7OztJQ0ozRCwyQkFBaUU7SUFBQyxZQUF5QjtJQUFBLGlCQUFNOzs7SUFBaEUsZ0RBQStCO0lBQUUsZUFBeUI7SUFBekIsMERBQXlCOzs7SUFFM0YsaUNBR2E7OztJQUZYLGlKQUF5RztJQUN6Ryx3REFBdUM7OztJQUwzQyw4QkFBa0Q7SUFDaEQseUVBQWlHO0lBRWpHLHVGQUdhO0lBRWIsOEJBQTJELGFBQUE7SUFFdkQsa0NBR3VDO0lBQ3ZDLDhCQUFtRCxhQUFBO0lBQ0MsWUFBaUM7SUFBQSxpQkFBTTtJQUN6RixnQ0FBbUQ7SUFBQSxhQUFpQztJQUFBLGlCQUFNLEVBQUEsRUFBQTtJQUc5RixnQ0FDcUksZUFBQTtJQUVqSSxhQUFpQztJQUFBLGlCQUFNO0lBQ3pDLGdDQUFnRjtJQUM5RSxhQUFpQztJQUFBLGlCQUFNLEVBQUEsRUFBQSxFQUFBOzs7SUF2QnZDLGVB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M0I7YUFDSjtTQUNKO1FBRUQsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1osSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUN4QjtJQUNMLENBQUM7O3VHQXJSUSxrQkFBa0I7b0dBQWxCLGtCQUFrQjs7Ozs7c09BRmhCLENBQUMsUUFBUSxDQUFDO1FDcER6QixvRUE0Qk07O1FBNUJBLHdDQUFtQjs7dUZEc0RaLGtCQUFrQjtjQUw5QixTQUFTOzJCQUNJLGdCQUFnQixhQUVmLENBQUMsUUFBUSxDQUFDOzJGQVNVLEtBQUs7a0JBQW5DLFNBQVM7bUJBQUMsV0FBVztZQUlOLGdCQUFnQjtrQkFBL0IsS0FBSztZQUNVLGFBQWE7a0JBQTVCLEtBQUs7WUFDVSxpQkFBaUI7a0JBQWhDLEtBQUs7WUFDVSxlQUFlO2tCQUE5QixLQUFLO1lBQ1UsWUFBWTtrQkFBM0IsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGVQaXBlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgSW5qZWN0b3IsIElucHV0LCBPbkRlc3Ryb3ksIE9uSW5pdCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEdsb2JhbGl6YXRpb24gfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2RhdGEvZ2xvYmFsaXphdGlvbic7XHJcbmltcG9ydCB7IENoYXJ0RGF0YSwgQ2hhcnREYXRhU2V0cywgQ2hhcnRPcHRpb25zIH0gZnJvbSAnY2hhcnQuanMnO1xyXG5pbXBvcnQgeyBDaGFydENvbXBvbmVudCB9IGZyb20gJy4uL2NoYXJ0L2NoYXJ0LmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IENvcmVCYXNlQ29tcG9uZW50IH0gZnJvbSAnLi4vY29tbW9uL2Jhc2UuY29tcG9uZW50JztcclxuaW1wb3J0IHsgTGVnZW5kRW50cnlEYXRhIH0gZnJvbSAnLi4vbGVnZW5kL2xlZ2VuZC1lbnRyeS9sZWdlbmQtZW50cnkuY29tcG9uZW50JztcclxuXHJcbmV4cG9ydCBlbnVtIExpbmVDaGFydFR5cGUge1xyXG4gICAgLyoqXHJcbiAgICAgKiBMaW5lIGNoYXJ0IHRha2VzIGluIGRhdGEgYXMgbnVtYmVyW11cclxuICAgICAqL1xyXG4gICAgTGluZSA9IDEsXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTY2F0dGVyIGNoYXJ0IHRha2VzIGluIGRhdGEgYXMgQ2hhcnRQb2ludFtdIHdpdGggeCBhbmQgeSBjb29yZGluYXRlc1xyXG4gICAgICovXHJcbiAgICBTY2F0dGVyID0gMixcclxuXHJcbiAgICAvKipcclxuICAgICAqIEhpc3RvcmljYWwgY2hhcnQgdGFrZXMgaW4gZGF0YSBhdCBDaGFydFBvaW50W10gd2l0aCB4IGFuZCB5IGNvb3JkaW5hdGVzXHJcbiAgICAgKiB4IGNvb3JkaW5hdGVzIG9yIGhpc3RvcmljYWwgY2hhcnQgYXJlIGluIHRoZSBmb3JtYXQgb2YgYW4gaW50ZWdlciB0aW1lc3RhbXBcclxuICAgICAqIHNvIHRoYXQgdGhlIHRvb2x0aXBzIGNhbiBmb3JtYXQgdGhlIGFwcHJvcHJpYXRlIGRhdGVcclxuICAgICAqL1xyXG4gICAgSGlzdG9yaWNhbCA9IDNcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBMaW5lQ2hhcnREYXRhIHtcclxuICAgIHRpdGxlOiBzdHJpbmc7XHJcbiAgICBjaGFydERhdGE6IENoYXJ0RGF0YTtcclxuICAgIGN1cnJlbnRWYWx1ZUxhYmVsPzogc3RyaW5nO1xyXG4gICAgZmlyc3RDdXJyZW50VmFsdWVMYWJlbD86IHN0cmluZztcclxuICAgIHNlY29uZEN1cnJlbnRWYWx1ZUxhYmVsPzogc3RyaW5nO1xyXG4gICAgdG90YWxDdXJyZW50VmFsdWVMYWJlbD86IHN0cmluZztcclxuICAgIGZpcnN0TGFiZWw/OiBzdHJpbmc7XHJcbiAgICBzZWNvbmRMYWJlbD86IHN0cmluZztcclxuICAgIHRvdGFsTGFiZWw/OiBzdHJpbmc7XHJcbiAgICB5QXhpc01pbkxhYmVsPzogc3RyaW5nO1xyXG4gICAgeUF4aXNNYXhMYWJlbD86IHN0cmluZztcclxuICAgIHhBeGlzTWF4TGFiZWw/OiBzdHJpbmc7XHJcbiAgICB4QXhpc01pbkxhYmVsPzogc3RyaW5nO1xyXG4gICAgeW1heFZhbHVlPzogbnVtYmVyO1xyXG4gICAgdHlwZT86IExpbmVDaGFydFR5cGU7XHJcbiAgICB4QXhpc01pbj86IG51bWJlcjtcclxuICAgIHhBeGlzTWF4PzogbnVtYmVyO1xyXG4gICAgdW5pdExhYmVsPzogc3RyaW5nO1xyXG4gICAgaXNMb2FkaW5nPzogYm9vbGVhbjtcclxufVxyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3NtZS1saW5lLWNoYXJ0JyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9saW5lLWNoYXJ0LmNvbXBvbmVudC5odG1sJyxcclxuICAgIHByb3ZpZGVyczogW0RhdGVQaXBlXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgTGluZUNoYXJ0Q29tcG9uZW50IGV4dGVuZHMgQ29yZUJhc2VDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBzb3VyY2UgbmFtZSB0byB1c2UgZm9yIGxvZ2dpbmdcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGdldCBsb2dTb3VyY2VOYW1lKCkge1xyXG4gICAgICAgIHJldHVybiAnTGluZUNoYXJ0Q29tcG9uZW50JztcclxuICAgIH1cclxuICAgIEBWaWV3Q2hpbGQoJ2xpbmVjaGFydCcpIHB1YmxpYyBjaGFydDogQ2hhcnRDb21wb25lbnQ7XHJcbiAgICAvKipcclxuICAgICAqICBGdW5jdGlvbiB0byBhcHBseSB0byB0b29sdGlwIGRhdGEgZm9yIHByZXR0eS1wcmludGluZyB0aGUgdmFsdWVcclxuICAgICAqL1xyXG4gICAgQElucHV0KCkgcHVibGljIHRvb2x0aXBGb3JtYXR0ZXI6IEZ1bmN0aW9uO1xyXG4gICAgQElucHV0KCkgcHVibGljIGxpbmVDaGFydERhdGE6IExpbmVDaGFydERhdGE7XHJcbiAgICBASW5wdXQoKSBwdWJsaWMgdXNlQ3VzdG9tU2V0dGluZ3M/OiBib29sZWFuO1xyXG4gICAgQElucHV0KCkgcHVibGljIGNoYXJ0TGVnZW5kRGF0YTogTGVnZW5kRW50cnlEYXRhW107XHJcbiAgICBASW5wdXQoKSBwdWJsaWMgY2hhcnRPcHRpb25zOiBDaGFydE9wdGlvbnM7XHJcblxyXG4gICAgcHVibGljIGdlbmVyYXRlZExlZ2VuZERhdGE6IExlZ2VuZEVudHJ5RGF0YVtdO1xyXG5cclxuICAgIC8vIGJsdWUgODBcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgcHJpbWFyeUxpbmVDb2xvciA9ICdyZ2JhKDUxLCAxMzMsIDE5OCwgMS4wKSc7XHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHByaW1hcnlCYWNrZ3JvdW5kQ29sb3IgPSAncmdiYSg1MSwgMTMzLCAxOTgsIDAuMSknO1xyXG5cclxuICAgIC8vIG1hZ2VudGFcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2Vjb25kYXJ5TGluZUNvbG9yID0gJ3JnYmEoMTgwLCAwLCAxNTgsIDEuMCknO1xyXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZWNvbmRhcnlCYWNrZ3JvdW5kQ29sb3IgPSAncmdiYSgxODAsIDAsIDE1OCwgMC4xKSc7XHJcblxyXG4gICAgLy8gdGVhbCA4MFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSB0ZXJ0aWFyeUxpbmVDb2xvciA9ICdyZ2JhKDUxLCAxNTUsIDE0MiwgMS4wKSc7XHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRlcnRpYXJ5QmFja2dyb3VuZENvbG9yID0gJ3JnYmEoNTEsIDE1NSwgMTQyLCAwLjEpJztcclxuXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRTZXR0aW5nczogQ2hhcnREYXRhU2V0c1tdID0gW1xyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgYm9yZGVyQ29sb3I6IHRoaXMucHJpbWFyeUxpbmVDb2xvcixcclxuICAgICAgICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLnByaW1hcnlCYWNrZ3JvdW5kQ29sb3IsXHJcbiAgICAgICAgICAgIHBvaW50SG92ZXJCYWNrZ3JvdW5kQ29sb3I6IHRoaXMucHJpbWFyeUxpbmVDb2xvclxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBib3JkZXJDb2xvcjogdGhpcy5zZWNvbmRhcnlMaW5lQ29sb3IsXHJcbiAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogdGhpcy5zZWNvbmRhcnlCYWNrZ3JvdW5kQ29sb3IsXHJcbiAgICAgICAgICAgIHBvaW50SG92ZXJCYWNrZ3JvdW5kQ29sb3I6IHRoaXMuc2Vjb25kYXJ5TGluZUNvbG9yXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIGJvcmRlckNvbG9yOiB0aGlzLnRlcnRpYXJ5TGluZUNvbG9yLFxyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMudGVydGlhcnlCYWNrZ3JvdW5kQ29sb3IsXHJcbiAgICAgICAgICAgIHBvaW50SG92ZXJCYWNrZ3JvdW5kQ29sb3I6IHRoaXMudGVydGlhcnlMaW5lQ29sb3JcclxuICAgICAgICB9XHJcbiAgICBdO1xyXG5cclxuICAgIHB1YmxpYyBnZXQgc2hvd0xlZ2VuZCgpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCBsZWdlbmREYXRhID0gdGhpcy5jaGFydExlZ2VuZERhdGEgfHwgdGhpcy5nZW5lcmF0ZWRMZWdlbmREYXRhO1xyXG4gICAgICAgIHJldHVybiAhIShsZWdlbmREYXRhICYmIGxlZ2VuZERhdGEubGVuZ3RoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnN0cnVjdHMgYSBuZXcgaW5zdGFuY2Ugb2YgQHNlZSBMaW5lQ2hhcnRDb21wb25lbnRcclxuICAgICAqIEBwYXJhbSBpbmplY3RvciB0aGUgaW5qZWN0b3Igc2VydmljZSBmb3IgdGhlIGJhc2UgY2xhc3Mgb2YgdGhpcyBjb21wb25lbnRcclxuICAgICAqIEBwYXJhbSBjaGFuZ2VEZXRlY3RvclJlZiBwcm92aWRlcyBkYXRhIGNoYW5nZSBkZXRlY3Rpb24gdG8gdGhlIGxpbmUgY2hhcnRcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IoaW5qZWN0b3I6IEluamVjdG9yLCBwcml2YXRlIGNoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZikge1xyXG4gICAgICAgIHN1cGVyKGluamVjdG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFuZ3VsYXIgbGlmZWN5Y2xlIGhvb2ssIGNhbGxlZCBhZnRlciB0aGUgY29tcG9uZW50IGlzIGluaXRpYWxpemVkXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnZhbGlkYXRlQ2hhcnRUeXBlKCk7XHJcbiAgICAgICAgLy8gcHJlc2VydmUgb3B0aW9ucyByZWZlcmVudGlhbCBpbnRlZ3JpdHlcclxuICAgICAgICBjb25zdCBvcmlnaW5hbE9wdGlvbnMgPSB0aGlzLmNoYXJ0T3B0aW9ucyB8fCB7fTtcclxuICAgICAgICBjb25zdCBvcHRpb25zID0gTXNmdFNtZS5kZWVwQ29weShvcmlnaW5hbE9wdGlvbnMpO1xyXG4gICAgICAgIHRoaXMuY2hhcnRPcHRpb25zID0gTXNmdFNtZS5kZWVwQXNzaWduKG9yaWdpbmFsT3B0aW9ucywgdGhpcy5nZXREZWZhdWx0T3B0aW9ucygpLCBvcHRpb25zKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGdldERlZmF1bHRPcHRpb25zKCkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHRvb2x0aXBzOiB7XHJcbiAgICAgICAgICAgICAgICBjYWxsYmFja3M6IHtcclxuICAgICAgICAgICAgICAgICAgICBsYWJlbDogKHRvb2x0aXBJdGVtLCBkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldFRvb2x0aXBMYWJlbCh0b29sdGlwSXRlbSwgZGF0YSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBzY2FsZXM6IHtcclxuICAgICAgICAgICAgICAgIHlBeGVzOiBbe1xyXG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgICAgIHRpY2tzOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW46IDAsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heDogdGhpcy5saW5lQ2hhcnREYXRhID8gdGhpcy5saW5lQ2hhcnREYXRhLnltYXhWYWx1ZSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWF4VGlja3NMaW1pdDogMVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1dLFxyXG4gICAgICAgICAgICAgICAgeEF4ZXM6IFt7XHJcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICAgICAgdGlja3M6IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWluOiB0aGlzLmxpbmVDaGFydERhdGEgPyB0aGlzLmxpbmVDaGFydERhdGEueEF4aXNNaW4gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heDogdGhpcy5saW5lQ2hhcnREYXRhID8gdGhpcy5saW5lQ2hhcnREYXRhLnhBeGlzTWF4IDogdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICBncmlkTGluZXM6IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogZmFsc2VcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBdXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGFuaW1hdGlvbjoge1xyXG4gICAgICAgICAgICAgICAgZHVyYXRpb246IDBcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgdGl0bGU6IHtcclxuICAgICAgICAgICAgICAgIGRpc3BsYXk6IGZhbHNlXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGxlZ2VuZDoge1xyXG4gICAgICAgICAgICAgICAgZGlzcGxheTogZmFsc2VcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBbmd1bGFyIGxpZmVjeWNsZSBob29rLCBjYWxsZWQgYWZ0ZXIgdGhlIHZpZXcgaXMgaW5pdGlhbGl6ZWRcclxuICAgICAqL1xyXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcclxuICAgICAgICB0aGlzLnJlZnJlc2goKTtcclxuICAgICAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRhY2goKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBnaXZlIHRoZSBjaGFydHMgc3RhbmRhcmQgYXBwZWFyYW5jZSBhY3Jvc3MgdGhlIHdob2xlIGFwcGxpY2F0aW9uIHVubGVzcyB1c2VyIHNldHMgdXNlQ3VzdG9tU2V0dGluZ3NcclxuICAgIHByaXZhdGUgdXNlRGVmYXVsdFNldHRpbmdzKCkge1xyXG4gICAgICAgIGlmICghdGhpcy5jaGFydCB8fCAhdGhpcy5saW5lQ2hhcnREYXRhIHx8ICF0aGlzLmxpbmVDaGFydERhdGEuY2hhcnREYXRhIHx8ICF0aGlzLmxpbmVDaGFydERhdGEuY2hhcnREYXRhLmRhdGFzZXRzKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGRhdGFTZXRzID0gdGhpcy5saW5lQ2hhcnREYXRhLmNoYXJ0RGF0YS5kYXRhc2V0cztcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IE1hdGgubWluKGRhdGFTZXRzLmxlbmd0aCwgMyk7IGkrKykge1xyXG4gICAgICAgICAgICBjb25zdCBkYXRhc2V0ID0gZGF0YVNldHNbaV07XHJcbiAgICAgICAgICAgIGRhdGFzZXQuYm9yZGVyQ29sb3IgPSB0aGlzLmRlZmF1bHRTZXR0aW5nc1tpXS5ib3JkZXJDb2xvcjtcclxuICAgICAgICAgICAgZGF0YXNldC5iYWNrZ3JvdW5kQ29sb3IgPSBkYXRhU2V0cy5sZW5ndGggPCAzID8gdGhpcy5kZWZhdWx0U2V0dGluZ3NbaV0uYmFja2dyb3VuZENvbG9yIDogJ3JnYmEoMCwwLDAsMCknO1xyXG4gICAgICAgICAgICBkYXRhc2V0LmJvcmRlcldpZHRoID0gMjtcclxuICAgICAgICAgICAgZGF0YXNldC5wb2ludEhvdmVyQmFja2dyb3VuZENvbG9yID0gdGhpcy5kZWZhdWx0U2V0dGluZ3NbaV0ucG9pbnRIb3ZlckJhY2tncm91bmRDb2xvcjtcclxuICAgICAgICAgICAgZGF0YXNldC5wb2ludFJhZGl1cyA9IDA7XHJcbiAgICAgICAgICAgIGRhdGFzZXQucG9pbnRIaXRSYWRpdXMgPSA1O1xyXG4gICAgICAgICAgICBkYXRhc2V0LnNob3dMaW5lID0gdHJ1ZTtcclxuICAgICAgICAgICAgZGF0YXNldC5saW5lVGVuc2lvbiA9IDA7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogZ2VuZXJhdGUgbGVnZW5kIGRhdGEgaWYgY3VycmVudFZhbHVlTGFiZWxEYXRhIGlzIGdpdmVuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZW5lcmF0ZUxlZ2VuZERhdGEoKSB7XHJcbiAgICAgICAgdGhpcy5nZW5lcmF0ZWRMZWdlbmREYXRhID0gW107XHJcbiAgICAgICAgY29uc3QgZGF0YVNldHMgPSB0aGlzLmxpbmVDaGFydERhdGEuY2hhcnREYXRhLmRhdGFzZXRzO1xyXG4gICAgICAgIGlmICghTXNmdFNtZS5pc051bGxPclVuZGVmaW5lZCh0aGlzLmxpbmVDaGFydERhdGEuY3VycmVudFZhbHVlTGFiZWwpICYmIGRhdGFTZXRzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgY29uc3QgdW5pdExhYmVsID0gdGhpcy5saW5lQ2hhcnREYXRhLnVuaXRMYWJlbCB8fCAnJztcclxuICAgICAgICAgICAgdGhpcy5nZW5lcmF0ZWRMZWdlbmREYXRhLnB1c2goe1xyXG4gICAgICAgICAgICAgICAgbGFiZWw6ICcnLFxyXG4gICAgICAgICAgICAgICAgZGlzcGxheVZhbHVlOiB0aGlzLmxpbmVDaGFydERhdGEuY3VycmVudFZhbHVlTGFiZWwgKyAnICcgKyB1bml0TGFiZWwsXHJcbiAgICAgICAgICAgICAgICBjb2xvcjogZGF0YVNldHNbMF0uYm9yZGVyQ29sb3IudG9TdHJpbmcoKVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmNoYXJ0TGVnZW5kRGF0YSA9IFtdO1xyXG4gICAgICAgICAgICBpZiAoIU1zZnRTbWUuaXNOdWxsT3JVbmRlZmluZWQodGhpcy5saW5lQ2hhcnREYXRhLmN1cnJlbnRWYWx1ZUxhYmVsKSAmJiB0aGlzLmxpbmVDaGFydERhdGEuZmlyc3RMYWJlbCAmJiBkYXRhU2V0cy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNoYXJ0TGVnZW5kRGF0YS5wdXNoKHtcclxuICAgICAgICAgICAgICAgICAgICBsYWJlbDogdGhpcy5saW5lQ2hhcnREYXRhLmZpcnN0TGFiZWwsXHJcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheVZhbHVlOiB0aGlzLmxpbmVDaGFydERhdGEuZmlyc3RDdXJyZW50VmFsdWVMYWJlbCxcclxuICAgICAgICAgICAgICAgICAgICBjb2xvcjogZGF0YVNldHNbMF0uYm9yZGVyQ29sb3IudG9TdHJpbmcoKVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCFNc2Z0U21lLmlzTnVsbE9yVW5kZWZpbmVkKHRoaXMubGluZUNoYXJ0RGF0YS5jdXJyZW50VmFsdWVMYWJlbCkgJiYgdGhpcy5saW5lQ2hhcnREYXRhLnNlY29uZExhYmVsICYmIGRhdGFTZXRzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2hhcnRMZWdlbmREYXRhLnB1c2goe1xyXG4gICAgICAgICAgICAgICAgICAgIGxhYmVsOiB0aGlzLmxpbmVDaGFydERhdGEuc2Vjb25kTGFiZWwsXHJcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheVZhbHVlOiB0aGlzLmxpbmVDaGFydERhdGEuc2Vjb25kQ3VycmVudFZhbHVlTGFiZWwsXHJcbiAgICAgICAgICAgICAgICAgICAgY29sb3I6IGRhdGFTZXRzWzFdLmJvcmRlckNvbG9yLnRvU3RyaW5nKClcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICghTXNmdFNtZS5pc051bGxPclVuZGVmaW5lZCh0aGlzLmxpbmVDaGFydERhdGEuY3VycmVudFZhbHVlTGFiZWwpICYmIHRoaXMubGluZUNoYXJ0RGF0YS50b3RhbExhYmVsICYmIGRhdGFTZXRzLmxlbmd0aCA+IDIpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2hhcnRMZWdlbmREYXRhLnB1c2goe1xyXG4gICAgICAgICAgICAgICAgICAgIGxhYmVsOiB0aGlzLmxpbmVDaGFydERhdGEudG90YWxMYWJlbCxcclxuICAgICAgICAgICAgICAgICAgICBkaXNwbGF5VmFsdWU6IHRoaXMubGluZUNoYXJ0RGF0YS50b3RhbEN1cnJlbnRWYWx1ZUxhYmVsLFxyXG4gICAgICAgICAgICAgICAgICAgIGNvbG9yOiBkYXRhU2V0c1syXS5ib3JkZXJDb2xvci50b1N0cmluZygpXHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93IGVycm9yIGlmIGNvbnN1bWVyIGlzIHRyeWluZyB0byBncmFwaCBhIHNjYXR0ZXIgcGxvdCB3aXRob3V0IHggeSBjb29yZGluYXRlc1xyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHZhbGlkYXRlQ2hhcnRUeXBlKCkge1xyXG4gICAgICAgIGlmICghdGhpcy5saW5lQ2hhcnREYXRhKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMubGluZUNoYXJ0RGF0YS5jaGFydERhdGEuZGF0YXNldHMuZm9yRWFjaChkYXRhc2V0ID0+IHtcclxuICAgICAgICAgICAgLy8gTm90ZTogdGhpcyB3b3VsZCBiZSBiZXR0ZXIgd3JpdHRlbiB3aXRoIGEgY2hlY2sgb24gZXZlcnkgZWxlbWVudCBvZiB0aGUgYXJyYXksXHJcbiAgICAgICAgICAgIC8vIEhvd2V2ZXIgdHNjIGlzIHVuYWJsZSB0byB0eXBlY2hlY2sgQXJyYXkuZXZlcnkgb24gYSB1bmlvbiBvZiBhcnJheSB0eXBlcy5cclxuICAgICAgICAgICAgLy8gU28gd2UgYXNzdW1lIHRoZSB0eXBlIGlzIG51bWJlcltdIGlmIHRoZSBmaXJzdCBlbGVtZW50IGlzIGEgbnVtYmVyLlxyXG4gICAgICAgICAgICBjb25zdCBpc051bUFycmF5ID0gZGF0YXNldC5kYXRhICYmIGRhdGFzZXQuZGF0YS5sZW5ndGggPiAwICYmIHR5cGVvZiBkYXRhc2V0LmRhdGFbMF0gPT09ICdudW1iZXInO1xyXG5cclxuICAgICAgICAgICAgaWYgKGlzTnVtQXJyYXkgJiYgdGhpcy5saW5lQ2hhcnREYXRhICYmIHRoaXMubGluZUNoYXJ0RGF0YS50eXBlICYmIHRoaXMubGluZUNoYXJ0RGF0YS50eXBlICE9PSBMaW5lQ2hhcnRUeXBlLkxpbmUpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSGlzdG9yaWNhbCBhbmQgU2NhdHRlciBjaGFydCB0eXBlcyByZXF1aXJlIGFsbCBkYXRhc2V0IGRhdGEgdG8gYmUgb2YgdHlwZSBDaGFydFBvaW50W10nKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogcmV0dXJuIHRoZSBzdHJpbmcgZm9yIHRoZSB0eXBlIG9mIGxpbmUgY2hhcnRcclxuICAgICAqIEBwYXJhbSB0eXBlIHRoZSB0eXBlIG9mIGxpbmUgY2hhcnRcclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldFR5cGVTdHJpbmcodHlwZTogTGluZUNoYXJ0VHlwZSk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHR5cGUgPT09IExpbmVDaGFydFR5cGUuU2NhdHRlciB8fCB0eXBlID09PSBMaW5lQ2hhcnRUeXBlLkhpc3RvcmljYWwgPyAnc2NhdHRlcicgOiAnbGluZSc7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRvb2wgdGlwIGxhYmVsIGFjY29yZGluZyB0byB0aGUgdHlwZSBvZiBjaGFydCBiZWluZyB1c2VkXHJcbiAgICAgKiBAcGFyYW0gdG9vbHRpcEl0ZW0gLSB0aGUgc3BlY2lmaWMgaXRlbSB0aGF0IG5lZWRzIGEgdG9vbHRpcFxyXG4gICAgICogQHBhcmFtIGRhdGEgLSB0aGUgbGluZWFyY2hhcnRkYXRhIG9iamVjdFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdldFRvb2x0aXBMYWJlbCh0b29sdGlwSXRlbSwgZGF0YSk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgZGF0YXNldCA9IGRhdGEuZGF0YXNldHNbdG9vbHRpcEl0ZW0uZGF0YXNldEluZGV4XTtcclxuICAgICAgICBjb25zdCBkYXRhUG9pbnQgPSBkYXRhc2V0LmRhdGFbdG9vbHRpcEl0ZW0uaW5kZXhdO1xyXG4gICAgICAgIGNvbnN0IHRpdGxlID0gZGF0YXNldC5sYWJlbDtcclxuICAgICAgICBsZXQgdmFsdWUgPSAnJztcclxuICAgICAgICBsZXQgbGFiZWwgPSAnJztcclxuICAgICAgICBpZiAodGhpcy5saW5lQ2hhcnREYXRhLnR5cGUgPT09IExpbmVDaGFydFR5cGUuSGlzdG9yaWNhbCkge1xyXG4gICAgICAgICAgICAvLyB0aGlzIGlzIHdoZXJlIHRvb2x0aXAgcHJldHR5IHByaW50aW5nIG5lZWRzIHRvIGhhcHBlblxyXG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMudG9vbHRpcEZvcm1hdHRlciA/XHJcbiAgICAgICAgICAgICAgICB0aGlzLnRvb2x0aXBGb3JtYXR0ZXIoZGF0YVBvaW50LnkpXHJcbiAgICAgICAgICAgICAgICA6IEdsb2JhbGl6YXRpb24ubnVtYmVyKGRhdGFQb2ludC55LCB7IG1heGltdW1GcmFjdGlvbkRpZ2l0czogMiB9KTtcclxuICAgICAgICAgICAgbGFiZWwgPSBHbG9iYWxpemF0aW9uLmRhdGVUaW1lT25seShuZXcgRGF0ZShkYXRhUG9pbnQueCkpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5saW5lQ2hhcnREYXRhLnR5cGUgPT09IExpbmVDaGFydFR5cGUuU2NhdHRlcikge1xyXG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMudG9vbHRpcEZvcm1hdHRlciA/XHJcbiAgICAgICAgICAgICAgICB0aGlzLnRvb2x0aXBGb3JtYXR0ZXIoZGF0YVBvaW50LnkpXHJcbiAgICAgICAgICAgICAgICA6IEdsb2JhbGl6YXRpb24ubnVtYmVyKGRhdGFQb2ludC55LCB7IG1heGltdW1GcmFjdGlvbkRpZ2l0czogMiB9KTtcclxuICAgICAgICAgICAgbGFiZWwgPSBkYXRhUG9pbnQueDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb25zdCB0bXBWYWx1ZSA9IGRhdGFQb2ludC55ID8gZGF0YVBvaW50LnkgOiBkYXRhUG9pbnQ7XHJcbiAgICAgICAgICAgIHZhbHVlID0gdGhpcy50b29sdGlwRm9ybWF0dGVyID8gdGhpcy50b29sdGlwRm9ybWF0dGVyKHRtcFZhbHVlKSA6IEdsb2JhbGl6YXRpb24ubnVtYmVyKHRtcFZhbHVlLCB7IG1heGltdW1GcmFjdGlvbkRpZ2l0czogMiB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBsYWJlbCA/ICd7MH0gezF9OiB7Mn0nLmZvcm1hdCh0aXRsZSwgbGFiZWwsIHZhbHVlKSA6ICd7MH06IHsxfScuZm9ybWF0KHRpdGxlLCB2YWx1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWZyZXNoIHRoZSBjaGFydCB3aGVuIG5ldyBkYXRhIGlzIGFkZGVkIHRvIGxpbmVDaGFydERhdGEgaW5wdXRcclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlZnJlc2goKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLnVzZUN1c3RvbVNldHRpbmdzKSB7XHJcbiAgICAgICAgICAgIHRoaXMudXNlRGVmYXVsdFNldHRpbmdzKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXRoaXMuY2hhcnRMZWdlbmREYXRhIHx8IHRoaXMuY2hhcnRMZWdlbmREYXRhLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLmdlbmVyYXRlTGVnZW5kRGF0YSgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMubGluZUNoYXJ0RGF0YSAmJiB0aGlzLmNoYXJ0T3B0aW9ucykge1xyXG4gICAgICAgICAgICBjb25zdCBzY2FsZXNDaGFuZ2VkID0gdGhpcy5jaGFydE9wdGlvbnMuc2NhbGVzLnlBeGVzWzBdLnRpY2tzLm1heCAhPT0gdGhpcy5saW5lQ2hhcnREYXRhLnltYXhWYWx1ZVxyXG4gICAgICAgICAgICAgICAgfHwgdGhpcy5jaGFydE9wdGlvbnMuc2NhbGVzLnhBeGVzWzBdLnRpY2tzLm1pbiAhPT0gdGhpcy5saW5lQ2hhcnREYXRhLnhBeGlzTWluXHJcbiAgICAgICAgICAgICAgICB8fCB0aGlzLmNoYXJ0T3B0aW9ucy5zY2FsZXMueEF4ZXNbMF0udGlja3MubWF4ICE9PSB0aGlzLmxpbmVDaGFydERhdGEueEF4aXNNYXg7XHJcblxyXG4gICAgICAgICAgICBpZiAoc2NhbGVzQ2hhbmdlZCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jaGFydE9wdGlvbnMuc2NhbGVzLnlBeGVzWzBdLnRpY2tzLm1heCA9IHRoaXMubGluZUNoYXJ0RGF0YS55bWF4VmFsdWU7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNoYXJ0T3B0aW9ucy5zY2FsZXMueEF4ZXNbMF0udGlja3MubWluID0gdGhpcy5saW5lQ2hhcnREYXRhLnhBeGlzTWluO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jaGFydE9wdGlvbnMuc2NhbGVzLnhBeGVzWzBdLnRpY2tzLm1heCA9IHRoaXMubGluZUNoYXJ0RGF0YS54QXhpc01heDtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGFydCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2hhcnQuaW5pdGlhbGl6ZSgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5jaGFydCkge1xyXG4gICAgICAgICAgICB0aGlzLmNoYXJ0LnJlZnJlc2goKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuIiwiPGRpdiAqbmdJZj1cImxpbmVDaGFydERhdGFcIiBjbGFzcz1cInNtZS1mb2N1cy16b25lXCI+XHJcbiAgPGRpdiAqbmdJZj1cImxpbmVDaGFydERhdGEudGl0bGVcIiBbYXR0ci5hcmlhLWhpZGRlbl09XCJzaG93TGVnZW5kXCI+IHt7IGxpbmVDaGFydERhdGEudGl0bGUgfX08L2Rpdj5cclxuXHJcbiAgPHNtZS1sZWdlbmQgKm5nSWY9XCJzaG93TGVnZW5kXCJcclxuICAgIFtsZWdlbmREYXRhXT1cIighY2hhcnRMZWdlbmREYXRhIHx8IGNoYXJ0TGVnZW5kRGF0YS5sZW5ndGggPT09IDApID8gZ2VuZXJhdGV